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 CHANGED
@@ -1,15 +1,15 @@
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';
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 code = fs.readFileSync('fixtures/default/sourcecode/default.js').toString();
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(JSON.stringify(create({modules, plugins: [myPlugin()]}), null, 2));
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);
@@ -0,0 +1,12 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "my-counter.js",
8
+ "declarations": [],
9
+ "exports": []
10
+ }
11
+ ]
12
+ }
@@ -4,22 +4,21 @@
4
4
  "modules": [
5
5
  {
6
6
  "kind": "javascript-module",
7
- "path": "my-element.js",
7
+ "path": "my-counter.js",
8
8
  "declarations": [
9
9
  {
10
10
  "kind": "class",
11
11
  "description": "",
12
- "name": "MyElement",
12
+ "name": "MyCounter",
13
13
  "members": [
14
14
  {
15
15
  "kind": "field",
16
- "name": "someField",
17
- "default": "",
18
- "foo": "Some custom information!"
16
+ "name": "count",
17
+ "default": "0"
19
18
  }
20
19
  ],
21
20
  "superclass": {
22
- "name": "HTMLElement"
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": "MyElement",
29
+ "name": "MyCounter",
31
30
  "declaration": {
32
- "name": "MyElement",
33
- "module": "my-element.js"
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 = ts.SyntaxKind;
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.push({
93
- default: value,
94
- description: doc,
95
- fieldName: name,
96
- name,
97
- type,
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, after analyzing, all information about your module should now be available
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
- return /*css*/ `
13
- .counter {
14
- display: flex;
15
- align-items: center;
16
- gap: 0.5rem;
17
- }
11
+ static css = css`
12
+ .counter {
13
+ display: flex;
14
+ align-items: center;
15
+ gap: 0.5rem;
16
+ }
18
17
 
19
- button {
20
- background-color: lightgreen;
21
- }
18
+ button {
19
+ background-color: lightgreen;
20
+ }
22
21
 
23
- button:disabled {
24
- background-color: gray;
25
- }
26
- `;
27
- }
22
+ button:disabled {
23
+ background-color: gray;
24
+ }
25
+ `;
28
26
 
29
- html() {
30
- return /*html*/ `
31
- <div>
32
- <button onClick="decrement" type="button"
33
- disabled="this.count === 0">-</button>
34
- <span>this.count</span>
35
- <button onClick="this.count++" type="button">+</button>
36
- <span>(this.count < 10 ? "single" : "double") + " digit"</span>
37
- </div>
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.4",
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",
@@ -1,44 +1,38 @@
1
- import { test } from 'uvu';
2
- import * as assert from 'uvu/assert';
3
- import path from 'path';
4
- import fs from 'fs';
5
- import globby from 'globby';
6
- import ts from 'typescript';
7
- import { create } from '@custom-elements-manifest/analyzer/src/create.js';
8
- import myPlugin from '../index.js';
9
-
10
- const fixturesDir = path.join(process.cwd(), 'fixtures');
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, 'utf-8'));
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
- const relativeModulePath = `.${path.sep}${path.relative(process.cwd(), glob)}`;
26
- const source = fs.readFileSync(relativeModulePath).toString();
27
-
28
- return ts.createSourceFile(
29
- 'my-element.js',
30
- source,
31
- ts.ScriptTarget.ES2015,
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
- }
@@ -1,6 +0,0 @@
1
- export class MyElement extends HTMLElement {
2
- /**
3
- * @foo Some custom information!
4
- */
5
- someField = '';
6
- }