wc-compiler 0.14.0 → 0.15.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/README.md +1 -1
- package/dist/wcc.dist.cjs +10280 -12114
- package/package.json +6 -7
- package/src/jsx-loader.js +5 -5
- package/src/wcc.js +80 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wc-compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Experimental native Web Components compiler.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,10 +43,9 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@projectevergreen/acorn-jsx-esm": "~0.1.0",
|
|
46
|
-
"
|
|
47
|
-
"acorn": "^8.
|
|
48
|
-
"
|
|
49
|
-
"acorn-walk": "^8.2.0",
|
|
46
|
+
"acorn": "^8.14.0",
|
|
47
|
+
"acorn-walk": "^8.3.4",
|
|
48
|
+
"astring": "^1.9.0",
|
|
50
49
|
"parse5": "^6.0.1",
|
|
51
50
|
"sucrase": "^3.35.0"
|
|
52
51
|
},
|
|
@@ -57,7 +56,7 @@
|
|
|
57
56
|
"@babel/preset-react": "^7.24.1",
|
|
58
57
|
"@ls-lint/ls-lint": "^1.10.0",
|
|
59
58
|
"@mapbox/rehype-prism": "^0.8.0",
|
|
60
|
-
"@rollup/plugin-commonjs": "^
|
|
59
|
+
"@rollup/plugin-commonjs": "^28.0.0",
|
|
61
60
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
62
61
|
"c8": "^7.11.2",
|
|
63
62
|
"chai": "^4.3.6",
|
|
@@ -79,7 +78,7 @@
|
|
|
79
78
|
"remark-rehype": "^10.1.0",
|
|
80
79
|
"remark-toc": "^8.0.1",
|
|
81
80
|
"rimraf": "^3.0.2",
|
|
82
|
-
"rollup": "^
|
|
81
|
+
"rollup": "^4.26.0",
|
|
83
82
|
"simple.css": "^0.1.3",
|
|
84
83
|
"unified": "^10.1.2"
|
|
85
84
|
}
|
package/src/jsx-loader.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// https://nodejs.org/api/esm.html#esm_loaders
|
|
3
3
|
import * as acorn from 'acorn';
|
|
4
4
|
import * as walk from 'acorn-walk';
|
|
5
|
-
import { generate } from '
|
|
5
|
+
import { generate } from 'astring';
|
|
6
6
|
import fs from 'fs';
|
|
7
|
+
// ideally we can eventually adopt an ESM compatible version of this plugin
|
|
8
|
+
// https://github.com/acornjs/acorn-jsx/issues/112
|
|
7
9
|
import jsx from '@projectevergreen/acorn-jsx-esm';
|
|
8
10
|
import { parse, parseFragment, serialize } from 'parse5';
|
|
9
|
-
// Need an acorn plugin for now - https://github.com/ProjectEvergreen/greenwood/issues/1218
|
|
10
|
-
import { importAttributes } from 'acorn-import-attributes';
|
|
11
11
|
import { transform } from 'sucrase';
|
|
12
12
|
|
|
13
13
|
const jsxRegex = /\.(jsx)$/;
|
|
@@ -32,7 +32,7 @@ export function getParser(moduleURL) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
return {
|
|
35
|
-
parser: acorn.Parser.extend(jsx()
|
|
35
|
+
parser: acorn.Parser.extend(jsx()),
|
|
36
36
|
config: {
|
|
37
37
|
// https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
|
|
38
38
|
...walk.base,
|
|
@@ -243,7 +243,7 @@ export function parseJsx(moduleURL) {
|
|
|
243
243
|
const hasOwnObservedAttributes = undefined;
|
|
244
244
|
let inferredObservability = false;
|
|
245
245
|
let observedAttributes = [];
|
|
246
|
-
let tree = acorn.Parser.extend(jsx()
|
|
246
|
+
let tree = acorn.Parser.extend(jsx()).parse(result.code, {
|
|
247
247
|
ecmaVersion: 'latest',
|
|
248
248
|
sourceType: 'module'
|
|
249
249
|
});
|
package/src/wcc.js
CHANGED
|
@@ -4,14 +4,30 @@ import './dom-shim.js';
|
|
|
4
4
|
|
|
5
5
|
import * as acorn from 'acorn';
|
|
6
6
|
import * as walk from 'acorn-walk';
|
|
7
|
-
import { generate } from '
|
|
7
|
+
import { generate } from 'astring';
|
|
8
8
|
import { getParser, parseJsx } from './jsx-loader.js';
|
|
9
9
|
import { parse, parseFragment, serialize } from 'parse5';
|
|
10
|
-
// Need an acorn plugin for now - https://github.com/ProjectEvergreen/greenwood/issues/1218
|
|
11
|
-
import { importAttributes } from 'acorn-import-attributes';
|
|
12
10
|
import { transform } from 'sucrase';
|
|
13
11
|
import fs from 'fs';
|
|
14
12
|
|
|
13
|
+
// https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
|
14
|
+
const VOID_ELEMENTS = [
|
|
15
|
+
'area',
|
|
16
|
+
'base',
|
|
17
|
+
'br',
|
|
18
|
+
'col',
|
|
19
|
+
'embed',
|
|
20
|
+
'hr',
|
|
21
|
+
'img',
|
|
22
|
+
'input',
|
|
23
|
+
'link',
|
|
24
|
+
'meta',
|
|
25
|
+
'param', // deprecated
|
|
26
|
+
'source',
|
|
27
|
+
'track',
|
|
28
|
+
'wbr'
|
|
29
|
+
];
|
|
30
|
+
|
|
15
31
|
function getParse(html) {
|
|
16
32
|
return html.indexOf('<html>') >= 0 || html.indexOf('<body>') >= 0 || html.indexOf('<head>') >= 0
|
|
17
33
|
? parse
|
|
@@ -33,17 +49,26 @@ async function renderComponentRoots(tree, definitions) {
|
|
|
33
49
|
|
|
34
50
|
if (definitions[tagName]) {
|
|
35
51
|
const { moduleURL } = definitions[tagName];
|
|
36
|
-
const elementInstance = await initializeCustomElement(moduleURL, tagName, node
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
const elementInstance = await initializeCustomElement(moduleURL, tagName, node, definitions);
|
|
53
|
+
|
|
54
|
+
if (elementInstance) {
|
|
55
|
+
const hasShadow = elementInstance.shadowRoot;
|
|
56
|
+
const elementHtml = hasShadow
|
|
57
|
+
? elementInstance.getInnerHTML({ includeShadowRoots: true })
|
|
58
|
+
: elementInstance.innerHTML;
|
|
59
|
+
const elementTree = parseFragment(elementHtml);
|
|
60
|
+
const hasLight = elementTree.childNodes > 0;
|
|
61
|
+
|
|
62
|
+
node.childNodes = node.childNodes.length === 0 && hasLight && !hasShadow
|
|
63
|
+
? elementTree.childNodes
|
|
64
|
+
: hasShadow
|
|
65
|
+
? [...elementTree.childNodes, ...node.childNodes]
|
|
66
|
+
: elementTree.childNodes;
|
|
67
|
+
} else {
|
|
68
|
+
console.warn(`WARNING: customElement <${tagName}> detected but not serialized. You may not have exported it.`);
|
|
69
|
+
}
|
|
45
70
|
} else {
|
|
46
|
-
console.warn(`WARNING: customElement <${tagName}> is not defined. You may not have imported it
|
|
71
|
+
console.warn(`WARNING: customElement <${tagName}> is not defined. You may not have imported it.`);
|
|
47
72
|
}
|
|
48
73
|
}
|
|
49
74
|
|
|
@@ -73,7 +98,7 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
|
|
|
73
98
|
...walk.base
|
|
74
99
|
};
|
|
75
100
|
|
|
76
|
-
walk.simple(parser.
|
|
101
|
+
walk.simple(parser.parse(result.code, {
|
|
77
102
|
ecmaVersion: 'latest',
|
|
78
103
|
sourceType: 'module'
|
|
79
104
|
}), {
|
|
@@ -82,7 +107,7 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
|
|
|
82
107
|
const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
|
|
83
108
|
const extension = specifier.split('.').pop();
|
|
84
109
|
|
|
85
|
-
//
|
|
110
|
+
// would like to decouple .jsx from the core, ideally
|
|
86
111
|
// https://github.com/ProjectEvergreen/wcc/issues/122
|
|
87
112
|
if (!isBareSpecifier && ['js', 'jsx', 'ts'].includes(extension)) {
|
|
88
113
|
const dependencyModuleURL = new URL(node.source.value, moduleURL);
|
|
@@ -124,7 +149,7 @@ async function getTagName(moduleURL) {
|
|
|
124
149
|
};
|
|
125
150
|
let tagName;
|
|
126
151
|
|
|
127
|
-
walk.simple(parser.
|
|
152
|
+
walk.simple(parser.parse(result.code, {
|
|
128
153
|
ecmaVersion: 'latest',
|
|
129
154
|
sourceType: 'module'
|
|
130
155
|
}), {
|
|
@@ -138,7 +163,41 @@ async function getTagName(moduleURL) {
|
|
|
138
163
|
return tagName;
|
|
139
164
|
}
|
|
140
165
|
|
|
141
|
-
|
|
166
|
+
function renderLightDomChildren(childNodes, iHTML = '') {
|
|
167
|
+
let innerHTML = iHTML;
|
|
168
|
+
|
|
169
|
+
childNodes.forEach((child) => {
|
|
170
|
+
const { nodeName, attrs = [], value } = child;
|
|
171
|
+
|
|
172
|
+
if (nodeName !== '#text') {
|
|
173
|
+
innerHTML += `<${nodeName}`;
|
|
174
|
+
|
|
175
|
+
if (attrs.length > 0) {
|
|
176
|
+
attrs.forEach(attr => {
|
|
177
|
+
innerHTML += ` ${attr.name}="${attr.value}"`;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
innerHTML += '>';
|
|
182
|
+
|
|
183
|
+
if (child.childNodes.length > 0) {
|
|
184
|
+
innerHTML = renderLightDomChildren(child.childNodes, innerHTML);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
innerHTML += VOID_ELEMENTS.includes(nodeName)
|
|
188
|
+
? ''
|
|
189
|
+
: `</${nodeName}>`;
|
|
190
|
+
} else if (nodeName === '#text') {
|
|
191
|
+
innerHTML += value;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return innerHTML;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function initializeCustomElement(elementURL, tagName, node = {}, definitions = [], isEntry, props = {}) {
|
|
199
|
+
const { attrs = [], childNodes = [] } = node;
|
|
200
|
+
|
|
142
201
|
if (!tagName) {
|
|
143
202
|
const depth = isEntry ? 1 : 0;
|
|
144
203
|
registerDependencies(elementURL, definitions, depth);
|
|
@@ -158,6 +217,9 @@ async function initializeCustomElement(elementURL, tagName, attrs = [], definiti
|
|
|
158
217
|
if (element) {
|
|
159
218
|
const elementInstance = new element(data); // eslint-disable-line new-cap
|
|
160
219
|
|
|
220
|
+
// support for HTML (Light DOM) Web Components
|
|
221
|
+
elementInstance.innerHTML = renderLightDomChildren(childNodes);
|
|
222
|
+
|
|
161
223
|
attrs.forEach((attr) => {
|
|
162
224
|
elementInstance.setAttribute(attr.name, attr.value);
|
|
163
225
|
|
|
@@ -207,7 +269,7 @@ async function renderFromHTML(html, elements = []) {
|
|
|
207
269
|
const definitions = [];
|
|
208
270
|
|
|
209
271
|
for (const url of elements) {
|
|
210
|
-
|
|
272
|
+
registerDependencies(url, definitions, 1);
|
|
211
273
|
}
|
|
212
274
|
|
|
213
275
|
const elementTree = getParse(html)(html);
|