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.
- package/dist/claude-md.js +19 -38
- package/dist/commands/add.js +57 -94
- package/dist/commands/component.js +96 -201
- package/dist/commands/connect.js +41 -0
- package/dist/commands/doctor.js +74 -428
- package/dist/commands/generate.js +25 -4
- package/dist/commands/import.js +2 -2
- package/dist/commands/init.js +13 -10
- package/dist/commands/refit.js +13 -2
- package/dist/commands/summary.js +9 -5
- package/dist/commands/sync.js +84 -0
- package/dist/commands/template.js +81 -53
- package/dist/commands/upgrade.js +5 -3
- package/dist/commands/use.js +7 -8
- package/dist/component-codegen.js +50 -23
- package/dist/copy/connect.pt-BR.js +3 -0
- package/dist/doctor/apply-fix.js +2 -2
- package/dist/doctor/scan.js +33 -2
- package/dist/doctor/their-names.js +8 -2
- package/dist/fonts.js +29 -5
- package/dist/global-sheet.js +14 -125
- package/dist/guide.js +131 -83
- package/dist/install-marks.js +4 -4
- package/dist/local-edits.js +257 -0
- package/dist/project-facts.js +138 -32
- package/dist/recipe-css.js +249 -0
- package/dist/skills.js +5 -16
- package/dist/their-tongue.js +180 -43
- package/dist/wired-slugs.js +31 -17
- package/package.json +1 -1
- package/dist/setup-prompt.js +0 -95
- package/dist/sheet-needed.js +0 -317
- package/dist/skill-configure.js +0 -13
- package/dist/wiring-read.js +0 -212
|
@@ -2,8 +2,9 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { generateComponentFiles } from "../component-codegen.js";
|
|
4
4
|
import { readProjectConfig, resolveRegistry } from "../config.js";
|
|
5
|
+
import { detectAppDirs } from "../global-sheet.js";
|
|
5
6
|
import { installedSlugs } from "../installed.js";
|
|
6
|
-
import {
|
|
7
|
+
import { reactMajorOf, readInstalledConvention, readInstalledScheme, theirThemeVars, } from "../project-facts.js";
|
|
7
8
|
import { postGenerate, RegistryError } from "../registry.js";
|
|
8
9
|
import { flavourResolver } from "../styles-flavour.js";
|
|
9
10
|
import { projectTongue } from "../their-tongue.js";
|
|
@@ -75,7 +76,17 @@ export async function generate(description, opts) {
|
|
|
75
76
|
// project as the stylesheet it has to match.
|
|
76
77
|
await readInstalledConvention(root, slug), res.name, await readInstalledScheme(root, slug),
|
|
77
78
|
/** O VOCABULÁRIO DELE - um componente gerado cai no mesmo projeto e fala a mesma língua. */
|
|
78
|
-
await projectTongue(root, slug),
|
|
79
|
+
await projectTongue(root, slug),
|
|
80
|
+
/**
|
|
81
|
+
* AS PASTAS DE APP, para a resposta ser a INTERSEÇÃO delas - ver `theirThemeVars`.
|
|
82
|
+
*
|
|
83
|
+
* Um componente materializado vai para uma pasta que num monorepo os dois apps importam, e
|
|
84
|
+
* ele não sabe em qual será usado. Varrer da raiz faria o `@theme` do app A responder por
|
|
85
|
+
* um componente escrito no app B: emitimos `bg-brand`, aquele app não gera a classe, e a
|
|
86
|
+
* propriedade renderiza NADA - pior que o valor arbitrário, porque nada falta na tela. É a
|
|
87
|
+
* mesma lição de `INV-VOLTA-12`, que saiu com a instrução de import e não com a topologia.
|
|
88
|
+
*/
|
|
89
|
+
await theirThemeVars(root, await detectAppDirs(root, config.pagesDir)));
|
|
79
90
|
/**
|
|
80
91
|
* A EDICAO DELE VENCE A REESCRITA (T7) - a leitura que faltava.
|
|
81
92
|
*
|
|
@@ -109,8 +120,18 @@ export async function generate(description, opts) {
|
|
|
109
120
|
console.log(` • <${comp} /> - compose its parts + content (see the recipe)`);
|
|
110
121
|
}
|
|
111
122
|
else {
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
/**
|
|
124
|
+
* O ARQUIVO NÃO É IMPORTADO DA NOSSA PASTA - `INV-GERAL-13`, 11/09.
|
|
125
|
+
*
|
|
126
|
+
* A instrução mandava `@import "_synthesisui/ds/<slug>/generated/<name>.css"` e envolver a
|
|
127
|
+
* marcação num `data-ds` nosso. As duas apontavam para dentro da nossa pasta, e é a dependência
|
|
128
|
+
* que esta etapa fechou.
|
|
129
|
+
*
|
|
130
|
+
* A folha gerada já passou pela porta de tradução, então ela fala o vocabulário dele: copiá-la
|
|
131
|
+
* para onde as folhas dele vivem não perde nada, e o que fica aqui segue sendo a referência.
|
|
132
|
+
*/
|
|
133
|
+
console.log(` • copy _synthesisui/ds/${slug}/generated/${res.name}.css next to your own stylesheets - it already speaks your vocabulary, and nothing of ours has to be loaded`);
|
|
134
|
+
console.log(` • <div class="ds-${res.name}">…</div>`);
|
|
114
135
|
}
|
|
115
136
|
console.log(` (${res.usage.inputTokens} in / ${res.usage.outputTokens} out tokens · AI action - additive; nothing else changed)`);
|
|
116
137
|
}
|
package/dist/commands/import.js
CHANGED
|
@@ -4643,7 +4643,7 @@ export async function runImport(opts) {
|
|
|
4643
4643
|
*/
|
|
4644
4644
|
if (payload?.slug) {
|
|
4645
4645
|
/**
|
|
4646
|
-
*
|
|
4646
|
+
* O QUE O CSS DELE AINDA IMPORTA - e este aviso sai do CLI, não da skill.
|
|
4647
4647
|
*
|
|
4648
4648
|
* MEDIDO em 24/08: o `globals.css` dele importa `_synthesisui/ds/codelevel/`, o nome escolhido
|
|
4649
4649
|
* derivou `codelevel-ds`, ninguém mencionou, e o `next build` dele terminou em exit code 1 com
|
|
@@ -4658,7 +4658,7 @@ export async function runImport(opts) {
|
|
|
4658
4658
|
const warning = wiringWarning(census.wiredSlugs ?? [], payload.slug);
|
|
4659
4659
|
if (warning) {
|
|
4660
4660
|
console.log("");
|
|
4661
|
-
console.log(section("Your CSS
|
|
4661
|
+
console.log(section("Your CSS still imports a stylesheet of ours"));
|
|
4662
4662
|
for (const line of warning.split("\n"))
|
|
4663
4663
|
console.log(body(line));
|
|
4664
4664
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_CONFIG, writeProjectConfig } from "../config.js";
|
|
2
2
|
import { body, section, snippet } from "../output.js";
|
|
3
|
-
import { setupPrompt } from "../setup-prompt.js";
|
|
4
3
|
import { resolveDeps, stylesFor, tailwindMajor } from "../stack.js";
|
|
5
4
|
import { formMix, measuredStyle } from "../styles-flavour.js";
|
|
6
5
|
import { add } from "./add.js";
|
|
@@ -134,19 +133,23 @@ export async function init(opts) {
|
|
|
134
133
|
dir: root,
|
|
135
134
|
setupHints: false,
|
|
136
135
|
});
|
|
136
|
+
/**
|
|
137
|
+
* ERAM DOIS PASSOS E É UM - `INV-GERAL-13`, 11/09.
|
|
138
|
+
*
|
|
139
|
+
* O passo 2 colava `setupPrompt` no agente dele: dois `@import` da nossa folha, um `data-ds` na
|
|
140
|
+
* árvore dele, e o mapa de tipografia. Ele não existe mais, porque nada que a plataforma escreve
|
|
141
|
+
* precisa de folha nossa carregada - e um comando de primeira vez é o pior lugar possível para
|
|
142
|
+
* ensinar uma dependência que o produto promete não criar.
|
|
143
|
+
*/
|
|
137
144
|
console.log("");
|
|
138
|
-
console.log(section("
|
|
139
|
-
console.log(body("
|
|
140
|
-
console.log(body("
|
|
145
|
+
console.log(section("One step left, and it is not a file you edit"));
|
|
146
|
+
console.log(body("Turn the check and the tools on - run this BEFORE you open your agent,"));
|
|
147
|
+
console.log(body("because hooks and tools are read when a session starts:"));
|
|
141
148
|
console.log("");
|
|
142
149
|
console.log(snippet(["npx synthesisui@latest connect"]));
|
|
143
150
|
console.log("");
|
|
144
|
-
console.log(body("
|
|
145
|
-
console.log("");
|
|
146
|
-
console.log(snippet(setupPrompt(opts.ds).split("\n")));
|
|
147
|
-
console.log("");
|
|
148
|
-
console.log(body("Then ask it for something real. The check introduces itself on the first"));
|
|
149
|
-
console.log(body("clean file and goes quiet after that."));
|
|
151
|
+
console.log(body("Then ask your agent for something real. The check introduces itself on the"));
|
|
152
|
+
console.log(body("first clean file and goes quiet after that."));
|
|
150
153
|
return;
|
|
151
154
|
}
|
|
152
155
|
console.log("");
|
package/dist/commands/refit.js
CHANGED
|
@@ -2,9 +2,10 @@ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { basename, join } from "node:path";
|
|
3
3
|
import { generateComponentFiles } from "../component-codegen.js";
|
|
4
4
|
import { readProjectConfig, resolveRegistry } from "../config.js";
|
|
5
|
+
import { detectAppDirs } from "../global-sheet.js";
|
|
5
6
|
import { installedSlugs } from "../installed.js";
|
|
6
7
|
import { body, section, snippet } from "../output.js";
|
|
7
|
-
import {
|
|
8
|
+
import { reactMajorOf, readInstalledConvention, readInstalledScheme, theirThemeVars, } from "../project-facts.js";
|
|
8
9
|
import { fetchComponent, postRefit, postSaveComponent, RegistryError, } from "../registry.js";
|
|
9
10
|
import { flavourResolver } from "../styles-flavour.js";
|
|
10
11
|
import { projectTongue } from "../their-tongue.js";
|
|
@@ -121,7 +122,17 @@ export async function refit(file, opts) {
|
|
|
121
122
|
const flavourOf = await flavourResolver(root, config.styles);
|
|
122
123
|
const { files } = generateComponentFiles(slug, res.name, res.recipe, res.css, saved.version, flavourOf(res.name), await reactMajorOf(root), await readInstalledConvention(root, slug), res.name, await readInstalledScheme(root, slug),
|
|
123
124
|
/** O VOCABULÁRIO DELE - o `refit` reescreve o componente e não passava pela porta. */
|
|
124
|
-
await projectTongue(root, slug),
|
|
125
|
+
await projectTongue(root, slug),
|
|
126
|
+
/**
|
|
127
|
+
* AS PASTAS DE APP, para a resposta ser a INTERSEÇÃO delas - ver `theirThemeVars`.
|
|
128
|
+
*
|
|
129
|
+
* Um componente materializado vai para uma pasta que num monorepo os dois apps importam, e
|
|
130
|
+
* ele não sabe em qual será usado. Varrer da raiz faria o `@theme` do app A responder por
|
|
131
|
+
* um componente escrito no app B: emitimos `bg-brand`, aquele app não gera a classe, e a
|
|
132
|
+
* propriedade renderiza NADA - pior que o valor arbitrário, porque nada falta na tela. É a
|
|
133
|
+
* mesma lição de `INV-VOLTA-12`, que saiu com a instrução de import e não com a topologia.
|
|
134
|
+
*/
|
|
135
|
+
await theirThemeVars(root, await detectAppDirs(root, config.pagesDir)));
|
|
125
136
|
/**
|
|
126
137
|
* A EDICAO DELE VENCE A REESCRITA (T7) - a leitura que faltava, a mesma do `generate`.
|
|
127
138
|
*
|
package/dist/commands/summary.js
CHANGED
|
@@ -68,12 +68,16 @@ export async function summary(slug, opts) {
|
|
|
68
68
|
/**
|
|
69
69
|
* LINHA 3 - O QUE FAZER AGORA, e é uma coisa só.
|
|
70
70
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
71
|
+
* AS DUAS LINHAS DE FIAÇÃO SAÍRAM EM 11/09 - `INV-GERAL-13`. Elas eram descritas aqui como *"o
|
|
72
|
+
* portão de tudo o mais"*, e essa frase era verdadeira enquanto o que a plataforma escrevia
|
|
73
|
+
* dependia da nossa folha. Não depende mais: um componente chega falando os nomes que o código
|
|
74
|
+
* dele declara, ou carregando o valor.
|
|
75
|
+
*
|
|
76
|
+
* Este é o último ecrã da primeira corrida, e é o pior lugar do produto para ensinar uma
|
|
77
|
+
* dependência - ele é lido uma vez, com atenção, por alguém que está decidindo se fica.
|
|
74
78
|
*/
|
|
75
79
|
console.log("");
|
|
76
|
-
console.log(body("
|
|
77
|
-
console.log(body(
|
|
80
|
+
console.log(body("Nothing of ours goes into your code - there is no"));
|
|
81
|
+
console.log(body("stylesheet to import and no attribute to add."));
|
|
78
82
|
console.log(paint.blue(snippet(["npx synthesisui@latest doctor"])));
|
|
79
83
|
}
|
package/dist/commands/sync.js
CHANGED
|
@@ -8,6 +8,7 @@ import { markSent, readEvents } from "../doctor/ledger.js";
|
|
|
8
8
|
import { checkableName, closeRequest, readRequests, verifyAndCloseRequests, } from "../doctor/requests.js";
|
|
9
9
|
import { sampledForUpload } from "../doctor/style-ledger.js";
|
|
10
10
|
import { describeDelta, fingerprintReadings, readSyncMark, writeSyncMark, } from "../last-sync.js";
|
|
11
|
+
import { installedVersion, landedLine, localEdits, readInstalledPair, sentLine, settleBaseline, } from "../local-edits.js";
|
|
11
12
|
import { measuredScope, rememberScope } from "../measured-scope.js";
|
|
12
13
|
import { fromCensus } from "../memory/observation.js";
|
|
13
14
|
import { reportMeasurement } from "../memory/report.js";
|
|
@@ -551,6 +552,43 @@ export async function remeasure(args) {
|
|
|
551
552
|
return;
|
|
552
553
|
}
|
|
553
554
|
}
|
|
555
|
+
/**
|
|
556
|
+
* O QUE ELE MUDOU NO DESIGN SYSTEM INSTALADO, lido do disco e sem rede.
|
|
557
|
+
*
|
|
558
|
+
* A comparação é contra `.installed.json`, a cópia que o `add` deixa ao lado. Um sistema
|
|
559
|
+
* instalado antes desta etapa não a tem, e aí o comando DIZ o que falta em vez de tratar o
|
|
560
|
+
* documento inteiro como mudado - ver `readInstalledPair`.
|
|
561
|
+
*/
|
|
562
|
+
let edits = [];
|
|
563
|
+
let localDocument = null;
|
|
564
|
+
let localSaid = null;
|
|
565
|
+
{
|
|
566
|
+
const version = await installedVersion(root, slug);
|
|
567
|
+
/**
|
|
568
|
+
* UM ERRO INESPERADO AQUI É DITO, e não engolido. A primeira escrita caía em
|
|
569
|
+
* "not-installed" para qualquer exceção - um disco cheio, uma permissão, um link quebrado -
|
|
570
|
+
* e a saída ficava idêntica à de um repositório sem sistema instalado.
|
|
571
|
+
*/
|
|
572
|
+
const pair = version
|
|
573
|
+
? await readInstalledPair(root, slug, version).catch((error) => ({
|
|
574
|
+
kind: "unreadable",
|
|
575
|
+
where: `_synthesisui/ds/${slug}/v${version}`,
|
|
576
|
+
why: error instanceof Error ? error.message : String(error),
|
|
577
|
+
}))
|
|
578
|
+
: { kind: "not-installed" };
|
|
579
|
+
if (pair.kind === "pair") {
|
|
580
|
+
edits = localEdits(pair.installed, pair.local);
|
|
581
|
+
if (edits.length > 0)
|
|
582
|
+
localDocument = pair.local;
|
|
583
|
+
localSaid = sentLine(edits, slug);
|
|
584
|
+
}
|
|
585
|
+
else if (pair.kind === "unreadable") {
|
|
586
|
+
localSaid = `your local ${slug} could not be read, so nothing of it went up: ${pair.why}\n ${pair.where}`;
|
|
587
|
+
}
|
|
588
|
+
else if (pair.kind === "no-baseline") {
|
|
589
|
+
localSaid = `we cannot tell what changed in your local ${slug}: ${pair.why}`;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
554
592
|
const res = await fetch(`${base}/api/registry/ds/${slug}/census`, {
|
|
555
593
|
method: "POST",
|
|
556
594
|
headers: {
|
|
@@ -568,6 +606,17 @@ export async function remeasure(args) {
|
|
|
568
606
|
census: census.ledger
|
|
569
607
|
? { ...census, ledger: sampledForUpload(census.ledger) }
|
|
570
608
|
: census,
|
|
609
|
+
/**
|
|
610
|
+
* E O QUE O AGENTE DELE MUDOU NOS ARQUIVOS DO DESIGN SYSTEM - a outra metade do ciclo.
|
|
611
|
+
*
|
|
612
|
+
* O prompt que a plataforma monta termina mandando rodar este comando, e até aqui ele
|
|
613
|
+
* media só o CÓDIGO dele: o design system instalado aparecia apenas para descobrir quais
|
|
614
|
+
* slugs existem. O documento só sobe quando há diferença de verdade contra o que o `add`
|
|
615
|
+
* instalou - sem edição, este campo não existe e nada muda do lado de lá.
|
|
616
|
+
*/
|
|
617
|
+
...(edits.length > 0 && localDocument
|
|
618
|
+
? { document: localDocument, edits }
|
|
619
|
+
: {}),
|
|
571
620
|
}),
|
|
572
621
|
}).catch(() => null);
|
|
573
622
|
if (!res?.ok) {
|
|
@@ -580,6 +629,20 @@ export async function remeasure(args) {
|
|
|
580
629
|
console.log("");
|
|
581
630
|
console.log(section("Sent"));
|
|
582
631
|
console.log(body(`${out.written ?? 0} of ${out.total ?? 0} components written.`));
|
|
632
|
+
/**
|
|
633
|
+
* O QUE VEIO DOS ARQUIVOS DELE, DITO - e antes de qualquer outra nota, porque é a única parte
|
|
634
|
+
* desta saída que fala do trabalho que ELE acabou de fazer.
|
|
635
|
+
*
|
|
636
|
+
* Um "ok" mudo depois de um agente ter mexido em doze peças é pior que nenhuma saída: ele não
|
|
637
|
+
* tem como saber se o comando entendeu o trabalho, e roda de novo para conferir.
|
|
638
|
+
*/
|
|
639
|
+
if (localSaid)
|
|
640
|
+
console.log(body(localSaid));
|
|
641
|
+
/** A única frase no passado, e ela vem DEPOIS da resposta do servidor. */
|
|
642
|
+
if (out.hisEdits?.applied)
|
|
643
|
+
console.log(body(landedLine(out.hisEdits.applied, slug)));
|
|
644
|
+
if (out.hisEdits?.refused)
|
|
645
|
+
console.log(body(paint.strong(` ✕ your local changes were refused, and nothing of them was written: ${out.hisEdits.refused}`)));
|
|
583
646
|
for (const note of out.notes ?? [])
|
|
584
647
|
console.log(body(paint.faint(note)));
|
|
585
648
|
/**
|
|
@@ -662,6 +725,27 @@ export async function remeasure(args) {
|
|
|
662
725
|
...(args.cli ? { cli: args.cli } : {}),
|
|
663
726
|
readings: fingerprintReadings(census.components),
|
|
664
727
|
};
|
|
728
|
+
/**
|
|
729
|
+
* E O BASELINE PASSA A SER O QUE ESTÁ NO DISCO - a metade que fecha o ciclo.
|
|
730
|
+
*
|
|
731
|
+
* Sem esta linha, todo `sync` reenviaria a mesma alteração para sempre, e o documento na
|
|
732
|
+
* plataforma ganharia uma revisão nova a cada rodada sem nada ter mudado. Só depois de o
|
|
733
|
+
* servidor ter aceitado: uma recusa mantém o baseline velho, para a próxima rodada tentar de
|
|
734
|
+
* novo em vez de esquecer o que ele fez.
|
|
735
|
+
*/
|
|
736
|
+
/**
|
|
737
|
+
* A CONDIÇÃO É `applied`, e não "não recusou" - a diferença apaga o trabalho dele.
|
|
738
|
+
*
|
|
739
|
+
* Um servidor que responde 200 SEM o campo `hisEdits` é todo deploy anterior a esta etapa, e
|
|
740
|
+
* essa janela existe de verdade: o CLI é publicado antes de a plataforma subir. Com
|
|
741
|
+
* `!refused`, o CLI dava o baseline por assentado, o disco esquecia o que o agente fez, e a
|
|
742
|
+
* plataforma nunca tinha recebido. A alteração some dos dois lados.
|
|
743
|
+
*/
|
|
744
|
+
if (out.hisEdits?.applied && localDocument) {
|
|
745
|
+
const version = await installedVersion(root, slug);
|
|
746
|
+
if (version)
|
|
747
|
+
await settleBaseline(root, slug, version, localDocument).catch(() => { });
|
|
748
|
+
}
|
|
665
749
|
console.log(body(paint.faint(describeDelta(mark, await readSyncMark(root)))));
|
|
666
750
|
await writeSyncMark(root, mark);
|
|
667
751
|
/**
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, relative } from "node:path";
|
|
3
3
|
import { readProjectConfig, resolveRegistry } from "../config.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { inTheirTongue, projectTongue } from "../their-tongue.js";
|
|
4
|
+
import { installedSheetCss, RECIPE_HEADER, recipeRulesFor, } from "../recipe-css.js";
|
|
5
|
+
import { fetchDesignSystem, fetchTemplate } from "../registry.js";
|
|
6
|
+
import { inTheirTongue, projectTongue, tongueFromArtifacts, } from "../their-tongue.js";
|
|
7
7
|
import { keptLine, recordWritten, editedHere as theirEdits, } from "../written.js";
|
|
8
8
|
/**
|
|
9
|
+
* A INSTRUÇÃO SAI DE TODA PÁGINA, SEMPRE - `INV-GERAL-13`, 11/09.
|
|
10
|
+
*
|
|
11
|
+
* Esta filtragem era CONDICIONAL: ela rodava só quando a medição dizia que a página não precisava
|
|
12
|
+
* mais da folha, e no caso contrário o comentário ficava no arquivo dele mandando importar. Não há
|
|
13
|
+
* mais caso contrário - as regras que a página veste são copiadas para o `.css` ao lado dela
|
|
14
|
+
* (`recipe-css.ts`), e nada no arquivo aponta para nós.
|
|
15
|
+
*
|
|
9
16
|
* O QUE O ARQUIVO DIZ TAMBÉM É COBRANÇA - e ela é a metade que FICA no repositório dele.
|
|
10
17
|
*
|
|
11
18
|
* O DEFEITO, achado pela revisão de DX no fecho da etapa 11: o fecho no terminal parou de mandar
|
|
@@ -88,12 +95,28 @@ export async function template(slug, name, opts) {
|
|
|
88
95
|
return;
|
|
89
96
|
}
|
|
90
97
|
/**
|
|
91
|
-
* NENHUMA MATERIALIZAÇÃO VAZA VOCABULÁRIO INTERNO (INV-VOLTA-02) - a mesma porta do
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
98
|
+
* NENHUMA MATERIALIZAÇÃO VAZA VOCABULÁRIO INTERNO (INV-VOLTA-02) - a mesma porta do `component`,
|
|
99
|
+
* e agora também o mesmo CAMINHO DE LEITURA.
|
|
100
|
+
*
|
|
101
|
+
* SEM `add`, O SISTEMA VEM DO REGISTRY. Uma página trazida antes do install - e o próprio guard
|
|
102
|
+
* de edição deste comando já reconhece esse fluxo - não tinha pasta para ler, `projectTongue`
|
|
103
|
+
* respondia `null`, e o arquivo ia a disco com `var(--ds-*)` cru e as classes `.ds-*` sem uma
|
|
104
|
+
* regra sequer. Calado: o relatório da tradução só existe quando houve tradução.
|
|
105
|
+
*
|
|
106
|
+
* O `component` recebeu este conserto em 10/09 (`tongueFromArtifacts`) e o `template` não - "a
|
|
107
|
+
* mesma promessa, duas implementações, uma delas ausente" é literalmente o defeito que
|
|
108
|
+
* `INV-VOLTA-02` nomeia, e ele estava aqui.
|
|
109
|
+
*
|
|
110
|
+
* UMA IDA A MAIS À REDE, e só neste caminho: quem já instalou lê do disco como sempre.
|
|
95
111
|
*/
|
|
96
|
-
const
|
|
112
|
+
const installedTongue = await projectTongue(root, slug);
|
|
113
|
+
const fromRegistry = installedTongue
|
|
114
|
+
? null
|
|
115
|
+
: await fetchDesignSystem(base, slug, opts.version).catch(() => null);
|
|
116
|
+
const tongue = installedTongue ??
|
|
117
|
+
(fromRegistry
|
|
118
|
+
? await tongueFromArtifacts(root, fromRegistry.artifacts)
|
|
119
|
+
: null);
|
|
97
120
|
const speak = (code) => (tongue ? inTheirTongue(code, tongue) : null);
|
|
98
121
|
let named = 0;
|
|
99
122
|
let inlined = 0;
|
|
@@ -130,38 +153,55 @@ export async function template(slug, name, opts) {
|
|
|
130
153
|
content: translate(f.code),
|
|
131
154
|
});
|
|
132
155
|
/**
|
|
133
|
-
*
|
|
134
|
-
* `sheet-needed.ts`, a mesma porta que o `component` usa.
|
|
156
|
+
* AS REGRAS DE RECEITA VÊM JUNTO, no `.css` ao lado da página - `INV-GERAL-13`, 11/09.
|
|
135
157
|
*
|
|
136
|
-
* O
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* que renderiza igual sem os dois passava a pedi-los, e pedir cria exatamente a dependência que
|
|
140
|
-
* a plataforma promete não criar: a gente é referência, não dependência.
|
|
158
|
+
* O QUE MUDOU PARA O CLIENTE: a página renderiza sem nada nosso carregado no app dele. Ela veste
|
|
159
|
+
* `.ds-hero`, `.ds-nav` e as outras classes que o sistema declara, e essas regras passam a morar
|
|
160
|
+
* no arquivo ao lado dela - traduzidas para o vocabulário dele, como todo o resto.
|
|
141
161
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
162
|
+
* POR QUE A PÁGINA ERA O ÚLTIMO CASO. Ela é a única materialização que dependia da folha por
|
|
163
|
+
* CLASSE, e não por variável: a tradução reescreve `var(--ds-*)` e não tem o que fazer com
|
|
164
|
+
* `.ds-hero`, porque o corpo daquela regra nunca esteve no arquivo. Enquanto isso fosse verdade,
|
|
165
|
+
* este comando terminava mandando instalar o sistema e colar um `@import` - e foi essa instrução
|
|
166
|
+
* que abriu esta etapa.
|
|
145
167
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
168
|
+
* O CSS COPIADO PASSA PELA MESMA PORTA: `translate` é a tradução que todo byte deste comando
|
|
169
|
+
* atravessa, e um caminho que escreve CSS sem passá-la é o defeito que `INV-VOLTA-02` nomeia.
|
|
148
170
|
*/
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
171
|
+
const recipes = recipeRulesFor({
|
|
172
|
+
source: pieces.map((f) => f.content).join("\n"),
|
|
173
|
+
/**
|
|
174
|
+
* A FOLHA DE ONDE AS REGRAS SÃO COPIADAS - do disco quando ele instalou, do registry quando não.
|
|
175
|
+
*
|
|
176
|
+
* Sem as duas, `recipes.rules` é 0 e a página sai vestindo `.ds-*` que ninguém declara - com o
|
|
177
|
+
* cabeçalho dela afirmando que a folha ao lado escopa cada regra. Uma frase falsa dentro do
|
|
178
|
+
* arquivo dele é pior que uma instrução: o terminal rola, o arquivo fica.
|
|
179
|
+
*/
|
|
180
|
+
sheetCss: fromRegistry?.artifacts?.["tokens.css"] ??
|
|
181
|
+
(await installedSheetCss(root, slug)),
|
|
182
|
+
});
|
|
183
|
+
if (recipes.rules > 0) {
|
|
184
|
+
/**
|
|
185
|
+
* O ARQUIVO IRMÃO É O DESTINO, e ele já existe no alvo `next` - a página o importa desde que
|
|
186
|
+
* as media queries e o hambúrguer CSS-only passaram a viajar nele. Criar um terceiro arquivo
|
|
187
|
+
* daria à página dois CSS para importar e a ninguém uma razão.
|
|
188
|
+
*/
|
|
189
|
+
const sibling = pieces.find((p) => p.filename.endsWith(".css"));
|
|
190
|
+
const block = `${RECIPE_HEADER}\n${translate(recipes.css)}\n`;
|
|
191
|
+
if (sibling)
|
|
192
|
+
sibling.content = `${block}\n${sibling.content}`;
|
|
193
|
+
else
|
|
194
|
+
pieces.push({
|
|
195
|
+
rel: join(dirname(pageRel), pageFile.filename.replace(/\.tsx$/, ".css")),
|
|
196
|
+
filename: pageFile.filename.replace(/\.tsx$/, ".css"),
|
|
197
|
+
content: block,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
158
200
|
await mkdir(pageDir, { recursive: true });
|
|
159
201
|
/** OS BYTES QUE FORAM A DISCO, para o fingerprint lembrar EXATAMENTE o que escrevemos. */
|
|
160
202
|
const landed = [];
|
|
161
203
|
for (const piece of pieces) {
|
|
162
|
-
const content =
|
|
163
|
-
? piece.content
|
|
164
|
-
: withoutTheSheetInstruction(piece.content);
|
|
204
|
+
const content = withoutTheSheetInstruction(piece.content);
|
|
165
205
|
await writeFile(join(root, piece.rel), content, "utf8");
|
|
166
206
|
landed.push({ filename: piece.filename, content });
|
|
167
207
|
console.log(piece.rel === pageRel
|
|
@@ -180,35 +220,23 @@ export async function template(slug, name, opts) {
|
|
|
180
220
|
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` : ""}.`);
|
|
181
221
|
if (still.size > 0) {
|
|
182
222
|
const sample = [...still].sort().slice(0, 3).join(", ");
|
|
183
|
-
console.log(` ${still.size}
|
|
223
|
+
console.log(` ${still.size} value${still.size === 1 ? "" : "s"} the system declares no value for (${sample}${still.size > 3 ? ", …" : ""}) - ${still.size === 1 ? "that declaration is" : "those declarations are"} dropped by the browser. Please report this: the sheet we read is incomplete.`);
|
|
184
224
|
}
|
|
185
225
|
}
|
|
226
|
+
if (recipes.rules > 0)
|
|
227
|
+
console.log(` ${recipes.rules} rule${recipes.rules === 1 ? "" : "s"} for ${recipes.classes.slice(0, 3).join(", ")}${recipes.classes.length > 3 ? `, +${recipes.classes.length - 3}` : ""} came along in the stylesheet next to it - nothing to import.`);
|
|
186
228
|
console.log("");
|
|
187
229
|
console.log("Next steps:");
|
|
188
230
|
console.log(` • use it in a route, e.g. ${join(config.pagesDir, "page.tsx")}:`);
|
|
189
231
|
console.log(` import Page from "@/${defaultDir.replace(/\\/g, "/")}/${pageFile.filename.replace(/\.tsx$/, "")}";`);
|
|
190
|
-
|
|
191
|
-
/** E ELE DIZ O QUE PEDE A FOLHA - um setup cobrado sem motivo dito ensina a ignorar o próximo. */
|
|
192
|
-
if (need)
|
|
193
|
-
console.log(` • what still needs the sheet here: ${[...need.recipeClasses, ...need.classes, ...need.variables].slice(0, 3).join(", ")}`);
|
|
194
|
-
console.log(` • ensure the DS is installed: synthesisui add ${slug} (provides tokens.css)`);
|
|
195
|
-
console.log(` • @import "_synthesisui/ds/${slug}/tokens.css" in your global CSS`);
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
console.log(` • nothing to install: every value in this page is a name YOUR code declares, so it renders without our stylesheet`);
|
|
199
|
-
}
|
|
232
|
+
console.log(` • nothing to install: this page and its stylesheet stand on their own`);
|
|
200
233
|
console.log(" • refine the file: wire real data, split into components, swap placeholders");
|
|
201
234
|
/**
|
|
202
|
-
* E A LINHA DO ESCOPO
|
|
235
|
+
* E A LINHA DO ESCOPO NÃO SAI MAIS - `INV-GERAL-13`, 11/09.
|
|
203
236
|
*
|
|
204
|
-
* Ela mandava *"keep the data-ds wrapper and the ds-* classes (stays on-system)"
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* frases que não podem ser verdadeiras ao mesmo tempo -, e a medição já responde qual das duas é:
|
|
209
|
-
* chegar aqui com `chargesTheSheet` falso significa zero variável nossa e zero classe nossa no
|
|
210
|
-
* que acabou de ser escrito.
|
|
237
|
+
* Ela mandava *"keep the data-ds wrapper and the ds-* classes (stays on-system)"*. O `data-ds`
|
|
238
|
+
* existia para a NOSSA folha aplicar dentro dele, e o app dele não a carrega: pedir que ele
|
|
239
|
+
* mantenha um atributo nosso na árvore dele é a mesma dependência com outro nome. As classes
|
|
240
|
+
* continuam valendo, e agora elas são declaradas pelo arquivo ao lado da própria página.
|
|
211
241
|
*/
|
|
212
|
-
if (chargesTheSheet)
|
|
213
|
-
console.log(` • keep the data-ds="${slug}" wrapper and the ds-* / layout classes (stays on-system)`);
|
|
214
242
|
}
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -7,9 +7,10 @@ import { generateComponentFiles } from "../component-codegen.js";
|
|
|
7
7
|
import { readProjectConfig, readToken, resolveRegistry } from "../config.js";
|
|
8
8
|
import { unsentEvents } from "../doctor/ledger.js";
|
|
9
9
|
import { diffLocalDocuments, localChangelogMarkdown, } from "../document-diff.js";
|
|
10
|
+
import { detectAppDirs } from "../global-sheet.js";
|
|
10
11
|
import { installedBehind, MATERIALISER_SINCE } from "../install-marks.js";
|
|
11
12
|
import { body, section, snippet } from "../output.js";
|
|
12
|
-
import {
|
|
13
|
+
import { reactMajorOf, readInstalledConvention, readInstalledScheme, theirThemeVars, } from "../project-facts.js";
|
|
13
14
|
import { fetchChangelog, fetchComponent, fetchDesignSystem, RegistryError, } from "../registry.js";
|
|
14
15
|
import { flavourResolver } from "../styles-flavour.js";
|
|
15
16
|
import { projectTongue } from "../their-tongue.js";
|
|
@@ -419,8 +420,9 @@ export async function upgrade(asked, opts) {
|
|
|
419
420
|
* língua do repositório. Resolvido uma vez para a corrida inteira, como o sabor.
|
|
420
421
|
*/
|
|
421
422
|
const tongue = await projectTongue(root, slug);
|
|
422
|
-
/**
|
|
423
|
-
|
|
423
|
+
/** O `@theme` DELE é o MESMO para a corrida inteira - ver `theirThemeVars`. */
|
|
424
|
+
/** As pastas de app - a resposta é a INTERSEÇÃO delas. Ver `theirThemeVars`. */
|
|
425
|
+
const themeVars = await theirThemeVars(root, await detectAppDirs(root, config.pagesDir));
|
|
424
426
|
for (const entry of entries) {
|
|
425
427
|
const tsxPath = join(componentsRoot, entry, `${entry}.tsx`);
|
|
426
428
|
let head = "";
|
package/dist/commands/use.js
CHANGED
|
@@ -90,10 +90,12 @@ export async function use(slug, intent, opts) {
|
|
|
90
90
|
// The styling contract differs by target: Next projects in this product use
|
|
91
91
|
// Tailwind v4 backed by the DS; the "general" target is framework-agnostic CSS.
|
|
92
92
|
const stylingRule = config.target === "general"
|
|
93
|
-
? `- Style with the design system only:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
? `- Style with the design system only: bring its recipes in as code ` +
|
|
94
|
+
`(\`npx synthesisui component ${slug} <name>\`) and write the names THIS project declares - ` +
|
|
95
|
+
`\`find_token\` answers with the exact one. Never use raw hex/px outside the system's scale.`
|
|
96
|
+
: `- Style with the design system only: bring its recipes in as code ` +
|
|
97
|
+
`(\`npx synthesisui component ${slug} <name>\`) and use this project's own Tailwind utilities ` +
|
|
98
|
+
`(${utilities}…). Never use raw hex/px outside the system's scale.`;
|
|
97
99
|
const task = intent.trim() || "build the UI I describe next";
|
|
98
100
|
const prompt = [
|
|
99
101
|
`Use the "${name}" design system (slug: ${slug}, v${version}) to: ${task}`,
|
|
@@ -106,11 +108,8 @@ export async function use(slug, intent, opts) {
|
|
|
106
108
|
`\`${config.componentsDir}/\` and \`${config.pagesDir}/\`). If it does, modify only what's ` +
|
|
107
109
|
`needed and keep the rest of the file intact and on-system. If it doesn't, build it new - ` +
|
|
108
110
|
`components in \`${config.componentsDir}/\`, pages in \`${config.pagesDir}/\`.`,
|
|
109
|
-
`- Scope the markup with \`data-ds="${slug}"\` (or rely on it at the app root).`,
|
|
110
111
|
stylingRule,
|
|
111
|
-
|
|
112
|
-
? '- Make sure `tokens.css` + `theme.css` are imported in the global CSS (see the GUIDE\'s "How to apply").'
|
|
113
|
-
: '- Make sure `tokens.css` is imported in the global CSS (see the GUIDE\'s "How to apply").',
|
|
112
|
+
"- Nothing of the platform's is imported into this project: a component brought in by `component` carries everything it needs.",
|
|
114
113
|
"- Implement the behavior yourself (open/close, focus, routing) - the system ships the looks, not the JS.",
|
|
115
114
|
"",
|
|
116
115
|
"Composition (make it look composed, not just correct):",
|