@eturnity/dom_to_svg 8.10.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.
- package/LICENSE +21 -0
- package/README.md +47 -0
- package/lib/accessibility.d.ts +3 -0
- package/lib/accessibility.d.ts.map +1 -0
- package/lib/accessibility.js +201 -0
- package/lib/accessibility.js.map +1 -0
- package/lib/css.d.ts +26 -0
- package/lib/css.d.ts.map +1 -0
- package/lib/css.js +96 -0
- package/lib/css.js.map +1 -0
- package/lib/dom.d.ts +22 -0
- package/lib/dom.d.ts.map +1 -0
- package/lib/dom.js +33 -0
- package/lib/dom.js.map +1 -0
- package/lib/element.d.ts +3 -0
- package/lib/element.d.ts.map +1 -0
- package/lib/element.js +417 -0
- package/lib/element.js.map +1 -0
- package/lib/gradients.d.ts +3 -0
- package/lib/gradients.d.ts.map +1 -0
- package/lib/gradients.js +78 -0
- package/lib/gradients.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +75 -0
- package/lib/index.js.map +1 -0
- package/lib/inline.d.ts +14 -0
- package/lib/inline.d.ts.map +1 -0
- package/lib/inline.js +138 -0
- package/lib/inline.js.map +1 -0
- package/lib/stacking.d.ts +38 -0
- package/lib/stacking.d.ts.map +1 -0
- package/lib/stacking.js +125 -0
- package/lib/stacking.js.map +1 -0
- package/lib/svg.d.ts +14 -0
- package/lib/svg.d.ts.map +1 -0
- package/lib/svg.js +245 -0
- package/lib/svg.js.map +1 -0
- package/lib/test/PuppeteerAdapter.d.ts +90 -0
- package/lib/test/PuppeteerAdapter.d.ts.map +1 -0
- package/lib/test/PuppeteerAdapter.js +196 -0
- package/lib/test/PuppeteerAdapter.js.map +1 -0
- package/lib/test/injected-script.d.ts +2 -0
- package/lib/test/injected-script.d.ts.map +1 -0
- package/lib/test/injected-script.js +26 -0
- package/lib/test/injected-script.js.map +1 -0
- package/lib/test/test.d.ts +6 -0
- package/lib/test/test.d.ts.map +1 -0
- package/lib/test/test.js +245 -0
- package/lib/test/test.js.map +1 -0
- package/lib/test/util.d.ts +9 -0
- package/lib/test/util.d.ts.map +1 -0
- package/lib/test/util.js +33 -0
- package/lib/test/util.js.map +1 -0
- package/lib/text.d.ts +5 -0
- package/lib/text.d.ts.map +1 -0
- package/lib/text.js +138 -0
- package/lib/text.js.map +1 -0
- package/lib/traversal.d.ts +32 -0
- package/lib/traversal.d.ts.map +1 -0
- package/lib/traversal.js +12 -0
- package/lib/traversal.js.map +1 -0
- package/lib/util.d.ts +20 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +43 -0
- package/lib/util.js.map +1 -0
- package/package.json +112 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Felix Frederick Becker
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# DOM to SVG
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dom-to-svg)
|
|
4
|
+
[](https://github.com/felixfbecker/dom-to-svg/actions)
|
|
5
|
+

|
|
6
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
7
|
+
|
|
8
|
+
Library to convert a given HTML DOM node into an accessible SVG "screenshot".
|
|
9
|
+
|
|
10
|
+
## Demo 📸
|
|
11
|
+
|
|
12
|
+
Try out the [SVG Screenshots Chrome extension](https://chrome.google.com/webstore/detail/svg-screenshot/nfakpcpmhhilkdpphcjgnokknpbpdllg) which uses this library to allow you to take SVG screenshots of any webpage.
|
|
13
|
+
You can find the source code at [github.com/felixfbecker/svg-screenshots](https://github.com/felixfbecker/svg-screenshots).
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { documentToSVG, elementToSVG, inlineResources, formatXML } from 'dom-to-svg'
|
|
19
|
+
|
|
20
|
+
// Capture the whole document
|
|
21
|
+
const svgDocument = documentToSVG(document)
|
|
22
|
+
|
|
23
|
+
// Capture specific element
|
|
24
|
+
const svgDocument = elementToSVG(document.querySelector('#my-element'))
|
|
25
|
+
|
|
26
|
+
// Inline external resources (fonts, images, etc) as data: URIs
|
|
27
|
+
await inlineResources(svgDocument.documentElement)
|
|
28
|
+
|
|
29
|
+
// Get SVG string
|
|
30
|
+
const svgString = new XMLSerializer().serializeToString(svgDocument)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The output can be used as-is as valid SVG or easily passed to other packages to pretty-print or compress.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- Does NOT rely on `<foreignObject>` - SVGs will work in design tools like Illustrator, Figma etc.
|
|
38
|
+
- Maintains DOM accessibility tree by annotating SVG with correct ARIA attributes.
|
|
39
|
+
- Maintains interactive links.
|
|
40
|
+
- Maintains text to allow copying to clipboard.
|
|
41
|
+
- Can inline external resources like images, fonts, etc to make SVG self-contained.
|
|
42
|
+
- Maintains CSS stacking order of elements.
|
|
43
|
+
- Outputs debug attributes on SVG to trace elements back to their DOM nodes.
|
|
44
|
+
|
|
45
|
+
## Caveats
|
|
46
|
+
|
|
47
|
+
- Designed to run in the browser. Using JSDOM on the server will likely not work, but it can easily run inside Puppeteer.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility.d.ts","sourceRoot":"","sources":["../src/accessibility.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAOjD,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,OAAO,EAChB,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,aAAa,CAAC,GACvE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6MrB"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { hasLabels, isHTMLElement } from './dom.js';
|
|
2
|
+
const isStandaloneFooter = (element) => !element.closest('article, aside, main, nav, section, [role="article"], [role="complementary"], [role="main"], [role="navigation"], [role="region"]');
|
|
3
|
+
export function getAccessibilityAttributes(element, { labels, getUniqueId }) {
|
|
4
|
+
var _a, _b, _c;
|
|
5
|
+
// https://www.w3.org/TR/html-aria/
|
|
6
|
+
const attributes = new Map();
|
|
7
|
+
switch (element.tagName) {
|
|
8
|
+
case 'A':
|
|
9
|
+
attributes.set('role', 'link');
|
|
10
|
+
break;
|
|
11
|
+
case 'ARTICLE':
|
|
12
|
+
attributes.set('role', 'article');
|
|
13
|
+
break;
|
|
14
|
+
case 'ASIDE':
|
|
15
|
+
attributes.set('role', 'complementary');
|
|
16
|
+
break;
|
|
17
|
+
case 'BODY':
|
|
18
|
+
attributes.set('role', 'document');
|
|
19
|
+
break;
|
|
20
|
+
case 'BUTTON':
|
|
21
|
+
case 'SUMMARY':
|
|
22
|
+
attributes.set('role', 'button');
|
|
23
|
+
break;
|
|
24
|
+
case 'DD':
|
|
25
|
+
attributes.set('role', 'definition');
|
|
26
|
+
break;
|
|
27
|
+
case 'DETAILS':
|
|
28
|
+
attributes.set('role', 'group');
|
|
29
|
+
break;
|
|
30
|
+
case 'DFN':
|
|
31
|
+
attributes.set('role', 'term');
|
|
32
|
+
break;
|
|
33
|
+
case 'DIALOG':
|
|
34
|
+
attributes.set('role', 'dialog');
|
|
35
|
+
break;
|
|
36
|
+
case 'DT':
|
|
37
|
+
attributes.set('role', 'term');
|
|
38
|
+
break;
|
|
39
|
+
case 'FIELDSET':
|
|
40
|
+
attributes.set('role', 'group');
|
|
41
|
+
break;
|
|
42
|
+
case 'FIGURE':
|
|
43
|
+
attributes.set('role', 'figure');
|
|
44
|
+
break;
|
|
45
|
+
case 'FOOTER':
|
|
46
|
+
if (isStandaloneFooter(element)) {
|
|
47
|
+
attributes.set('role', 'contentinfo');
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case 'FORM':
|
|
51
|
+
attributes.set('role', 'form');
|
|
52
|
+
break;
|
|
53
|
+
case 'H1':
|
|
54
|
+
case 'H2':
|
|
55
|
+
case 'H3':
|
|
56
|
+
case 'H4':
|
|
57
|
+
case 'H5':
|
|
58
|
+
case 'H6':
|
|
59
|
+
attributes.set('role', 'heading');
|
|
60
|
+
attributes.set('aria-level', element.tagName.slice(1));
|
|
61
|
+
break;
|
|
62
|
+
case 'HEADER':
|
|
63
|
+
if (isStandaloneFooter(element)) {
|
|
64
|
+
attributes.set('role', 'banner');
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
case 'HR':
|
|
68
|
+
attributes.set('role', 'separator');
|
|
69
|
+
break;
|
|
70
|
+
case 'IMG': {
|
|
71
|
+
const alt = element.getAttribute('alt');
|
|
72
|
+
if (alt === null || alt !== '') {
|
|
73
|
+
attributes.set('role', 'img');
|
|
74
|
+
if (alt) {
|
|
75
|
+
attributes.set('aria-label', alt);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'INPUT':
|
|
81
|
+
switch (element.type) {
|
|
82
|
+
case 'button':
|
|
83
|
+
case 'image':
|
|
84
|
+
case 'reset':
|
|
85
|
+
case 'submit':
|
|
86
|
+
attributes.set('role', 'button');
|
|
87
|
+
break;
|
|
88
|
+
case 'number':
|
|
89
|
+
attributes.set('role', 'spinbutton');
|
|
90
|
+
break;
|
|
91
|
+
case 'range':
|
|
92
|
+
attributes.set('role', 'slider');
|
|
93
|
+
break;
|
|
94
|
+
case 'checkbox':
|
|
95
|
+
attributes.set('role', 'checkbox');
|
|
96
|
+
break;
|
|
97
|
+
case 'radio':
|
|
98
|
+
attributes.set('role', 'radio');
|
|
99
|
+
break;
|
|
100
|
+
case 'email':
|
|
101
|
+
case 'tel':
|
|
102
|
+
if (!element.hasAttribute('list')) {
|
|
103
|
+
attributes.set('role', 'textbox');
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case 'LI':
|
|
109
|
+
if (((_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.tagName) === 'OL' ||
|
|
110
|
+
((_b = element.parentElement) === null || _b === void 0 ? void 0 : _b.tagName) === 'UL' ||
|
|
111
|
+
((_c = element.parentElement) === null || _c === void 0 ? void 0 : _c.tagName) === 'MENU') {
|
|
112
|
+
attributes.set('role', 'listitem');
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case 'LINK':
|
|
116
|
+
if (element.href) {
|
|
117
|
+
attributes.set('role', 'link');
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
case 'MAIN':
|
|
121
|
+
attributes.set('role', 'main');
|
|
122
|
+
break;
|
|
123
|
+
case 'MATH':
|
|
124
|
+
attributes.set('role', 'math');
|
|
125
|
+
break;
|
|
126
|
+
case 'OL':
|
|
127
|
+
case 'UL':
|
|
128
|
+
case 'MENU':
|
|
129
|
+
attributes.set('role', 'list');
|
|
130
|
+
break;
|
|
131
|
+
case 'NAV':
|
|
132
|
+
attributes.set('role', 'navigation');
|
|
133
|
+
break;
|
|
134
|
+
case 'OPTION':
|
|
135
|
+
attributes.set('role', 'option');
|
|
136
|
+
break;
|
|
137
|
+
case 'PROGRESS':
|
|
138
|
+
attributes.set('role', 'progressbar');
|
|
139
|
+
break;
|
|
140
|
+
case 'SECTION':
|
|
141
|
+
attributes.set('role', 'region');
|
|
142
|
+
break;
|
|
143
|
+
case 'SELECT':
|
|
144
|
+
attributes.set('role', !element.hasAttribute('multiple') && element.size <= 1 ? 'combobox' : 'listbox');
|
|
145
|
+
break;
|
|
146
|
+
case 'TABLE':
|
|
147
|
+
attributes.set('role', 'table');
|
|
148
|
+
break;
|
|
149
|
+
case 'THEAD':
|
|
150
|
+
case 'TBODY':
|
|
151
|
+
case 'TFOOT':
|
|
152
|
+
attributes.set('role', 'rowgroup');
|
|
153
|
+
break;
|
|
154
|
+
case 'TEXTAREA':
|
|
155
|
+
attributes.set('role', 'textbox');
|
|
156
|
+
break;
|
|
157
|
+
case 'TD':
|
|
158
|
+
attributes.set('role', 'cell');
|
|
159
|
+
break;
|
|
160
|
+
case 'TH':
|
|
161
|
+
attributes.set('role', element.closest('thead') ? 'columnheader' : 'rowheader');
|
|
162
|
+
break;
|
|
163
|
+
case 'TR':
|
|
164
|
+
attributes.set('role', 'tablerow');
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
if (element.hasAttribute('disabled')) {
|
|
168
|
+
attributes.set('aria-disabled', 'true');
|
|
169
|
+
}
|
|
170
|
+
if (element.hasAttribute('placeholder')) {
|
|
171
|
+
attributes.set('aria-placeholder', element.getAttribute('placeholder') || '');
|
|
172
|
+
}
|
|
173
|
+
const tabIndex = element.getAttribute('tabindex');
|
|
174
|
+
if (tabIndex) {
|
|
175
|
+
attributes.set('tabindex', tabIndex);
|
|
176
|
+
}
|
|
177
|
+
if (isHTMLElement(element) && hasLabels(element) && element.labels) {
|
|
178
|
+
// Need to invert the label[for] / [aria-labelledby] relationship
|
|
179
|
+
attributes.set('aria-labelledby', [...element.labels]
|
|
180
|
+
.map(label => {
|
|
181
|
+
let labelId = label.id || labels.get(label);
|
|
182
|
+
if (!labelId) {
|
|
183
|
+
labelId = getUniqueId('label');
|
|
184
|
+
labels.set(label, labelId);
|
|
185
|
+
}
|
|
186
|
+
return labelId;
|
|
187
|
+
})
|
|
188
|
+
.join(' '));
|
|
189
|
+
}
|
|
190
|
+
for (const attribute of element.attributes) {
|
|
191
|
+
if (attribute.name.startsWith('aria-')) {
|
|
192
|
+
attributes.set(attribute.name, attribute.value);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const customRole = element.getAttribute('role');
|
|
196
|
+
if (customRole) {
|
|
197
|
+
attributes.set('role', customRole);
|
|
198
|
+
}
|
|
199
|
+
return attributes;
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=accessibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility.js","sourceRoot":"","sources":["../src/accessibility.ts"],"names":[],"mappings":"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","sourcesContent":["import { hasLabels, isHTMLElement } from './dom.js'\nimport { TraversalContext } from './traversal.js'\n\nconst isStandaloneFooter = (element: Element): boolean =>\n\t!element.closest(\n\t\t'article, aside, main, nav, section, [role=\"article\"], [role=\"complementary\"], [role=\"main\"], [role=\"navigation\"], [role=\"region\"]'\n\t)\n\nexport function getAccessibilityAttributes(\n\telement: Element,\n\t{ labels, getUniqueId }: Pick<TraversalContext, 'labels' | 'getUniqueId'>\n): Map<string, string> {\n\t// https://www.w3.org/TR/html-aria/\n\tconst attributes = new Map<string, string>()\n\tswitch (element.tagName) {\n\t\tcase 'A':\n\t\t\tattributes.set('role', 'link')\n\t\t\tbreak\n\t\tcase 'ARTICLE':\n\t\t\tattributes.set('role', 'article')\n\t\t\tbreak\n\t\tcase 'ASIDE':\n\t\t\tattributes.set('role', 'complementary')\n\t\t\tbreak\n\t\tcase 'BODY':\n\t\t\tattributes.set('role', 'document')\n\t\t\tbreak\n\t\tcase 'BUTTON':\n\t\tcase 'SUMMARY':\n\t\t\tattributes.set('role', 'button')\n\t\t\tbreak\n\t\tcase 'DD':\n\t\t\tattributes.set('role', 'definition')\n\t\t\tbreak\n\t\tcase 'DETAILS':\n\t\t\tattributes.set('role', 'group')\n\t\t\tbreak\n\t\tcase 'DFN':\n\t\t\tattributes.set('role', 'term')\n\t\t\tbreak\n\t\tcase 'DIALOG':\n\t\t\tattributes.set('role', 'dialog')\n\t\t\tbreak\n\t\tcase 'DT':\n\t\t\tattributes.set('role', 'term')\n\t\t\tbreak\n\t\tcase 'FIELDSET':\n\t\t\tattributes.set('role', 'group')\n\t\t\tbreak\n\t\tcase 'FIGURE':\n\t\t\tattributes.set('role', 'figure')\n\t\t\tbreak\n\t\tcase 'FOOTER':\n\t\t\tif (isStandaloneFooter(element)) {\n\t\t\t\tattributes.set('role', 'contentinfo')\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'FORM':\n\t\t\tattributes.set('role', 'form')\n\t\t\tbreak\n\t\tcase 'H1':\n\t\tcase 'H2':\n\t\tcase 'H3':\n\t\tcase 'H4':\n\t\tcase 'H5':\n\t\tcase 'H6':\n\t\t\tattributes.set('role', 'heading')\n\t\t\tattributes.set('aria-level', element.tagName.slice(1))\n\t\t\tbreak\n\t\tcase 'HEADER':\n\t\t\tif (isStandaloneFooter(element)) {\n\t\t\t\tattributes.set('role', 'banner')\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'HR':\n\t\t\tattributes.set('role', 'separator')\n\t\t\tbreak\n\t\tcase 'IMG': {\n\t\t\tconst alt = element.getAttribute('alt')\n\t\t\tif (alt === null || alt !== '') {\n\t\t\t\tattributes.set('role', 'img')\n\t\t\t\tif (alt) {\n\t\t\t\t\tattributes.set('aria-label', alt)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tcase 'INPUT':\n\t\t\tswitch ((element as HTMLInputElement).type) {\n\t\t\t\tcase 'button':\n\t\t\t\tcase 'image':\n\t\t\t\tcase 'reset':\n\t\t\t\tcase 'submit':\n\t\t\t\t\tattributes.set('role', 'button')\n\t\t\t\t\tbreak\n\t\t\t\tcase 'number':\n\t\t\t\t\tattributes.set('role', 'spinbutton')\n\t\t\t\t\tbreak\n\t\t\t\tcase 'range':\n\t\t\t\t\tattributes.set('role', 'slider')\n\t\t\t\t\tbreak\n\t\t\t\tcase 'checkbox':\n\t\t\t\t\tattributes.set('role', 'checkbox')\n\t\t\t\t\tbreak\n\t\t\t\tcase 'radio':\n\t\t\t\t\tattributes.set('role', 'radio')\n\t\t\t\t\tbreak\n\t\t\t\tcase 'email':\n\t\t\t\tcase 'tel':\n\t\t\t\t\tif (!element.hasAttribute('list')) {\n\t\t\t\t\t\tattributes.set('role', 'textbox')\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'LI':\n\t\t\tif (\n\t\t\t\telement.parentElement?.tagName === 'OL' ||\n\t\t\t\telement.parentElement?.tagName === 'UL' ||\n\t\t\t\telement.parentElement?.tagName === 'MENU'\n\t\t\t) {\n\t\t\t\tattributes.set('role', 'listitem')\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'LINK':\n\t\t\tif ((element as HTMLLinkElement).href) {\n\t\t\t\tattributes.set('role', 'link')\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'MAIN':\n\t\t\tattributes.set('role', 'main')\n\t\t\tbreak\n\t\tcase 'MATH':\n\t\t\tattributes.set('role', 'math')\n\t\t\tbreak\n\t\tcase 'OL':\n\t\tcase 'UL':\n\t\tcase 'MENU':\n\t\t\tattributes.set('role', 'list')\n\t\t\tbreak\n\t\tcase 'NAV':\n\t\t\tattributes.set('role', 'navigation')\n\t\t\tbreak\n\t\tcase 'OPTION':\n\t\t\tattributes.set('role', 'option')\n\t\t\tbreak\n\t\tcase 'PROGRESS':\n\t\t\tattributes.set('role', 'progressbar')\n\t\t\tbreak\n\t\tcase 'SECTION':\n\t\t\tattributes.set('role', 'region')\n\t\t\tbreak\n\t\tcase 'SELECT':\n\t\t\tattributes.set(\n\t\t\t\t'role',\n\t\t\t\t!element.hasAttribute('multiple') && (element as HTMLSelectElement).size <= 1 ? 'combobox' : 'listbox'\n\t\t\t)\n\t\t\tbreak\n\t\tcase 'TABLE':\n\t\t\tattributes.set('role', 'table')\n\t\t\tbreak\n\t\tcase 'THEAD':\n\t\tcase 'TBODY':\n\t\tcase 'TFOOT':\n\t\t\tattributes.set('role', 'rowgroup')\n\t\t\tbreak\n\t\tcase 'TEXTAREA':\n\t\t\tattributes.set('role', 'textbox')\n\t\t\tbreak\n\t\tcase 'TD':\n\t\t\tattributes.set('role', 'cell')\n\t\t\tbreak\n\t\tcase 'TH':\n\t\t\tattributes.set('role', element.closest('thead') ? 'columnheader' : 'rowheader')\n\t\t\tbreak\n\t\tcase 'TR':\n\t\t\tattributes.set('role', 'tablerow')\n\t\t\tbreak\n\t}\n\tif (element.hasAttribute('disabled')) {\n\t\tattributes.set('aria-disabled', 'true')\n\t}\n\tif (element.hasAttribute('placeholder')) {\n\t\tattributes.set('aria-placeholder', element.getAttribute('placeholder') || '')\n\t}\n\tconst tabIndex = element.getAttribute('tabindex')\n\tif (tabIndex) {\n\t\tattributes.set('tabindex', tabIndex)\n\t}\n\tif (isHTMLElement(element) && hasLabels(element) && element.labels) {\n\t\t// Need to invert the label[for] / [aria-labelledby] relationship\n\t\tattributes.set(\n\t\t\t'aria-labelledby',\n\t\t\t[...element.labels]\n\t\t\t\t.map(label => {\n\t\t\t\t\tlet labelId = label.id || labels.get(label)\n\t\t\t\t\tif (!labelId) {\n\t\t\t\t\t\tlabelId = getUniqueId('label')\n\t\t\t\t\t\tlabels.set(label, labelId)\n\t\t\t\t\t}\n\t\t\t\t\treturn labelId\n\t\t\t\t})\n\t\t\t\t.join(' ')\n\t\t)\n\t}\n\n\tfor (const attribute of element.attributes) {\n\t\tif (attribute.name.startsWith('aria-')) {\n\t\t\tattributes.set(attribute.name, attribute.value)\n\t\t}\n\t}\n\tconst customRole = element.getAttribute('role')\n\tif (customRole) {\n\t\tattributes.set('role', customRole)\n\t}\n\treturn attributes\n}\n"]}
|
package/lib/css.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const isCSSFontFaceRule: (rule: CSSRule) => rule is CSSFontFaceRule;
|
|
2
|
+
export declare const isInline: (styles: CSSStyleDeclaration) => boolean;
|
|
3
|
+
export declare const isPositioned: (styles: CSSStyleDeclaration) => boolean;
|
|
4
|
+
export declare const isInFlow: (styles: CSSStyleDeclaration) => boolean;
|
|
5
|
+
export declare const isTransparent: (color: string) => boolean;
|
|
6
|
+
export declare const hasUniformBorder: (styles: CSSStyleDeclaration) => boolean;
|
|
7
|
+
/** A side of a box. */
|
|
8
|
+
export declare type Side = 'top' | 'bottom' | 'right' | 'left';
|
|
9
|
+
/** Whether the given side is a horizontal side. */
|
|
10
|
+
export declare const isHorizontal: (side: Side) => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the (elliptic) border radii for a given side.
|
|
13
|
+
* For example, for the top side it will return the horizontal top-left and the horizontal top-right border radii.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBorderRadiiForSide(side: Side, styles: CSSStyleDeclaration, bounds: DOMRectReadOnly): [number, number];
|
|
16
|
+
/**
|
|
17
|
+
* Returns the factor by which all border radii have to be scaled to fit correctly.
|
|
18
|
+
*
|
|
19
|
+
* @see https://drafts.csswg.org/css-backgrounds-3/#corner-overlap
|
|
20
|
+
*/
|
|
21
|
+
export declare const calculateOverlappingCurvesFactor: (styles: CSSStyleDeclaration, bounds: DOMRectReadOnly) => number;
|
|
22
|
+
export declare const isVisible: (styles: CSSStyleDeclaration) => boolean;
|
|
23
|
+
export declare function parseCSSLength(length: string, containerLength: number): number | undefined;
|
|
24
|
+
export declare const unescapeStringValue: (value: string) => string;
|
|
25
|
+
export declare function copyCssStyles(from: CSSStyleDeclaration, to: CSSStyleDeclaration): void;
|
|
26
|
+
//# sourceMappingURL=css.d.ts.map
|
package/lib/css.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,SAAU,OAAO,4BAAkE,CAAA;AAEjH,eAAO,MAAM,QAAQ,WAAY,mBAAmB,KAAG,OACoB,CAAA;AAE3E,eAAO,MAAM,YAAY,WAAY,mBAAmB,KAAG,OAAuC,CAAA;AAElG,eAAO,MAAM,QAAQ,WAAY,mBAAmB,KAAG,OACkC,CAAA;AAEzF,eAAO,MAAM,aAAa,UAAW,MAAM,KAAG,OAAkE,CAAA;AAEhH,eAAO,MAAM,gBAAgB,WAAY,mBAAmB,KAAG,OAiBZ,CAAA;AAEnD,uBAAuB;AACvB,oBAAY,IAAI,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;AAKtD,mDAAmD;AACnD,eAAO,MAAM,YAAY,SAAU,IAAI,KAAG,OAA8C,CAAA;AAYxF;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,eAAe,GACrB,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BlB;AAED;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,WAAY,mBAAmB,UAAU,eAAe,KAAG,MAQtG,CAAA;AAEF,eAAO,MAAM,SAAS,WAAY,mBAAmB,KAAG,OAIjC,CAAA;AAEvB,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ1F;AAED,eAAO,MAAM,mBAAmB,UAAW,MAAM,KAAG,MAK1B,CAAA;AAE1B,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,mBAAmB,GAAG,IAAI,CAItF"}
|
package/lib/css.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export const isCSSFontFaceRule = (rule) => rule.type === CSSRule.FONT_FACE_RULE;
|
|
2
|
+
export const isInline = (styles) => styles.displayOutside === 'inline' || styles.display.startsWith('inline-');
|
|
3
|
+
export const isPositioned = (styles) => styles.position !== 'static';
|
|
4
|
+
export const isInFlow = (styles) => styles.float !== 'none' && styles.position !== 'absolute' && styles.position !== 'fixed';
|
|
5
|
+
export const isTransparent = (color) => color === 'transparent' || color === 'rgba(0, 0, 0, 0)';
|
|
6
|
+
export const hasUniformBorder = (styles) => parseFloat(styles.borderTopWidth) !== 0 &&
|
|
7
|
+
styles.borderTopStyle !== 'none' &&
|
|
8
|
+
styles.borderTopStyle !== 'inset' &&
|
|
9
|
+
styles.borderTopStyle !== 'outset' &&
|
|
10
|
+
!isTransparent(styles.borderTopColor) &&
|
|
11
|
+
// Cannot use border property directly as in Firefox those are empty strings.
|
|
12
|
+
// Need to get the specific border properties from the specific sides.
|
|
13
|
+
// https://stackoverflow.com/questions/41696063/getcomputedstyle-returns-empty-strings-on-ff-when-instead-crome-returns-a-comp
|
|
14
|
+
styles.borderTopWidth === styles.borderLeftWidth &&
|
|
15
|
+
styles.borderTopWidth === styles.borderRightWidth &&
|
|
16
|
+
styles.borderTopWidth === styles.borderBottomWidth &&
|
|
17
|
+
styles.borderTopColor === styles.borderLeftColor &&
|
|
18
|
+
styles.borderTopColor === styles.borderRightColor &&
|
|
19
|
+
styles.borderTopColor === styles.borderBottomColor &&
|
|
20
|
+
styles.borderTopStyle === styles.borderLeftStyle &&
|
|
21
|
+
styles.borderTopStyle === styles.borderRightStyle &&
|
|
22
|
+
styles.borderTopStyle === styles.borderBottomStyle;
|
|
23
|
+
/** The 4 sides of a box. */
|
|
24
|
+
const SIDES = ['top', 'bottom', 'right', 'left'];
|
|
25
|
+
/** Whether the given side is a horizontal side. */
|
|
26
|
+
export const isHorizontal = (side) => side === 'bottom' || side === 'top';
|
|
27
|
+
/**
|
|
28
|
+
* The two corners for each side, in order of lower coordinate to higher coordinate.
|
|
29
|
+
*/
|
|
30
|
+
const CORNERS = {
|
|
31
|
+
top: ['left', 'right'],
|
|
32
|
+
bottom: ['left', 'right'],
|
|
33
|
+
left: ['top', 'bottom'],
|
|
34
|
+
right: ['top', 'bottom'],
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Returns the (elliptic) border radii for a given side.
|
|
38
|
+
* For example, for the top side it will return the horizontal top-left and the horizontal top-right border radii.
|
|
39
|
+
*/
|
|
40
|
+
export function getBorderRadiiForSide(side, styles, bounds) {
|
|
41
|
+
var _a, _b, _c, _d;
|
|
42
|
+
const [horizontalStyle1, verticalStyle1] = styles
|
|
43
|
+
.getPropertyValue(isHorizontal(side)
|
|
44
|
+
? `border-${side}-${CORNERS[side][0]}-radius`
|
|
45
|
+
: `border-${CORNERS[side][0]}-${side}-radius`)
|
|
46
|
+
.split(' ');
|
|
47
|
+
const [horizontalStyle2, verticalStyle2] = styles
|
|
48
|
+
.getPropertyValue(isHorizontal(side)
|
|
49
|
+
? `border-${side}-${CORNERS[side][1]}-radius`
|
|
50
|
+
: `border-${CORNERS[side][1]}-${side}-radius`)
|
|
51
|
+
.split(' ');
|
|
52
|
+
if (isHorizontal(side)) {
|
|
53
|
+
return [
|
|
54
|
+
(_a = parseCSSLength(horizontalStyle1 || '0px', bounds.width)) !== null && _a !== void 0 ? _a : 0,
|
|
55
|
+
(_b = parseCSSLength(horizontalStyle2 || '0px', bounds.width)) !== null && _b !== void 0 ? _b : 0,
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
return [
|
|
59
|
+
(_c = parseCSSLength(verticalStyle1 || horizontalStyle1 || '0px', bounds.height)) !== null && _c !== void 0 ? _c : 0,
|
|
60
|
+
(_d = parseCSSLength(verticalStyle2 || horizontalStyle2 || '0px', bounds.height)) !== null && _d !== void 0 ? _d : 0,
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns the factor by which all border radii have to be scaled to fit correctly.
|
|
65
|
+
*
|
|
66
|
+
* @see https://drafts.csswg.org/css-backgrounds-3/#corner-overlap
|
|
67
|
+
*/
|
|
68
|
+
export const calculateOverlappingCurvesFactor = (styles, bounds) => Math.min(...SIDES.map(side => {
|
|
69
|
+
const length = isHorizontal(side) ? bounds.width : bounds.height;
|
|
70
|
+
const radiiSum = getBorderRadiiForSide(side, styles, bounds).reduce((sum, radius) => sum + radius, 0);
|
|
71
|
+
return length / radiiSum;
|
|
72
|
+
}), 1);
|
|
73
|
+
export const isVisible = (styles) => styles.displayOutside !== 'none' &&
|
|
74
|
+
styles.display !== 'none' &&
|
|
75
|
+
styles.visibility !== 'hidden' &&
|
|
76
|
+
styles.opacity !== '0';
|
|
77
|
+
export function parseCSSLength(length, containerLength) {
|
|
78
|
+
if (length.endsWith('px')) {
|
|
79
|
+
return parseFloat(length);
|
|
80
|
+
}
|
|
81
|
+
if (length.endsWith('%')) {
|
|
82
|
+
return (parseFloat(length) / 100) * containerLength;
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
export const unescapeStringValue = (value) => value
|
|
87
|
+
// Replace hex escape sequences
|
|
88
|
+
.replace(/\\([\da-f]{1,2})/gi, (substring, codePoint) => String.fromCodePoint(parseInt(codePoint, 16)))
|
|
89
|
+
// Replace all other escapes (quotes, backslash, etc)
|
|
90
|
+
.replace(/\\(.)/g, '$1');
|
|
91
|
+
export function copyCssStyles(from, to) {
|
|
92
|
+
for (const property of from) {
|
|
93
|
+
to.setProperty(property, from.getPropertyValue(property), from.getPropertyPriority(property));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=css.js.map
|
package/lib/css.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"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","sourcesContent":["export const isCSSFontFaceRule = (rule: CSSRule): rule is CSSFontFaceRule => rule.type === CSSRule.FONT_FACE_RULE\n\nexport const isInline = (styles: CSSStyleDeclaration): boolean =>\n\tstyles.displayOutside === 'inline' || styles.display.startsWith('inline-')\n\nexport const isPositioned = (styles: CSSStyleDeclaration): boolean => styles.position !== 'static'\n\nexport const isInFlow = (styles: CSSStyleDeclaration): boolean =>\n\tstyles.float !== 'none' && styles.position !== 'absolute' && styles.position !== 'fixed'\n\nexport const isTransparent = (color: string): boolean => color === 'transparent' || color === 'rgba(0, 0, 0, 0)'\n\nexport const hasUniformBorder = (styles: CSSStyleDeclaration): boolean =>\n\tparseFloat(styles.borderTopWidth) !== 0 &&\n\tstyles.borderTopStyle !== 'none' &&\n\tstyles.borderTopStyle !== 'inset' &&\n\tstyles.borderTopStyle !== 'outset' &&\n\t!isTransparent(styles.borderTopColor) &&\n\t// Cannot use border property directly as in Firefox those are empty strings.\n\t// Need to get the specific border properties from the specific sides.\n\t// https://stackoverflow.com/questions/41696063/getcomputedstyle-returns-empty-strings-on-ff-when-instead-crome-returns-a-comp\n\tstyles.borderTopWidth === styles.borderLeftWidth &&\n\tstyles.borderTopWidth === styles.borderRightWidth &&\n\tstyles.borderTopWidth === styles.borderBottomWidth &&\n\tstyles.borderTopColor === styles.borderLeftColor &&\n\tstyles.borderTopColor === styles.borderRightColor &&\n\tstyles.borderTopColor === styles.borderBottomColor &&\n\tstyles.borderTopStyle === styles.borderLeftStyle &&\n\tstyles.borderTopStyle === styles.borderRightStyle &&\n\tstyles.borderTopStyle === styles.borderBottomStyle\n\n/** A side of a box. */\nexport type Side = 'top' | 'bottom' | 'right' | 'left'\n\n/** The 4 sides of a box. */\nconst SIDES: Side[] = ['top', 'bottom', 'right', 'left']\n\n/** Whether the given side is a horizontal side. */\nexport const isHorizontal = (side: Side): boolean => side === 'bottom' || side === 'top'\n\n/**\n * The two corners for each side, in order of lower coordinate to higher coordinate.\n */\nconst CORNERS: Record<Side, [Side, Side]> = {\n\ttop: ['left', 'right'],\n\tbottom: ['left', 'right'],\n\tleft: ['top', 'bottom'],\n\tright: ['top', 'bottom'],\n}\n\n/**\n * Returns the (elliptic) border radii for a given side.\n * For example, for the top side it will return the horizontal top-left and the horizontal top-right border radii.\n */\nexport function getBorderRadiiForSide(\n\tside: Side,\n\tstyles: CSSStyleDeclaration,\n\tbounds: DOMRectReadOnly\n): [number, number] {\n\tconst [horizontalStyle1, verticalStyle1] = styles\n\t\t.getPropertyValue(\n\t\t\tisHorizontal(side)\n\t\t\t\t? `border-${side}-${CORNERS[side][0]}-radius`\n\t\t\t\t: `border-${CORNERS[side][0]}-${side}-radius`\n\t\t)\n\t\t.split(' ')\n\n\tconst [horizontalStyle2, verticalStyle2] = styles\n\t\t.getPropertyValue(\n\t\t\tisHorizontal(side)\n\t\t\t\t? `border-${side}-${CORNERS[side][1]}-radius`\n\t\t\t\t: `border-${CORNERS[side][1]}-${side}-radius`\n\t\t)\n\t\t.split(' ')\n\n\tif (isHorizontal(side)) {\n\t\treturn [\n\t\t\tparseCSSLength(horizontalStyle1 || '0px', bounds.width) ?? 0,\n\t\t\tparseCSSLength(horizontalStyle2 || '0px', bounds.width) ?? 0,\n\t\t]\n\t}\n\treturn [\n\t\tparseCSSLength(verticalStyle1 || horizontalStyle1 || '0px', bounds.height) ?? 0,\n\t\tparseCSSLength(verticalStyle2 || horizontalStyle2 || '0px', bounds.height) ?? 0,\n\t]\n}\n\n/**\n * Returns the factor by which all border radii have to be scaled to fit correctly.\n *\n * @see https://drafts.csswg.org/css-backgrounds-3/#corner-overlap\n */\nexport const calculateOverlappingCurvesFactor = (styles: CSSStyleDeclaration, bounds: DOMRectReadOnly): number =>\n\tMath.min(\n\t\t...SIDES.map(side => {\n\t\t\tconst length = isHorizontal(side) ? bounds.width : bounds.height\n\t\t\tconst radiiSum = getBorderRadiiForSide(side, styles, bounds).reduce((sum, radius) => sum + radius, 0)\n\t\t\treturn length / radiiSum\n\t\t}),\n\t\t1\n\t)\n\nexport const isVisible = (styles: CSSStyleDeclaration): boolean =>\n\tstyles.displayOutside !== 'none' &&\n\tstyles.display !== 'none' &&\n\tstyles.visibility !== 'hidden' &&\n\tstyles.opacity !== '0'\n\nexport function parseCSSLength(length: string, containerLength: number): number | undefined {\n\tif (length.endsWith('px')) {\n\t\treturn parseFloat(length)\n\t}\n\tif (length.endsWith('%')) {\n\t\treturn (parseFloat(length) / 100) * containerLength\n\t}\n\treturn undefined\n}\n\nexport const unescapeStringValue = (value: string): string =>\n\tvalue\n\t\t// Replace hex escape sequences\n\t\t.replace(/\\\\([\\da-f]{1,2})/gi, (substring, codePoint) => String.fromCodePoint(parseInt(codePoint, 16)))\n\t\t// Replace all other escapes (quotes, backslash, etc)\n\t\t.replace(/\\\\(.)/g, '$1')\n\nexport function copyCssStyles(from: CSSStyleDeclaration, to: CSSStyleDeclaration): void {\n\tfor (const property of from) {\n\t\tto.setProperty(property, from.getPropertyValue(property), from.getPropertyPriority(property))\n\t}\n}\n"]}
|
package/lib/dom.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const svgNamespace = "http://www.w3.org/2000/svg";
|
|
2
|
+
export declare const xlinkNamespace = "http://www.w3.org/1999/xlink";
|
|
3
|
+
export declare const xhtmlNamespace = "http://www.w3.org/1999/xhtml";
|
|
4
|
+
export declare const isElement: (node: Node) => node is Element;
|
|
5
|
+
export declare const isTextNode: (node: Node) => node is Text;
|
|
6
|
+
export declare const isCommentNode: (node: Node) => node is Comment;
|
|
7
|
+
export declare const isSVGElement: (element: Element) => element is SVGElement;
|
|
8
|
+
export declare const isSVGSVGElement: (element: Element) => element is SVGSVGElement;
|
|
9
|
+
export declare const isSVGGraphicsElement: (element: Element) => element is SVGGraphicsElement;
|
|
10
|
+
export declare const isSVGGroupElement: (element: Element) => element is SVGGElement;
|
|
11
|
+
export declare const isSVGAnchorElement: (element: Element) => element is SVGAElement;
|
|
12
|
+
export declare const isSVGTextContentElement: (element: Element) => element is SVGTextContentElement;
|
|
13
|
+
export declare const isSVGImageElement: (element: Element) => element is SVGImageElement;
|
|
14
|
+
export declare const isSVGStyleElement: (element: Element) => element is SVGStyleElement;
|
|
15
|
+
export declare const isHTMLElement: (element: Element) => element is HTMLElement;
|
|
16
|
+
export declare const isHTMLAnchorElement: (element: Element) => element is HTMLAnchorElement;
|
|
17
|
+
export declare const isHTMLLabelElement: (element: Element) => element is HTMLLabelElement;
|
|
18
|
+
export declare const isHTMLImageElement: (element: Element) => element is HTMLImageElement;
|
|
19
|
+
export declare const isHTMLInputElement: (element: Element) => element is HTMLInputElement;
|
|
20
|
+
export declare const hasLabels: (element: HTMLElement) => element is HTMLElement & Pick<HTMLInputElement, "labels">;
|
|
21
|
+
export declare function traverseDOM(node: Node, shouldEnter?: (node: Node) => boolean): Iterable<Node>;
|
|
22
|
+
//# sourceMappingURL=dom.d.ts.map
|
package/lib/dom.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,YAAY,+BAA+B,CAAA;AACxD,eAAO,MAAM,cAAc,iCAAiC,CAAA;AAC5D,eAAO,MAAM,cAAc,iCAAiC,CAAA;AAG5D,eAAO,MAAM,SAAS,SAAU,IAAI,oBAAyD,CAAA;AAC7F,eAAO,MAAM,UAAU,SAAU,IAAI,iBAAmD,CAAA;AACxF,eAAO,MAAM,aAAa,SAAU,IAAI,oBAAyD,CAAA;AAGjG,eAAO,MAAM,YAAY,YAAa,OAAO,0BAAiE,CAAA;AAC9G,eAAO,MAAM,eAAe,YAAa,OAAO,6BACG,CAAA;AACnD,eAAO,MAAM,oBAAoB,YAAa,OAAO,kCACqB,CAAA;AAC1E,eAAO,MAAM,iBAAiB,YAAa,OAAO,2BACD,CAAA;AACjD,eAAO,MAAM,kBAAkB,YAAa,OAAO,2BACF,CAAA;AACjD,eAAO,MAAM,uBAAuB,YAAa,OAAO,qCACP,CAAA;AACjD,eAAO,MAAM,iBAAiB,YAAa,OAAO,+BACG,CAAA;AACrD,eAAO,MAAM,iBAAiB,YAAa,OAAO,+BACG,CAAA;AAGrD,eAAO,MAAM,aAAa,YAAa,OAAO,2BAAoE,CAAA;AAClH,eAAO,MAAM,mBAAmB,YAAa,OAAO,iCACF,CAAA;AAClD,eAAO,MAAM,kBAAkB,YAAa,OAAO,gCACG,CAAA;AACtD,eAAO,MAAM,kBAAkB,YAAa,OAAO,gCACC,CAAA;AACpD,eAAO,MAAM,kBAAkB,YAAa,OAAO,gCACG,CAAA;AACtD,eAAO,MAAM,SAAS,YAAa,WAAW,8DAC1B,CAAA;AAEpB,wBAAiB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,GAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAO1G"}
|
package/lib/dom.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Namespaces
|
|
2
|
+
export const svgNamespace = 'http://www.w3.org/2000/svg';
|
|
3
|
+
export const xlinkNamespace = 'http://www.w3.org/1999/xlink';
|
|
4
|
+
export const xhtmlNamespace = 'http://www.w3.org/1999/xhtml';
|
|
5
|
+
// DOM
|
|
6
|
+
export const isElement = (node) => node.nodeType === Node.ELEMENT_NODE;
|
|
7
|
+
export const isTextNode = (node) => node.nodeType === Node.TEXT_NODE;
|
|
8
|
+
export const isCommentNode = (node) => node.nodeType === Node.COMMENT_NODE;
|
|
9
|
+
// SVG
|
|
10
|
+
export const isSVGElement = (element) => element.namespaceURI === svgNamespace;
|
|
11
|
+
export const isSVGSVGElement = (element) => isSVGElement(element) && element.tagName === 'svg';
|
|
12
|
+
export const isSVGGraphicsElement = (element) => isSVGElement(element) && 'getCTM' in element && 'getScreenCTM' in element;
|
|
13
|
+
export const isSVGGroupElement = (element) => isSVGElement(element) && element.tagName === 'g';
|
|
14
|
+
export const isSVGAnchorElement = (element) => isSVGElement(element) && element.tagName === 'a';
|
|
15
|
+
export const isSVGTextContentElement = (element) => isSVGElement(element) && 'textLength' in element;
|
|
16
|
+
export const isSVGImageElement = (element) => element.tagName === 'image' && isSVGElement(element);
|
|
17
|
+
export const isSVGStyleElement = (element) => element.tagName === 'style' && isSVGElement(element);
|
|
18
|
+
// HTML
|
|
19
|
+
export const isHTMLElement = (element) => element.namespaceURI === xhtmlNamespace;
|
|
20
|
+
export const isHTMLAnchorElement = (element) => element.tagName === 'A' && isHTMLElement(element);
|
|
21
|
+
export const isHTMLLabelElement = (element) => element.tagName === 'LABEL' && isHTMLElement(element);
|
|
22
|
+
export const isHTMLImageElement = (element) => element.tagName === 'IMG' && isHTMLElement(element);
|
|
23
|
+
export const isHTMLInputElement = (element) => element.tagName === 'INPUT' && isHTMLElement(element);
|
|
24
|
+
export const hasLabels = (element) => 'labels' in element;
|
|
25
|
+
export function* traverseDOM(node, shouldEnter = () => true) {
|
|
26
|
+
yield node;
|
|
27
|
+
if (shouldEnter(node)) {
|
|
28
|
+
for (const childNode of node.childNodes) {
|
|
29
|
+
yield* traverseDOM(childNode);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=dom.js.map
|
package/lib/dom.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"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","sourcesContent":["// Namespaces\nexport const svgNamespace = 'http://www.w3.org/2000/svg'\nexport const xlinkNamespace = 'http://www.w3.org/1999/xlink'\nexport const xhtmlNamespace = 'http://www.w3.org/1999/xhtml'\n\n// DOM\nexport const isElement = (node: Node): node is Element => node.nodeType === Node.ELEMENT_NODE\nexport const isTextNode = (node: Node): node is Text => node.nodeType === Node.TEXT_NODE\nexport const isCommentNode = (node: Node): node is Comment => node.nodeType === Node.COMMENT_NODE\n\n// SVG\nexport const isSVGElement = (element: Element): element is SVGElement => element.namespaceURI === svgNamespace\nexport const isSVGSVGElement = (element: Element): element is SVGSVGElement =>\n\tisSVGElement(element) && element.tagName === 'svg'\nexport const isSVGGraphicsElement = (element: Element): element is SVGGraphicsElement =>\n\tisSVGElement(element) && 'getCTM' in element && 'getScreenCTM' in element\nexport const isSVGGroupElement = (element: Element): element is SVGGElement =>\n\tisSVGElement(element) && element.tagName === 'g'\nexport const isSVGAnchorElement = (element: Element): element is SVGAElement =>\n\tisSVGElement(element) && element.tagName === 'a'\nexport const isSVGTextContentElement = (element: Element): element is SVGTextContentElement =>\n\tisSVGElement(element) && 'textLength' in element\nexport const isSVGImageElement = (element: Element): element is SVGImageElement =>\n\telement.tagName === 'image' && isSVGElement(element)\nexport const isSVGStyleElement = (element: Element): element is SVGStyleElement =>\n\telement.tagName === 'style' && isSVGElement(element)\n\n// HTML\nexport const isHTMLElement = (element: Element): element is HTMLElement => element.namespaceURI === xhtmlNamespace\nexport const isHTMLAnchorElement = (element: Element): element is HTMLAnchorElement =>\n\telement.tagName === 'A' && isHTMLElement(element)\nexport const isHTMLLabelElement = (element: Element): element is HTMLLabelElement =>\n\telement.tagName === 'LABEL' && isHTMLElement(element)\nexport const isHTMLImageElement = (element: Element): element is HTMLImageElement =>\n\telement.tagName === 'IMG' && isHTMLElement(element)\nexport const isHTMLInputElement = (element: Element): element is HTMLInputElement =>\n\telement.tagName === 'INPUT' && isHTMLElement(element)\nexport const hasLabels = (element: HTMLElement): element is HTMLElement & Pick<HTMLInputElement, 'labels'> =>\n\t'labels' in element\n\nexport function* traverseDOM(node: Node, shouldEnter: (node: Node) => boolean = () => true): Iterable<Node> {\n\tyield node\n\tif (shouldEnter(node)) {\n\t\tfor (const childNode of node.childNodes) {\n\t\t\tyield* traverseDOM(childNode)\n\t\t}\n\t}\n}\n"]}
|
package/lib/element.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,gBAAgB,EAAY,MAAM,gBAAgB,CAAA;AAG3D,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAyNzF"}
|