parse5-htmlparser2-tree-adapter 6.0.1 → 7.1.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/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  <br>
17
17
 
18
18
  <p align="center">
19
- 📖 <a href="https://github.com/inikulin/parse5/tree/master/packages/parse5-htmlparser2-tree-adapter/docs/index.md"><b>Documentation</b></a> 📖
19
+ 📖 <a href="https://parse5.js.org/modules/parse5_htmlparser2_tree_adapter.html"><b>Documentation</b></a> 📖
20
20
  </p>
21
21
 
22
22
  ---
@@ -30,5 +30,5 @@
30
30
  </p>
31
31
 
32
32
  <p align="center">
33
- <a href="https://github.com/inikulin/parse5/tree/master/docs/version-history.md">Version history</a>
33
+ <a href="https://github.com/inikulin/parse5/releases">Changelog</a>
34
34
  </p>
@@ -0,0 +1,6 @@
1
+ import { type TreeAdapterTypeMap, type TreeAdapter } from 'parse5';
2
+ import { type AnyNode, type ParentNode, type ChildNode, Element, Document, ProcessingInstruction, Comment, Text } from 'domhandler';
3
+ export type Htmlparser2TreeAdapterMap = TreeAdapterTypeMap<AnyNode, ParentNode, ChildNode, Document, Document, Element, Comment, Text, Element, ProcessingInstruction>;
4
+ /** @internal */
5
+ export declare function serializeDoctypeContent(name: string, publicId: string, systemId: string): string;
6
+ export declare const adapter: TreeAdapter<Htmlparser2TreeAdapterMap>;
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adapter = void 0;
4
+ exports.serializeDoctypeContent = serializeDoctypeContent;
5
+ const parse5_1 = require("parse5");
6
+ const domhandler_1 = require("domhandler");
7
+ function enquoteDoctypeId(id) {
8
+ const quote = id.includes('"') ? "'" : '"';
9
+ return quote + id + quote;
10
+ }
11
+ /** @internal */
12
+ function serializeDoctypeContent(name, publicId, systemId) {
13
+ let str = '!DOCTYPE ';
14
+ if (name) {
15
+ str += name;
16
+ }
17
+ if (publicId) {
18
+ str += ` PUBLIC ${enquoteDoctypeId(publicId)}`;
19
+ }
20
+ else if (systemId) {
21
+ str += ' SYSTEM';
22
+ }
23
+ if (systemId) {
24
+ str += ` ${enquoteDoctypeId(systemId)}`;
25
+ }
26
+ return str;
27
+ }
28
+ exports.adapter = {
29
+ // Re-exports from domhandler
30
+ isCommentNode: domhandler_1.isComment,
31
+ isElementNode: domhandler_1.isTag,
32
+ isTextNode: domhandler_1.isText,
33
+ //Node construction
34
+ createDocument() {
35
+ const node = new domhandler_1.Document([]);
36
+ node['x-mode'] = parse5_1.html.DOCUMENT_MODE.NO_QUIRKS;
37
+ return node;
38
+ },
39
+ createDocumentFragment() {
40
+ return new domhandler_1.Document([]);
41
+ },
42
+ createElement(tagName, namespaceURI, attrs) {
43
+ const attribs = Object.create(null);
44
+ const attribsNamespace = Object.create(null);
45
+ const attribsPrefix = Object.create(null);
46
+ for (let i = 0; i < attrs.length; i++) {
47
+ const attrName = attrs[i].name;
48
+ attribs[attrName] = attrs[i].value;
49
+ attribsNamespace[attrName] = attrs[i].namespace;
50
+ attribsPrefix[attrName] = attrs[i].prefix;
51
+ }
52
+ const node = new domhandler_1.Element(tagName, attribs, []);
53
+ node.namespace = namespaceURI;
54
+ node['x-attribsNamespace'] = attribsNamespace;
55
+ node['x-attribsPrefix'] = attribsPrefix;
56
+ return node;
57
+ },
58
+ createCommentNode(data) {
59
+ return new domhandler_1.Comment(data);
60
+ },
61
+ createTextNode(value) {
62
+ return new domhandler_1.Text(value);
63
+ },
64
+ //Tree mutation
65
+ appendChild(parentNode, newNode) {
66
+ const prev = parentNode.children[parentNode.children.length - 1];
67
+ if (prev) {
68
+ prev.next = newNode;
69
+ newNode.prev = prev;
70
+ }
71
+ parentNode.children.push(newNode);
72
+ newNode.parent = parentNode;
73
+ },
74
+ insertBefore(parentNode, newNode, referenceNode) {
75
+ const insertionIdx = parentNode.children.indexOf(referenceNode);
76
+ const { prev } = referenceNode;
77
+ if (prev) {
78
+ prev.next = newNode;
79
+ newNode.prev = prev;
80
+ }
81
+ referenceNode.prev = newNode;
82
+ newNode.next = referenceNode;
83
+ parentNode.children.splice(insertionIdx, 0, newNode);
84
+ newNode.parent = parentNode;
85
+ },
86
+ setTemplateContent(templateElement, contentElement) {
87
+ exports.adapter.appendChild(templateElement, contentElement);
88
+ },
89
+ getTemplateContent(templateElement) {
90
+ return templateElement.children[0];
91
+ },
92
+ setDocumentType(document, name, publicId, systemId) {
93
+ const data = serializeDoctypeContent(name, publicId, systemId);
94
+ let doctypeNode = document.children.find((node) => (0, domhandler_1.isDirective)(node) && node.name === '!doctype');
95
+ if (doctypeNode) {
96
+ doctypeNode.data = data !== null && data !== void 0 ? data : null;
97
+ }
98
+ else {
99
+ doctypeNode = new domhandler_1.ProcessingInstruction('!doctype', data);
100
+ exports.adapter.appendChild(document, doctypeNode);
101
+ }
102
+ doctypeNode['x-name'] = name;
103
+ doctypeNode['x-publicId'] = publicId;
104
+ doctypeNode['x-systemId'] = systemId;
105
+ },
106
+ setDocumentMode(document, mode) {
107
+ document['x-mode'] = mode;
108
+ },
109
+ getDocumentMode(document) {
110
+ return document['x-mode'];
111
+ },
112
+ detachNode(node) {
113
+ if (node.parent) {
114
+ const idx = node.parent.children.indexOf(node);
115
+ const { prev, next } = node;
116
+ node.prev = null;
117
+ node.next = null;
118
+ if (prev) {
119
+ prev.next = next;
120
+ }
121
+ if (next) {
122
+ next.prev = prev;
123
+ }
124
+ node.parent.children.splice(idx, 1);
125
+ node.parent = null;
126
+ }
127
+ },
128
+ insertText(parentNode, text) {
129
+ const lastChild = parentNode.children[parentNode.children.length - 1];
130
+ if (lastChild && (0, domhandler_1.isText)(lastChild)) {
131
+ lastChild.data += text;
132
+ }
133
+ else {
134
+ exports.adapter.appendChild(parentNode, exports.adapter.createTextNode(text));
135
+ }
136
+ },
137
+ insertTextBefore(parentNode, text, referenceNode) {
138
+ const prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
139
+ if (prevNode && (0, domhandler_1.isText)(prevNode)) {
140
+ prevNode.data += text;
141
+ }
142
+ else {
143
+ exports.adapter.insertBefore(parentNode, exports.adapter.createTextNode(text), referenceNode);
144
+ }
145
+ },
146
+ adoptAttributes(recipient, attrs) {
147
+ for (let i = 0; i < attrs.length; i++) {
148
+ const attrName = attrs[i].name;
149
+ if (recipient.attribs[attrName] === undefined) {
150
+ recipient.attribs[attrName] = attrs[i].value;
151
+ recipient['x-attribsNamespace'][attrName] = attrs[i].namespace;
152
+ recipient['x-attribsPrefix'][attrName] = attrs[i].prefix;
153
+ }
154
+ }
155
+ },
156
+ //Tree traversing
157
+ getFirstChild(node) {
158
+ return node.children[0];
159
+ },
160
+ getChildNodes(node) {
161
+ return node.children;
162
+ },
163
+ getParentNode(node) {
164
+ return node.parent;
165
+ },
166
+ getAttrList(element) {
167
+ return element.attributes;
168
+ },
169
+ //Node data
170
+ getTagName(element) {
171
+ return element.name;
172
+ },
173
+ getNamespaceURI(element) {
174
+ return element.namespace;
175
+ },
176
+ getTextNodeContent(textNode) {
177
+ return textNode.data;
178
+ },
179
+ getCommentNodeContent(commentNode) {
180
+ return commentNode.data;
181
+ },
182
+ getDocumentTypeNodeName(doctypeNode) {
183
+ var _a;
184
+ return (_a = doctypeNode['x-name']) !== null && _a !== void 0 ? _a : '';
185
+ },
186
+ getDocumentTypeNodePublicId(doctypeNode) {
187
+ var _a;
188
+ return (_a = doctypeNode['x-publicId']) !== null && _a !== void 0 ? _a : '';
189
+ },
190
+ getDocumentTypeNodeSystemId(doctypeNode) {
191
+ var _a;
192
+ return (_a = doctypeNode['x-systemId']) !== null && _a !== void 0 ? _a : '';
193
+ },
194
+ //Node types
195
+ isDocumentTypeNode(node) {
196
+ return (0, domhandler_1.isDirective)(node) && node.name === '!doctype';
197
+ },
198
+ // Source code location
199
+ setNodeSourceCodeLocation(node, location) {
200
+ if (location) {
201
+ node.startIndex = location.startOffset;
202
+ node.endIndex = location.endOffset;
203
+ }
204
+ node.sourceCodeLocation = location;
205
+ },
206
+ getNodeSourceCodeLocation(node) {
207
+ return node.sourceCodeLocation;
208
+ },
209
+ updateNodeSourceCodeLocation(node, endLocation) {
210
+ if (endLocation.endOffset != null)
211
+ node.endIndex = endLocation.endOffset;
212
+ node.sourceCodeLocation = Object.assign(Object.assign({}, node.sourceCodeLocation), endLocation);
213
+ },
214
+ };
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,6 @@
1
+ import { type TreeAdapterTypeMap, type TreeAdapter } from 'parse5';
2
+ import { type AnyNode, type ParentNode, type ChildNode, Element, Document, ProcessingInstruction, Comment, Text } from 'domhandler';
3
+ export type Htmlparser2TreeAdapterMap = TreeAdapterTypeMap<AnyNode, ParentNode, ChildNode, Document, Document, Element, Comment, Text, Element, ProcessingInstruction>;
4
+ /** @internal */
5
+ export declare function serializeDoctypeContent(name: string, publicId: string, systemId: string): string;
6
+ export declare const adapter: TreeAdapter<Htmlparser2TreeAdapterMap>;
package/dist/index.js ADDED
@@ -0,0 +1,213 @@
1
+ import { html } from 'parse5';
2
+ import { Element, Document, ProcessingInstruction, Comment, Text, isDirective, isText, isComment, isTag, } from 'domhandler';
3
+ function enquoteDoctypeId(id) {
4
+ const quote = id.includes('"') ? "'" : '"';
5
+ return quote + id + quote;
6
+ }
7
+ /** @internal */
8
+ export function serializeDoctypeContent(name, publicId, systemId) {
9
+ let str = '!DOCTYPE ';
10
+ if (name) {
11
+ str += name;
12
+ }
13
+ if (publicId) {
14
+ str += ` PUBLIC ${enquoteDoctypeId(publicId)}`;
15
+ }
16
+ else if (systemId) {
17
+ str += ' SYSTEM';
18
+ }
19
+ if (systemId) {
20
+ str += ` ${enquoteDoctypeId(systemId)}`;
21
+ }
22
+ return str;
23
+ }
24
+ export const adapter = {
25
+ // Re-exports from domhandler
26
+ isCommentNode: isComment,
27
+ isElementNode: isTag,
28
+ isTextNode: isText,
29
+ //Node construction
30
+ createDocument() {
31
+ const node = new Document([]);
32
+ node['x-mode'] = html.DOCUMENT_MODE.NO_QUIRKS;
33
+ return node;
34
+ },
35
+ createDocumentFragment() {
36
+ return new Document([]);
37
+ },
38
+ createElement(tagName, namespaceURI, attrs) {
39
+ const attribs = Object.create(null);
40
+ const attribsNamespace = Object.create(null);
41
+ const attribsPrefix = Object.create(null);
42
+ for (let i = 0; i < attrs.length; i++) {
43
+ const attrName = attrs[i].name;
44
+ attribs[attrName] = attrs[i].value;
45
+ attribsNamespace[attrName] = attrs[i].namespace;
46
+ attribsPrefix[attrName] = attrs[i].prefix;
47
+ }
48
+ const node = new Element(tagName, attribs, []);
49
+ node.namespace = namespaceURI;
50
+ node['x-attribsNamespace'] = attribsNamespace;
51
+ node['x-attribsPrefix'] = attribsPrefix;
52
+ return node;
53
+ },
54
+ createCommentNode(data) {
55
+ return new Comment(data);
56
+ },
57
+ createTextNode(value) {
58
+ return new Text(value);
59
+ },
60
+ //Tree mutation
61
+ appendChild(parentNode, newNode) {
62
+ const prev = parentNode.children[parentNode.children.length - 1];
63
+ if (prev) {
64
+ prev.next = newNode;
65
+ newNode.prev = prev;
66
+ }
67
+ parentNode.children.push(newNode);
68
+ newNode.parent = parentNode;
69
+ },
70
+ insertBefore(parentNode, newNode, referenceNode) {
71
+ const insertionIdx = parentNode.children.indexOf(referenceNode);
72
+ const { prev } = referenceNode;
73
+ if (prev) {
74
+ prev.next = newNode;
75
+ newNode.prev = prev;
76
+ }
77
+ referenceNode.prev = newNode;
78
+ newNode.next = referenceNode;
79
+ parentNode.children.splice(insertionIdx, 0, newNode);
80
+ newNode.parent = parentNode;
81
+ },
82
+ setTemplateContent(templateElement, contentElement) {
83
+ adapter.appendChild(templateElement, contentElement);
84
+ },
85
+ getTemplateContent(templateElement) {
86
+ return templateElement.children[0];
87
+ },
88
+ setDocumentType(document, name, publicId, systemId) {
89
+ const data = serializeDoctypeContent(name, publicId, systemId);
90
+ let doctypeNode = document.children.find((node) => isDirective(node) && node.name === '!doctype');
91
+ if (doctypeNode) {
92
+ doctypeNode.data = data !== null && data !== void 0 ? data : null;
93
+ }
94
+ else {
95
+ doctypeNode = new ProcessingInstruction('!doctype', data);
96
+ adapter.appendChild(document, doctypeNode);
97
+ }
98
+ doctypeNode['x-name'] = name;
99
+ doctypeNode['x-publicId'] = publicId;
100
+ doctypeNode['x-systemId'] = systemId;
101
+ },
102
+ setDocumentMode(document, mode) {
103
+ document['x-mode'] = mode;
104
+ },
105
+ getDocumentMode(document) {
106
+ return document['x-mode'];
107
+ },
108
+ detachNode(node) {
109
+ if (node.parent) {
110
+ const idx = node.parent.children.indexOf(node);
111
+ const { prev, next } = node;
112
+ node.prev = null;
113
+ node.next = null;
114
+ if (prev) {
115
+ prev.next = next;
116
+ }
117
+ if (next) {
118
+ next.prev = prev;
119
+ }
120
+ node.parent.children.splice(idx, 1);
121
+ node.parent = null;
122
+ }
123
+ },
124
+ insertText(parentNode, text) {
125
+ const lastChild = parentNode.children[parentNode.children.length - 1];
126
+ if (lastChild && isText(lastChild)) {
127
+ lastChild.data += text;
128
+ }
129
+ else {
130
+ adapter.appendChild(parentNode, adapter.createTextNode(text));
131
+ }
132
+ },
133
+ insertTextBefore(parentNode, text, referenceNode) {
134
+ const prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
135
+ if (prevNode && isText(prevNode)) {
136
+ prevNode.data += text;
137
+ }
138
+ else {
139
+ adapter.insertBefore(parentNode, adapter.createTextNode(text), referenceNode);
140
+ }
141
+ },
142
+ adoptAttributes(recipient, attrs) {
143
+ for (let i = 0; i < attrs.length; i++) {
144
+ const attrName = attrs[i].name;
145
+ if (recipient.attribs[attrName] === undefined) {
146
+ recipient.attribs[attrName] = attrs[i].value;
147
+ recipient['x-attribsNamespace'][attrName] = attrs[i].namespace;
148
+ recipient['x-attribsPrefix'][attrName] = attrs[i].prefix;
149
+ }
150
+ }
151
+ },
152
+ //Tree traversing
153
+ getFirstChild(node) {
154
+ return node.children[0];
155
+ },
156
+ getChildNodes(node) {
157
+ return node.children;
158
+ },
159
+ getParentNode(node) {
160
+ return node.parent;
161
+ },
162
+ getAttrList(element) {
163
+ return element.attributes;
164
+ },
165
+ //Node data
166
+ getTagName(element) {
167
+ return element.name;
168
+ },
169
+ getNamespaceURI(element) {
170
+ return element.namespace;
171
+ },
172
+ getTextNodeContent(textNode) {
173
+ return textNode.data;
174
+ },
175
+ getCommentNodeContent(commentNode) {
176
+ return commentNode.data;
177
+ },
178
+ getDocumentTypeNodeName(doctypeNode) {
179
+ var _a;
180
+ return (_a = doctypeNode['x-name']) !== null && _a !== void 0 ? _a : '';
181
+ },
182
+ getDocumentTypeNodePublicId(doctypeNode) {
183
+ var _a;
184
+ return (_a = doctypeNode['x-publicId']) !== null && _a !== void 0 ? _a : '';
185
+ },
186
+ getDocumentTypeNodeSystemId(doctypeNode) {
187
+ var _a;
188
+ return (_a = doctypeNode['x-systemId']) !== null && _a !== void 0 ? _a : '';
189
+ },
190
+ //Node types
191
+ isDocumentTypeNode(node) {
192
+ return isDirective(node) && node.name === '!doctype';
193
+ },
194
+ // Source code location
195
+ setNodeSourceCodeLocation(node, location) {
196
+ if (location) {
197
+ node.startIndex = location.startOffset;
198
+ node.endIndex = location.endOffset;
199
+ }
200
+ node.sourceCodeLocation = location;
201
+ },
202
+ getNodeSourceCodeLocation(node) {
203
+ return node.sourceCodeLocation;
204
+ },
205
+ updateNodeSourceCodeLocation(node, endLocation) {
206
+ if (endLocation.endOffset != null)
207
+ node.endIndex = endLocation.endOffset;
208
+ node.sourceCodeLocation = {
209
+ ...node.sourceCodeLocation,
210
+ ...endLocation,
211
+ };
212
+ },
213
+ };
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "parse5-htmlparser2-tree-adapter",
3
+ "type": "module",
3
4
  "description": "htmlparser2 tree adapter for parse5.",
4
- "version": "6.0.1",
5
+ "version": "7.1.0",
5
6
  "author": "Ivan Nikulin <ifaaan@gmail.com> (https://github.com/inikulin)",
6
7
  "contributors": "https://github.com/inikulin/parse5/graphs/contributors",
7
- "homepage": "https://github.com/inikulin/parse5",
8
+ "homepage": "https://parse5.js.org",
9
+ "funding": "https://github.com/inikulin/parse5?sponsor=1",
8
10
  "keywords": [
9
11
  "parse5",
10
12
  "parser",
@@ -12,16 +14,27 @@
12
14
  "htmlparser2"
13
15
  ],
14
16
  "license": "MIT",
15
- "main": "./lib/index.js",
17
+ "main": "dist/cjs/index.js",
18
+ "module": "dist/index.js",
19
+ "types": "dist/index.d.ts",
20
+ "exports": {
21
+ "import": "./dist/index.js",
22
+ "require": "./dist/cjs/index.js"
23
+ },
16
24
  "dependencies": {
17
- "parse5": "^6.0.1"
25
+ "domhandler": "^5.0.3",
26
+ "parse5": "^7.0.0"
27
+ },
28
+ "scripts": {
29
+ "build:cjs": "tsc --moduleResolution node10 --module CommonJS --target ES6 --outDir dist/cjs && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json"
18
30
  },
19
31
  "repository": {
20
32
  "type": "git",
21
33
  "url": "git://github.com/inikulin/parse5.git"
22
34
  },
23
35
  "files": [
24
- "lib"
25
- ],
26
- "gitHead": "37227a3429584903cbd1799dade995266fc2dbe6"
36
+ "dist/cjs/package.json",
37
+ "dist/**/*.js",
38
+ "dist/**/*.d.ts"
39
+ ]
27
40
  }
package/lib/index.js DELETED
@@ -1,348 +0,0 @@
1
- 'use strict';
2
-
3
- const doctype = require('parse5/lib/common/doctype');
4
- const { DOCUMENT_MODE } = require('parse5/lib/common/html');
5
-
6
- //Conversion tables for DOM Level1 structure emulation
7
- const nodeTypes = {
8
- element: 1,
9
- text: 3,
10
- cdata: 4,
11
- comment: 8
12
- };
13
-
14
- const nodePropertyShorthands = {
15
- tagName: 'name',
16
- childNodes: 'children',
17
- parentNode: 'parent',
18
- previousSibling: 'prev',
19
- nextSibling: 'next',
20
- nodeValue: 'data'
21
- };
22
-
23
- //Node
24
- class Node {
25
- constructor(props) {
26
- for (const key of Object.keys(props)) {
27
- this[key] = props[key];
28
- }
29
- }
30
-
31
- get firstChild() {
32
- const children = this.children;
33
-
34
- return (children && children[0]) || null;
35
- }
36
-
37
- get lastChild() {
38
- const children = this.children;
39
-
40
- return (children && children[children.length - 1]) || null;
41
- }
42
-
43
- get nodeType() {
44
- return nodeTypes[this.type] || nodeTypes.element;
45
- }
46
- }
47
-
48
- Object.keys(nodePropertyShorthands).forEach(key => {
49
- const shorthand = nodePropertyShorthands[key];
50
-
51
- Object.defineProperty(Node.prototype, key, {
52
- get: function() {
53
- return this[shorthand] || null;
54
- },
55
- set: function(val) {
56
- this[shorthand] = val;
57
- return val;
58
- }
59
- });
60
- });
61
-
62
- //Node construction
63
- exports.createDocument = function() {
64
- return new Node({
65
- type: 'root',
66
- name: 'root',
67
- parent: null,
68
- prev: null,
69
- next: null,
70
- children: [],
71
- 'x-mode': DOCUMENT_MODE.NO_QUIRKS
72
- });
73
- };
74
-
75
- exports.createDocumentFragment = function() {
76
- return new Node({
77
- type: 'root',
78
- name: 'root',
79
- parent: null,
80
- prev: null,
81
- next: null,
82
- children: []
83
- });
84
- };
85
-
86
- exports.createElement = function(tagName, namespaceURI, attrs) {
87
- const attribs = Object.create(null);
88
- const attribsNamespace = Object.create(null);
89
- const attribsPrefix = Object.create(null);
90
-
91
- for (let i = 0; i < attrs.length; i++) {
92
- const attrName = attrs[i].name;
93
-
94
- attribs[attrName] = attrs[i].value;
95
- attribsNamespace[attrName] = attrs[i].namespace;
96
- attribsPrefix[attrName] = attrs[i].prefix;
97
- }
98
-
99
- return new Node({
100
- type: tagName === 'script' || tagName === 'style' ? tagName : 'tag',
101
- name: tagName,
102
- namespace: namespaceURI,
103
- attribs: attribs,
104
- 'x-attribsNamespace': attribsNamespace,
105
- 'x-attribsPrefix': attribsPrefix,
106
- children: [],
107
- parent: null,
108
- prev: null,
109
- next: null
110
- });
111
- };
112
-
113
- exports.createCommentNode = function(data) {
114
- return new Node({
115
- type: 'comment',
116
- data: data,
117
- parent: null,
118
- prev: null,
119
- next: null
120
- });
121
- };
122
-
123
- const createTextNode = function(value) {
124
- return new Node({
125
- type: 'text',
126
- data: value,
127
- parent: null,
128
- prev: null,
129
- next: null
130
- });
131
- };
132
-
133
- //Tree mutation
134
- const appendChild = (exports.appendChild = function(parentNode, newNode) {
135
- const prev = parentNode.children[parentNode.children.length - 1];
136
-
137
- if (prev) {
138
- prev.next = newNode;
139
- newNode.prev = prev;
140
- }
141
-
142
- parentNode.children.push(newNode);
143
- newNode.parent = parentNode;
144
- });
145
-
146
- const insertBefore = (exports.insertBefore = function(parentNode, newNode, referenceNode) {
147
- const insertionIdx = parentNode.children.indexOf(referenceNode);
148
- const prev = referenceNode.prev;
149
-
150
- if (prev) {
151
- prev.next = newNode;
152
- newNode.prev = prev;
153
- }
154
-
155
- referenceNode.prev = newNode;
156
- newNode.next = referenceNode;
157
-
158
- parentNode.children.splice(insertionIdx, 0, newNode);
159
- newNode.parent = parentNode;
160
- });
161
-
162
- exports.setTemplateContent = function(templateElement, contentElement) {
163
- appendChild(templateElement, contentElement);
164
- };
165
-
166
- exports.getTemplateContent = function(templateElement) {
167
- return templateElement.children[0];
168
- };
169
-
170
- exports.setDocumentType = function(document, name, publicId, systemId) {
171
- const data = doctype.serializeContent(name, publicId, systemId);
172
- let doctypeNode = null;
173
-
174
- for (let i = 0; i < document.children.length; i++) {
175
- if (document.children[i].type === 'directive' && document.children[i].name === '!doctype') {
176
- doctypeNode = document.children[i];
177
- break;
178
- }
179
- }
180
-
181
- if (doctypeNode) {
182
- doctypeNode.data = data;
183
- doctypeNode['x-name'] = name;
184
- doctypeNode['x-publicId'] = publicId;
185
- doctypeNode['x-systemId'] = systemId;
186
- } else {
187
- appendChild(
188
- document,
189
- new Node({
190
- type: 'directive',
191
- name: '!doctype',
192
- data: data,
193
- 'x-name': name,
194
- 'x-publicId': publicId,
195
- 'x-systemId': systemId
196
- })
197
- );
198
- }
199
- };
200
-
201
- exports.setDocumentMode = function(document, mode) {
202
- document['x-mode'] = mode;
203
- };
204
-
205
- exports.getDocumentMode = function(document) {
206
- return document['x-mode'];
207
- };
208
-
209
- exports.detachNode = function(node) {
210
- if (node.parent) {
211
- const idx = node.parent.children.indexOf(node);
212
- const prev = node.prev;
213
- const next = node.next;
214
-
215
- node.prev = null;
216
- node.next = null;
217
-
218
- if (prev) {
219
- prev.next = next;
220
- }
221
-
222
- if (next) {
223
- next.prev = prev;
224
- }
225
-
226
- node.parent.children.splice(idx, 1);
227
- node.parent = null;
228
- }
229
- };
230
-
231
- exports.insertText = function(parentNode, text) {
232
- const lastChild = parentNode.children[parentNode.children.length - 1];
233
-
234
- if (lastChild && lastChild.type === 'text') {
235
- lastChild.data += text;
236
- } else {
237
- appendChild(parentNode, createTextNode(text));
238
- }
239
- };
240
-
241
- exports.insertTextBefore = function(parentNode, text, referenceNode) {
242
- const prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
243
-
244
- if (prevNode && prevNode.type === 'text') {
245
- prevNode.data += text;
246
- } else {
247
- insertBefore(parentNode, createTextNode(text), referenceNode);
248
- }
249
- };
250
-
251
- exports.adoptAttributes = function(recipient, attrs) {
252
- for (let i = 0; i < attrs.length; i++) {
253
- const attrName = attrs[i].name;
254
-
255
- if (typeof recipient.attribs[attrName] === 'undefined') {
256
- recipient.attribs[attrName] = attrs[i].value;
257
- recipient['x-attribsNamespace'][attrName] = attrs[i].namespace;
258
- recipient['x-attribsPrefix'][attrName] = attrs[i].prefix;
259
- }
260
- }
261
- };
262
-
263
- //Tree traversing
264
- exports.getFirstChild = function(node) {
265
- return node.children[0];
266
- };
267
-
268
- exports.getChildNodes = function(node) {
269
- return node.children;
270
- };
271
-
272
- exports.getParentNode = function(node) {
273
- return node.parent;
274
- };
275
-
276
- exports.getAttrList = function(element) {
277
- const attrList = [];
278
-
279
- for (const name in element.attribs) {
280
- attrList.push({
281
- name: name,
282
- value: element.attribs[name],
283
- namespace: element['x-attribsNamespace'][name],
284
- prefix: element['x-attribsPrefix'][name]
285
- });
286
- }
287
-
288
- return attrList;
289
- };
290
-
291
- //Node data
292
- exports.getTagName = function(element) {
293
- return element.name;
294
- };
295
-
296
- exports.getNamespaceURI = function(element) {
297
- return element.namespace;
298
- };
299
-
300
- exports.getTextNodeContent = function(textNode) {
301
- return textNode.data;
302
- };
303
-
304
- exports.getCommentNodeContent = function(commentNode) {
305
- return commentNode.data;
306
- };
307
-
308
- exports.getDocumentTypeNodeName = function(doctypeNode) {
309
- return doctypeNode['x-name'];
310
- };
311
-
312
- exports.getDocumentTypeNodePublicId = function(doctypeNode) {
313
- return doctypeNode['x-publicId'];
314
- };
315
-
316
- exports.getDocumentTypeNodeSystemId = function(doctypeNode) {
317
- return doctypeNode['x-systemId'];
318
- };
319
-
320
- //Node types
321
- exports.isTextNode = function(node) {
322
- return node.type === 'text';
323
- };
324
-
325
- exports.isCommentNode = function(node) {
326
- return node.type === 'comment';
327
- };
328
-
329
- exports.isDocumentTypeNode = function(node) {
330
- return node.type === 'directive' && node.name === '!doctype';
331
- };
332
-
333
- exports.isElementNode = function(node) {
334
- return !!node.attribs;
335
- };
336
-
337
- // Source code location
338
- exports.setNodeSourceCodeLocation = function(node, location) {
339
- node.sourceCodeLocation = location;
340
- };
341
-
342
- exports.getNodeSourceCodeLocation = function(node) {
343
- return node.sourceCodeLocation;
344
- };
345
-
346
- exports.updateNodeSourceCodeLocation = function(node, endLocation) {
347
- node.sourceCodeLocation = Object.assign(node.sourceCodeLocation, endLocation);
348
- };