synthesisui 0.16.421 → 0.16.423

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.
@@ -14,7 +14,7 @@
14
14
  * emits. It renders completely unstyled, and nothing anywhere reports a problem.
15
15
  */
16
16
  import { readdir, readFile } from "node:fs/promises";
17
- import { join, relative } from "node:path";
17
+ import { join, relative, sep } from "node:path";
18
18
  import { DEFAULT_CONVENTION, } from "./component-codegen.js";
19
19
  /**
20
20
  * Which React the consumer is on, for the ref-carrying prop type.
@@ -172,42 +172,148 @@ export async function readInstalledScheme(root, slug) {
172
172
  }
173
173
  }
174
174
  /**
175
- * O QUE A FOLHA INSTALADA DECLARA NO `@theme` - a resposta que decide de quem é o VALOR.
175
+ * O QUE O `@theme` **DELE** DECLARA, NO APP ONDE O COMPONENTE VAI VIVER - e desde 11/09 é esta a
176
+ * resposta que decide o utilitário.
176
177
  *
177
- * O QUE O CLIENTE PERCEBE SEM ISTO: o componente sai vestindo `rounded-lg` e `font-mono`, a classe
178
- * existe em qualquer projeto com Tailwind, e ela pinta o **default do Tailwind** em vez do raio e da
179
- * fonte do sistema dele. Nada falta na tela - é a mesma peça com os números de outra biblioteca, o
180
- * que é mais difícil de achar que uma classe morta.
178
+ * O QUE O CLIENTE GANHA: o componente sai vestindo `rounded-lg` só quando `rounded-lg` já pinta o
179
+ * raio DELE - porque o `@theme` daquele app declara `--radius-lg`. Onde ele não declara, sai o
180
+ * valor arbitrário, que a porta de tradução resolve no nome dele ou no literal. Nos dois casos o
181
+ * arquivo funciona sem nenhuma folha nossa carregada.
181
182
  *
182
- * A folha deixa de declarar por dois motivos legítimos: o alinhamento tirou a linha para não roubar
183
- * uma classe que o app dele já usa (`INV-VOLTA-13`), ou o compilador não faz ponte para um nome que
184
- * não está em `meta.ownedNames`. Os dois se leem no mesmo lugar - o arquivo que caiu na pasta dele -
185
- * e é por isso que a pergunta é respondida AQUI e não no servidor: só nesta máquina existe a folha
186
- * que ele realmente tem.
183
+ * A PERGUNTA MUDOU DE LADO, e é a metade que faltava de `INV-GERAL-13`. Até aqui quem respondia era
184
+ * `installedThemeVars`, sobre a NOSSA folha: o codegen escrevia `rounded-lg` quando o nosso
185
+ * `theme.css` declarava `--radius-lg`, e aquela linha só existe dentro de um arquivo que o app dele
186
+ * teria que importar. Ou seja, o utilitário nomeado era a última dependência de runtime da nossa
187
+ * folha - invisível, porque a classe existe em qualquer projeto com Tailwind e pinta o default sem
188
+ * nada faltar na tela.
187
189
  *
188
- * MEDIDO em 07/09 sobre todos os componentes: 58 de 110 utilitários de token no `codelevel` (53%) e
189
- * 34 de 241 no `ember` (14%) não carregavam o valor do sistema.
190
+ * `null` É UMA RESPOSTA, e ela significa **não sei** - nunca "ele não declara nada". Os dois casos
191
+ * existem de verdade e pedem coisas opostas:
190
192
  *
191
- * `null` quando não há folha - projeto sem `add`, ou install antigo. Nesse caso nada pinta de
192
- * qualquer forma, e o `refit`/`generate` já dizem isso.
193
+ * nenhum `@theme` em lugar nenhum Tailwind v3 (o tema mora no `tailwind.config`), ou projeto
194
+ * sem Tailwind. Ali `rounded-lg` PODE pintar o valor dele, e
195
+ * responder "vazio" faria todo utilitário virar valor
196
+ * arbitrário - a régua acerta o argumento e erra o projeto
197
+ * um `@theme` que não declara ISTO aí o conjunto vem preenchido e a ausência é um fato
198
+ *
199
+ * Quem chama trata `null` como o `minted` sempre tratou: o nome legível fica, porque não há medição
200
+ * que o contradiga.
201
+ *
202
+ * A RESPOSTA É DO APP, E NÃO DO REPOSITÓRIO - e essa é a lição de `INV-VOLTA-12`, que saiu do
203
+ * produto com a instrução de import e não com a topologia. Num monorepo, varrer da raiz faz o
204
+ * `@theme` do app A responder por um componente escrito no app B: emitimos `bg-brand`, aquele app
205
+ * não gera a classe, e a propriedade renderiza NADA - pior que o valor arbitrário, porque nada
206
+ * falta na tela.
207
+ *
208
+ * A RESPOSTA É A INTERSEÇÃO DOS APPS, mais o que é compartilhado - ver o corpo. Um componente
209
+ * materializado vai para uma pasta que num monorepo os dois apps importam, e ele não sabe em qual
210
+ * será usado: o nome só é seguro quando vale em todos.
193
211
  */
194
- export async function installedThemeVars(root, slug) {
195
- const dir = join(root, "_synthesisui", "ds", slug);
196
- const version = await pinnedVersion(dir);
197
- if (!version)
198
- return null;
199
- const css = await readFile(join(dir, `v${version}`, "theme.css"), "utf8").catch(() => "");
200
- if (!css)
201
- return null;
212
+ export async function theirThemeVars(root,
213
+ /**
214
+ * As pastas de app deste repositório - `detectAppDirs`. Vazia num projeto de um app só, que é a
215
+ * maioria, e aí a resposta é a do repositório inteiro.
216
+ */
217
+ apps = []) {
218
+ const shared = new Set();
219
+ let sawTheme = false;
220
+ const collect = async (dir, into, skipApps) => {
221
+ const walk = async (at) => {
222
+ for (const entry of await readdir(at, { withFileTypes: true }).catch(() => [])) {
223
+ if (SKIP.has(entry.name) || entry.name.startsWith("."))
224
+ continue;
225
+ const path = join(at, entry.name);
226
+ const rel = relative(root, path).split(sep).join("/");
227
+ /** Ao varrer o compartilhado, toda pasta que É app (ou contém uma) fica de fora. */
228
+ if (skipApps &&
229
+ apps.some((app) => app === rel || app.startsWith(`${rel}/`)))
230
+ continue;
231
+ if (entry.isDirectory())
232
+ await walk(path);
233
+ else if (/\.css$/i.test(entry.name)) {
234
+ const css = await readFile(path, "utf8").catch(() => "");
235
+ if (!THEME_BLOCK.test(css))
236
+ continue;
237
+ sawTheme = true;
238
+ for (const name of themeVarsIn(css))
239
+ into.add(name);
240
+ }
241
+ }
242
+ };
243
+ await walk(dir);
244
+ };
245
+ /** O que NÃO mora em nenhum app: o pacote compartilhado, e ele vale para todos. */
246
+ await collect(root, shared, apps.length > 0);
247
+ if (apps.length === 0)
248
+ return sawTheme ? shared : null;
202
249
  /**
203
- * Só o que está DENTRO de um `@theme` conta - é a única coisa que o Tailwind v4 lê para gerar
204
- * utilitário. Uma variável no `[data-ds]` do `tokens.css` não gera nada, e foi tratar as duas como
205
- * iguais que fez o `theme.css` parecer suficiente quando não era.
250
+ * E O QUE CADA APP DECLARA, INTERSECTADO - porque um componente materializado não sabe em qual
251
+ * app vai ser usado.
252
+ *
253
+ * `components/<nome>/` num monorepo é compartilhado por construção. Se o app A declara
254
+ * `--color-brand` e o B não, escrever `bg-brand` entrega uma propriedade que renderiza NADA no B -
255
+ * pior que o valor arbitrário, porque nada falta na tela. A interseção é a única resposta que vale
256
+ * em qualquer um deles, e ela degrada para "o que o repositório declara" quando há um app só.
206
257
  */
207
- const blocks = css.matchAll(/@theme[^{]*\{([\s\S]*?)\n\}/g);
208
- const declared = new Set();
209
- for (const block of blocks)
210
- for (const m of block[1].matchAll(/^\s*(--[a-zA-Z0-9-]+)\s*:/gm))
211
- declared.add(m[1]);
212
- return declared;
258
+ let common = null;
259
+ for (const app of apps) {
260
+ const mine = new Set(shared);
261
+ await collect(join(root, ...app.split("/")), mine, false);
262
+ if (common === null)
263
+ common = mine;
264
+ else
265
+ for (const name of [...common])
266
+ if (!mine.has(name))
267
+ common.delete(name);
268
+ }
269
+ return sawTheme ? (common ?? shared) : null;
270
+ }
271
+ /** As pastas que nenhuma varredura de CSS dele deve entrar - `_synthesisui/` é NOSSA. */
272
+ const SKIP = new Set([
273
+ "node_modules",
274
+ ".git",
275
+ "dist",
276
+ ".next",
277
+ "build",
278
+ "out",
279
+ "_synthesisui",
280
+ ]);
281
+ /** Existe um `@theme` neste texto? - a pergunta que separa "não declara" de "não sei". */
282
+ const THEME_BLOCK = /@theme[^{]*\{/;
283
+ /**
284
+ * Os nomes declarados dentro de um `@theme { … }` - a única coisa que o Tailwind v4 lê para gerar
285
+ * utilitário. Uma variável no `:root` não gera classe nenhuma, e tratar as duas como iguais foi o
286
+ * que fez o `theme.css` parecer suficiente quando não era.
287
+ *
288
+ * NADA AQUI ASSUME COMO ELE FORMATA - e essa suposição era legítima enquanto esta função lia a
289
+ * NOSSA folha, que nós escrevemos. Ela deixou de ser no instante em que a pergunta mudou de lado.
290
+ *
291
+ * As duas âncoras antigas eram nossas: `\n\}` para fechar o bloco (uma folha com `@theme { … }`
292
+ * numa linha só nunca fechava) e `^\s*--nome:` para a declaração (nenhuma delas começa a linha num
293
+ * arquivo minificado). Nos dois casos o conjunto saía VAZIO, e vazio não é "não declara": é todo
294
+ * utilitário nomeado virando valor arbitrário, calado.
295
+ *
296
+ * O bloco é contado por CHAVES, e a declaração é delimitada pela pontuação - `{` ou `;` antes, e
297
+ * `;` ou `}` depois, este em lookahead para que o `;` de uma declaração possa abrir a próxima. É a
298
+ * mesma correção que `their-tongue.ts` recebeu no mesmo diff, pelo mesmo motivo.
299
+ */
300
+ function themeVarsIn(css) {
301
+ const out = [];
302
+ for (const m of css.matchAll(/@theme[^{]*\{/g)) {
303
+ let depth = 1;
304
+ let i = (m.index ?? 0) + m[0].length;
305
+ const start = i;
306
+ for (; i < css.length && depth > 0; i += 1) {
307
+ const c = css[i];
308
+ if (c === "{")
309
+ depth += 1;
310
+ else if (c === "}")
311
+ depth -= 1;
312
+ }
313
+ for (const d of css
314
+ .slice(start, i - 1)
315
+ .matchAll(/(?:^|[{;])\s*(--[a-zA-Z0-9-]+)\s*:\s*[^;}]+(?=[;}]|$)/g))
316
+ out.push(d[1]);
317
+ }
318
+ return out;
213
319
  }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * AS REGRAS DE RECEITA QUE UMA PÁGINA VESTE, COPIADAS PARA O CSS DELA.
3
+ *
4
+ * O QUE O CLIENTE GANHA: a página que o `template` escreve renderiza sem nenhuma folha nossa
5
+ * carregada no app dele. Ela veste `.ds-hero`, `.ds-nav` e as outras classes que o sistema declara,
6
+ * e essas regras passam a morar no `.css` colocalizado ao lado da própria página - traduzidas para
7
+ * o vocabulário dele, como todo o resto.
8
+ *
9
+ * O QUE ISTO SUBSTITUI. Uma página é a única materialização que depende da folha por CLASSE, e não
10
+ * por variável: a tradução (`their-tongue.ts`) reescreve `var(--ds-*)` e não tem o que fazer com
11
+ * `.ds-hero`, porque o corpo daquela regra nunca esteve no arquivo. Enquanto isso fosse verdade, o
12
+ * `template` terminava mandando instalar o sistema e colar um `@import` - a instrução que
13
+ * `INV-GERAL-13` proíbe, e a última que sobrava no produto.
14
+ *
15
+ * A PÁGINA VESTE TRÊS CAMADAS, e a primeira versão desta cópia lia UMA.
16
+ *
17
+ * A folha compilada escopa no mesmo `[data-ds]` três coisas diferentes, e a revisão do fecho mediu
18
+ * o que ficava para trás:
19
+ *
20
+ * `@layer components` uma regra por receita - `.ds-hero`, `.ds-nav`
21
+ * `@layer base` o CHÃO do sistema (cor do texto e família do corpo), o piso de
22
+ * `:focus-visible`, e o bloco de `prefers-reduced-motion`
23
+ * `@layer utilities` os utilitários DELE que a folha espelha
24
+ *
25
+ * Copiar só a primeira entregava a página com as receitas e SEM o chão de tipografia, sem o anel de
26
+ * foco e sem a regra de movimento reduzido - uma regra de acessibilidade que o sistema declara e
27
+ * que sumiria sem uma linha em lugar nenhum, sob um terminal dizendo *"nothing to install: this page
28
+ * and its stylesheet stand on their own"*.
29
+ *
30
+ * O QUE A CÓPIA DESFAZ É UMA COISA SÓ: o `@layer`. As camadas existem para o CSS dele poder
31
+ * sobrescrever o nosso sem disputa de especificidade, e isso só faz sentido dentro de uma folha que
32
+ * traz as duas metades. Soltas no arquivo dele, elas mudariam a ordem de cascata daquele arquivo.
33
+ *
34
+ * O `[data-ds="<slug>"]` FICA, e ele é o que impede o vazamento. A página que o `template` escreve
35
+ * já nasce dentro de um wrapper com esse atributo - é assim que o CSS colocalizado dela sempre
36
+ * aplicou -, então o seletor resolve. Desescopar transformaria `.ds-button` numa regra global no
37
+ * app inteiro dele, e um `import "./landing.css"` não isola nada: seria a nossa folha entrando pela
38
+ * porta que esta etapa acabou de fechar.
39
+ *
40
+ * O QUE ELA NÃO FAZ: inventar regra. Só as classes que a página REALMENTE veste são copiadas, e o
41
+ * que a folha não declara não vira nada - a página perde aquilo do mesmo jeito que perderia hoje,
42
+ * e quem chama diz o quê.
43
+ */
44
+ /**
45
+ * O corpo de CADA `@layer { … }` da folha, com as chaves de dentro contadas.
46
+ *
47
+ * O nome da camada não filtra nada: `base`, `components` e `utilities` carregam, todas as três,
48
+ * regras escopadas que a página veste. O que decide se uma regra é copiada é a CLASSE que ela
49
+ * declara e que o arquivo escreve - a mesma pergunta em qualquer camada.
50
+ */
51
+ function layerBodies(css) {
52
+ const out = [];
53
+ for (const m of css.matchAll(/@layer\s+[\w-]+\s*\{/g)) {
54
+ let depth = 1;
55
+ let i = (m.index ?? 0) + m[0].length;
56
+ const start = i;
57
+ for (; i < css.length && depth > 0; i += 1) {
58
+ const c = css[i];
59
+ if (c === "{")
60
+ depth += 1;
61
+ else if (c === "}")
62
+ depth -= 1;
63
+ }
64
+ out.push(css.slice(start, i - 1));
65
+ }
66
+ return out;
67
+ }
68
+ /**
69
+ * AS REGRAS DE UM CORPO DE CAMADA, uma a uma - prelúdio + bloco.
70
+ *
71
+ * Uma regra de agrupamento (`@media`, `@supports`) vem inteira, com o corpo dela: cortá-la ao meio
72
+ * produziria CSS inválido, e as media queries são justamente onde mora o comportamento responsivo
73
+ * que a página precisa manter.
74
+ */
75
+ function rulesIn(body) {
76
+ const out = [];
77
+ let i = 0;
78
+ let start = 0;
79
+ while (i < body.length) {
80
+ if (body[i] !== "{") {
81
+ i += 1;
82
+ continue;
83
+ }
84
+ const prelude = body.slice(start, i).trim();
85
+ let depth = 1;
86
+ let j = i + 1;
87
+ for (; j < body.length && depth > 0; j += 1) {
88
+ if (body[j] === "{")
89
+ depth += 1;
90
+ else if (body[j] === "}")
91
+ depth -= 1;
92
+ }
93
+ if (prelude)
94
+ out.push({ prelude, block: body.slice(i + 1, j - 1) });
95
+ i = j;
96
+ start = j;
97
+ }
98
+ return out;
99
+ }
100
+ /** Os nomes de classe que um prelúdio de seletor menciona - `sm\:ds-hero` conta como `ds-hero`. */
101
+ function classesOf(prelude) {
102
+ const out = [];
103
+ for (const m of prelude.matchAll(/\.((?:\\.|[\w-])+)/g)) {
104
+ const bare = m[1].replace(/\\(.)/g, "$1");
105
+ out.push((bare.split(":").pop() ?? bare).replace(/^[!-]/, ""));
106
+ }
107
+ return out;
108
+ }
109
+ /**
110
+ * A REGRA É O ATRIBUTO, E NÃO A FUNÇÃO - e esta capacidade já estava provada antes de nascer aqui.
111
+ *
112
+ * A primeira versão desta função casava só o valor LITERAL de `class`/`className`. Funcionava porque
113
+ * o NOSSO gerador emite literal - ou seja, a régua estava calibrada na forma da nossa própria saída,
114
+ * e o refino que o próprio cabeçalho da página manda ele fazer a deixava para trás.
115
+ *
116
+ * `sheet-needed.ts`, apagado nesta mesma etapa, já tinha resolvido isso, com a medição escrita:
117
+ * `className={cn(…)}` aparece **66 vezes em `packages/ui/src` e 239 em `apps/web-dashboard`** do
118
+ * `frontend-hub` (08/09) - 305 sítios onde a pergunta era feita sobre um texto que não continha a
119
+ * resposta. Uma capacidade provada não se reimplementa mais fraca porque o módulo mudou de nome.
120
+ *
121
+ * POR QUE NÃO O NOME DA FUNÇÃO: casar `cn|clsx|twMerge` seria a lista dos casos de hoje - o próximo
122
+ * projeto chama a dele de `cx`, `classes`, ou passa um ternário direto. O que é estrutural é o
123
+ * ATRIBUTO: dentro do valor de um `class`/`className`, toda string literal é candidata a classe.
124
+ *
125
+ * O QUE ISTO NÃO ALCANÇA, com o número: a tabela de variantes numa const separada (`cva`, `tv`), que
126
+ * chega ao atributo por VARIÁVEL. `sheet-needed.ts` seguia a variável; aqui o erro cai para o lado
127
+ * seguro - uma classe não vista é uma regra não copiada, e a página perde estilo em vez de ganhar
128
+ * regra que ninguém veste. Quando aparecer uma página que a use, o número dela abre a frente.
129
+ */
130
+ export function classesWorn(source) {
131
+ const out = new Set();
132
+ const collect = (body) => {
133
+ for (const raw of body.split(/\s+/)) {
134
+ if (!raw)
135
+ continue;
136
+ const bare = raw.split(":").pop() ?? raw;
137
+ out.add(bare.replace(/^[!-]/, ""));
138
+ }
139
+ };
140
+ for (const m of source.matchAll(/class(?:Name)?=(?:"([^"]*)"|'([^']*)'|\{`([^`]*)`\}|\{"([^"]*)"\})/g))
141
+ collect(m[1] ?? m[2] ?? m[3] ?? m[4] ?? "");
142
+ /** E toda string DENTRO da expressão do atributo - ver `attributeExpressions`. */
143
+ for (const expr of attributeExpressions(source))
144
+ for (const lit of expr.matchAll(/"([^"]*)"|'([^']*)'|`([^`]*)`/g))
145
+ collect(lit[1] ?? lit[2] ?? lit[3] ?? "");
146
+ return out;
147
+ }
148
+ /**
149
+ * O VALOR DE UM ATRIBUTO DE CLASSE, QUANDO ELE É UMA EXPRESSÃO - copiado de `sheet-needed.ts`, que
150
+ * saiu nesta etapa, e com a medição que o originou preservada acima.
151
+ */
152
+ function attributeExpressions(source) {
153
+ const out = [];
154
+ const ATTR = /class(?:Name)?=\{/g;
155
+ for (const m of source.matchAll(ATTR)) {
156
+ let depth = 0;
157
+ let i = (m.index ?? 0) + m[0].length - 1;
158
+ const start = i;
159
+ /** Aspas contam para NÃO deixar uma chave dentro de string fechar a expressão cedo. */
160
+ let quote = null;
161
+ for (; i < source.length; i += 1) {
162
+ const c = source[i];
163
+ if (quote) {
164
+ if (c === "\\")
165
+ i += 1;
166
+ else if (c === quote)
167
+ quote = null;
168
+ continue;
169
+ }
170
+ if (c === '"' || c === "'" || c === "`")
171
+ quote = c;
172
+ else if (c === "{")
173
+ depth += 1;
174
+ else if (c === "}") {
175
+ depth -= 1;
176
+ if (depth === 0)
177
+ break;
178
+ }
179
+ }
180
+ if (depth === 0)
181
+ out.push(source.slice(start + 1, i));
182
+ }
183
+ return out;
184
+ }
185
+ /**
186
+ * AS REGRAS QUE ESTA PÁGINA VESTE, desescopadas e prontas para o `.css` ao lado dela.
187
+ *
188
+ * `sheetCss` é a folha compilada da versão instalada (`_synthesisui/ds/<slug>/v<n>/tokens.css`) -
189
+ * o insumo NOSSO, que continua caindo na pasta e que nada no app dele importa.
190
+ *
191
+ * O seletor sai como está, escopo incluído: a página vive dentro do wrapper que o carrega, e é ele
192
+ * que mantém estas regras dentro da página em vez de soltas no app dele.
193
+ */
194
+ export function recipeRulesFor(input) {
195
+ const worn = classesWorn(input.source);
196
+ const out = [];
197
+ const classes = new Set();
198
+ for (const body of layerBodies(input.sheetCss))
199
+ for (const { prelude, block } of rulesIn(body)) {
200
+ /** Uma regra de agrupamento entra inteira quando algo dentro dela é vestido. */
201
+ const names = prelude.startsWith("@")
202
+ ? [...classesOf(prelude), ...classesOf(block)]
203
+ : classesOf(prelude);
204
+ const hit = names.filter((n) => worn.has(n));
205
+ if (hit.length === 0)
206
+ continue;
207
+ for (const n of hit)
208
+ classes.add(n);
209
+ out.push(`${prelude.replace(/\s+/g, " ").trim()} {${block}}`);
210
+ }
211
+ return {
212
+ css: out.join("\n"),
213
+ rules: out.length,
214
+ classes: [...classes].sort(),
215
+ };
216
+ }
217
+ /**
218
+ * A FOLHA COMPILADA DA VERSÃO INSTALADA - o insumo NOSSO, de onde as regras são copiadas.
219
+ *
220
+ * A folha da raiz é um re-export de uma linha (`@import "./v<n>/tokens.css"`), então quem tem as
221
+ * regras é o arquivo da versão; o `.lock` diz qual é. Vazio quando não há pasta - e aí não há o que
222
+ * copiar, o que é uma resposta e não uma falha.
223
+ */
224
+ export async function installedSheetCss(root, slug) {
225
+ const { readFile } = await import("node:fs/promises");
226
+ const { join } = await import("node:path");
227
+ const dir = join(root, "_synthesisui", "ds", slug);
228
+ const lock = await readFile(join(dir, ".lock"), "utf8").catch(() => null);
229
+ let version = 0;
230
+ if (lock) {
231
+ try {
232
+ version = JSON.parse(lock).version ?? 0;
233
+ }
234
+ catch {
235
+ version = 0;
236
+ }
237
+ }
238
+ const versioned = await readFile(join(dir, `v${version}`, "tokens.css"), "utf8").catch(() => "");
239
+ if (versioned)
240
+ return versioned;
241
+ return readFile(join(dir, "tokens.css"), "utf8").catch(() => "");
242
+ }
243
+ /**
244
+ * O CABEÇALHO DO BLOCO COPIADO - procedência, e nenhuma instrução.
245
+ *
246
+ * Ele responde a pergunta de quem abre o arquivo depois ("de onde vieram estas regras?") sem pedir
247
+ * nada. A versão anterior deste produto respondia a mesma pergunta mandando importar a folha.
248
+ */
249
+ export const RECIPE_HEADER = "/* From your design system, copied here so this page needs no stylesheet of ours. */";
package/dist/skills.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { ADAPT_SKILL, ADAPT_SKILL_PATH } from "./skill-adapt.js";
2
2
  import { COMPOSE_SKILL, COMPOSE_SKILL_PATH } from "./skill-compose.js";
3
- import { CONFIGURE_SKILL, CONFIGURE_SKILL_PATH } from "./skill-configure.js";
4
3
  import { IMPORT_SKILL, IMPORT_SKILL_PATH } from "./skill-import.js";
5
4
  import { INIT_SKILL, INIT_SKILL_PATH } from "./skill-init.js";
6
5
  /**
@@ -11,6 +10,11 @@ import { INIT_SKILL, INIT_SKILL_PATH } from "./skill-init.js";
11
10
  * conta própria, rodasse `connect` de novo. Ninguém roda um comando de novo sem motivo.
12
11
  *
13
12
  * É a lei 8 no caso mais barato dela: a lacuna existe, a gente sabe qual é, e dizer custa uma linha.
13
+ *
14
+ * ERAM CINCO E SÃO QUATRO desde 11/09: `/sui-configure-ds` existia para fazer os tokens chegarem ao
15
+ * navegador dele pelo `@import` da nossa folha, e nenhum app dele carrega nada nosso
16
+ * (`INV-GERAL-13`). Quem já tem o arquivo é avisado pelo `connect`, que o NOMEIA sem apagá-lo -
17
+ * ver `RETIRED_SKILLS`.
14
18
  */
15
19
  export const SKILLS = [
16
20
  {
@@ -54,19 +58,4 @@ export const SKILLS = [
54
58
  label: "/sui-compose",
55
59
  what: "build what the system does not have",
56
60
  },
57
- /**
58
- * A DE LIGAR O SISTEMA NO APP, e ela é a única aqui que fecha um passo que a esteira já sabia
59
- * diagnosticar e não sabia resolver.
60
- *
61
- * O `add` IMPRIME a fiação, o `doctor` CONFERE a fiação com três ✓/✗, e nada a ESCREVE. Enquanto
62
- * ela falta, os tokens não chegam ao navegador e o `doctor --fix` fica recusado de propósito - um
63
- * fix num projeto sem fiação trocou 210 literais por variáveis que o navegador não resolvia e mudou
64
- * a página (06/08).
65
- */
66
- {
67
- path: CONFIGURE_SKILL_PATH,
68
- source: CONFIGURE_SKILL,
69
- label: "/sui-configure-ds",
70
- what: "the tokens, loaded by your app",
71
- },
72
61
  ];