pseudo-dom 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -144,10 +144,12 @@ if (typeof document === 'undefined') {
144
144
  }
145
145
  ```
146
146
 
147
- `installGlobal(target = globalThis)` fills in `document` / `Node` / `Element` / `HTMLElement` on `target`, using
147
+ `installGlobal(target = globalThis)` fills in `document` / `Node` / `Element` / `HTMLElement` / `HTMLDocument` /
148
+ `window` (a self-reference, like a real browser's) on `target`, using
148
149
  [browser-or-node](https://www.npmjs.com/package/browser-or-node) to check whether a real DOM (a real browser, or a
149
150
  jsdom-based test environment) is already there first - it's always safe to call, everywhere: it does nothing when
150
- one is.
151
+ one is. `Node` / `Element` / `HTMLElement` / `HTMLDocument` are the classes themselves (not instances), so
152
+ `x instanceof Element` works, matching the real DOM's.
151
153
 
152
154
  There's no real rendering to look at, so `logElement(node, [label])` prints a readable, indented view of a node's
153
155
  markup to the console (`prettyPrint(node, [indent])`, from the same module, returns the string instead of printing
@@ -317,10 +319,14 @@ order in which an event travels down through them). A node which has no parent h
317
319
  <dd><p>Remember the element which has the focus in a tree.</p>
318
320
  </dd>
319
321
  <dt><a href="#escapeText">escapeText(text)</a> ⇒ <code>string</code></dt>
320
- <dd><p>Escape text so it is safe inside HTML text content.</p>
322
+ <dd><p>Escape text so it is safe inside HTML text content. Coerces to a string first - unlike a real DOM, pseudo-dom&#39;s
323
+ setAttribute does not itself coerce (see the same note on escapeAttributeValue), and nodeValue is not guaranteed
324
+ to be a string either.</p>
321
325
  </dd>
322
326
  <dt><a href="#escapeAttributeValue">escapeAttributeValue(value)</a> ⇒ <code>string</code></dt>
323
- <dd><p>Escape a value so it is safe inside a double-quoted HTML attribute.</p>
327
+ <dd><p>Escape a value so it is safe inside a double-quoted HTML attribute. Coerces to a string first: a real DOM&#39;s
328
+ setAttribute always stores a string, however pseudo-dom&#39;s does not coerce what it is given, so a value set via
329
+ setAttribute(name, 5) is stored (and read back by getAttribute) as the number 5, not the string &#39;5&#39;.</p>
324
330
  </dd>
325
331
  <dt><a href="#serializeAttributes">serializeAttributes(element)</a> ⇒ <code>string</code></dt>
326
332
  <dd><p>Every attribute of the element, serialized (class instead of className, boolean attributes bare, the never-real
@@ -5483,24 +5489,28 @@ Remember the element which has the focus in a tree.
5483
5489
  <a name="escapeText"></a>
5484
5490
 
5485
5491
  ## escapeText(text) ⇒ <code>string</code>
5486
- Escape text so it is safe inside HTML text content.
5492
+ Escape text so it is safe inside HTML text content. Coerces to a string first - unlike a real DOM, pseudo-dom's
5493
+ setAttribute does not itself coerce (see the same note on escapeAttributeValue), and nodeValue is not guaranteed
5494
+ to be a string either.
5487
5495
 
5488
5496
  **Kind**: global function
5489
5497
 
5490
5498
  | Param | Type |
5491
5499
  | --- | --- |
5492
- | text | <code>string</code> |
5500
+ | text | <code>\*</code> |
5493
5501
 
5494
5502
  <a name="escapeAttributeValue"></a>
5495
5503
 
5496
5504
  ## escapeAttributeValue(value) ⇒ <code>string</code>
5497
- Escape a value so it is safe inside a double-quoted HTML attribute.
5505
+ Escape a value so it is safe inside a double-quoted HTML attribute. Coerces to a string first: a real DOM's
5506
+ setAttribute always stores a string, however pseudo-dom's does not coerce what it is given, so a value set via
5507
+ setAttribute(name, 5) is stored (and read back by getAttribute) as the number 5, not the string '5'.
5498
5508
 
5499
5509
  **Kind**: global function
5500
5510
 
5501
5511
  | Param | Type |
5502
5512
  | --- | --- |
5503
- | value | <code>string</code> |
5513
+ | value | <code>\*</code> |
5504
5514
 
5505
5515
  <a name="serializeAttributes"></a>
5506
5516
 
@@ -5566,9 +5576,10 @@ context.
5566
5576
 
5567
5577
  * [generateDocument(root, context)](#generateDocument) ⇒ <code>Window</code> \| <code>PseudoEventTarget</code>
5568
5578
  * [~newWindow](#generateDocument..newWindow) : <code>Window</code> \| <code>PseudoEventTarget</code>
5569
- * [~Node](#generateDocument..Node) : <code>Node</code> \| <code>PseudoNode</code>
5570
- * [~Element](#generateDocument..Element) : <code>Element</code> \| <code>PseudoElement</code>
5571
- * [~HTMLElement](#generateDocument..HTMLElement) : <code>HTMLElement</code> \| <code>PseudoHTMLElement</code>
5579
+ * [~Node](#generateDocument..Node) : <code>function</code>
5580
+ * [~Element](#generateDocument..Element) : <code>function</code>
5581
+ * [~HTMLElement](#generateDocument..HTMLElement) : <code>function</code>
5582
+ * [~HTMLDocument](#generateDocument..HTMLDocument) : <code>function</code>
5572
5583
  * [~document](#generateDocument..document) : <code>Document</code> \| [<code>PseudoHTMLDocument</code>](#PseudoHTMLDocument)
5573
5584
 
5574
5585
  <a name="generateDocument..newWindow"></a>
@@ -5577,22 +5588,35 @@ context.
5577
5588
  **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5578
5589
  <a name="generateDocument..Node"></a>
5579
5590
 
5580
- ### generateDocument~Node : <code>Node</code> \| <code>PseudoNode</code>
5591
+ ### generateDocument~Node : <code>function</code>
5592
+ The Node class itself (matching the DOM's window.Node), not an instance - the right-hand side of `instanceof`
5593
+ must be a constructor, so `x instanceof Node` needs this, not `new PseudoNode()`.
5594
+
5581
5595
  **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5582
5596
  <a name="generateDocument..Element"></a>
5583
5597
 
5584
- ### generateDocument~Element : <code>Element</code> \| <code>PseudoElement</code>
5598
+ ### generateDocument~Element : <code>function</code>
5599
+ The Element class itself, for the same reason as Node.
5600
+
5585
5601
  **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5586
5602
  <a name="generateDocument..HTMLElement"></a>
5587
5603
 
5588
- ### generateDocument~HTMLElement : <code>HTMLElement</code> \| <code>PseudoHTMLElement</code>
5589
- Create an instance of HTMLElement if not available
5604
+ ### generateDocument~HTMLElement : <code>function</code>
5605
+ The HTMLElement class itself, for the same reason as Node.
5606
+
5607
+ **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5608
+ <a name="generateDocument..HTMLDocument"></a>
5609
+
5610
+ ### generateDocument~HTMLDocument : <code>function</code>
5611
+ The HTMLDocument class itself, for the same reason as Node (so `document instanceof HTMLDocument`, a common
5612
+ real-DOM-detection check, works).
5590
5613
 
5591
5614
  **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5592
5615
  <a name="generateDocument..document"></a>
5593
5616
 
5594
5617
  ### generateDocument~document : <code>Document</code> \| [<code>PseudoHTMLDocument</code>](#PseudoHTMLDocument)
5595
- Define document when not available
5618
+ Define document when not available - a real instance, unlike the classes above (window.document IS an object,
5619
+ not a constructor).
5596
5620
 
5597
5621
  **Kind**: inner constant of [<code>generateDocument</code>](#generateDocument)
5598
5622
  <a name="nearestElementSibling"></a>
@@ -734,30 +734,42 @@
734
734
  */
735
735
  const newWindow = typeof root.document === 'undefined' ? root : new EventTargetService_1.default()
736
736
  /**
737
- * @type {Node|PseudoNode}
737
+ * The Node class itself (matching the DOM's window.Node), not an instance - the right-hand side of `instanceof`
738
+ * must be a constructor, so `x instanceof Node` needs this, not `new PseudoNode()`.
739
+ * @type {Function}
738
740
  */
739
- const Node = root.Node || new NodeService_1.NodeService()
741
+ const Node = root.Node || NodeService_1.NodeService
740
742
  if (typeof newWindow.Node === 'undefined') {
741
743
  newWindow.Node = Node
742
744
  }
743
745
  /**
744
- *
745
- * @type {Element|PseudoElement}
746
+ * The Element class itself, for the same reason as Node.
747
+ * @type {Function}
746
748
  */
747
- const Element = root.Element || new ElementService_1.ElementService()
749
+ const Element = root.Element || ElementService_1.ElementService
748
750
  if (typeof newWindow.Element === 'undefined') {
749
751
  newWindow.Element = Element
750
752
  }
751
753
  /**
752
- * Create an instance of HTMLElement if not available
753
- * @type {HTMLElement|PseudoHTMLElement}
754
+ * The HTMLElement class itself, for the same reason as Node.
755
+ * @type {Function}
754
756
  */
755
- const HTMLElement = root.HTMLElement || new HTMLElementService_1.HTMLElementService()
757
+ const HTMLElement = root.HTMLElement || HTMLElementService_1.HTMLElementService
756
758
  if (typeof newWindow.HTMLElement === 'undefined') {
757
759
  newWindow.HTMLElement = HTMLElement
758
760
  }
759
761
  /**
760
- * Define document when not available
762
+ * The HTMLDocument class itself, for the same reason as Node (so `document instanceof HTMLDocument`, a common
763
+ * real-DOM-detection check, works).
764
+ * @type {Function}
765
+ */
766
+ const HTMLDocument = root.HTMLDocument || PseudoHTMLDocument_1.default
767
+ if (typeof newWindow.HTMLDocument === 'undefined') {
768
+ newWindow.HTMLDocument = HTMLDocument
769
+ }
770
+ /**
771
+ * Define document when not available - a real instance, unlike the classes above (window.document IS an object,
772
+ * not a constructor).
761
773
  * @type {Document|PseudoHTMLDocument}
762
774
  */
763
775
  const document = root.document || new PseudoHTMLDocument_1.default()
@@ -814,17 +826,21 @@
814
826
  * When there is no real DOM already available (a real browser, or a jsdom-based test environment - isBrowser is
815
827
  * true for both, since jsdom's window has a document too, and a jsdom document should never be overwritten, real
816
828
  * DOM behaviour is always closer to the real thing), populate the given global-like target with document / Node /
817
- * Element / HTMLElement, generated by generateDocument, so code written against a real DOM's globals works as-is.
818
- * Does nothing when a real DOM is already there, matching generateDocument's own only-fill-what-is-missing
819
- * behaviour - calling this is always safe, in any environment.
829
+ * Element / HTMLElement / HTMLDocument, generated by generateDocument, plus window (a self-reference, matching a
830
+ * real browser's global scope - some code checks for a bare `window` before falling back to `global`), so code
831
+ * written against a real DOM's globals works as-is. Does nothing when a real DOM is already there, matching
832
+ * generateDocument's own only-fill-what-is-missing behaviour - calling this is always safe, in any environment.
820
833
  * @memberOf module:factories
821
- * @param {*} [target] The object to add document / Node / Element / HTMLElement onto - defaults to globalThis, so
822
- * bare `document`, `Node`, etc. resolve from anywhere once this has run
834
+ * @param {*} [target] The object to add document / Node / Element / HTMLElement / window onto - defaults to
835
+ * globalThis, so bare `document`, `Node`, `window`, etc. resolve from anywhere once this has run
823
836
  * @returns {*} The same target, for convenience
824
837
  */
825
838
  const installGlobal = (target = typeof globalThis !== 'undefined' ? globalThis : {}) => {
826
839
  if (!browser_or_node_1.isBrowser) {
827
840
  (0, generateDocument_1.default)(target, target)
841
+ if (typeof target.window === 'undefined') {
842
+ target.window = target
843
+ }
828
844
  }
829
845
  return target
830
846
  }
@@ -1055,17 +1071,21 @@
1055
1071
  // Boolean HTML attributes: present (with no value) when true, absent entirely when false
1056
1072
  const BOOLEAN_ATTRIBUTES = new Set(['hidden'])
1057
1073
  /**
1058
- * Escape text so it is safe inside HTML text content.
1059
- * @param {string} text
1074
+ * Escape text so it is safe inside HTML text content. Coerces to a string first - unlike a real DOM, pseudo-dom's
1075
+ * setAttribute does not itself coerce (see the same note on escapeAttributeValue), and nodeValue is not guaranteed
1076
+ * to be a string either.
1077
+ * @param {*} text
1060
1078
  * @returns {string}
1061
1079
  */
1062
- const escapeText = text => text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1080
+ const escapeText = text => String(text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1063
1081
  /**
1064
- * Escape a value so it is safe inside a double-quoted HTML attribute.
1065
- * @param {string} value
1082
+ * Escape a value so it is safe inside a double-quoted HTML attribute. Coerces to a string first: a real DOM's
1083
+ * setAttribute always stores a string, however pseudo-dom's does not coerce what it is given, so a value set via
1084
+ * setAttribute(name, 5) is stored (and read back by getAttribute) as the number 5, not the string '5'.
1085
+ * @param {*} value
1066
1086
  * @returns {string}
1067
1087
  */
1068
- const escapeAttributeValue = value => value.replace(/&/g, '&amp;').replace(/"/g, '&quot;')
1088
+ const escapeAttributeValue = value => String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
1069
1089
  /**
1070
1090
  * Every attribute of the element, serialized (class instead of className, boolean attributes bare, the never-real
1071
1091
  * mock properties left out, style added from the live CSSStyleDeclaration when it is not empty).