Skip to content

Configuration

@cssdoc/core ships an expansive standard tag vocabulary out of the box, so most projects need no configuration. When you want custom tags or want to turn standard ones off, add a cssdoc.json and load it with @cssdoc/config — the analog of @microsoft/tsdoc-config.

sh
npm i -D @cssdoc/config @cssdoc/core

cssdoc.json

jsonc
{
  "$schema": "https://cssdoc.dev/cssdoc.schema.json",
  "extends": ["./base.cssdoc.json"],
  "noStandardTags": false,
  "tagDefinitions": [
    { "tagName": "@token", "syntaxKind": "block", "allowMultiple": true },
    { "tagName": "@pattern", "syntaxKind": "record", "recordKind": "layout" },
  ],
  "supportForTags": {
    "@privateRemarks": false,
  },
  "modifierConvention": "bem",
  "rules": {
    "unknown-modifier": "warn",
  },
}
FieldMeaning
extendsPaths (local ./… or package specifiers) to other cssdoc.json files to inherit from.
noStandardTagsDisable every built-in standard tag; only tagDefinitions remain.
tagDefinitionsCustom tags: tagName, syntaxKind (record/block/modifier/inline), allowMultiple?, recordKind?, aliasFor?.
supportForTagsEnable or disable specific tags by name.
modifierConventionHow modifier classes are spelled — a preset (bem, rscss, bare) or a custom object. A custom object can also map BEM elements to parts (elementSeparator), state classes to states (statePrefixes), and native pseudo-classes to states (statePseudoClasses). Defaults to bem.
rulesPer-rule severity overrides (off/warn/error).
namingName-case to enforce on component/part class names — a preset (pascalCase/camelCase/lowercase) or a custom regex.
structureIgnoreClass names exempt from structure-unknown-selector — external classes (utilities, cross-component refs) named in @structure. Literal names or simple * globs (e.g. util-*).
providersUpstream cssdoc providers this config consumes — [{ path, baseHref? }]. Their documented components resolve in this scope's lint and hover. See below.

See Modifier conventions for the convention forms and the full rule list.

A render block configures markdown output: structureView chooses which Structure representation(s) render ("text"/"diagram"/"both", default "both"); structureVariantView chooses how @variant alternatives render when authored ("diagram", default — one combined flowchart with a labelled subgraph per variant — or "sections" for separate ### Variant: <name> subsections). See Authoring → Alternative structures.

Consuming another provider

extends inherits configuration (tags, convention, rules); providers imports another provider's components, so a consumer can compose them without a false structure-unknown-selector and get hover on their classes. The two are orthogonal — a consumer typically uses both.

jsonc
{
  "extends": ["../vendor/cssdoc.json"], // convention + tags
  "providers": [
    { "path": "../vendor/vendor.css", "baseHref": "/vendor/" }, // local source (parsed with its own convention)
    { "path": "@vendor/ui/model.json", "baseHref": "https://vendor.dev/api/" }, // a published model
  ],
}

Each path resolves relative (./…) or via Node resolution (a package specifier). A .json path loads a published model — the @cssdoc/json emitter's model.json (a CssDocEntry[]); any other path is a source stylesheet, parsed with the provider's own governing cssdoc.json convention. baseHref prefixes links to the provider's rendered doc pages (<baseHref><name>.md).

Rule severities

Each lint rule has a configurable severity — off, warn, or error — set under rules in cssdoc.json:

jsonc
{
  "modifierConvention": "bem",
  "rules": {
    "unknown-modifier": "warn",
    "undocumented-modifier": "error",
  },
}

The rule ids:

RuleDefaultFires when…
missing-summarywarna record has no @summary.
undocumented-modifierwarna modifier has no @modifier description.
deprecated-requires-canonicalwarna deprecated modifier has no replacement.
name-not-in-csswarna documented modifier/part isn't in any selector.
unknown-modifierwarna consumer uses a modifier candidate that isn't documented.
deprecated-modifierwarna consumer uses a deprecated modifier.
unknown-statewarna consumer uses a state class (statePrefixes) that isn't documented.
unknown-partwarna consumer uses an element class (elementSeparator) that isn't documented.
undocumented-partwarna part has no @part description.
undocumented-css-partwarna shadow part (@csspart) has no description.
component-name-casewarna component class breaks the configured naming.component case (see below).
part-name-casewarna part class breaks the configured naming.part case.
disallowed-elementwarna component is used on a host tag outside the documented @element allow-list.
duplicate-record-iderrora record id is duplicated for the same kind in the current scope.
duplicate-record-id-cross-kindwarna record id is shared across kinds (for example component + layout).
structure-unknown-selectorwarnan @structure selector names a class that isn't a documented member.
structure-unknown-recordwarnan @structure record reference targets no documented record of that name/kind.
structure-ambiguous-recordwarnan untyped @structure record reference matches multiple kinds.
invalid-default-valuewarna registered property's default doesn't match its syntax.
invalid-property-valuewarnan assignment doesn't match a property's declared syntax.
invalid-fallback-valuewarna var(--x, …) fallback doesn't match the declared syntax.
unknown-custom-propertyoffa var(--x) isn't documented (opt-in via a property prefix).
cssdoc-directivewarna cssdoc-expect-error directive matched no problem (unused expectation).

unknown-modifier defaults to warn because BEM's -- is an unambiguous signal — only base--… tokens are candidates. Under weak-signal conventions (bare/OOCSS), where every chained class is a candidate, set it to off to avoid flagging unrelated classes.

Loading it

ts
import { CssDocConfigFile } from "@cssdoc/config";
import { parseCssDocs } from "@cssdoc/core";

const configFile = CssDocConfigFile.loadForFolder(process.cwd());
if (configFile.hasErrors) console.warn(configFile.getErrorSummary());

const model = parseCssDocs(css, { configuration: configFile.toConfiguration() });

loadForFolder walks up to the nearest cssdoc.json (or cssdoc.jsonc). A missing file is not an error; a malformed one collects messages on getErrorSummary() instead of throwing (it's validated against a JSON schema). Either name is parsed as JSON with comments, so you can annotate your config with // comments and trailing commas — name it cssdoc.jsonc to make that explicit to your editor.

Every cssdoc tool that reads CSS — the emitters, generators, linters, and language server — accepts the same configuration, so a custom tag you register is understood everywhere.

Released under the MIT License