pseudo-dom 0.8.0 → 0.10.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 +971 -3
- package/browser/pseudo-dom.js +1141 -470
- package/browser/pseudo-dom.min.js +1 -1
- package/dist/classes/PseudoHTMLDocument.d.ts +41 -41
- package/dist/classes/PseudoHTMLDocument.js +74 -74
- package/dist/factories/createDataset.d.ts +10 -0
- package/dist/factories/createDataset.js +78 -0
- package/dist/factories/createDataset.min.js +1 -0
- package/dist/factories/createStyleDeclaration.d.ts +30 -0
- package/dist/factories/createStyleDeclaration.js +64 -0
- package/dist/factories/createStyleDeclaration.min.js +1 -0
- package/dist/functions/getElementById.d.ts +13 -13
- package/dist/functions/getElementById.js +33 -33
- package/dist/interfaces/PseudoCSSStyleDeclaration.d.ts +14 -0
- package/dist/interfaces/PseudoCSSStyleDeclaration.js +5 -0
- package/dist/interfaces/PseudoCSSStyleDeclaration.min.js +1 -0
- package/dist/interfaces/PseudoDocument.d.ts +35 -35
- package/dist/interfaces/PseudoDocumentFragment.d.ts +10 -10
- package/dist/interfaces/PseudoElement.d.ts +765 -702
- package/dist/interfaces/PseudoHTMLElement.d.ts +12 -1
- package/dist/interfaces/PseudoShadowRoot.d.ts +12 -3
- package/dist/services/CSSStyleDeclarationService.d.ts +73 -0
- package/dist/services/CSSStyleDeclarationService.js +156 -0
- package/dist/services/CSSStyleDeclarationService.min.js +1 -0
- package/dist/services/DocumentFragmentService.d.ts +21 -21
- package/dist/services/DocumentFragmentService.js +42 -42
- package/dist/services/DocumentService.d.ts +46 -46
- package/dist/services/DocumentService.js +95 -95
- package/dist/services/ElementService.d.ts +361 -191
- package/dist/services/ElementService.js +717 -426
- package/dist/services/ElementService.min.js +1 -1
- package/dist/services/HTMLElementService.d.ts +31 -1
- package/dist/services/HTMLElementService.js +43 -4
- package/dist/services/HTMLElementService.min.js +1 -1
- package/dist/services/NodeService.d.ts +305 -297
- package/dist/services/NodeService.js +732 -721
- package/dist/services/NodeService.min.js +1 -1
- package/dist/services/ShadowRootService.d.ts +16 -4
- package/dist/services/ShadowRootService.js +24 -9
- package/dist/services/ShadowRootService.min.js +1 -1
- package/package.json +1 -1
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Substitute for the DOM HTMLDocument Class.
|
|
3
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
-
* @version 1.0.0
|
|
5
|
-
*/
|
|
6
|
-
import { HTMLElementService as PseudoHTMLElement } from '../services/HTMLElementService';
|
|
7
|
-
import { DocumentService } from '../services/DocumentService';
|
|
8
|
-
import { NodeService } from '../services/NodeService';
|
|
9
|
-
/**
|
|
10
|
-
* Simulate the behaviour of the HTMLDocument Class when there is no DOM available. Like the real HTMLDocument, this
|
|
11
|
-
* only adds the html/head/body structure on top of what Document already gives (createElement, createTextNode,
|
|
12
|
-
* createComment, createDocumentFragment, getElementById, textContent always null).
|
|
13
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
14
|
-
* @class
|
|
15
|
-
* @augments DocumentService
|
|
16
|
-
* @property {PseudoHTMLElement} head - A reference to the Head child element
|
|
17
|
-
* @property {PseudoHTMLElement} body - A reference to the Body child element
|
|
18
|
-
*/
|
|
19
|
-
declare class PseudoHTMLDocument extends DocumentService {
|
|
20
|
-
head: PseudoHTMLElement | null;
|
|
21
|
-
body: PseudoHTMLElement | null;
|
|
22
|
-
/**
|
|
23
|
-
* The root HTML element is acts as the parent to all HTML elements in the document.
|
|
24
|
-
* @constructor
|
|
25
|
-
*/
|
|
26
|
-
constructor();
|
|
27
|
-
/**
|
|
28
|
-
* A copy of this document with none of its html/head/body (cloneNode, from the inherited cloneShallow hook, fills
|
|
29
|
-
* them back in, deep copies own document's, empty otherwise - see cloneNode).
|
|
30
|
-
* @returns {PseudoHTMLDocument}
|
|
31
|
-
*/
|
|
32
|
-
protected cloneShallow(): NodeService;
|
|
33
|
-
/**
|
|
34
|
-
* Make a copy of this document. The copy has no parent or listeners, and a deep copy has copies of everything in
|
|
35
|
-
* the document (a shallow one is an empty document).
|
|
36
|
-
* @param {boolean} [deep=false] Copy everything in the document as well
|
|
37
|
-
* @returns {PseudoHTMLDocument}
|
|
38
|
-
*/
|
|
39
|
-
cloneNode(deep?: boolean): PseudoHTMLDocument;
|
|
40
|
-
}
|
|
41
|
-
export default PseudoHTMLDocument;
|
|
1
|
+
/**
|
|
2
|
+
* @file Substitute for the DOM HTMLDocument Class.
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { HTMLElementService as PseudoHTMLElement } from '../services/HTMLElementService';
|
|
7
|
+
import { DocumentService } from '../services/DocumentService';
|
|
8
|
+
import { NodeService } from '../services/NodeService';
|
|
9
|
+
/**
|
|
10
|
+
* Simulate the behaviour of the HTMLDocument Class when there is no DOM available. Like the real HTMLDocument, this
|
|
11
|
+
* only adds the html/head/body structure on top of what Document already gives (createElement, createTextNode,
|
|
12
|
+
* createComment, createDocumentFragment, getElementById, textContent always null).
|
|
13
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
14
|
+
* @class
|
|
15
|
+
* @augments DocumentService
|
|
16
|
+
* @property {PseudoHTMLElement} head - A reference to the Head child element
|
|
17
|
+
* @property {PseudoHTMLElement} body - A reference to the Body child element
|
|
18
|
+
*/
|
|
19
|
+
declare class PseudoHTMLDocument extends DocumentService {
|
|
20
|
+
head: PseudoHTMLElement | null;
|
|
21
|
+
body: PseudoHTMLElement | null;
|
|
22
|
+
/**
|
|
23
|
+
* The root HTML element is acts as the parent to all HTML elements in the document.
|
|
24
|
+
* @constructor
|
|
25
|
+
*/
|
|
26
|
+
constructor();
|
|
27
|
+
/**
|
|
28
|
+
* A copy of this document with none of its html/head/body (cloneNode, from the inherited cloneShallow hook, fills
|
|
29
|
+
* them back in, deep copies own document's, empty otherwise - see cloneNode).
|
|
30
|
+
* @returns {PseudoHTMLDocument}
|
|
31
|
+
*/
|
|
32
|
+
protected cloneShallow(): NodeService;
|
|
33
|
+
/**
|
|
34
|
+
* Make a copy of this document. The copy has no parent or listeners, and a deep copy has copies of everything in
|
|
35
|
+
* the document (a shallow one is an empty document).
|
|
36
|
+
* @param {boolean} [deep=false] Copy everything in the document as well
|
|
37
|
+
* @returns {PseudoHTMLDocument}
|
|
38
|
+
*/
|
|
39
|
+
cloneNode(deep?: boolean): PseudoHTMLDocument;
|
|
40
|
+
}
|
|
41
|
+
export default PseudoHTMLDocument;
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
require('core-js/modules/esnext.iterator.constructor.js')
|
|
4
|
-
require('core-js/modules/esnext.iterator.find.js')
|
|
5
|
-
Object.defineProperty(exports, '__esModule', {
|
|
6
|
-
value: true
|
|
7
|
-
})
|
|
8
|
-
const DocumentService_1 = require('../services/DocumentService')
|
|
9
|
-
/**
|
|
10
|
-
* Simulate the behaviour of the HTMLDocument Class when there is no DOM available. Like the real HTMLDocument, this
|
|
11
|
-
* only adds the html/head/body structure on top of what Document already gives (createElement, createTextNode,
|
|
12
|
-
* createComment, createDocumentFragment, getElementById, textContent always null).
|
|
13
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
14
|
-
* @class
|
|
15
|
-
* @augments DocumentService
|
|
16
|
-
* @property {PseudoHTMLElement} head - A reference to the Head child element
|
|
17
|
-
* @property {PseudoHTMLElement} body - A reference to the Body child element
|
|
18
|
-
*/
|
|
19
|
-
class PseudoHTMLDocument extends DocumentService_1.DocumentService {
|
|
20
|
-
/**
|
|
21
|
-
* The root HTML element is acts as the parent to all HTML elements in the document.
|
|
22
|
-
* @constructor
|
|
23
|
-
*/
|
|
24
|
-
constructor () {
|
|
25
|
-
super()
|
|
26
|
-
const html = this.createElement('html')
|
|
27
|
-
this.appendChild(html)
|
|
28
|
-
/**
|
|
29
|
-
* Create document head element
|
|
30
|
-
* @type {PseudoHTMLElement}
|
|
31
|
-
*/
|
|
32
|
-
this.head = this.createElement('head')
|
|
33
|
-
html.appendChild(this.head)
|
|
34
|
-
/**
|
|
35
|
-
* Create document body element
|
|
36
|
-
* @type {PseudoHTMLElement}
|
|
37
|
-
*/
|
|
38
|
-
this.body = this.createElement('body')
|
|
39
|
-
html.appendChild(this.body)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* A copy of this document with none of its html/head/body (cloneNode, from the inherited cloneShallow hook, fills
|
|
44
|
-
* them back in, deep copies own document's, empty otherwise - see cloneNode).
|
|
45
|
-
* @returns {PseudoHTMLDocument}
|
|
46
|
-
*/
|
|
47
|
-
cloneShallow () {
|
|
48
|
-
const copy = new this.constructor()
|
|
49
|
-
while (copy.firstChild) {
|
|
50
|
-
copy.removeChild(copy.firstChild)
|
|
51
|
-
}
|
|
52
|
-
copy.head = null
|
|
53
|
-
copy.body = null
|
|
54
|
-
return copy
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Make a copy of this document. The copy has no parent or listeners, and a deep copy has copies of everything in
|
|
59
|
-
* the document (a shallow one is an empty document).
|
|
60
|
-
* @param {boolean} [deep=false] Copy everything in the document as well
|
|
61
|
-
* @returns {PseudoHTMLDocument}
|
|
62
|
-
*/
|
|
63
|
-
cloneNode (deep = false) {
|
|
64
|
-
const copy = super.cloneNode(deep)
|
|
65
|
-
if (deep) {
|
|
66
|
-
const html = Array.from(copy.childNodes).find(child => child.tagName === 'html')
|
|
67
|
-
const inHtml = tagName => html ? Array.from(html.childNodes).find(child => child.tagName === tagName) || null : null
|
|
68
|
-
copy.head = inHtml('head')
|
|
69
|
-
copy.body = inHtml('body')
|
|
70
|
-
}
|
|
71
|
-
return copy
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
exports.default = PseudoHTMLDocument
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
4
|
+
require('core-js/modules/esnext.iterator.find.js')
|
|
5
|
+
Object.defineProperty(exports, '__esModule', {
|
|
6
|
+
value: true
|
|
7
|
+
})
|
|
8
|
+
const DocumentService_1 = require('../services/DocumentService')
|
|
9
|
+
/**
|
|
10
|
+
* Simulate the behaviour of the HTMLDocument Class when there is no DOM available. Like the real HTMLDocument, this
|
|
11
|
+
* only adds the html/head/body structure on top of what Document already gives (createElement, createTextNode,
|
|
12
|
+
* createComment, createDocumentFragment, getElementById, textContent always null).
|
|
13
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
14
|
+
* @class
|
|
15
|
+
* @augments DocumentService
|
|
16
|
+
* @property {PseudoHTMLElement} head - A reference to the Head child element
|
|
17
|
+
* @property {PseudoHTMLElement} body - A reference to the Body child element
|
|
18
|
+
*/
|
|
19
|
+
class PseudoHTMLDocument extends DocumentService_1.DocumentService {
|
|
20
|
+
/**
|
|
21
|
+
* The root HTML element is acts as the parent to all HTML elements in the document.
|
|
22
|
+
* @constructor
|
|
23
|
+
*/
|
|
24
|
+
constructor () {
|
|
25
|
+
super()
|
|
26
|
+
const html = this.createElement('html')
|
|
27
|
+
this.appendChild(html)
|
|
28
|
+
/**
|
|
29
|
+
* Create document head element
|
|
30
|
+
* @type {PseudoHTMLElement}
|
|
31
|
+
*/
|
|
32
|
+
this.head = this.createElement('head')
|
|
33
|
+
html.appendChild(this.head)
|
|
34
|
+
/**
|
|
35
|
+
* Create document body element
|
|
36
|
+
* @type {PseudoHTMLElement}
|
|
37
|
+
*/
|
|
38
|
+
this.body = this.createElement('body')
|
|
39
|
+
html.appendChild(this.body)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A copy of this document with none of its html/head/body (cloneNode, from the inherited cloneShallow hook, fills
|
|
44
|
+
* them back in, deep copies own document's, empty otherwise - see cloneNode).
|
|
45
|
+
* @returns {PseudoHTMLDocument}
|
|
46
|
+
*/
|
|
47
|
+
cloneShallow () {
|
|
48
|
+
const copy = new this.constructor()
|
|
49
|
+
while (copy.firstChild) {
|
|
50
|
+
copy.removeChild(copy.firstChild)
|
|
51
|
+
}
|
|
52
|
+
copy.head = null
|
|
53
|
+
copy.body = null
|
|
54
|
+
return copy
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Make a copy of this document. The copy has no parent or listeners, and a deep copy has copies of everything in
|
|
59
|
+
* the document (a shallow one is an empty document).
|
|
60
|
+
* @param {boolean} [deep=false] Copy everything in the document as well
|
|
61
|
+
* @returns {PseudoHTMLDocument}
|
|
62
|
+
*/
|
|
63
|
+
cloneNode (deep = false) {
|
|
64
|
+
const copy = super.cloneNode(deep)
|
|
65
|
+
if (deep) {
|
|
66
|
+
const html = Array.from(copy.childNodes).find(child => child.tagName === 'html')
|
|
67
|
+
const inHtml = tagName => html ? Array.from(html.childNodes).find(child => child.tagName === tagName) || null : null
|
|
68
|
+
copy.head = inHtml('head')
|
|
69
|
+
copy.body = inHtml('body')
|
|
70
|
+
}
|
|
71
|
+
return copy
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.default = PseudoHTMLDocument
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A live DOMStringMap-like object for an element's data-* attributes.
|
|
3
|
+
* @memberOf module:factories
|
|
4
|
+
* @param {*} element The element whose data-* attributes this reflects
|
|
5
|
+
* @returns {Object.<string, string>}
|
|
6
|
+
*/
|
|
7
|
+
declare const createDataset: (element: any) => {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
};
|
|
10
|
+
export default createDataset;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
4
|
+
require('core-js/modules/esnext.iterator.map.js')
|
|
5
|
+
Object.defineProperty(exports, '__esModule', {
|
|
6
|
+
value: true
|
|
7
|
+
})
|
|
8
|
+
/**
|
|
9
|
+
* @file Wraps an element in a Proxy which behaves like the DOM's DOMStringMap (element.dataset): a live view of its
|
|
10
|
+
* data-* attributes, under their camelCase names, backed by the element's own getAttribute / setAttribute /
|
|
11
|
+
* hasAttribute / removeAttribute (nothing is stored separately, so it can never fall out of sync with the
|
|
12
|
+
* attributes).
|
|
13
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
14
|
+
* @version 1.0.0
|
|
15
|
+
*/
|
|
16
|
+
const createStyleDeclaration_1 = require('./createStyleDeclaration')
|
|
17
|
+
const DATA_PREFIX = 'data-'
|
|
18
|
+
const attributeName = property => `${DATA_PREFIX}${(0, createStyleDeclaration_1.camelToKebab)(property)}`
|
|
19
|
+
/**
|
|
20
|
+
* Every data-* attribute name currently on the element, as [attributeName, camelCaseName] pairs.
|
|
21
|
+
* @param {*} element
|
|
22
|
+
* @returns {Array<Array<string>>}
|
|
23
|
+
*/
|
|
24
|
+
const dataAttributes = element => {
|
|
25
|
+
const names = []
|
|
26
|
+
for (let index = 0; index < element.attributes.length; index++) {
|
|
27
|
+
const name = element.attributes.item(index).name
|
|
28
|
+
if (name.indexOf(DATA_PREFIX) === 0 && name.length > DATA_PREFIX.length) {
|
|
29
|
+
names.push([name, (0, createStyleDeclaration_1.kebabToCamel)(name.slice(DATA_PREFIX.length))])
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return names
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A live DOMStringMap-like object for an element's data-* attributes.
|
|
36
|
+
* @memberOf module:factories
|
|
37
|
+
* @param {*} element The element whose data-* attributes this reflects
|
|
38
|
+
* @returns {Object.<string, string>}
|
|
39
|
+
*/
|
|
40
|
+
const createDataset = element => new Proxy({}, {
|
|
41
|
+
get (_target, property) {
|
|
42
|
+
if (typeof property !== 'string') {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
const value = element.getAttribute(attributeName(property))
|
|
46
|
+
return value === null ? undefined : value
|
|
47
|
+
},
|
|
48
|
+
set (_target, property, value) {
|
|
49
|
+
if (typeof property !== 'string') {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
element.setAttribute(attributeName(property), String(value))
|
|
53
|
+
return true
|
|
54
|
+
},
|
|
55
|
+
deleteProperty (_target, property) {
|
|
56
|
+
if (typeof property === 'string') {
|
|
57
|
+
element.removeAttribute(attributeName(property))
|
|
58
|
+
}
|
|
59
|
+
return true
|
|
60
|
+
},
|
|
61
|
+
has (_target, property) {
|
|
62
|
+
return typeof property === 'string' && element.hasAttribute(attributeName(property))
|
|
63
|
+
},
|
|
64
|
+
ownKeys () {
|
|
65
|
+
return dataAttributes(element).map(([, camelCaseName]) => camelCaseName)
|
|
66
|
+
},
|
|
67
|
+
getOwnPropertyDescriptor (_target, property) {
|
|
68
|
+
if (typeof property !== 'string' || !element.hasAttribute(attributeName(property))) {
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
configurable: true,
|
|
74
|
+
value: element.getAttribute(attributeName(property))
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
exports.default = createDataset
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js"),Object.defineProperty(exports,"__esModule",{value:!0});const createStyleDeclaration_1=require("./createStyleDeclaration"),DATA_PREFIX="data-",attributeName=t=>`data-${(0,createStyleDeclaration_1.camelToKebab)(t)}`,dataAttributes=t=>{const e=[];for(let r=0;r<t.attributes.length;r++){const a=t.attributes.item(r).name;0===a.indexOf("data-")&&a.length>5&&e.push([a,(0,createStyleDeclaration_1.kebabToCamel)(a.slice(5))])}return e},createDataset=t=>new Proxy({},{get(e,r){if("string"!=typeof r)return;const a=t.getAttribute(attributeName(r));return null===a?void 0:a},set:(e,r,a)=>"string"==typeof r&&(t.setAttribute(attributeName(r),String(a)),!0),deleteProperty:(e,r)=>("string"==typeof r&&t.removeAttribute(attributeName(r)),!0),has:(e,r)=>"string"==typeof r&&t.hasAttribute(attributeName(r)),ownKeys:()=>dataAttributes(t).map(([,t])=>t),getOwnPropertyDescriptor(e,r){if("string"==typeof r&&t.hasAttribute(attributeName(r)))return{enumerable:!0,configurable:!0,value:t.getAttribute(attributeName(r))}}});exports.default=createDataset;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Wraps a CSSStyleDeclarationService in a Proxy so arbitrary camelCase CSS properties (element.style.
|
|
3
|
+
* backgroundColor) work like the DOM's, on top of its real methods (getPropertyValue, setProperty, cssText, ...).
|
|
4
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
import { CSSStyleDeclarationService } from '../services/CSSStyleDeclarationService';
|
|
8
|
+
/**
|
|
9
|
+
* kebab-case -> camelCase ("background-color" -> "backgroundColor").
|
|
10
|
+
* @param {string} name
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
declare const kebabToCamel: (name: string) => string;
|
|
14
|
+
/**
|
|
15
|
+
* camelCase -> kebab-case ("backgroundColor" -> "background-color").
|
|
16
|
+
* @param {string} name
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
declare const camelToKebab: (name: string) => string;
|
|
20
|
+
/**
|
|
21
|
+
* A live CSSStyleDeclaration-like object: its real methods (cssText, getPropertyValue, setProperty, ...) work as
|
|
22
|
+
* declared, and any other property name is treated as a camelCase CSS property (declaration.backgroundColor reads /
|
|
23
|
+
* writes the "background-color" declaration), matching what a real element.style supports.
|
|
24
|
+
* @memberOf module:factories
|
|
25
|
+
* @param {string} [cssText=''] Initial declarations
|
|
26
|
+
* @returns {CSSStyleDeclarationService}
|
|
27
|
+
*/
|
|
28
|
+
declare const createStyleDeclaration: (cssText?: string) => CSSStyleDeclarationService;
|
|
29
|
+
export { kebabToCamel, camelToKebab };
|
|
30
|
+
export default createStyleDeclaration;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.camelToKebab = exports.kebabToCamel = void 0
|
|
7
|
+
/**
|
|
8
|
+
* @file Wraps a CSSStyleDeclarationService in a Proxy so arbitrary camelCase CSS properties (element.style.
|
|
9
|
+
* backgroundColor) work like the DOM's, on top of its real methods (getPropertyValue, setProperty, cssText, ...).
|
|
10
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
11
|
+
* @version 1.0.0
|
|
12
|
+
*/
|
|
13
|
+
const CSSStyleDeclarationService_1 = require('../services/CSSStyleDeclarationService')
|
|
14
|
+
const isIndex = property => /^\d+$/.test(property)
|
|
15
|
+
/**
|
|
16
|
+
* kebab-case -> camelCase ("background-color" -> "backgroundColor").
|
|
17
|
+
* @param {string} name
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
const kebabToCamel = name => name.replace(/-([a-z0-9])/gi, (_match, letter) => letter.toUpperCase())
|
|
21
|
+
exports.kebabToCamel = kebabToCamel
|
|
22
|
+
/**
|
|
23
|
+
* camelCase -> kebab-case ("backgroundColor" -> "background-color").
|
|
24
|
+
* @param {string} name
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
const camelToKebab = name => name.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)
|
|
28
|
+
exports.camelToKebab = camelToKebab
|
|
29
|
+
/**
|
|
30
|
+
* A live CSSStyleDeclaration-like object: its real methods (cssText, getPropertyValue, setProperty, ...) work as
|
|
31
|
+
* declared, and any other property name is treated as a camelCase CSS property (declaration.backgroundColor reads /
|
|
32
|
+
* writes the "background-color" declaration), matching what a real element.style supports.
|
|
33
|
+
* @memberOf module:factories
|
|
34
|
+
* @param {string} [cssText=''] Initial declarations
|
|
35
|
+
* @returns {CSSStyleDeclarationService}
|
|
36
|
+
*/
|
|
37
|
+
const createStyleDeclaration = (cssText = '') => {
|
|
38
|
+
const target = new CSSStyleDeclarationService_1.CSSStyleDeclarationService(cssText)
|
|
39
|
+
return new Proxy(target, {
|
|
40
|
+
get (declaration, property, receiver) {
|
|
41
|
+
if (typeof property !== 'string') {
|
|
42
|
+
return Reflect.get(declaration, property, receiver)
|
|
43
|
+
}
|
|
44
|
+
if (isIndex(property)) {
|
|
45
|
+
return declaration.item(Number(property))
|
|
46
|
+
}
|
|
47
|
+
if (property in declaration) {
|
|
48
|
+
return Reflect.get(declaration, property, receiver)
|
|
49
|
+
}
|
|
50
|
+
return declaration.getPropertyValue(camelToKebab(property))
|
|
51
|
+
},
|
|
52
|
+
set (declaration, property, value) {
|
|
53
|
+
if (typeof property !== 'string' || property === 'cssText') {
|
|
54
|
+
return Reflect.set(declaration, property, value)
|
|
55
|
+
}
|
|
56
|
+
declaration.setProperty(camelToKebab(property), value === null || typeof value === 'undefined' ? '' : String(value))
|
|
57
|
+
return true
|
|
58
|
+
},
|
|
59
|
+
has (declaration, property) {
|
|
60
|
+
return typeof property === 'string' && (property in declaration || declaration.getPropertyValue(camelToKebab(property)) !== '')
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
exports.default = createStyleDeclaration
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.camelToKebab=exports.kebabToCamel=void 0;const CSSStyleDeclarationService_1=require("../services/CSSStyleDeclarationService"),isIndex=e=>/^\d+$/.test(e),kebabToCamel=e=>e.replace(/-([a-z0-9])/gi,(e,t)=>t.toUpperCase());exports.kebabToCamel=kebabToCamel;const camelToKebab=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`);exports.camelToKebab=camelToKebab;const createStyleDeclaration=(e="")=>{const t=new CSSStyleDeclarationService_1.CSSStyleDeclarationService(e);return new Proxy(t,{get:(e,t,a)=>"string"!=typeof t?Reflect.get(e,t,a):isIndex(t)?e.item(Number(t)):t in e?Reflect.get(e,t,a):e.getPropertyValue(camelToKebab(t)),set:(e,t,a)=>"string"!=typeof t||"cssText"===t?Reflect.set(e,t,a):(e.setProperty(camelToKebab(t),null==a?"":String(a)),!0),has:(e,t)=>"string"==typeof t&&(t in e||""!==e.getPropertyValue(camelToKebab(t)))})};exports.default=createStyleDeclaration;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { NodeService } from '../services/NodeService';
|
|
2
|
-
import { PseudoElement } from '../interfaces/PseudoElement';
|
|
3
|
-
/**
|
|
4
|
-
* The first element, in tree order, below (not including) the given node whose id matches the given value, or null
|
|
5
|
-
* when there is none. Shared by Document and DocumentFragment, which both implement the DOM's NonElementParentNode
|
|
6
|
-
* mixin (so ShadowRoot, a DocumentFragment, gets it too).
|
|
7
|
-
* @memberOf module:functions
|
|
8
|
-
* @param {NodeService} root The node to search below
|
|
9
|
-
* @param {string} id
|
|
10
|
-
* @returns {PseudoElement|null}
|
|
11
|
-
*/
|
|
12
|
-
declare const getElementById: (root: NodeService, id: string) => PseudoElement | null;
|
|
13
|
-
export default getElementById;
|
|
1
|
+
import { NodeService } from '../services/NodeService';
|
|
2
|
+
import { PseudoElement } from '../interfaces/PseudoElement';
|
|
3
|
+
/**
|
|
4
|
+
* The first element, in tree order, below (not including) the given node whose id matches the given value, or null
|
|
5
|
+
* when there is none. Shared by Document and DocumentFragment, which both implement the DOM's NonElementParentNode
|
|
6
|
+
* mixin (so ShadowRoot, a DocumentFragment, gets it too).
|
|
7
|
+
* @memberOf module:functions
|
|
8
|
+
* @param {NodeService} root The node to search below
|
|
9
|
+
* @param {string} id
|
|
10
|
+
* @returns {PseudoElement|null}
|
|
11
|
+
*/
|
|
12
|
+
declare const getElementById: (root: NodeService, id: string) => PseudoElement | null;
|
|
13
|
+
export default getElementById;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', {
|
|
4
|
-
value: true
|
|
5
|
-
})
|
|
6
|
-
const NodeService_1 = require('../services/NodeService')
|
|
7
|
-
/**
|
|
8
|
-
* The first element, in tree order, below (not including) the given node whose id matches the given value, or null
|
|
9
|
-
* when there is none. Shared by Document and DocumentFragment, which both implement the DOM's NonElementParentNode
|
|
10
|
-
* mixin (so ShadowRoot, a DocumentFragment, gets it too).
|
|
11
|
-
* @memberOf module:functions
|
|
12
|
-
* @param {NodeService} root The node to search below
|
|
13
|
-
* @param {string} id
|
|
14
|
-
* @returns {PseudoElement|null}
|
|
15
|
-
*/
|
|
16
|
-
const getElementById = (root, id) => {
|
|
17
|
-
const search = node => {
|
|
18
|
-
for (const child of Array.from(node.childNodes)) {
|
|
19
|
-
if (child.nodeType === NodeService_1.NodeService.ELEMENT_NODE) {
|
|
20
|
-
if (child.id === id) {
|
|
21
|
-
return child
|
|
22
|
-
}
|
|
23
|
-
const found = search(child)
|
|
24
|
-
if (found) {
|
|
25
|
-
return found
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return null
|
|
30
|
-
}
|
|
31
|
-
return search(root)
|
|
32
|
-
}
|
|
33
|
-
exports.default = getElementById
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
const NodeService_1 = require('../services/NodeService')
|
|
7
|
+
/**
|
|
8
|
+
* The first element, in tree order, below (not including) the given node whose id matches the given value, or null
|
|
9
|
+
* when there is none. Shared by Document and DocumentFragment, which both implement the DOM's NonElementParentNode
|
|
10
|
+
* mixin (so ShadowRoot, a DocumentFragment, gets it too).
|
|
11
|
+
* @memberOf module:functions
|
|
12
|
+
* @param {NodeService} root The node to search below
|
|
13
|
+
* @param {string} id
|
|
14
|
+
* @returns {PseudoElement|null}
|
|
15
|
+
*/
|
|
16
|
+
const getElementById = (root, id) => {
|
|
17
|
+
const search = node => {
|
|
18
|
+
for (const child of Array.from(node.childNodes)) {
|
|
19
|
+
if (child.nodeType === NodeService_1.NodeService.ELEMENT_NODE) {
|
|
20
|
+
if (child.id === id) {
|
|
21
|
+
return child
|
|
22
|
+
}
|
|
23
|
+
const found = search(child)
|
|
24
|
+
if (found) {
|
|
25
|
+
return found
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
return search(root)
|
|
32
|
+
}
|
|
33
|
+
exports.default = getElementById
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Substitute for the DOM CSSStyleDeclaration Class. Real instances (from createStyleDeclaration) also accept
|
|
3
|
+
* arbitrary camelCase CSS property names (declaration.backgroundColor), which cannot be expressed in an interface.
|
|
4
|
+
*/
|
|
5
|
+
export interface PseudoCSSStyleDeclaration {
|
|
6
|
+
get length(): number;
|
|
7
|
+
get cssText(): string;
|
|
8
|
+
set cssText(cssText: string);
|
|
9
|
+
item(index: number): string;
|
|
10
|
+
getPropertyValue(property: string): string;
|
|
11
|
+
getPropertyPriority(property: string): string;
|
|
12
|
+
setProperty(property: string, value: string, priority: string): void;
|
|
13
|
+
removeProperty(property: string): string;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { PseudoNode } from './PseudoNode';
|
|
2
|
-
import { PseudoElement } from './PseudoElement';
|
|
3
|
-
import { PseudoDocumentFragment } from './PseudoDocumentFragment';
|
|
4
|
-
export interface PseudoDocument extends PseudoNode {
|
|
5
|
-
/**
|
|
6
|
-
* The first element, in tree order, whose id matches the given value, or null when there is none.
|
|
7
|
-
* @param {string} id
|
|
8
|
-
* @returns {PseudoElement|null}
|
|
9
|
-
*/
|
|
10
|
-
getElementById(id: string): PseudoElement | null;
|
|
11
|
-
/**
|
|
12
|
-
* Make an element of the given type which belongs to this document but is not added anywhere until it is appended.
|
|
13
|
-
* @param {string} [tagName='div'] The type of element to create
|
|
14
|
-
* @returns {PseudoElement}
|
|
15
|
-
*/
|
|
16
|
-
createElement(tagName: string): PseudoElement;
|
|
17
|
-
/**
|
|
18
|
-
* Make a text node which belongs to this document.
|
|
19
|
-
* @param {string} [data=''] The text
|
|
20
|
-
* @returns {PseudoNode}
|
|
21
|
-
*/
|
|
22
|
-
createTextNode(data: string): PseudoNode;
|
|
23
|
-
/**
|
|
24
|
-
* Make a comment which belongs to this document.
|
|
25
|
-
* @param {string} [data=''] The comment
|
|
26
|
-
* @returns {PseudoNode}
|
|
27
|
-
*/
|
|
28
|
-
createComment(data: string): PseudoNode;
|
|
29
|
-
/**
|
|
30
|
-
* Make an empty document fragment which belongs to this document, a container for nodes which can be built up and
|
|
31
|
-
* then inserted in one go.
|
|
32
|
-
* @returns {PseudoDocumentFragment}
|
|
33
|
-
*/
|
|
34
|
-
createDocumentFragment(): PseudoDocumentFragment;
|
|
35
|
-
}
|
|
1
|
+
import { PseudoNode } from './PseudoNode';
|
|
2
|
+
import { PseudoElement } from './PseudoElement';
|
|
3
|
+
import { PseudoDocumentFragment } from './PseudoDocumentFragment';
|
|
4
|
+
export interface PseudoDocument extends PseudoNode {
|
|
5
|
+
/**
|
|
6
|
+
* The first element, in tree order, whose id matches the given value, or null when there is none.
|
|
7
|
+
* @param {string} id
|
|
8
|
+
* @returns {PseudoElement|null}
|
|
9
|
+
*/
|
|
10
|
+
getElementById(id: string): PseudoElement | null;
|
|
11
|
+
/**
|
|
12
|
+
* Make an element of the given type which belongs to this document but is not added anywhere until it is appended.
|
|
13
|
+
* @param {string} [tagName='div'] The type of element to create
|
|
14
|
+
* @returns {PseudoElement}
|
|
15
|
+
*/
|
|
16
|
+
createElement(tagName: string): PseudoElement;
|
|
17
|
+
/**
|
|
18
|
+
* Make a text node which belongs to this document.
|
|
19
|
+
* @param {string} [data=''] The text
|
|
20
|
+
* @returns {PseudoNode}
|
|
21
|
+
*/
|
|
22
|
+
createTextNode(data: string): PseudoNode;
|
|
23
|
+
/**
|
|
24
|
+
* Make a comment which belongs to this document.
|
|
25
|
+
* @param {string} [data=''] The comment
|
|
26
|
+
* @returns {PseudoNode}
|
|
27
|
+
*/
|
|
28
|
+
createComment(data: string): PseudoNode;
|
|
29
|
+
/**
|
|
30
|
+
* Make an empty document fragment which belongs to this document, a container for nodes which can be built up and
|
|
31
|
+
* then inserted in one go.
|
|
32
|
+
* @returns {PseudoDocumentFragment}
|
|
33
|
+
*/
|
|
34
|
+
createDocumentFragment(): PseudoDocumentFragment;
|
|
35
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { PseudoNode } from './PseudoNode';
|
|
2
|
-
import { PseudoElement } from './PseudoElement';
|
|
3
|
-
export interface PseudoDocumentFragment extends PseudoNode {
|
|
4
|
-
/**
|
|
5
|
-
* The first element, in tree order, whose id matches the given value, or null when there is none.
|
|
6
|
-
* @param {string} id
|
|
7
|
-
* @returns {PseudoElement|null}
|
|
8
|
-
*/
|
|
9
|
-
getElementById(id: string): PseudoElement | null;
|
|
10
|
-
}
|
|
1
|
+
import { PseudoNode } from './PseudoNode';
|
|
2
|
+
import { PseudoElement } from './PseudoElement';
|
|
3
|
+
export interface PseudoDocumentFragment extends PseudoNode {
|
|
4
|
+
/**
|
|
5
|
+
* The first element, in tree order, whose id matches the given value, or null when there is none.
|
|
6
|
+
* @param {string} id
|
|
7
|
+
* @returns {PseudoElement|null}
|
|
8
|
+
*/
|
|
9
|
+
getElementById(id: string): PseudoElement | null;
|
|
10
|
+
}
|