@kanso-labs/unplugin-style-dictionary 0.7.0 → 0.9.0
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 +432 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +266 -27
- package/dist/index.js.map +1 -1
- package/dist/rolldown.d.ts +2 -2
- package/dist/rollup.d.ts +2 -2
- package/dist/types.d.ts +190 -2
- package/dist/vite.d.ts +2 -2
- package/dist/webpack.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,12 +21,16 @@ build on Rolldown/tsdown) that both need tokens compiled ahead of them.
|
|
|
21
21
|
- **Asynchronous builds**: Native support for Style Dictionary v4/v5 async
|
|
22
22
|
compilation API.
|
|
23
23
|
- **Automatic watching**: Reads the `source` and `include` patterns from your
|
|
24
|
-
Style Dictionary configurations and watches the files they match
|
|
25
|
-
|
|
24
|
+
Style Dictionary configurations and watches the files they match, including a
|
|
25
|
+
token package resolved through `node_modules` in a workspace. What a change
|
|
26
|
+
then triggers depends on the target — see
|
|
26
27
|
[Watching, per target](#watching-per-target).
|
|
27
28
|
- **Config flexibility**: Supports file paths (JSON, JSON5, JSONC, JS, MJS, TS),
|
|
28
29
|
configuration objects, or functions — including registering custom formats at
|
|
29
30
|
config-resolution time.
|
|
31
|
+
- **Error overlay**: A rebuild that fails under Vite's dev server is pushed to
|
|
32
|
+
the error overlay rather than only to the terminal, and cleared on the next
|
|
33
|
+
one that succeeds.
|
|
30
34
|
- **Atomic writes**: Every generated file is written to a temporary sibling and
|
|
31
35
|
renamed into place, so code importing a token file while it is being rebuilt
|
|
32
36
|
never reads a half-written file.
|
|
@@ -124,6 +128,33 @@ _The subpaths also need a TypeScript `moduleResolution` of `bundler`, `node16`
|
|
|
124
128
|
or `nodenext`. The deprecated `node10` cannot resolve them, and TypeScript 6
|
|
125
129
|
already warns that it stops working in 7._
|
|
126
130
|
|
|
131
|
+
### Finding a Config File
|
|
132
|
+
|
|
133
|
+
With no `config`, the root is searched for `sd.config.json`, `config.json`,
|
|
134
|
+
`sd.config.js` and `sd.config.mjs`, in that order — and the first one that
|
|
135
|
+
**looks like a Style Dictionary configuration** wins. That means declaring at
|
|
136
|
+
least one of `platforms`, `source`, `include` or `tokens`. A candidate that
|
|
137
|
+
fails the check is reported and skipped rather than adopted, so an unrelated
|
|
138
|
+
`config.json` — an extremely common name for something else — no longer gets
|
|
139
|
+
compiled over and added to the watch set. The path that was picked is printed,
|
|
140
|
+
so which configuration a build used is answerable from the console.
|
|
141
|
+
|
|
142
|
+
`config.json` stays in the list because Style Dictionary's own CLI defaults to
|
|
143
|
+
it, so a project relying on that default keeps working.
|
|
144
|
+
|
|
145
|
+
**Two of the four names are modules, and reading a module runs it.** A root
|
|
146
|
+
`sd.config.js` is imported — freshly, on every watch event — and validation
|
|
147
|
+
cannot prevent that, because the check can only look at what the import
|
|
148
|
+
returned. If you name your configuration explicitly, or have none, say so:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
StyleDictionary({ config: false })
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
That turns discovery off entirely: nothing is looked for, nothing is watched,
|
|
155
|
+
and nothing is compiled. A configuration you name yourself is never
|
|
156
|
+
second-guessed by the check above — it goes straight to Style Dictionary.
|
|
157
|
+
|
|
127
158
|
### Config File Formats
|
|
128
159
|
|
|
129
160
|
A `config` path may be `.json`, `.json5`, `.jsonc`, `.js`, `.mjs` or `.ts`. The
|
|
@@ -191,6 +222,38 @@ source and no config file does not reach it, so a dev server editing unrelated
|
|
|
191
222
|
project files leaves it alone — treat it as the place to prepare a build, not as
|
|
192
223
|
a general file-change hook.
|
|
193
224
|
|
|
225
|
+
**It is handed what the host is doing**, so the configuration it returns can
|
|
226
|
+
depend on it — build an expensive platform on `vite build` and skip it while the
|
|
227
|
+
dev server runs:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
styleDictionaryPlugin({
|
|
231
|
+
config: ({ command, mode, watch }) => ({
|
|
232
|
+
source: ['tokens/**/*.json'],
|
|
233
|
+
platforms: {
|
|
234
|
+
css: {
|
|
235
|
+
transformGroup: 'css',
|
|
236
|
+
buildPath: 'dist/',
|
|
237
|
+
files: [{ destination: 'vars.css', format: 'css/variables' }],
|
|
238
|
+
},
|
|
239
|
+
// Shells out to a native toolchain, so it is worth a minute of a real
|
|
240
|
+
// build and not worth a second of every rebuild.
|
|
241
|
+
...(command === 'build' && !watch ? { ios: iosPlatform(mode) } : {}),
|
|
242
|
+
},
|
|
243
|
+
}),
|
|
244
|
+
})
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`command` is `'serve'` only under Vite's dev server; every other target builds.
|
|
248
|
+
`mode` is Vite's or webpack's own, and follows `command` on rollup and rolldown,
|
|
249
|
+
which have no such concept. `watch` is read from the host rather than inferred
|
|
250
|
+
from `command`, because `rollup --watch` both watches and builds. The full
|
|
251
|
+
contract is [`StyleDictionaryConfigContext`](#options-reference).
|
|
252
|
+
|
|
253
|
+
A function taking no arguments stays valid — TypeScript accepts one of fewer
|
|
254
|
+
parameters and JavaScript ignores the extra argument — so the example below
|
|
255
|
+
needs no change.
|
|
256
|
+
|
|
194
257
|
```typescript
|
|
195
258
|
// Named `styleDictionaryPlugin` here to avoid colliding with the `StyleDictionary`
|
|
196
259
|
// class imported from the `style-dictionary` package itself, below.
|
|
@@ -252,12 +315,78 @@ reaches no hook, while on a Linux runner the same edit reaches a rebuild. Treat
|
|
|
252
315
|
rolldown's watch mode as compiling once and not tracking tokens, and reach for a
|
|
253
316
|
one-shot build or another target if you need rebuild-on-change.
|
|
254
317
|
|
|
318
|
+
**A token package resolved through `node_modules` is watched too, and that took
|
|
319
|
+
a fix.** In a workspace — `app/node_modules/@acme/tokens` symlinked to
|
|
320
|
+
`packages/tokens` — Vite's dev-server watcher is built with `**/node_modules/**`
|
|
321
|
+
already in its ignore list, and the entries a consumer adds are appended after
|
|
322
|
+
it rather than subtracted from it. So the first build was correct and no edit
|
|
323
|
+
ever rebuilt, with nothing printed to say so. The plugin now un-ignores exactly
|
|
324
|
+
the files it registers, by name, on Vite 6, 7 and 8. The rest of `node_modules`
|
|
325
|
+
stays ignored, which matters: handing the whole dependency tree to the watcher
|
|
326
|
+
is thousands of files no token build reads.
|
|
327
|
+
|
|
328
|
+
Nothing is needed from you for that. If you had worked around it with a
|
|
329
|
+
`server.watch.ignored` negation of your own, it still works — the plugin appends
|
|
330
|
+
to your list rather than replacing it.
|
|
331
|
+
|
|
255
332
|
"Safe from rebuild loops" is worth stating because consuming code imports the
|
|
256
333
|
generated file, so every regenerate is itself a change the host reacts to. The
|
|
257
334
|
plugin subtracts its own output from the watch list, skips recompiling when a
|
|
258
335
|
watch rebuild re-enters `buildStart`, and skips the write entirely when a
|
|
259
336
|
rebuild renders bytes identical to what is already on disk.
|
|
260
337
|
|
|
338
|
+
## Building Only Some Platforms
|
|
339
|
+
|
|
340
|
+
Every rebuild used to compile every platform, so a dev server serving a web app
|
|
341
|
+
paid for Objective-C headers, Android XML and Dart classes on every token save.
|
|
342
|
+
`platforms` narrows it:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
StyleDictionary({
|
|
346
|
+
config: 'sd.config.json',
|
|
347
|
+
// Build everything once, then rebuild only css while serving.
|
|
348
|
+
platforms: { watch: ['css'] },
|
|
349
|
+
})
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Measured on a six-platform configuration (css, scss, js, ios, android, flutter),
|
|
353
|
+
with the timer around the build call alone:
|
|
354
|
+
|
|
355
|
+
| Tokens | All platforms | css only | Saved |
|
|
356
|
+
| ------ | ------------- | -------- | ------ |
|
|
357
|
+
| 500 | 12 ms | 1 ms | 10 ms |
|
|
358
|
+
| 3,000 | 36 ms | 2 ms | 34 ms |
|
|
359
|
+
| 10,000 | 103 ms | 4 ms | 99 ms |
|
|
360
|
+
| 30,000 | 330 ms | 12 ms | 319 ms |
|
|
361
|
+
|
|
362
|
+
An array — `platforms: ['css']` — applies to every build. The object form splits
|
|
363
|
+
the first compile from the watch rebuilds, and an omitted key means every
|
|
364
|
+
platform. A name the configuration does not define is an error, matching Style
|
|
365
|
+
Dictionary's own CLI.
|
|
366
|
+
|
|
367
|
+
**Unselected platforms keep whatever they last wrote.** Nothing removes or
|
|
368
|
+
refreshes their files, so scoping the `build` half ships stale output for the
|
|
369
|
+
rest. Scope `watch` unless that is what you want.
|
|
370
|
+
|
|
371
|
+
## Generated Output Is Disposable
|
|
372
|
+
|
|
373
|
+
Nothing removes a generated file, ever. Drop a `files` entry from a
|
|
374
|
+
configuration, remove a whole platform, or move a `buildPath`, and the old
|
|
375
|
+
output stays where it was — still resolving, still importable, still carrying
|
|
376
|
+
its old token values, and in a package build still published, with nothing in
|
|
377
|
+
the log mentioning it.
|
|
378
|
+
|
|
379
|
+
So treat the build directory as disposable: delete it when a configuration
|
|
380
|
+
changes shape, and keep it out of version control and out of any directory
|
|
381
|
+
holding hand-written files.
|
|
382
|
+
|
|
383
|
+
There is deliberately no `clean` option. Style Dictionary's
|
|
384
|
+
`cleanAllPlatforms()` does not solve this — it removes the destinations the
|
|
385
|
+
_current_ configuration declares, which are exactly the files that are not
|
|
386
|
+
orphans, and it removes the `buildPath` directory along with them. Measured:
|
|
387
|
+
after dropping `legacy.scss` from a configuration, a clean run left
|
|
388
|
+
`legacy.scss` standing and deleted `vars.css`, the file still in use.
|
|
389
|
+
|
|
261
390
|
## Skipping a Build That Would Change Nothing
|
|
262
391
|
|
|
263
392
|
A configuration whose output is already newer than everything it reads is not
|
|
@@ -355,6 +484,41 @@ A compile that fails is reported at every level, including `'silent'`, which is
|
|
|
355
484
|
why there is no `'error'`. `log.warnings` is never touched: if your
|
|
356
485
|
configuration turns a warning into a thrown build, that stays your decision.
|
|
357
486
|
|
|
487
|
+
### Where the messages go
|
|
488
|
+
|
|
489
|
+
Through your bundler, not straight to the console, and each one takes them its
|
|
490
|
+
own way:
|
|
491
|
+
|
|
492
|
+
| Target | Progress lines | A failed compile |
|
|
493
|
+
| ------------------ | ------------------------ | ---------------------------------- |
|
|
494
|
+
| Vite | `config.logger.info` | `config.logger.error` |
|
|
495
|
+
| Rollup, Rolldown | the plugin context's log | the context's warning channel |
|
|
496
|
+
| Webpack | the console | `compilation.warnings`, so `stats` |
|
|
497
|
+
| No host (one-shot) | the console | the console |
|
|
498
|
+
|
|
499
|
+
That is what makes a `customLogger` and `clearScreen` work under Vite, and what
|
|
500
|
+
puts a failed compile into `stats.toJson()` under webpack — where it reaches CI
|
|
501
|
+
annotations and anything else reading the build's own output.
|
|
502
|
+
|
|
503
|
+
**A failure is reported as a warning, never on the host's error channel.**
|
|
504
|
+
Rollup's `this.error` aborts the bundle, so reporting a failure through it would
|
|
505
|
+
stop every build that reported one — taking the decision `failOnError` exists to
|
|
506
|
+
make. The same reasoning puts webpack's report in `compilation.warnings` rather
|
|
507
|
+
than `compilation.errors`, so `failOnError: false` really does leave the build
|
|
508
|
+
passing.
|
|
509
|
+
|
|
510
|
+
**Your bundler's own log level applies.** `vite --logLevel silent` silences
|
|
511
|
+
Vite's logger, and the plugin's lines are Vite's logger's now, so they go too.
|
|
512
|
+
Nothing is lost by it that matters: `failOnError` decides whether a broken token
|
|
513
|
+
set stops the build, and it decides that whether or not anything was printed.
|
|
514
|
+
|
|
515
|
+
Colour follows the usual conventions, which it previously ignored entirely: no
|
|
516
|
+
escapes when `NO_COLOR` is set, or when the stream is not a terminal, or under
|
|
517
|
+
`TERM=dumb`; escapes when `FORCE_COLOR` is set to anything but `0`, including on
|
|
518
|
+
a non-terminal, which is what that variable is for. `NO_COLOR` wins over
|
|
519
|
+
`FORCE_COLOR`. stdout and stderr are decided separately, because they are
|
|
520
|
+
redirected separately.
|
|
521
|
+
|
|
358
522
|
## Failing the Build
|
|
359
523
|
|
|
360
524
|
A token compile that fails stops the build. `vite build`, `rollup` and `webpack`
|
|
@@ -373,17 +537,81 @@ StyleDictionary({
|
|
|
373
537
|
})
|
|
374
538
|
```
|
|
375
539
|
|
|
376
|
-
A
|
|
540
|
+
**A configuration that resolves no tokens is a failure, not an empty build.**
|
|
541
|
+
Style Dictionary writes the destination with nothing in it and reports success,
|
|
542
|
+
so a token file deleted mid-session used to take the generated output down with
|
|
543
|
+
it, and a `source` matching nothing shipped an empty stylesheet from a build
|
|
544
|
+
that exited 0. The check runs before the compile, so the previous good output is
|
|
545
|
+
still on disk when it fires and nothing is overwritten. The message names the
|
|
546
|
+
configuration and the patterns that matched no files.
|
|
547
|
+
|
|
548
|
+
This is about the resolved token set, not about the patterns: a configuration
|
|
549
|
+
that supplies `tokens` inline and declares no `source` at all is valid and
|
|
550
|
+
builds. And it goes through `failOnError` like any other compile failure, so
|
|
551
|
+
`failOnError: false` reports it and carries on.
|
|
552
|
+
|
|
553
|
+
A failure is always reported by the plugin, whatever `failOnError` and `silent`
|
|
554
|
+
are set to — see [Where the messages go](#where-the-messages-go) for which
|
|
555
|
+
channel it arrives on, and for the one thing that can still suppress it.
|
|
556
|
+
|
|
557
|
+
Under Vite's dev server it is reported to the browser as well. A failed rebuild
|
|
558
|
+
is pushed to Vite's error overlay, naming this plugin and carrying Style
|
|
559
|
+
Dictionary's message, and the overlay is dismissed by the next rebuild that
|
|
560
|
+
succeeds — so a page left rendering the last good token file says so instead of
|
|
561
|
+
looking current. Set `errorOverlay: false` to keep the failure in the terminal
|
|
562
|
+
only.
|
|
563
|
+
|
|
564
|
+
`failOnError` and `errorOverlay` answer different questions and do not interact:
|
|
565
|
+
the first decides whether the host stops, the second whether the browser is
|
|
566
|
+
told. The dev server's default is not to stop, which is exactly when the overlay
|
|
567
|
+
is the only thing that can report the failure.
|
|
568
|
+
|
|
569
|
+
## Build Hooks
|
|
570
|
+
|
|
571
|
+
Three optional callbacks, for work that has to happen around a compile rather
|
|
572
|
+
than inside one — formatting the generated files, type-checking them, telling
|
|
573
|
+
something else they have landed.
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
StyleDictionary({
|
|
577
|
+
config: 'sd.config.json',
|
|
578
|
+
onBuildStart: () => console.log('compiling tokens'),
|
|
579
|
+
onBuildEnd: async (files, durationMs) => {
|
|
580
|
+
console.log(`wrote ${files.length} files in ${durationMs}ms`)
|
|
581
|
+
await formatGeneratedFiles(files)
|
|
582
|
+
},
|
|
583
|
+
onBuildError: (error) => notifySomething(error),
|
|
584
|
+
})
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
`files` holds the absolute, platform-native path of every file the build
|
|
588
|
+
declares, sorted. It is what the build declares rather than what it happened to
|
|
589
|
+
write this time: a configuration skipped because its output was already current
|
|
590
|
+
contributes its destinations too, so a post-processing step still sees the whole
|
|
591
|
+
set on a rebuild that changed one file.
|
|
592
|
+
|
|
593
|
+
A rebuild is a build, so all three fire again on every watch-triggered one.
|
|
594
|
+
|
|
595
|
+
**A hook cannot fail the build that called it.** The return value is not
|
|
596
|
+
awaited, so nothing waits for post-processing; a hook that throws is reported
|
|
597
|
+
and the build stands, and a promise that rejects is caught and reported rather
|
|
598
|
+
than reaching the host as an unhandled rejection — which would otherwise take a
|
|
599
|
+
dev server down from inside a step meant to reformat a file.
|
|
600
|
+
|
|
601
|
+
`onBuildError` fires whatever `failOnError` is set to, and before that option
|
|
602
|
+
decides whether to rethrow. The two answer different questions: one is whether
|
|
603
|
+
the host stops, the other is that a build went wrong.
|
|
377
604
|
|
|
378
605
|
## Public API
|
|
379
606
|
|
|
380
|
-
Small on purpose. Four bundler entry points, one root entry, and
|
|
607
|
+
Small on purpose. Four bundler entry points, one root entry, and two types.
|
|
381
608
|
|
|
382
609
|
| Import | What it is |
|
|
383
610
|
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
384
611
|
| `…/vite`, `…/rolldown`, `…/rollup`, `…/webpack` | Default export: the plugin for that bundler. Call it with the options below. |
|
|
385
612
|
| `…` (the root) | Default export, also named `unplugin`: the unplugin instance, carrying `.vite`, `.rolldown`, `.rollup` and `.webpack`. |
|
|
386
613
|
| `UnpluginStyleDictionaryOptions` | The options type, exported from every entry above. |
|
|
614
|
+
| `StyleDictionaryConfigContext` | What the function form of `config` is handed, exported from every entry above. |
|
|
387
615
|
|
|
388
616
|
Anything not in that table is internal, whatever a build output happens to
|
|
389
617
|
contain. In particular the watch filter and the raw unplugin factory are not
|
|
@@ -403,7 +631,7 @@ const plugin = styleDictionary.rollup({ config: 'sd.config.json' })
|
|
|
403
631
|
|
|
404
632
|
## Options Reference
|
|
405
633
|
|
|
406
|
-
|
|
634
|
+
````typescript
|
|
407
635
|
/**
|
|
408
636
|
* Options for the Style Dictionary unplugin factory, shared across all bundler
|
|
409
637
|
* targets (Vite, Rolldown, Rollup, Webpack).
|
|
@@ -415,12 +643,72 @@ const plugin = styleDictionary.rollup({ config: 'sd.config.json' })
|
|
|
415
643
|
* build (e.g. `tsdown`/`rolldown build` without `--watch`) only builds once, in
|
|
416
644
|
* `buildStart`.
|
|
417
645
|
*
|
|
646
|
+
* Everything the plugin says goes through the host rather than to the console:
|
|
647
|
+
* Vite's `config.logger`, the plugin context under rollup and rolldown, and
|
|
648
|
+
* `compilation.warnings` under webpack, which is what puts a failed compile in
|
|
649
|
+
* `stats.toJson()`. A failure is reported on the warning channel and never the
|
|
650
|
+
* error one — rollup's `this.error` aborts the bundle, and that decision is
|
|
651
|
+
* `failOnError`'s alone. Where no host offers a channel the console is used,
|
|
652
|
+
* with colour gated on `NO_COLOR`, `FORCE_COLOR` and whether the stream is a
|
|
653
|
+
* terminal.
|
|
654
|
+
*
|
|
655
|
+
* The three `onBuild*` hooks are called synchronously and their return value
|
|
656
|
+
* is not awaited, so a build never waits for one. A hook may still be written
|
|
657
|
+
* `async`: a promise it returns is left to run on its own, and a rejection is
|
|
658
|
+
* caught and reported rather than reaching the host as an unhandled one. A
|
|
659
|
+
* hook that throws is reported and does not fail the build that called it.
|
|
660
|
+
*
|
|
661
|
+
* They return `Promise<void> | void` rather than `void` for that reason. Both
|
|
662
|
+
* accept an `async` hook as far as the compiler is concerned, but `void` alone
|
|
663
|
+
* makes one a `no-misused-promises` error under the type-aware lint rules a
|
|
664
|
+
* consumer is likely to be running — for a hook this documents as supported.
|
|
665
|
+
*
|
|
418
666
|
* Rolldown's watch mode is the exception, and it is not about glob patterns.
|
|
419
667
|
* `addWatchFile` is accepted either way, but what happens next differs by
|
|
420
668
|
* platform — on macOS a file registered through it is watched by nothing, while
|
|
421
669
|
* on a Linux runner the same edit reaches a rebuild. Do not rely on a token
|
|
422
670
|
* edit triggering a rebuild there.
|
|
423
671
|
*/
|
|
672
|
+
/**
|
|
673
|
+
* What the host is doing, handed to the function form of `config` so it can
|
|
674
|
+
* decide what to build.
|
|
675
|
+
*
|
|
676
|
+
* Only Vite reports all three. Where a host does not say, the value is
|
|
677
|
+
* derived rather than guessed at, and each field below says how.
|
|
678
|
+
*/
|
|
679
|
+
export interface StyleDictionaryConfigContext {
|
|
680
|
+
/**
|
|
681
|
+
* Whether the host is serving or building.
|
|
682
|
+
*
|
|
683
|
+
* `'serve'` comes from Vite's own `config.command` and is the dev server.
|
|
684
|
+
* Every other target builds, so it is `'build'` there — rollup, rolldown and
|
|
685
|
+
* webpack have no serving mode of their own to report.
|
|
686
|
+
*/
|
|
687
|
+
command: 'build' | 'serve'
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* The host's mode, as it names it.
|
|
691
|
+
*
|
|
692
|
+
* Vite reports its `config.mode` — `'development'` serving,
|
|
693
|
+
* `'production'` building, or whatever `--mode` named. webpack reports its
|
|
694
|
+
* `mode` option. rollup and rolldown have no such concept, so the value
|
|
695
|
+
* follows `command`: `'development'` when serving, `'production'` when
|
|
696
|
+
* building.
|
|
697
|
+
*/
|
|
698
|
+
mode: string
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Whether the host will keep rebuilding.
|
|
702
|
+
*
|
|
703
|
+
* `true` under Vite's dev server, `rollup --watch`, `rolldown.watch()` and
|
|
704
|
+
* `webpack --watch`; `false` for a one-shot build. It is read from the
|
|
705
|
+
* host — the plugin context's `meta.watchMode` on the three rollup-shaped
|
|
706
|
+
* targets, and `compiler.watchMode` on webpack — rather than inferred from
|
|
707
|
+
* `command`, because `rollup --watch` both watches and builds.
|
|
708
|
+
*/
|
|
709
|
+
watch: boolean
|
|
710
|
+
}
|
|
711
|
+
|
|
424
712
|
export interface UnpluginStyleDictionaryOptions {
|
|
425
713
|
/**
|
|
426
714
|
* Whether a configuration whose output is already up to date may skip its
|
|
@@ -462,18 +750,64 @@ export interface UnpluginStyleDictionaryOptions {
|
|
|
462
750
|
* - A function that returns a config or array of configs (or resolves to them).
|
|
463
751
|
* Useful for calling `StyleDictionary.registerFormat()` (or other `register*`
|
|
464
752
|
* methods) before returning a config that references the custom format by name.
|
|
753
|
+
* It is handed a `StyleDictionaryConfigContext` describing what the host is
|
|
754
|
+
* doing, so an expensive platform can be built only when it is wanted —
|
|
755
|
+
* skipped under the dev server, built by `vite build`. A function taking no
|
|
756
|
+
* arguments stays valid: TypeScript accepts one of fewer parameters, and
|
|
757
|
+
* JavaScript ignores the extra argument.
|
|
465
758
|
*
|
|
466
759
|
* If not provided, the root directory is searched for 'sd.config.json',
|
|
467
760
|
* 'config.json', 'sd.config.js' and 'sd.config.mjs', in that order. The
|
|
468
|
-
* first one that
|
|
761
|
+
* first one that *looks like a Style Dictionary configuration* wins — it has
|
|
762
|
+
* to declare at least one of `platforms`, `source`, `include` or `tokens` —
|
|
763
|
+
* and the path it picked is announced, so which file a build used is
|
|
764
|
+
* answerable from the console. A candidate that fails that check is reported
|
|
765
|
+
* and skipped rather than adopted, because `config.json` is an extremely
|
|
766
|
+
* common name for something else entirely.
|
|
767
|
+
*
|
|
768
|
+
* **`false` turns discovery off.** Two of the four names are modules rather
|
|
769
|
+
* than data, and reading a module means running it: a `sd.config.js` in the
|
|
770
|
+
* root is imported, freshly, on every watch event. Validation cannot prevent
|
|
771
|
+
* that, because the check can only look at what the import returned — so a
|
|
772
|
+
* project that names its configuration explicitly, or has none, should say
|
|
773
|
+
* `config: false` rather than rely on there being nothing to find.
|
|
469
774
|
*/
|
|
470
775
|
config?:
|
|
471
|
-
| ((
|
|
776
|
+
| ((
|
|
777
|
+
context: StyleDictionaryConfigContext,
|
|
778
|
+
) => Config | Config[] | Promise<Config | Config[]>)
|
|
472
779
|
| Config
|
|
473
780
|
| Config[]
|
|
781
|
+
| false
|
|
474
782
|
| string
|
|
475
783
|
| string[]
|
|
476
784
|
|
|
785
|
+
/**
|
|
786
|
+
* Whether a failed rebuild is pushed to Vite's error overlay.
|
|
787
|
+
*
|
|
788
|
+
* A rebuild that fails under the dev server used to reach the browser
|
|
789
|
+
* nowhere: the page went on rendering the last good generated file, and the
|
|
790
|
+
* only trace was one red terminal line the developer may not have been
|
|
791
|
+
* looking at. With this on, the failure is sent to the page as an error
|
|
792
|
+
* frame naming this plugin, and the overlay is dismissed on the next
|
|
793
|
+
* rebuild that succeeds.
|
|
794
|
+
*
|
|
795
|
+
* This is Vite's overlay, so it does nothing on the other three targets,
|
|
796
|
+
* and nothing under `vite build` — there is no page to draw on.
|
|
797
|
+
*
|
|
798
|
+
* It is not `failOnError`'s job, and the two are independent. `failOnError`
|
|
799
|
+
* decides whether the host stops; this decides whether the browser is told.
|
|
800
|
+
* A dev server deliberately keeps serving through a failed rebuild, which is
|
|
801
|
+
* precisely the case where the overlay is the only thing that can say so.
|
|
802
|
+
*
|
|
803
|
+
* A failure Style Dictionary raises before this plugin can catch it — a
|
|
804
|
+
* token file that is not valid JSON, which rejects out of band — reaches
|
|
805
|
+
* neither the overlay nor this option.
|
|
806
|
+
*
|
|
807
|
+
* @default true
|
|
808
|
+
*/
|
|
809
|
+
errorOverlay?: boolean
|
|
810
|
+
|
|
477
811
|
/**
|
|
478
812
|
* Whether a compile that fails should throw rather than only be reported.
|
|
479
813
|
*
|
|
@@ -513,11 +847,101 @@ export interface UnpluginStyleDictionaryOptions {
|
|
|
513
847
|
* A compile that fails is reported at every level, so there is no
|
|
514
848
|
* `'error'`: `'silent'` is the quietest and still reports a failure.
|
|
515
849
|
*
|
|
850
|
+
* This option governs what the plugin says, not where it goes. The messages
|
|
851
|
+
* are handed to the host — Vite's `config.logger`, the rollup and rolldown
|
|
852
|
+
* plugin context, webpack's `compilation` — so a host silenced by its own
|
|
853
|
+
* log level suppresses them after this option has let them through. A
|
|
854
|
+
* failure still stops the build whenever `failOnError` says it should,
|
|
855
|
+
* printed or not.
|
|
856
|
+
*
|
|
516
857
|
* @default undefined, which prints the plugin's own lines and leaves the
|
|
517
858
|
* configuration's `log.verbosity` alone
|
|
518
859
|
*/
|
|
519
860
|
logLevel?: 'info' | 'silent' | 'verbose' | 'warn'
|
|
520
861
|
|
|
862
|
+
/**
|
|
863
|
+
* Called once a build has finished, with every file it declares and how long
|
|
864
|
+
* it took in milliseconds.
|
|
865
|
+
*
|
|
866
|
+
* The paths are absolute and platform-native, sorted so two runs of the same
|
|
867
|
+
* configuration hand back the same order. They are what the build declares
|
|
868
|
+
* rather than what it wrote this time: a configuration skipped by `cache`
|
|
869
|
+
* contributes its destinations too, because they are on disk and current,
|
|
870
|
+
* and a post-processing step that ignored them would leave half the output
|
|
871
|
+
* untouched on a rebuild that changed one file.
|
|
872
|
+
*
|
|
873
|
+
* This is where formatting the generated files, type-checking them, or
|
|
874
|
+
* telling something else they have landed belongs.
|
|
875
|
+
*
|
|
876
|
+
* @default undefined
|
|
877
|
+
*/
|
|
878
|
+
onBuildEnd?: (files: string[], durationMs: number) => Promise<void> | void
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Called when a build fails, with whatever was thrown.
|
|
882
|
+
*
|
|
883
|
+
* It fires whatever `failOnError` is set to, and before that option decides
|
|
884
|
+
* whether to rethrow — the two answer different questions, and under a dev
|
|
885
|
+
* server the default is not to throw at all.
|
|
886
|
+
*
|
|
887
|
+
* The failure is reported to the console either way, so this is for reacting
|
|
888
|
+
* to one rather than for noticing it.
|
|
889
|
+
*
|
|
890
|
+
* @default undefined
|
|
891
|
+
*/
|
|
892
|
+
onBuildError?: (error: unknown) => Promise<void> | void
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Called before a build begins, once per build.
|
|
896
|
+
*
|
|
897
|
+
* A watch-triggered rebuild is a build, so this fires again for each one.
|
|
898
|
+
*
|
|
899
|
+
* @default undefined
|
|
900
|
+
*/
|
|
901
|
+
onBuildStart?: () => Promise<void> | void
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Which platforms to build, by the names the configuration defines.
|
|
905
|
+
*
|
|
906
|
+
* Every rebuild used to compile every platform. Measured on a six-platform
|
|
907
|
+
* configuration (css, scss, js, ios, android, flutter), with the timer around
|
|
908
|
+
* the build call alone:
|
|
909
|
+
*
|
|
910
|
+
* ```
|
|
911
|
+
* tokens all platforms css only saved
|
|
912
|
+
* 500 12 ms 1 ms 10 ms
|
|
913
|
+
* 3000 36 ms 2 ms 34 ms
|
|
914
|
+
* 10000 103 ms 4 ms 99 ms
|
|
915
|
+
* 30000 330 ms 12 ms 319 ms
|
|
916
|
+
* ```
|
|
917
|
+
*
|
|
918
|
+
* So a dev server serving a web app paid for Objective-C headers, Android
|
|
919
|
+
* XML and Dart classes on every token save, and the cost grows with the
|
|
920
|
+
* token count.
|
|
921
|
+
*
|
|
922
|
+
* Two shapes. An array selects the same platforms for every build. An object
|
|
923
|
+
* splits the first compile from the watch rebuilds, which is the common
|
|
924
|
+
* want — build everything once, then rebuild only what the page uses:
|
|
925
|
+
*
|
|
926
|
+
* ```typescript
|
|
927
|
+
* platforms: ['css']
|
|
928
|
+
* platforms: { watch: ['css'] }
|
|
929
|
+
* ```
|
|
930
|
+
*
|
|
931
|
+
* An omitted key means every platform, so `{ watch: ['css'] }` builds all of
|
|
932
|
+
* them once and then only css. A name the configuration does not define is an
|
|
933
|
+
* error, matching Style Dictionary's own CLI — "Must be defined in the
|
|
934
|
+
* config".
|
|
935
|
+
*
|
|
936
|
+
* **Unselected platforms keep whatever they last wrote.** Their files are not
|
|
937
|
+
* removed and not refreshed, so a one-shot build that scopes platforms ships
|
|
938
|
+
* stale output for the rest. Scope the watch half rather than the build half
|
|
939
|
+
* unless that is what you want.
|
|
940
|
+
*
|
|
941
|
+
* @default undefined, which builds every platform
|
|
942
|
+
*/
|
|
943
|
+
platforms?: string[] | { build?: string[]; watch?: string[] }
|
|
944
|
+
|
|
521
945
|
/**
|
|
522
946
|
* Whether the table of generated files and their sizes is produced.
|
|
523
947
|
*
|
|
@@ -581,7 +1005,7 @@ export interface UnpluginStyleDictionaryOptions {
|
|
|
581
1005
|
*/
|
|
582
1006
|
watch?: string | string[]
|
|
583
1007
|
}
|
|
584
|
-
|
|
1008
|
+
````
|
|
585
1009
|
|
|
586
1010
|
## Migrating from `vite-plugin-style-dictionary`
|
|
587
1011
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { UnpluginStyleDictionaryOptions } from "./types.js";
|
|
1
|
+
import { StyleDictionaryConfigContext, UnpluginStyleDictionaryOptions } from "./types.js";
|
|
2
2
|
//#region src/index.d.ts
|
|
3
3
|
export declare const unplugin: import("unplugin").UnpluginInstance<UnpluginStyleDictionaryOptions | undefined, false>;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { type UnpluginStyleDictionaryOptions, unplugin as default };
|
|
5
|
+
export { type StyleDictionaryConfigContext, type UnpluginStyleDictionaryOptions, unplugin as default };
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|