synthesisui 0.16.310 → 0.16.312

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.
@@ -9,7 +9,7 @@ import { body, section, snippet } from "../output.js";
9
9
  import { findCollision, reactMajorOf, readInstalledConvention, readInstalledScheme, } from "../project-facts.js";
10
10
  import { fetchComponent, RegistryError } from "../registry.js";
11
11
  import { flavourResolver } from "../styles-flavour.js";
12
- import { inTheirTongue, tongueOf } from "../their-tongue.js";
12
+ import { inTheirTongue, projectTongue } from "../their-tongue.js";
13
13
  import { readCensus, unreadComment, unreadForComponent, } from "../unread-for-component.js";
14
14
  /**
15
15
  * Writes the shared `cn.ts` next to the components, built from THIS project's
@@ -98,7 +98,7 @@ export async function component(slug, name, opts) {
98
98
  * apagaria a cor. Um projeto de destino chega sem mapa no `.lock`, nada é traduzido, e a folha
99
99
  * continua sendo o caminho - o comando DIZ qual dos dois aconteceu.
100
100
  */
101
- const tongue = await tongueFor(root, slug);
101
+ const tongue = await projectTongue(root, slug);
102
102
  const spoken = tongue ? inTheirTongue(res.css, tongue) : null;
103
103
  const css = spoken ? spoken.css : res.css;
104
104
  /**
@@ -325,35 +325,3 @@ export async function component(slug, name, opts) {
325
325
  }
326
326
  console.log("");
327
327
  }
328
- /**
329
- * O VOCABULÁRIO DESTE REPOSITÓRIO, do que o `add` já deixou na pasta - ver `tongueOf`.
330
- *
331
- * `null` quando não há mapa: é a resposta de um projeto de destino, de um repositório que nunca
332
- * buildou, ou de um install feito por um CLI anterior a 0.16.290. Nos três casos nada é traduzido e
333
- * a folha instalada continua sendo o caminho, que é o comportamento de sempre.
334
- */
335
- async function tongueFor(root, slug) {
336
- const dir = join(root, "_synthesisui", "ds", slug);
337
- const lock = await readFile(join(dir, ".lock"), "utf8").catch(() => null);
338
- if (!lock)
339
- return null;
340
- let map = [];
341
- let version = 0;
342
- try {
343
- const parsed = JSON.parse(lock);
344
- map = parsed.tokenMap ?? [];
345
- version = parsed.version ?? 0;
346
- }
347
- catch {
348
- return null;
349
- }
350
- if (map.length === 0)
351
- return null;
352
- /**
353
- * O VALOR COMPILADO MORA NA PASTA DA VERSÃO - a folha da raiz é um re-export de uma linha, escrito
354
- * assim de propósito para que o `@import` dele nunca mude entre updates (ver `add.ts`). É de lá
355
- * que sai o literal para as variáveis que não têm nome dele.
356
- */
357
- const installed = await readFile(join(dir, `v${version}`, "tokens.css"), "utf8").catch(() => "");
358
- return tongueOf(map, installed);
359
- }
@@ -2,6 +2,7 @@ import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
  import { readProjectConfig, resolveRegistry } from "../config.js";
4
4
  import { fetchTemplate } from "../registry.js";
5
+ import { inTheirTongue, projectTongue } from "../their-tongue.js";
5
6
  /**
6
7
  * Materializes a whole page from a DS template into the project (hybrid
7
8
  * codegen-first): the server codegens deterministic files, we write them, and
@@ -27,14 +28,46 @@ export async function template(slug, name, opts) {
27
28
  const defaultDir = join("templates", asName ?? name);
28
29
  const pageRel = opts.out ?? join(defaultDir, pageFile.filename);
29
30
  const pageDir = dirname(join(root, pageRel));
31
+ /**
32
+ * NENHUMA MATERIALIZAÇÃO VAZA VOCABULÁRIO INTERNO (INV-VOLTA-02) - a mesma porta do
33
+ * `component`. Uma página inteira saía com `var(--ds-*)` cru enquanto um componente avulso
34
+ * falava a língua dele; a promessa é uma só. Sem mapa no `.lock`, nada é traduzido e a folha
35
+ * instalada continua sendo o caminho - e a saída diz qual dos dois aconteceu.
36
+ */
37
+ const tongue = await projectTongue(root, slug);
38
+ const speak = (code) => (tongue ? inTheirTongue(code, tongue) : null);
39
+ let named = 0;
40
+ let inlined = 0;
41
+ const still = new Set();
30
42
  await mkdir(pageDir, { recursive: true });
31
- await writeFile(join(root, pageRel), pageFile.code, "utf8");
43
+ const spokenPage = speak(pageFile.code);
44
+ if (spokenPage) {
45
+ named += spokenPage.named;
46
+ inlined += spokenPage.inlined;
47
+ for (const l of spokenPage.left)
48
+ still.add(l);
49
+ }
50
+ await writeFile(join(root, pageRel), spokenPage ? spokenPage.css : pageFile.code, "utf8");
32
51
  console.log(`✓ wrote ${pageRel} (${slug} v${generated.version})`);
33
52
  for (const f of siblings) {
34
53
  const rel = join(dirname(pageRel), f.filename);
35
- await writeFile(join(root, rel), f.code, "utf8");
54
+ const spoken = speak(f.code);
55
+ if (spoken) {
56
+ named += spoken.named;
57
+ inlined += spoken.inlined;
58
+ for (const l of spoken.left)
59
+ still.add(l);
60
+ }
61
+ await writeFile(join(root, rel), spoken ? spoken.css : f.code, "utf8");
36
62
  console.log(`✓ wrote ${rel}`);
37
63
  }
64
+ if (named > 0 || inlined > 0) {
65
+ console.log(` ${named} reference${named === 1 ? "" : "s"} now speak${named === 1 ? "s" : ""} the name YOUR code gives the value${inlined > 0 ? `, and ${inlined} carr${inlined === 1 ? "ies" : "y"} the value because your code names no token for it` : ""}.`);
66
+ if (still.size > 0) {
67
+ const sample = [...still].sort().slice(0, 3).join(", ");
68
+ console.log(` ${still.size} still point${still.size === 1 ? "s" : ""} at our stylesheet (${sample}${still.size > 3 ? ", …" : ""}), so tokens.css is still needed here.`);
69
+ }
70
+ }
38
71
  console.log("");
39
72
  console.log("Next steps:");
40
73
  console.log(` • use it in a route, e.g. ${join(config.pagesDir, "page.tsx")}:`);
@@ -152,8 +152,10 @@ export function triageLedger(ledger, triagedBy) {
152
152
  };
153
153
  }
154
154
  /** `0.16.133` é mais velha que `0.16.134`. Compara número por número, e o que não é número não
155
- * desempata nada - uma pré-release não é motivo para dizer que a medição está velha. */
156
- function isOlder(measured, current) {
155
+ * desempata nada - uma pré-release não é motivo para dizer que a medição está velha.
156
+ * Exportada porque é a TERCEIRA cópia desta pergunta (cli-version.ts e reinterpret.ts na web têm
157
+ * as outras) e a auditoria de 26/08 a encontrou fora do twin-drift - agora ele a amarra. */
158
+ export function isOlder(measured, current) {
157
159
  const parts = (v) => v.split(".").map((p) => Number.parseInt(p, 10));
158
160
  const a = parts(measured);
159
161
  const b = parts(current);
package/dist/guide.js CHANGED
@@ -18,20 +18,6 @@ const kebab = (v) => v.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
18
18
  const cssProp = (v) => (/^[A-Z]/.test(v) ? "-" : "") + kebab(v);
19
19
  const list = (items) => items.length ? items.map((i) => `\`${i}\``).join(", ") : "_(none)_";
20
20
  const dataAttrs = (variants) => Object.entries(variants).map(([axis, opts]) => `data-${kebab(axis)}="${Object.keys(opts).join("|")}"`);
21
- // Famílias genéricas do CSS - fallbacks, não webfonts a carregar.
22
- const GENERIC_FAMILIES = new Set([
23
- "sans-serif",
24
- "serif",
25
- "monospace",
26
- "system-ui",
27
- "ui-sans-serif",
28
- "ui-serif",
29
- "ui-monospace",
30
- "cursive",
31
- "fantasy",
32
- "inherit",
33
- "initial",
34
- ]);
35
21
  /** Famílias custom do documento (display/body/mono), deduplicadas, sem genéricos. */
36
22
  /**
37
23
  * THE STRUCTURE, WITH WHAT EACH PART IS FOR AND WHEN IT EXISTS.
@@ -45,3 +45,43 @@ export function tongueOf(map, installedCss) {
45
45
  }
46
46
  return { names, values };
47
47
  }
48
+ /**
49
+ * NENHUMA MATERIALIZAÇÃO VAZA VOCABULÁRIO INTERNO - a regra da camada, num lugar só (dono, 26/08).
50
+ *
51
+ * Toda saída que escreve código no repositório dele passa por ESTA porta: carrega o vocabulário do
52
+ * projeto (`projectTongue`) e traduz (`inTheirTongue`). O `template` entregava páginas inteiras com
53
+ * `--ds-*` cru enquanto o `component` traduzia - a mesma promessa, duas implementações, uma delas
54
+ * ausente. Um mecanismo novo de materialização que chamar esta função já nasce coberto; um que não
55
+ * chamar é reprovado pelo gate (ver contracts/camada-6-volta.md, INV-VOLTA-02).
56
+ *
57
+ * `null` quando não há mapa: projeto de destino, repositório que nunca buildou, ou install anterior
58
+ * a 0.16.290. Nos três casos nada é traduzido e a folha instalada continua sendo o caminho - e quem
59
+ * chama DIZ qual dos dois aconteceu.
60
+ */
61
+ export async function projectTongue(root, slug) {
62
+ const { readFile } = await import("node:fs/promises");
63
+ const { join } = await import("node:path");
64
+ const dir = join(root, "_synthesisui", "ds", slug);
65
+ const lock = await readFile(join(dir, ".lock"), "utf8").catch(() => null);
66
+ if (!lock)
67
+ return null;
68
+ let map = [];
69
+ let version = 0;
70
+ try {
71
+ const parsed = JSON.parse(lock);
72
+ map = parsed.tokenMap ?? [];
73
+ version = parsed.version ?? 0;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ if (map.length === 0)
79
+ return null;
80
+ /**
81
+ * O VALOR COMPILADO MORA NA PASTA DA VERSÃO - a folha da raiz é um re-export de uma linha, escrito
82
+ * assim de propósito para que o `@import` dele nunca mude entre updates (ver `add.ts`). É de lá
83
+ * que sai o literal para as variáveis que não têm nome dele.
84
+ */
85
+ const installed = await readFile(join(dir, `v${version}`, "tokens.css"), "utf8").catch(() => "");
86
+ return tongueOf(map, installed);
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.310",
3
+ "version": "0.16.312",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {