cem
cem is a command-line tool for generating Custom Elements Manifest (CEM) files from TypeScript sources. It analyzes your codebase and generates rich metadata for your custom elements, facilitating documentation, tooling, and integration.
[!NOTE]
cem
best supports LitElements written in idiomatic style with TypeScript decorators. There is rudimentary support forextends HTMLElement
, but it is not a high priority for development. If you need something more specific open an issue.
Installation
For go binaries:
go install bennypowers.dev/cem@latest
For NPM projects:
npm install --save-dev @pwrs/cem
Or clone this repository and build from source:
git clone https://github.com/bennypowers/cem.git
cd cem
make
Features
cem generate
- Generates CEM files from source code using syntax analysis powered by go and tree-sitter.
- Identifies custom elements, classes, variables, functions, and exports.
- Supports elements written in idiomatic Lit typescript style, with a
@customElement
decorator, and@property
decorators on class fields.
JSDoc
Use JSDoc comments to add metadata to your element classes, similar to other
tools. Add a description by separating the name of the item with -
@attr
/@attribute
— Custom element attributes@csspart
— CSS shadow parts@cssprop
/@cssproperty
— Custom CSS properties@cssstate
— Custom CSS states@demo
— Demo URL@deprecated
— Marks a feature or member as deprecated@event
— Custom events dispatched by the element@slot
— Named or default slots@summary
— Short summary for documentation
See the test-fixtures directory for examples
HTML Template Analysis for Slots and Parts
- Automatically detects
<slot>
elements andpart
attributes in your element’srender()
template. - Merges slot and part information found in templates with any provided via JSDoc, ensuring comprehensive documentation in the generated manifest.
- Deprecation and other metadata for slots and parts can be specified via YAML in HTML comments.
- Supports documenting slots and parts inline in your template HTML using HTML comments with YAML blocks.
- YAML comments are not necessary to detect slots and parts, but help in documenting them for your users.
Examples
<!--
summary: The main slot for content
description: |
This slot displays user-provided content.
Supports multiline **markdown**.
deprecated: true
-->
<slot></slot>
<!-- slot:
summary: Named slot summary
part:
summary: Part summary
-->
<slot name="info" part="info-part"></slot>
CSS Custom Properties
Supports CSS Custom Properties by scanning css files and css tagged-template-literals
- Custom properties beginning with
_
will be ignored (treated as "private") e.g.var(--_private)
- If you provide a Design Tokens Community Group format module (JSON) to
cem
via the--design-tokens
flag,cem
will add metadata from your design system to any matching css variables it finds in your elements - You can use jsdoc-like comment syntax before each var call to document your variables
Example
:host {
color:
/**
* custom color for use in this element
* @summary color
* @deprecated just use the `color` property
*/
var(--custom-color);
border:
1px
solid
/** Border color of the element */
var(--border-color);
}
Element Demos
cem generate
supports documenting your elements' demos by linking directly
from JSDoc, or by configurable file-system based discovery.
1. JSDoc @demo
Tag
Add demos directly to your element class or members with the @demo
tag:
/**
* @demo https://example.com/my-element-plain/
* @demo https://example.com/my-element-fancy/ - A fancier demo with description
*/
@customElement('my-element')
class MyElement extends LitElement {
// ...
}
Demos defined this way will always appear in your manifest for the element.
2. Demo Discovery
cem
can automatically discover demos from your codebase based on your
repository structure and configuration.
Demo Discovery Options
Configure demo discovery with the demoDiscovery
key in your .config/cem.yaml
file
sourceControlRootUrl: "https://github.com/your/repo/tree/main/"
generate:
demoDiscovery:
fileGlob: "demos/**/*.html"
urlPattern: "demos/(?P<tag>[\w-]+)/(?P<demo>[\w-]+).html"
urlTemplate: "https://example.com/elements/{tag}/{demo}/"
Demo discovery options:
Option | Type | Description |
---|---|---|
fileGlob |
string | Glob pattern for discovering demo files. |
sourceControlRootUrl |
string | Canonical public source control URL for your repository root (on the main branch). |
urlPattern |
string | Pattern for generating demo URLs, e.g. "demos/{tag}.html" . {tag} is replaced by tag name. |
urlTemplate |
string | (optional) Alternative URL template for demo links. |
Configuration Reference
You can configure CEM via .config/cem.yaml
, relative to your project root,
or via CLI flags.
Example Configuration
sourceControlRootUrl: "https://github.com/your/repo/tree/main/"
generate:
files:
- "src/**/*.ts"
exclude:
- "src/**/*.test.ts"
output: "custom-elements.json"
noDefaultExcludes: false
designTokens:
spec: "npm:@my-ds/tokens/tokens.json"
prefix: "--my-ds"
demoDiscovery:
fileGlob: "demos/**/*.html"
urlPattern: "demos/(?P<tag>[\w-]+)/(?P<demo>[\w-]+).html"
urlTemplate: "https://example.com/elements/{tag}/{demo}/"
Usage
Generate a custom elements manifest from your files:
cem generate \
"src/**/*.ts" \
--design-tokens npm:@my-ds/tokens/tokens.json \
--exclude "src/**/*.test.ts" \
--output custom-elements.json
For npm projects you can use npx @pwrs/cem generate ...
.
Command Line Arguments
Argument | Type | Description |
---|---|---|
<files or globs> |
positional (array) | Files or glob patterns to include |
--output, -o |
string | Write the manifest to this file instead of stdout |
--exclude, -e |
array | Files or glob patterns to exclude |
--no-default-excludes |
bool | Do not exclude files by default (e.g., .d.ts files will be included unless excluded explicitly) |
--design-tokens, -t |
string | Path or npm specifier for DTCG-format design tokens |
--design-tokens-prefix, -p |
string | CSS custom property prefix for design tokens |
--demo-discovery-file-glob |
string | Glob pattern for discovering demo files |
--demo-discovery-url-pattern |
string | Go Regexp pattern with named capture groups for generating canonical demo urls |
--demo-discovery-url-template |
string | URL pattern string using {groupName} syntax to interpolate named captures from the URL pattern |
--source-control-root-url |
string | Glob pattern for discovering demo files |
By default, some files (like .d.ts
TypeScript declaration files) are excluded from the manifest.
Use --no-default-excludes
if you want to include all matching files and manage excludes yourself.
Contributing
For information on building and testing, please see CONTRIBUTING.md.
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0.
© 2025 Benny Powers web@bennypowers.com