Generating Documentation in Custom Elements Manifest (CEM) format
Since Stencil v4.42, Stencil supports automatically generating a Custom Elements Manifest (CEM) file in your project. The CEM format is a standardized JSON format for describing custom elements and is supported by a variety of tools in the web components ecosystem.
import { Config } from '@stencil/core';
export const config: Config = {
outputTargets: [
{
type: 'docs-custom-elements-manifest',
file: 'path/to/cem.json'
}
]
};
The JSON file output by Stencil conforms to the CEM Schema interface.
Properties, Methods, Events, and Attributes
The CEM output target includes information about your components' properties, methods, events, and attributes based on the decorators you use in your Stencil components.
CSS Properties
Stencil can document CSS variables if you annotate them with JSDoc-style comments in your CSS/SCSS files. If, for instance, you had a component with a CSS file like the following:
:host {
/**
* @prop --background: Background of the button
* @prop --background-activated: Background of the button when activated
* @prop --background-focused: Background of the button when focused
*/
--background: pink;
--background-activated: aqua;
--background-focused: fuchsia;
}
Then you'd get the following in the JSON output:
[
{
"cssProperties": [
{
"name": "background",
"description": "Background of the button"
},
{
"name": "background-activated",
"description": "Background of the button when activated"
},
{
"name": "background-focused",
"description": "Background of the button when focused"
}
]
}
]
Slots and CSS Parts
If one of your Stencil components makes use of
slots for
rendering children or CSS Parts for styling,
you can document them by using the @slot and @part JSDoc tags in the
component's comments.
For instance, if you had a my-button component with a slot you might document
it like so:
import { Component, h } from '@stencil/core';
/**
* @slot buttonContent - Slot for the content of the button
*
* @part button - The button element
*/
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true,
})
export class MyButton {
render() {
return <button part="button"><slot name="buttonContent"></slot></button>
}
}
This would show up in the generated JSON file like so:
"slots": [
{
"name": "buttonContent",
"description": "Slot for the content of the button"
}
],
"cssParts": [
{
"name": "button",
"description": "The button element"
}
]
Stencil does not check that the slots you document in a component's JSDoc
comment using the @slot tag are actually present in the JSX returned by the
component's render function.
It is up to you as the component author to ensure the @slot tags on a
component are kept up to date.
Custom States
You can document Custom States for your components using the @AttachInternals decorator
and JSDoc comments.
For example:
import { Component, h, AttachInternals } from '@stencil/core';
/**
* My Element component
*/
@Component({
tag: 'my-element',
styleUrl: 'my-element.css',
shadow: true,
})
export class MyElement {
@AttachInternals({
states: {
new: true,
/** If this item is older than 6 months old. Use via `:state(archived)` */
archived: false
},
}) internals!: ElementInternals;
This would show up in the generated JSON file like so:
"customStates": [
{
"name": "new",
"description": ""
},
{
"name": "archived",
"description": "If this item is older than 6 months old. Use via `:state(archived)"
}
]
Demos
You can save demos for a component in the usage/ subdirectory within
that component's directory. The content of these files will be added to the
demos property of the generated JSON. This allows you to keep examples right
next to the code, making it easy to include them in a documentation site or
other downstream consumer(s) of your docs.
Stencil doesn't check that your demos are up-to-date! If you make any changes to your component's API you'll need to remember to update your demos manually.
If, for instance, you had a usage example like this:
# How to use `my-button`
A button is often a great help in adding interactivity to an app!
You could use it like this:
```html
<my-button>My Button!</my-button>
```
You'd get the following in the JSON output under the "usage" key:
"demos": [{
"url": "my-button-usage.md",
"description": "# How to use `my-button`\n\nA button is often a great help in adding interactivity to an app!\n\nYou could use it like this:\n\n```html\n<my-button>My Button!</my-button>\n```\n"
}]