pseudo-dom 0.4.0 → 0.5.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.
@@ -1,5 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ require('core-js/modules/esnext.iterator.constructor.js')
4
+ require('core-js/modules/esnext.iterator.every.js')
5
+ require('core-js/modules/esnext.iterator.for-each.js')
3
6
  const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
4
7
  return mod && mod.__esModule
5
8
  ? mod
@@ -10,7 +13,7 @@ const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
10
13
  Object.defineProperty(exports, '__esModule', {
11
14
  value: true
12
15
  })
13
- exports.NodeService = void 0
16
+ exports.CommentService = exports.TextService = exports.NodeService = void 0
14
17
  /**
15
18
  * @file Substitute for the DOM Node Class.
16
19
  * @author Joshua Heagle <joshuaheagle@gmail.com>
@@ -35,8 +38,9 @@ class NodeService extends EventTargetService_1.default {
35
38
  */
36
39
  constructor () {
37
40
  super()
38
- this.nodeValueStore = ''
39
- this.textContentStore = ''
41
+ this.nodeValueStore = null
42
+ this.ownerDocumentStore = null
43
+ this.nodeId = NodeService.nextNodeId++
40
44
  this.nodeNameValue = ''
41
45
  this.children = (0, generateNodeList_1.default)()
42
46
  this.parent = null
@@ -56,7 +60,8 @@ class NodeService extends EventTargetService_1.default {
56
60
  }
57
61
 
58
62
  get isConnected () {
59
- return !!this.parent
63
+ // Connected means the tree the node is in has a document at the top
64
+ return this.getRootNode().nodeType === NodeService.DOCUMENT_NODE
60
65
  }
61
66
 
62
67
  get lastChild () {
@@ -84,7 +89,11 @@ class NodeService extends EventTargetService_1.default {
84
89
  }
85
90
 
86
91
  get ownerDocument () {
87
- return null
92
+ if (this.nodeType === NodeService.DOCUMENT_NODE) {
93
+ return null
94
+ }
95
+ const root = this.getRootNode()
96
+ return root.nodeType === NodeService.DOCUMENT_NODE ? root : this.ownerDocumentStore
88
97
  }
89
98
 
90
99
  get parentNode () {
@@ -100,11 +109,34 @@ class NodeService extends EventTargetService_1.default {
100
109
  }
101
110
 
102
111
  get textContent () {
103
- return this.textContentStore
112
+ if (this.nodeType === NodeService.DOCUMENT_NODE || this.nodeType === NodeService.DOCUMENT_TYPE_NODE) {
113
+ return null
114
+ }
115
+ // The text of everything below, in order (comments and the like do not count)
116
+ let text = ''
117
+ Array.from(this.childNodes).forEach(child => {
118
+ if (child.nodeType === NodeService.TEXT_NODE) {
119
+ text += child.nodeValue
120
+ } else if (child.nodeType !== NodeService.COMMENT_NODE) {
121
+ text += child.textContent
122
+ }
123
+ })
124
+ return text
104
125
  }
105
126
 
106
127
  set textContent (text) {
107
- this.textContentStore = text
128
+ if (this.nodeType === NodeService.DOCUMENT_NODE || this.nodeType === NodeService.DOCUMENT_TYPE_NODE) {
129
+ return
130
+ }
131
+ // All the children are replaced by a single text node (or none for an empty text)
132
+ while (this.firstChild) {
133
+ this.removeChild(this.firstChild)
134
+ }
135
+ if (text !== null && typeof text !== 'undefined' && String(text) !== '') {
136
+ const textNode = new TextService(String(text))
137
+ textNode.ownerDocumentStore = this.ownerDocument
138
+ this.appendChild(textNode)
139
+ }
108
140
  }
109
141
 
110
142
  /**
@@ -116,6 +148,36 @@ class NodeService extends EventTargetService_1.default {
116
148
  return this.insertBefore(childNode, null)
117
149
  }
118
150
 
151
+ /**
152
+ * Whether this kind of node can have children (text, comments and attributes cannot).
153
+ * @returns {boolean}
154
+ */
155
+ get acceptsChildren () {
156
+ return true
157
+ }
158
+
159
+ /**
160
+ * Make a copy of this node without its children, its parent or its listeners, which is what cloneNode starts from.
161
+ * Kinds of node which are made with arguments override this to give them.
162
+ * @returns {NodeService}
163
+ */
164
+ cloneShallow () {
165
+ const copy = new this.constructor()
166
+ copy.nodeValue = this.nodeValue
167
+ copy.ownerDocumentStore = this.ownerDocumentStore
168
+ return copy
169
+ }
170
+
171
+ /**
172
+ * Whether another node of the same type is equal to this one apart from its children, which isEqualNode compares
173
+ * afterwards. Kinds of node with more to compare (an element has attributes) override this.
174
+ * @param {NodeService} other The node to compare with
175
+ * @returns {boolean}
176
+ */
177
+ equalsShallow (other) {
178
+ return this.nodeName === other.nodeName && this.nodeValue === other.nodeValue
179
+ }
180
+
119
181
  /**
120
182
  * Called each time a node has been inserted as a child of this node, so that nodes which need to react to children
121
183
  * (for example elements applying default events) can do so.
@@ -123,19 +185,62 @@ class NodeService extends EventTargetService_1.default {
123
185
  */
124
186
  childInserted (child) {}
125
187
  /**
126
- * Not implemented yet.
127
- * @throws {Error}
188
+ * Make a copy of this node (without its parent, and without its event listeners). With deep the children are copied
189
+ * too, all the way down.
190
+ * @param {boolean} [deep=false] Copy the children as well
191
+ * @returns {PseudoNode}
128
192
  */
129
193
  cloneNode (deep = false) {
130
- throw new Error(`NodeService.cloneNode(${deep}) is not implemented yet.`)
194
+ const copy = this.cloneShallow()
195
+ if (deep) {
196
+ Array.from(this.childNodes).forEach(child => copy.appendChild(child.cloneNode(true)))
197
+ }
198
+ return copy
131
199
  }
132
200
 
133
201
  /**
134
- * Not implemented yet.
135
- * @throws {Error}
202
+ * Say where another node is in relation to this one, as the bits of NodeService.DOCUMENT_POSITION_*: 0 for this node
203
+ * itself, DISCONNECTED (with IMPLEMENTATION_SPECIFIC and a consistent PRECEDING or FOLLOWING) for a node in another tree,
204
+ * CONTAINS + PRECEDING when the other node is an ancestor, CONTAINED_BY + FOLLOWING when it is a descendant,
205
+ * otherwise PRECEDING or FOLLOWING by their order in the tree.
206
+ * @param {PseudoNode} otherNode The node to locate
207
+ * @returns {number}
136
208
  */
137
209
  compareDocumentPosition (otherNode) {
138
- throw new Error('NodeService.compareDocumentPosition() is not implemented yet.')
210
+ if (otherNode === this) {
211
+ return 0
212
+ }
213
+ const pathFromRoot = node => {
214
+ const path = []
215
+ for (let current = node; current; current = current.parentNode) {
216
+ path.unshift(current)
217
+ }
218
+ return path
219
+ }
220
+ const mine = pathFromRoot(this)
221
+ const theirs = pathFromRoot(otherNode)
222
+ if (mine[0] !== theirs[0]) {
223
+ // Not in the same tree, so there is no real order: use a consistent one (the order the nodes were made in)
224
+ const before = otherNode.nodeId < this.nodeId ? NodeService.DOCUMENT_POSITION_PRECEDING : NodeService.DOCUMENT_POSITION_FOLLOWING
225
+ return NodeService.DOCUMENT_POSITION_DISCONNECTED | NodeService.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | before
226
+ }
227
+ if (theirs.length < mine.length && theirs.every((node, index) => mine[index] === node)) {
228
+ return NodeService.DOCUMENT_POSITION_CONTAINS | NodeService.DOCUMENT_POSITION_PRECEDING
229
+ }
230
+ if (mine.length < theirs.length && mine.every((node, index) => theirs[index] === node)) {
231
+ return NodeService.DOCUMENT_POSITION_CONTAINED_BY | NodeService.DOCUMENT_POSITION_FOLLOWING
232
+ }
233
+ // The paths part ways at siblings: whichever comes first among them is first in the tree
234
+ let depth = 0
235
+ while (mine[depth] === theirs[depth]) {
236
+ ++depth
237
+ }
238
+ for (let sibling = mine[depth].nextSibling; sibling; sibling = sibling.nextSibling) {
239
+ if (sibling === theirs[depth]) {
240
+ return NodeService.DOCUMENT_POSITION_FOLLOWING
241
+ }
242
+ }
243
+ return NodeService.DOCUMENT_POSITION_PRECEDING
139
244
  }
140
245
 
141
246
  /**
@@ -173,6 +278,9 @@ class NodeService extends EventTargetService_1.default {
173
278
  * @throws {Error} When the reference node is not a child of this node, or the new node is this node or contains it
174
279
  */
175
280
  insertBefore (newNode, referenceNode = null) {
281
+ if (!this.acceptsChildren) {
282
+ throw new Error('This kind of node cannot have children.')
283
+ }
176
284
  if (referenceNode !== null && referenceNode.parentNode !== this) {
177
285
  throw new Error('The node before which the new node is to be inserted is not a child of this node.')
178
286
  }
@@ -210,11 +318,18 @@ class NodeService extends EventTargetService_1.default {
210
318
  }
211
319
 
212
320
  /**
213
- * Not implemented yet.
214
- * @throws {Error}
321
+ * Whether another node is the same as this one, by what they hold: the same type, name and value (an element also
322
+ * needs the same attributes), and children which are equal in the same order.
323
+ * @param {PseudoNode|null} otherNode The node to compare with
324
+ * @returns {boolean}
215
325
  */
216
326
  isEqualNode (otherNode) {
217
- throw new Error('NodeService.isEqualNode() is not implemented yet.')
327
+ if (!otherNode || otherNode.nodeType !== this.nodeType || !this.equalsShallow(otherNode)) {
328
+ return false
329
+ }
330
+ const mine = Array.from(this.childNodes)
331
+ const theirs = Array.from(otherNode.childNodes)
332
+ return mine.length === theirs.length && mine.every((child, index) => child.isEqualNode(theirs[index]))
218
333
  }
219
334
 
220
335
  isSameNode (otherNode) {
@@ -229,7 +344,34 @@ class NodeService extends EventTargetService_1.default {
229
344
  return null
230
345
  }
231
346
 
232
- normalize () {}
347
+ /**
348
+ * Tidy the text below this node: neighbouring text nodes are joined into one and empty text nodes are removed.
349
+ */
350
+ normalize () {
351
+ let child = this.firstChild
352
+ while (child) {
353
+ if (child.nodeType === NodeService.TEXT_NODE) {
354
+ // Join the text nodes which follow into this one, and drop it when it is empty
355
+ let text = child.nodeValue
356
+ let following = child.nextSibling
357
+ while (following && following.nodeType === NodeService.TEXT_NODE) {
358
+ text += following.nodeValue
359
+ const after = following.nextSibling
360
+ this.removeChild(following)
361
+ following = after
362
+ }
363
+ child.nodeValue = text
364
+ if (text === '') {
365
+ this.removeChild(child)
366
+ }
367
+ child = following
368
+ } else {
369
+ child.normalize()
370
+ child = child.nextSibling
371
+ }
372
+ }
373
+ }
374
+
233
375
  /**
234
376
  * Remove a child from this node, it no longer has a parent or siblings afterwards.
235
377
  * @param {PseudoNode} childElement The child node to remove
@@ -285,3 +427,157 @@ NodeService.DOCUMENT_NODE = 9
285
427
  NodeService.DOCUMENT_TYPE_NODE = 10
286
428
  NodeService.DOCUMENT_FRAGMENT_NODE = 11
287
429
  NodeService.NOTATION_NODE = 12
430
+ NodeService.DOCUMENT_POSITION_DISCONNECTED = 1
431
+ NodeService.DOCUMENT_POSITION_PRECEDING = 2
432
+ NodeService.DOCUMENT_POSITION_FOLLOWING = 4
433
+ NodeService.DOCUMENT_POSITION_CONTAINS = 8
434
+ NodeService.DOCUMENT_POSITION_CONTAINED_BY = 16
435
+ NodeService.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32
436
+ NodeService.nextNodeId = 1
437
+ /**
438
+ * Simulate the behaviour of the Text Class when there is no DOM available: the text in an element.
439
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
440
+ * @class
441
+ * @augments NodeService
442
+ * @property {string} data - The text
443
+ * @property {number} length - How many characters there are
444
+ * @property {string} wholeText - The text of this node and of the text nodes next to it
445
+ */
446
+ class TextService extends NodeService {
447
+ /**
448
+ * @param {string} [data=''] The text
449
+ * @constructor
450
+ */
451
+ constructor (data = '') {
452
+ super()
453
+ this.nodeValue = String(data)
454
+ }
455
+
456
+ get acceptsChildren () {
457
+ return false
458
+ }
459
+
460
+ get nodeName () {
461
+ return '#text'
462
+ }
463
+
464
+ get nodeType () {
465
+ return NodeService.TEXT_NODE
466
+ }
467
+
468
+ get data () {
469
+ return this.nodeValue
470
+ }
471
+
472
+ set data (data) {
473
+ this.nodeValue = String(data)
474
+ }
475
+
476
+ get length () {
477
+ return this.data.length
478
+ }
479
+
480
+ get textContent () {
481
+ return this.data
482
+ }
483
+
484
+ set textContent (text) {
485
+ this.data = text === null ? '' : String(text)
486
+ }
487
+
488
+ get wholeText () {
489
+ let first = this
490
+ while (first.previousSibling && first.previousSibling.nodeType === NodeService.TEXT_NODE) {
491
+ first = first.previousSibling
492
+ }
493
+ let text = ''
494
+ for (let current = first; current && current.nodeType === NodeService.TEXT_NODE; current = current.nextSibling) {
495
+ text += current.nodeValue
496
+ }
497
+ return text
498
+ }
499
+
500
+ /**
501
+ * Break this text node in two at a position: this node keeps the text before it and a new node with the rest is put
502
+ * after this one.
503
+ * @param {number} offset How many characters stay in this node
504
+ * @returns {TextService} The new node
505
+ * @throws {Error} When the offset is beyond the end of the text
506
+ */
507
+ splitText (offset) {
508
+ if (offset < 0 || offset > this.length) {
509
+ throw new Error('The offset is beyond the end of the text.')
510
+ }
511
+ const rest = new TextService(this.data.slice(offset))
512
+ rest.ownerDocumentStore = this.ownerDocumentStore
513
+ this.data = this.data.slice(0, offset)
514
+ if (this.parentNode) {
515
+ this.parentNode.insertBefore(rest, this.nextSibling)
516
+ }
517
+ return rest
518
+ }
519
+
520
+ cloneShallow () {
521
+ const copy = new TextService(this.data)
522
+ copy.ownerDocumentStore = this.ownerDocumentStore
523
+ return copy
524
+ }
525
+ }
526
+ exports.TextService = TextService
527
+ /**
528
+ * Simulate the behaviour of the Comment Class when there is no DOM available: a note in the markup which is not shown.
529
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
530
+ * @class
531
+ * @augments NodeService
532
+ * @property {string} data - The comment
533
+ * @property {number} length - How many characters there are
534
+ */
535
+ class CommentService extends NodeService {
536
+ /**
537
+ * @param {string} [data=''] The comment
538
+ * @constructor
539
+ */
540
+ constructor (data = '') {
541
+ super()
542
+ this.nodeValue = String(data)
543
+ }
544
+
545
+ get acceptsChildren () {
546
+ return false
547
+ }
548
+
549
+ get nodeName () {
550
+ return '#comment'
551
+ }
552
+
553
+ get nodeType () {
554
+ return NodeService.COMMENT_NODE
555
+ }
556
+
557
+ get data () {
558
+ return this.nodeValue
559
+ }
560
+
561
+ set data (data) {
562
+ this.nodeValue = String(data)
563
+ }
564
+
565
+ get length () {
566
+ return this.data.length
567
+ }
568
+
569
+ get textContent () {
570
+ return this.data
571
+ }
572
+
573
+ set textContent (text) {
574
+ this.data = text === null ? '' : String(text)
575
+ }
576
+
577
+ cloneShallow () {
578
+ const copy = new CommentService(this.data)
579
+ copy.ownerDocumentStore = this.ownerDocumentStore
580
+ return copy
581
+ }
582
+ }
583
+ exports.CommentService = CommentService
@@ -1 +1 @@
1
- "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NodeService=void 0;const generateNodeList_1=__importDefault(require("../factories/generateNodeList")),TreeLinker_1=require("collect-your-stuff/dist/collections/linked-tree-list/TreeLinker"),EventTargetService_1=__importDefault(require("./EventTargetService"));class NodeService extends EventTargetService_1.default{constructor(){super(),this.nodeValueStore="",this.textContentStore="",this.nodeNameValue="",this.children=(0,generateNodeList_1.default)(),this.parent=null,this.listLinker=null}get baseURI(){return window.location||"/"}get childNodes(){return this.children}get firstChild(){return this.children.first?this.children.first.data:null}get isConnected(){return!!this.parent}get lastChild(){return this.children.last?this.children.last.data:null}get nextSibling(){return this.listLinker&&this.listLinker.next?this.listLinker.next.data:null}get nodeName(){return this.nodeNameValue||""}get nodeType(){return NodeService.DEFAULT_NODE}get nodeValue(){return this.nodeValueStore}set nodeValue(e){this.nodeValueStore=e}get ownerDocument(){return null}get parentNode(){return this.parent}get parentElement(){return this.parent&&this.parent.nodeType===NodeService.ELEMENT_NODE?this.parent:null}get previousSibling(){return this.listLinker&&this.listLinker.prev?this.listLinker.prev.data:null}get textContent(){return this.textContentStore}set textContent(e){this.textContentStore=e}appendChild(e){return this.insertBefore(e,null)}childInserted(e){}cloneNode(e=!1){throw new Error(`NodeService.cloneNode(${e}) is not implemented yet.`)}compareDocumentPosition(e){throw new Error("NodeService.compareDocumentPosition() is not implemented yet.")}contains(e){let t=e;for(;t;){if(t===this)return!0;t=t.parentNode}return!1}getRootNode(e={composed:!1}){return this.parent?this.parent.getRootNode(e):this}hasChildNodes(){return this.children.length>0}insertBefore(e,t=null){if(null!==t&&t.parentNode!==this)throw new Error("The node before which the new node is to be inserted is not a child of this node.");if(e===t)return e;if("function"==typeof e.contains&&e.contains(this))throw new Error("The new node cannot be inserted into itself or one of its own descendants.");if(e.nodeType===NodeService.DOCUMENT_FRAGMENT_NODE){for(;e.firstChild;)this.insertBefore(e.firstChild,t);return e}e.parentNode&&e.parentNode.removeChild(e);const r=new TreeLinker_1.TreeLinker({data:e});this.children.insertBefore(t?t.listLinker:null,r);const i=e;return i.parent=this,i.listLinker=r,this.childInserted(i),e}isDefaultNamespace(e){return null===e}isEqualNode(e){throw new Error("NodeService.isEqualNode() is not implemented yet.")}isSameNode(e){return this===e}lookupPrefix(e){return null}lookupNamespaceURI(e){return null}normalize(){}removeChild(e){if(!e||e.parentNode!==this)throw new Error("The node to be removed is not a child of this node.");const t=e;return this.children.remove(t.listLinker),t.parent=null,t.listLinker=null,e}replaceChild(e,t){if(!t||t.parentNode!==this)throw new Error("The node to be replaced is not a child of this node.");if(e===t)return t;let r=t.nextSibling;return r===e&&(r=e.nextSibling),this.removeChild(t),this.insertBefore(e,r),t}}exports.NodeService=NodeService,NodeService.DEFAULT_NODE=0,NodeService.ELEMENT_NODE=1,NodeService.ATTRIBUTE_NODE=2,NodeService.TEXT_NODE=3,NodeService.CDATA_SECTION_NODE=4,NodeService.ENTITY_REFERENCE_NODE=5,NodeService.ENTITY_NODE=6,NodeService.PROCESSING_INSTRUCTION_NODE=7,NodeService.COMMENT_NODE=8,NodeService.DOCUMENT_NODE=9,NodeService.DOCUMENT_TYPE_NODE=10,NodeService.DOCUMENT_FRAGMENT_NODE=11,NodeService.NOTATION_NODE=12;
1
+ "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.every.js"),require("core-js/modules/esnext.iterator.for-each.js");var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.CommentService=exports.TextService=exports.NodeService=void 0;const generateNodeList_1=__importDefault(require("../factories/generateNodeList")),TreeLinker_1=require("collect-your-stuff/dist/collections/linked-tree-list/TreeLinker"),EventTargetService_1=__importDefault(require("./EventTargetService"));class NodeService extends EventTargetService_1.default{constructor(){super(),this.nodeValueStore=null,this.ownerDocumentStore=null,this.nodeId=NodeService.nextNodeId++,this.nodeNameValue="",this.children=(0,generateNodeList_1.default)(),this.parent=null,this.listLinker=null}get baseURI(){return window.location||"/"}get childNodes(){return this.children}get firstChild(){return this.children.first?this.children.first.data:null}get isConnected(){return this.getRootNode().nodeType===NodeService.DOCUMENT_NODE}get lastChild(){return this.children.last?this.children.last.data:null}get nextSibling(){return this.listLinker&&this.listLinker.next?this.listLinker.next.data:null}get nodeName(){return this.nodeNameValue||""}get nodeType(){return NodeService.DEFAULT_NODE}get nodeValue(){return this.nodeValueStore}set nodeValue(e){this.nodeValueStore=e}get ownerDocument(){if(this.nodeType===NodeService.DOCUMENT_NODE)return null;const e=this.getRootNode();return e.nodeType===NodeService.DOCUMENT_NODE?e:this.ownerDocumentStore}get parentNode(){return this.parent}get parentElement(){return this.parent&&this.parent.nodeType===NodeService.ELEMENT_NODE?this.parent:null}get previousSibling(){return this.listLinker&&this.listLinker.prev?this.listLinker.prev.data:null}get textContent(){if(this.nodeType===NodeService.DOCUMENT_NODE||this.nodeType===NodeService.DOCUMENT_TYPE_NODE)return null;let e="";return Array.from(this.childNodes).forEach(t=>{t.nodeType===NodeService.TEXT_NODE?e+=t.nodeValue:t.nodeType!==NodeService.COMMENT_NODE&&(e+=t.textContent)}),e}set textContent(e){if(this.nodeType!==NodeService.DOCUMENT_NODE&&this.nodeType!==NodeService.DOCUMENT_TYPE_NODE){for(;this.firstChild;)this.removeChild(this.firstChild);if(null!=e&&""!==String(e)){const t=new TextService(String(e));t.ownerDocumentStore=this.ownerDocument,this.appendChild(t)}}}appendChild(e){return this.insertBefore(e,null)}get acceptsChildren(){return!0}cloneShallow(){const e=new this.constructor;return e.nodeValue=this.nodeValue,e.ownerDocumentStore=this.ownerDocumentStore,e}equalsShallow(e){return this.nodeName===e.nodeName&&this.nodeValue===e.nodeValue}childInserted(e){}cloneNode(e=!1){const t=this.cloneShallow();return e&&Array.from(this.childNodes).forEach(e=>t.appendChild(e.cloneNode(!0))),t}compareDocumentPosition(e){if(e===this)return 0;const t=e=>{const t=[];for(let r=e;r;r=r.parentNode)t.unshift(r);return t},r=t(this),n=t(e);if(r[0]!==n[0]){const t=e.nodeId<this.nodeId?NodeService.DOCUMENT_POSITION_PRECEDING:NodeService.DOCUMENT_POSITION_FOLLOWING;return NodeService.DOCUMENT_POSITION_DISCONNECTED|NodeService.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC|t}if(n.length<r.length&&n.every((e,t)=>r[t]===e))return NodeService.DOCUMENT_POSITION_CONTAINS|NodeService.DOCUMENT_POSITION_PRECEDING;if(r.length<n.length&&r.every((e,t)=>n[t]===e))return NodeService.DOCUMENT_POSITION_CONTAINED_BY|NodeService.DOCUMENT_POSITION_FOLLOWING;let i=0;for(;r[i]===n[i];)++i;for(let e=r[i].nextSibling;e;e=e.nextSibling)if(e===n[i])return NodeService.DOCUMENT_POSITION_FOLLOWING;return NodeService.DOCUMENT_POSITION_PRECEDING}contains(e){let t=e;for(;t;){if(t===this)return!0;t=t.parentNode}return!1}getRootNode(e={composed:!1}){return this.parent?this.parent.getRootNode(e):this}hasChildNodes(){return this.children.length>0}insertBefore(e,t=null){if(!this.acceptsChildren)throw new Error("This kind of node cannot have children.");if(null!==t&&t.parentNode!==this)throw new Error("The node before which the new node is to be inserted is not a child of this node.");if(e===t)return e;if("function"==typeof e.contains&&e.contains(this))throw new Error("The new node cannot be inserted into itself or one of its own descendants.");if(e.nodeType===NodeService.DOCUMENT_FRAGMENT_NODE){for(;e.firstChild;)this.insertBefore(e.firstChild,t);return e}e.parentNode&&e.parentNode.removeChild(e);const r=new TreeLinker_1.TreeLinker({data:e});this.children.insertBefore(t?t.listLinker:null,r);const n=e;return n.parent=this,n.listLinker=r,this.childInserted(n),e}isDefaultNamespace(e){return null===e}isEqualNode(e){if(!e||e.nodeType!==this.nodeType||!this.equalsShallow(e))return!1;const t=Array.from(this.childNodes),r=Array.from(e.childNodes);return t.length===r.length&&t.every((e,t)=>e.isEqualNode(r[t]))}isSameNode(e){return this===e}lookupPrefix(e){return null}lookupNamespaceURI(e){return null}normalize(){let e=this.firstChild;for(;e;)if(e.nodeType===NodeService.TEXT_NODE){let t=e.nodeValue,r=e.nextSibling;for(;r&&r.nodeType===NodeService.TEXT_NODE;){t+=r.nodeValue;const e=r.nextSibling;this.removeChild(r),r=e}e.nodeValue=t,""===t&&this.removeChild(e),e=r}else e.normalize(),e=e.nextSibling}removeChild(e){if(!e||e.parentNode!==this)throw new Error("The node to be removed is not a child of this node.");const t=e;return this.children.remove(t.listLinker),t.parent=null,t.listLinker=null,e}replaceChild(e,t){if(!t||t.parentNode!==this)throw new Error("The node to be replaced is not a child of this node.");if(e===t)return t;let r=t.nextSibling;return r===e&&(r=e.nextSibling),this.removeChild(t),this.insertBefore(e,r),t}}exports.NodeService=NodeService,NodeService.DEFAULT_NODE=0,NodeService.ELEMENT_NODE=1,NodeService.ATTRIBUTE_NODE=2,NodeService.TEXT_NODE=3,NodeService.CDATA_SECTION_NODE=4,NodeService.ENTITY_REFERENCE_NODE=5,NodeService.ENTITY_NODE=6,NodeService.PROCESSING_INSTRUCTION_NODE=7,NodeService.COMMENT_NODE=8,NodeService.DOCUMENT_NODE=9,NodeService.DOCUMENT_TYPE_NODE=10,NodeService.DOCUMENT_FRAGMENT_NODE=11,NodeService.NOTATION_NODE=12,NodeService.DOCUMENT_POSITION_DISCONNECTED=1,NodeService.DOCUMENT_POSITION_PRECEDING=2,NodeService.DOCUMENT_POSITION_FOLLOWING=4,NodeService.DOCUMENT_POSITION_CONTAINS=8,NodeService.DOCUMENT_POSITION_CONTAINED_BY=16,NodeService.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC=32,NodeService.nextNodeId=1;class TextService extends NodeService{constructor(e=""){super(),this.nodeValue=String(e)}get acceptsChildren(){return!1}get nodeName(){return"#text"}get nodeType(){return NodeService.TEXT_NODE}get data(){return this.nodeValue}set data(e){this.nodeValue=String(e)}get length(){return this.data.length}get textContent(){return this.data}set textContent(e){this.data=null===e?"":String(e)}get wholeText(){let e=this;for(;e.previousSibling&&e.previousSibling.nodeType===NodeService.TEXT_NODE;)e=e.previousSibling;let t="";for(let r=e;r&&r.nodeType===NodeService.TEXT_NODE;r=r.nextSibling)t+=r.nodeValue;return t}splitText(e){if(e<0||e>this.length)throw new Error("The offset is beyond the end of the text.");const t=new TextService(this.data.slice(e));return t.ownerDocumentStore=this.ownerDocumentStore,this.data=this.data.slice(0,e),this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling),t}cloneShallow(){const e=new TextService(this.data);return e.ownerDocumentStore=this.ownerDocumentStore,e}}exports.TextService=TextService;class CommentService extends NodeService{constructor(e=""){super(),this.nodeValue=String(e)}get acceptsChildren(){return!1}get nodeName(){return"#comment"}get nodeType(){return NodeService.COMMENT_NODE}get data(){return this.nodeValue}set data(e){this.nodeValue=String(e)}get length(){return this.data.length}get textContent(){return this.data}set textContent(e){this.data=null===e?"":String(e)}cloneShallow(){const e=new CommentService(this.data);return e.ownerDocumentStore=this.ownerDocumentStore,e}}exports.CommentService=CommentService;
@@ -0,0 +1 @@
1
+ export { TextService } from './NodeService';
@@ -0,0 +1,13 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ })
6
+ exports.TextService = void 0
7
+ const NodeService_1 = require('./NodeService')
8
+ Object.defineProperty(exports, 'TextService', {
9
+ enumerable: true,
10
+ get: function () {
11
+ return NodeService_1.TextService
12
+ }
13
+ })
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TextService=void 0;var NodeService_1=require("./NodeService");Object.defineProperty(exports,"TextService",{enumerable:!0,get:function(){return NodeService_1.TextService}});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pseudo-dom",
3
3
  "description": "Mock the DOM on the server side for managing state and testing",
4
- "version": "0.4.0",
4
+ "version": "0.5.0",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
7
7
  "author": "Joshua Heagle",
@@ -19,7 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "collect-your-stuff": "^2.1.0",
22
- "core-js": "^3.50.0"
22
+ "core-js": "^3.50.0",
23
+ "si-funciona": "^2.6.0"
23
24
  },
24
25
  "devDependencies": {
25
26
  "js-build-tools": "^5.0.0",