als-document 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser-tests/node.js +9 -9
- package/browser-tests/parser.js +21 -21
- package/docs/#.md +7 -10
- package/docs/2.node.md +22 -1
- package/docs/5. Document.md +8 -25
- package/document.js +6 -6
- package/index.js +6 -6
- package/index.mjs +6 -6
- package/lib/node/document.js +39 -7
- package/lib/node/find.js +1 -0
- package/lib/node/node.js +19 -5
- package/lib/node/single-node.js +2 -2
- package/lib/parse/cache.js +1 -1
- package/lib/query/check-element.js +2 -2
- package/package.json +1 -1
- package/readme.md +31 -29
- package/tests/class-list.test.js +67 -0
- package/tests/document.test.js +90 -0
- package/tests/node.test.js +9 -9
- package/tests/parser.test.js +19 -19
package/browser-tests/node.js
CHANGED
|
@@ -9,7 +9,7 @@ describe('Constructor and Basic Properties', () => {
|
|
|
9
9
|
const rootNode = new Node('ROOT');
|
|
10
10
|
const divNode = new Node('div', { class: 'container' }, rootNode);
|
|
11
11
|
|
|
12
|
-
assert(divNode.tagName === 'div', "Tag name is correct");
|
|
12
|
+
assert(divNode.tagName.toLowerCase().toLowerCase() === 'div', "Tag name is correct");
|
|
13
13
|
assert(divNode.attributes.class === 'container', "Attributes are correct");
|
|
14
14
|
assert(divNode.parent === rootNode, "Parent node is correct");
|
|
15
15
|
});
|
|
@@ -124,13 +124,13 @@ describe('Content Manipulation', () => {
|
|
|
124
124
|
const childNode = new Node('p', {}, rootNode);
|
|
125
125
|
|
|
126
126
|
childNode.insertAdjacentElement('beforebegin', new Node('span'));
|
|
127
|
-
expect(rootNode.childNodes[0].tagName).equalTo('span');
|
|
127
|
+
expect(rootNode.childNodes[0].tagName.toLowerCase()).equalTo('span');
|
|
128
128
|
|
|
129
129
|
childNode.insertAdjacentElement('afterend', new Node('a'));
|
|
130
|
-
expect(rootNode.childNodes[2].tagName).equalTo('a');
|
|
130
|
+
expect(rootNode.childNodes[2].tagName.toLowerCase()).equalTo('a');
|
|
131
131
|
|
|
132
132
|
childNode.insertAdjacentHTML('beforebegin', '<strong></strong>');
|
|
133
|
-
expect(rootNode.childNodes[1].tagName).equalTo('strong');
|
|
133
|
+
expect(rootNode.childNodes[1].tagName.toLowerCase()).equalTo('strong');
|
|
134
134
|
|
|
135
135
|
childNode.insertAdjacentText('afterend', 'Some text');
|
|
136
136
|
expect(typeof rootNode.childNodes[3].nodeValue).equalTo('string');
|
|
@@ -145,10 +145,10 @@ describe('Content Manipulation', () => {
|
|
|
145
145
|
|
|
146
146
|
const newNode = new Node('span');
|
|
147
147
|
newNode.innerHTML = '<a href="#">Link</a>';
|
|
148
|
-
expect(newNode.childNodes[0].tagName).equalTo('a');
|
|
148
|
+
expect(newNode.childNodes[0].tagName.toLowerCase()).equalTo('a');
|
|
149
149
|
|
|
150
150
|
newNode.childNodes[0].outerHTML = '<div><strong>New content</strong></div>';
|
|
151
|
-
expect(newNode.childNodes[0].childNodes[0].tagName).equalTo('strong');
|
|
151
|
+
expect(newNode.childNodes[0].childNodes[0].tagName.toLowerCase()).equalTo('strong');
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
it('Works with text content', () => {
|
|
@@ -181,9 +181,9 @@ describe('Other Methods and Properties', () => {
|
|
|
181
181
|
|
|
182
182
|
// Проверяем свойство children
|
|
183
183
|
expect(rootNode.children.length).equalTo(3);
|
|
184
|
-
expect(rootNode.children[0].tagName).equalTo('p');
|
|
185
|
-
expect(rootNode.children[1].tagName).equalTo('span');
|
|
186
|
-
expect(rootNode.children[2].tagName).equalTo('a');
|
|
184
|
+
expect(rootNode.children[0].tagName.toLowerCase()).equalTo('p');
|
|
185
|
+
expect(rootNode.children[1].tagName.toLowerCase()).equalTo('span');
|
|
186
|
+
expect(rootNode.children[2].tagName.toLowerCase()).equalTo('a');
|
|
187
187
|
});
|
|
188
188
|
|
|
189
189
|
it('Gets the parent element', () => {
|
package/browser-tests/parser.js
CHANGED
|
@@ -11,17 +11,17 @@ describe('HTML Parser', () => {
|
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
it('correctly sets node type', () => {
|
|
14
|
-
expect(parsedHTML.tagName).equalTo('div');
|
|
14
|
+
expect(parsedHTML.tagName.toLowerCase()).equalTo('div');
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('correctly sets child nodes', () => {
|
|
18
18
|
expect(parsedHTML.children.length).equalTo(1);
|
|
19
|
-
expect(parsedHTML.children[0].tagName).equalTo('p');
|
|
19
|
+
expect(parsedHTML.children[0].tagName.toLowerCase()).equalTo('p');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
it('correctly parses nested HTML', () => {
|
|
23
23
|
const nestedHTML = parseHTML('<div><span><a href="#">Link</a></span></div>');
|
|
24
|
-
expect(nestedHTML.children[0].children[0].children[0].tagName).equalTo('a');
|
|
24
|
+
expect(nestedHTML.children[0].children[0].children[0].tagName.toLowerCase()).equalTo('a');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('correctly parses text nodes', () => {
|
|
@@ -44,7 +44,7 @@ describe('Query API', () => {
|
|
|
44
44
|
it('can select nested nodes', () => {
|
|
45
45
|
const nestedHTML = parseHTML('<div><span><a href="#">Link</a></span></div>');
|
|
46
46
|
const collection = nestedHTML.querySelectorAll('a');
|
|
47
|
-
expect(collection[0].tagName).equalTo('a');
|
|
47
|
+
expect(collection[0].tagName.toLowerCase()).equalTo('a');
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -77,7 +77,7 @@ describe('Advanced tests', () => {
|
|
|
77
77
|
const result = parseHTML('<div><p>Text</div>');
|
|
78
78
|
// Depending on the behavior you expect: either an error, or a specific structure.
|
|
79
79
|
// For this example, I'll assume you expect the <p> tag to be auto-closed
|
|
80
|
-
expect(result.children[0].children[0].tagName).equalTo('p');
|
|
80
|
+
expect(result.children[0].children[0].tagName.toLowerCase()).equalTo('p');
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
it('handles attributes without values', () => {
|
|
@@ -88,7 +88,7 @@ describe('Advanced tests', () => {
|
|
|
88
88
|
it('ignores comments', () => {
|
|
89
89
|
const result = parseHTML('<!-- this is a comment --><div></div>');
|
|
90
90
|
expect(result.children.length).equalTo(1);
|
|
91
|
-
expect(result.children[0].tagName).equalTo('div');
|
|
91
|
+
expect(result.children[0].tagName.toLowerCase()).equalTo('div');
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it('correctly parses script content', () => {
|
|
@@ -164,17 +164,17 @@ describe('CDATA', () => {
|
|
|
164
164
|
it('basic test', () => {
|
|
165
165
|
const test1 = '<![CDATA[This is CDATA content]]>';
|
|
166
166
|
const root1 = parseHTML(test1);
|
|
167
|
-
assert(root1.childNodes[0].tagName === "#cdata-section", "Test 1: CDATA node not created");
|
|
167
|
+
assert(root1.childNodes[0].tagName.toLowerCase() === "#cdata-section", "Test 1: CDATA node not created");
|
|
168
168
|
assert(root1.childNodes[0].nodeValue === "This is CDATA content", "Test 1: CDATA content not correct");
|
|
169
169
|
})
|
|
170
170
|
|
|
171
171
|
it('nested CDATA', () => {
|
|
172
172
|
const test2 = '<div><![CDATA[Inside a div]]><p>Paragraph</p></div>';
|
|
173
173
|
const root2 = parseHTML(test2);
|
|
174
|
-
assert(root2.childNodes[0].tagName === "div", "Test 2: Parent div not created");
|
|
175
|
-
assert(root2.childNodes[0].childNodes[0].tagName === "#cdata-section", "Test 2: CDATA node not created inside div");
|
|
174
|
+
assert(root2.childNodes[0].tagName.toLowerCase() === "div", "Test 2: Parent div not created");
|
|
175
|
+
assert(root2.childNodes[0].childNodes[0].tagName.toLowerCase() === "#cdata-section", "Test 2: CDATA node not created inside div");
|
|
176
176
|
assert(root2.childNodes[0].childNodes[0].nodeValue === "Inside a div", "Test 2: CDATA content not correct inside div");
|
|
177
|
-
assert(root2.childNodes[0].childNodes[1].tagName === "p", "Test 2: Paragraph not created after CDATA");
|
|
177
|
+
assert(root2.childNodes[0].childNodes[1].tagName.toLowerCase() === "p", "Test 2: Paragraph not created after CDATA");
|
|
178
178
|
})
|
|
179
179
|
|
|
180
180
|
it('multiple lines', () => {
|
|
@@ -185,7 +185,7 @@ inside this CDATA
|
|
|
185
185
|
block.
|
|
186
186
|
]]>`;
|
|
187
187
|
const root3 = parseHTML(test3);
|
|
188
|
-
assert(root3.childNodes[0].tagName === "#cdata-section", "Test 3: CDATA node not created");
|
|
188
|
+
assert(root3.childNodes[0].tagName.toLowerCase() === "#cdata-section", "Test 3: CDATA node not created");
|
|
189
189
|
assert(root3.childNodes[0].nodeValue.trim() === "Multiple lines \ninside this CDATA\nblock.", "Test 3: Multi-line CDATA content not correct");
|
|
190
190
|
|
|
191
191
|
})
|
|
@@ -193,7 +193,7 @@ block.
|
|
|
193
193
|
it('inside html', () => {
|
|
194
194
|
const test4 = '<![CDATA[<span>This should be text</span>]]>';
|
|
195
195
|
const root4 = parseHTML(test4);
|
|
196
|
-
assert(root4.childNodes[0].tagName === "#cdata-section", "Test 4: CDATA node not created");
|
|
196
|
+
assert(root4.childNodes[0].tagName.toLowerCase() === "#cdata-section", "Test 4: CDATA node not created");
|
|
197
197
|
assert(root4.childNodes[0].nodeValue === "<span>This should be text</span>", "Test 4: HTML inside CDATA not treated as text");
|
|
198
198
|
|
|
199
199
|
})
|
|
@@ -213,9 +213,9 @@ describe('signle tags, script and style', () => {
|
|
|
213
213
|
</script>
|
|
214
214
|
`;
|
|
215
215
|
const rootStyleScript = parseHTML(testStyleScript);
|
|
216
|
-
assert(rootStyleScript.childNodes[0].tagName === "style", "Test Style/Script 1: Style tag not created");
|
|
216
|
+
assert(rootStyleScript.childNodes[0].tagName.toLowerCase() === "style", "Test Style/Script 1: Style tag not created");
|
|
217
217
|
assert(rootStyleScript.childNodes[0].textContent.trim() === "body { color: red; }\n p > a { text-decoration: none; }", "Test Style/Script 1: Style content not correct");
|
|
218
|
-
assert(rootStyleScript.childNodes[1].tagName === "script", "Test Style/Script 2: Script tag not created");
|
|
218
|
+
assert(rootStyleScript.childNodes[1].tagName.toLowerCase() === "script", "Test Style/Script 2: Script tag not created");
|
|
219
219
|
assert(rootStyleScript.childNodes[1].textContent.trim() === 'if (x < 5 && y > 3) {\n console.log("This shouldn\'t be parsed as tags");\n }', "Test Style/Script 2: Script content not correct");
|
|
220
220
|
})
|
|
221
221
|
|
|
@@ -225,9 +225,9 @@ describe('signle tags, script and style', () => {
|
|
|
225
225
|
<link rel="stylesheet" href="styles.css">
|
|
226
226
|
`;
|
|
227
227
|
const rootMetaLink = parseHTML(testMetaLink);
|
|
228
|
-
assert(rootMetaLink.children[0].tagName === "meta", "Test Meta/Link 1: Meta tag not created");
|
|
228
|
+
assert(rootMetaLink.children[0].tagName.toLowerCase() === "meta", "Test Meta/Link 1: Meta tag not created");
|
|
229
229
|
assert(rootMetaLink.children[0].getAttribute("charset") === "UTF-8", "Test Meta/Link 1: Meta content not correct");
|
|
230
|
-
assert(rootMetaLink.children[1].tagName === "link", "Test Meta/Link 2: Link tag not created");
|
|
230
|
+
assert(rootMetaLink.children[1].tagName.toLowerCase() === "link", "Test Meta/Link 2: Link tag not created");
|
|
231
231
|
assert(rootMetaLink.children[1].getAttribute("rel") === "stylesheet", "Test Meta/Link 2: Link rel attribute not correct");
|
|
232
232
|
assert(rootMetaLink.children[1].getAttribute("href") === "styles.css", "Test Meta/Link 2: Link href attribute not correct");
|
|
233
233
|
})
|
|
@@ -236,7 +236,7 @@ describe('signle tags, script and style', () => {
|
|
|
236
236
|
const testUnmatchedClose = `<div>Some content</p></div>`;
|
|
237
237
|
const rootUnmatchedClose = parseHTML(testUnmatchedClose);
|
|
238
238
|
// Зависит от вашего решения обработки. Если вы решите исправлять такой HTML, тест может выглядеть так:
|
|
239
|
-
assert(rootUnmatchedClose.childNodes[0].tagName === "div", "Test Unmatched Close: Div tag not created");
|
|
239
|
+
assert(rootUnmatchedClose.childNodes[0].tagName.toLowerCase() === "div", "Test Unmatched Close: Div tag not created");
|
|
240
240
|
assert(rootUnmatchedClose.childNodes[0].textContent.trim() === "Some content", "Test Unmatched Close: Div content not correct");
|
|
241
241
|
})
|
|
242
242
|
|
|
@@ -244,7 +244,7 @@ describe('signle tags, script and style', () => {
|
|
|
244
244
|
const testUnmatchedOpen = `<div>Some content`;
|
|
245
245
|
const rootUnmatchedOpen = parseHTML(testUnmatchedOpen);
|
|
246
246
|
// Снова зависит от вашего решения. Если вы решите автоматически закрывать тег:
|
|
247
|
-
assert(rootUnmatchedOpen.childNodes[0].tagName === "div", "Test Unmatched Open: Div tag not created");
|
|
247
|
+
assert(rootUnmatchedOpen.childNodes[0].tagName.toLowerCase() === "div", "Test Unmatched Open: Div tag not created");
|
|
248
248
|
assert(rootUnmatchedOpen.childNodes[0].textContent.trim() === "Some content", "Test Unmatched Open: Div content not correct");
|
|
249
249
|
})
|
|
250
250
|
})
|
|
@@ -270,7 +270,7 @@ describe('Specific elements handling', () => {
|
|
|
270
270
|
const html = parseHTML(svg)
|
|
271
271
|
const svgParsed = html.querySelector('svg')
|
|
272
272
|
|
|
273
|
-
assert(svgParsed.tagName === svgElement.tagName)
|
|
273
|
+
assert(svgParsed.tagName.toLowerCase() === svgElement.tagName.toLowerCase())
|
|
274
274
|
|
|
275
275
|
assert(svgElement.getAttribute('version') === svgParsed.getAttribute('version'))
|
|
276
276
|
assert(svgElement.getAttribute('id') === svgParsed.getAttribute('id'))
|
|
@@ -297,7 +297,7 @@ describe('Specific elements handling', () => {
|
|
|
297
297
|
const html = parseHTML(canvas)
|
|
298
298
|
const canvasElement = html.children[0]
|
|
299
299
|
|
|
300
|
-
expect(canvasElement.tagName).equalTo('canvas');
|
|
300
|
+
expect(canvasElement.tagName.toLowerCase()).equalTo('canvas');
|
|
301
301
|
expect(canvasElement.getAttribute('id')).equalTo('myCanvas');
|
|
302
302
|
expect(canvasElement.getAttribute('width')).equalTo('300');
|
|
303
303
|
expect(canvasElement.getAttribute('height')).equalTo('150');
|
|
@@ -313,7 +313,7 @@ describe('Specific elements handling', () => {
|
|
|
313
313
|
const html = parseHTML(svgHTML);
|
|
314
314
|
const svgElement = html.children[0]
|
|
315
315
|
|
|
316
|
-
expect(svgElement.tagName).equalTo('svg');
|
|
316
|
+
expect(svgElement.tagName.toLowerCase()).equalTo('svg');
|
|
317
317
|
expect(svgElement.getAttribute('xmlns')).equalTo(svgNamespace);
|
|
318
318
|
expect(svgElement.getAttribute('xmlns:xml')).equalTo(xmlNamespace);
|
|
319
319
|
});
|
package/docs/#.md
CHANGED
|
@@ -40,13 +40,10 @@ import { parseHTML, Node, Query, TextNode, SingleNode, Root, Document } from 'al
|
|
|
40
40
|
</script>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
## Change log
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* Document
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* set title
|
|
51
|
-
* get body
|
|
52
|
-
* get head
|
|
43
|
+
## Change log for 1.3
|
|
44
|
+
* added getter and setter for node.innerText
|
|
45
|
+
* prev and next now works with childIndex=0
|
|
46
|
+
* querySelctor not includes the parent any more
|
|
47
|
+
* Document new getters and setters include clone
|
|
48
|
+
* tagName - uppers, _tagName - lowers
|
|
49
|
+
|
package/docs/2.node.md
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
`Node` is a fundamental class that represents an element node in the DOM tree. It provides functionality similar to the native DOM API in browsers, but with its own implementation.
|
|
4
4
|
|
|
5
5
|
### Properties:
|
|
6
|
-
- **tagName**: Represents the tag name of the element.
|
|
6
|
+
- **tagName**: Represents the tag name of the element (upper cased).
|
|
7
|
+
- **_tagName**: Represents the tag name of the element (lower cased).
|
|
8
|
+
- **innerText**
|
|
7
9
|
- **attributes**: A dictionary of attributes and their values.
|
|
8
10
|
- **childNodes**: An array of child nodes for the element.
|
|
9
11
|
- **isSingle**: Boolean value to check if the node is a self-closing tag.
|
|
@@ -23,3 +25,22 @@
|
|
|
23
25
|
- **appendChild**: Add a child node to the element.
|
|
24
26
|
- **insert(place,element)**: place (0-3) or beforebegin,afterbegin,... eleemnt - raw html or element
|
|
25
27
|
|
|
28
|
+
|
|
29
|
+
### Examples:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
const div = new Node('div');
|
|
33
|
+
div.setAttribute('class', 'container');
|
|
34
|
+
|
|
35
|
+
const img = new SingleNode('img', { src: 'image.jpg', alt: 'An image' });
|
|
36
|
+
div.appendChild(img);
|
|
37
|
+
|
|
38
|
+
console.log(div.outerHTML); // Outputs: <div class="container"><img src="image.jpg" alt="An image"></div>
|
|
39
|
+
|
|
40
|
+
const p = new Node('p',{},div); // adding as last child to parent div
|
|
41
|
+
p.textContent = "Hello, world!";
|
|
42
|
+
|
|
43
|
+
const foundP = div.querySelector('p');
|
|
44
|
+
console.log(foundP.textContent); // Outputs: Hello, world!
|
|
45
|
+
```
|
|
46
|
+
|
package/docs/5. Document.md
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
### Document node (extends Node)
|
|
2
2
|
|
|
3
3
|
Has additional getters and setters:
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
const div = new Node('div');
|
|
15
|
-
div.setAttribute('class', 'container');
|
|
16
|
-
|
|
17
|
-
const img = new SingleNode('img', { src: 'image.jpg', alt: 'An image' });
|
|
18
|
-
div.appendChild(img);
|
|
19
|
-
|
|
20
|
-
console.log(div.outerHTML); // Outputs: <div class="container"><img src="image.jpg" alt="An image"></div>
|
|
21
|
-
|
|
22
|
-
const p = new Node('p',{},div); // adding as last child to parent div
|
|
23
|
-
p.textContent = "Hello, world!";
|
|
24
|
-
|
|
25
|
-
const foundP = div.querySelector('p');
|
|
26
|
-
console.log(foundP.textContent); // Outputs: Hello, world!
|
|
27
|
-
```
|
|
28
|
-
|
|
4
|
+
* get documentElement
|
|
5
|
+
* get html
|
|
6
|
+
* get head
|
|
7
|
+
* get body
|
|
8
|
+
* get title
|
|
9
|
+
* get charset
|
|
10
|
+
* set title
|
|
11
|
+
* get clone - return cloned new instance of Document
|