als-document 1.1.1 → 1.1.2

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/document.js CHANGED
@@ -22,7 +22,7 @@ function buildStyle(attributes){
22
22
  const styles=attributes.style || "";
23
23
  con
24
24
  class NodeClassList{
25
25
  constructor(node){ this.node=node }
26
26
  get classes(){ return (this.node.attributes.class || "").split(" ").filter(Boolean) }
27
27
  set classes(val){ this.node.attributes.class=val.join(" ") }
28
28
  contains(className){ return this.classes.includes(className) }
29
29
  add(className){
30
30
  const currentClasses=this.classes;
31
31
  if (!currentClasses.includes(className)) this.classes=[...currentClasses,className];
32
32
  }
33
33
  remove(className){ this.classes=this.classes.filter(cls=>cls!==className); }
34
34
  toggle(className){
35
35
  if (this.classes.includes(className)) this.remove(className);
36
36
  else this.add(className);
37
37
  }
38
38
  replace(oldClass,newClass){
39
39
  if (this.classes.includes(oldClass)){
40
40
  this.remove(oldClass);
41
41
  this.add(newClass);
42
42
  }
43
43
  }
44
44
  }
45
45
  function insertBefore(arr,index,newItem){
46
46
  const existingIndex=arr.indexOf(newItem);
47
47
  if (existingIndex!==-1) arr.splice(existingIndex,1);
48
48
  arr.splice(index,0,newItem);
49
- }
50
49
  class Node{
51
50
  constructor(tagName,attributes={},parent=null){
52
51
  this.isSingle=false;
53
52
  this.tagName=tagName;
54
53
  this.attributes=attributes;
55
54
  this.childNodes=[];
56
55
  if (parent!==null) parent.childNodes.push(this)
57
56
  this.parent=parent;
58
57
  this._classList=null;
59
58
  this.__style=null;
60
59
  this._dataset=null
61
60
  }
62
61
  get id(){ return this.attributes.id ? this.attributes.id : null; }
63
62
  set id(newValue){ this.attributes.id=newValue; }
64
63
  get className(){ return this.attributes.class || null }
65
64
  get parentNode(){ return this.parent }
66
65
  get ancestors(){
67
66
  if (!this.parent) return []
68
67
  const ancestors=[]
69
68
  let element=this.parent
70
69
  while (element.tagName!=='ROOT'){
71
70
  ancestors.push(element)
72
71
  element=element.parent
73
72
  }
74
73
  return ancestors.reverse()
75
74
  }
76
75
  get childNodeIndex(){
77
76
  if (!this.parent) return null
78
77
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
79
78
  }
80
79
  get childIndex(){
81
80
  if (!this.parent) return null
82
81
  return this.parent.children ? this.parent.children.indexOf(this) : null
83
82
  }
84
83
  get previousElementSibling(){ return this.prev }
85
84
  get prev(){
86
85
  if (!this.childIndex) return null
87
86
  return this.parent.children[this.childIndex-1]
88
87
  }
89
88
  get nextElementSibling(){ return this.next }
90
89
  get next(){
91
90
  if (!this.childIndex) return null
92
91
  return this.parent.children[this.childIndex+1] || null
93
92
  }
94
93
  get dataset(){
95
94
  if (!this._dataset) this._dataset=getDataset(this);
96
95
  return this._dataset;
97
96
  }
98
97
  get classList(){
99
98
  if (!this._classList) this._classList=new NodeClassList(this);
100
99
  return this._classList;
101
100
  }
102
101
  get style(){
103
102
  if (!this.__style) this.__style=buildStyle(this.attributes)
104
103
  return this.__style
105
104
  }
106
105
  get outerHTML(){
107
106
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
108
107
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
109
108
  }
110
109
  getAttribute(attrName){ return this.attributes[attrName] || null }
111
110
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
112
111
  removeAttribute(attrName){ delete this.attributes[attrName] }
113
112
  remove(){
114
113
  if (!this.parent) return
115
114
  const index=this.childNodeIndex;
116
115
  if (index!==null) this.parent.childNodes.splice(index,1);
117
116
  }
118
117
  get innerHTML(){
119
118
  return this.childNodes.map(child=>{
120
119
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
121
120
  else if (child instanceof TextNode) return child.textContent;
122
121
  else return child
123
122
  }).join("");
124
123
  }
125
124
  $$(query){ return this.querySelectorAll(query) }
126
125
  querySelectorAll(query){
127
126
  const selectors=Query.get(query)
128
127
  return find(selectors,this,new Set())
129
128
  }
130
129
  $(query){ return this.querySelector(query) }
131
130
  querySelector(query){
132
131
  const selectors=Query.get(query)
133
132
  return find(selectors,this,new Set(),true)[0] || null
134
133
  }
135
134
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
136
135
  getElementsByTagName(query){ return this.querySelectorAll(query) }
137
136
  getElementById(query){ return this.querySelector('#'+query) }
138
137
  get children(){
139
138
  return this.childNodes.filter(child=>{
140
139
  if (!(child instanceof Node)) return false
141
140
  if (child.tagName==='#comment') return false
142
141
  return true
143
142
  });
144
143
  }
145
144
  insertAdjacentElement(position,newElement){
146
145
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
147
146
  const pos=position.toLowerCase();
148
147
  if (pos==='afterbegin' || pos==='beforeend'){
149
148
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
150
149
  else if (pos==="beforeend") this.childNodes.push(newElement);
151
150
  newElement.parent=this
152
151
  return newElement
153
152
  }
154
153
  if (!this.parent) throw new Error("Can't insert element to element without parent")
155
154
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
156
155
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
157
156
  newElement.parent=this.parent
158
157
  return newElement
159
158
  }
160
159
  insertAdjacentHTML(position,html){
161
160
  const newNode=parseHTML(html);
162
161
  newNode.childNodes.forEach(node=>{
163
162
  this.insertAdjacentElement(position,node);
164
163
  });
165
164
  return newNode
166
165
  }
167
166
  insertAdjacentText(position,text){
168
167
  return this.insertAdjacentElement(position,new TextNode(text));
169
168
  }
170
169
  insert(position,element){
171
170
  const positions=['beforebegin','afterbegin','beforeend','afterend']
172
171
  if (positions[position]) position=positions[position]
173
172
  if (typeof element==='string'){
174
173
  element=element.trim()
175
174
  if (element.startsWith('<') && element.endsWith('>')){
176
175
  return this.insertAdjacentHTML(position,element)
177
176
  }
178
177
  return this.insertAdjacentText(position,element)
179
178
  }
180
179
  return this.insertAdjacentElement(position,element)
181
180
  }
182
181
  set innerHTML(html){
183
182
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
184
183
  }
185
184
  set outerHTML(html){
186
185
  const parsed=parseHTML(html);
187
186
  if (!this.parent) return console.log('element has no parent node')
188
187
  const index=this.childIndex
189
188
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
190
189
  }
191
190
  appendChild(newChild){
192
191
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
193
192
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
194
193
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
195
194
  else return newChild
196
195
  this.childNodes.push(newChild);
197
196
  newChild.parent=this;
198
197
  return newChild;
199
198
  }
200
199
  get textContent(){
201
200
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
202
201
  return this.childNodes.map(child=>{
203
202
  if (child instanceof SingleNode) return ''
204
203
  if (child instanceof TextNode) return child.nodeValue
205
204
  if (child instanceof Node) return child.textContent;
206
205
  else return child;
207
206
  }).join(" ");
208
207
  }
209
208
  set textContent(value){
210
209
  this.childNodes=[];
211
210
  if (value!==null && value!==undefined){
212
211
  this.childNodes.push(value.toString());
213
212
  }
214
213
  }
214
+ }
215
215
  class Node{
216
216
  constructor(tagName,attributes={},parent=null){
217
217
  this.isSingle=false;
218
218
  this.tagName=tagName;
219
219
  this.attributes=attributes;
220
220
  this.childNodes=[];
221
221
  if (parent!==null) parent.childNodes.push(this)
222
222
  this.parent=parent;
223
223
  this._classList=null;
224
224
  this.__style=null;
225
225
  this._dataset=null
226
226
  }
227
227
  get id(){ return this.attributes.id ? this.attributes.id : null; }
228
228
  set id(newValue){ this.attributes.id=newValue; }
229
229
  get className(){ return this.attributes.class || null }
230
230
  get parentNode(){ return this.parent }
231
231
  get ancestors(){
232
232
  if (!this.parent) return []
233
233
  const ancestors=[]
234
234
  let element=this.parent
235
235
  while (element.tagName!=='ROOT'){
236
236
  ancestors.push(element)
237
237
  element=element.parent
238
238
  }
239
239
  return ancestors.reverse()
240
240
  }
241
241
  get childNodeIndex(){
242
242
  if (!this.parent) return null
243
243
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
244
244
  }
245
245
  get childIndex(){
246
246
  if (!this.parent) return null
247
247
  return this.parent.children ? this.parent.children.indexOf(this) : null
248
248
  }
249
249
  get previousElementSibling(){ return this.prev }
250
250
  get prev(){
251
251
  if (!this.childIndex) return null
252
252
  return this.parent.children[this.childIndex-1]
253
253
  }
254
254
  get nextElementSibling(){ return this.next }
255
255
  get next(){
256
256
  if (!this.childIndex) return null
257
257
  return this.parent.children[this.childIndex+1] || null
258
258
  }
259
259
  get dataset(){
260
260
  if (!this._dataset) this._dataset=getDataset(this);
261
261
  return this._dataset;
262
262
  }
263
263
  get classList(){
264
264
  if (!this._classList) this._classList=new NodeClassList(this);
265
265
  return this._classList;
266
266
  }
267
267
  get style(){
268
268
  if (!this.__style) this.__style=buildStyle(this.attributes)
269
269
  return this.__style
270
270
  }
271
271
  get outerHTML(){
272
272
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
273
273
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
274
274
  }
275
275
  getAttribute(attrName){ return this.attributes[attrName]!==undefined ? this.attributes[attrName] : null }
276
276
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
277
277
  removeAttribute(attrName){ delete this.attributes[attrName] }
278
278
  remove(){
279
279
  if (!this.parent) return
280
280
  const index=this.childNodeIndex;
281
281
  if (index!==null) this.parent.childNodes.splice(index,1);
282
282
  }
283
283
  get innerHTML(){
284
284
  return this.childNodes.map(child=>{
285
285
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
286
286
  else if (child instanceof TextNode) return child.textContent;
287
287
  else return child
288
288
  }).join("");
289
289
  }
290
290
  $$(query){ return this.querySelectorAll(query) }
291
291
  querySelectorAll(query){
292
292
  const selectors=Query.get(query)
293
293
  return find(selectors,this,new Set())
294
294
  }
295
295
  $(query){ return this.querySelector(query) }
296
296
  querySelector(query){
297
297
  const selectors=Query.get(query)
298
298
  return find(selectors,this,new Set(),true)[0] || null
299
299
  }
300
300
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
301
301
  getElementsByTagName(query){ return this.querySelectorAll(query) }
302
302
  getElementById(query){ return this.querySelector('#'+query) }
303
303
  get children(){
304
304
  return this.childNodes.filter(child=>{
305
305
  if (!(child instanceof Node)) return false
306
306
  if (child.tagName==='#comment') return false
307
307
  return true
308
308
  });
309
309
  }
310
310
  insertAdjacentElement(position,newElement){
311
311
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
312
312
  const pos=position.toLowerCase();
313
313
  if (pos==='afterbegin' || pos==='beforeend'){
314
314
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
315
315
  else if (pos==="beforeend") this.childNodes.push(newElement);
316
316
  newElement.parent=this
317
317
  return newElement
318
318
  }
319
319
  if (!this.parent) throw new Error("Can't insert element to element without parent")
320
320
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
321
321
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
322
322
  newElement.parent=this.parent
323
323
  return newElement
324
324
  }
325
325
  insertAdjacentHTML(position,html){
326
326
  const newNode=parseHTML(html);
327
327
  newNode.childNodes.forEach(node=>{
328
328
  this.insertAdjacentElement(position,node);
329
329
  });
330
330
  return newNode
331
331
  }
332
332
  insertAdjacentText(position,text){
333
333
  return this.insertAdjacentElement(position,new TextNode(text));
334
334
  }
335
335
  insert(position,element){
336
336
  const positions=['beforebegin','afterbegin','beforeend','afterend']
337
337
  if (positions[position]) position=positions[position]
338
338
  if (typeof element==='string'){
339
339
  element=element.trim()
340
340
  if (element.startsWith('<') && element.endsWith('>')){
341
341
  return this.insertAdjacentHTML(position,element)
342
342
  }
343
343
  return this.insertAdjacentText(position,element)
344
344
  }
345
345
  return this.insertAdjacentElement(position,element)
346
346
  }
347
347
  set innerHTML(html){
348
348
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
349
349
  }
350
350
  set outerHTML(html){
351
351
  const parsed=parseHTML(html);
352
352
  if (!this.parent) return console.log('element has no parent node')
353
353
  const index=this.childIndex
354
354
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
355
355
  }
356
356
  appendChild(newChild){
357
357
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
358
358
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
359
359
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
360
360
  else return newChild
361
361
  this.childNodes.push(newChild);
362
362
  newChild.parent=this;
363
363
  return newChild;
364
364
  }
365
365
  get textContent(){
366
366
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
367
367
  return this.childNodes.map(child=>{
368
368
  if (child instanceof SingleNode) return ''
369
369
  if (child instanceof TextNode) return child.nodeValue
370
370
  if (child instanceof Node) return child.textContent;
371
371
  else return child;
372
372
  }).join(" ");
373
373
  }
374
374
  set textContent(value){
375
375
  this.childNodes=[];
376
376
  if (value!==null && value!==undefined){
377
377
  this.childNodes.push(value.toString());
378
378
  }
379
379
  }
380
380
  }
381
381
  class SingleNode extends Node{
382
382
  constructor(tagName,attributes={},parent=null){
383
383
  if(attributes['?'] && tagName==='?xml') delete attributes['?']
384
384
  super(tagName,attributes,parent);
385
385
  this.isSingle=true
386
386
  }
387
387
  get outerHTML(){
388
388
  if (this.tagName==="#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
389
389
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
390
390
  return `<${this.tagName} ${attrs}${this.tagName==='?xml' ? '?' : ''}>`;
391
391
  }
392
392
  get innerHTML(){ return ""; }
393
393
  set innerHTML(_){ }
394
394
  $(_){return null}
395
395
  $$(_){return []}
396
396
  querySelectorAll(_){ return []; }
397
397
  querySelector(_){ return null; }
398
398
  getElementsByClassName(_){ return []; }
399
399
  getElementsByTagName(_){ return []; }
400
400
  getElementById(_){ return null; }
401
401
  get children(){ return []; }
402
402
  insertAdjacentElement(_,__){ }
403
403
  insertAdjacentHTML(_,__){ }
404
404
  insertAdjacentText(_,__){ }
405
405
  appendChild(_){ }
406
406
  insert(_,__){ }
407
407
  get textContent(){ return ""; }
408
408
  set textContent(_){ }
409
409
  }
package/index.js CHANGED
@@ -21,7 +21,7 @@ function buildStyle(attributes){
21
21
  const styles=attributes.style || "";
22
22
  con
23
23
  class NodeClassList{
24
24
  constructor(node){ this.node=node }
25
25
  get classes(){ return (this.node.attributes.class || "").split(" ").filter(Boolean) }
26
26
  set classes(val){ this.node.attributes.class=val.join(" ") }
27
27
  contains(className){ return this.classes.includes(className) }
28
28
  add(className){
29
29
  const currentClasses=this.classes;
30
30
  if (!currentClasses.includes(className)) this.classes=[...currentClasses,className];
31
31
  }
32
32
  remove(className){ this.classes=this.classes.filter(cls=>cls!==className); }
33
33
  toggle(className){
34
34
  if (this.classes.includes(className)) this.remove(className);
35
35
  else this.add(className);
36
36
  }
37
37
  replace(oldClass,newClass){
38
38
  if (this.classes.includes(oldClass)){
39
39
  this.remove(oldClass);
40
40
  this.add(newClass);
41
41
  }
42
42
  }
43
43
  }
44
44
  function insertBefore(arr,index,newItem){
45
45
  const existingIndex=arr.indexOf(newItem);
46
46
  if (existingIndex!==-1) arr.splice(existingIndex,1);
47
47
  arr.splice(index,0,newItem);
48
- }
49
48
  class Node{
50
49
  constructor(tagName,attributes={},parent=null){
51
50
  this.isSingle=false;
52
51
  this.tagName=tagName;
53
52
  this.attributes=attributes;
54
53
  this.childNodes=[];
55
54
  if (parent!==null) parent.childNodes.push(this)
56
55
  this.parent=parent;
57
56
  this._classList=null;
58
57
  this.__style=null;
59
58
  this._dataset=null
60
59
  }
61
60
  get id(){ return this.attributes.id ? this.attributes.id : null; }
62
61
  set id(newValue){ this.attributes.id=newValue; }
63
62
  get className(){ return this.attributes.class || null }
64
63
  get parentNode(){ return this.parent }
65
64
  get ancestors(){
66
65
  if (!this.parent) return []
67
66
  const ancestors=[]
68
67
  let element=this.parent
69
68
  while (element.tagName!=='ROOT'){
70
69
  ancestors.push(element)
71
70
  element=element.parent
72
71
  }
73
72
  return ancestors.reverse()
74
73
  }
75
74
  get childNodeIndex(){
76
75
  if (!this.parent) return null
77
76
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
78
77
  }
79
78
  get childIndex(){
80
79
  if (!this.parent) return null
81
80
  return this.parent.children ? this.parent.children.indexOf(this) : null
82
81
  }
83
82
  get previousElementSibling(){ return this.prev }
84
83
  get prev(){
85
84
  if (!this.childIndex) return null
86
85
  return this.parent.children[this.childIndex-1]
87
86
  }
88
87
  get nextElementSibling(){ return this.next }
89
88
  get next(){
90
89
  if (!this.childIndex) return null
91
90
  return this.parent.children[this.childIndex+1] || null
92
91
  }
93
92
  get dataset(){
94
93
  if (!this._dataset) this._dataset=getDataset(this);
95
94
  return this._dataset;
96
95
  }
97
96
  get classList(){
98
97
  if (!this._classList) this._classList=new NodeClassList(this);
99
98
  return this._classList;
100
99
  }
101
100
  get style(){
102
101
  if (!this.__style) this.__style=buildStyle(this.attributes)
103
102
  return this.__style
104
103
  }
105
104
  get outerHTML(){
106
105
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
107
106
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
108
107
  }
109
108
  getAttribute(attrName){ return this.attributes[attrName] || null }
110
109
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
111
110
  removeAttribute(attrName){ delete this.attributes[attrName] }
112
111
  remove(){
113
112
  if (!this.parent) return
114
113
  const index=this.childNodeIndex;
115
114
  if (index!==null) this.parent.childNodes.splice(index,1);
116
115
  }
117
116
  get innerHTML(){
118
117
  return this.childNodes.map(child=>{
119
118
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
120
119
  else if (child instanceof TextNode) return child.textContent;
121
120
  else return child
122
121
  }).join("");
123
122
  }
124
123
  $$(query){ return this.querySelectorAll(query) }
125
124
  querySelectorAll(query){
126
125
  const selectors=Query.get(query)
127
126
  return find(selectors,this,new Set())
128
127
  }
129
128
  $(query){ return this.querySelector(query) }
130
129
  querySelector(query){
131
130
  const selectors=Query.get(query)
132
131
  return find(selectors,this,new Set(),true)[0] || null
133
132
  }
134
133
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
135
134
  getElementsByTagName(query){ return this.querySelectorAll(query) }
136
135
  getElementById(query){ return this.querySelector('#'+query) }
137
136
  get children(){
138
137
  return this.childNodes.filter(child=>{
139
138
  if (!(child instanceof Node)) return false
140
139
  if (child.tagName==='#comment') return false
141
140
  return true
142
141
  });
143
142
  }
144
143
  insertAdjacentElement(position,newElement){
145
144
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
146
145
  const pos=position.toLowerCase();
147
146
  if (pos==='afterbegin' || pos==='beforeend'){
148
147
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
149
148
  else if (pos==="beforeend") this.childNodes.push(newElement);
150
149
  newElement.parent=this
151
150
  return newElement
152
151
  }
153
152
  if (!this.parent) throw new Error("Can't insert element to element without parent")
154
153
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
155
154
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
156
155
  newElement.parent=this.parent
157
156
  return newElement
158
157
  }
159
158
  insertAdjacentHTML(position,html){
160
159
  const newNode=parseHTML(html);
161
160
  newNode.childNodes.forEach(node=>{
162
161
  this.insertAdjacentElement(position,node);
163
162
  });
164
163
  return newNode
165
164
  }
166
165
  insertAdjacentText(position,text){
167
166
  return this.insertAdjacentElement(position,new TextNode(text));
168
167
  }
169
168
  insert(position,element){
170
169
  const positions=['beforebegin','afterbegin','beforeend','afterend']
171
170
  if (positions[position]) position=positions[position]
172
171
  if (typeof element==='string'){
173
172
  element=element.trim()
174
173
  if (element.startsWith('<') && element.endsWith('>')){
175
174
  return this.insertAdjacentHTML(position,element)
176
175
  }
177
176
  return this.insertAdjacentText(position,element)
178
177
  }
179
178
  return this.insertAdjacentElement(position,element)
180
179
  }
181
180
  set innerHTML(html){
182
181
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
183
182
  }
184
183
  set outerHTML(html){
185
184
  const parsed=parseHTML(html);
186
185
  if (!this.parent) return console.log('element has no parent node')
187
186
  const index=this.childIndex
188
187
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
189
188
  }
190
189
  appendChild(newChild){
191
190
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
192
191
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
193
192
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
194
193
  else return newChild
195
194
  this.childNodes.push(newChild);
196
195
  newChild.parent=this;
197
196
  return newChild;
198
197
  }
199
198
  get textContent(){
200
199
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
201
200
  return this.childNodes.map(child=>{
202
201
  if (child instanceof SingleNode) return ''
203
202
  if (child instanceof TextNode) return child.nodeValue
204
203
  if (child instanceof Node) return child.textContent;
205
204
  else return child;
206
205
  }).join(" ");
207
206
  }
208
207
  set textContent(value){
209
208
  this.childNodes=[];
210
209
  if (value!==null && value!==undefined){
211
210
  this.childNodes.push(value.toString());
212
211
  }
213
212
  }
213
+ }
214
214
  class Node{
215
215
  constructor(tagName,attributes={},parent=null){
216
216
  this.isSingle=false;
217
217
  this.tagName=tagName;
218
218
  this.attributes=attributes;
219
219
  this.childNodes=[];
220
220
  if (parent!==null) parent.childNodes.push(this)
221
221
  this.parent=parent;
222
222
  this._classList=null;
223
223
  this.__style=null;
224
224
  this._dataset=null
225
225
  }
226
226
  get id(){ return this.attributes.id ? this.attributes.id : null; }
227
227
  set id(newValue){ this.attributes.id=newValue; }
228
228
  get className(){ return this.attributes.class || null }
229
229
  get parentNode(){ return this.parent }
230
230
  get ancestors(){
231
231
  if (!this.parent) return []
232
232
  const ancestors=[]
233
233
  let element=this.parent
234
234
  while (element.tagName!=='ROOT'){
235
235
  ancestors.push(element)
236
236
  element=element.parent
237
237
  }
238
238
  return ancestors.reverse()
239
239
  }
240
240
  get childNodeIndex(){
241
241
  if (!this.parent) return null
242
242
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
243
243
  }
244
244
  get childIndex(){
245
245
  if (!this.parent) return null
246
246
  return this.parent.children ? this.parent.children.indexOf(this) : null
247
247
  }
248
248
  get previousElementSibling(){ return this.prev }
249
249
  get prev(){
250
250
  if (!this.childIndex) return null
251
251
  return this.parent.children[this.childIndex-1]
252
252
  }
253
253
  get nextElementSibling(){ return this.next }
254
254
  get next(){
255
255
  if (!this.childIndex) return null
256
256
  return this.parent.children[this.childIndex+1] || null
257
257
  }
258
258
  get dataset(){
259
259
  if (!this._dataset) this._dataset=getDataset(this);
260
260
  return this._dataset;
261
261
  }
262
262
  get classList(){
263
263
  if (!this._classList) this._classList=new NodeClassList(this);
264
264
  return this._classList;
265
265
  }
266
266
  get style(){
267
267
  if (!this.__style) this.__style=buildStyle(this.attributes)
268
268
  return this.__style
269
269
  }
270
270
  get outerHTML(){
271
271
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
272
272
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
273
273
  }
274
274
  getAttribute(attrName){ return this.attributes[attrName]!==undefined ? this.attributes[attrName] : null }
275
275
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
276
276
  removeAttribute(attrName){ delete this.attributes[attrName] }
277
277
  remove(){
278
278
  if (!this.parent) return
279
279
  const index=this.childNodeIndex;
280
280
  if (index!==null) this.parent.childNodes.splice(index,1);
281
281
  }
282
282
  get innerHTML(){
283
283
  return this.childNodes.map(child=>{
284
284
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
285
285
  else if (child instanceof TextNode) return child.textContent;
286
286
  else return child
287
287
  }).join("");
288
288
  }
289
289
  $$(query){ return this.querySelectorAll(query) }
290
290
  querySelectorAll(query){
291
291
  const selectors=Query.get(query)
292
292
  return find(selectors,this,new Set())
293
293
  }
294
294
  $(query){ return this.querySelector(query) }
295
295
  querySelector(query){
296
296
  const selectors=Query.get(query)
297
297
  return find(selectors,this,new Set(),true)[0] || null
298
298
  }
299
299
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
300
300
  getElementsByTagName(query){ return this.querySelectorAll(query) }
301
301
  getElementById(query){ return this.querySelector('#'+query) }
302
302
  get children(){
303
303
  return this.childNodes.filter(child=>{
304
304
  if (!(child instanceof Node)) return false
305
305
  if (child.tagName==='#comment') return false
306
306
  return true
307
307
  });
308
308
  }
309
309
  insertAdjacentElement(position,newElement){
310
310
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
311
311
  const pos=position.toLowerCase();
312
312
  if (pos==='afterbegin' || pos==='beforeend'){
313
313
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
314
314
  else if (pos==="beforeend") this.childNodes.push(newElement);
315
315
  newElement.parent=this
316
316
  return newElement
317
317
  }
318
318
  if (!this.parent) throw new Error("Can't insert element to element without parent")
319
319
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
320
320
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
321
321
  newElement.parent=this.parent
322
322
  return newElement
323
323
  }
324
324
  insertAdjacentHTML(position,html){
325
325
  const newNode=parseHTML(html);
326
326
  newNode.childNodes.forEach(node=>{
327
327
  this.insertAdjacentElement(position,node);
328
328
  });
329
329
  return newNode
330
330
  }
331
331
  insertAdjacentText(position,text){
332
332
  return this.insertAdjacentElement(position,new TextNode(text));
333
333
  }
334
334
  insert(position,element){
335
335
  const positions=['beforebegin','afterbegin','beforeend','afterend']
336
336
  if (positions[position]) position=positions[position]
337
337
  if (typeof element==='string'){
338
338
  element=element.trim()
339
339
  if (element.startsWith('<') && element.endsWith('>')){
340
340
  return this.insertAdjacentHTML(position,element)
341
341
  }
342
342
  return this.insertAdjacentText(position,element)
343
343
  }
344
344
  return this.insertAdjacentElement(position,element)
345
345
  }
346
346
  set innerHTML(html){
347
347
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
348
348
  }
349
349
  set outerHTML(html){
350
350
  const parsed=parseHTML(html);
351
351
  if (!this.parent) return console.log('element has no parent node')
352
352
  const index=this.childIndex
353
353
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
354
354
  }
355
355
  appendChild(newChild){
356
356
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
357
357
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
358
358
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
359
359
  else return newChild
360
360
  this.childNodes.push(newChild);
361
361
  newChild.parent=this;
362
362
  return newChild;
363
363
  }
364
364
  get textContent(){
365
365
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
366
366
  return this.childNodes.map(child=>{
367
367
  if (child instanceof SingleNode) return ''
368
368
  if (child instanceof TextNode) return child.nodeValue
369
369
  if (child instanceof Node) return child.textContent;
370
370
  else return child;
371
371
  }).join(" ");
372
372
  }
373
373
  set textContent(value){
374
374
  this.childNodes=[];
375
375
  if (value!==null && value!==undefined){
376
376
  this.childNodes.push(value.toString());
377
377
  }
378
378
  }
379
379
  }
380
380
  class SingleNode extends Node{
381
381
  constructor(tagName,attributes={},parent=null){
382
382
  if(attributes['?'] && tagName==='?xml') delete attributes['?']
383
383
  super(tagName,attributes,parent);
384
384
  this.isSingle=true
385
385
  }
386
386
  get outerHTML(){
387
387
  if (this.tagName==="#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
388
388
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
389
389
  return `<${this.tagName} ${attrs}${this.tagName==='?xml' ? '?' : ''}>`;
390
390
  }
391
391
  get innerHTML(){ return ""; }
392
392
  set innerHTML(_){ }
393
393
  $(_){return null}
394
394
  $$(_){return []}
395
395
  querySelectorAll(_){ return []; }
396
396
  querySelector(_){ return null; }
397
397
  getElementsByClassName(_){ return []; }
398
398
  getElementsByTagName(_){ return []; }
399
399
  getElementById(_){ return null; }
400
400
  get children(){ return []; }
401
401
  insertAdjacentElement(_,__){ }
402
402
  insertAdjacentHTML(_,__){ }
403
403
  insertAdjacentText(_,__){ }
404
404
  appendChild(_){ }
405
405
  insert(_,__){ }
406
406
  get textContent(){ return ""; }
407
407
  set textContent(_){ }
408
408
  }
package/index.mjs CHANGED
@@ -21,7 +21,7 @@ function buildStyle(attributes){
21
21
  const styles=attributes.style || "";
22
22
  con
23
23
  class NodeClassList{
24
24
  constructor(node){ this.node=node }
25
25
  get classes(){ return (this.node.attributes.class || "").split(" ").filter(Boolean) }
26
26
  set classes(val){ this.node.attributes.class=val.join(" ") }
27
27
  contains(className){ return this.classes.includes(className) }
28
28
  add(className){
29
29
  const currentClasses=this.classes;
30
30
  if (!currentClasses.includes(className)) this.classes=[...currentClasses,className];
31
31
  }
32
32
  remove(className){ this.classes=this.classes.filter(cls=>cls!==className); }
33
33
  toggle(className){
34
34
  if (this.classes.includes(className)) this.remove(className);
35
35
  else this.add(className);
36
36
  }
37
37
  replace(oldClass,newClass){
38
38
  if (this.classes.includes(oldClass)){
39
39
  this.remove(oldClass);
40
40
  this.add(newClass);
41
41
  }
42
42
  }
43
43
  }
44
44
  function insertBefore(arr,index,newItem){
45
45
  const existingIndex=arr.indexOf(newItem);
46
46
  if (existingIndex!==-1) arr.splice(existingIndex,1);
47
47
  arr.splice(index,0,newItem);
48
- }
49
48
  class Node{
50
49
  constructor(tagName,attributes={},parent=null){
51
50
  this.isSingle=false;
52
51
  this.tagName=tagName;
53
52
  this.attributes=attributes;
54
53
  this.childNodes=[];
55
54
  if (parent!==null) parent.childNodes.push(this)
56
55
  this.parent=parent;
57
56
  this._classList=null;
58
57
  this.__style=null;
59
58
  this._dataset=null
60
59
  }
61
60
  get id(){ return this.attributes.id ? this.attributes.id : null; }
62
61
  set id(newValue){ this.attributes.id=newValue; }
63
62
  get className(){ return this.attributes.class || null }
64
63
  get parentNode(){ return this.parent }
65
64
  get ancestors(){
66
65
  if (!this.parent) return []
67
66
  const ancestors=[]
68
67
  let element=this.parent
69
68
  while (element.tagName!=='ROOT'){
70
69
  ancestors.push(element)
71
70
  element=element.parent
72
71
  }
73
72
  return ancestors.reverse()
74
73
  }
75
74
  get childNodeIndex(){
76
75
  if (!this.parent) return null
77
76
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
78
77
  }
79
78
  get childIndex(){
80
79
  if (!this.parent) return null
81
80
  return this.parent.children ? this.parent.children.indexOf(this) : null
82
81
  }
83
82
  get previousElementSibling(){ return this.prev }
84
83
  get prev(){
85
84
  if (!this.childIndex) return null
86
85
  return this.parent.children[this.childIndex-1]
87
86
  }
88
87
  get nextElementSibling(){ return this.next }
89
88
  get next(){
90
89
  if (!this.childIndex) return null
91
90
  return this.parent.children[this.childIndex+1] || null
92
91
  }
93
92
  get dataset(){
94
93
  if (!this._dataset) this._dataset=getDataset(this);
95
94
  return this._dataset;
96
95
  }
97
96
  get classList(){
98
97
  if (!this._classList) this._classList=new NodeClassList(this);
99
98
  return this._classList;
100
99
  }
101
100
  get style(){
102
101
  if (!this.__style) this.__style=buildStyle(this.attributes)
103
102
  return this.__style
104
103
  }
105
104
  get outerHTML(){
106
105
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
107
106
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
108
107
  }
109
108
  getAttribute(attrName){ return this.attributes[attrName] || null }
110
109
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
111
110
  removeAttribute(attrName){ delete this.attributes[attrName] }
112
111
  remove(){
113
112
  if (!this.parent) return
114
113
  const index=this.childNodeIndex;
115
114
  if (index!==null) this.parent.childNodes.splice(index,1);
116
115
  }
117
116
  get innerHTML(){
118
117
  return this.childNodes.map(child=>{
119
118
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
120
119
  else if (child instanceof TextNode) return child.textContent;
121
120
  else return child
122
121
  }).join("");
123
122
  }
124
123
  $$(query){ return this.querySelectorAll(query) }
125
124
  querySelectorAll(query){
126
125
  const selectors=Query.get(query)
127
126
  return find(selectors,this,new Set())
128
127
  }
129
128
  $(query){ return this.querySelector(query) }
130
129
  querySelector(query){
131
130
  const selectors=Query.get(query)
132
131
  return find(selectors,this,new Set(),true)[0] || null
133
132
  }
134
133
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
135
134
  getElementsByTagName(query){ return this.querySelectorAll(query) }
136
135
  getElementById(query){ return this.querySelector('#'+query) }
137
136
  get children(){
138
137
  return this.childNodes.filter(child=>{
139
138
  if (!(child instanceof Node)) return false
140
139
  if (child.tagName==='#comment') return false
141
140
  return true
142
141
  });
143
142
  }
144
143
  insertAdjacentElement(position,newElement){
145
144
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
146
145
  const pos=position.toLowerCase();
147
146
  if (pos==='afterbegin' || pos==='beforeend'){
148
147
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
149
148
  else if (pos==="beforeend") this.childNodes.push(newElement);
150
149
  newElement.parent=this
151
150
  return newElement
152
151
  }
153
152
  if (!this.parent) throw new Error("Can't insert element to element without parent")
154
153
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
155
154
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
156
155
  newElement.parent=this.parent
157
156
  return newElement
158
157
  }
159
158
  insertAdjacentHTML(position,html){
160
159
  const newNode=parseHTML(html);
161
160
  newNode.childNodes.forEach(node=>{
162
161
  this.insertAdjacentElement(position,node);
163
162
  });
164
163
  return newNode
165
164
  }
166
165
  insertAdjacentText(position,text){
167
166
  return this.insertAdjacentElement(position,new TextNode(text));
168
167
  }
169
168
  insert(position,element){
170
169
  const positions=['beforebegin','afterbegin','beforeend','afterend']
171
170
  if (positions[position]) position=positions[position]
172
171
  if (typeof element==='string'){
173
172
  element=element.trim()
174
173
  if (element.startsWith('<') && element.endsWith('>')){
175
174
  return this.insertAdjacentHTML(position,element)
176
175
  }
177
176
  return this.insertAdjacentText(position,element)
178
177
  }
179
178
  return this.insertAdjacentElement(position,element)
180
179
  }
181
180
  set innerHTML(html){
182
181
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
183
182
  }
184
183
  set outerHTML(html){
185
184
  const parsed=parseHTML(html);
186
185
  if (!this.parent) return console.log('element has no parent node')
187
186
  const index=this.childIndex
188
187
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
189
188
  }
190
189
  appendChild(newChild){
191
190
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
192
191
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
193
192
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
194
193
  else return newChild
195
194
  this.childNodes.push(newChild);
196
195
  newChild.parent=this;
197
196
  return newChild;
198
197
  }
199
198
  get textContent(){
200
199
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
201
200
  return this.childNodes.map(child=>{
202
201
  if (child instanceof SingleNode) return ''
203
202
  if (child instanceof TextNode) return child.nodeValue
204
203
  if (child instanceof Node) return child.textContent;
205
204
  else return child;
206
205
  }).join(" ");
207
206
  }
208
207
  set textContent(value){
209
208
  this.childNodes=[];
210
209
  if (value!==null && value!==undefined){
211
210
  this.childNodes.push(value.toString());
212
211
  }
213
212
  }
213
+ }
214
214
  class Node{
215
215
  constructor(tagName,attributes={},parent=null){
216
216
  this.isSingle=false;
217
217
  this.tagName=tagName;
218
218
  this.attributes=attributes;
219
219
  this.childNodes=[];
220
220
  if (parent!==null) parent.childNodes.push(this)
221
221
  this.parent=parent;
222
222
  this._classList=null;
223
223
  this.__style=null;
224
224
  this._dataset=null
225
225
  }
226
226
  get id(){ return this.attributes.id ? this.attributes.id : null; }
227
227
  set id(newValue){ this.attributes.id=newValue; }
228
228
  get className(){ return this.attributes.class || null }
229
229
  get parentNode(){ return this.parent }
230
230
  get ancestors(){
231
231
  if (!this.parent) return []
232
232
  const ancestors=[]
233
233
  let element=this.parent
234
234
  while (element.tagName!=='ROOT'){
235
235
  ancestors.push(element)
236
236
  element=element.parent
237
237
  }
238
238
  return ancestors.reverse()
239
239
  }
240
240
  get childNodeIndex(){
241
241
  if (!this.parent) return null
242
242
  return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
243
243
  }
244
244
  get childIndex(){
245
245
  if (!this.parent) return null
246
246
  return this.parent.children ? this.parent.children.indexOf(this) : null
247
247
  }
248
248
  get previousElementSibling(){ return this.prev }
249
249
  get prev(){
250
250
  if (!this.childIndex) return null
251
251
  return this.parent.children[this.childIndex-1]
252
252
  }
253
253
  get nextElementSibling(){ return this.next }
254
254
  get next(){
255
255
  if (!this.childIndex) return null
256
256
  return this.parent.children[this.childIndex+1] || null
257
257
  }
258
258
  get dataset(){
259
259
  if (!this._dataset) this._dataset=getDataset(this);
260
260
  return this._dataset;
261
261
  }
262
262
  get classList(){
263
263
  if (!this._classList) this._classList=new NodeClassList(this);
264
264
  return this._classList;
265
265
  }
266
266
  get style(){
267
267
  if (!this.__style) this.__style=buildStyle(this.attributes)
268
268
  return this.__style
269
269
  }
270
270
  get outerHTML(){
271
271
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
272
272
  return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
273
273
  }
274
274
  getAttribute(attrName){ return this.attributes[attrName]!==undefined ? this.attributes[attrName] : null }
275
275
  setAttribute(attrName,value=''){ this.attributes[attrName]=value }
276
276
  removeAttribute(attrName){ delete this.attributes[attrName] }
277
277
  remove(){
278
278
  if (!this.parent) return
279
279
  const index=this.childNodeIndex;
280
280
  if (index!==null) this.parent.childNodes.splice(index,1);
281
281
  }
282
282
  get innerHTML(){
283
283
  return this.childNodes.map(child=>{
284
284
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
285
285
  else if (child instanceof TextNode) return child.textContent;
286
286
  else return child
287
287
  }).join("");
288
288
  }
289
289
  $$(query){ return this.querySelectorAll(query) }
290
290
  querySelectorAll(query){
291
291
  const selectors=Query.get(query)
292
292
  return find(selectors,this,new Set())
293
293
  }
294
294
  $(query){ return this.querySelector(query) }
295
295
  querySelector(query){
296
296
  const selectors=Query.get(query)
297
297
  return find(selectors,this,new Set(),true)[0] || null
298
298
  }
299
299
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
300
300
  getElementsByTagName(query){ return this.querySelectorAll(query) }
301
301
  getElementById(query){ return this.querySelector('#'+query) }
302
302
  get children(){
303
303
  return this.childNodes.filter(child=>{
304
304
  if (!(child instanceof Node)) return false
305
305
  if (child.tagName==='#comment') return false
306
306
  return true
307
307
  });
308
308
  }
309
309
  insertAdjacentElement(position,newElement){
310
310
  if (newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
311
311
  const pos=position.toLowerCase();
312
312
  if (pos==='afterbegin' || pos==='beforeend'){
313
313
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
314
314
  else if (pos==="beforeend") this.childNodes.push(newElement);
315
315
  newElement.parent=this
316
316
  return newElement
317
317
  }
318
318
  if (!this.parent) throw new Error("Can't insert element to element without parent")
319
319
  if (pos==="beforebegin") insertBefore(this.parent.childNodes,this.childNodeIndex,newElement)
320
320
  else if (pos==="afterend") this.parent.childNodes.splice(this.childNodeIndex+1,0,newElement);
321
321
  newElement.parent=this.parent
322
322
  return newElement
323
323
  }
324
324
  insertAdjacentHTML(position,html){
325
325
  const newNode=parseHTML(html);
326
326
  newNode.childNodes.forEach(node=>{
327
327
  this.insertAdjacentElement(position,node);
328
328
  });
329
329
  return newNode
330
330
  }
331
331
  insertAdjacentText(position,text){
332
332
  return this.insertAdjacentElement(position,new TextNode(text));
333
333
  }
334
334
  insert(position,element){
335
335
  const positions=['beforebegin','afterbegin','beforeend','afterend']
336
336
  if (positions[position]) position=positions[position]
337
337
  if (typeof element==='string'){
338
338
  element=element.trim()
339
339
  if (element.startsWith('<') && element.endsWith('>')){
340
340
  return this.insertAdjacentHTML(position,element)
341
341
  }
342
342
  return this.insertAdjacentText(position,element)
343
343
  }
344
344
  return this.insertAdjacentElement(position,element)
345
345
  }
346
346
  set innerHTML(html){
347
347
  this.childNodes=html.trim().startsWith('<') ? parseHTML(html).childNodes : [html]
348
348
  }
349
349
  set outerHTML(html){
350
350
  const parsed=parseHTML(html);
351
351
  if (!this.parent) return console.log('element has no parent node')
352
352
  const index=this.childIndex
353
353
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
354
354
  }
355
355
  appendChild(newChild){
356
356
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
357
357
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
358
358
  } else if (typeof newChild==='string') newChild=new TextNode(newChild)
359
359
  else return newChild
360
360
  this.childNodes.push(newChild);
361
361
  newChild.parent=this;
362
362
  return newChild;
363
363
  }
364
364
  get textContent(){
365
365
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
366
366
  return this.childNodes.map(child=>{
367
367
  if (child instanceof SingleNode) return ''
368
368
  if (child instanceof TextNode) return child.nodeValue
369
369
  if (child instanceof Node) return child.textContent;
370
370
  else return child;
371
371
  }).join(" ");
372
372
  }
373
373
  set textContent(value){
374
374
  this.childNodes=[];
375
375
  if (value!==null && value!==undefined){
376
376
  this.childNodes.push(value.toString());
377
377
  }
378
378
  }
379
379
  }
380
380
  class SingleNode extends Node{
381
381
  constructor(tagName,attributes={},parent=null){
382
382
  if(attributes['?'] && tagName==='?xml') delete attributes['?']
383
383
  super(tagName,attributes,parent);
384
384
  this.isSingle=true
385
385
  }
386
386
  get outerHTML(){
387
387
  if (this.tagName==="#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
388
388
  const attrs=Object.entries(this.attributes).map(([key,val])=>val.length ? `${key}="${val}"` : key).join(" ");
389
389
  return `<${this.tagName} ${attrs}${this.tagName==='?xml' ? '?' : ''}>`;
390
390
  }
391
391
  get innerHTML(){ return ""; }
392
392
  set innerHTML(_){ }
393
393
  $(_){return null}
394
394
  $$(_){return []}
395
395
  querySelectorAll(_){ return []; }
396
396
  querySelector(_){ return null; }
397
397
  getElementsByClassName(_){ return []; }
398
398
  getElementsByTagName(_){ return []; }
399
399
  getElementById(_){ return null; }
400
400
  get children(){ return []; }
401
401
  insertAdjacentElement(_,__){ }
402
402
  insertAdjacentHTML(_,__){ }
403
403
  insertAdjacentText(_,__){ }
404
404
  appendChild(_){ }
405
405
  insert(_,__){ }
406
406
  get textContent(){ return ""; }
407
407
  set textContent(_){ }
408
408
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "als-document",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "A powerful HTML parser & DOM manipulation library for both backend and frontend.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
package/src/node/node.js CHANGED
@@ -73,7 +73,7 @@ class Node {
73
73
  return `<${this.tagName}${attrs ? ' ' + attrs : ''}>${this.innerHTML}</${this.tagName}>`;
74
74
  }
75
75
 
76
- getAttribute(attrName) { return this.attributes[attrName] || null }
76
+ getAttribute(attrName) { return this.attributes[attrName] !== undefined ? this.attributes[attrName] : null }
77
77
  setAttribute(attrName, value='') { this.attributes[attrName] = value }
78
78
  removeAttribute(attrName) { delete this.attributes[attrName] }
79
79
 
@@ -1,3 +0,0 @@
1
- {
2
- "liveServer.settings.port": 5502
3
- }