# How DESIGN.md Handles Unknown Sections, Tokens, and Component Properties

> DESIGN.md detects unknown sections, tokens, and component properties, records them, and emits diagnostic warnings with typo suggestions for correction.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: how-to-guide
- Published: 2026-07-03

---

**DESIGN.md detects unknown sections, tokens, and component properties, records them in the `DesignSystemState` while preserving the original document structure, and emits diagnostic warnings with typo suggestions to help authors correct mistakes.**

The [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) linter uses a defensive parsing strategy to manage design system documentation that extends beyond the official schema. When processing a [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) file, the system identifies unrecognized headings, YAML keys, and component properties, ensuring that unknown content is neither deleted nor silently ignored. This approach allows authors to experiment with custom extensions while receiving actionable feedback on potential schema violations.

## Detecting Unknown Top-Level Sections

When the parser encounters a section heading that is not part of the canonical schema, the fixer in [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts) records it as an *unknown* section. During a "fix" operation, the system preserves the unrecognized section but relocates it to the end of the file. This ensures that known sections can be reordered according to specification while maintaining document integrity.

The behavior is verified by the test case **"should append unknown sections at the end"** in [`packages/cli/src/linter/fixer/handler.test.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.test.ts).

```typescript
import { fixSectionOrder } from '@design.md/cli';

const input = {
  content: '',
  sections: [
    { heading: 'Unknown', content: '## Unknown\ncontent' },

    { heading: 'Colors',   content: '## Colors\ncontent' },

    { heading: 'Overview', content: '## Overview\ncontent' },

  ],
};

const result = fixSectionOrder(input);
// result.fixedContent ends with the unknown section:
// ...## Colors\ncontent\n## Overview\ncontent\n## Unknown\ncontent

```

## Recording Unknown Keys and Tokens

The parser constructs a `DesignSystemState` object defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts) that explicitly tracks unrecognized content through the `unknownKeys` and `unknownKeyValues` properties. These collections store raw YAML keys that the schema does not recognize, allowing downstream rules to inspect them without discarding data.

During parsing, [`packages/cli/src/linter/parser/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/parser/handler.ts) populates these fields alongside `rawValues` for recognized keys, ensuring the original [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) can be reconstructed unchanged after linting or fixing operations.

## Diagnostic Reporting for Unknown Keys

The `unknownKey` rule in [`packages/cli/src/linter/linter/rules/unknown-key.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/unknown-key.ts) walks through `state.unknownKeys` and performs a **Levenshtein distance** check against the list of known top-level keys. When a close match is detected, the linter emits a diagnostic finding such as `"Unrecognized top-level key 'Colrs'; did you mean 'Colors'?"`, helping authors identify and correct typos.

```typescript
import { unknownKey } from '@design.md/cli/linter/rules/unknown-key';

const state = {
  unknownKeys: ['Colrs'],               // typo in a known key
  unknownKeyValues: { Colrs: { red: '#ff0000' } },
  // …other required fields omitted for brevity
};

const findings = unknownKey(state);
// → [{ message: "Unrecognized top‑level key ‘Colrs’; did you mean ‘Colors’?" }]

```

## Identifying Token-Like Unknown Keys

Some unknown keys may contain hex colors, dimension values, or `fontFamily` properties that resemble legitimate design tokens. The `token-like-ignored` rule in [`packages/cli/src/linter/linter/rules/token-like-ignored.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/token-like-ignored.ts) spots these patterns and warns the author that a top-level key appears token-like but is not recognized by the schema.

```typescript
import { tokenLikeIgnored } from '@design.md/cli/linter/rules/token-like-ignored';

const state = {
  unknownKeys: ['brandColors'],
  unknownKeyValues: {
    brandColors: { primary: '#0061ff', secondary: '#e0e0e0' },
  },
  // …other required fields
};

const findings = tokenLikeIgnored(state);
// → warning that “brandColors” looks like a token map but isn’t a recognized schema key

```

## Component Property Validation

Component sub-tokens such as `fontWeight` and `borderWidth` are declared in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) via the `component_sub_tokens` definition. The model validator in [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts) checks each component's `properties` map against this allowed set. If a property name is not recognized, it is routed to `unknownKeys` and `unknownKeyValues`, where it is reported using the same diagnostic mechanisms as top-level unknown keys.

```typescript
import { resolveComponentProperties } from '@design.md/cli/linter/model/handler';

const component = {
  name: 'Button',
  properties: new Map([['fontWeight', '600']]),  // valid
};

const result = resolveComponentProperties(component);
// → succeeds because ‘fontWeight’ is listed in COMPONENT_SUB_TOKENS

const badComponent = {
  name: 'Button',
  properties: new Map([['unknownProp', 'value']]),
};

const badResult = resolveComponentProperties(badComponent);
// → unknown property ends up in unknownKeys → diagnostics emitted

```

## Preserving Unknown Content

The parser never discards unknown sections, keys, or properties. All raw values are maintained in `rawValues` (for recognized keys) and `unknownKeyValues` (for unrecognized keys), enabling the linter to reconstruct the original document exactly. This preservation strategy ensures that experimental or custom extensions are not destroyed during automated formatting or fixing operations.

## Summary

- **Detection**: Unknown sections, keys, and component properties are identified during parsing and recorded in `DesignSystemState`.
- **Reordering**: Unknown sections are moved to the end of the file during fix operations to allow proper ordering of known sections.
- **Diagnostics**: The linter uses Levenshtein distance to suggest corrections for typos and warns about token-like keys that may be schema omissions.
- **Preservation**: All original content is stored in `rawValues` and `unknownKeyValues`, allowing full document reconstruction without data loss.

## Frequently Asked Questions

### What happens to unknown sections when DESIGN.md fixes document structure?

The fixer in [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts) preserves unknown sections but moves them to the end of the file. This allows the linter to reorder canonical sections according to the schema while keeping unrecognized content intact and readable.

### How does DESIGN.md suggest corrections for misspelled keys?

The `unknownKey` rule in [`packages/cli/src/linter/linter/rules/unknown-key.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/unknown-key.ts) calculates the Levenshtein distance between unrecognized keys and known schema keys. When a close match is found, it emits a diagnostic message asking if the author meant the similar recognized key, such as suggesting "Colors" for "Colrs".

### Are unknown component properties deleted during linting?

No. Unknown component properties are routed to `unknownKeys` and `unknownKeyValues` in the `DesignSystemState` defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts). Like unknown top-level keys, they are preserved in the document and reported as diagnostics, allowing authors to correct or formalize them without losing data.

### Can DESIGN.md distinguish between custom keys and token-like typos?

Yes. The `token-like-ignored` rule in [`packages/cli/src/linter/linter/rules/token-like-ignored.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/token-like-ignored.ts) specifically identifies unknown keys that contain token-like structures such as hex colors or dimension values. This helps authors distinguish between intentional custom extensions and accidental misspellings of standard token keys.