als-document 1.1.0 → 1.1.1

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.
@@ -0,0 +1,3 @@
1
+ {
2
+ "liveServer.settings.port": 5502
3
+ }
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] || 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
  }
@@ -36,7 +36,7 @@ function parseHTML(html){
36
36
  const root=new Root();
37
37
  const stack=[root];
38
38
  le
39
39
  }
40
40
  function buildFromCache(cached){
41
41
  function buildNode(cache,parent=null){
42
42
  if(typeof cache==='string') return parent.childNodes.push(cache)
43
43
  const{isSingle,tagName,attributes,childNodes,textContent}=cache
44
44
  if(textContent) return parent.childNodes.push(new TextNode(textContent))
45
45
  if(isSingle) return parent.childNodes.push(new SingleNode(tagName,attributes))
46
46
  const newDoc=tagName==='ROOT' ? new Root() : new Node(tagName,attributes,parent)
47
47
  childNodes.forEach(childNode=>{
48
48
  buildNode(childNode,newDoc)
49
49
  });
50
50
  return newDoc
51
51
  }
52
52
  return buildNode(cached)
53
53
  }
54
54
 
55
- function cacheDoc(doc){
56
55
  const props=['isSingle','tagName','attributes']
57
56
  function addToCache(element,cache={}){
58
57
  if(typeof element==='string') return element
59
58
  if(element.nodeName==='#text') return{textContent:element.textContent}
60
59
  props.forEach(prop=>{
61
60
  if(element[prop]) cache[prop]=element[prop]
62
61
  });
63
62
  if(!element.childNodes) return cache
64
63
  cache.childNodes=[]
65
64
  element.childNodes.forEach(childNode=>{
66
65
  cache.childNodes.push(addToCache(childNode))
67
66
  });
68
67
  return cache
69
68
  }
70
69
  return addToCache(doc)
70
+ function cacheDoc(doc){
71
71
  const props=['isSingle','tagName','attributes']
72
72
  function addToCache(element,cache={}){
73
73
  if(typeof element==='string') return element
74
74
  if(element.nodeName==='#text') return{textContent:element.textContent}
75
75
  props.forEach(prop=>{
76
76
  if(element[prop]){
77
77
  cache[prop]=typeof element[prop]==='object' ?{...element[prop]} : element[prop]
78
78
  }
79
79
  });
80
80
  if(!element.childNodes) return cache
81
81
  cache.childNodes=[]
82
82
  element.childNodes.forEach(childNode=>{
83
83
  cache.childNodes.push(addToCache(childNode))
84
84
  });
85
85
  return cache
86
86
  }
87
87
  return addToCache(doc)
88
88
  }
89
89
  return { parseHTML, Node, Query, TextNode, SingleNode, buildFromCache, cacheDoc, Root }
90
90
  })()