synthesisui 0.16.227 → 0.16.231
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/absorb-plan.js +57 -5
- package/dist/commands/absorb.js +5 -6
- package/dist/commands/doctor.js +130 -34
- package/dist/commands/hook.js +3 -3
- package/dist/commands/mcp.js +3 -3
- package/dist/config.js +13 -6
- package/dist/doctor/apply-fix.js +40 -5
- package/dist/doctor/scan.js +62 -4
- package/dist/doctor/their-names.js +154 -0
- package/dist/doctor/tokens.js +18 -4
- package/dist/install-marks.js +28 -1
- package/dist/measured-scope.js +3 -1
- package/dist/skill-adapt.js +155 -70
- package/package.json +1 -1
package/dist/doctor/scan.js
CHANGED
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
* takes eight seconds and needs a build step is a diagnosis nobody runs.
|
|
11
11
|
*/
|
|
12
12
|
import { normalizeValue, tokenMatch } from "./tokens.js";
|
|
13
|
+
/**
|
|
14
|
+
* O NOME QUE SE ESCREVE NO ARQUIVO DELE - e existe uma função só para isto por um motivo.
|
|
15
|
+
*
|
|
16
|
+
* Seis lugares decidem o que a pessoa vê ou o que o `--fix` grava: o relatório, o plano, o hook, o
|
|
17
|
+
* MCP, a aplicação e a contagem. Deixar cada um lembrar de preferir `theirToken` é o padrão do
|
|
18
|
+
* argumento opcional que se esquece - e o sintoma seria o pior possível: o comando aconselhando um
|
|
19
|
+
* nome e o hook aconselhando outro, sobre o mesmo arquivo.
|
|
20
|
+
*/
|
|
21
|
+
export const nameToWrite = (f) => f.theirToken ?? f.token;
|
|
13
22
|
/**
|
|
14
23
|
* `next/og` renders JSX to a PNG on the server. There is no document, so there
|
|
15
24
|
* is no `var(--ds-*)` to read: every colour in such a file MUST be a literal.
|
|
@@ -54,9 +63,35 @@ const OPEN = `["']?`;
|
|
|
54
63
|
/** `rounded-[14px]`, `border-radius: 14px`, `borderRadius: "14px"`. Zero and
|
|
55
64
|
* full pills are idiom, not drift - nobody tokenizes `0` or `9999px`. */
|
|
56
65
|
const RADIUS = new RegExp(`(?:border-?[Rr]adius\\s*:\\s*${OPEN}|rounded(?:-[a-z]+)?-\\[)(-?\\d*\\.?\\d+)(px|rem|em)`, "g");
|
|
57
|
-
/**
|
|
58
|
-
*
|
|
59
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Arbitrary spacing: `p-[18px]`, `gap-[7px]`, `margin: 18px`, `gap: "18px"`.
|
|
68
|
+
* The JSX side also writes `paddingLeft`, `marginTop` and friends.
|
|
69
|
+
*
|
|
70
|
+
* `em` ENTROU EM 13/08, e a falta dele era uma palavra: o padrão do RAIO logo acima já aceitava as
|
|
71
|
+
* três unidades e o do espaçamento aceitava duas. Não era doutrina, era assimetria - e o custo dela é
|
|
72
|
+
* o pior tipo, porque um valor que a varredura não vê não aparece nem como lacuna.
|
|
73
|
+
*
|
|
74
|
+
* Medido no repositório real, o que estava invisível:
|
|
75
|
+
*
|
|
76
|
+
* 933 espaçamentos em `em` 300×0.5em · 276×1em · 116×0.25em
|
|
77
|
+
* 144 raios em `em` lidos, mas nunca nomeados (ver `normalizeValue`)
|
|
78
|
+
* 325 arquivos
|
|
79
|
+
*
|
|
80
|
+
* O dono achou pelo caminho que a gente não quer que ele precise usar (13/08): a skill abriu o
|
|
81
|
+
* `.scss` por conta própria e listou quatro `em` que o comando tinha acabado de chamar de limpo -
|
|
82
|
+
* *"não chegou nem a entrar no css, acho isso errado"*.
|
|
83
|
+
*
|
|
84
|
+
* E O KEBAB VEIO NA MESMA PUXADA, escondido atrás do primeiro. O sufixo aceito era só o camelCase
|
|
85
|
+
* do JSX (`paddingLeft`), então `padding-right: 1em` - a forma que TODO css escreve - não casava com
|
|
86
|
+
* nada. Foram os quatro `em` daquele mesmo arquivo que denunciaram: com `em` já no padrão, um
|
|
87
|
+
* continuou aparecendo e três não.
|
|
88
|
+
*
|
|
89
|
+
* 1175 `padding-*`/`margin-*` em kebab, em 335 arquivos do repositório real
|
|
90
|
+
*
|
|
91
|
+
* Duas gramáticas para a mesma propriedade é o tipo de coisa que só aparece quando alguém aponta
|
|
92
|
+
* para um arquivo e conta na mão.
|
|
93
|
+
*/
|
|
94
|
+
const SPACING = new RegExp(`(?:\\b[pmg](?:[trblxy])?-\\[|gap-\\[|(?:padding|margin|gap)(?:[A-Z][a-z]+|(?:-[a-z]+)+)?\\s*:\\s*${OPEN})(-?\\d*\\.?\\d+)(px|rem|em)`, "g");
|
|
60
95
|
/** A font stack written by hand rather than taken from the type scale. */
|
|
61
96
|
const FONT = /font-family\s*:\s*([^;}\n]+)/g;
|
|
62
97
|
/**
|
|
@@ -370,11 +405,22 @@ function scanCore(file, source, table) {
|
|
|
370
405
|
// The kind is already known here, and without passing it the lookup
|
|
371
406
|
// answers a `gap` with a radius token.
|
|
372
407
|
const match = tokenMatch(table, literal, kind);
|
|
408
|
+
/**
|
|
409
|
+
* O NOME DELE VEM DA MESMA CHAVE QUE A NOSSA FAMÍLIA VALIDOU - ver `theirNames`.
|
|
410
|
+
*
|
|
411
|
+
* A chave carrega o `kind` porque o valor sozinho não decide: `4px` é `--radius-xs` e
|
|
412
|
+
* `--spacing` no vocabulário dele, e qual dos dois está certo depende de onde o literal está.
|
|
413
|
+
*/
|
|
414
|
+
const theirs = table.aliases.get(`${kind}:${normalizeValue(literal, table.rootPx)}`);
|
|
373
415
|
findings.push({
|
|
374
416
|
kind,
|
|
375
417
|
line: at,
|
|
376
418
|
literal,
|
|
377
419
|
token: match?.token ?? null,
|
|
420
|
+
...(/(?<!r)em$/i.test(literal.trim())
|
|
421
|
+
? { fontRelative: true }
|
|
422
|
+
: {}),
|
|
423
|
+
...(theirs ? { theirToken: theirs } : {}),
|
|
378
424
|
/**
|
|
379
425
|
* A COINCIDÊNCIA VIAJA COM O ACHADO - ver `tokenMatch`.
|
|
380
426
|
*
|
|
@@ -562,6 +608,8 @@ export function diagnose(files) {
|
|
|
562
608
|
byLiteral.set(key, {
|
|
563
609
|
kind: f.kind,
|
|
564
610
|
token: f.token,
|
|
611
|
+
...(f.theirToken ? { theirToken: f.theirToken } : {}),
|
|
612
|
+
...(f.fontRelative ? { fontRelative: true } : {}),
|
|
565
613
|
count: 1,
|
|
566
614
|
files: new Set([f.file]),
|
|
567
615
|
...(f.crossFamily ? { crossFamily: true } : {}),
|
|
@@ -573,6 +621,8 @@ export function diagnose(files) {
|
|
|
573
621
|
literal: key.slice(key.indexOf(":") + 1),
|
|
574
622
|
kind: v.kind,
|
|
575
623
|
token: v.token,
|
|
624
|
+
...(v.theirToken ? { theirToken: v.theirToken } : {}),
|
|
625
|
+
...(v.fontRelative ? { fontRelative: true } : {}),
|
|
576
626
|
count: v.count,
|
|
577
627
|
files: v.files.size,
|
|
578
628
|
...(v.crossFamily ? { crossFamily: true } : {}),
|
|
@@ -585,7 +635,15 @@ export function diagnose(files) {
|
|
|
585
635
|
files: files.filter((f) => f.findings.length > 0 || (f.phantoms?.length ?? 0) > 0),
|
|
586
636
|
findings: flat,
|
|
587
637
|
counts,
|
|
588
|
-
|
|
638
|
+
/**
|
|
639
|
+
* QUANTOS JÁ TÊM NOME NESTE REPOSITÓRIO - e o dele conta.
|
|
640
|
+
*
|
|
641
|
+
* Este número é a promessa que a tela faz ("9 of those have a name waiting"), e enquanto ele
|
|
642
|
+
* contava só os nossos, 852 achados que o repositório DELE nomeia saíam como "the system has no
|
|
643
|
+
* name for it". Uma promessa medida por metade do vocabulário que existe é uma promessa menor
|
|
644
|
+
* que a verdade.
|
|
645
|
+
*/
|
|
646
|
+
named: flat.filter((f) => nameToWrite(f)).length,
|
|
589
647
|
tokenUses,
|
|
590
648
|
phantomUses,
|
|
591
649
|
coverage: total === 0 ? 100 : Math.round(((tokenUses + ownUses) / total) * 100),
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { DS_FAMILY, normalizeValue } from "./tokens.js";
|
|
2
|
+
/**
|
|
3
|
+
* COMO ELE CHAMA O VALOR - para a gente parar de renomear as variáveis dele.
|
|
4
|
+
*
|
|
5
|
+
* O doctor sempre soube dizer o que o sistema chama de `#888`. O que ele fazia com isso é que estava
|
|
6
|
+
* errado: mandava trocar por `var(--ds-color-gray-400)` num repositório que declara
|
|
7
|
+
* `--color-lightgray-700: #888888` desde antes de a gente existir. `--fix --write` escrevia o NOSSO
|
|
8
|
+
* nome dentro do arquivo dele.
|
|
9
|
+
*
|
|
10
|
+
* Medido no repositório vivo em 13/08, repo inteiro:
|
|
11
|
+
*
|
|
12
|
+
* 141 tokens que ELE declara
|
|
13
|
+
* 181 tokens que o sistema declara
|
|
14
|
+
* 114 dos nossos seguram um valor que um dos dele também segura
|
|
15
|
+
*
|
|
16
|
+
* 995 achados com nome nosso
|
|
17
|
+
* 737 deles (74%) renomeavam uma variável que ele já tem
|
|
18
|
+
*
|
|
19
|
+
* E o grupo que saía como "the system has no name for it":
|
|
20
|
+
*
|
|
21
|
+
* 5383 sem nome nosso
|
|
22
|
+
* 852 ...mas o repositório DELE nomeia (843 cor · 8 tipo · 1 motion)
|
|
23
|
+
*
|
|
24
|
+
* A LEI JÁ EXISTIA, num sentido só. `absorb-plan.ts` diz, sobre a direção repo -> sistema: *"quando o
|
|
25
|
+
* vocabulário DELES já nomeia o valor, o nome é o deles"*. Na direção sistema -> repo a gente fazia o
|
|
26
|
+
* contrário. É a mesma lei 11 um nível abaixo da cor: não reescrever o vocabulário dele.
|
|
27
|
+
*
|
|
28
|
+
* ESTE MAPA NÃO É UM ARQUIVO, e é de propósito (dono, 13/08: *"talvez essas informações possam vir do
|
|
29
|
+
* MCP para não levar isso para o usuário ficar vendo"*). Ele é derivado das folhas de estilo dele a
|
|
30
|
+
* cada rodada - 686 folhas e 797KB no repo real, 4ms no hook inteiro (80ms -> 84ms, medido ponta a
|
|
31
|
+
* ponta), e o `absorb` já pagava essa varredura hoje. Um
|
|
32
|
+
* mapa gravado envelhece no dia em que ele renomeia um token, e aí a gente sugere um nome que não
|
|
33
|
+
* existe mais. O MCP ganha de graça, porque `check_file` roda este mesmo doctor.
|
|
34
|
+
*
|
|
35
|
+
* E ele nunca aparece na tela: o que aparece é o nome DELE, no lugar onde antes aparecia o nosso.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* QUANDO A FORMA DO VALOR JÁ DECIDE A FAMÍLIA - e é isto que a segunda porta pede.
|
|
39
|
+
*
|
|
40
|
+
* A porta admitia só COR, e o motivo estava certo pela metade: o que impede um comprimento de entrar
|
|
41
|
+
* é a AMBIGUIDADE (`24px` pode ser raio, espaçamento ou tamanho de fonte, e sem um token nosso não há
|
|
42
|
+
* o que decidisse), não o fato de ser cor. Uma pilha de fontes não é ambígua - `'Figtree', sans-serif`
|
|
43
|
+
* não pode ser um espaçamento -, e uma duração também não: `s` e `ms` só existem em motion.
|
|
44
|
+
*
|
|
45
|
+
* Então a regra é a forma, e o comprimento continua de fora, declarado. Medido no repositório real em
|
|
46
|
+
* 14/08: 7 achados em 6 arquivos saíam como "the system has no name for it" sobre a família de fontes
|
|
47
|
+
* que o próprio css dele nomeia `--dashboard-font-family`. É pouco, e é o único grupo que sobrou do
|
|
48
|
+
* item que eu tinha nomeado - os `em` saíram na leva anterior.
|
|
49
|
+
*/
|
|
50
|
+
const UNAMBIGUOUS = {
|
|
51
|
+
/** `#rrggbbaa`, que é onde toda a família de dialetos cai. */
|
|
52
|
+
color: /^#[0-9a-f]{8}$/,
|
|
53
|
+
/** `s` e `ms` não aparecem em nenhuma outra família do contrato. */
|
|
54
|
+
motion: /^-?[\d.]+ms$/,
|
|
55
|
+
/** Uma pilha de fontes: tem vírgula, ou é uma das palavras genéricas do CSS. */
|
|
56
|
+
font: /,|^(?:serif|sans-serif|monospace|cursive|fantasy|system-ui)$/,
|
|
57
|
+
};
|
|
58
|
+
const segments = (name) => name.replace(/^--/, "").split("-");
|
|
59
|
+
/**
|
|
60
|
+
* QUAL DOS NOMES DELE, quando mais de um segura o mesmo valor - e são 18 no repo real.
|
|
61
|
+
*
|
|
62
|
+
* O empate não é decorativo: `4px` é `--radius-xs` E `--spacing` lá dentro, `24px` é `--text-h2` E
|
|
63
|
+
* `--spacing-lg`. Escolher errado escreve um token de tipo numa posição de espaçamento, que é
|
|
64
|
+
* exatamente o erro de categoria que o `crossFamily` foi criado para impedir do nosso lado.
|
|
65
|
+
*
|
|
66
|
+
* Três critérios, nesta ordem, e todos LIDOS do repositório dele:
|
|
67
|
+
*
|
|
68
|
+
* 1. quantos segmentos ele compartilha com o nosso token daquela família
|
|
69
|
+
* `--ds-radius-xs` puxa `--radius-xs` (2) e não `--spacing` (0)
|
|
70
|
+
* 2. a convenção dominante dele - o primeiro segmento mais frequente entre os tokens dele
|
|
71
|
+
* no repo real, `--color-*` (57) contra `--dashboard-*` (25)
|
|
72
|
+
* 3. ordem de declaração, que é o desempate que sempre existe e nunca inventa
|
|
73
|
+
*/
|
|
74
|
+
function pick(candidates, ours, convention) {
|
|
75
|
+
const mine = ours ? new Set(segments(ours)) : null;
|
|
76
|
+
let best = candidates[0];
|
|
77
|
+
let bestScore = [-1, -1];
|
|
78
|
+
for (const name of candidates) {
|
|
79
|
+
const parts = segments(name);
|
|
80
|
+
const shared = mine ? parts.filter((p) => mine.has(p)).length : 0;
|
|
81
|
+
const score = [
|
|
82
|
+
shared,
|
|
83
|
+
convention.get(parts[0] ?? "") ?? 0,
|
|
84
|
+
];
|
|
85
|
+
if (score[0] > bestScore[0] ||
|
|
86
|
+
(score[0] === bestScore[0] && score[1] > bestScore[1])) {
|
|
87
|
+
best = name;
|
|
88
|
+
bestScore = score;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return best;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* O MAPA DE UMA RODADA: `<natureza>:<valor normalizado>` -> como ELE chama.
|
|
95
|
+
*
|
|
96
|
+
* A chave carrega a natureza porque o valor sozinho não decide: o mesmo `4px` tem dois nomes no
|
|
97
|
+
* vocabulário dele, e qual dos dois está certo depende de o literal estar num raio ou num
|
|
98
|
+
* espaçamento. É a mesma razão pela qual `tokenMatch` recebe o `kind`.
|
|
99
|
+
*
|
|
100
|
+
* DUAS PORTAS, e a segunda é o que faz o número dobrar:
|
|
101
|
+
*
|
|
102
|
+
* o sistema nomeia o valor a NOSSA família valida a natureza, e o nome dele entra
|
|
103
|
+
* o sistema NÃO nomeia entra o valor cuja FORMA já decide a família - ver `UNAMBIGUOUS`
|
|
104
|
+
*
|
|
105
|
+
* O que fica de fora da segunda porta é o COMPRIMENTO, e ele fica por um motivo e não por descuido:
|
|
106
|
+
* `24px` pode ser raio, espaçamento ou tamanho de fonte, e sem um token nosso não há o que validasse.
|
|
107
|
+
* Esses continuam saindo como "no name for it", que é verdade e é o caminho do `absorb`.
|
|
108
|
+
*/
|
|
109
|
+
export function theirNames(ours, theirs) {
|
|
110
|
+
const out = new Map();
|
|
111
|
+
if (theirs.byName.size === 0)
|
|
112
|
+
return out;
|
|
113
|
+
/** A convenção dominante dele, contada e não suposta - ver `pick`. */
|
|
114
|
+
const convention = new Map();
|
|
115
|
+
for (const name of theirs.byName.keys()) {
|
|
116
|
+
const head = segments(name)[0] ?? "";
|
|
117
|
+
convention.set(head, (convention.get(head) ?? 0) + 1);
|
|
118
|
+
}
|
|
119
|
+
for (const [kind, prefix] of Object.entries(DS_FAMILY)) {
|
|
120
|
+
for (const [name, raw] of ours.byName) {
|
|
121
|
+
if (!name.startsWith(prefix))
|
|
122
|
+
continue;
|
|
123
|
+
const value = normalizeValue(raw, ours.rootPx);
|
|
124
|
+
const key = `${kind}:${value}`;
|
|
125
|
+
if (out.has(key))
|
|
126
|
+
continue;
|
|
127
|
+
const candidates = theirs.byValue.get(value);
|
|
128
|
+
if (!candidates || candidates.length === 0)
|
|
129
|
+
continue;
|
|
130
|
+
out.set(key, pick(candidates, name, convention));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
for (const [value, candidates] of theirs.byValue) {
|
|
134
|
+
for (const [kind, form] of Object.entries(UNAMBIGUOUS)) {
|
|
135
|
+
if (!form.test(value))
|
|
136
|
+
continue;
|
|
137
|
+
const key = `${kind}:${value}`;
|
|
138
|
+
if (out.has(key))
|
|
139
|
+
continue;
|
|
140
|
+
out.set(key, pick(candidates, null, convention));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* A TABELA COM O VOCABULÁRIO DELE DENTRO - um passo, e é este que os comandos chamam.
|
|
147
|
+
*
|
|
148
|
+
* `ours` continua sendo a lei: é ela que diz se `2rem` é tipo ou raio, e é dela que sai a cobertura.
|
|
149
|
+
* A dele decide só COMO SE ESCREVE. Separar as duas é o mesmo desenho que o `absorb` já usa
|
|
150
|
+
* ("DUAS TABELAS, e é a diferença entre elas que define o trabalho").
|
|
151
|
+
*/
|
|
152
|
+
export function withTheirNames(ours, theirs) {
|
|
153
|
+
return { ...ours, aliases: theirNames(ours, theirs) };
|
|
154
|
+
}
|
package/dist/doctor/tokens.js
CHANGED
|
@@ -31,6 +31,7 @@ export const EMPTY_TABLE = {
|
|
|
31
31
|
byValue: new Map(),
|
|
32
32
|
rootPx: DEFAULT_ROOT_PX,
|
|
33
33
|
rootFrom: null,
|
|
34
|
+
aliases: new Map(),
|
|
34
35
|
declared: new Set(),
|
|
35
36
|
keyframes: new Set(),
|
|
36
37
|
};
|
|
@@ -120,10 +121,19 @@ export function normalizeValue(raw, rootPx) {
|
|
|
120
121
|
* A FAMÍLIA CONTINUA MANDANDO: `4px` passa a casar com `--ds-radius-xs` E com `--ds-spacing-3xs`,
|
|
121
122
|
* e é `tokenMatch` quem escolhe pelo `kind` - um raio não vira espaçamento dentro de um `gap`.
|
|
122
123
|
*/
|
|
123
|
-
|
|
124
|
+
/**
|
|
125
|
+
* `em` CAI AQUI JUNTO, e o que impede isso de virar uma suposição é o achado, não o normalizador.
|
|
126
|
+
*
|
|
127
|
+
* Converter `1em` por `rootPx` é certo sempre que a fonte do elemento é a da raiz, e errado quando
|
|
128
|
+
* um ancestral a mudou - e isto aqui não tem como saber qual dos dois. Ele converte para a
|
|
129
|
+
* CONVERSA existir (sem isto, `1em` não casa com degrau nenhum e sai como "o sistema não nomeia
|
|
130
|
+
* isto", sobre um valor que o sistema nomeia); quem impede a troca automática é `Finding.fontRelative`,
|
|
131
|
+
* que o `--fix` recusa. Ver `scan.ts`.
|
|
132
|
+
*/
|
|
133
|
+
const len = /^(-?\d*\.?\d+)(px|r?em)$/.exec(v);
|
|
124
134
|
if (len) {
|
|
125
135
|
const n = Number.parseFloat(len[1]);
|
|
126
|
-
const px = len[2] === "
|
|
136
|
+
const px = len[2] === "px" ? n : n * rootPx;
|
|
127
137
|
/** Arredonda o rastro binário: `0.35rem * 16` é 5.6000000000000005. */
|
|
128
138
|
return `${Math.round(px * 1e4) / 1e4}px`;
|
|
129
139
|
}
|
|
@@ -431,6 +441,8 @@ export function buildTable(input) {
|
|
|
431
441
|
byValue,
|
|
432
442
|
rootPx,
|
|
433
443
|
rootFrom: input.rootFrom ?? null,
|
|
444
|
+
/** Vazio até `withTheirNames` ler o vocabulário dele - ver `their-names.ts`. */
|
|
445
|
+
aliases: new Map(),
|
|
434
446
|
declared: parseDeclaredNames(input.css),
|
|
435
447
|
keyframes: new Set([...input.css.matchAll(/@keyframes\s+([a-zA-Z0-9_-]+)/g)].map((m) => m[1])),
|
|
436
448
|
};
|
|
@@ -492,7 +504,9 @@ export function nearestToken(table, literal) {
|
|
|
492
504
|
* radius is one a person stops reading, and this one has exactly one job that
|
|
493
505
|
* nobody else does: naming the right token.
|
|
494
506
|
*/
|
|
495
|
-
|
|
507
|
+
/** Exportado para `their-names.ts`, que precisa da MESMA divisão de família para validar a natureza
|
|
508
|
+
* de um nome dele - duas tabelas de família seriam duas leis. */
|
|
509
|
+
export const DS_FAMILY = {
|
|
496
510
|
color: "--ds-color-",
|
|
497
511
|
radius: "--ds-radius-",
|
|
498
512
|
spacing: "--ds-spacing-",
|
|
@@ -521,7 +535,7 @@ export function tokenMatch(table, literal, kind) {
|
|
|
521
535
|
const hit = table.byValue.get(normalizeValue(literal, table.rootPx));
|
|
522
536
|
if (!hit || hit.length === 0)
|
|
523
537
|
return null;
|
|
524
|
-
const prefix = kind ?
|
|
538
|
+
const prefix = kind ? DS_FAMILY[kind] : undefined;
|
|
525
539
|
const family = prefix ? hit.filter((n) => n.startsWith(prefix)) : [];
|
|
526
540
|
const pool = family.length > 0 ? family : hit;
|
|
527
541
|
// Semantic roles name intent; primitives name a shelf. Prefer intent.
|
package/dist/install-marks.js
CHANGED
|
@@ -96,7 +96,34 @@ export const MATERIALISER_SINCE = "0.16.220";
|
|
|
96
96
|
* tem nome para isto" sobre um valor que o sistema dela nomeia - medido no repo real, 243 trocas
|
|
97
97
|
* viraram 764 sobre os mesmos 4433 valores à mão.
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
/**
|
|
100
|
+
* 0.16.223 -> 0.16.229 em 13/08, e o SIM mais forte que esta marca já teve: o hook passou a
|
|
101
|
+
* aconselhar o nome DELE. Um pin anterior lê o mesmo arquivo e manda escrever
|
|
102
|
+
* `var(--ds-color-gray-400)` num repositório que declara `--color-lightgray-700: #888888` - e a
|
|
103
|
+
* pessoa acaba com dois conselhos diferentes sobre o mesmo valor, porque o `doctor` de hoje diz o
|
|
104
|
+
* nome dela. Medido no repo real: 737 de 995 sugestões renomeavam uma variável dela, e outras 852
|
|
105
|
+
* saíam como "o sistema não nomeia isto" sobre valores que o repositório dela nomeia.
|
|
106
|
+
*
|
|
107
|
+
* É também a primeira vez que o hook VARRE as folhas de estilo, revisando a escolha declarada em
|
|
108
|
+
* `loadSystem` - medido ponta a ponta no repo real, 80ms -> 84ms, contra oferecer o nome errado.
|
|
109
|
+
*/
|
|
110
|
+
/**
|
|
111
|
+
* 0.16.229 -> 0.16.230 em 13/08: `em` passou a ser um comprimento como os outros. O padrão do RAIO
|
|
112
|
+
* já aceitava as três unidades e o do ESPAÇAMENTO aceitava duas - assimetria, não doutrina - e um
|
|
113
|
+
* hook pinado antes disto lê o mesmo arquivo e não vê 933 espaçamentos e 144 raios, em 325 arquivos
|
|
114
|
+
* do repositório real. Não é medir menos: é chamar de limpo o que não é.
|
|
115
|
+
*
|
|
116
|
+
* A 0.16.229 nunca chegou ao npm, mas a marca sobe assim mesmo - uma marca que aponta para uma
|
|
117
|
+
* versão que ninguém pode instalar é uma marca que nunca dispara.
|
|
118
|
+
*/
|
|
119
|
+
/**
|
|
120
|
+
* 0.16.230 -> 0.16.231 em 14/08: a segunda porta do mapa de vocabulário deixou de ser "só cor" e
|
|
121
|
+
* passou a ser "a forma que já decide a família" - uma pilha de fontes não pode ser um espaçamento, e
|
|
122
|
+
* `ms` só existe em motion. Um hook pinado antes disto olha o arquivo que a pessoa acabou de escrever
|
|
123
|
+
* e diz que o sistema não nomeia a fonte que o css dela nomeia. Medido no repositório real: as trocas
|
|
124
|
+
* com nome disponível foram de 1624 para 1631.
|
|
125
|
+
*/
|
|
126
|
+
export const CHECKER_SINCE = "0.16.231";
|
|
100
127
|
/**
|
|
101
128
|
* A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
|
|
102
129
|
*
|
package/dist/measured-scope.js
CHANGED
|
@@ -117,7 +117,9 @@ export function describeScope(m) {
|
|
|
117
117
|
]
|
|
118
118
|
: []),
|
|
119
119
|
];
|
|
120
|
-
|
|
120
|
+
/** O ARQUIVO, e não a palavra: "census" é o nosso nome para a medição; `_synthesisui/census.json`
|
|
121
|
+
* é um caminho que ele abre. Ver a guarda de vocabulário em `doctor-intent.spec.ts`. */
|
|
122
|
+
return `read from _synthesisui/census.json: ${parts.join(" · ")}`;
|
|
121
123
|
}
|
|
122
124
|
/**
|
|
123
125
|
* GRAVA ONDE ESTE SISTEMA FOI MEDIDO, no ponteiro dele.
|