Skip to content

Commit cf429ae

Browse files
committed
Merge branch 'master' into feat/add-helpers-package
2 parents d7a7912 + e8794d4 commit cf429ae

File tree

93 files changed

+1717
-3705
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+1717
-3705
lines changed

.github/workflows/main.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This is a basic workflow to help you get started with Actions
2+
3+
name: Tests
4+
5+
# Controls when the action will run.
6+
on:
7+
# Triggers the workflow on push or pull request events but only for the master branch
8+
push:
9+
branches: [ master ]
10+
pull_request:
11+
branches: [ master ]
12+
13+
# Allows you to run this workflow manually from the Actions tab
14+
workflow_dispatch:
15+
16+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
17+
jobs:
18+
# This workflow contains a single job called "build"
19+
test:
20+
# The type of runner that the job will run on
21+
runs-on: ubuntu-latest
22+
23+
# Steps represent a sequence of tasks that will be executed as part of the job
24+
steps:
25+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
26+
- uses: actions/checkout@v2
27+
28+
# Runs a set of commands using the runners shell
29+
- name: run tests
30+
run: |
31+
yarn
32+
cd packages/analyzer
33+
npm test

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
dist/
2-
node_modules/
2+
node_modules/
3+
.DS_Store

packages/analyzer/README.md

Lines changed: 49 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Custom Elements Manifest is a file format that describes custom elements. This f
1111
- [JSDoc Support](#supported-jsdoc)
1212
- [Advanced configuration](#advanced-configuration)
1313
- [Plugins](#plugins)
14+
- [Authoring Plugins Handbook](docs/plugins.md)
1415
- [Browser](#usage-in-the-browser)
1516

1617
## Install
@@ -33,16 +34,18 @@ cem analyze
3334

3435
### Options
3536

36-
| Command/option | Type | Description | Example |
37-
| ---------------- | ---------- | ---------------------------------------------------- | --------------------- |
38-
| analyze | | Analyze your components | |
39-
| --globs | string[] | Globs to analyze | `--globs "foo.js"` |
40-
| --exclude | string[] | Globs to exclude | `--exclude "foo.js"` |
41-
| --dev | boolean | Enables extra logging for debugging | `--dev` |
42-
| --litelement | boolean | Enable special handling for LitElement syntax | `--litelement` |
43-
| --fast | boolean | Enable special handling for FASTElement syntax | `--fast` |
44-
| --stencil | boolean | Enable special handling for Stencil syntax | `--stencil` |
45-
| --catalyst | boolean | Enable special handling for Catalyst syntax | `--catalyst` |
37+
| Command/option | Type | Description | Example |
38+
| ---------------- | ---------- | ----------------------------------------------------------- | --------------------- |
39+
| analyze | | Analyze your components | |
40+
| --globs | string[] | Globs to analyze | `--globs "foo.js"` |
41+
| --exclude | string[] | Globs to exclude | `--exclude "foo.js"` |
42+
| --outdir | string | Directory to output the Manifest to | `--outdir dist` |
43+
| --watch | boolean | Enables watch mode, generates a new manifest on file change | `--watch` |
44+
| --dev | boolean | Enables extra logging for debugging | `--dev` |
45+
| --litelement | boolean | Enable special handling for LitElement syntax | `--litelement` |
46+
| --fast | boolean | Enable special handling for FASTElement syntax | `--fast` |
47+
| --stencil | boolean | Enable special handling for Stencil syntax | `--stencil` |
48+
| --catalyst | boolean | Enable special handling for Catalyst syntax | `--catalyst` |
4649

4750
## Demo
4851

@@ -73,7 +76,7 @@ customElements.define('my-element', MyElement);
7376

7477
```JSON
7578
{
76-
"schemaVersion": "0.1.0",
79+
"schemaVersion": "1.0.0",
7780
"readme": "",
7881
"modules": [
7982
{
@@ -135,10 +138,11 @@ customElements.define('my-element', MyElement);
135138
**TL;DR:**
136139
- JavaScript
137140
- TypeScript
138-
- LitElement (opt-in via CLI flag)
139-
- FASTElement (opt-in via CLI flag)
140-
- Stencil (opt-in via CLI flag)
141-
- Catalyst (opt-in via CLI flag)
141+
- [LitElement](https://lit.dev) (opt-in via CLI flag)
142+
- [FASTElement](https://www.fast.design/docs/fast-element/getting-started/) (opt-in via CLI flag)
143+
- [Stencil](https://stenciljs.com/) (opt-in via CLI flag)
144+
- [Catalyst](https://github.github.io/catalyst/) (opt-in via CLI flag)
145+
- [Atomico](https://atomicojs.github.io/) (opt-in via [community plugin](https://github.com/atomicojs/custom-elements-manifest))
142146

143147
Support for other web component libraries can be done via custom [plugins](#plugins), feel free to create your own for your favourite libraries.
144148

@@ -209,7 +213,7 @@ customElements.define('my-element', MyElement);
209213

210214
```json
211215
{
212-
"schemaVersion": "0.1.0",
216+
"schemaVersion": "1.0.0",
213217
"readme": "",
214218
"modules": [
215219
{
@@ -322,6 +326,7 @@ customElements.define('my-element', MyElement);
322326
*
323327
* @csspart bar - Styles the color of bar
324328
*
329+
* @slot - This is a default/unnamed slot
325330
* @slot container - You can put some elements here
326331
*
327332
* @cssprop --text-color - Controls the color of foo
@@ -353,7 +358,9 @@ import myAwesomePlugin from 'awesome-plugin';
353358
export default {
354359
globs: ['src/**/*.js'],
355360
exclude: ['src/foo.js'],
361+
outdir: 'dist',
356362
dev: true,
363+
watch: true,
357364
plugins: [
358365
myAwesomePlugin()
359366
],
@@ -374,7 +381,9 @@ Config types:
374381
interface userConfigOptions {
375382
globs: string[],
376383
exclude: string[],
384+
outdir: string,
377385
dev: boolean,
386+
watch: boolean,
378387
plugins: Array<() => Plugin>,
379388
overrideModuleCreation: ({ts: TypeScript, globs: string[]}) => SourceFile[]
380389
}
@@ -385,62 +394,30 @@ interface userConfigOptions {
385394

386395
You can also write custom plugins to extend the functionality to fit what your project needs. You can extract custom JSDoc tags for example, or implement support for a new Web Component library.
387396

388-
> You can use the [online playground](https://custom-elements-manifest.netlify.app/) for quickly prototyping plugin ideas, right in the browser
397+
> **TIP:** You can use the [online playground](https://custom-elements-manifest.netlify.app/) for quickly prototyping plugin ideas, right in the browser
389398
390-
A plugin is a function that returns an object. There are several hooks you can opt in to:
399+
A plugin is a function that returns an object. You can read about plugins in more detail in the [authoring plugins documentation](docs/plugins.md). There are several hooks you can opt in to:
391400

392401
- **collectPhase**: First passthrough through the AST of all modules in a project, before continuing to the `analyzePhase`. Runs for each module, and gives access to a Context object that you can use for sharing data between phases, and gives access to the AST nodes of your source code. This is useful for collecting information you may need access to in a later phase.
393402
- **analyzePhase**: Runs for each module, and gives access to the current Module's moduleDoc, and gives access to the AST nodes of your source code. This is generally used for AST stuff.
394403
- **moduleLinkPhase**: Runs after a module is done analyzing, all information about your module should now be available. You can use this hook to stitch pieces of information together.
395404
- **packageLinkPhase**: Runs after all modules are done analyzing, and after post-processing. All information should now be available and linked together.
396405

397-
> **TIP:** When writing custom plugins, [ASTExplorer](https://astexplorer.net/#/gist/f99a9fba2c21e015d0a8590d291523e5/cce02565e487b584c943d317241991f19b105f94) is your friend 🙂
406+
> **TIP:** When writing custom plugins, [ASTExplorer](https://astexplorer.net/#/gist/f99a9fba2c21e015d0a8590d291523e5/cce02565e487b584c943d317241991f19b105f94) is your friend 🙂
398407
399-
For a reference implementation of a plugin, you can take a look at the [Stencil plugin](/plugins/stencil.js), here's an example of a simpler plugin, that adds a custom JSDoc tag to a members doc:
400-
401-
Example source code:
402-
```js
403-
404-
export class MyElement extends HTMLElement {
405-
/**
406-
* @foo Some custom information!
407-
*/
408-
message = ''
409-
}
410-
```
408+
To get started developing custom plugins, take a look at the [cem-plugin-template](https://github.com/open-wc/cem-plugin-template) repository to quickly get you up and running. Also take a look at the [authoring plugins documentation](docs/plugins.md).
411409

412410
`custom-elements-manifest.config.mjs`:
413411
```js
414412
export default {
415413
plugins: [
416414
{
415+
// Make sure to always give your plugins a name, this helps when debugging
416+
name: 'my-plugin',
417417
// Runs for all modules in a project, before continuing to the `analyzePhase`
418418
collectPhase({ts, node, context}){},
419419
// Runs for each module
420-
analyzePhase({ts, node, moduleDoc, context}){
421-
// You can use this phase to access a module's AST nodes and mutate the custom-elements-manifest
422-
switch (node.kind) {
423-
case ts.SyntaxKind.ClassDeclaration:
424-
const className = node.name.getText();
425-
426-
node.members?.forEach(member => {
427-
const memberName = member.name.getText();
428-
429-
member.jsDoc?.forEach(jsDoc => {
430-
jsDoc.tags?.forEach(tag => {
431-
if(tag.tagName.getText() === 'foo') {
432-
const description = tag.comment;
433-
434-
const classDeclaration = moduleDoc.declarations.find(declaration => declaration.name === className);
435-
const messageField = classDeclaration.members.find(member => member.name === memberName);
436-
437-
messageField.foo = description
438-
}
439-
});
440-
});
441-
});
442-
}
443-
},
420+
analyzePhase({ts, node, moduleDoc, context}){},
444421
// Runs for each module, after analyzing, all information about your module should now be available
445422
moduleLinkPhase({moduleDoc, context}){},
446423
// Runs after modules have been parsed and after post-processing
@@ -450,31 +427,7 @@ export default {
450427
}
451428
```
452429

453-
You can also use plugins to output custom documentation:
454-
455-
```js
456-
import path from 'path';
457-
import fs from 'fs';
458-
459-
function generateReadme() {
460-
const components = ['my-component-a', 'my-component-b'];
461-
462-
return {
463-
packageLinkPhase({customElementsManifest, context}) {
464-
customElementsManifest.modules.forEach(mod => {
465-
mod.declarations.forEach(declaration => {
466-
if(components.includes(declaration.tagName)) {
467-
fs.writeFileSync(
468-
`${path.dirname(mod.path)}/README.md`,
469-
renderClassdocAsMarkdown(declaration)
470-
);
471-
}
472-
});
473-
});
474-
}
475-
}
476-
}
477-
```
430+
> **TIP:** Make sure to check out the [cem-plugin-template](https://github.com/open-wc/cem-plugin-template) repository if you're interested in authoring custom plugins, and check the [authoring plugins documentation](docs/plugins.md) for more information.
478431
479432
## How it works
480433

@@ -499,78 +452,35 @@ During the package link phase, we'll have all the information we need about a pa
499452
- Finding a CustomElement's tagname by finding its `customElements.define()` call, if present
500453
- Applying inheritance to classes (adding inherited members/attributes/events etc)
501454

502-
### Can I bring my own instance of TS?
503-
504-
No! Or well, you can. But that might break things. TypeScript doesn't follow semver, which means that there may be breaking changes in between minor or even patch versions of TypeScript. This means that if you use a different version of TypeScript than the analyzer's version of TypeScript, things will almost definitely break. As a convenience, plugin functions get passed the analyzer's version of TS to ensure there are no version incompatibilities, and everything works as expected.
505-
506-
## Overriding sourceFile creation
507-
508-
By default, `@custom-elements-manifest/analyzer` does _not_ compile any code with TS. It just uses the TS compiler API to create an AST of your source code. This means that there is no `typeChecker` available in plugins.
509-
510-
If you _do_ want to use the `typeChecker`, you can override the creation of modules in your `custom-elements-manifest.config.js`:
511-
512-
```js
513-
import { defaultCompilerOptions } from './compilerOptions.js';
514-
import { myPlugin } from './my-plugin.js';
515-
516-
let typeChecker;
517-
518-
export default {
519-
globs: ['fixtures/-default/package/**/*.js'],
520-
exclude: [],
521-
dev: true,
522-
overrideModuleCreation: ({ts, globs}) => {
523-
const program = ts.createProgram(globs, defaultCompilerOptions);
524-
typeChecker = program.getTypeChecker();
525-
526-
return program.getSourceFiles().filter(sf => globs.find(glob => sf.fileName.includes(glob)));
527-
},
528-
plugins: [
529-
/** You can now pass the typeChecker to your plugins */
530-
myPlugin(typeChecker)
531-
],
532-
}
533-
534-
```
535-
536-
`my-plugin.js`:
537-
```js
538-
export function myPlugin(typeChecker) {
539-
return {
540-
analyzePhase({ts, moduleDoc, context}) {
541-
// do something with typeChecker
542-
}
543-
}
544-
}
545-
546-
```
547-
548455
## Usage in the browser
549456

550457
You can also run the analyzer in the browser. You can import it like so:
551458

552459
```html
553460
<html>
554-
<head>
555-
<!-- For reasons, you need to load typescript separately. Make sure to load version ~4.3.0, otherwise things might break -->
556-
<script src="https://unpkg.com/[email protected]/lib/typescript.js"></script>
557-
558-
<!-- Import the code for the analyzer -->
559-
<script src="https://unpkg.com/@custom-element-manifest/[email protected]/browser/create.js"></script>
560-
</head>
561461
<body>
562-
<script>
563-
const code = `export function foo() {}`;
462+
<script type="module">
463+
import { ts, create, litPlugin } from '@custom-element-manifest/analyzer/browser/index.js';
464+
// or
465+
import { ts, create, litPlugin } from 'https://unpkg.com/@custom-element-manifest/analyzer/browser/index.js';
564466
565467
const modules = [ts.createSourceFile(
566-
'',
567-
code,
468+
'src/my-element.js',
469+
'export function foo() {}',
568470
ts.ScriptTarget.ES2015,
569471
true,
570472
)];
571473
572-
console.log(analyzer.create({modules}));
474+
const manifest = create({
475+
modules,
476+
plugins: [litPlugin()],
477+
dev: false
478+
});
479+
480+
console.log(manifest);
573481
</script>
574482
</body>
575483
</html>
576-
```
484+
```
485+
486+
Because typescript doesn't follow semver, and may do breaking changes on minor or patch versions, typescript is bundled with the analyzer to avoid any typescript version mismatches.

0 commit comments

Comments
 (0)