@stag-build/phonebook 0.1.2 → 0.1.4
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 +10 -1
- package/dist/cli.js +22 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts +21 -2
- package/dist/commands/init.js +33 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/engines/android.d.ts +54 -0
- package/dist/engines/android.js +152 -6
- package/dist/engines/android.js.map +1 -1
- package/dist/engines/ios.d.ts +53 -4
- package/dist/engines/ios.js +142 -27
- package/dist/engines/ios.js.map +1 -1
- package/dist/errors.js +12 -1
- package/dist/errors.js.map +1 -1
- package/dist/ios/snapshotTestClass.d.ts +44 -0
- package/dist/ios/snapshotTestClass.js +115 -0
- package/dist/ios/snapshotTestClass.js.map +1 -1
- package/dist/ios/unrendered.d.ts +38 -0
- package/dist/ios/unrendered.js +92 -0
- package/dist/ios/unrendered.js.map +1 -0
- package/dist/manifest.d.ts +23 -2
- package/dist/manifest.js +58 -0
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/server.d.ts +28 -0
- package/dist/mcp/server.js +232 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/png.d.ts +18 -0
- package/dist/png.js +44 -0
- package/dist/png.js.map +1 -0
- package/dist/scan/android.js +142 -16
- package/dist/scan/android.js.map +1 -1
- package/dist/scan/gaps.d.ts +52 -0
- package/dist/scan/gaps.js +169 -0
- package/dist/scan/gaps.js.map +1 -0
- package/dist/scan/ios.d.ts +44 -0
- package/dist/scan/ios.js +445 -41
- package/dist/scan/ios.js.map +1 -1
- package/dist/scan/scope.d.ts +30 -0
- package/dist/scan/scope.js +208 -0
- package/dist/scan/scope.js.map +1 -0
- package/dist/scan/stats.d.ts +12 -0
- package/dist/scan/stats.js +24 -0
- package/dist/scan/stats.js.map +1 -0
- package/dist/scan/types.d.ts +87 -1
- package/dist/site/build.js +0 -0
- package/dist/site/build.js.map +1 -1
- package/package.json +1 -1
package/dist/scan/android.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readdir, readFile } from 'node:fs/promises';
|
|
2
2
|
import { join, relative } from 'node:path';
|
|
3
3
|
import { previewHints } from './hints.js';
|
|
4
|
+
import { componentGaps } from './gaps.js';
|
|
5
|
+
import { computeStats } from './stats.js';
|
|
4
6
|
/**
|
|
5
7
|
* Regex-based heuristic scanner for Jetpack Compose `@Composable` / `@Preview`
|
|
6
8
|
* functions. Walks each module's `src/main` tree and matches previews to
|
|
@@ -9,6 +11,8 @@ import { previewHints } from './hints.js';
|
|
|
9
11
|
export async function scanAndroid(projectDir, modules) {
|
|
10
12
|
const components = [];
|
|
11
13
|
const orphanPreviews = [];
|
|
14
|
+
const extraLocales = await detectLocales(projectDir, modules);
|
|
15
|
+
const enumTypes = new Set();
|
|
12
16
|
for (const module of modules) {
|
|
13
17
|
const moduleDir = join(projectDir, ...module.split(':').filter(Boolean));
|
|
14
18
|
const srcRoot = join(moduleDir, 'src', 'main');
|
|
@@ -16,6 +20,8 @@ export async function scanAndroid(projectDir, modules) {
|
|
|
16
20
|
for (const file of files) {
|
|
17
21
|
const relFile = relative(projectDir, file);
|
|
18
22
|
const content = await readFile(file, 'utf8');
|
|
23
|
+
for (const enumName of findEnums(content))
|
|
24
|
+
enumTypes.add(enumName);
|
|
19
25
|
const { fileComponents, filePreviews } = scanKotlinFile(content, relFile);
|
|
20
26
|
for (const comp of fileComponents)
|
|
21
27
|
components.push(comp);
|
|
@@ -24,10 +30,25 @@ export async function scanAndroid(projectDir, modules) {
|
|
|
24
30
|
}
|
|
25
31
|
components.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
26
32
|
orphanPreviews.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
33
|
+
for (const component of components) {
|
|
34
|
+
const gaps = componentGaps({
|
|
35
|
+
platform: 'android',
|
|
36
|
+
component: component.name,
|
|
37
|
+
properties: component.properties ?? [],
|
|
38
|
+
previewNames: component.previews.map((p) => p.displayName ?? p.name),
|
|
39
|
+
hasDarkPreview: component.previews.some((p) => p.dark),
|
|
40
|
+
previewText: component.previews.map((p) => p.annotationText ?? '').join('\n'),
|
|
41
|
+
extraLocales,
|
|
42
|
+
enumTypes: [...enumTypes],
|
|
43
|
+
});
|
|
44
|
+
if (gaps.length > 0)
|
|
45
|
+
component.gaps = gaps;
|
|
46
|
+
}
|
|
27
47
|
return {
|
|
28
48
|
platform: 'android',
|
|
29
49
|
components,
|
|
30
50
|
orphanPreviews,
|
|
51
|
+
extraLocales,
|
|
31
52
|
stats: computeStats(components, orphanPreviews),
|
|
32
53
|
};
|
|
33
54
|
}
|
|
@@ -82,11 +103,13 @@ function scanKotlinFile(content, relFile) {
|
|
|
82
103
|
});
|
|
83
104
|
}
|
|
84
105
|
else {
|
|
106
|
+
const properties = findParameters(content, fn.funIndex);
|
|
85
107
|
fileComponents.push({
|
|
86
108
|
name: fn.name,
|
|
87
109
|
file: relFile,
|
|
88
110
|
line: fn.line,
|
|
89
111
|
previews: [],
|
|
112
|
+
...(properties.length > 0 ? { properties } : {}),
|
|
90
113
|
});
|
|
91
114
|
}
|
|
92
115
|
}
|
|
@@ -100,11 +123,13 @@ function scanKotlinFile(content, relFile) {
|
|
|
100
123
|
filePreviews.push(preview);
|
|
101
124
|
}
|
|
102
125
|
else {
|
|
126
|
+
const properties = findParameters(content, fn.funIndex);
|
|
103
127
|
fileComponents.push({
|
|
104
128
|
name: fn.name,
|
|
105
129
|
file: relFile,
|
|
106
130
|
line: fn.line,
|
|
107
131
|
previews: [preview],
|
|
132
|
+
...(properties.length > 0 ? { properties } : {}),
|
|
108
133
|
});
|
|
109
134
|
}
|
|
110
135
|
}
|
|
@@ -126,6 +151,123 @@ function bestPrefixMatch(name, components) {
|
|
|
126
151
|
* the block of annotations (e.g. `@Composable`, `@Preview(...)`) found within
|
|
127
152
|
* roughly 5 lines above the `fun` keyword.
|
|
128
153
|
*/
|
|
154
|
+
/**
|
|
155
|
+
* Parameters of the composable whose `fun` keyword starts at `funIndex`.
|
|
156
|
+
*
|
|
157
|
+
* A composable's parameters are its states: a `Boolean` has two values, a
|
|
158
|
+
* nullable can be absent, a `List` can be empty. `Modifier` is excluded because
|
|
159
|
+
* it configures placement rather than describing a state.
|
|
160
|
+
*/
|
|
161
|
+
function findParameters(content, funIndex) {
|
|
162
|
+
const open = content.indexOf('(', funIndex);
|
|
163
|
+
if (open === -1)
|
|
164
|
+
return [];
|
|
165
|
+
let depth = 0;
|
|
166
|
+
let close = -1;
|
|
167
|
+
const cap = Math.min(content.length, open + 4000);
|
|
168
|
+
for (let i = open; i < cap; i++) {
|
|
169
|
+
if (content[i] === '(')
|
|
170
|
+
depth++;
|
|
171
|
+
else if (content[i] === ')') {
|
|
172
|
+
depth--;
|
|
173
|
+
if (depth === 0) {
|
|
174
|
+
close = i;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (close === -1)
|
|
180
|
+
return [];
|
|
181
|
+
const properties = [];
|
|
182
|
+
for (const raw of splitTopLevel(content.slice(open + 1, close))) {
|
|
183
|
+
const match = raw.match(/^\s*(?:@\w+(?:\([^)]*\))?\s+)*(\w+)\s*:\s*([^=]+)/);
|
|
184
|
+
if (!match)
|
|
185
|
+
continue;
|
|
186
|
+
const name = match[1];
|
|
187
|
+
const type = match[2].trim();
|
|
188
|
+
if (type.startsWith('Modifier'))
|
|
189
|
+
continue;
|
|
190
|
+
properties.push({ name, type, kind: classifyKotlinType(type) });
|
|
191
|
+
}
|
|
192
|
+
return properties;
|
|
193
|
+
}
|
|
194
|
+
/** Enum type names declared in this file. */
|
|
195
|
+
function findEnums(content) {
|
|
196
|
+
const results = [];
|
|
197
|
+
const regex = /\benum\s+class\s+([A-Z]\w*)/g;
|
|
198
|
+
let match;
|
|
199
|
+
while ((match = regex.exec(content)) !== null)
|
|
200
|
+
results.push(match[1]);
|
|
201
|
+
return results;
|
|
202
|
+
}
|
|
203
|
+
/** Splits a parameter list on commas that are not inside brackets. */
|
|
204
|
+
function splitTopLevel(text) {
|
|
205
|
+
const parts = [];
|
|
206
|
+
let depth = 0;
|
|
207
|
+
let current = '';
|
|
208
|
+
for (const char of text) {
|
|
209
|
+
if (char === '<' || char === '(' || char === '[')
|
|
210
|
+
depth++;
|
|
211
|
+
else if (char === '>' || char === ')' || char === ']')
|
|
212
|
+
depth--;
|
|
213
|
+
if (char === ',' && depth === 0) {
|
|
214
|
+
parts.push(current);
|
|
215
|
+
current = '';
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
current += char;
|
|
219
|
+
}
|
|
220
|
+
if (current.trim())
|
|
221
|
+
parts.push(current);
|
|
222
|
+
return parts;
|
|
223
|
+
}
|
|
224
|
+
/** Types whose values are a spectrum rather than a set of states worth previewing. */
|
|
225
|
+
const SCALAR_TYPES = new Set([
|
|
226
|
+
'String', 'Int', 'Long', 'Float', 'Double', 'Char', 'Dp', 'TextUnit', 'Color',
|
|
227
|
+
'Any', 'Unit',
|
|
228
|
+
]);
|
|
229
|
+
function classifyKotlinType(type) {
|
|
230
|
+
const bare = type.replace(/\s+/g, '');
|
|
231
|
+
if (bare.endsWith('?'))
|
|
232
|
+
return 'optional';
|
|
233
|
+
if (/^(List|Set|Array|Collection|Iterable|Map)</.test(bare))
|
|
234
|
+
return 'collection';
|
|
235
|
+
if (bare === 'Boolean')
|
|
236
|
+
return 'bool';
|
|
237
|
+
if (bare.includes('->'))
|
|
238
|
+
return 'other';
|
|
239
|
+
if (SCALAR_TYPES.has(bare))
|
|
240
|
+
return 'other';
|
|
241
|
+
if (/^[A-Z]\w*$/.test(bare))
|
|
242
|
+
return 'enum-like';
|
|
243
|
+
return 'other';
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Locales the project ships, from `res/values-<code>` resource directories.
|
|
247
|
+
* The unqualified `values` directory is the default language, not a locale.
|
|
248
|
+
*/
|
|
249
|
+
async function detectLocales(projectDir, modules) {
|
|
250
|
+
const found = new Set();
|
|
251
|
+
for (const module of modules) {
|
|
252
|
+
const moduleDir = join(projectDir, ...module.split(':').filter(Boolean));
|
|
253
|
+
const resDir = join(moduleDir, 'src', 'main', 'res');
|
|
254
|
+
let entries;
|
|
255
|
+
try {
|
|
256
|
+
entries = await readdir(resDir, { withFileTypes: true });
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
for (const entry of entries) {
|
|
262
|
+
if (!entry.isDirectory())
|
|
263
|
+
continue;
|
|
264
|
+
const match = entry.name.match(/^values-([a-z]{2}(?:-r[A-Z]{2})?)$/);
|
|
265
|
+
if (match)
|
|
266
|
+
found.add(match[1].replace('-r', '-'));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return [...found].sort();
|
|
270
|
+
}
|
|
129
271
|
function findAnnotatedFunctions(content) {
|
|
130
272
|
const results = [];
|
|
131
273
|
const funRegex = /\bfun\s+([A-Z]\w*)\s*\(/g;
|
|
@@ -182,22 +324,6 @@ function matchPreviewsToComponents(previews, components, orphanPreviews) {
|
|
|
182
324
|
}
|
|
183
325
|
}
|
|
184
326
|
}
|
|
185
|
-
function computeStats(components, orphanPreviews) {
|
|
186
|
-
const withPreview = components.filter((c) => c.previews.length > 0).length;
|
|
187
|
-
const withDarkPreview = components.filter((c) => c.previews.some((p) => p.dark)).length;
|
|
188
|
-
const totalPreviews = components.reduce((sum, c) => sum + c.previews.length, 0) + orphanPreviews.length;
|
|
189
|
-
const allPreviews = [...components.flatMap((c) => c.previews), ...orphanPreviews];
|
|
190
|
-
const hintCount = allPreviews.reduce((sum, p) => sum + (p.hints?.length ?? 0), 0);
|
|
191
|
-
const selfPreviewed = components.filter((c) => c.previews.some((p) => p.name === c.name && p.line === c.line)).length;
|
|
192
|
-
return {
|
|
193
|
-
components: components.length,
|
|
194
|
-
withPreview,
|
|
195
|
-
withDarkPreview,
|
|
196
|
-
totalPreviews,
|
|
197
|
-
hintCount,
|
|
198
|
-
selfPreviewed,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
327
|
async function walkKotlinFiles(dir) {
|
|
202
328
|
const results = [];
|
|
203
329
|
let entries;
|
package/dist/scan/android.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"android.js","sourceRoot":"","sources":["../../src/scan/android.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"android.js","sourceRoot":"","sources":["../../src/scan/android.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAA6C,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,OAAiB;IACrE,MAAM,UAAU,GAAuB,EAAE,CAAC;IAC1C,MAAM,cAAc,GAAqB,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;QAE7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7C,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,OAAO,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAEnE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAE1E,KAAK,MAAM,IAAI,IAAI,cAAc;gBAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEzD,yBAAyB,CAAC,YAAY,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3E,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAE/E,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,aAAa,CAAC;YACzB,QAAQ,EAAE,SAAS;YACnB,SAAS,EAAE,SAAS,CAAC,IAAI;YACzB,UAAU,EAAE,SAAS,CAAC,UAAU,IAAI,EAAE;YACtC,YAAY,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;YACpE,cAAc,EAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACtD,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7E,YAAY;YACZ,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC;SAC1B,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;IAC7C,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,UAAU;QACV,cAAc;QACd,YAAY;QACZ,KAAK,EAAE,YAAY,CAAC,UAAU,EAAE,cAAc,CAAC;KAChD,CAAC;AACJ,CAAC;AAWD,SAAS,cAAc,CACrB,OAAe,EACf,OAAe;IAEf,MAAM,SAAS,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAElD,MAAM,cAAc,GAAuB,EAAE,CAAC;IAC9C,MAAM,YAAY,GAAqB,EAAE,CAAC;IAC1C,MAAM,kBAAkB,GAAmD,EAAE,CAAC;IAE9E,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;QAC1D,IAAI,CAAC,YAAY;YAAE,SAAS;QAE5B,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAC/E,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,6EAA6E;YAC7E,uEAAuE;YACvE,4EAA4E;YAC5E,kBAAkB;YAClB,IAAI,WAA+B,CAAC;YACpC,IAAI,IAAI,GAAG,KAAK,CAAC;YACjB,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;gBACrD,IAAI,SAAS,IAAI,CAAC,WAAW;oBAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC1D,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,IAAI,GAAG,IAAI,CAAC;YAClD,CAAC;YACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;gBAAE,IAAI,GAAG,IAAI,CAAC;YAE/C,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClE,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,YAAY,CAAC;gBACzB,QAAQ,EAAE,SAAS;gBACnB,YAAY,EAAE,EAAE,CAAC,IAAI;gBACrB,WAAW;gBACX,cAAc;gBACd,QAAQ;aACT,CAAC,CAAC;YAEH,kBAAkB,CAAC,IAAI,CAAC;gBACtB,EAAE;gBACF,OAAO,EAAE;oBACP,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvC,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,IAAI;oBACJ,cAAc;oBACd,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvC;aACF,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,CAAC;gBAClB,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,QAAQ,EAAE,EAAE;gBACZ,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,6EAA6E;IAC7E,gFAAgF;IAChF,wDAAwD;IACxD,KAAK,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,kBAAkB,EAAE,CAAC;QACjD,MAAM,aAAa,GAAG,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC/D,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,CAAC;gBAClB,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,QAAQ,EAAE,CAAC,OAAO,CAAC;gBACnB,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAC1C,CAAC;AAED,gFAAgF;AAChF,SAAS,eAAe,CAAC,IAAY,EAAE,UAA8B;IACnE,IAAI,IAAkC,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,GAAG,IAAI,CAAC;QAChE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,OAAe,EAAE,QAAgB;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;aAC3B,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,KAAK,GAAG,CAAC,CAAC;gBACV,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAE5B,MAAM,UAAU,GAAwB,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC7E,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAC1C,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,6CAA6C;AAC7C,SAAS,SAAS,CAAC,OAAe;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,8BAA8B,CAAC;IAC7C,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;aACrD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;QAC/D,IAAI,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO,GAAG,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QACD,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sFAAsF;AACtF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO;IAC7E,KAAK,EAAE,MAAM;CACd,CAAC,CAAC;AAEH,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IAC1C,IAAI,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IACjF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAC3C,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IAChD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,aAAa,CAAC,UAAkB,EAAE,OAAiB;IAChE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACrD,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YACnC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACrE,IAAI,KAAK;gBAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC7C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,0BAA0B,CAAC;IAC5C,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;QAC7B,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAE7C,gEAAgE;QAChE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5E,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,KAAa;IAClD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,IAAI,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;8FAC8F;AAC9F,SAAS,eAAe,CAAC,OAAe,EAAE,QAAgB;IACxD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAClD,IAAI,UAAU,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAC5E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,SAAS,yBAAyB,CAChC,QAA0B,EAC1B,UAA8B,EAC9B,cAAgC;IAEhC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,IAAkC,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM;oBAAE,IAAI,GAAG,IAAI,CAAC;YAChE,CAAC;QACH,CAAC;QACD,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;AACH,CAAC;AAGD,KAAK,UAAU,eAAe,CAAC,GAAW;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;gBAAE,SAAS;YACrC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage gaps: what a component is *missing*, as opposed to what an existing
|
|
3
|
+
* preview got wrong.
|
|
4
|
+
*
|
|
5
|
+
* `hints.ts` answers "this preview's name promises something its annotation
|
|
6
|
+
* doesn't declare". That only ever fires on a preview that already exists, so a
|
|
7
|
+
* component with no previews at all — or one preview standing in for four
|
|
8
|
+
* states — produces no hints and reads as fine.
|
|
9
|
+
*
|
|
10
|
+
* This module answers the other half: given what a component actually is (its
|
|
11
|
+
* stored properties or parameters) and what the project supports (its locales),
|
|
12
|
+
* which previews *should* exist and don't. The output is guidance for an agent
|
|
13
|
+
* to act on, not a verdict — Phonebook renders previews, it never writes them,
|
|
14
|
+
* and whether a state is worth covering is a judgment the agent makes with the
|
|
15
|
+
* component's source in front of it.
|
|
16
|
+
*/
|
|
17
|
+
export type PropertyKind = 'bool' | 'optional' | 'collection' | 'enum-like' | 'other';
|
|
18
|
+
export interface ComponentProperty {
|
|
19
|
+
name: string;
|
|
20
|
+
/** Type as written in source, e.g. "Bool", "[Status]", "Status?". */
|
|
21
|
+
type: string;
|
|
22
|
+
kind: PropertyKind;
|
|
23
|
+
}
|
|
24
|
+
export interface CoverageGap {
|
|
25
|
+
rule: string;
|
|
26
|
+
severity: 'warning' | 'info';
|
|
27
|
+
message: string;
|
|
28
|
+
suggestion: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CoverageGapInput {
|
|
31
|
+
platform: 'android' | 'ios';
|
|
32
|
+
component: string;
|
|
33
|
+
properties: ComponentProperty[];
|
|
34
|
+
/** Display names of the previews already covering this component. */
|
|
35
|
+
previewNames: string[];
|
|
36
|
+
/** True when at least one existing preview declares a dark configuration. */
|
|
37
|
+
hasDarkPreview: boolean;
|
|
38
|
+
/** Raw text of every existing preview for this component, for "already declares it" checks. */
|
|
39
|
+
previewText: string;
|
|
40
|
+
/** Locales the project ships, beyond its development language. Empty when unlocalized. */
|
|
41
|
+
extraLocales: string[];
|
|
42
|
+
/** Enum types declared anywhere in the project. A property of one of these
|
|
43
|
+
* has a known, finite set of states; a property of any other named type is
|
|
44
|
+
* left alone rather than guessed at. */
|
|
45
|
+
enumTypes?: string[];
|
|
46
|
+
/** Types the component reads via `@Environment(X.self)` (iOS only). */
|
|
47
|
+
environmentTypes?: string[];
|
|
48
|
+
/** Everything the previews pass to `.environment(...)`, including through any
|
|
49
|
+
* project helper they call. A type named anywhere in here is supplied. */
|
|
50
|
+
environmentProvided?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function componentGaps(input: CoverageGapInput): CoverageGap[];
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage gaps: what a component is *missing*, as opposed to what an existing
|
|
3
|
+
* preview got wrong.
|
|
4
|
+
*
|
|
5
|
+
* `hints.ts` answers "this preview's name promises something its annotation
|
|
6
|
+
* doesn't declare". That only ever fires on a preview that already exists, so a
|
|
7
|
+
* component with no previews at all — or one preview standing in for four
|
|
8
|
+
* states — produces no hints and reads as fine.
|
|
9
|
+
*
|
|
10
|
+
* This module answers the other half: given what a component actually is (its
|
|
11
|
+
* stored properties or parameters) and what the project supports (its locales),
|
|
12
|
+
* which previews *should* exist and don't. The output is guidance for an agent
|
|
13
|
+
* to act on, not a verdict — Phonebook renders previews, it never writes them,
|
|
14
|
+
* and whether a state is worth covering is a judgment the agent makes with the
|
|
15
|
+
* component's source in front of it.
|
|
16
|
+
*/
|
|
17
|
+
/** A state name the previews already mention, however it is spelled. */
|
|
18
|
+
function covers(input, ...words) {
|
|
19
|
+
const haystack = [...input.previewNames, input.previewText].join(' ').toLowerCase();
|
|
20
|
+
return words.some((w) => haystack.includes(w.toLowerCase()));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* True when some preview passes *this* property in its absent or empty form.
|
|
24
|
+
*
|
|
25
|
+
* Checked against the property by name rather than by looking for "nil"
|
|
26
|
+
* anywhere: a preview that passes `author: nil` covers the absent author, and
|
|
27
|
+
* says nothing about an empty `replies` in the same call.
|
|
28
|
+
*/
|
|
29
|
+
function coversPropertyAs(input, property, forms) {
|
|
30
|
+
const pattern = new RegExp(`\\b${property}\\s*[:=]\\s*(?:${forms.source})`, 'i');
|
|
31
|
+
return pattern.test(input.previewText);
|
|
32
|
+
}
|
|
33
|
+
const ABSENT_FORMS = /nil|null|\.none|None/;
|
|
34
|
+
const EMPTY_FORMS = /\[\s*\]|emptyList\(\)|emptySet\(\)|\.init\(\)|listOf\(\)|setOf\(\)/;
|
|
35
|
+
function stateCount(input) {
|
|
36
|
+
// A component with one preview has one state covered no matter what that
|
|
37
|
+
// preview is called; "Default" is not two states.
|
|
38
|
+
return new Set(input.previewNames.map((n) => n.toLowerCase())).size;
|
|
39
|
+
}
|
|
40
|
+
const IOS_ENV = {
|
|
41
|
+
dark: '.preferredColorScheme(.dark)',
|
|
42
|
+
dynamicType: '.dynamicTypeSize(.accessibility3)',
|
|
43
|
+
locale: (code) => `.environment(\\.locale, .init(identifier: "${code}"))`,
|
|
44
|
+
};
|
|
45
|
+
const ANDROID_ENV = {
|
|
46
|
+
dark: '@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)',
|
|
47
|
+
dynamicType: '@Preview(fontScale = 1.5f)',
|
|
48
|
+
locale: (code) => `@Preview(locale = "${code}")`,
|
|
49
|
+
};
|
|
50
|
+
export function componentGaps(input) {
|
|
51
|
+
const gaps = [];
|
|
52
|
+
const env = input.platform === 'ios' ? IOS_ENV : ANDROID_ENV;
|
|
53
|
+
const previewCount = input.previewNames.length;
|
|
54
|
+
if (previewCount === 0) {
|
|
55
|
+
gaps.push({
|
|
56
|
+
rule: 'no-preview',
|
|
57
|
+
severity: 'warning',
|
|
58
|
+
message: `"${input.component}" has no preview, so it never reaches the gallery.`,
|
|
59
|
+
suggestion: 'add one preview per meaningful state; call get_preview_guidance for the template',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (const prop of input.properties) {
|
|
63
|
+
if (prop.kind === 'bool') {
|
|
64
|
+
const both = stateCount(input) >= 2;
|
|
65
|
+
if (!both) {
|
|
66
|
+
gaps.push({
|
|
67
|
+
rule: 'state-bool',
|
|
68
|
+
severity: 'warning',
|
|
69
|
+
message: `"${input.component}" takes ${prop.name}: ${prop.type}, which has two states, but ${previewCount === 0 ? 'no preview covers either' : 'only one preview exists'}.`,
|
|
70
|
+
suggestion: `one preview per value of ${prop.name}, named "${input.component}/<State>"`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (prop.kind === 'optional') {
|
|
76
|
+
const covered = coversPropertyAs(input, prop.name, ABSENT_FORMS) ||
|
|
77
|
+
covers(input, 'empty', 'none', 'missing', 'placeholder');
|
|
78
|
+
if (!covered) {
|
|
79
|
+
gaps.push({
|
|
80
|
+
rule: 'state-optional',
|
|
81
|
+
severity: 'warning',
|
|
82
|
+
message: `"${input.component}" takes ${prop.name}: ${prop.type}, which can be absent, and no preview covers the absent case.`,
|
|
83
|
+
suggestion: `a preview with ${prop.name} set to nil, named "${input.component}/Empty"`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (prop.kind === 'collection') {
|
|
89
|
+
const covered = coversPropertyAs(input, prop.name, EMPTY_FORMS) || covers(input, 'empty', 'none', 'zero');
|
|
90
|
+
if (!covered) {
|
|
91
|
+
gaps.push({
|
|
92
|
+
rule: 'state-collection',
|
|
93
|
+
severity: 'warning',
|
|
94
|
+
message: `"${input.component}" takes ${prop.name}: ${prop.type}, which can be empty, and no preview covers the empty case.`,
|
|
95
|
+
suggestion: `a preview with ${prop.name} empty, named "${input.component}/Empty"`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (prop.kind === 'enum-like') {
|
|
101
|
+
// Only when the project actually declares it as an enum. Every other
|
|
102
|
+
// named type — a class, a struct, a protocol — has no finite set of
|
|
103
|
+
// states to enumerate, and guessing at one would fill the report with
|
|
104
|
+
// work that does not exist.
|
|
105
|
+
const declared = (input.enumTypes ?? []).includes(prop.type.replace(/\s+/g, ''));
|
|
106
|
+
if (declared && stateCount(input) < 2) {
|
|
107
|
+
gaps.push({
|
|
108
|
+
rule: 'state-enum',
|
|
109
|
+
severity: 'warning',
|
|
110
|
+
message: `"${input.component}" takes ${prop.name}: ${prop.type}, an enum, and ${previewCount === 0 ? 'no preview covers any case' : 'only one preview exists'}.`,
|
|
111
|
+
suggestion: `one preview per case of ${prop.type}, named "${input.component}/<Case>"`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Before every configuration rule below, because those describe a preview
|
|
117
|
+
// that renders the wrong thing and this one describes a preview that does not
|
|
118
|
+
// render at all. SwiftUI has no default for an @Observable read out of the
|
|
119
|
+
// environment: the property's getter traps the moment the body reads it, so a
|
|
120
|
+
// preview missing one is not thin coverage, it is a crash with a name.
|
|
121
|
+
//
|
|
122
|
+
// Direct reads only. A view that renders a subview with environment needs of
|
|
123
|
+
// its own still traps, and finding that needs the call graph rather than the
|
|
124
|
+
// one struct — worth doing, not done here, and a rule that catches the direct
|
|
125
|
+
// case is already the difference between a preview that runs and one that
|
|
126
|
+
// does not.
|
|
127
|
+
if (input.platform === 'ios' && previewCount > 0) {
|
|
128
|
+
const provided = input.environmentProvided ?? '';
|
|
129
|
+
for (const type of input.environmentTypes ?? []) {
|
|
130
|
+
if (provided.includes(type))
|
|
131
|
+
continue;
|
|
132
|
+
gaps.push({
|
|
133
|
+
rule: 'env-missing',
|
|
134
|
+
severity: 'warning',
|
|
135
|
+
message: `"${input.component}" reads @Environment(${type}.self) and no preview supplies one, so every preview of it traps at render.`,
|
|
136
|
+
suggestion: `pass ${type} to .environment(...) in each preview — an unsatisfied @Environment traps rather than defaulting`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (previewCount > 0 && !input.hasDarkPreview) {
|
|
141
|
+
gaps.push({
|
|
142
|
+
rule: 'theme-dark',
|
|
143
|
+
severity: 'warning',
|
|
144
|
+
message: `"${input.component}" has no dark-theme preview, so a dark-mode regression cannot show up in the gallery.`,
|
|
145
|
+
suggestion: env.dark,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (previewCount > 0 && !covers(input, 'dynamictypesize', 'fontscale', 'sizecategory', 'accessibility')) {
|
|
149
|
+
gaps.push({
|
|
150
|
+
rule: 'dynamic-type',
|
|
151
|
+
severity: 'info',
|
|
152
|
+
message: `"${input.component}" has no large-text preview, the configuration that most often breaks a layout.`,
|
|
153
|
+
suggestion: env.dynamicType,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// Silent on an unlocalized project: telling every repository to cover locales
|
|
157
|
+
// it does not ship would make the report noise rather than a to-do list.
|
|
158
|
+
if (previewCount > 0 && input.extraLocales.length > 0 && !covers(input, 'locale', 'environment(\\.locale', 'rtl')) {
|
|
159
|
+
const sample = input.extraLocales[0];
|
|
160
|
+
gaps.push({
|
|
161
|
+
rule: 'localization',
|
|
162
|
+
severity: 'info',
|
|
163
|
+
message: `The project ships ${input.extraLocales.length} localization${input.extraLocales.length === 1 ? '' : 's'} (${input.extraLocales.slice(0, 4).join(', ')}${input.extraLocales.length > 4 ? ', …' : ''}) and "${input.component}" is previewed in the development language only.`,
|
|
164
|
+
suggestion: env.locale(sample),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return gaps;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=gaps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaps.js","sourceRoot":"","sources":["../../src/scan/gaps.ts"],"names":[],"mappings":"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"}
|
package/dist/scan/ios.d.ts
CHANGED
|
@@ -5,3 +5,47 @@ import type { CoverageReport } from './types.js';
|
|
|
5
5
|
* matches previews to components by file + name heuristics.
|
|
6
6
|
*/
|
|
7
7
|
export declare function scanIos(projectDir: string): Promise<CoverageReport>;
|
|
8
|
+
/**
|
|
9
|
+
* True when `source` renders `component` — the name followed by an opening
|
|
10
|
+
* parenthesis, which is how a SwiftUI view is instantiated.
|
|
11
|
+
*
|
|
12
|
+
* A bare mention is not a render: `StatusRowView.Context` names the type
|
|
13
|
+
* without showing anything, and a comment saying "like AvatarView" shows even
|
|
14
|
+
* less. Requiring the parenthesis costs the zero-argument spelling nothing —
|
|
15
|
+
* `RowList()` still matches — and keeps the answer to something a reader
|
|
16
|
+
* would agree with.
|
|
17
|
+
*/
|
|
18
|
+
export declare function rendersComponent(source: string, component: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Where `source` renders `component` behind a condition, when every place it
|
|
21
|
+
* does is behind one — so whether it appears depends on state the caller sets.
|
|
22
|
+
*
|
|
23
|
+
* This is what separates a parent that shows a child from a parent that might.
|
|
24
|
+
* IceCubes' StatusRowView renders StatusRowDetailView only `if isFocused`, and
|
|
25
|
+
* its one preview builds a timeline row, where nothing is focused: the preview
|
|
26
|
+
* exists, and the detail view is not in it. Treating that as coverage is how a
|
|
27
|
+
* redesigned view reaches no screenshot and no one is told.
|
|
28
|
+
*
|
|
29
|
+
* The brace stack is the whole trick — a frame remembers the text that opened
|
|
30
|
+
* it, and that text is the condition when it reads as one. No Swift is
|
|
31
|
+
* evaluated and none needs to be: the question is whether a render is guarded
|
|
32
|
+
* and behind what, not which way the guard goes.
|
|
33
|
+
*
|
|
34
|
+
* Returns the innermost condition around the first guarded render. A component
|
|
35
|
+
* that renders the same child behind two different conditions is rare, and the
|
|
36
|
+
* answer to the first is the answer to both: nothing shows it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function onlyRendersConditionally(source: string, component: string): {
|
|
39
|
+
guard: string;
|
|
40
|
+
line: number;
|
|
41
|
+
} | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Which of `known` this source renders — the same rule as `rendersComponent`,
|
|
44
|
+
* asked once for the whole set.
|
|
45
|
+
*
|
|
46
|
+
* Reading the names out of the source and intersecting beats testing every
|
|
47
|
+
* known component against it: a project has hundreds of components and a scan
|
|
48
|
+
* asks this of every preview body, and the regex-per-name version is that
|
|
49
|
+
* product.
|
|
50
|
+
*/
|
|
51
|
+
export declare function componentsNamedIn(source: string, known: ReadonlySet<string>): string[];
|