wc-compiler 0.3.1 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wc-compiler",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Experimental native Web Components compiler.",
5
5
  "main": "src/wcc.js",
6
6
  "type": "module",
@@ -10,21 +10,23 @@
10
10
  "node": ">=14"
11
11
  },
12
12
  "files": [
13
- "src/"
13
+ "src/",
14
+ "dist/wcc.dist.cjs"
14
15
  ],
15
16
  "publishConfig": {
16
17
  "access": "public"
17
18
  },
18
19
  "scripts": {
20
+ "clean": "rimraf ./dist",
19
21
  "lint": "eslint \"*.*js\" \"./src/**/**/*.js\" \"./test/**/**/*.js\"",
20
22
  "develop": "concurrently \"nodemon --watch src --watch docs -e js,md,css,html ./build.js\" \"http-server ./dist --open\"",
21
23
  "build": "node ./build.js",
22
24
  "serve": "node ./build.js && http-server ./dist --open",
23
- "example:ssg": "node ./examples/ssg.js",
24
- "example:ssr": "node ./examples/ssr.js",
25
25
  "start": "npm run develop",
26
26
  "test": "c8 mocha --parallel",
27
- "test:tdd": "npm run test --watch"
27
+ "test:tdd": "npm run test --watch",
28
+ "dist": "rollup -c rollup.config.js",
29
+ "prepublishOnly": "npm run clean && npm run dist"
28
30
  },
29
31
  "dependencies": {
30
32
  "acorn": "^8.7.0",
@@ -33,6 +35,8 @@
33
35
  },
34
36
  "devDependencies": {
35
37
  "@mapbox/rehype-prism": "^0.8.0",
38
+ "@rollup/plugin-commonjs": "^22.0.0",
39
+ "@rollup/plugin-node-resolve": "^13.3.0",
36
40
  "c8": "^7.11.2",
37
41
  "chai": "^4.3.6",
38
42
  "concurrently": "^7.1.0",
@@ -40,6 +44,7 @@
40
44
  "http-server": "^14.1.0",
41
45
  "jsdom": "^19.0.0",
42
46
  "mocha": "^9.2.2",
47
+ "node-fetch": "^3.2.6",
43
48
  "nodemon": "^2.0.15",
44
49
  "prismjs": "^1.28.0",
45
50
  "rehype-autolink-headings": "^6.1.1",
@@ -49,6 +54,8 @@
49
54
  "remark-parse": "^10.0.1",
50
55
  "remark-rehype": "^10.1.0",
51
56
  "remark-toc": "^8.0.1",
57
+ "rimraf": "^3.0.2",
58
+ "rollup": "^2.75.7",
52
59
  "simple.css": "^0.1.3",
53
60
  "unified": "^10.1.2"
54
61
  }
package/src/wcc.js CHANGED
@@ -4,10 +4,7 @@ import './dom-shim.js';
4
4
  import * as acorn from 'acorn';
5
5
  import * as walk from 'acorn-walk';
6
6
  import { parse, parseFragment, serialize } from 'parse5';
7
-
8
- import fs from 'node:fs/promises';
9
-
10
- let definitions;
7
+ import fs from 'fs';
11
8
 
12
9
  function getParse(html) {
13
10
  return html.indexOf('<html>') >= 0 || html.indexOf('<body>') >= 0 || html.indexOf('<head>') >= 0
@@ -23,53 +20,58 @@ function isCustomElementDefinitionNode(node) {
23
20
  && expression.callee.property.name === 'define';
24
21
  }
25
22
 
26
- async function renderComponentRoots(tree) {
23
+ async function renderComponentRoots(tree, definitions) {
27
24
  for (const node of tree.childNodes) {
28
25
  if (node.tagName && node.tagName.indexOf('-') > 0) {
29
26
  const { tagName } = node;
30
- const { moduleURL } = definitions[tagName];
31
- const elementInstance = await initializeCustomElement(moduleURL, tagName, node.attrs);
32
- const elementHtml = elementInstance.shadowRoot
33
- ? elementInstance.getInnerHTML({ includeShadowRoots: true })
34
- : elementInstance.innerHTML;
35
- const elementTree = parseFragment(elementHtml);
36
-
37
- node.childNodes = node.childNodes.length === 0
38
- ? elementTree.childNodes
39
- : [...elementTree.childNodes, ...node.childNodes];
27
+
28
+ if (definitions[tagName]) {
29
+ const { moduleURL } = definitions[tagName];
30
+ const elementInstance = await initializeCustomElement(moduleURL, tagName, node.attrs, definitions);
31
+ const elementHtml = elementInstance.shadowRoot
32
+ ? elementInstance.getInnerHTML({ includeShadowRoots: true })
33
+ : elementInstance.innerHTML;
34
+ const elementTree = parseFragment(elementHtml);
35
+
36
+ node.childNodes = node.childNodes.length === 0
37
+ ? elementTree.childNodes
38
+ : [...elementTree.childNodes, ...node.childNodes];
39
+ } else {
40
+ console.warn(`WARNING: customElement <${tagName}> is not defined. You may not have imported it yet.`);
41
+ }
40
42
  }
41
43
 
42
44
  if (node.childNodes && node.childNodes.length > 0) {
43
- await renderComponentRoots(node);
45
+ await renderComponentRoots(node, definitions);
44
46
  }
45
47
 
46
48
  // does this only apply to `<template>` tags?
47
49
  if (node.content && node.content.childNodes && node.content.childNodes.length > 0) {
48
- await renderComponentRoots(node.content);
50
+ await renderComponentRoots(node.content, definitions);
49
51
  }
50
52
  }
51
53
 
52
54
  return tree;
53
55
  }
54
56
 
55
- async function registerDependencies(moduleURL) {
56
- const moduleContents = await fs.readFile(moduleURL, 'utf-8');
57
+ function registerDependencies(moduleURL, definitions) {
58
+ const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
57
59
 
58
60
  walk.simple(acorn.parse(moduleContents, {
59
61
  ecmaVersion: 'latest',
60
62
  sourceType: 'module'
61
63
  }), {
62
- async ImportDeclaration(node) {
64
+ ImportDeclaration(node) {
63
65
  const specifier = node.source.value;
64
66
  const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
65
67
 
66
68
  if (!isBareSpecifier) {
67
69
  const dependencyModuleURL = new URL(node.source.value, moduleURL);
68
70
 
69
- await registerDependencies(dependencyModuleURL);
71
+ registerDependencies(dependencyModuleURL, definitions);
70
72
  }
71
73
  },
72
- async ExpressionStatement(node) {
74
+ ExpressionStatement(node) {
73
75
  if (isCustomElementDefinitionNode(node)) {
74
76
  const { arguments: args } = node.expression;
75
77
  const tagName = args[0].value;
@@ -84,14 +86,14 @@ async function registerDependencies(moduleURL) {
84
86
  }
85
87
 
86
88
  async function getTagName(moduleURL) {
87
- const moduleContents = await fs.readFile(moduleURL, 'utf-8');
89
+ const moduleContents = await fs.promises.readFile(moduleURL, 'utf-8');
88
90
  let tagName;
89
91
 
90
92
  walk.simple(acorn.parse(moduleContents, {
91
93
  ecmaVersion: 'latest',
92
94
  sourceType: 'module'
93
95
  }), {
94
- async ExpressionStatement(node) {
96
+ ExpressionStatement(node) {
95
97
  if (isCustomElementDefinitionNode(node)) {
96
98
 
97
99
  tagName = node.expression.arguments[0].value;
@@ -102,13 +104,15 @@ async function getTagName(moduleURL) {
102
104
  return tagName;
103
105
  }
104
106
 
105
- async function initializeCustomElement(elementURL, tagName, attrs = []) {
106
- await registerDependencies(elementURL);
107
+ async function initializeCustomElement(elementURL, tagName, attrs = [], definitions = []) {
108
+ registerDependencies(elementURL, definitions);
107
109
 
110
+ // https://github.com/ProjectEvergreen/wcc/pull/67/files#r902061804
111
+ const { pathname } = elementURL;
108
112
  const element = tagName
109
113
  ? customElements.get(tagName)
110
- : (await import(elementURL)).default;
111
- const dataLoader = (await import(elementURL)).getData;
114
+ : (await import(pathname)).default;
115
+ const dataLoader = (await import(pathname)).getData;
112
116
  const data = dataLoader ? await dataLoader() : {};
113
117
  const elementInstance = new element(data); // eslint-disable-line new-cap
114
118
 
@@ -126,16 +130,15 @@ async function initializeCustomElement(elementURL, tagName, attrs = []) {
126
130
  }
127
131
 
128
132
  async function renderToString(elementURL) {
129
- definitions = [];
130
-
133
+ const definitions = [];
131
134
  const elementTagName = await getTagName(elementURL);
132
- const elementInstance = await initializeCustomElement(elementURL);
135
+ const elementInstance = await initializeCustomElement(elementURL, undefined, undefined, definitions);
133
136
 
134
137
  const elementHtml = elementInstance.shadowRoot
135
138
  ? elementInstance.getInnerHTML({ includeShadowRoots: true })
136
139
  : elementInstance.innerHTML;
137
140
  const elementTree = getParse(elementHtml)(elementHtml);
138
- const finalTree = await renderComponentRoots(elementTree);
141
+ const finalTree = await renderComponentRoots(elementTree, definitions);
139
142
  const html = elementTagName ? `
140
143
  <${elementTagName}>
141
144
  ${serialize(finalTree)}
@@ -150,14 +153,14 @@ async function renderToString(elementURL) {
150
153
  }
151
154
 
152
155
  async function renderFromHTML(html, elements = []) {
153
- definitions = [];
156
+ const definitions = [];
154
157
 
155
158
  for (const url of elements) {
156
- await initializeCustomElement(url);
159
+ await initializeCustomElement(url, undefined, undefined, definitions);
157
160
  }
158
161
 
159
162
  const elementTree = getParse(html)(html);
160
- const finalTree = await renderComponentRoots(elementTree);
163
+ const finalTree = await renderComponentRoots(elementTree, definitions);
161
164
 
162
165
  return {
163
166
  html: serialize(finalTree),