dowel-ui 0.12.0 → 0.14.0
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/README.md +43 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +9 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/codemod.d.ts +22 -0
- package/dist/cli/codemod.d.ts.map +1 -0
- package/dist/cli/codemod.js +69 -0
- package/dist/cli/codemod.js.map +1 -0
- package/dist/cli/diff.d.ts +23 -0
- package/dist/cli/diff.d.ts.map +1 -0
- package/dist/cli/diff.js +122 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/doctor.d.ts +81 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +185 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +362 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/scan.d.ts +43 -0
- package/dist/cli/scan.d.ts.map +1 -0
- package/dist/cli/scan.js +265 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/stock.d.ts +29 -0
- package/dist/cli/stock.d.ts.map +1 -0
- package/dist/cli/stock.js +104 -0
- package/dist/cli/stock.js.map +1 -0
- package/dist/registry.json +40 -25
- package/package.json +9 -2
package/dist/cli/scan.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { findRawColor } from '../eslint/no-raw-color.js';
|
|
4
|
+
import { stockNames, stockTokens } from './stock.js';
|
|
5
|
+
/** Which files are worth reading.
|
|
6
|
+
*
|
|
7
|
+
* CSS is here because the stock vocabulary lives in a stylesheet: a project
|
|
8
|
+
* migrating from shadcn has `--background: 0 0% 100%` in its own theme file,
|
|
9
|
+
* and that is the first thing to find. */
|
|
10
|
+
const EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.css', '.mdx']);
|
|
11
|
+
/** A test file, where a colour is the subject rather than the styling.
|
|
12
|
+
*
|
|
13
|
+
* The linter already exempts these - a test about the accent has to write a
|
|
14
|
+
* hex down to have something to assert - and this has to exempt exactly the
|
|
15
|
+
* same files. Sharing `findRawColor` keeps the two agreeing on what a colour
|
|
16
|
+
* *is*; it cannot make them agree on where one is allowed, and the first live
|
|
17
|
+
* run of `check` reported six violations in dowel's own stand that the linter
|
|
18
|
+
* passes. A report stricter than the build it precedes teaches a reader to
|
|
19
|
+
* ignore it. */
|
|
20
|
+
const TEST_FILE = /\.(?:test|spec)\.[jt]sx?$/;
|
|
21
|
+
/** Directories never worth walking into.
|
|
22
|
+
*
|
|
23
|
+
* `node_modules` would otherwise dominate the report with other people's
|
|
24
|
+
* colours, and a build output would report the same finding a second time from
|
|
25
|
+
* the compiled copy - which reads as two problems where there is one. */
|
|
26
|
+
const SKIP_DIRECTORIES = new Set([
|
|
27
|
+
'node_modules',
|
|
28
|
+
'.git',
|
|
29
|
+
'dist',
|
|
30
|
+
'build',
|
|
31
|
+
'out',
|
|
32
|
+
'.next',
|
|
33
|
+
'.astro',
|
|
34
|
+
'.turbo',
|
|
35
|
+
'coverage',
|
|
36
|
+
'target',
|
|
37
|
+
]);
|
|
38
|
+
/** Every file under `root` worth scanning, as absolute paths, in a stable
|
|
39
|
+
* order - a report that reshuffles between runs cannot be diffed. */
|
|
40
|
+
export function collectFiles(root) {
|
|
41
|
+
const found = [];
|
|
42
|
+
const walk = (directory) => {
|
|
43
|
+
let entries;
|
|
44
|
+
try {
|
|
45
|
+
entries = readdirSync(directory).sort();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// A directory that cannot be read is not a finding: it is somebody's
|
|
49
|
+
// permissions, and stopping the whole report over it would be worse
|
|
50
|
+
// than the gap.
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
const path = resolve(directory, entry);
|
|
55
|
+
let isDirectory;
|
|
56
|
+
try {
|
|
57
|
+
isDirectory = statSync(path).isDirectory();
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (isDirectory) {
|
|
63
|
+
if (SKIP_DIRECTORIES.has(entry) || entry.startsWith('.'))
|
|
64
|
+
continue;
|
|
65
|
+
walk(path);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const dot = entry.lastIndexOf('.');
|
|
69
|
+
if (dot < 0)
|
|
70
|
+
continue;
|
|
71
|
+
if (!EXTENSIONS.has(entry.slice(dot)))
|
|
72
|
+
continue;
|
|
73
|
+
found.push(path);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
walk(root);
|
|
77
|
+
return found;
|
|
78
|
+
}
|
|
79
|
+
/** A stock custom property, as it appears in either half of a project:
|
|
80
|
+
* `--muted-foreground` in a stylesheet, `var(--muted-foreground)` in a style
|
|
81
|
+
* object.
|
|
82
|
+
*
|
|
83
|
+
* Built from the table rather than written out, so a name added there is found
|
|
84
|
+
* here without a second edit. */
|
|
85
|
+
const STOCK_PROPERTY = new RegExp(`--(${stockNames.join('|')})\\b`, 'g');
|
|
86
|
+
/** The same names as Tailwind utilities, which is how they reach a component:
|
|
87
|
+
* `bg-muted`, `text-muted-foreground`, `border-input`, `hover:bg-accent`.
|
|
88
|
+
*
|
|
89
|
+
* The prefix list is what Tailwind actually generates from a colour token, and
|
|
90
|
+
* the opening character class is what keeps `bg-primary` from matching inside
|
|
91
|
+
* `custom-bg-primary`. */
|
|
92
|
+
const UTILITY_PREFIXES = 'bg|text|border|fill|stroke|ring|outline|divide|shadow|from|via|to|accent|caret|decoration';
|
|
93
|
+
const STOCK_UTILITY = new RegExp(`(?:^|[\\s"'\`:\\[({])((?:${UTILITY_PREFIXES})-(?:${stockNames.join('|')}))\\b`, 'g');
|
|
94
|
+
/** Turn an offset into a 1-based line and column. */
|
|
95
|
+
function locate(source, index) {
|
|
96
|
+
let line = 1;
|
|
97
|
+
let lineStart = 0;
|
|
98
|
+
for (let i = 0; i < index; i += 1) {
|
|
99
|
+
if (source.charCodeAt(i) === 10 /* \n */) {
|
|
100
|
+
line += 1;
|
|
101
|
+
lineStart = i + 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { line, column: index - lineStart + 1 };
|
|
105
|
+
}
|
|
106
|
+
/** Every string literal in a source file, with where it starts.
|
|
107
|
+
*
|
|
108
|
+
* This is the textual stand-in for the rule's `Literal` and `TemplateElement`
|
|
109
|
+
* visitors, and it exists so that a colour is only reported where a colour
|
|
110
|
+
* could actually be written - in a string - rather than anywhere the
|
|
111
|
+
* characters happen to appear. Without it, a comment explaining the rule would
|
|
112
|
+
* be a finding: it has to write a colour down to say which ones are forbidden.
|
|
113
|
+
*
|
|
114
|
+
* It is a small scanner rather than a regular expression because quotes nest:
|
|
115
|
+
* an apostrophe inside double quotes is one string, not two.
|
|
116
|
+
*/
|
|
117
|
+
export function stringLiterals(source) {
|
|
118
|
+
const literals = [];
|
|
119
|
+
let i = 0;
|
|
120
|
+
while (i < source.length) {
|
|
121
|
+
const char = source[i];
|
|
122
|
+
// A line comment: skip to the newline. Nothing in it is a literal, and a
|
|
123
|
+
// commented-out colour is not a colour on a screen.
|
|
124
|
+
if (char === '/' && source[i + 1] === '/') {
|
|
125
|
+
while (i < source.length && source[i] !== '\n')
|
|
126
|
+
i += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
// A block comment. An opener inside a string is handled by the branch
|
|
130
|
+
// below taking the whole string first.
|
|
131
|
+
if (char === '/' && source[i + 1] === '*') {
|
|
132
|
+
const end = source.indexOf('*/', i + 2);
|
|
133
|
+
i = end < 0 ? source.length : end + 2;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
137
|
+
const quote = char;
|
|
138
|
+
const start = i + 1;
|
|
139
|
+
i = start;
|
|
140
|
+
while (i < source.length) {
|
|
141
|
+
if (source[i] === '\\') {
|
|
142
|
+
i += 2;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (source[i] === quote)
|
|
146
|
+
break;
|
|
147
|
+
i += 1;
|
|
148
|
+
}
|
|
149
|
+
literals.push({ text: source.slice(start, i), index: start });
|
|
150
|
+
i += 1;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
i += 1;
|
|
154
|
+
}
|
|
155
|
+
return literals;
|
|
156
|
+
}
|
|
157
|
+
/** What to say about one match.
|
|
158
|
+
*
|
|
159
|
+
* One builder for both shapes a stock name takes, so that a custom property
|
|
160
|
+
* and the utility spelling of the same name cannot end up described
|
|
161
|
+
* differently - which they were, and the ambiguous case was the one that
|
|
162
|
+
* suffered: both branches said "has no dowel equivalent", and a name that
|
|
163
|
+
* exists in both vocabularies has the opposite problem.
|
|
164
|
+
*
|
|
165
|
+
* `subject` is the text as it was written, `prefix` is what a replacement has
|
|
166
|
+
* to keep in front of the token (`--`, or `bg-`). */
|
|
167
|
+
function describe(subject, prefix, replacement) {
|
|
168
|
+
switch (replacement.kind) {
|
|
169
|
+
case 'token':
|
|
170
|
+
return `\`${subject}\` is the stock shadcn vocabulary; dowel calls this \`${prefix}${replacement.token}\`.`;
|
|
171
|
+
case 'unmapped':
|
|
172
|
+
return `\`${subject}\` is the stock shadcn vocabulary and has no dowel equivalent - ${replacement.note}`;
|
|
173
|
+
case 'ambiguous':
|
|
174
|
+
return `\`${subject}\` exists in both vocabularies: ${replacement.note}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Read one file and say what is wrong with it. */
|
|
178
|
+
export function scanSource(source, file) {
|
|
179
|
+
const findings = [];
|
|
180
|
+
const isStylesheet = file.endsWith('.css');
|
|
181
|
+
/* Stock names are still reported in a test - a test on the old vocabulary
|
|
182
|
+
* has to be migrated with everything else. Only the colour pass is exempt. */
|
|
183
|
+
const isTest = TEST_FILE.test(file);
|
|
184
|
+
const add = (kind, index, text, message, replacement) => {
|
|
185
|
+
const { line, column } = locate(source, index);
|
|
186
|
+
findings.push({ file, line, column, kind, text, message, replacement });
|
|
187
|
+
};
|
|
188
|
+
/* Stock custom properties, anywhere in the file. In a stylesheet that is a
|
|
189
|
+
* declaration; in a component it is a `var()` call. Both are the same
|
|
190
|
+
* finding and take the same fix. */
|
|
191
|
+
for (const match of source.matchAll(STOCK_PROPERTY)) {
|
|
192
|
+
const name = match[1];
|
|
193
|
+
const replacement = stockTokens[name];
|
|
194
|
+
add('stock', match.index, match[0], describe(`--${name}`, '--', replacement), replacement);
|
|
195
|
+
}
|
|
196
|
+
/* The same names as utilities. Only in code: a stylesheet writing
|
|
197
|
+
* `bg-primary` is writing about a class, usually in an `@apply`, and the
|
|
198
|
+
* custom-property pass above has already spoken about the same file. */
|
|
199
|
+
if (!isStylesheet) {
|
|
200
|
+
for (const match of source.matchAll(STOCK_UTILITY)) {
|
|
201
|
+
const utility = match[1];
|
|
202
|
+
const name = stockNames.find((candidate) => utility.endsWith(`-${candidate}`));
|
|
203
|
+
if (!name)
|
|
204
|
+
continue;
|
|
205
|
+
const replacement = stockTokens[name];
|
|
206
|
+
const prefix = utility.slice(0, utility.length - name.length);
|
|
207
|
+
add('stock', match.index + match[0].indexOf(utility), utility, describe(utility, prefix, replacement), replacement);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/* Colours written down. In code this reads string literals, exactly like the
|
|
211
|
+
* rule does; a stylesheet is read whole, because that is where a colour
|
|
212
|
+
* appears outside any string - and where, in a theme file, it is supposed
|
|
213
|
+
* to. */
|
|
214
|
+
if (isTest) {
|
|
215
|
+
// Nothing: a test writes colours down on purpose, and the linter exempts
|
|
216
|
+
// the same files.
|
|
217
|
+
}
|
|
218
|
+
else if (isStylesheet) {
|
|
219
|
+
// A stylesheet that defines the dowel tokens is the one place raw colour
|
|
220
|
+
// belongs. Recognised by what it declares rather than by its name: a
|
|
221
|
+
// product may call its theme anything.
|
|
222
|
+
const definesTheme = /--accent-base\s*:/.test(source);
|
|
223
|
+
if (!definesTheme) {
|
|
224
|
+
for (const [index, line] of source.split('\n').entries()) {
|
|
225
|
+
const finding = findRawColor(line);
|
|
226
|
+
if (finding) {
|
|
227
|
+
findings.push({
|
|
228
|
+
file,
|
|
229
|
+
line: index + 1,
|
|
230
|
+
column: 1,
|
|
231
|
+
kind: 'color',
|
|
232
|
+
text: line.trim(),
|
|
233
|
+
message: finding.message,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
for (const literal of stringLiterals(source)) {
|
|
241
|
+
const finding = findRawColor(literal.text);
|
|
242
|
+
if (finding)
|
|
243
|
+
add('color', literal.index, literal.text.trim(), finding.message);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return findings.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
247
|
+
}
|
|
248
|
+
/** Scan a whole project. Paths in the findings are relative to `root`, with
|
|
249
|
+
* forward slashes, so a report reads the same on either platform. */
|
|
250
|
+
export function scanProject(root) {
|
|
251
|
+
const findings = [];
|
|
252
|
+
for (const file of collectFiles(root)) {
|
|
253
|
+
let source;
|
|
254
|
+
try {
|
|
255
|
+
source = readFileSync(file, 'utf8');
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const name = relative(root, file).split(sep).join('/');
|
|
261
|
+
findings.push(...scanSource(source, name));
|
|
262
|
+
}
|
|
263
|
+
return findings;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/cli/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** What to do with a stock name that has been found. */
|
|
2
|
+
export type Replacement =
|
|
3
|
+
/** A straight rename: this stock name means that dowel token. */
|
|
4
|
+
{
|
|
5
|
+
readonly kind: 'token';
|
|
6
|
+
readonly token: string;
|
|
7
|
+
readonly note?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Stock-only, and dowel has nothing that means it yet. */
|
|
10
|
+
| {
|
|
11
|
+
readonly kind: 'unmapped';
|
|
12
|
+
readonly note: string;
|
|
13
|
+
}
|
|
14
|
+
/** The name exists in both vocabularies. Reported with its ambiguity spelled
|
|
15
|
+
* out; never rewritten, because the tool cannot tell which one it is
|
|
16
|
+
* looking at and a wrong guess breaks a correct project. */
|
|
17
|
+
| {
|
|
18
|
+
readonly kind: 'ambiguous';
|
|
19
|
+
readonly stockMeaning: string;
|
|
20
|
+
readonly note: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const stockTokens: Readonly<Record<string, Replacement>>;
|
|
23
|
+
/** The stock names, longest first.
|
|
24
|
+
*
|
|
25
|
+
* Order matters wherever these are matched one after another: `--sidebar` is a
|
|
26
|
+
* prefix of `--sidebar-border`, and trying the short one first would rewrite
|
|
27
|
+
* half of the long one and leave `-border` dangling. */
|
|
28
|
+
export declare const stockNames: readonly string[];
|
|
29
|
+
//# sourceMappingURL=stock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stock.d.ts","sourceRoot":"","sources":["../../src/cli/stock.ts"],"names":[],"mappings":"AAoCA,wDAAwD;AACxD,MAAM,MAAM,WAAW;AACrB,iEAAiE;AAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AAC5E,2DAA2D;GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACtD;;4DAE4D;GAC1D;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAYxF,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA2D7D,CAAA;AAED;;;;wDAIwD;AACxD,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAEvC,CAAA"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The stock shadcn vocabulary, and what it means here.
|
|
3
|
+
*
|
|
4
|
+
* A product arriving at dowel almost never arrives from nothing. It arrives
|
|
5
|
+
* from stock shadcn/ui, whose theme names colours by their role in a page -
|
|
6
|
+
* `--background`, `--muted-foreground`, `--card` - and whose components are
|
|
7
|
+
* written against those names. dowel names them by what they are on a screen
|
|
8
|
+
* instead: a ground, a raised surface, dimmed ink. The two vocabularies
|
|
9
|
+
* overlap almost entirely in meaning and not at all in spelling.
|
|
10
|
+
*
|
|
11
|
+
* So the first thing a migration needs is this table, and it has to live in
|
|
12
|
+
* one place: `check` reports what it finds, `codemod` rewrites it, and the two
|
|
13
|
+
* disagreeing would be worse than either alone - a report that names a
|
|
14
|
+
* replacement the rewriter does not make.
|
|
15
|
+
*
|
|
16
|
+
* The mapping is deliberately incomplete in two directions.
|
|
17
|
+
*
|
|
18
|
+
* Every stock name is listed, because the point is to find all of them; but a
|
|
19
|
+
* few have no honest equivalent and say so, because guessing one would put a
|
|
20
|
+
* wrong colour on a screen and call the migration done. `--chart-1` is the
|
|
21
|
+
* clearest case: dowel has no chart palette until the charts version, and
|
|
22
|
+
* mapping it to the accent would make five series the same colour.
|
|
23
|
+
*
|
|
24
|
+
* And two names exist in *both* vocabularies meaning different things, which a
|
|
25
|
+
* table keyed by name cannot resolve. `--accent` is stock shadcn's hover fill
|
|
26
|
+
* and it is also dowel's flagship token - the product's own hue. A scanner
|
|
27
|
+
* reading names alone sees no difference between a project that has not
|
|
28
|
+
* migrated and one that has, so these are reported for a human to judge and
|
|
29
|
+
* never rewritten.
|
|
30
|
+
*
|
|
31
|
+
* That distinction is not theoretical: the first live run of `check` reported
|
|
32
|
+
* twenty-four violations in dowel's own stand, every one of them a correct use
|
|
33
|
+
* of `--accent`, and `codemod --write` would have rewritten them to `--soft`
|
|
34
|
+
* and broken a project that was already right.
|
|
35
|
+
*/
|
|
36
|
+
/*
|
|
37
|
+
* The table, in the order the tokens read on a screen: grounds, then surfaces,
|
|
38
|
+
* then ink, then the accent, then status, then the odd ones out.
|
|
39
|
+
*
|
|
40
|
+
* `--foreground` and `--background` are the pair everything else is defined
|
|
41
|
+
* against in stock shadcn, and they are the pair that most often survives a
|
|
42
|
+
* half-finished migration: a product swaps its components over and leaves the
|
|
43
|
+
* page itself on the old names, so the screen has two grounds that agree only
|
|
44
|
+
* by accident of both being near-black.
|
|
45
|
+
*/
|
|
46
|
+
export const stockTokens = {
|
|
47
|
+
background: { kind: 'token', token: 'bg' },
|
|
48
|
+
foreground: { kind: 'token', token: 'text' },
|
|
49
|
+
card: { kind: 'token', token: 'raise' },
|
|
50
|
+
'card-foreground': { kind: 'token', token: 'text' },
|
|
51
|
+
popover: { kind: 'token', token: 'raise' },
|
|
52
|
+
'popover-foreground': { kind: 'token', token: 'text' },
|
|
53
|
+
muted: { kind: 'token', token: 'soft' },
|
|
54
|
+
'muted-foreground': { kind: 'token', token: 'dim' },
|
|
55
|
+
border: { kind: 'token', token: 'line' },
|
|
56
|
+
input: { kind: 'token', token: 'line' },
|
|
57
|
+
ring: {
|
|
58
|
+
kind: 'token',
|
|
59
|
+
token: 'accent',
|
|
60
|
+
note: 'dowel draws focus from the accent; there is no separate ring colour.',
|
|
61
|
+
},
|
|
62
|
+
primary: { kind: 'token', token: 'accent' },
|
|
63
|
+
'primary-foreground': { kind: 'token', token: 'on-accent' },
|
|
64
|
+
secondary: { kind: 'token', token: 'soft' },
|
|
65
|
+
'secondary-foreground': { kind: 'token', token: 'text' },
|
|
66
|
+
/* The collision. Both vocabularies have this name and they mean opposite
|
|
67
|
+
* things: stock `--accent` is the quiet fill a row takes on hover, dowel's
|
|
68
|
+
* `--accent` is the product's own colour - the loudest thing on the screen.
|
|
69
|
+
* Rewriting it blindly turns every accent in a migrated project into a grey,
|
|
70
|
+
* so it is reported and left alone. */
|
|
71
|
+
accent: {
|
|
72
|
+
kind: 'ambiguous',
|
|
73
|
+
stockMeaning: 'soft',
|
|
74
|
+
note: "stock `--accent` is a hover fill; dowel's `--accent` is the product's own hue. If this project has not migrated yet, it means `--soft`; if it has, it is already right.",
|
|
75
|
+
},
|
|
76
|
+
'accent-foreground': {
|
|
77
|
+
kind: 'ambiguous',
|
|
78
|
+
stockMeaning: 'text',
|
|
79
|
+
note: "stock `--accent-foreground` is ink on a hover fill; dowel has `--on-accent` for ink on the accent itself. Which one this is depends on whether the project has migrated.",
|
|
80
|
+
},
|
|
81
|
+
destructive: { kind: 'token', token: 'bad' },
|
|
82
|
+
'destructive-foreground': { kind: 'token', token: 'on-bad' },
|
|
83
|
+
radius: { kind: 'token', token: 'radius-md', note: 'the control radius.' },
|
|
84
|
+
'chart-1': { kind: 'unmapped', note: 'dowel has no chart palette yet; leave it until the charts version.' },
|
|
85
|
+
'chart-2': { kind: 'unmapped', note: 'dowel has no chart palette yet; leave it until the charts version.' },
|
|
86
|
+
'chart-3': { kind: 'unmapped', note: 'dowel has no chart palette yet; leave it until the charts version.' },
|
|
87
|
+
'chart-4': { kind: 'unmapped', note: 'dowel has no chart palette yet; leave it until the charts version.' },
|
|
88
|
+
'chart-5': { kind: 'unmapped', note: 'dowel has no chart palette yet; leave it until the charts version.' },
|
|
89
|
+
sidebar: { kind: 'token', token: 'raise' },
|
|
90
|
+
'sidebar-foreground': { kind: 'token', token: 'text' },
|
|
91
|
+
'sidebar-primary': { kind: 'token', token: 'accent' },
|
|
92
|
+
'sidebar-primary-foreground': { kind: 'token', token: 'on-accent' },
|
|
93
|
+
'sidebar-accent': { kind: 'token', token: 'soft' },
|
|
94
|
+
'sidebar-accent-foreground': { kind: 'token', token: 'text' },
|
|
95
|
+
'sidebar-border': { kind: 'token', token: 'line' },
|
|
96
|
+
'sidebar-ring': { kind: 'token', token: 'accent' },
|
|
97
|
+
};
|
|
98
|
+
/** The stock names, longest first.
|
|
99
|
+
*
|
|
100
|
+
* Order matters wherever these are matched one after another: `--sidebar` is a
|
|
101
|
+
* prefix of `--sidebar-border`, and trying the short one first would rewrite
|
|
102
|
+
* half of the long one and leave `-border` dangling. */
|
|
103
|
+
export const stockNames = Object.keys(stockTokens).sort((a, b) => b.length - a.length || a.localeCompare(b));
|
|
104
|
+
//# sourceMappingURL=stock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stock.js","sourceRoot":"","sources":["../../src/cli/stock.ts"],"names":[],"mappings":"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"}
|