wc-compiler 0.4.0 → 0.6.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 +4 -4
- package/dist/{wcc.dist.js → wcc.dist.cjs} +14029 -96
- package/package.json +12 -8
- package/src/dom-shim.js +55 -58
- package/src/jsx-loader.js +273 -0
- package/src/wcc.js +62 -38
package/src/wcc.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
/* eslint-disable max-depth */
|
|
1
2
|
// this must come first
|
|
2
3
|
import './dom-shim.js';
|
|
3
4
|
|
|
4
5
|
import * as acorn from 'acorn';
|
|
5
6
|
import * as walk from 'acorn-walk';
|
|
7
|
+
import escodegen from 'escodegen';
|
|
8
|
+
import { getParser, parseJsx } from './jsx-loader.js';
|
|
6
9
|
import { parse, parseFragment, serialize } from 'parse5';
|
|
7
|
-
import fs from 'fs
|
|
8
|
-
|
|
9
|
-
let definitions;
|
|
10
|
+
import fs from 'fs';
|
|
10
11
|
|
|
11
12
|
function getParse(html) {
|
|
12
13
|
return html.indexOf('<html>') >= 0 || html.indexOf('<body>') >= 0 || html.indexOf('<head>') >= 0
|
|
@@ -22,87 +23,110 @@ function isCustomElementDefinitionNode(node) {
|
|
|
22
23
|
&& expression.callee.property.name === 'define';
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
async function renderComponentRoots(tree) {
|
|
26
|
+
async function renderComponentRoots(tree, definitions) {
|
|
26
27
|
for (const node of tree.childNodes) {
|
|
27
28
|
if (node.tagName && node.tagName.indexOf('-') > 0) {
|
|
28
29
|
const { tagName } = node;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
|
|
31
|
+
if (definitions[tagName]) {
|
|
32
|
+
const { moduleURL } = definitions[tagName];
|
|
33
|
+
const elementInstance = await initializeCustomElement(moduleURL, tagName, node.attrs, definitions);
|
|
34
|
+
const elementHtml = elementInstance.shadowRoot
|
|
35
|
+
? elementInstance.getInnerHTML({ includeShadowRoots: true })
|
|
36
|
+
: elementInstance.innerHTML;
|
|
37
|
+
const elementTree = parseFragment(elementHtml);
|
|
38
|
+
|
|
39
|
+
node.childNodes = node.childNodes.length === 0
|
|
40
|
+
? elementTree.childNodes
|
|
41
|
+
: [...elementTree.childNodes, ...node.childNodes];
|
|
42
|
+
} else {
|
|
43
|
+
console.warn(`WARNING: customElement <${tagName}> is not defined. You may not have imported it yet.`);
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
if (node.childNodes && node.childNodes.length > 0) {
|
|
42
|
-
await renderComponentRoots(node);
|
|
48
|
+
await renderComponentRoots(node, definitions);
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
// does this only apply to `<template>` tags?
|
|
46
52
|
if (node.content && node.content.childNodes && node.content.childNodes.length > 0) {
|
|
47
|
-
await renderComponentRoots(node.content);
|
|
53
|
+
await renderComponentRoots(node.content, definitions);
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
return tree;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
const moduleContents =
|
|
60
|
+
function registerDependencies(moduleURL, definitions, depth = 0) {
|
|
61
|
+
const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
|
|
62
|
+
const nextDepth = depth += 1;
|
|
63
|
+
const customParser = getParser(moduleURL);
|
|
64
|
+
const parser = customParser ? customParser.parser : acorn;
|
|
65
|
+
const config = customParser ? customParser.config : {
|
|
66
|
+
...walk.base
|
|
67
|
+
};
|
|
56
68
|
|
|
57
|
-
walk.simple(
|
|
69
|
+
walk.simple(parser.parse(moduleContents, {
|
|
58
70
|
ecmaVersion: 'latest',
|
|
59
71
|
sourceType: 'module'
|
|
60
72
|
}), {
|
|
61
|
-
|
|
73
|
+
ImportDeclaration(node) {
|
|
62
74
|
const specifier = node.source.value;
|
|
63
75
|
const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
|
|
64
76
|
|
|
65
77
|
if (!isBareSpecifier) {
|
|
66
78
|
const dependencyModuleURL = new URL(node.source.value, moduleURL);
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
registerDependencies(dependencyModuleURL, definitions, nextDepth);
|
|
69
81
|
}
|
|
70
82
|
},
|
|
71
|
-
|
|
83
|
+
ExpressionStatement(node) {
|
|
72
84
|
if (isCustomElementDefinitionNode(node)) {
|
|
73
85
|
const { arguments: args } = node.expression;
|
|
74
86
|
const tagName = args[0].value;
|
|
87
|
+
const tree = parseJsx(moduleURL);
|
|
88
|
+
const isEntry = nextDepth - 1 === 1;
|
|
75
89
|
|
|
76
90
|
definitions[tagName] = {
|
|
77
91
|
instanceName: args[1].name,
|
|
78
|
-
moduleURL
|
|
92
|
+
moduleURL,
|
|
93
|
+
source: escodegen.generate(tree),
|
|
94
|
+
url: moduleURL,
|
|
95
|
+
isEntry
|
|
79
96
|
};
|
|
80
97
|
}
|
|
81
98
|
}
|
|
82
|
-
});
|
|
99
|
+
}, config);
|
|
83
100
|
}
|
|
84
101
|
|
|
85
102
|
async function getTagName(moduleURL) {
|
|
86
|
-
const moduleContents = await fs.readFile(moduleURL, 'utf-8');
|
|
103
|
+
const moduleContents = await fs.promises.readFile(moduleURL, 'utf-8');
|
|
104
|
+
const customParser = getParser(moduleURL);
|
|
105
|
+
const parser = customParser ? customParser.parser : acorn;
|
|
106
|
+
const config = customParser ? customParser.config : {
|
|
107
|
+
...walk.base
|
|
108
|
+
};
|
|
87
109
|
let tagName;
|
|
88
110
|
|
|
89
|
-
walk.simple(
|
|
111
|
+
walk.simple(parser.parse(moduleContents, {
|
|
90
112
|
ecmaVersion: 'latest',
|
|
91
113
|
sourceType: 'module'
|
|
92
114
|
}), {
|
|
93
|
-
|
|
115
|
+
ExpressionStatement(node) {
|
|
94
116
|
if (isCustomElementDefinitionNode(node)) {
|
|
95
|
-
|
|
96
117
|
tagName = node.expression.arguments[0].value;
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
|
-
});
|
|
120
|
+
}, config);
|
|
100
121
|
|
|
101
122
|
return tagName;
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
async function initializeCustomElement(elementURL, tagName, attrs = []) {
|
|
105
|
-
|
|
125
|
+
async function initializeCustomElement(elementURL, tagName, attrs = [], definitions = [], isEntry) {
|
|
126
|
+
if (!tagName) {
|
|
127
|
+
const depth = isEntry ? 1 : 0;
|
|
128
|
+
registerDependencies(elementURL, definitions, depth);
|
|
129
|
+
}
|
|
106
130
|
|
|
107
131
|
// https://github.com/ProjectEvergreen/wcc/pull/67/files#r902061804
|
|
108
132
|
const { pathname } = elementURL;
|
|
@@ -127,16 +151,16 @@ async function initializeCustomElement(elementURL, tagName, attrs = []) {
|
|
|
127
151
|
}
|
|
128
152
|
|
|
129
153
|
async function renderToString(elementURL) {
|
|
130
|
-
definitions = [];
|
|
131
|
-
|
|
154
|
+
const definitions = [];
|
|
132
155
|
const elementTagName = await getTagName(elementURL);
|
|
133
|
-
const
|
|
156
|
+
const isEntry = !!elementTagName;
|
|
157
|
+
const elementInstance = await initializeCustomElement(elementURL, undefined, undefined, definitions, isEntry);
|
|
134
158
|
|
|
135
159
|
const elementHtml = elementInstance.shadowRoot
|
|
136
160
|
? elementInstance.getInnerHTML({ includeShadowRoots: true })
|
|
137
161
|
: elementInstance.innerHTML;
|
|
138
162
|
const elementTree = getParse(elementHtml)(elementHtml);
|
|
139
|
-
const finalTree = await renderComponentRoots(elementTree);
|
|
163
|
+
const finalTree = await renderComponentRoots(elementTree, definitions);
|
|
140
164
|
const html = elementTagName ? `
|
|
141
165
|
<${elementTagName}>
|
|
142
166
|
${serialize(finalTree)}
|
|
@@ -151,14 +175,14 @@ async function renderToString(elementURL) {
|
|
|
151
175
|
}
|
|
152
176
|
|
|
153
177
|
async function renderFromHTML(html, elements = []) {
|
|
154
|
-
definitions = [];
|
|
178
|
+
const definitions = [];
|
|
155
179
|
|
|
156
180
|
for (const url of elements) {
|
|
157
|
-
await initializeCustomElement(url);
|
|
181
|
+
await initializeCustomElement(url, undefined, undefined, definitions, true);
|
|
158
182
|
}
|
|
159
183
|
|
|
160
184
|
const elementTree = getParse(html)(html);
|
|
161
|
-
const finalTree = await renderComponentRoots(elementTree);
|
|
185
|
+
const finalTree = await renderComponentRoots(elementTree, definitions);
|
|
162
186
|
|
|
163
187
|
return {
|
|
164
188
|
html: serialize(finalTree),
|