cem-plugin-wrec 0.1.4 → 0.2.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/dev.js +12 -12
- package/fixtures/hello-world/actual.json +61 -0
- package/fixtures/hello-world/expected.json +61 -0
- package/fixtures/hello-world/sourcecode/hello-world.js +28 -0
- package/fixtures/my-counter/actual.json +12 -0
- package/fixtures/{default → my-counter}/expected.json +9 -10
- package/fixtures/my-counter/sourcecode/my-counter.js +43 -0
- package/index.js +22 -14
- package/my-counter.js +25 -28
- package/package.json +3 -2
- package/test/integration.test.js +23 -29
- package/fixtures/default/actual.json +0 -39
- package/fixtures/default/sourcecode/default.js +0 -6
package/dev.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import ts from
|
|
3
|
-
import { create } from
|
|
4
|
-
import myPlugin from
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import { create } from "@custom-elements-manifest/analyzer/src/create.js";
|
|
4
|
+
import myPlugin from "./index.js";
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const name = "my-counter";
|
|
7
|
+
const file = `${name}.js`;
|
|
8
|
+
const path = `fixtures/${name}/sourcecode/${file}`;
|
|
9
|
+
const code = fs.readFileSync(path).toString();
|
|
7
10
|
|
|
8
|
-
const modules = [ts.createSourceFile(
|
|
9
|
-
'my-element.js',
|
|
10
|
-
code,
|
|
11
|
-
ts.ScriptTarget.ES2015,
|
|
12
|
-
true,
|
|
13
|
-
)];
|
|
11
|
+
const modules = [ts.createSourceFile(file, code, ts.ScriptTarget.ES2015, true)];
|
|
14
12
|
|
|
15
|
-
console.log(
|
|
13
|
+
console.log(
|
|
14
|
+
JSON.stringify(create({ modules, plugins: [myPlugin()] }), null, 2),
|
|
15
|
+
);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "hello-world.js",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "class",
|
|
11
|
+
"description": "",
|
|
12
|
+
"name": "HelloWorld",
|
|
13
|
+
"members": [
|
|
14
|
+
{
|
|
15
|
+
"kind": "field",
|
|
16
|
+
"name": "#name",
|
|
17
|
+
"privacy": "private",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "string"
|
|
20
|
+
},
|
|
21
|
+
"default": "\"World\""
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "field",
|
|
25
|
+
"name": "#p",
|
|
26
|
+
"privacy": "private"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"attributes": [
|
|
30
|
+
{
|
|
31
|
+
"name": "name"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"superclass": {
|
|
35
|
+
"name": "HTMLElement"
|
|
36
|
+
},
|
|
37
|
+
"tagName": "hello-world",
|
|
38
|
+
"customElement": true
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"exports": [
|
|
42
|
+
{
|
|
43
|
+
"kind": "js",
|
|
44
|
+
"name": "HelloWorld",
|
|
45
|
+
"declaration": {
|
|
46
|
+
"name": "HelloWorld",
|
|
47
|
+
"module": "hello-world.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"kind": "custom-element-definition",
|
|
52
|
+
"name": "hello-world",
|
|
53
|
+
"declaration": {
|
|
54
|
+
"name": "HelloWorld",
|
|
55
|
+
"module": "hello-world.js"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "hello-world.js",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "class",
|
|
11
|
+
"description": "",
|
|
12
|
+
"name": "HelloWorld",
|
|
13
|
+
"members": [
|
|
14
|
+
{
|
|
15
|
+
"kind": "field",
|
|
16
|
+
"name": "#name",
|
|
17
|
+
"privacy": "private",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "string"
|
|
20
|
+
},
|
|
21
|
+
"default": "\"World\""
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "field",
|
|
25
|
+
"name": "#p",
|
|
26
|
+
"privacy": "private"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"attributes": [
|
|
30
|
+
{
|
|
31
|
+
"name": "name"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"superclass": {
|
|
35
|
+
"name": "HTMLElement"
|
|
36
|
+
},
|
|
37
|
+
"tagName": "hello-world",
|
|
38
|
+
"customElement": true
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"exports": [
|
|
42
|
+
{
|
|
43
|
+
"kind": "js",
|
|
44
|
+
"name": "HelloWorld",
|
|
45
|
+
"declaration": {
|
|
46
|
+
"name": "HelloWorld",
|
|
47
|
+
"module": "hello-world.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"kind": "custom-element-definition",
|
|
52
|
+
"name": "hello-world",
|
|
53
|
+
"declaration": {
|
|
54
|
+
"name": "HelloWorld",
|
|
55
|
+
"module": "hello-world.js"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class HelloWorld extends HTMLElement {
|
|
2
|
+
static get observedAttributes() {
|
|
3
|
+
return ["name"];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
#name = "World";
|
|
7
|
+
#p = document.createElement("p");
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.attachShadow({ mode: "open" });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
this.#p.textContent = `Hello, ${this.#name}!`;
|
|
16
|
+
this.shadowRoot.replaceChild(this.#p);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
20
|
+
console.log("attributeChangedCallback", name, oldValue, newValue);
|
|
21
|
+
if (name === "name") {
|
|
22
|
+
this.#name = newValue;
|
|
23
|
+
this.#p.textContent = `Hello, ${this.#name}!`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
customElements.define("hello-world", HelloWorld);
|
|
@@ -4,22 +4,21 @@
|
|
|
4
4
|
"modules": [
|
|
5
5
|
{
|
|
6
6
|
"kind": "javascript-module",
|
|
7
|
-
"path": "my-
|
|
7
|
+
"path": "my-counter.js",
|
|
8
8
|
"declarations": [
|
|
9
9
|
{
|
|
10
10
|
"kind": "class",
|
|
11
11
|
"description": "",
|
|
12
|
-
"name": "
|
|
12
|
+
"name": "MyCounter",
|
|
13
13
|
"members": [
|
|
14
14
|
{
|
|
15
15
|
"kind": "field",
|
|
16
|
-
"name": "
|
|
17
|
-
"default": ""
|
|
18
|
-
"foo": "Some custom information!"
|
|
16
|
+
"name": "count",
|
|
17
|
+
"default": "0"
|
|
19
18
|
}
|
|
20
19
|
],
|
|
21
20
|
"superclass": {
|
|
22
|
-
"name": "
|
|
21
|
+
"name": "Wrec"
|
|
23
22
|
},
|
|
24
23
|
"customElement": true
|
|
25
24
|
}
|
|
@@ -27,13 +26,13 @@
|
|
|
27
26
|
"exports": [
|
|
28
27
|
{
|
|
29
28
|
"kind": "js",
|
|
30
|
-
"name": "
|
|
29
|
+
"name": "MyCounter",
|
|
31
30
|
"declaration": {
|
|
32
|
-
"name": "
|
|
33
|
-
"module": "my-
|
|
31
|
+
"name": "MyCounter",
|
|
32
|
+
"module": "my-counter.js"
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
]
|
|
37
36
|
}
|
|
38
37
|
]
|
|
39
|
-
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { css, html, Wrec } from "wrec";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is a counter web component implemented with wrec.
|
|
5
|
+
*/
|
|
6
|
+
class MyCounter extends Wrec {
|
|
7
|
+
static properties = {
|
|
8
|
+
count: { doc: "initial value", type: Number, reflect: true, value: 0 },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
static css = css`
|
|
12
|
+
.counter {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 0.5rem;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
button {
|
|
19
|
+
background-color: lightgreen;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
button:disabled {
|
|
23
|
+
background-color: gray;
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
static html = html`
|
|
28
|
+
<div>
|
|
29
|
+
<button onClick="decrement" type="button" disabled="this.count === 0">
|
|
30
|
+
-
|
|
31
|
+
</button>
|
|
32
|
+
<span>this.count</span>
|
|
33
|
+
<button onClick="this.count++" type="button">+</button>
|
|
34
|
+
<span>(this.count < 10 ? "single" : "double") + " digit"</span>
|
|
35
|
+
</div>
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
decrement() {
|
|
39
|
+
if (this.count > 0) this.count--;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
MyCounter.register();
|
package/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
//TODO: Does this support JSDoc comment attributes like @attr by default?
|
|
2
1
|
export default function wrecPlugin() {
|
|
3
2
|
const MEMBERS_TO_HIDE = new Set(["css", "html", "properties"]);
|
|
4
3
|
|
|
5
4
|
let currentClass;
|
|
6
5
|
let isStatic = false;
|
|
7
|
-
let Kind = {};
|
|
8
6
|
let propertyName = "";
|
|
9
7
|
|
|
10
|
-
function nodeValue(node) {
|
|
8
|
+
function nodeValue(Kind, node) {
|
|
11
9
|
const { initializer } = node;
|
|
12
10
|
switch (initializer.kind) {
|
|
13
11
|
case Kind.Identifier:
|
|
@@ -38,8 +36,8 @@ export default function wrecPlugin() {
|
|
|
38
36
|
|
|
39
37
|
// Runs for each module
|
|
40
38
|
analyzePhase({ ts, node, moduleDoc, context }) {
|
|
41
|
-
Kind
|
|
42
|
-
|
|
39
|
+
// All property constant values of Kind are documented in SyntaxKind.md.
|
|
40
|
+
const Kind = ts.SyntaxKind;
|
|
43
41
|
switch (node.kind) {
|
|
44
42
|
case Kind.ClassDeclaration:
|
|
45
43
|
const className = node.name.getText();
|
|
@@ -81,7 +79,7 @@ export default function wrecPlugin() {
|
|
|
81
79
|
if (initializer.kind === Kind.ObjectLiteralExpression) {
|
|
82
80
|
for (const property2 of initializer.properties) {
|
|
83
81
|
const name2 = property2.name.getText();
|
|
84
|
-
const value2 = nodeValue(property2);
|
|
82
|
+
const value2 = nodeValue(Kind, property2);
|
|
85
83
|
if (name2 === "doc") doc = value2;
|
|
86
84
|
if (name2 === "type") type = value2;
|
|
87
85
|
if (name2 === "value") value = value2;
|
|
@@ -89,13 +87,22 @@ export default function wrecPlugin() {
|
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
currentClass.attributes.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
90
|
+
const attribute = currentClass.attributes.find(
|
|
91
|
+
(obj) => obj.name === name,
|
|
92
|
+
);
|
|
93
|
+
if (attribute) {
|
|
94
|
+
attribute.default = value;
|
|
95
|
+
attribute.description = doc;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const member = currentClass.members.find(
|
|
99
|
+
(obj) => obj.name === name,
|
|
100
|
+
);
|
|
101
|
+
if (member) {
|
|
102
|
+
member.default = value;
|
|
103
|
+
member.description = doc;
|
|
104
|
+
member.reflects = true;
|
|
105
|
+
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
isStatic = false;
|
|
@@ -113,7 +120,8 @@ export default function wrecPlugin() {
|
|
|
113
120
|
}
|
|
114
121
|
},
|
|
115
122
|
|
|
116
|
-
// Runs for each module
|
|
123
|
+
// Runs for each module. After analyzing,
|
|
124
|
+
// all information about your module should now be available.
|
|
117
125
|
moduleLinkPhase({ moduleDoc, context }) {
|
|
118
126
|
const classes = moduleDoc?.declarations?.filter(
|
|
119
127
|
(declaration) => declaration.kind === "class",
|
package/my-counter.js
CHANGED
|
@@ -1,42 +1,39 @@
|
|
|
1
|
-
import { Wrec } from "wrec";
|
|
1
|
+
import { css, html, Wrec } from "wrec";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* This is a counter web component.
|
|
4
|
+
* This is a counter web component implemented with wrec.
|
|
5
5
|
*/
|
|
6
6
|
class MyCounter extends Wrec {
|
|
7
7
|
static properties = {
|
|
8
8
|
count: { doc: "initial value", type: Number, reflect: true, value: 0 },
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
css
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
11
|
+
static css = css`
|
|
12
|
+
.counter {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 0.5rem;
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
button {
|
|
19
|
+
background-color: lightgreen;
|
|
20
|
+
}
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
22
|
+
button:disabled {
|
|
23
|
+
background-color: gray;
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
28
26
|
|
|
29
|
-
html
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
27
|
+
static html = html`
|
|
28
|
+
<div>
|
|
29
|
+
<button onClick="decrement" type="button" disabled="this.count === 0">
|
|
30
|
+
-
|
|
31
|
+
</button>
|
|
32
|
+
<span>this.count</span>
|
|
33
|
+
<button onClick="this.count++" type="button">+</button>
|
|
34
|
+
<span>(this.count < 10 ? "single" : "double") + " digit"</span>
|
|
35
|
+
</div>
|
|
36
|
+
`;
|
|
40
37
|
|
|
41
38
|
decrement() {
|
|
42
39
|
if (this.count > 0) this.count--;
|
package/package.json
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "0.1
|
|
8
|
+
"version": "0.2.1",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"reinstall": "rm -rf node_modules package-lock.json && npm install"
|
|
10
|
+
"reinstall": "rm -rf node_modules package-lock.json && npm install",
|
|
11
|
+
"test": "uvu test"
|
|
11
12
|
},
|
|
12
13
|
"devDependencies": {
|
|
13
14
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
package/test/integration.test.js
CHANGED
|
@@ -1,44 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
// This uses the uvu test runner at https://github.com/lukeed/uvu.
|
|
2
|
+
import { test } from "uvu";
|
|
3
|
+
import * as assert from "uvu/assert";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import { globby } from "globby";
|
|
7
|
+
import ts from "typescript";
|
|
8
|
+
|
|
9
|
+
import { create } from "@custom-elements-manifest/analyzer/src/create.js";
|
|
10
|
+
import myPlugin from "../index.js";
|
|
11
|
+
|
|
12
|
+
const fixturesDir = path.join(process.cwd(), "fixtures");
|
|
11
13
|
let testCases = fs.readdirSync(fixturesDir);
|
|
12
14
|
|
|
13
|
-
testCases.forEach(testCase => {
|
|
15
|
+
testCases.forEach((testCase) => {
|
|
14
16
|
test(`Testcase ${testCase}`, async () => {
|
|
15
|
-
|
|
16
17
|
const fixturePath = path.join(fixturesDir, `${testCase}/expected.json`);
|
|
17
|
-
const fixture = JSON.parse(fs.readFileSync(fixturePath,
|
|
18
|
+
const fixture = JSON.parse(fs.readFileSync(fixturePath, "utf-8"));
|
|
18
19
|
|
|
19
20
|
const packagePath = path.join(fixturesDir, `${testCase}/sourcecode`);
|
|
20
21
|
const packagePathPosix = packagePath.split(path.sep).join(path.posix.sep);
|
|
21
22
|
const outputPath = path.join(fixturesDir, `${testCase}/actual.json`);
|
|
22
23
|
|
|
23
24
|
const globs = await globby(packagePathPosix);
|
|
24
|
-
const modules = globs.map(glob => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
true,
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const result = create({modules, plugins: [myPlugin()]});
|
|
37
|
-
|
|
25
|
+
const modules = globs.map((glob) => {
|
|
26
|
+
const relativeModulePath = `.${path.sep}${path.relative(process.cwd(), glob)}`;
|
|
27
|
+
const file = path.basename(relativeModulePath);
|
|
28
|
+
const source = fs.readFileSync(relativeModulePath).toString();
|
|
29
|
+
return ts.createSourceFile(file, source, ts.ScriptTarget.ES2015, true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const result = create({ modules, plugins: [myPlugin()] });
|
|
38
33
|
fs.writeFileSync(outputPath, JSON.stringify(result, null, 2));
|
|
39
|
-
|
|
40
34
|
assert.equal(result, fixture);
|
|
41
35
|
});
|
|
42
36
|
});
|
|
43
37
|
|
|
44
|
-
test.run();
|
|
38
|
+
test.run();
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": "0.1.0",
|
|
3
|
-
"readme": "",
|
|
4
|
-
"modules": [
|
|
5
|
-
{
|
|
6
|
-
"kind": "javascript-module",
|
|
7
|
-
"path": "my-element.js",
|
|
8
|
-
"declarations": [
|
|
9
|
-
{
|
|
10
|
-
"kind": "class",
|
|
11
|
-
"description": "",
|
|
12
|
-
"name": "MyElement",
|
|
13
|
-
"members": [
|
|
14
|
-
{
|
|
15
|
-
"kind": "field",
|
|
16
|
-
"name": "someField",
|
|
17
|
-
"default": "",
|
|
18
|
-
"foo": "Some custom information!"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"superclass": {
|
|
22
|
-
"name": "HTMLElement"
|
|
23
|
-
},
|
|
24
|
-
"customElement": true
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"exports": [
|
|
28
|
-
{
|
|
29
|
-
"kind": "js",
|
|
30
|
-
"name": "MyElement",
|
|
31
|
-
"declaration": {
|
|
32
|
-
"name": "MyElement",
|
|
33
|
-
"module": "my-element.js"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
}
|