diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 211ec338..a659fd5a 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -54,7 +54,7 @@ jobs: - name: Install Dev if: steps.cache-dev.outputs.cache-hit != 'true' run: npm ci - working-directory: 'dev' + working-directory: "dev" - name: Test run: npm run test:all diff --git a/.husky/pre-commit b/.husky/pre-commit index 5e7ae3ef..d3b37051 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,4 +2,4 @@ . "$(dirname -- "$0")/_/husky.sh" npx eslint --fix -# npx prettier --write +npx prettier --write . diff --git a/ANALYZE.md b/ANALYZE.md index a60727ce..bb03f053 100644 --- a/ANALYZE.md +++ b/ANALYZE.md @@ -189,28 +189,30 @@ In addition, the entire content of HTMLElement is copied into the interfaces, so ### Component discovery -An LWC component class is automatically identified from a JavaScript/Typescript file if: +An LWC component class is automatically identified from a JavaScript/Typescript file if: + - It is the default export of the file - The JS file name equals the parent folder name (ex: `/../mycomp/mycomp.{js|ts}`) -- There is an HTML template with the same name in the same folder (ex: `/../mycomp/mycomp.html`) +- There is an HTML template with the same name in the same folder (ex: `/../mycomp/mycomp.html`) The component is named after the last 2 parts of its parent directory. For example, if the file path is `/../myns/mycomp/mycomp.js`, then the component tag is `myns-mycomp`. The name is also transformed from camel case -to dash case: `/../myns/mycomp/myComp.js` leads to `myns-my-comp`. +to dash case: `/../myns/mycomp/myComp.js` leads to `myns-my-comp`. + +For components that are not following the previous naming scheme, it uses 2 other methods: -For components that are not following the previous naming scheme, it uses 2 other methods: - Checks if the class extends `LightningElement`. - This only works with a direct inheritance as it doesn't check the whole hierarchy. + This only works with a direct inheritance as it doesn't check the whole hierarchy. - Looks for a `@lwcelement` JSDoc tag. - The JSDoc tag can also override the default tag name. + The JSDoc tag can also override the default tag name. ```javascript /** * @lwcelement my-element */ export default class MyElement extends BaseComponent { -``` +``` #### In your own code @@ -249,4 +251,4 @@ export default class MyElement extends LightningElement { */ @api prop3; } -``` \ No newline at end of file +``` diff --git a/README.md b/README.md index d5c62fa7..bd256153 100644 --- a/README.md +++ b/README.md @@ -1,262 +1,262 @@ -

web-component-analyzer

- -

- Downloads per month - NPM Version - Dependencies - Contributors -

- -

- Web component analyzer GIF -

- -`web-component-analyzer` is a CLI that makes it possible to easily analyze web components. It analyzes your code and jsdoc in order to extract `properties`, `attributes`, `methods`, `events`, `slots`, `css shadow parts` and `css custom properties`. Works with both javascript and typescript. - -Try the online playground [here](https://runem.github.io/web-component-analyzer/) - -In addition to [vanilla web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) this tool supports web components built with the following libraries: - -- [lit-element](https://github.com/Polymer/lit-element) -- [polymer](https://github.com/Polymer/polymer) -- [stencil](https://github.com/ionic-team/stencil) (partial) -- [lwc](https://github.com/salesforce/lwc) -- [open an issue for library requests](https://github.com/runem/web-component-analyzer/issues) - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#installation) - -## ➤ Installation - - -```bash -$ npm install -g web-component-analyzer -``` - -**or** - - -```bash -$ npx web-component-analyzer src -``` - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#usage) - -## ➤ Usage - - -```bash -$ wca analyze -$ wca analyze src --format markdown -$ wca analyze "src/**/*.{js,ts}" --outDir components -$ wca analyze my-element.js --outFile custom-elements.json -$ wca analyze --outFiles {dir}/custom-element.json -``` - - - -The analyze command analyses an optional `` and emits the output to the console as default. When the `` is omitted it will find all components excluding `node_modules`. The default format is `markdown`. - -### Options - - -| Option | Type | Description | -| --------------------------- | -------------------------------- | ---------------------------------------------------------------------------- | -| `--format ` | `markdown` \| `json` \| `vscode` | Specify output format. Default is `markdown`. | -| `--outDir ` | `directory path` | Direct output to a directory where each file corresponds to a web component. | -| `--outFile ` | `file path` | Concatenate and emit output to a single file. | -| `--outFiles ` | `file path with pattern` | Emit output to multiple files using a pattern. Available substitutions:
**{dir}**: The directory of the component
**{filename}**: The filename (without ext) of the component
**{tagname}**: The element's tag name | -| `--visibility ` | `public` \| `protected` \| `private` | The mininmum member visibility to output. Default is `public`. | -| `--features ` | `member` \| `method` \| `cssproperty` \| `csspart` \| `event` \| `slot` | Choose specific features to output. Multiple features are given seperated by a space. All features are enabled as default.
**Example**: `--features member slot event` | -| `--dry` | `boolean` | Don't write any files | - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#api) - -## ➤ Output Formats - -### json - - -```bash -wca analyze src --format json --outFile custom-elements.json -``` - -Try the online playground [here](https://runem.github.io/web-component-analyzer?format=json) - -This json format is for experimental and demo purposes, and is still being actively discussed. You can expect changes to this format. Please follow and contribute to the discussion at: - -- https://github.com/webcomponents/custom-elements-json -- https://github.com/w3c/webcomponents/issues/776 - -### markdown - - -```bash -wca analyze src --format markdown --outDir readme -``` - -Try the online playground [here](https://runem.github.io/web-component-analyzer?format=markdown) - -Web Component Analyzer can output markdown documentation of your web components. This can either be output into a single file using `--outFile` or into multiple files using `--outDir`. - -### vscode - - -```bash -wca analyze src --format vscode --outFile vscode-html-custom-data.json -``` - -VSCode supports a JSON format called [vscode custom data](https://github.com/microsoft/vscode-custom-data) for the built in html editor which is set using `html.customData` vscode setting. Web Component Analyzer can output this format. - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-does-this-tool-analyze-my-components) - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-to-document-your-components-using-jsdoc) - -## ➤ How to document your components using JSDoc - -In addition to analyzing the code of your components, this library also use JSDoc to construct the documentation. It's especially a good idea to use JSDoc for documenting `slots`, `events`, `css custom properties` and `css shadow parts` as these not analyzed statically by this tool as of now (except when constructing a CustomEvent within your component). - -Here's an example including all supported JSDoc tags. All JSDoc tags are on the the form `@tag {type} name - comment` and `@tag {type} [name=default] - comment`. - - -```javascript -/** - * Here is a description of my web component. - * - * @element my-element - * - * @fires change - This jsdoc tag makes it possible to document events. - * @fires submit - * - * @attr {Boolean} disabled - This jsdoc tag documents an attribute. - * @attr {on|off} switch - Here is an attribute with either the "on" or "off" value. - * @attr [my-attr=default value] - * - * @prop {String} myProp - You can use this jsdoc tag to document properties. - * @prop value - * - * @slot - This is an unnamed slot (the default slot) - * @slot start - This is a slot named "start". - * @slot end - * - * @cssprop --main-bg-color - This jsdoc tag can be used to document css custom properties. - * @cssprop [--main-color=red] - - * @csspart container - */ -class MyElement extends HTMLElement { - - /** - * This is a description of a property with an attribute with exactly the same name: "color". - * @type {"red"|"green"|"blue"} - * @attr - */ - color = "red"; - - /** - * This is a description of a property with an attribute called "my-prop". - * @type {number} - * @deprecated - * @attr my-prop - */ - myProp = 10 - - static get observedAttributes () { - return [ - /** - * The header text of this element - */ - "header" - ]; - } - -} -``` - -### Overview of supported JSDoc tags - - -| JSDoc Tag | Description | -| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `@element` | Gives your component a tag name. This JSDoc tag is useful if your 'customElements.define` is called dynamically eg. using a custom function. | -| `@fires` | Documents events. | -| `@slot` | Documents slots. Using an empty name here documents the unnamed (default) slot. | -| `@attr` or `@attribute` | Documents an attribute on your component. | -| `@prop` or `@property` | Documents a property on your component. | -| `@cssprop` or `@cssproperty` | Documents a css custom property on your component. | -| `@csspart` | Documents a css shadow part on your component. | - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#contributors) - -## ➤ How does this tool analyze my components? - -This tool extract information about your components by looking at your code directly and by looking at your JSDoc comments. - -**Code**: Web Component Analyzer supports multiple libraries. [Click here](https://github.com/runem/web-component-analyzer/blob/master/ANALYZE.md) for an overview of how each library is analyzed. - -**JSDoc**: Read next section to learn more about how JSDoc is analyzed. - -## ➤ API - -You can also directly use the underlying functionality of this tool if you don't want to use the CLI. Web Component Analyzer analyzes Typescript source files, so you will have to include the Typescript parser. Here are some examples of how to use the API. - -### Analyze Typescript source file - - -```typescript -import { analyzeSourceFile } from "web-component-analyzer"; - -const result = analyzeSourceFile(sourceFile, { checker }); -``` - -### Analyze text - - -```javascript -import { analyzeText } from "web-component-analyzer"; - -const code = `class MyElement extends HTMLElement { - -} - -customElements.define("my-element", MyElement); -`; - - -const { results, program } = analyzeText(code); -// or -const { results, program } = analyzeText([ - { fileName: "file1.js", text: code }, - { fileName: "file2.js", text: "..." }, // these files can depend on each other - { fileName: "file3.js", text: "...", analyze: false } -]); -// each result in "results" is the result of analyzing the corresponding text where "analyze" is not false -``` - -### Transform the result - - -```javascript -import { transformAnalyzerResult } from "web-component-analyzer"; - -const result = // the result of analyzing the component using one of the above functions - -const format = "markdown"; // or "json" - -const output = transformAnalyzerResult(format, result, program); - -// "output" is now a string containing the result of the "markdown" transformer -``` - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-does-this-tool-analyze-my-components) - -## ➤ Contributors - -| [Rune Mehlsen](https://github.com/runem) | -| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| [Rune Mehlsen](https://github.com/runem) | - -[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#license) - -## ➤ License - -Licensed under [MIT](https://opensource.org/licenses/MIT). +

web-component-analyzer

+ +

+ Downloads per month + NPM Version + Dependencies + Contributors +

+ +

+ Web component analyzer GIF +

+ +`web-component-analyzer` is a CLI that makes it possible to easily analyze web components. It analyzes your code and jsdoc in order to extract `properties`, `attributes`, `methods`, `events`, `slots`, `css shadow parts` and `css custom properties`. Works with both javascript and typescript. + +Try the online playground [here](https://runem.github.io/web-component-analyzer/) + +In addition to [vanilla web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) this tool supports web components built with the following libraries: + +- [lit-element](https://github.com/Polymer/lit-element) +- [polymer](https://github.com/Polymer/polymer) +- [stencil](https://github.com/ionic-team/stencil) (partial) +- [lwc](https://github.com/salesforce/lwc) +- [open an issue for library requests](https://github.com/runem/web-component-analyzer/issues) + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#installation) + +## ➤ Installation + + +```bash +$ npm install -g web-component-analyzer +``` + +**or** + + +```bash +$ npx web-component-analyzer src +``` + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#usage) + +## ➤ Usage + + +```bash +$ wca analyze +$ wca analyze src --format markdown +$ wca analyze "src/**/*.{js,ts}" --outDir components +$ wca analyze my-element.js --outFile custom-elements.json +$ wca analyze --outFiles {dir}/custom-element.json +``` + + + +The analyze command analyses an optional `` and emits the output to the console as default. When the `` is omitted it will find all components excluding `node_modules`. The default format is `markdown`. + +### Options + + +| Option | Type | Description | +| --------------------------- | -------------------------------- | ---------------------------------------------------------------------------- | +| `--format ` | `markdown` \| `json` \| `vscode` | Specify output format. Default is `markdown`. | +| `--outDir ` | `directory path` | Direct output to a directory where each file corresponds to a web component. | +| `--outFile ` | `file path` | Concatenate and emit output to a single file. | +| `--outFiles ` | `file path with pattern` | Emit output to multiple files using a pattern. Available substitutions:
**{dir}**: The directory of the component
**{filename}**: The filename (without ext) of the component
**{tagname}**: The element's tag name | +| `--visibility ` | `public` \| `protected` \| `private` | The mininmum member visibility to output. Default is `public`. | +| `--features ` | `member` \| `method` \| `cssproperty` \| `csspart` \| `event` \| `slot` | Choose specific features to output. Multiple features are given seperated by a space. All features are enabled as default.
**Example**: `--features member slot event` | +| `--dry` | `boolean` | Don't write any files | + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#api) + +## ➤ Output Formats + +### json + + +```bash +wca analyze src --format json --outFile custom-elements.json +``` + +Try the online playground [here](https://runem.github.io/web-component-analyzer?format=json) + +This json format is for experimental and demo purposes, and is still being actively discussed. You can expect changes to this format. Please follow and contribute to the discussion at: + +- https://github.com/webcomponents/custom-elements-json +- https://github.com/w3c/webcomponents/issues/776 + +### markdown + + +```bash +wca analyze src --format markdown --outDir readme +``` + +Try the online playground [here](https://runem.github.io/web-component-analyzer?format=markdown) + +Web Component Analyzer can output markdown documentation of your web components. This can either be output into a single file using `--outFile` or into multiple files using `--outDir`. + +### vscode + + +```bash +wca analyze src --format vscode --outFile vscode-html-custom-data.json +``` + +VSCode supports a JSON format called [vscode custom data](https://github.com/microsoft/vscode-custom-data) for the built in html editor which is set using `html.customData` vscode setting. Web Component Analyzer can output this format. + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-does-this-tool-analyze-my-components) + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-to-document-your-components-using-jsdoc) + +## ➤ How to document your components using JSDoc + +In addition to analyzing the code of your components, this library also use JSDoc to construct the documentation. It's especially a good idea to use JSDoc for documenting `slots`, `events`, `css custom properties` and `css shadow parts` as these not analyzed statically by this tool as of now (except when constructing a CustomEvent within your component). + +Here's an example including all supported JSDoc tags. All JSDoc tags are on the the form `@tag {type} name - comment` and `@tag {type} [name=default] - comment`. + + +```javascript +/** + * Here is a description of my web component. + * + * @element my-element + * + * @fires change - This jsdoc tag makes it possible to document events. + * @fires submit + * + * @attr {Boolean} disabled - This jsdoc tag documents an attribute. + * @attr {on|off} switch - Here is an attribute with either the "on" or "off" value. + * @attr [my-attr=default value] + * + * @prop {String} myProp - You can use this jsdoc tag to document properties. + * @prop value + * + * @slot - This is an unnamed slot (the default slot) + * @slot start - This is a slot named "start". + * @slot end + * + * @cssprop --main-bg-color - This jsdoc tag can be used to document css custom properties. + * @cssprop [--main-color=red] + + * @csspart container + */ +class MyElement extends HTMLElement { + + /** + * This is a description of a property with an attribute with exactly the same name: "color". + * @type {"red"|"green"|"blue"} + * @attr + */ + color = "red"; + + /** + * This is a description of a property with an attribute called "my-prop". + * @type {number} + * @deprecated + * @attr my-prop + */ + myProp = 10 + + static get observedAttributes () { + return [ + /** + * The header text of this element + */ + "header" + ]; + } + +} +``` + +### Overview of supported JSDoc tags + + +| JSDoc Tag | Description | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `@element` | Gives your component a tag name. This JSDoc tag is useful if your 'customElements.define` is called dynamically eg. using a custom function. | +| `@fires` | Documents events. | +| `@slot` | Documents slots. Using an empty name here documents the unnamed (default) slot. | +| `@attr` or `@attribute` | Documents an attribute on your component. | +| `@prop` or `@property` | Documents a property on your component. | +| `@cssprop` or `@cssproperty` | Documents a css custom property on your component. | +| `@csspart` | Documents a css shadow part on your component. | + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#contributors) + +## ➤ How does this tool analyze my components? + +This tool extract information about your components by looking at your code directly and by looking at your JSDoc comments. + +**Code**: Web Component Analyzer supports multiple libraries. [Click here](https://github.com/runem/web-component-analyzer/blob/master/ANALYZE.md) for an overview of how each library is analyzed. + +**JSDoc**: Read next section to learn more about how JSDoc is analyzed. + +## ➤ API + +You can also directly use the underlying functionality of this tool if you don't want to use the CLI. Web Component Analyzer analyzes Typescript source files, so you will have to include the Typescript parser. Here are some examples of how to use the API. + +### Analyze Typescript source file + + +```typescript +import { analyzeSourceFile } from "web-component-analyzer"; + +const result = analyzeSourceFile(sourceFile, { checker }); +``` + +### Analyze text + + +```javascript +import { analyzeText } from "web-component-analyzer"; + +const code = `class MyElement extends HTMLElement { + +} + +customElements.define("my-element", MyElement); +`; + + +const { results, program } = analyzeText(code); +// or +const { results, program } = analyzeText([ + { fileName: "file1.js", text: code }, + { fileName: "file2.js", text: "..." }, // these files can depend on each other + { fileName: "file3.js", text: "...", analyze: false } +]); +// each result in "results" is the result of analyzing the corresponding text where "analyze" is not false +``` + +### Transform the result + + +```javascript +import { transformAnalyzerResult } from "web-component-analyzer"; + +const result = // the result of analyzing the component using one of the above functions + +const format = "markdown"; // or "json" + +const output = transformAnalyzerResult(format, result, program); + +// "output" is now a string containing the result of the "markdown" transformer +``` + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#how-does-this-tool-analyze-my-components) + +## ➤ Contributors + +| [Rune Mehlsen](https://github.com/runem) | +| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| [Rune Mehlsen](https://github.com/runem) | + +[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#license) + +## ➤ License + +Licensed under [MIT](https://opensource.org/licenses/MIT). diff --git a/dev/src/lit-element/lit-element.js b/dev/src/lit-element/lit-element.js index 373d6c1b..53c22aa8 100644 --- a/dev/src/lit-element/lit-element.js +++ b/dev/src/lit-element/lit-element.js @@ -23,7 +23,7 @@ export class MyElement extends LitElement { }; } - update(changedProperties: Map): void { + update(changedProperties) { super.update(); } diff --git a/src/cli/cli.ts b/src/cli/cli.ts index ac64a968..97719d65 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -110,7 +110,7 @@ o {tagname}: The element's tag name`, .strict() .alias("h", "help").argv; - if ((argv as {verbose: boolean}).verbose) { + if ((argv as { verbose: boolean }).verbose) { /* eslint-disable-next-line no-console */ console.log("CLI options:", argv); } diff --git a/test/flavors/custom-element/discover-test.ts b/test/flavors/custom-element/discover-test.ts index e7d8ae46..ee55cddc 100644 --- a/test/flavors/custom-element/discover-test.ts +++ b/test/flavors/custom-element/discover-test.ts @@ -159,14 +159,8 @@ tsTest("Correctly discovers multiple declarations", t => { t.is(componentDefinitions.length, 1); t.is(componentDefinitions[0].tagName, "my-element"); - t.is( - componentDefinitions[0].declaration?.members?.some(m => m.propName === "prototype"), - false - ); - t.is( - componentDefinitions[0].declaration?.methods?.some(m => m.name === "new"), - false - ); + t.is(componentDefinitions[0].declaration?.members?.some(m => m.propName === "prototype"), false); + t.is(componentDefinitions[0].declaration?.methods?.some(m => m.name === "new"), false); }); tsTest("Discovers elements using typescript >=4.3 syntax", t => { diff --git a/test/flavors/lwc/comp/c0/c0.html b/test/flavors/lwc/comp/c0/c0.html index d5183a4c..96b21236 100644 --- a/test/flavors/lwc/comp/c0/c0.html +++ b/test/flavors/lwc/comp/c0/c0.html @@ -1,3 +1,3 @@ diff --git a/test/flavors/lwc/comp/c0/c0.js b/test/flavors/lwc/comp/c0/c0.js index 3f8fddce..4608c1db 100644 --- a/test/flavors/lwc/comp/c0/c0.js +++ b/test/flavors/lwc/comp/c0/c0.js @@ -1,7 +1,6 @@ -import { LightningElement } from 'lwc'; +import { LightningElement } from "lwc"; /** * Simple component. */ -export default class C0 extends LightningElement { -} +export default class C0 extends LightningElement {} diff --git a/test/flavors/lwc/comp/c1/c1.js b/test/flavors/lwc/comp/c1/c1.js index d5875ad8..64674174 100644 --- a/test/flavors/lwc/comp/c1/c1.js +++ b/test/flavors/lwc/comp/c1/c1.js @@ -1,7 +1,6 @@ -import { LightningElement } from 'lwc'; +import { LightningElement } from "lwc"; /** * Simple component. */ -export default class C1 extends LightningElement { -} +export default class C1 extends LightningElement {} diff --git a/test/flavors/lwc/comp/c2/c2.js b/test/flavors/lwc/comp/c2/c2.js index 4a17e87c..3e531d20 100644 --- a/test/flavors/lwc/comp/c2/c2.js +++ b/test/flavors/lwc/comp/c2/c2.js @@ -1,7 +1,6 @@ -import { OtherElement } from 'lwc'; +import { OtherElement } from "lwc"; /** * Simple component. */ -export default class C3 extends OtherElement { -} +export default class C3 extends OtherElement {} diff --git a/test/helpers/ts-test.ts b/test/helpers/ts-test.ts index e55a0086..30c2fb4d 100644 --- a/test/helpers/ts-test.ts +++ b/test/helpers/ts-test.ts @@ -6,7 +6,7 @@ type TestFunction = (title: string, implementation: Implementation) => void; const TS_MODULES_ALL = ["current", "4.8", "4.9", "5.0", "5.1"] as const; -type TsModuleKind = typeof TS_MODULES_ALL[number]; +type TsModuleKind = (typeof TS_MODULES_ALL)[number]; const TS_MODULES_DEFAULT: readonly TsModuleKind[] = TS_MODULES_ALL;