spec-layer 0.6.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -42
- package/dist/cli.js +501 -151
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,12 @@ against them. The Foundation landing under `tokens/` as Design Tokens Format
|
|
|
60
60
|
Module 2025.10 files, rather than `ai/foundation.yaml`, needs 0.4.0 or later.
|
|
61
61
|
`tools` and `skill` need 0.5.0 or later. `components/` in place of
|
|
62
62
|
`ai/components/`, `path` in place of `aiPath` in the manifest, and the
|
|
63
|
-
`outputs` block need 0.6.0 or later.
|
|
63
|
+
`outputs` block need 0.6.0 or later. `component-specs/` beside `tokens/`,
|
|
64
|
+
`componentSpecsDir`, cwd-relative manifest paths, and the `tokens/` directory
|
|
65
|
+
need 0.7.0 or later. The `census` and `config_hash` blocks inside
|
|
66
|
+
`resolver.json`, and the `transform` and `resolved` fields in
|
|
67
|
+
`spec-layer.meta.json`, need 0.8.0 or later; an earlier version pulls the same
|
|
68
|
+
files without those fields.
|
|
64
69
|
|
|
65
70
|
## Commands
|
|
66
71
|
|
|
@@ -146,7 +151,7 @@ carry no key and are meant to be committed with the rest of the repository.
|
|
|
146
151
|
## Pulling part of a library
|
|
147
152
|
|
|
148
153
|
By default `pull` writes the Foundation and every documented component. When
|
|
149
|
-
your repo implements only some of them, narrow what lands in `
|
|
154
|
+
your repo implements only some of them, narrow what lands in `component-specs/`:
|
|
150
155
|
|
|
151
156
|
```bash
|
|
152
157
|
npx spec-layer pull --only foundation # tokens and styles, no components
|
|
@@ -177,7 +182,7 @@ That stores an `include` block in `speclayer.json`:
|
|
|
177
182
|
Selection flags on `pull` replace the stored selection for that run; they are
|
|
178
183
|
never merged with it.
|
|
179
184
|
|
|
180
|
-
The selection only decides which `
|
|
185
|
+
The selection only decides which `component-specs/` files are written. `bundle.json`
|
|
181
186
|
always holds the whole library, so `list` and `show` can answer for any
|
|
182
187
|
artifact, written or not, and `status` compares one hash.
|
|
183
188
|
|
|
@@ -244,7 +249,7 @@ matter what the ignore rules say.
|
|
|
244
249
|
```text
|
|
245
250
|
.speclayer/
|
|
246
251
|
bundle.json the published bundle, verbatim
|
|
247
|
-
manifest.json
|
|
252
|
+
manifest.json every artifact indexed by content hash and path, plus the selection, outputs, and componentSpecsDir
|
|
248
253
|
tokens/ the Foundation as Design Tokens Format Module 2025.10 files
|
|
249
254
|
<collection>.<mode>.json one file per collection and mode, rooted at the collection name
|
|
250
255
|
styles.typography.json text styles as typography composites (when present)
|
|
@@ -252,19 +257,22 @@ matter what the ignore rules say.
|
|
|
252
257
|
resolver.json Design Tokens Resolver Module 2025.10: sets, modifiers, order
|
|
253
258
|
spec-layer.meta.json Figma ids, scopes, code syntax, publication, keyed by DTCG path
|
|
254
259
|
report.json what DTCG could not express, with reasons and stable ids
|
|
255
|
-
components/<name>.yaml one file per selected component
|
|
256
260
|
outputs/
|
|
257
|
-
web-css.map.json DTCG path -> CSS custom property,
|
|
258
|
-
web-css.report.json what the CSS
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
web-css.map.json DTCG path -> CSS custom property, where the name came from, and which file declares it
|
|
262
|
+
web-css.report.json what the CSS files could not express
|
|
263
|
+
component-specs/
|
|
264
|
+
<name>.yaml one brief per selected component, byte-identical to Copy for AI
|
|
265
|
+
tokens/
|
|
266
|
+
index.css imports every file below, in resolver order
|
|
267
|
+
<collection>.css one file per single-mode collection, at :root
|
|
268
|
+
<collection>.<mode>.css one file per mode of a multi-mode collection; the default at :root
|
|
261
269
|
```
|
|
262
270
|
|
|
263
|
-
Point your agent at
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
Point your agent at `component-specs/` and `.speclayer/tokens/`, and import
|
|
272
|
+
`tokens/index.css` from the platform's root stylesheet. The component YAML is
|
|
273
|
+
the same compact form the plugin's **Copy for AI** puts on your clipboard;
|
|
274
|
+
`bundle.json` additionally holds the full canonical artifacts if you need
|
|
275
|
+
them.
|
|
268
276
|
|
|
269
277
|
In `manifest.json`, an artifact the selection left unwritten has `"path":
|
|
270
278
|
null`. A manifest from CLI 0.1.0 has no `selection` field and means
|
|
@@ -275,12 +283,19 @@ interrupted pull never leaves a half-written directory. `pull` refuses an
|
|
|
275
283
|
output directory that is the current directory, a parent of it, or an existing
|
|
276
284
|
non-empty directory it did not write, since the swap replaces that directory.
|
|
277
285
|
|
|
286
|
+
`component-specs/` and `tokens/` are written in place, not swapped. `pull`
|
|
287
|
+
owns exactly the files there that begin with its marker (the CSS header, or
|
|
288
|
+
the brief's opening `spec_layer:` lines): it replaces or removes those,
|
|
289
|
+
ignores dotfiles, and refuses to run when anything else is present. A
|
|
290
|
+
repository that already uses a path can set `componentSpecsDir` or
|
|
291
|
+
`outputs[].path`.
|
|
292
|
+
|
|
278
293
|
When nothing changed since the last pull with the same selection, `pull`
|
|
279
294
|
prints `Already up to date` and writes nothing. Every republish stamps a new
|
|
280
295
|
export id and time into the canonical artifacts, so `bundle.json` and
|
|
281
296
|
`manifest.json` change on each republish even when the content did not. The
|
|
282
|
-
`
|
|
283
|
-
stable.
|
|
297
|
+
`component-specs/` YAML files, the `.speclayer/tokens/` files, and the
|
|
298
|
+
`tokens/` CSS stay stable.
|
|
284
299
|
|
|
285
300
|
## Configuring the token output
|
|
286
301
|
|
|
@@ -309,19 +324,26 @@ the report are not token files; exclude them from token globs.
|
|
|
309
324
|
|
|
310
325
|
## Token files for your code
|
|
311
326
|
|
|
312
|
-
`pull` also writes a
|
|
313
|
-
|
|
314
|
-
when that pull writes the Foundation; with
|
|
315
|
-
exactly as it was, and `list` shows it as
|
|
327
|
+
`pull` also writes a `tokens/` directory at `outputs[].path`: one CSS file
|
|
328
|
+
per collection and mode plus `index.css`, one per platform output. The
|
|
329
|
+
directory is written only when that pull writes the Foundation; with
|
|
330
|
+
`--only components` it is left exactly as it was, and `list` shows it as
|
|
331
|
+
`not written`.
|
|
316
332
|
|
|
317
333
|
```css
|
|
334
|
+
/* Generated by spec-layer from library lib_..., foundation sha256:..., web/css/kebab.
|
|
335
|
+
Do not edit. Change the design in Figma, republish, and run spec-layer pull. */
|
|
336
|
+
|
|
318
337
|
:root {
|
|
319
338
|
/* Foundation */
|
|
320
339
|
--foundation-colors-blue-500: #2e72d1;
|
|
321
340
|
--foundation-spacing-200: 8px;
|
|
322
|
-
/* Mapped Colors, Light */
|
|
323
|
-
--mapped-colors-surface-primary-default: var(--foundation-colors-blue-500);
|
|
324
341
|
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
```css
|
|
345
|
+
/* Generated by spec-layer from library lib_..., foundation sha256:..., web/css/kebab.
|
|
346
|
+
Do not edit. Change the design in Figma, republish, and run spec-layer pull. */
|
|
325
347
|
|
|
326
348
|
[data-theme="dark"] {
|
|
327
349
|
/* Mapped Colors, Dark */
|
|
@@ -329,23 +351,42 @@ exactly as it was, and `list` shows it as `not written`.
|
|
|
329
351
|
}
|
|
330
352
|
```
|
|
331
353
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
354
|
+
`index.css` holds the header, then one comment and one import per file, in
|
|
355
|
+
resolver order, and no declarations of its own:
|
|
356
|
+
|
|
357
|
+
```css
|
|
358
|
+
/* Generated by spec-layer from library lib_..., foundation sha256:..., web/css/kebab.
|
|
359
|
+
Do not edit. Change the design in Figma, republish, and run spec-layer pull. */
|
|
360
|
+
|
|
361
|
+
/* Foundation */
|
|
362
|
+
@import "./foundation.css";
|
|
363
|
+
/* Mapped Colors, Dark */
|
|
364
|
+
@import "./mapped-colors.dark.css";
|
|
365
|
+
```
|
|
337
366
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
367
|
+
A set, which has one mode by construction, writes one file named for the
|
|
368
|
+
collection alone, at `:root`. A collection with modes writes one file per
|
|
369
|
+
mode: the default mode's file sits at `:root`, every other mode's file under
|
|
370
|
+
`[data-theme="<mode>"]`. Aliases stay as `var()`. A number whose Figma scopes
|
|
371
|
+
state no unit stays a bare number. Nothing about a mode's name selects a
|
|
372
|
+
media query. To let the OS choose a theme, set that collection's selector to
|
|
373
|
+
`:root` under `modes` and import the mode's file yourself under `@media
|
|
374
|
+
(prefers-color-scheme: dark)`. The CLI never assumes that.
|
|
375
|
+
|
|
376
|
+
The directory is written **in place** at the path in `speclayer.json`,
|
|
377
|
+
outside the managed directory, so your bundler keeps watching it and the diff
|
|
378
|
+
shows up in review. Every file begins with a header naming the library and
|
|
379
|
+
the Foundation's content hash; `pull` owns exactly the files there that begin
|
|
380
|
+
with it, replacing or removing those, ignoring dotfiles, and refusing to run
|
|
381
|
+
when anything else is present. A `speclayer.json` written by CLI 0.6.0 names
|
|
382
|
+
a `.css` file at this path, and `pull` refuses it: set `path` to a directory
|
|
383
|
+
and delete the old file.
|
|
343
384
|
|
|
344
385
|
```json
|
|
345
386
|
{
|
|
346
387
|
"platforms": ["web"],
|
|
347
388
|
"outputs": [
|
|
348
|
-
{ "platform": "web", "format": "css", "path": "
|
|
389
|
+
{ "platform": "web", "format": "css", "path": "tokens", "case": "kebab" }
|
|
349
390
|
]
|
|
350
391
|
}
|
|
351
392
|
```
|
|
@@ -355,28 +396,28 @@ at the repository root, so the path is always on record. `pull` writes every
|
|
|
355
396
|
entry; `"outputs": []` writes none. `case` chooses how derived names are
|
|
356
397
|
spelled: `kebab` (default), `camel`, `pascal`, `snake`, or `constant`. A name
|
|
357
398
|
the designer declared as `code_syntax` in Figma is used verbatim and never
|
|
358
|
-
re-cased. `.speclayer/outputs/web-css.map.json` records every emitted name
|
|
359
|
-
whether it was declared or derived
|
|
360
|
-
both omitted and listed in `web-css.report.json`.
|
|
399
|
+
re-cased. `.speclayer/outputs/web-css.map.json` records every emitted name,
|
|
400
|
+
whether it was declared or derived, and which file declares it; two tokens
|
|
401
|
+
that would share a name are both omitted and listed in `web-css.report.json`.
|
|
361
402
|
|
|
362
403
|
Two collections with modes share one attribute by default, which cannot be
|
|
363
404
|
right for both; the report says so, and `modes` declares a selector per
|
|
364
405
|
collection:
|
|
365
406
|
|
|
366
407
|
```json
|
|
367
|
-
{ "platform": "web", "format": "css", "path": "
|
|
408
|
+
{ "platform": "web", "format": "css", "path": "tokens",
|
|
368
409
|
"modes": { "Density": "[data-density=\"{mode}\"]" } }
|
|
369
410
|
```
|
|
370
411
|
|
|
371
412
|
`root` and `modeSelector` override the defaults `:root` and
|
|
372
413
|
`[data-theme="{mode}"]`; `{mode}` and `{collection}` are replaced by slugs.
|
|
373
414
|
A repository that already builds tokens with Style Dictionary can keep reading
|
|
374
|
-
|
|
375
|
-
source, so import one or the other.
|
|
415
|
+
`.speclayer/tokens/`: the CSS files are a projection of the same record, not a
|
|
416
|
+
second source, so import one or the other.
|
|
376
417
|
|
|
377
|
-
Commit `.speclayer/`, `speclayer.json`, and the output
|
|
378
|
-
that would rather regenerate in CI ignores them and runs
|
|
379
|
-
`status` exits `2` when a pull is due.
|
|
418
|
+
Commit `.speclayer/`, `speclayer.json`, `component-specs/`, and the output
|
|
419
|
+
paths. A repository that would rather regenerate in CI ignores them and runs
|
|
420
|
+
`pull` there; `status` exits `2` when a pull is due.
|
|
380
421
|
|
|
381
422
|
## Exit codes
|
|
382
423
|
|