@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/dist/types.d.ts CHANGED
@@ -11,12 +11,69 @@ import { Config } from "style-dictionary";
11
11
  * build (e.g. `tsdown`/`rolldown build` without `--watch`) only builds once, in
12
12
  * `buildStart`.
13
13
  *
14
+ * Everything the plugin says goes through the host rather than to the console:
15
+ * Vite's `config.logger`, the plugin context under rollup and rolldown, and
16
+ * `compilation.warnings` under webpack, which is what puts a failed compile in
17
+ * `stats.toJson()`. A failure is reported on the warning channel and never the
18
+ * error one — rollup's `this.error` aborts the bundle, and that decision is
19
+ * `failOnError`'s alone. Where no host offers a channel the console is used,
20
+ * with colour gated on `NO_COLOR`, `FORCE_COLOR` and whether the stream is a
21
+ * terminal.
22
+ *
23
+ * The three `onBuild*` hooks are called synchronously and their return value
24
+ * is not awaited, so a build never waits for one. A hook may still be written
25
+ * `async`: a promise it returns is left to run on its own, and a rejection is
26
+ * caught and reported rather than reaching the host as an unhandled one. A
27
+ * hook that throws is reported and does not fail the build that called it.
28
+ *
29
+ * They return `Promise<void> | void` rather than `void` for that reason. Both
30
+ * accept an `async` hook as far as the compiler is concerned, but `void` alone
31
+ * makes one a `no-misused-promises` error under the type-aware lint rules a
32
+ * consumer is likely to be running — for a hook this documents as supported.
33
+ *
14
34
  * Rolldown's watch mode is the exception, and it is not about glob patterns.
15
35
  * `addWatchFile` is accepted either way, but what happens next differs by
16
36
  * platform — on macOS a file registered through it is watched by nothing, while
17
37
  * on a Linux runner the same edit reaches a rebuild. Do not rely on a token
18
38
  * edit triggering a rebuild there.
19
39
  */
40
+ /**
41
+ * What the host is doing, handed to the function form of `config` so it can
42
+ * decide what to build.
43
+ *
44
+ * Only Vite reports all three. Where a host does not say, the value is
45
+ * derived rather than guessed at, and each field below says how.
46
+ */
47
+ export interface StyleDictionaryConfigContext {
48
+ /**
49
+ * Whether the host is serving or building.
50
+ *
51
+ * `'serve'` comes from Vite's own `config.command` and is the dev server.
52
+ * Every other target builds, so it is `'build'` there — rollup, rolldown and
53
+ * webpack have no serving mode of their own to report.
54
+ */
55
+ command: 'build' | 'serve';
56
+ /**
57
+ * The host's mode, as it names it.
58
+ *
59
+ * Vite reports its `config.mode` — `'development'` serving,
60
+ * `'production'` building, or whatever `--mode` named. webpack reports its
61
+ * `mode` option. rollup and rolldown have no such concept, so the value
62
+ * follows `command`: `'development'` when serving, `'production'` when
63
+ * building.
64
+ */
65
+ mode: string;
66
+ /**
67
+ * Whether the host will keep rebuilding.
68
+ *
69
+ * `true` under Vite's dev server, `rollup --watch`, `rolldown.watch()` and
70
+ * `webpack --watch`; `false` for a one-shot build. It is read from the
71
+ * host — the plugin context's `meta.watchMode` on the three rollup-shaped
72
+ * targets, and `compiler.watchMode` on webpack — rather than inferred from
73
+ * `command`, because `rollup --watch` both watches and builds.
74
+ */
75
+ watch: boolean;
76
+ }
20
77
  export interface UnpluginStyleDictionaryOptions {
21
78
  /**
22
79
  * Whether a configuration whose output is already up to date may skip its
@@ -57,12 +114,54 @@ export interface UnpluginStyleDictionaryOptions {
57
114
  * - A function that returns a config or array of configs (or resolves to them).
58
115
  * Useful for calling `StyleDictionary.registerFormat()` (or other `register*`
59
116
  * methods) before returning a config that references the custom format by name.
117
+ * It is handed a `StyleDictionaryConfigContext` describing what the host is
118
+ * doing, so an expensive platform can be built only when it is wanted —
119
+ * skipped under the dev server, built by `vite build`. A function taking no
120
+ * arguments stays valid: TypeScript accepts one of fewer parameters, and
121
+ * JavaScript ignores the extra argument.
60
122
  *
61
123
  * If not provided, the root directory is searched for 'sd.config.json',
62
124
  * 'config.json', 'sd.config.js' and 'sd.config.mjs', in that order. The
63
- * first one that exists wins, and the rest are not looked at.
125
+ * first one that *looks like a Style Dictionary configuration* wins it has
126
+ * to declare at least one of `platforms`, `source`, `include` or `tokens` —
127
+ * and the path it picked is announced, so which file a build used is
128
+ * answerable from the console. A candidate that fails that check is reported
129
+ * and skipped rather than adopted, because `config.json` is an extremely
130
+ * common name for something else entirely.
131
+ *
132
+ * **`false` turns discovery off.** Two of the four names are modules rather
133
+ * than data, and reading a module means running it: a `sd.config.js` in the
134
+ * root is imported, freshly, on every watch event. Validation cannot prevent
135
+ * that, because the check can only look at what the import returned — so a
136
+ * project that names its configuration explicitly, or has none, should say
137
+ * `config: false` rather than rely on there being nothing to find.
138
+ */
139
+ config?: ((context: StyleDictionaryConfigContext) => Config | Config[] | Promise<Config | Config[]>) | Config | Config[] | false | string | string[];
140
+ /**
141
+ * Whether a failed rebuild is pushed to Vite's error overlay.
142
+ *
143
+ * A rebuild that fails under the dev server used to reach the browser
144
+ * nowhere: the page went on rendering the last good generated file, and the
145
+ * only trace was one red terminal line the developer may not have been
146
+ * looking at. With this on, the failure is sent to the page as an error
147
+ * frame naming this plugin, and the overlay is dismissed on the next
148
+ * rebuild that succeeds.
149
+ *
150
+ * This is Vite's overlay, so it does nothing on the other three targets,
151
+ * and nothing under `vite build` — there is no page to draw on.
152
+ *
153
+ * It is not `failOnError`'s job, and the two are independent. `failOnError`
154
+ * decides whether the host stops; this decides whether the browser is told.
155
+ * A dev server deliberately keeps serving through a failed rebuild, which is
156
+ * precisely the case where the overlay is the only thing that can say so.
157
+ *
158
+ * A failure Style Dictionary raises before this plugin can catch it — a
159
+ * token file that is not valid JSON, which rejects out of band — reaches
160
+ * neither the overlay nor this option.
161
+ *
162
+ * @default true
64
163
  */
65
- config?: (() => Config | Config[] | Promise<Config | Config[]>) | Config | Config[] | string | string[];
164
+ errorOverlay?: boolean;
66
165
  /**
67
166
  * Whether a compile that fails should throw rather than only be reported.
68
167
  *
@@ -101,10 +200,99 @@ export interface UnpluginStyleDictionaryOptions {
101
200
  * A compile that fails is reported at every level, so there is no
102
201
  * `'error'`: `'silent'` is the quietest and still reports a failure.
103
202
  *
203
+ * This option governs what the plugin says, not where it goes. The messages
204
+ * are handed to the host — Vite's `config.logger`, the rollup and rolldown
205
+ * plugin context, webpack's `compilation` — so a host silenced by its own
206
+ * log level suppresses them after this option has let them through. A
207
+ * failure still stops the build whenever `failOnError` says it should,
208
+ * printed or not.
209
+ *
104
210
  * @default undefined, which prints the plugin's own lines and leaves the
105
211
  * configuration's `log.verbosity` alone
106
212
  */
107
213
  logLevel?: 'info' | 'silent' | 'verbose' | 'warn';
214
+ /**
215
+ * Called once a build has finished, with every file it declares and how long
216
+ * it took in milliseconds.
217
+ *
218
+ * The paths are absolute and platform-native, sorted so two runs of the same
219
+ * configuration hand back the same order. They are what the build declares
220
+ * rather than what it wrote this time: a configuration skipped by `cache`
221
+ * contributes its destinations too, because they are on disk and current,
222
+ * and a post-processing step that ignored them would leave half the output
223
+ * untouched on a rebuild that changed one file.
224
+ *
225
+ * This is where formatting the generated files, type-checking them, or
226
+ * telling something else they have landed belongs.
227
+ *
228
+ * @default undefined
229
+ */
230
+ onBuildEnd?: (files: string[], durationMs: number) => Promise<void> | void;
231
+ /**
232
+ * Called when a build fails, with whatever was thrown.
233
+ *
234
+ * It fires whatever `failOnError` is set to, and before that option decides
235
+ * whether to rethrow — the two answer different questions, and under a dev
236
+ * server the default is not to throw at all.
237
+ *
238
+ * The failure is reported to the console either way, so this is for reacting
239
+ * to one rather than for noticing it.
240
+ *
241
+ * @default undefined
242
+ */
243
+ onBuildError?: (error: unknown) => Promise<void> | void;
244
+ /**
245
+ * Called before a build begins, once per build.
246
+ *
247
+ * A watch-triggered rebuild is a build, so this fires again for each one.
248
+ *
249
+ * @default undefined
250
+ */
251
+ onBuildStart?: () => Promise<void> | void;
252
+ /**
253
+ * Which platforms to build, by the names the configuration defines.
254
+ *
255
+ * Every rebuild used to compile every platform. Measured on a six-platform
256
+ * configuration (css, scss, js, ios, android, flutter), with the timer around
257
+ * the build call alone:
258
+ *
259
+ * ```
260
+ * tokens all platforms css only saved
261
+ * 500 12 ms 1 ms 10 ms
262
+ * 3000 36 ms 2 ms 34 ms
263
+ * 10000 103 ms 4 ms 99 ms
264
+ * 30000 330 ms 12 ms 319 ms
265
+ * ```
266
+ *
267
+ * So a dev server serving a web app paid for Objective-C headers, Android
268
+ * XML and Dart classes on every token save, and the cost grows with the
269
+ * token count.
270
+ *
271
+ * Two shapes. An array selects the same platforms for every build. An object
272
+ * splits the first compile from the watch rebuilds, which is the common
273
+ * want — build everything once, then rebuild only what the page uses:
274
+ *
275
+ * ```typescript
276
+ * platforms: ['css']
277
+ * platforms: { watch: ['css'] }
278
+ * ```
279
+ *
280
+ * An omitted key means every platform, so `{ watch: ['css'] }` builds all of
281
+ * them once and then only css. A name the configuration does not define is an
282
+ * error, matching Style Dictionary's own CLI — "Must be defined in the
283
+ * config".
284
+ *
285
+ * **Unselected platforms keep whatever they last wrote.** Their files are not
286
+ * removed and not refreshed, so a one-shot build that scopes platforms ships
287
+ * stale output for the rest. Scope the watch half rather than the build half
288
+ * unless that is what you want.
289
+ *
290
+ * @default undefined, which builds every platform
291
+ */
292
+ platforms?: string[] | {
293
+ build?: string[];
294
+ watch?: string[];
295
+ };
108
296
  /**
109
297
  * Whether the table of generated files and their sizes is produced.
110
298
  *
package/dist/vite.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { UnpluginStyleDictionaryOptions } from "./types.js";
1
+ import { StyleDictionaryConfigContext, UnpluginStyleDictionaryOptions } from "./types.js";
2
2
  //#region src/vite.d.ts
3
3
  declare const _default: (options?: UnpluginStyleDictionaryOptions | undefined) => import("vite").Plugin<any>;
4
4
  //#endregion
5
- export { type UnpluginStyleDictionaryOptions, _default as default };
5
+ export { type StyleDictionaryConfigContext, type UnpluginStyleDictionaryOptions, _default as default };
6
6
  //# sourceMappingURL=vite.d.ts.map
package/dist/webpack.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { UnpluginStyleDictionaryOptions } from "./types.js";
1
+ import { StyleDictionaryConfigContext, UnpluginStyleDictionaryOptions } from "./types.js";
2
2
  //#region src/webpack.d.ts
3
3
  declare const _default: (options?: UnpluginStyleDictionaryOptions | undefined) => import("webpack").WebpackPluginInstance;
4
4
  //#endregion
5
- export { type UnpluginStyleDictionaryOptions, _default as default };
5
+ export { type StyleDictionaryConfigContext, type UnpluginStyleDictionaryOptions, _default as default };
6
6
  //# sourceMappingURL=webpack.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanso-labs/unplugin-style-dictionary",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Compile Style Dictionary design tokens ahead of your bundler (Vite, Rolldown, Rollup, or Webpack) from a single unplugin-based plugin, with automatic watching and rebuilding under Vite",
5
5
  "keywords": [
6
6
  "unplugin",