wc-compiler 0.2.2 → 0.3.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 +27 -43
- package/package.json +5 -2
- package/src/wcc.js +19 -19
package/README.md
CHANGED
|
@@ -1,44 +1,17 @@
|
|
|
1
|
-
# wcc
|
|
2
|
-
|
|
3
1
|
<img src="https://merry-caramel-524e61.netlify.app/assets/wcc-logo.png" width="30%"/>
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
**Web Components Compiler (WCC)** is a NodeJS package designed to make server-side rendering (SSR) of native Web Components easier. It can render (within reason 😅) your Web Component into static HTML leveraging [Declarative Shadow DOM](https://web.dev/declarative-shadow-dom/).
|
|
10
|
-
|
|
11
|
-
It is not a static site generator or framework. It is focused on producing raw HTML from Web Components with the intent of being easily _integrated_ into a site generator or framework.
|
|
12
|
-
|
|
13
|
-
> _The original motivation for this project was to create a [purpose built, lighter weight alternative to puppeteer for SSR of native `HTMLElement` based Web Components](https://github.com/ProjectEvergreen/greenwood/issues/935) for the project [**Greenwood**](https://www.greenwoodjs.io/)._
|
|
14
|
-
|
|
15
|
-
In addition, WCC hopes to provide a surface area to explore patterns around [streaming](https://github.com/ProjectEvergreen/wcc/issues/5) and serverless rendering, as well as acting as a test bed for the [Web Components Community Groups](https://github.com/webcomponents-cg) discussions around community protocols, like [hydration](https://github.com/ProjectEvergreen/wcc/issues/3).
|
|
16
|
-
|
|
17
|
-
## Key Features
|
|
3
|
+
# Web Components Compiler (WCC)
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- `innerHTML`
|
|
24
|
-
- `[get|set|has]Attribute`
|
|
25
|
-
1. Recursive rendering of nested custom elements
|
|
26
|
-
1. Optional Declarative Shadow DOM (for producing purely content driven static pages)
|
|
27
|
-
1. Metadata and runtime hints to support progressive hydration and lazy loading strategies
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
**wcc** can be installed from npm.
|
|
32
|
-
|
|
33
|
-
```shell
|
|
34
|
-
$ npm install wc-compiler --save-dev
|
|
35
|
-
```
|
|
5
|
+
[](https://app.netlify.com/sites/merry-caramel-524e61/deploys)
|
|
6
|
+
[](https://github.com/ProjectEvergreen/wcc/tags)
|
|
7
|
+

|
|
8
|
+
[](https://raw.githubusercontent.com/ProjectEvergreen/wcc/master/LICENSE.md)
|
|
36
9
|
|
|
37
|
-
|
|
10
|
+
> _Experimental Web Components compiler. It's Web Components all the way down!_ 🐢
|
|
38
11
|
|
|
39
|
-
|
|
12
|
+
## How It Works
|
|
40
13
|
|
|
41
|
-
1.
|
|
14
|
+
1. Write a Web Component
|
|
42
15
|
```js
|
|
43
16
|
const template = document.createElement('template');
|
|
44
17
|
|
|
@@ -68,17 +41,13 @@ WCC exposes a few utilities to render your Web Components. Below is one example
|
|
|
68
41
|
|
|
69
42
|
customElements.define('wcc-footer', Footer);
|
|
70
43
|
```
|
|
71
|
-
|
|
72
|
-
1. Using NodeJS, create a file that imports `renderToString` and provide it the path to your web component
|
|
44
|
+
1. Run it through the compiler
|
|
73
45
|
```js
|
|
74
46
|
import { renderToString } from 'wc-compiler';
|
|
75
47
|
|
|
76
|
-
const { html } = await renderToString(new URL('./path/to/
|
|
77
|
-
|
|
78
|
-
console.debug({ html })
|
|
48
|
+
const { html } = await renderToString(new URL('./path/to/component.js', import.meta.url));
|
|
79
49
|
```
|
|
80
|
-
|
|
81
|
-
1. You will get the following HTML output that can be used in conjunction with your preferred site framework or templating solution.
|
|
50
|
+
1. Get HTML!
|
|
82
51
|
```html
|
|
83
52
|
<wcc-footer>
|
|
84
53
|
<template shadowroot="open">
|
|
@@ -96,5 +65,20 @@ WCC exposes a few utilities to render your Web Components. Below is one example
|
|
|
96
65
|
</wcc-footer>
|
|
97
66
|
```
|
|
98
67
|
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
**WCC** runs on NodeJS and can be installed from npm.
|
|
71
|
+
|
|
72
|
+
```shell
|
|
73
|
+
$ npm install wc-compiler --save-dev
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Documentation
|
|
77
|
+
|
|
78
|
+
See our [website](https://merry-caramel-524e61.netlify.app/) for API docs and examples.
|
|
79
|
+
|
|
80
|
+
## Motivation
|
|
81
|
+
|
|
82
|
+
**WCC** is not a static site generator, framework or bundler. It is focused on producing raw HTML from Web Components with the intent of being easily integrated into a site generator or framework, like [**Greenwood**](https://github.com/ProjectEvergreen/greenwood/), the original motivation for creating [this project](https://github.com/ProjectEvergreen/greenwood/issues/935).
|
|
99
83
|
|
|
100
|
-
|
|
84
|
+
In addition, **WCC** hopes to provide a surface area to explore patterns around [streaming](https://github.com/ProjectEvergreen/wcc/issues/5) and serverless rendering, as well as acting as a test bed for the [Web Components Community Groups](https://github.com/webcomponents-cg) discussions around community protocols, like [hydration](https://github.com/ProjectEvergreen/wcc/issues/3).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wc-compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Experimental native Web Components compiler.",
|
|
5
5
|
"main": "src/wcc.js",
|
|
6
6
|
"type": "module",
|
|
@@ -42,11 +42,14 @@
|
|
|
42
42
|
"mocha": "^9.2.2",
|
|
43
43
|
"nodemon": "^2.0.15",
|
|
44
44
|
"prismjs": "^1.28.0",
|
|
45
|
-
"
|
|
45
|
+
"rehype-autolink-headings": "^6.1.1",
|
|
46
46
|
"rehype-raw": "^6.1.1",
|
|
47
|
+
"rehype-slug": "^5.0.1",
|
|
47
48
|
"rehype-stringify": "^9.0.3",
|
|
48
49
|
"remark-parse": "^10.0.1",
|
|
49
50
|
"remark-rehype": "^10.1.0",
|
|
51
|
+
"remark-toc": "^8.0.1",
|
|
52
|
+
"simple.css": "^0.1.3",
|
|
50
53
|
"unified": "^10.1.2"
|
|
51
54
|
}
|
|
52
55
|
}
|
package/src/wcc.js
CHANGED
|
@@ -23,26 +23,29 @@ function isCustomElementDefinitionNode(node) {
|
|
|
23
23
|
&& expression.callee.property.name === 'define';
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
async function renderComponentRoots(tree
|
|
26
|
+
async function renderComponentRoots(tree) {
|
|
27
27
|
for (const node of tree.childNodes) {
|
|
28
28
|
if (node.tagName && node.tagName.indexOf('-') > 0) {
|
|
29
29
|
const { tagName } = node;
|
|
30
30
|
const { moduleURL } = definitions[tagName];
|
|
31
31
|
const elementInstance = await initializeCustomElement(moduleURL, tagName, node.attrs);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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];
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
if (node.childNodes && node.childNodes.length > 0) {
|
|
40
|
-
await renderComponentRoots(node
|
|
43
|
+
await renderComponentRoots(node);
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
// does this only apply to `<template>` tags?
|
|
44
47
|
if (node.content && node.content.childNodes && node.content.childNodes.length > 0) {
|
|
45
|
-
await renderComponentRoots(node.content
|
|
48
|
+
await renderComponentRoots(node.content);
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -122,18 +125,18 @@ async function initializeCustomElement(elementURL, tagName, attrs = []) {
|
|
|
122
125
|
return elementInstance;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
async function renderToString(elementURL
|
|
128
|
+
async function renderToString(elementURL) {
|
|
126
129
|
definitions = [];
|
|
127
130
|
|
|
128
|
-
const { lightMode = false } = options;
|
|
129
|
-
const includeShadowRoots = !lightMode;
|
|
130
131
|
const elementTagName = await getTagName(elementURL);
|
|
131
132
|
const elementInstance = await initializeCustomElement(elementURL);
|
|
132
133
|
|
|
133
|
-
const elementHtml = elementInstance.
|
|
134
|
+
const elementHtml = elementInstance.shadowRoot
|
|
135
|
+
? elementInstance.getInnerHTML({ includeShadowRoots: true })
|
|
136
|
+
: elementInstance.innerHTML;
|
|
134
137
|
const elementTree = getParse(elementHtml)(elementHtml);
|
|
135
|
-
const finalTree = await renderComponentRoots(elementTree
|
|
136
|
-
const html =
|
|
138
|
+
const finalTree = await renderComponentRoots(elementTree);
|
|
139
|
+
const html = elementTagName ? `
|
|
137
140
|
<${elementTagName}>
|
|
138
141
|
${serialize(finalTree)}
|
|
139
142
|
</${elementTagName}>
|
|
@@ -146,18 +149,15 @@ async function renderToString(elementURL, options = {}) {
|
|
|
146
149
|
};
|
|
147
150
|
}
|
|
148
151
|
|
|
149
|
-
async function renderFromHTML(html, elements = []
|
|
152
|
+
async function renderFromHTML(html, elements = []) {
|
|
150
153
|
definitions = [];
|
|
151
154
|
|
|
152
|
-
const { lightMode = false } = options;
|
|
153
|
-
const includeShadowRoots = !lightMode;
|
|
154
|
-
|
|
155
155
|
for (const url of elements) {
|
|
156
156
|
await initializeCustomElement(url);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
const elementTree = getParse(html)(html);
|
|
160
|
-
const finalTree = await renderComponentRoots(elementTree
|
|
160
|
+
const finalTree = await renderComponentRoots(elementTree);
|
|
161
161
|
|
|
162
162
|
return {
|
|
163
163
|
html: serialize(finalTree),
|