@pwrs/cem

Dark Mode

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 for extends 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

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 -

See the test-fixtures directory for examples

HTML Template Analysis for Slots and Parts

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

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