synthesisui 0.16.441 → 0.16.443
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/doctor/transcribe.js +188 -2
- package/dist/doctor/value-ledger.js +55 -1
- package/package.json +1 -1
|
@@ -64,6 +64,17 @@ const COLOR_PROPERTY = {
|
|
|
64
64
|
text: "color",
|
|
65
65
|
border: "borderColor",
|
|
66
66
|
ring: "outlineColor",
|
|
67
|
+
/**
|
|
68
|
+
* `outline-brand-blue` - a v4 escreve o contorno com o nome dela própria, e não só com `ring`.
|
|
69
|
+
*
|
|
70
|
+
* Medido no `codelevel` em 20/09: o `CommandBlock` usa `focus-visible:outline-brand-blue`, e
|
|
71
|
+
* `brand-blue` é a cor de AÇÃO que ele escolheu no import. Sem esta linha o leitor não sabia de
|
|
72
|
+
* que propriedade se tratava, e a nota dele caía por ele usar o próprio sistema.
|
|
73
|
+
*
|
|
74
|
+
* Um sufixo que não resolve para cor nenhuma - `outline-2`, que é largura - continua não lido,
|
|
75
|
+
* porque o leitor de cor devolve `null` e nenhum valor errado entra no lugar.
|
|
76
|
+
*/
|
|
77
|
+
outline: "outlineColor",
|
|
67
78
|
fill: "fill",
|
|
68
79
|
stroke: "stroke",
|
|
69
80
|
decoration: "textDecorationColor",
|
|
@@ -713,7 +724,69 @@ export function readUtility(raw, declared) {
|
|
|
713
724
|
};
|
|
714
725
|
}
|
|
715
726
|
const read = readUtilityCore(utility, declared);
|
|
716
|
-
|
|
727
|
+
if (read)
|
|
728
|
+
return withAlpha(read, utility.split("/")[1]);
|
|
729
|
+
return readNegative(utility, declared);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* O SINAL DE MENOS NÃO APAGA O DEGRAU - `-top-1` é o `top-1` dele, para o outro lado.
|
|
733
|
+
*
|
|
734
|
+
* Medido no `codelevel` em 20/09: `-top-1` e `-right-1` no `TierBadge` e `-top-5` no
|
|
735
|
+
* `ConfettiBurst` caíam em não lido, enquanto `top-1` seria lido. É o mesmo valor da escala dele,
|
|
736
|
+
* na direção oposta - e sobrepor ou pendurar um elemento é justamente o caso em que a distância é
|
|
737
|
+
* negativa por desenho.
|
|
738
|
+
*
|
|
739
|
+
* E ELE NÃO CRIA DEGRAU NOVO: o valor lido é o degrau que ele já tem, com o sinal. Tratar `-1`
|
|
740
|
+
* como um degrau próprio dobraria a escala dele e faria o sistema propor vocabulário que ele nunca
|
|
741
|
+
* escreveria.
|
|
742
|
+
*
|
|
743
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
744
|
+
* E POR QUE O `gap` FICA DE FORA, mesmo com `-space-x-2` sendo cinco dos oito casos dele.
|
|
745
|
+
*
|
|
746
|
+
* `space-x` é lido como `columnGap` - uma aproximação que o próprio comentário da tabela assume,
|
|
747
|
+
* e que é exata onde o pai arranja. Um `columnGap` NEGATIVO não é CSS válido: o que
|
|
748
|
+
* `-space-x-2` faz é margem negativa nos filhos, que é como a pilha de avatares dele se
|
|
749
|
+
* sobrepõe. Emitir `columnGap: -0.5rem` seria errado em silêncio, e a regra deste arquivo é que
|
|
750
|
+
* isso é pior que não lido.
|
|
751
|
+
*
|
|
752
|
+
* Então os cinco `-space-x-*` do `Avatar` continuam não lidos, agora por um motivo que se pode
|
|
753
|
+
* escrever - e resolvê-los é modelar margem negativa, não remendar o sinal.
|
|
754
|
+
*/
|
|
755
|
+
const NAO_ACEITA_NEGATIVO = new Set([
|
|
756
|
+
"gap",
|
|
757
|
+
"columnGap",
|
|
758
|
+
"rowGap",
|
|
759
|
+
"width",
|
|
760
|
+
"height",
|
|
761
|
+
"padding",
|
|
762
|
+
"paddingInline",
|
|
763
|
+
"paddingBlock",
|
|
764
|
+
"paddingTop",
|
|
765
|
+
"paddingRight",
|
|
766
|
+
"paddingBottom",
|
|
767
|
+
"paddingLeft",
|
|
768
|
+
]);
|
|
769
|
+
function readNegative(utility, declared) {
|
|
770
|
+
if (!utility.startsWith("-"))
|
|
771
|
+
return null;
|
|
772
|
+
const positivo = readUtilityCore(utility.slice(1), declared);
|
|
773
|
+
if (!positivo)
|
|
774
|
+
return null;
|
|
775
|
+
if (NAO_ACEITA_NEGATIVO.has(positivo.property))
|
|
776
|
+
return null;
|
|
777
|
+
/** Só um comprimento se nega. Uma palavra-chave com menos na frente não é valor nenhum. */
|
|
778
|
+
const m = /^(-?)([\d.]+)([a-z%]*)$/.exec(positivo.value.trim());
|
|
779
|
+
if (!m || !m[3])
|
|
780
|
+
return null;
|
|
781
|
+
const n = Number(m[2]);
|
|
782
|
+
if (!Number.isFinite(n) || n === 0)
|
|
783
|
+
return null;
|
|
784
|
+
return {
|
|
785
|
+
...positivo,
|
|
786
|
+
value: `${m[1] ? "" : "-"}${m[2]}${m[3]}`,
|
|
787
|
+
/** O token dele some: `-1` não é o `--spacing-1` dele, é o negativo dele. */
|
|
788
|
+
...(positivo.token ? { token: undefined } : {}),
|
|
789
|
+
};
|
|
717
790
|
}
|
|
718
791
|
function readUtilityCore(utility, declared) {
|
|
719
792
|
/**
|
|
@@ -791,6 +864,68 @@ function readUtilityCore(utility, declared) {
|
|
|
791
864
|
* nome do Tailwind é o valor CSS verbatim em toda a escala publicada. O gatilho do
|
|
792
865
|
* MetricCard real diz "isto tem explicação" com ele (12/08).
|
|
793
866
|
*/
|
|
867
|
+
/**
|
|
868
|
+
* `will-change-transform` - DICA PARA O NAVEGADOR, e ela precisa ser LIDA para poder ser
|
|
869
|
+
* classificada como arranjo.
|
|
870
|
+
*
|
|
871
|
+
* Medido no `codelevel` em 20/09: `Aurora` e `Orb` a escrevem, e ela caía em valor não lido.
|
|
872
|
+
* Não pinta nada - diz ao compositor que a camada vai se mover, para promovê-la antes. Quem a
|
|
873
|
+
* tira do denominador é `STRUCTURAL_PROPERTIES`, pela propriedade; aqui ela só deixa de ser
|
|
874
|
+
* invisível.
|
|
875
|
+
*/
|
|
876
|
+
/**
|
|
877
|
+
* AS QUATRO PROPRIEDADES QUE FALTAVAM NA TABELA - E05 da jornada `a-escala-e-do-usuario`.
|
|
878
|
+
*
|
|
879
|
+
* Medidas no `codelevel` em 20/09, dez dos valores que a conta dava como não lidos. Nenhuma
|
|
880
|
+
* delas é ambígua: `outline-2` é uma largura, `brightness-95` é um filtro de 95%. O leitor
|
|
881
|
+
* simplesmente não tinha a propriedade.
|
|
882
|
+
*
|
|
883
|
+
* Button active:brightness-95 filtro
|
|
884
|
+
* CommandBlock outline-2 · outline-offset-2 contorno: largura e distância
|
|
885
|
+
* Card·PillNav backdrop-saturate-140 filtro de fundo
|
|
886
|
+
* QuestItem line-through · underline-offset-4 · decoration-2
|
|
887
|
+
*
|
|
888
|
+
* A ORDEM IMPORTA: `outline` e `decoration` já são prefixos de COR, e a leitura de cor roda
|
|
889
|
+
* antes. `outline-brand-blue` continua indo por lá; só o que ela recusa - um número - chega
|
|
890
|
+
* aqui. Inverter isso leria a cor dele como largura, que é o errado-em-silêncio de sempre.
|
|
891
|
+
*/
|
|
892
|
+
const contorno = /^outline-(\d+)$/.exec(core);
|
|
893
|
+
if (contorno)
|
|
894
|
+
return { property: "outlineWidth", value: `${contorno[1]}px` };
|
|
895
|
+
const contornoDist = /^outline-offset-(\d+)$/.exec(core);
|
|
896
|
+
if (contornoDist)
|
|
897
|
+
return { property: "outlineOffset", value: `${contornoDist[1]}px` };
|
|
898
|
+
const brilho = /^brightness-(\d+)$/.exec(core);
|
|
899
|
+
if (brilho)
|
|
900
|
+
return {
|
|
901
|
+
property: "filter",
|
|
902
|
+
value: `brightness(${Number(brilho[1]) / 100})`,
|
|
903
|
+
};
|
|
904
|
+
const satFundo = /^backdrop-saturate-(\d+)$/.exec(core);
|
|
905
|
+
if (satFundo)
|
|
906
|
+
return {
|
|
907
|
+
property: "backdropFilter",
|
|
908
|
+
value: `saturate(${Number(satFundo[1]) / 100})`,
|
|
909
|
+
};
|
|
910
|
+
/** A grafia entre colchetes carrega a unidade dele, e ela viaja como está. */
|
|
911
|
+
const satFundoCru = /^backdrop-saturate-\[([\d.]+%?)\]$/.exec(core);
|
|
912
|
+
if (satFundoCru)
|
|
913
|
+
return { property: "backdropFilter", value: `saturate(${satFundoCru[1]})` };
|
|
914
|
+
if (core === "line-through" || core === "underline" || core === "overline")
|
|
915
|
+
return { property: "textDecorationLine", value: core };
|
|
916
|
+
const sublinhado = /^underline-offset-(\d+)$/.exec(core);
|
|
917
|
+
if (sublinhado)
|
|
918
|
+
return { property: "textUnderlineOffset", value: `${sublinhado[1]}px` };
|
|
919
|
+
const espessura = /^decoration-(\d+)$/.exec(core);
|
|
920
|
+
if (espessura)
|
|
921
|
+
return {
|
|
922
|
+
property: "textDecorationThickness",
|
|
923
|
+
value: `${espessura[1]}px`,
|
|
924
|
+
};
|
|
925
|
+
const willChange = /^will-change-([a-z-]+)$/.exec(core);
|
|
926
|
+
if (willChange) {
|
|
927
|
+
return { property: "willChange", value: willChange[1] };
|
|
928
|
+
}
|
|
794
929
|
const cursor = /^cursor-([a-z-]+)$/.exec(core);
|
|
795
930
|
if (cursor)
|
|
796
931
|
return { property: "cursor", value: cursor[1] };
|
|
@@ -1435,6 +1570,17 @@ const BRACKET_PROPERTY = {
|
|
|
1435
1570
|
z: "zIndex",
|
|
1436
1571
|
grid: "gridTemplateColumns",
|
|
1437
1572
|
aspect: "aspectRatio",
|
|
1573
|
+
/**
|
|
1574
|
+
* `ease-[var(--ease-emphasis)]` - o caminho arbitrário já resolvia o `var()`; faltava dizer a
|
|
1575
|
+
* qual propriedade o `ease` pertence, e sem isso a leitura morria no último passo.
|
|
1576
|
+
*
|
|
1577
|
+
* Medido no `codelevel` em 20/09: `Card`, `Progress` e `Toast` escrevem essa classe, e
|
|
1578
|
+
* `--ease-emphasis` é o `motion.easings.emphasis` DELE, publicado na v1. Três dos 35 valores
|
|
1579
|
+
* "não lidos" eram ele apontando para o próprio vocabulário.
|
|
1580
|
+
*
|
|
1581
|
+
* O `ease-out` nomeado continua sendo lido pela tabela `EASING`, antes daqui.
|
|
1582
|
+
*/
|
|
1583
|
+
ease: "transitionTimingFunction",
|
|
1438
1584
|
};
|
|
1439
1585
|
/**
|
|
1440
1586
|
* What is inside the brackets, resolved.
|
|
@@ -1665,10 +1811,50 @@ const GRADIENT_DIRECTION = {
|
|
|
1665
1811
|
};
|
|
1666
1812
|
/** A colour stop's value: their token first, Tailwind's table second, a literal last. */
|
|
1667
1813
|
function stopValue(raw, declared) {
|
|
1814
|
+
/**
|
|
1815
|
+
* A PARADA COM ALFA - `from-white/85`, e o resto do leitor já sabia ler isso.
|
|
1816
|
+
*
|
|
1817
|
+
* Medido no `codelevel` em 20/09: o `Card` escreve `bg-gradient-to-b from-white/85
|
|
1818
|
+
* to-white/60`, com as três cores declaradas no CSS dele, e o gradiente inteiro caía em
|
|
1819
|
+
* `unreadable`. O `SkillNode`, que escreve o mesmo sem alfa, compunha perfeitamente -
|
|
1820
|
+
* `linear-gradient(to bottom right, {color.white}, {color.amber.50})`. A diferença era a barra.
|
|
1821
|
+
*
|
|
1822
|
+
* `readUtility` já resolve alfa em toda cor, por `withAlpha`. Esta função era a única que via a
|
|
1823
|
+
* barra e devolvia `null` - e um gradiente com UMA parada ilegível não é meio lido: o
|
|
1824
|
+
* compositor descarta o gradiente inteiro, então a barra apagava a decisão toda.
|
|
1825
|
+
*/
|
|
1826
|
+
const comAlfa = /^(.+)\/(\d{1,3})$/.exec(raw);
|
|
1827
|
+
if (comAlfa) {
|
|
1828
|
+
const base = stopValue(comAlfa[1], declared);
|
|
1829
|
+
if (!base)
|
|
1830
|
+
return null;
|
|
1831
|
+
const pct = Number(comAlfa[2]);
|
|
1832
|
+
if (!Number.isFinite(pct) || pct > 100)
|
|
1833
|
+
return null;
|
|
1834
|
+
/** A grafia do CSS moderno: `color-mix` não, `/ <alpha>` dentro do próprio valor. */
|
|
1835
|
+
return `color-mix(in oklab, ${base} ${pct}%, transparent)`;
|
|
1836
|
+
}
|
|
1668
1837
|
if (declared.has(`--color-${raw}`))
|
|
1669
1838
|
return refFor(raw);
|
|
1670
1839
|
if (TAILWIND_COLOR[raw])
|
|
1671
1840
|
return TAILWIND_COLOR[raw];
|
|
1841
|
+
/**
|
|
1842
|
+
* A PALETA DO FRAMEWORK TAMBÉM PINTA UMA PARADA - e o caminho normal de cor já a consulta.
|
|
1843
|
+
*
|
|
1844
|
+
* Medido no `codelevel` em 20/09, contra o censo de produção: o `SkillNode` escreve
|
|
1845
|
+
* `bg-gradient-to-br from-white to-amber-50`, e o gradiente inteiro era descartado porque
|
|
1846
|
+
* `amber-50` não resolvia aqui. Ninguém declara `--color-amber-50` no código dele: é a paleta
|
|
1847
|
+
* padrão do Tailwind, que `frameworkDeclaration` conhece e esta função não consultava.
|
|
1848
|
+
*
|
|
1849
|
+
* A assimetria era a falha: `bg-amber-50` sozinho era lido, e `to-amber-50` não. Uma parada
|
|
1850
|
+
* ilegível derruba o gradiente inteiro, então a cor da paleta apagava a decisão toda.
|
|
1851
|
+
*
|
|
1852
|
+
* O valor vem com o carimbo de framework do outro lado; aqui só o valor interessa, porque uma
|
|
1853
|
+
* parada é uma string dentro do `linear-gradient`.
|
|
1854
|
+
*/
|
|
1855
|
+
const daPaleta = frameworkDeclaration("color", raw);
|
|
1856
|
+
if (daPaleta)
|
|
1857
|
+
return daPaleta.value;
|
|
1672
1858
|
if (/^#[0-9a-fA-F]{3,8}$/.test(raw) ||
|
|
1673
1859
|
raw === "transparent" ||
|
|
1674
1860
|
raw === "white" ||
|
|
@@ -1689,7 +1875,7 @@ function stopValue(raw, declared) {
|
|
|
1689
1875
|
* prefix, so stops only count when a `bg-gradient-to-*` sits in the SAME class list -
|
|
1690
1876
|
* and a direction whose stops do not resolve is reported, never half-built.
|
|
1691
1877
|
*/
|
|
1692
|
-
function composeGradient(utilities, declared) {
|
|
1878
|
+
export function composeGradient(utilities, declared) {
|
|
1693
1879
|
const dir = utilities.find((u) => GRADIENT_DIRECTION[u.replace(/^bg-gradient-/, "")] &&
|
|
1694
1880
|
u.startsWith("bg-gradient-"));
|
|
1695
1881
|
if (!dir)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseClass, readUtility } from "./transcribe.js";
|
|
1
|
+
import { composeGradient, parseClass, readUtility } from "./transcribe.js";
|
|
2
2
|
/**
|
|
3
3
|
* AS PROPRIEDADES QUE SÃO ARRANJO - a definição de "estrutura", por propriedade resolvida.
|
|
4
4
|
*
|
|
@@ -50,6 +50,15 @@ const STRUCTURAL_PROPERTIES = new Set([
|
|
|
50
50
|
"isolation",
|
|
51
51
|
"textOverflow",
|
|
52
52
|
"borderCollapse",
|
|
53
|
+
/**
|
|
54
|
+
* `will-change` É DICA PARA O NAVEGADOR, nunca decisão de design - medido no `codelevel` em
|
|
55
|
+
* 20/09, onde `will-change-transform` no `Aurora` e no `Orb` contava como valor perdido.
|
|
56
|
+
*
|
|
57
|
+
* Ela não pinta nada: diz ao compositor do navegador que aquela camada vai se mover, para ele
|
|
58
|
+
* promovê-la antes. Trocá-la muda desempenho, não aparência - que é exatamente a linha que
|
|
59
|
+
* separa este conjunto do resto.
|
|
60
|
+
*/
|
|
61
|
+
"willChange",
|
|
53
62
|
]);
|
|
54
63
|
/**
|
|
55
64
|
* TOKENS DE ARRANJO QUE O RESOLVEDOR NÃO DEVOLVE COMO DECLARAÇÃO - a metade utilitária da mesma
|
|
@@ -121,6 +130,14 @@ const ARRANJO_SEM_VALOR = [
|
|
|
121
130
|
/^order-(\d+|first|last|none)$/,
|
|
122
131
|
/** Margem `auto` é centralização - a única margem cujo valor não sai de escala nenhuma. */
|
|
123
132
|
/^-?m[xytblrse]?-auto$/,
|
|
133
|
+
/**
|
|
134
|
+
* O GRUPO NOMEADO É O MESMO GRUPO - `group/tt`, e `group` já estava em `STRUCTURAL_TOKENS`.
|
|
135
|
+
*
|
|
136
|
+
* A v4 deixa nomear o grupo para que um filho alcance o ancestral certo quando há dois
|
|
137
|
+
* aninhados; o `Tooltip` dele usa `group/tt` por isso. É mecanismo de seletor, não aparência -
|
|
138
|
+
* e o conjunto exato não pegava porque a barra e o nome vêm colados.
|
|
139
|
+
*/
|
|
140
|
+
/^(group|peer)\/[A-Za-z0-9_-]+$/,
|
|
124
141
|
];
|
|
125
142
|
/** `mx-auto` e `col-span-6` nomeiam arranjo; `gap-6` nomeia uma escolha de escala. */
|
|
126
143
|
export function arranjoSemValor(utility) {
|
|
@@ -177,8 +194,45 @@ defined) {
|
|
|
177
194
|
answered: 0,
|
|
178
195
|
unknown: 0,
|
|
179
196
|
};
|
|
197
|
+
/**
|
|
198
|
+
* O GRADIENTE É UMA DECISÃO EM TRÊS CLASSES, E A CONTA VIA TRÊS PERDAS.
|
|
199
|
+
*
|
|
200
|
+
* Medido no `codelevel` em 20/09: o `SkillNode` escreve `bg-gradient-to-br from-white
|
|
201
|
+
* to-amber-50`, e o transcritor compõe isso perfeitamente -
|
|
202
|
+
* `linear-gradient(to bottom right, {color.white}, {color.amber.50})`. A receita dele tem o
|
|
203
|
+
* gradiente. E esta conta, que olha uma classe de cada vez, chamava as três de não lidas.
|
|
204
|
+
*
|
|
205
|
+
* O leitor entendeu e o contador não: dez dos 35 valores "não lidos" dele eram isso. Um número
|
|
206
|
+
* que contradiz a receita ao lado dele é o defeito que este arquivo mais evita.
|
|
207
|
+
*
|
|
208
|
+
* A composição roda por GRUPO DE MODIFICADOR, igual ao `transcribe` - é o que as três partes de
|
|
209
|
+
* um gradiente têm em comum. E o guarda dele continua de pé: uma parada sem direção no MESMO
|
|
210
|
+
* grupo não compõe, porque `slide-in-from-bottom-2` usa o mesmo prefixo `from-`. As paradas de
|
|
211
|
+
* dark do `Card`, que moram numa camada sem a direção, seguem não lidas - e é verdade que
|
|
212
|
+
* seguem: o gradiente escuro dele não está sendo lido.
|
|
213
|
+
*/
|
|
214
|
+
const grupos = new Map();
|
|
215
|
+
for (const cls of tokens) {
|
|
216
|
+
const { modifiers, utility } = parseClass(cls);
|
|
217
|
+
const chave = modifiers.join(":");
|
|
218
|
+
grupos.set(chave, [...(grupos.get(chave) ?? []), utility]);
|
|
219
|
+
}
|
|
220
|
+
const compostas = new Set();
|
|
221
|
+
for (const [chave, utilidades] of grupos) {
|
|
222
|
+
const g = composeGradient(utilidades, declared);
|
|
223
|
+
/** Só o que COMPÔS conta: um gradiente quebrado continua sendo perda, e diz qual peça. */
|
|
224
|
+
if (!g.value)
|
|
225
|
+
continue;
|
|
226
|
+
const prefixo = chave ? `${chave}:` : "";
|
|
227
|
+
for (const u of g.consumed)
|
|
228
|
+
compostas.add(`${prefixo}${u}`);
|
|
229
|
+
}
|
|
180
230
|
for (const cls of tokens) {
|
|
181
231
|
account.seen += 1;
|
|
232
|
+
if (compostas.has(cls)) {
|
|
233
|
+
account.interpreted += 1;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
182
236
|
account[destinationOf(cls, declared, answered, defined)] += 1;
|
|
183
237
|
}
|
|
184
238
|
return account;
|
package/package.json
CHANGED