62 Commits

Author SHA1 Message Date
David East 9bf8eae671 release: 0.4.0 (#161)
Test / test (push) Has been cancelled
Test / npm-registry-smoke-windows (push) Has been cancelled
0.4.0
2026-07-27 16:09:10 -04:00
Yudhi Armyndharis 6a879d73ca docs: correct lint/diff output examples and rule count in README (#119)
- lint `summary` uses the key `infos`, not `info`
- the `diff` JSON includes all token categories plus a `findings`
  block (before/after/delta) and `regression`; the example previously
  showed only two token categories and omitted `findings`
- the linter runs ten rules — add the missing `token-like-ignored` row

Co-authored-by: David East <deast@google.com>
2026-07-27 14:52:47 -04:00
Yudhi Armyndharis 59e41f15ba chore: declare supported Node engine range (>=18) (#124) 2026-07-27 14:52:39 -04:00
Zach Shallbetter 961439fc06 feat: add omitted frontmatter key to suppress expected-missing lint warnings (#155)
Implement support for an optional omitted frontmatter configuration key in DESIGN.md, allowing design system authors to explicitly declare token categories that are intentionally skipped or absent (Issue #78).

* Update Parser: Add 'omitted' to the known schema keys and types. Implement frontmatter parsing supporting both bare strings (e.g. - spacing) and object mappings with reasons (e.g. section: rounded, reason: "No rounded corners").
* Update Model: Forward the parsed omitted sections to the compiled DesignSystemState. Add optional rule property to linter Findings.
* Implement Omission Validation & Suppression:
  - Create omittedRule to validate the omitted configuration, warning on unknown or redundant sections (if tokens exist for a section listed in omitted).
  - Update missing-sections and missing-typography rules to skip warnings if the targets are explicitly listed as omitted.
  - Register the new rule in the default linter list.
* Test Coverage: Add test suites verifying frontmatter parsing, model mapping, linter warnings (declared-omission, redundant-omission, unknown-omission), and rule suppressions.
* Docs: Document the omitted frontmatter key in README.md and spec.mdx, update active rule counts, and regenerate docs/spec.md.

---------

Co-authored-by: David East <deast@google.com>
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Sudarshan sunil hadmode <sudarshan.deve@gmail.com>
2026-07-27 13:51:59 -04:00
jalendarreddy97 d2250c96a7 test(cli): add command integration test for css-tailwind export trailing newline (#144)
* fix: avoid extra css-tailwind newline

* chore: retrigger cla check

---------

Co-authored-by: David East <deast@google.com>
2026-07-27 13:00:33 -04:00
Mike ddd718a5cb test(linter): add unit test for single trailing newline in tailwind v4 serializer (#140)
Use stdout.write because serializeTailwindV4 already ends with one
newline; console.log added a second byte that broke git diff --check.

Also exit cleanly on missing DESIGN.md with a friendly message instead
of dumping a Node stack trace after the JSON error.

Fixes #139
Fixes #132

Co-authored-by: David East <deast@google.com>
2026-07-27 12:59:13 -04:00
Vedant Wagh bcfd0283ca feat: data-driven Color and Dimension type definitions (fixes #97) (#117)
Test / test (push) Has been cancelled
Test / npm-registry-smoke-windows (push) Has been cancelled
* feat: data-driven Color and Dimension type definitions (fixes #97)

* fix(export): align export test expectations with structured error formats

* fix(ts): eliminate duplicate typeDefinitions identifiers and properties for clean CI compilation

---------

Co-authored-by: David East <deast@google.com>
2026-07-24 17:12:13 -04:00
Yudhi Armyndharis 2513a54eca feat(lint): flag unrecognized typography sub-properties (#125)
Test / test (push) Has been cancelled
Test / npm-registry-smoke-windows (push) Has been cancelled
A typography token's sub-properties outside the schema (fontFamily,
fontSize, fontWeight, lineHeight, letterSpacing, fontFeature, fontVariation)
were silently dropped by the model — never resolved, never exported, and
with no diagnostic, so a typo like `fontwight` or an unsupported property
like `textTransform` vanished without a trace. Emit a warning for each,
mirroring how unknown component sub-tokens are already reported.
2026-07-22 12:36:52 -04:00
Arshdeep singh 6d53299bbd feat(linter): detect token name collisions (#150)
Adds duplicate and collision detection to the model builder for nested and flat token keys, preventing silent overwrites in the symbol table.
2026-07-22 12:36:11 -04:00
Syeda Qurrat-ul-Ain | AI Full-Stack Engineer 198b69fb4a Fix/spec command path (#157)
* fix(cli): add defensive type guard to parseDimension to prevent runtime crashes

* fix(cli): resolve spec.md path resolution issue in compiled CLI
2026-07-22 12:05:47 -04:00
Julio César Suástegui bde692f2bc fix: render primitive types from spec config (#131)
* fix: render primitive types from spec config

* chore: retrigger cla check

---------

Co-authored-by: Julio César Suástegui <juliosuas@users.noreply.github.com>
2026-07-13 21:46:17 -04:00
Yudhi Armyndharis e17180d751 fix(export): escape line terminators in Tailwind v4 CSS string values (#122)
cssStringLiteral escaped only backslash and double-quote. A font-family value
containing a raw newline, carriage return, or form feed (legal via a YAML
quoted or block scalar) was emitted verbatim inside the CSS string literal,
where raw line terminators are illegal and can break the value out of the
@theme token. Emit them as CSS hex escapes (e.g. `\a `).
2026-07-13 21:39:22 -04:00
Arpit Jain d060743604 fix(export): set exit code 0 on a successful export (#152)
The success branches (css-tailwind, json-tailwind, dtcg, css-vars) write
their output but never assign process.exitCode, so a successful export
left the code at its incoming value instead of an explicit 0. That is the
success-path counterpart to #126, which decoupled the exit code from
source lint findings; the subprocess test there only exercises json-tailwind
and a real process happens to exit 0 when exitCode is unset, so the gap went
unnoticed. Set process.exitCode = 0 after the format branches (every error
branch already returns first).

The in-process export.test.ts added in #109 asserts process.exitCode === 0
after a css-vars export, so it was failing on main. Also fix a companion
assertion in that file: it read error.error for the human message, but the
error envelope is { error: CODE, message: TEXT }, so the text lives on
error.message.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
2026-07-13 21:37:18 -04:00
Matt Van Horn ea4a3240d4 feat: add CSS custom properties export format (--format css-vars) (#109)
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-07-01 15:47:04 -04:00
Yudhi Armyndharis 3486d7a2df fix(export): exit 0 on a successful export regardless of source lint findings (#126)
The export command derived its exit code from the source's lint summary, so
exporting a file that had any lint *error* exited 1 even though the export
produced correct output. That conflates "the source has lint findings"
(which `lint` already reports by exiting 1) with "the export failed."

Decouple them: a successful export exits 0; only an invalid --format or an
emitter failure exits 1 (and an unreadable input exits 2, via readInput).
Document the export exit codes in the README.
2026-07-01 15:46:20 -04:00
Yudhi Armyndharis 2c876a0a08 fix(cli): emit a single structured error with the intended exit code on input failure (#123)
On a missing or unreadable input file, readInput printed a structured
FILE_READ_ERROR JSON to stderr and then re-threw. The throw let the CLI
framework print a second, stack-trace error on top of the JSON and override
the exit code with 1 instead of the intended 2. Exit cleanly with code 2
right after the JSON, matching the function's documented "exits with error
JSON" contract.

Also unify the export command's stderr error envelope with readInput's
`{ error: <CODE>, message }` shape: an unknown --format now reports
`INVALID_FORMAT` (the human text moves to `message`), and emitter failures
forward the emitter's structured code (e.g. INVALID_TOKEN_NAME) instead of
discarding it.
2026-07-01 15:44:25 -04:00
Vedant Wagh 0ef46706bb fix: print hint when stdin is a TTY to prevent silent hang (#146)
When a user runs a command with "-" as the file path from an interactive
terminal (e.g. design.md lint -), the process blocks silently waiting
for EOF with no indication of what to do.

Add a TTY check before the stdin read loop. If stdin is attached to a
terminal, write to stderr:

  Reading from stdin… Press Ctrl+D when done.

The stdin stream is accepted as an optional second parameter on readInput
(defaulting to process.stdin), making the TTY path fully testable via
dependency injection without touching process.stdin directly.

Also exports StdinStream so callers can type mock streams without
duplicating the definition.
2026-07-01 15:38:01 -04:00
Vedant Wagh ab4876f5f5 fix: graceful ENOENT error when DESIGN.md is missing (#132) (#145)
* fix: replace ENOENT stack trace with FileReadError and human-readable stderr (#132)

Introduce a typed `FileReadError` class in `readInput` so the function
throws instead of calling `process.exit` directly. Each command handler
catches it and writes a plain-text error to stderr:

  Error: "DESIGN.md" not found.
  Create a DESIGN.md file or pass "-" to read from stdin.

This replaces the unhandled Node.js stack trace dump reported in #132.
`readInput` is now unit-testable without mocking `process.exit`, and
`FileReadError.filePath` identifies the specific missing file (important
for `diff`, which reads two files).

* fix: use error code to generate accurate FileReadError message

Replace the hardcoded "not found" string in all command handlers with
a friendlyMessage getter on FileReadError that checks the OS error code:
- ENOENT → "not found. Create a DESIGN.md file or pass '-' for stdin."
- EACCES → "could not be read: permission denied."
- other  → "could not be read: <raw message>"

This prevents a misleading "not found" message when the file exists
but cannot be read due to permissions or other I/O errors.
2026-07-01 14:59:27 -04:00
Yudhi Armyndharis 9609945bd8 perf: bound token-validation cost on adversarial input (#121)
Three small guards so a hostile DESIGN.md cannot pin CPU or exhaust the
call stack. All inputs are at the documented untrusted boundary (arbitrary
file/stdin), and none of the changes alter results for legitimate input.

- parseDimensionParts (and token-like-ignored's CSS_DIMENSION_RE) backtrack
  quadratically on long all-digit strings. Cap value length to 64 chars
  before matching; real CSS dimensions are far shorter.
- unknown-key runs an O(n*m) Levenshtein DP against every schema key for
  each unknown key. Skip a schema key whose length differs by more than the
  typo threshold — edit distance is at least the length difference, so the
  set of suggestions is unchanged.
- parseCssColor recurses for nested color-mix() with no depth bound. Thread
  a depth counter and stop at 32, so an over-deep value resolves to an
  invalid color (a precise error finding) instead of a RangeError that
  collapses the whole model build.
2026-07-01 14:10:29 -04:00
Yudhi Armyndharis 2528279ab6 fix(color): correct grad hue parsing and reject non-percentage color-mix weights (#120)
parseHue tested `endsWith('rad')` before `endsWith('grad')`, so a gradian
angle matched the radians branch first: `100grad` resolved to ~329.58deg
instead of 90deg, silently producing the wrong color, luminance, contrast
result, and exports. Test `grad` before `rad`; deg/rad/turn/unitless
behavior is unchanged.

parseColorWithWeight treated any bare number as a weight and multiplied it
by 100, so `color-mix(in srgb, red 20, blue)` produced a wildly wrong blend
instead of being rejected. CSS color-mix weights are percentages only;
require a `%` suffix and otherwise return null (invalid color).
2026-07-01 14:04:28 -04:00
Sudarshan sunil hadmode d3e1a2588a fix(export): remove extra trailing newline in css-tailwind output (#151)
serializeTailwindV4() already appends a trailing newline to the
@theme block. Using console.log() adds a second trailing newline,
making checked-in generated CSS fail strict whitespace gates like
git diff --check.

Fixes #139

Change-Id: I3a0150b2c0f8e6a7b9d4c3e2f1a0b9c8d7e6f5a4
2026-07-01 13:59:45 -04:00
Yudhi Armyndharis 81a1be14cb fix: resolve spec.md from the CLI entry directory after build (#118)
`npx @google/design.md spec` failed with "Failed to load spec.md" in
installed/published packages. The bundler emits the CLI to dist/index.js,
so getSpecContent() resolves spec.md alongside it at dist/spec.md, but the
build only copied docs/spec.md to dist/linter/. The dev-path fallback then
resolves outside the package, so the command threw.

Copy spec.md to dist/ as well, mirroring how spec-config.yaml is already
copied to both dist/ and dist/linter/. Add a `spec` invocation to the
tarball smoke test so the bundled-spec.md resolution is exercised in CI.
2026-07-01 13:58:57 -04:00
Matt Van Horn 2a19f5dd97 feat: add token-like-ignored lint rule for silently dropped frontmatter keys (#105)
Closes #100

Add a new `token-like-ignored` lint rule that warns when a top-level YAML
key is not part of the recognized export schema and its value looks like a
design-token map (hex colors, CSS dimensions, or typography property names).
These keys are silently dropped by `design.md export`, misleading users into
thinking their color palette or type scale was exported.

- Extend `ParsedDesignSystem` with `rawValues` so the parser carries all
  raw YAML values through to the model layer
- Extend `DesignSystemState` with `unknownKeyValues` populated by `ModelHandler`
- New rule `token-like-ignored` in `linter/rules/token-like-ignored.ts`
- 10 tests covering hex color maps, font maps, dimension maps, flat scalars,
  non-token objects, nested maps, and multi-key scenarios
- Register rule in `DEFAULT_RULE_DESCRIPTORS` and re-export from public API
- Update hardcoded rule-count assertions in `types.test.ts` and `spec.test.ts`

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
0.3.0
2026-06-15 16:27:02 -04:00
David East fcae37652e release: 0.3.0 (#108)
* release: 0.3.0

* fix: remove hardcoded local path from DTCG conformance test

* test: skip DTCG conformance test (upstream @terrazzo/token-types removed from npm)
2026-06-15 15:23:56 -04:00
Vikas c22a601d33 fix: support nested token declarations in frontmatter (#103)
* fix: support nested token declarations in frontmatter (#102)

* fix: support numeric/boolean properties and limit nesting depth

---------

Co-authored-by: vikks <imvikks@gmail.com>
2026-06-11 18:40:23 -04:00
Matt Van Horn b6173b64e2 docs: document Windows/PowerShell npx invocation (#93) (#104)
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-06-11 18:39:09 -04:00
David East 780fa38538 docs: add PHILOSOPHY.md (#99) 2026-06-03 07:31:24 -04:00
David East 18508f27ab fix: remove stale deps, add lint script, pin CI bun version (#98)
- Remove dead runtime dependencies with zero imports: ink, react,
  @json-render/core, @json-render/ink, mdast (type-only import,
  covered by @types/mdast)
- Remove @types/react from devDependencies
- Add package-level lint script (tsc --noEmit --skipLibCheck) so
  turbo lint actually runs
- Fix 10 pre-existing type errors in handler.test.ts where
  properties.get() returns ResolvedValue but tests compared against
  raw primitives
- Pin CI bun version to 1.3.9 to match root packageManager field
  instead of floating on latest
- Use root-level turbo commands in CI instead of cd-ing into
  packages/cli
- Add lint step to CI pipeline
- Regenerate bun.lock after dependency removal

bun install now completes with no peer warnings.
bun run build, bun run test, and bun run lint all pass at the root.

Closes #30
2026-06-02 01:41:43 -04:00
David East ef72df6e07 docs: update color spec to document all supported CSS color formats (#96)
The linter already supports oklch, oklab, lab, lch, rgb, hsl, hwb,
named colors, color-mix, and 8-digit hex alpha. But the spec, README,
and error messages all said only hex was accepted. This was blocking
adoption for teams using modern CSS color spaces (Issue #53).

Update the Color type definition in the spec, the token types table in
the README, the spec.mdx source, and the linter error message to
reflect the full range of supported formats.

Closes #53
2026-06-02 01:29:05 -04:00
Ryo Matsukawa 5deefe14c6 feat(linter): add unknown-key rule for unknown top-level keys (#84)
* feat(linter): add unknown-key rule for unknown top-level keys

* refactor(linter): narrow unknown-key to typo detection via Levenshtein

DESIGN.md is intentionally extensible, so warning on every unknown
top-level key flags legitimate custom fields. Restrict the rule to
likely typos of known schema keys (edit distance ≤ 2, case-insensitive)
and stay silent for unrelated extension keys.

Per @davideast review feedback on #84:
- Add SCHEMA_KEYS / SchemaKey in parser/spec.ts as the single source
  of truth and reference it from the model handler.
- Add a zero-dependency Levenshtein helper.
- Suggest the closest known key in the warning message.

* test(linter): add unit tests for levenshtein helper

Cover empty strings, single edit operations (insert/delete/substitute),
symmetry, the classic kitten/sitting case, and the exact distances
used by the unknown-key typo threshold.
2026-06-02 01:18:05 -04:00
David East 2bcb6c6c7d fix: lint --format markdown renders report instead of [object Object] (#95)
formatAsMarkdown template-literaled obj.summary directly, which coerced
the lint summary object { errors, warnings, infos } to its toString
representation '[object Object]'.

Detect the lint output shape (findings array + numeric summary) and
render a proper markdown report with severity counts and a bulleted
findings list. The legacy string-summary path for fixer/diff shapes
is preserved.

Adds 6 tests covering the regression, findings with and without paths,
empty findings, the --format md alias, and the legacy fixer shape.

Fixes the bug originally reported in PR #56.
2026-06-02 00:28:16 -04:00
David East 4f28dd28ce fix(model): handle boolean YAML scalars in component props and add Issue #75 tests (#94)
The component property loop only checked for typeof 'number' before
passing values to string-only helpers (isTokenReference, isValidColor,
isParseableDimension). Boolean YAML values (e.g. visible: true) fell
through to those helpers and only survived by accident due to the typeof
guards added in PR #79. This change handles booleans explicitly alongside
numbers so the intent is clear.

Adds three tests covering the exact reproducer from Issue #75
(opacity: 0.9), boolean properties (visible: true), and a mixed case
with numbers, booleans, and strings in the same component.
2026-06-01 23:27:42 -04:00
Syeda Qurrat-ul-Ain | AI Full-Stack Engineer a02b2d785f fix(cli): prevent crash on non-string YAML properties (Issue #75) (#79) 2026-06-01 23:15:03 -04:00
Andrew Barnes 444b982c1e fix tailwind v4 digit token names (#72) 2026-06-01 23:12:06 -04:00
David East ad4a492121 release: 0.2.0 (#91) 2026-05-26 09:52:28 -04:00
Dion Almaer 887a4bff89 feat: support standard and CSS Color Module formats in validator and linter (#73) 2026-05-08 15:35:07 -04:00
David East 1d002db4db fix: rename tailwind export formats for clarity and backwards compat (#64)
Rename export format flags to avoid 'Tailwind CSS' product name confusion
and restore backwards compatibility:

- css-tailwind: Tailwind v4 CSS @theme block (new)
- json-tailwind: Tailwind v3 theme.extend JSON
- tailwind: backwards-compatible alias for json-tailwind

The output-first naming (css-*, json-*) tells the user what they'll get
before which tool it targets. Bare 'tailwind' preserves existing behavior
(JSON output), preventing a breaking change from PR #45.

Updates README.md export section and interop docs to reflect new naming.
2026-05-02 10:58:37 -04:00
sbrsubuvga 2013b6e916 feat: add Tailwind CSS v4 export support (#45)
Adds a `--format tailwind` export that emits a CSS `@theme { ... }`
block using Tailwind v4's native CSS-variable token namespaces
(--color-*, --font-*, --text-*, --leading-*, --tracking-*,
--font-weight-*, --radius-*, --spacing-*).

The previous v3 JSON output is preserved under the explicit
`--format tailwind-v3` name. Since the project is pre-1.0 (0.1.1),
renaming `tailwind` to mean 'latest' follows the convention most
tooling uses for unversioned names.

New module: packages/cli/src/linter/tailwind/v4/
  - spec.ts — types and Zod schema for v4 theme data
  - handler.ts — DesignSystemState → v4 theme data
  - serialize.ts — v4 theme data → CSS @theme string

Tests: 17 new tests (handler + serializer + fixture).
2026-05-02 10:41:13 -04:00
Juan Camilo Velásquez Amarillo fb20a4e2a2 docs(ci): clarify npm install on Windows and add registry smoke test (#57)
- Document quoting for scoped package in shells that treat @ specially
- Explain ENOVERSIONS and registry/.npmrc checks (addresses #55)
- Add Windows CI job that installs @google/design.md from npmjs.org

Made-with: Cursor
2026-05-02 09:57:25 -04:00
Saatvik Sawarn 654f4c174e fix(diff): include components in token diff and remove dead import (#51)
The diff command compared colors, typography, rounded, and spacing but
silently skipped components — changes to button styles, added/removed
component tokens, etc. were invisible in the output.

- Add `components` field to the tokens diff using a local serializer
  that flattens ComponentDef.properties Maps into plain objects before
  passing them to the existing diffMaps utility
- Remove the unused `serializeDesignSystem` import
- Add diff.test.ts with 4 cases: no-change, added, removed, modified
2026-05-02 09:56:09 -04:00
Tejas B K 8e81772fc7 fix(model): handle numeric component prop values without crashing (#43)
Numeric values such as fontWeight: 600 or borderWidth: 1 are valid per
the DESIGN.md spec, which states bare numbers and quoted strings are
equivalent. However, the component property loop in ModelHandler passed
all rawValues directly to isTokenReference / isValidColor, both of which
call .match() and crash when rawValue is a number.

Fix: add a typeof rawValue === 'number' guard at the top of the loop,
storing numeric values as-is — matching the pattern already used by
parseTypography for the same property.

Fixes #42
2026-05-02 09:50:27 -04:00
d 🔹 97b4df9290 fix(cli): add Windows-friendly designmd bin alias (#62)
Closes #54.

The existing `design.md` bin entry produces a `node_modules/.bin/design.md`
shim file on Windows. Because the basename ends in `.md`, Windows command
resolution short-circuits to the Markdown file association before iterating
PATHEXT, so PowerShell opens the shim in the user's Markdown editor
(VS Code by default) instead of executing it.

Add a `designmd` alias bin that resolves to the same entrypoint. The dot-free
name lets the npm CMD/PowerShell shims resolve cleanly via PATHEXT on Windows
while leaving the original `design.md` bin in place for posix users and
existing scripts.

* `packages/cli/package.json`: add the alias to the bin map.
* `README.md`: add a "Windows tip" callout under CLI Installation explaining
  when to reach for the alias.
* `packages/cli/scripts/check-package.ts`: new check #5c verifies the bin
  map exposes at least one dot-free alias so future package edits don't
  silently regress this.

Pre-existing failure #20 (`CLI spec command failed to load spec.md`)
reproduces on `main@8ecd464` with my changes stashed (23 pass / 1 fail);
adding 5c yields 24 pass / 1 fail, with no other deltas.

Co-authored-by: d 🔹 <258577966+voidborne-d@users.noreply.github.com>
2026-05-01 16:27:40 -07:00
Christian Oliff 00625b3d74 Update checkout action version from v4 to v6 (#58) 2026-05-01 19:07:34 -04:00
Matt Van Horn 344e20c655 fix(linter): orphaned-tokens should not flag MD3 paired tokens or baseline families (#59)
Components that reference one MD3 token (e.g. `colors.primary`) imply
the rest of the family (`on-primary`, `primary-container`,
`primary-fixed-dim`, `inverse-primary`, etc.) is part of the same
in-use semantic group. The rule now derives a family root for each
color name and treats sibling tokens as referenced when any sibling is.

The MD3 baseline families (primary, secondary, tertiary, error,
surface, background, outline) are also exempt from the orphaned check
because they are part of the standard contract a design system ships,
not optional decoration. Custom tokens (e.g. `brand-blue`) still get
flagged when truly unused.

Result on the shipped examples:
- atmospheric-glass: 43 orphan findings -> 0
- paws-and-paths:    33 orphan findings -> 0
- totality-festival: 38 orphan findings -> 0

Fixes #46

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-05-01 19:06:41 -04:00
Tejas B K 8ecd4645b9 fix: resolve token references in rounded and spacing sections (#26) 2026-04-22 14:22:35 -04:00
tototofu 677eacea4c fix: support transparent hex colors (#14) (#24) 2026-04-22 14:10:57 -04:00
David East 6589f05166 docs: update README and spec generation (#12)
- Replace outdated tailwind command with export command in root README
- Add spec:gen script to packages/cli/package.json
- Fix path to repo root in generate.ts so it can find docs/spec.md
- Ignore smoke-test/ and *.tgz in packages/cli/.gitignore
- Note: packages/cli/README.md is generated from root README and ignored.
0.1.1
2026-04-21 13:30:27 -04:00
David East 7eec9e0ff3 chore: packaging for release (#11)
* chore: remove unused TUI dependencies

* fix: remove debug logging and add lazy-loaded config singleton

- Remove console.log/console.error from loadSpecConfig() that corrupted
  stdout JSON output for CLI and programmatic consumers
- Introduce getSpecConfig() lazy singleton to cache YAML file reads
- Add 3 new tests: no-stdout-pollution, lazy-load validity, cache identity

Fixes Critical Blockers #1 and #2 from pre-publish analysis.

* fix: address high-risk publishing issues

- Add engines field to package.json (node >= 18)
- Add prepublishOnly script to enforce build before publish
- Add Node.js smoke test to CI workflow
- Clean up unused SPEC_VERSION import in test

* fix: derive version from package.json and simplify spec.md resolution

Version:
- Create src/version.ts that reads ../package.json using import.meta.url
- Path is stable across source, bundle, installed, and npx contexts
  because npm always includes package.json in the published tarball
- Replace hardcoded '0.1.0' in index.ts with dynamic VERSION import
- Add 3 tests: matches package.json, valid semver, not fallback

spec.md path resolution:
- Reduce 5 shotgun candidate paths to 2 deterministic strategies:
  1. Bundle path: ./spec.md (build copies it alongside entry points)
  2. Dev path: ../../../../../docs/spec.md (relative to source)
- Add explicit specPath parameter for callers who know the path
- Update build script to copy spec.md to both dist/ and dist/linter/
- Add 3 tests: consistency, content length, explicit path contract

* fix: pre-publish hardening — 5 items

1. Move build-only deps to devDependencies (keep zod for type compat)
   - citty, mdast, remark-*, unified, unist-util-visit, yaml all bundled
   - Zero runtime require() calls to any npm dependency
2. Add 'designmd' bin alias for Windows shell compatibility
   - cmd.exe confuses .md extension with file association
3. Add ./package.json to exports map
   - Prevents ERR_PACKAGE_PATH_NOT_EXPORTED in strict ESM bundlers
4. Remove stale @types/react from devDependencies
5. Add tarball smoke test to CI workflow
   - Packs, installs in clean dir, runs CLI + programmatic import
   - Catches 'works in monorepo, breaks when installed' bugs
0.1.0
2026-04-21 11:52:42 -04:00
David East 89012cc4d1 docs: set up licensing and headers (#10)
* docs: update recommended tokens in spec

* feat: set up OSS boilerplate and license headers

* chore: update package.json for npm publish readiness

* chore: update build script and ignore copied files in packages/cli
2026-04-21 10:28:35 -04:00
David East 5361b6ec32 docs: update recommended tokens in spec (#9) 2026-04-20 13:14:05 -04:00