@ingcreators/annot-product-docs 0.2.0 → 0.3.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/dist/index.js CHANGED
@@ -1,15 +1,432 @@
1
- import { mkdir as e, readFile as t, readdir as n, writeFile as r } from "node:fs/promises";
2
- import { dirname as i, join as a, relative as o, resolve as s } from "node:path";
3
- import { test as c } from "@ingcreators/annot-playwright";
4
- import l from "js-yaml";
5
- import u from "remark-frontmatter";
6
- import d from "remark-mdx";
7
- import f from "remark-parse";
8
- import { unified as p } from "unified";
9
- import { visit as m } from "unist-util-visit";
10
- import { z as h } from "zod";
1
+ import { annotSourceResolvers as e, test as t } from "@ingcreators/annot-playwright";
2
+ import { mkdir as n, readFile as r, readdir as i, writeFile as a } from "node:fs/promises";
3
+ import o from "js-yaml";
4
+ import s from "remark-frontmatter";
5
+ import c from "remark-mdx";
6
+ import l from "remark-parse";
7
+ import { unified as u } from "unified";
8
+ import { visit as d } from "unist-util-visit";
9
+ import { z as f } from "zod";
10
+ import { dirname as p, isAbsolute as ee, join as te, relative as m, resolve as h } from "node:path";
11
+ import { bboxAnnotationsToSvg as g } from "@ingcreators/annot-annotator";
12
+ //#region src/config.ts
13
+ var ne = f.enum([
14
+ "cover",
15
+ "history",
16
+ "list",
17
+ "screen",
18
+ "reference"
19
+ ]), re = f.object({
20
+ book: f.string().optional(),
21
+ sheet: f.string().optional(),
22
+ sheets: f.record(f.string(), f.string()).optional(),
23
+ role: ne.optional(),
24
+ order: f.number().optional()
25
+ }).strict().refine((e) => !(e.sheet && e.sheets), "Specify either `xlsx.sheet` (single sheet) or `xlsx.sheets` (multi-sheet), not both."), ie = f.record(f.string(), f.unknown()), _ = f.object({
26
+ id: f.string().min(1, "`annot.id` is required."),
27
+ title: f.string().optional(),
28
+ purpose: f.string().optional(),
29
+ meta: ie.optional(),
30
+ xlsx: re.optional()
31
+ }).strict(), ae = f.object({
32
+ template: f.string().optional(),
33
+ templateSheets: f.object({
34
+ cover: f.string().optional(),
35
+ history: f.string().optional(),
36
+ list: f.string().optional(),
37
+ screen: f.string().optional(),
38
+ reference: f.string().optional()
39
+ }).strict().optional()
40
+ }).strict(), v = f.object({
41
+ meta: f.record(f.string(), f.unknown()).optional(),
42
+ xlsx: f.object({
43
+ defaultBook: f.string().optional(),
44
+ books: f.record(f.string(), ae).optional()
45
+ }).strict().optional()
46
+ }).strict();
47
+ function oe(e) {
48
+ let t = v.safeParse(e);
49
+ if (!t.success) {
50
+ let e = t.error.issues.map((e) => ` - ${e.path.length ? e.path.join(".") + ": " : ""}${e.message}`).join("\n");
51
+ throw Error(`Invalid \`annot-docs.config.ts\`:\n${e}`);
52
+ }
53
+ return t.data;
54
+ }
55
+ function se(e) {
56
+ return (e.xlsx?.role ?? "screen") === "screen";
57
+ }
58
+ //#endregion
59
+ //#region src/mdx.ts
60
+ var y = "annot:snapshot", ce = "/annot:snapshot", b = "annot:attributes", le = "/annot:attributes", ue = /^\s*\/\*\s*([^\s*]+)\s*([\s\S]*?)\*\/\s*$/;
61
+ async function x(e) {
62
+ return S(await r(e, "utf8"), { filePath: e });
63
+ }
64
+ function S(e, t = {}) {
65
+ let n = u().use(l).use(s, ["yaml"]).use(c).parse(e), r = de(n, t.filePath);
66
+ if (!r) return null;
67
+ let i = [], a = [], o = [], f = [], p = {};
68
+ return d(n, (t) => {
69
+ switch (t.type) {
70
+ case "mdxJsxFlowElement":
71
+ case "mdxJsxTextElement":
72
+ pe(t, e, {
73
+ screens: i,
74
+ transitions: a,
75
+ history: o,
76
+ screenLists: f
77
+ });
78
+ return;
79
+ case "mdxFlowExpression":
80
+ case "mdxTextExpression":
81
+ ye(t, p);
82
+ return;
83
+ }
84
+ }), {
85
+ frontmatter: r,
86
+ screens: i,
87
+ transitions: a,
88
+ history: o,
89
+ screenLists: f,
90
+ commentBlocks: p,
91
+ source: e
92
+ };
93
+ }
94
+ function de(e, t) {
95
+ let n = e.children.find((e) => e.type === "yaml");
96
+ if (!n || !n.value) return null;
97
+ let r = o.load(n.value);
98
+ if (!r || typeof r != "object") return null;
99
+ let i = r.annot;
100
+ if (!i || typeof i != "object") return null;
101
+ let a = _.safeParse(i);
102
+ if (!a.success) {
103
+ let e = t ? ` in ${t}` : "";
104
+ throw Error(`Invalid \`annot:\` frontmatter${e}:\n${fe(a.error)}`);
105
+ }
106
+ return a.data;
107
+ }
108
+ function fe(e) {
109
+ return e.issues.map((e) => ` - ${e.path.length ? e.path.join(".") + ": " : ""}${e.message}`).join("\n");
110
+ }
111
+ function pe(e, t, n) {
112
+ let r = e;
113
+ switch (r.name) {
114
+ case "Screen":
115
+ n.screens.push(me(r, t));
116
+ return;
117
+ case "Transition":
118
+ n.transitions.push(ge(r, t));
119
+ return;
120
+ case "HistoryEntry":
121
+ n.history.push(_e(r, t));
122
+ return;
123
+ case "ScreenList":
124
+ n.screenLists.push(ve(r));
125
+ return;
126
+ }
127
+ }
128
+ function me(e, t) {
129
+ let n = C(e), r = [], i = (n) => {
130
+ let a = n;
131
+ if (a.name === "Overlay") {
132
+ r.push(he(a, t));
133
+ return;
134
+ }
135
+ if (!(a.name === "Screen" && a !== e)) for (let e of a.children ?? []) i(e);
136
+ };
137
+ for (let t of e.children ?? []) i(t);
138
+ let a = w(n.id);
139
+ if (!a) throw Error("<Screen> requires an `id` prop.");
140
+ return {
141
+ id: a,
142
+ src: w(n.src),
143
+ overlays: r
144
+ };
145
+ }
146
+ function he(e, t) {
147
+ let n = C(e), r = n.match;
148
+ if (!T(r)) throw Error("<Overlay> requires a `match` prop with at least `{ role, name }`.");
149
+ return {
150
+ match: r,
151
+ intent: w(n.intent),
152
+ number: xe(n.number),
153
+ body: E(e, t)
154
+ };
155
+ }
156
+ function ge(e, t) {
157
+ let n = C(e), r = n.trigger;
158
+ if (!T(r)) throw Error("<Transition> requires a `trigger` prop with at least `{ role, name }`.");
159
+ return {
160
+ trigger: r,
161
+ on: w(n.on),
162
+ to: w(n.to),
163
+ body: E(e, t)
164
+ };
165
+ }
166
+ function _e(e, t) {
167
+ let n = C(e), r = w(n.version) ?? "", i = w(n.date) ?? "", a = w(n.author) ?? "";
168
+ if (!r || !i) throw Error("<HistoryEntry> requires `version` and `date` props.");
169
+ return {
170
+ version: r,
171
+ date: i,
172
+ author: a,
173
+ body: E(e, t)
174
+ };
175
+ }
176
+ function ve(e) {
177
+ let t = C(e);
178
+ return {
179
+ book: w(t.book),
180
+ sort: w(t.sort)
181
+ };
182
+ }
183
+ function ye(e, t) {
184
+ let n = e.value;
185
+ if (typeof n != "string") return;
186
+ let r = n.match(ue);
187
+ if (!r) return;
188
+ let i = (r[1] ?? "").trim(), a = (r[2] ?? "").trim();
189
+ switch (i) {
190
+ case y:
191
+ t.snapshot = a;
192
+ return;
193
+ case b:
194
+ t.attributes = a;
195
+ return;
196
+ case ce:
197
+ case le: return;
198
+ }
199
+ }
200
+ function C(e) {
201
+ let t = {};
202
+ for (let n of e.attributes ?? []) {
203
+ let e = n;
204
+ if (e.type !== "mdxJsxAttribute" || !e.name) continue;
205
+ if (e.value === null || e.value === void 0) {
206
+ t[e.name] = !0;
207
+ continue;
208
+ }
209
+ if (typeof e.value == "string") {
210
+ t[e.name] = e.value;
211
+ continue;
212
+ }
213
+ let r = e.value;
214
+ r.type === "mdxJsxAttributeValueExpression" && typeof r.value == "string" && (t[e.name] = be(r.value));
215
+ }
216
+ return t;
217
+ }
218
+ function be(e) {
219
+ let t = e.trim();
220
+ if (t) {
221
+ if (t === "true") return !0;
222
+ if (t === "false") return !1;
223
+ if (t === "null") return null;
224
+ if (/^-?\d+(\.\d+)?$/.test(t)) return Number.parseFloat(t);
225
+ if (t.startsWith("\"") && t.endsWith("\"")) try {
226
+ return JSON.parse(t);
227
+ } catch {
228
+ return t.slice(1, -1);
229
+ }
230
+ if (t.startsWith("'") && t.endsWith("'")) {
231
+ let e = t.slice(1, -1), n = e.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
232
+ try {
233
+ return JSON.parse(`"${n}"`);
234
+ } catch {
235
+ return e;
236
+ }
237
+ }
238
+ if (t.startsWith("{") && t.endsWith("}") || t.startsWith("[") && t.endsWith("]")) {
239
+ let e = t.replace(/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\s*:)/g, "$1\"$2\"$3").replace(/'([^'\\]*)'/g, "\"$1\"").replace(/,(\s*[}\]])/g, "$1");
240
+ try {
241
+ return JSON.parse(e);
242
+ } catch {
243
+ return t;
244
+ }
245
+ }
246
+ return t;
247
+ }
248
+ }
249
+ function w(e) {
250
+ return typeof e == "string" ? e : void 0;
251
+ }
252
+ function xe(e) {
253
+ return typeof e == "number" ? e : void 0;
254
+ }
255
+ function T(e) {
256
+ if (!e || typeof e != "object") return !1;
257
+ let t = e;
258
+ return !(typeof t.role != "string" || typeof t.name != "string" || t.under !== void 0 && !T(t.under));
259
+ }
260
+ function E(e, t) {
261
+ let n = e.position;
262
+ if (!n) return "";
263
+ let r = t.slice(n.start.offset, n.end.offset);
264
+ if (/\/>\s*$/.test(r)) return "";
265
+ let i = r.indexOf(">"), a = r.lastIndexOf("</");
266
+ return i < 0 || a < 0 || a <= i ? "" : r.slice(i + 1, a).trim();
267
+ }
268
+ function D(e, t) {
269
+ let n = e;
270
+ return t.snapshot !== void 0 && (n = O(n, y, t.snapshot)), t.attributes !== void 0 && (n = O(n, b, t.attributes)), n;
271
+ }
272
+ function O(e, t, n) {
273
+ let r = new RegExp(String.raw`\{\s*/\*\s*` + Ce(t) + String.raw`\s*[\s\S]*?\*/\s*\}`, "m"), i = Se(t, n);
274
+ return r.test(e) ? e.replace(r, i) : `${e.trimEnd()}\n\n${i}\n`;
275
+ }
276
+ function Se(e, t) {
277
+ let n = t.trim();
278
+ return n ? `{/* ${e}\n${n}\n*/}` : `{/* ${e} */}`;
279
+ }
280
+ function Ce(e) {
281
+ return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
282
+ }
283
+ //#endregion
284
+ //#region src/fixture.ts
285
+ var k = [
286
+ "type",
287
+ "required",
288
+ "placeholder",
289
+ "maxlength",
290
+ "minlength",
291
+ "pattern",
292
+ "min",
293
+ "max",
294
+ "step",
295
+ "disabled",
296
+ "readonly",
297
+ "checked",
298
+ "aria-required",
299
+ "aria-disabled",
300
+ "aria-readonly"
301
+ ], we = t.extend({
302
+ productDocs: async ({ page: e }, t) => {
303
+ await t({ sync: (t) => A(e, t) });
304
+ },
305
+ screen: async ({ page: e }, t) => {
306
+ let n = (t) => A(e, t);
307
+ await t({
308
+ sync: n,
309
+ capture: n
310
+ });
311
+ }
312
+ });
313
+ async function A(e, t) {
314
+ let n = await x(t.mdxPath);
315
+ if (!n) throw Error(`syncProductDocs: ${t.mdxPath} has no \`annot:\` frontmatter — refusing to write.`);
316
+ let r = n.screens.find((e) => e.id === t.id);
317
+ if (!r) throw Error(`syncProductDocs: ${t.mdxPath} has no <Screen id="${t.id}"> block.`);
318
+ let i = await (t.rootLocator ?? e.locator("body")).ariaSnapshot({
319
+ mode: "ai",
320
+ boxes: !0
321
+ }), o = await j(e, r.overlays, t.attributeWhitelist ?? k), s = D(n.source, {
322
+ snapshot: i.trim(),
323
+ attributes: o
324
+ });
325
+ await a(t.mdxPath, s, "utf8");
326
+ }
327
+ var Te = A;
328
+ async function j(e, t, n) {
329
+ let r = [];
330
+ for (let i of t) {
331
+ let t = e.getByRole(i.match.role, {
332
+ name: i.match.name,
333
+ exact: !0
334
+ });
335
+ if (await t.count() !== 1) continue;
336
+ let a = await t.evaluate((e, t) => {
337
+ let n = {};
338
+ for (let r of t) {
339
+ let t = e.getAttribute(r);
340
+ t !== null && (n[r] = t);
341
+ }
342
+ return n;
343
+ }, n), o = Object.keys(a);
344
+ if (o.length !== 0) {
345
+ r.push(`${i.match.role} "${i.match.name}":`);
346
+ for (let e of o) r.push(` ${e}: ${a[e]}`);
347
+ }
348
+ }
349
+ return r.join("\n");
350
+ }
351
+ //#endregion
352
+ //#region src/mdx-annotations.ts
353
+ function M(e) {
354
+ let t = [];
355
+ for (let n of e.split(/\r?\n/)) {
356
+ if (!n.trim()) continue;
357
+ let e = n.match(/^\s*-\s+([a-z]+)(?:\s+"([^"]*?)")?/);
358
+ if (!e) continue;
359
+ let r = e[1] ?? "", i = e[2] ?? "", a = n.match(/\[ref=(e\d+)\]/)?.[1], o = n.match(/\[box=(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\]/);
360
+ !a || !o || t.push({
361
+ role: r,
362
+ name: i,
363
+ ref: a,
364
+ box: {
365
+ x: Number.parseFloat(o[1] ?? "0"),
366
+ y: Number.parseFloat(o[2] ?? "0"),
367
+ width: Number.parseFloat(o[3] ?? "0"),
368
+ height: Number.parseFloat(o[4] ?? "0")
369
+ }
370
+ });
371
+ }
372
+ return t;
373
+ }
374
+ function N(e, t, n) {
375
+ let r = [], i = 1;
376
+ for (let a of e) {
377
+ let e = t.find((e) => e.role === a.match.role && e.name === a.match.name);
378
+ if (!e) continue;
379
+ let o = a.number ?? i++;
380
+ r.push({
381
+ type: "numberedBadge",
382
+ bbox: e.box,
383
+ number: o,
384
+ placement: "auto",
385
+ imageWidth: n.width,
386
+ imageHeight: n.height,
387
+ intent: a.intent === "action" ? "warning" : a.intent === "required" ? "error" : "info"
388
+ });
389
+ }
390
+ return r;
391
+ }
392
+ async function P(e) {
393
+ let t = e.cwd ?? process.cwd(), n = await x(ee(e.mdxPath) ? e.mdxPath : h(t, e.mdxPath));
394
+ if (!n) throw Error(`resolveMdxAnnotations: ${e.mdxPath} has no \`annot:\` frontmatter — cannot resolve.`);
395
+ let r = n.screens.find((t) => t.id === e.screenId);
396
+ if (!r) throw Error(`resolveMdxAnnotations: ${e.mdxPath} has no <Screen id="${e.screenId}"> block.`);
397
+ let i = M(n.commentBlocks.snapshot ?? "");
398
+ return N(r.overlays, i, e.dims);
399
+ }
400
+ function Ee(e) {
401
+ return `<svg xmlns="http://www.w3.org/2000/svg">${g(e)}</svg>`;
402
+ }
403
+ function De(e) {
404
+ return e.length === 0 ? F() : `<svg xmlns="http://www.w3.org/2000/svg">${g(e)}</svg>`;
405
+ }
406
+ function F() {
407
+ return "<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>";
408
+ }
409
+ //#endregion
410
+ //#region src/playwright-screenshot-hook.ts
411
+ var I = Symbol.for("@ingcreators/annot-product-docs:mdx-resolver"), L = async ({ annot: e, page: t }) => {
412
+ if (!e.mdx) return null;
413
+ let { id: n, path: r } = e.mdx;
414
+ return {
415
+ prepare: () => A(t, {
416
+ id: n,
417
+ mdxPath: r
418
+ }),
419
+ resolveAnnotations: (e) => P({
420
+ mdxPath: r,
421
+ screenId: n,
422
+ dims: e
423
+ })
424
+ };
425
+ }, R = L;
426
+ R[I] || (R[I] = !0, e.push(L));
427
+ //#endregion
11
428
  //#region src/resolver.ts
12
- function g(e) {
429
+ function z(e) {
13
430
  let t = [], n = e.split(/\r?\n/), r = [];
14
431
  for (let e of n) {
15
432
  if (!e.trim()) continue;
@@ -35,16 +452,16 @@ function g(e) {
35
452
  }
36
453
  return t;
37
454
  }
38
- async function _(e, t, n) {
39
- let r = te(t.filter((t) => t.role === e.role && t.name === e.name), e.under);
40
- if (r.length === 0) return ne(e, t);
455
+ async function B(e, t, n) {
456
+ let r = Ae(t.filter((t) => t.role === e.role && t.name === e.name), e.under);
457
+ if (r.length === 0) return je(e, t);
41
458
  if (r.length > 1) return {
42
459
  ok: !1,
43
460
  kind: "ambiguous",
44
461
  reason: `Multiple elements match role="${e.role}" name="${e.name}". Use \`under\` to disambiguate.`,
45
462
  candidates: r.map((e) => `[ref=${e.ref}]`)
46
463
  };
47
- let i = r[0], a = v(n, e), o = await a.count();
464
+ let i = r[0], a = ke(n, e), o = await a.count();
48
465
  return o === 0 ? {
49
466
  ok: !1,
50
467
  kind: "live-mismatch",
@@ -59,15 +476,15 @@ async function _(e, t, n) {
59
476
  entry: i
60
477
  };
61
478
  }
62
- async function ee(e, t, n) {
479
+ async function Oe(e, t, n) {
63
480
  let r = [];
64
481
  for (let i of e) r.push({
65
482
  overlay: i,
66
- result: await _(i.match, t, n)
483
+ result: await B(i.match, t, n)
67
484
  });
68
485
  return r;
69
486
  }
70
- function v(e, t) {
487
+ function ke(e, t) {
71
488
  let n = e.getByRole(t.role, {
72
489
  name: t.name,
73
490
  exact: !0
@@ -80,10 +497,10 @@ function v(e, t) {
80
497
  exact: !0
81
498
  })), n;
82
499
  }
83
- function te(e, t) {
500
+ function Ae(e, t) {
84
501
  return t ? e.filter((e) => e.ancestors.some((e) => e.role === t.role && e.name === t.name)) : e;
85
502
  }
86
- function ne(e, t) {
503
+ function je(e, t) {
87
504
  let n = t.filter((t) => t.name === e.name);
88
505
  if (n.length === 1 && n[0].role !== e.role) return {
89
506
  ok: !1,
@@ -93,7 +510,7 @@ function ne(e, t) {
93
510
  };
94
511
  let r = t.filter((t) => t.role === e.role);
95
512
  if (r.length > 0) {
96
- let t = re(e.name, r.map((e) => e.name));
513
+ let t = Me(e.name, r.map((e) => e.name));
97
514
  if (t) return {
98
515
  ok: !1,
99
516
  kind: "renamed",
@@ -107,16 +524,16 @@ function ne(e, t) {
107
524
  reason: `No element with role="${e.role}" name="${e.name}".`
108
525
  };
109
526
  }
110
- function re(e, t) {
527
+ function Me(e, t) {
111
528
  if (t.length === 0) return null;
112
- let n = t[0], r = y(e, n);
529
+ let n = t[0], r = V(e, n);
113
530
  for (let i of t.slice(1)) {
114
- let t = y(e, i);
531
+ let t = V(e, i);
115
532
  t > r && (n = i, r = t);
116
533
  }
117
534
  return r > .3 ? n : null;
118
535
  }
119
- function y(e, t) {
536
+ function V(e, t) {
120
537
  if (!e || !t) return 0;
121
538
  let n = (e) => {
122
539
  let t = /* @__PURE__ */ new Set();
@@ -130,7 +547,7 @@ function y(e, t) {
130
547
  }
131
548
  //#endregion
132
549
  //#region src/drift.ts
133
- function b(e) {
550
+ function H(e) {
134
551
  let { screen: t, liveSnapshot: n, storedAttributesYaml: r, freshAttributesYaml: i } = e, a = [], o = /* @__PURE__ */ new Set();
135
552
  for (let e of t.overlays) {
136
553
  let r = n.filter((t) => t.role === e.match.role && t.name === e.match.name);
@@ -160,7 +577,7 @@ function b(e) {
160
577
  }
161
578
  let s = n.filter((t) => t.role === e.match.role);
162
579
  if (s.length > 0) {
163
- let n = se(e.match.name, s.map((e) => e.name));
580
+ let n = Ie(e.match.name, s.map((e) => e.name));
164
581
  if (n) {
165
582
  o.add(`${e.match.role}|${n}`), a.push({
166
583
  severity: "warning",
@@ -183,7 +600,7 @@ function b(e) {
183
600
  }
184
601
  let s = new Set(t.overlays.map((e) => `${e.match.role}|${e.match.name}`));
185
602
  for (let e of n) {
186
- if (!oe(e.role)) continue;
603
+ if (!Fe(e.role)) continue;
187
604
  let n = `${e.role}|${e.name}`;
188
605
  s.has(n) || o.has(n) || a.push({
189
606
  severity: "warning",
@@ -196,22 +613,22 @@ function b(e) {
196
613
  }
197
614
  });
198
615
  }
199
- return r !== void 0 && i !== void 0 && C(r) !== C(i) && a.push({
616
+ return r !== void 0 && i !== void 0 && G(r) !== G(i) && a.push({
200
617
  severity: "info",
201
618
  kind: "attribute-drift",
202
619
  screenId: t.id,
203
620
  message: "`annot:attributes` block no longer matches live element attributes. Run `annot docs sync` to update."
204
621
  }), a;
205
622
  }
206
- function ie(e) {
207
- return b({
623
+ function Ne(e) {
624
+ return H({
208
625
  screen: e.screen,
209
- liveSnapshot: g(e.liveSnapshotYaml),
626
+ liveSnapshot: z(e.liveSnapshotYaml),
210
627
  storedAttributesYaml: e.storedAttributesYaml,
211
628
  freshAttributesYaml: e.freshAttributesYaml
212
629
  });
213
630
  }
214
- function x(e) {
631
+ function U(e) {
215
632
  let t = 0, n = 0, r = 0;
216
633
  for (let i of e) i.severity === "error" ? t++ : i.severity === "warning" ? n++ : r++;
217
634
  return {
@@ -220,7 +637,7 @@ function x(e) {
220
637
  infos: r
221
638
  };
222
639
  }
223
- var ae = new Set([
640
+ var Pe = new Set([
224
641
  "button",
225
642
  "checkbox",
226
643
  "combobox",
@@ -238,19 +655,19 @@ var ae = new Set([
238
655
  "textbox",
239
656
  "treeitem"
240
657
  ]);
241
- function oe(e) {
242
- return ae.has(e);
658
+ function Fe(e) {
659
+ return Pe.has(e);
243
660
  }
244
- function se(e, t) {
661
+ function Ie(e, t) {
245
662
  if (t.length === 0) return null;
246
- let n = t[0], r = S(e, n);
663
+ let n = t[0], r = W(e, n);
247
664
  for (let i of t.slice(1)) {
248
- let t = S(e, i);
665
+ let t = W(e, i);
249
666
  t > r && (n = i, r = t);
250
667
  }
251
668
  return r > .3 ? n : null;
252
669
  }
253
- function S(e, t) {
670
+ function W(e, t) {
254
671
  if (!e || !t) return 0;
255
672
  let n = (e) => {
256
673
  let t = /* @__PURE__ */ new Set();
@@ -262,364 +679,34 @@ function S(e, t) {
262
679
  for (let e of r) i.has(e) && a++;
263
680
  return a / Math.max(r.size, i.size);
264
681
  }
265
- function C(e) {
682
+ function G(e) {
266
683
  return e.split(/\r?\n/).map((e) => e.trimEnd()).filter((e) => e.length > 0).join("\n");
267
684
  }
268
- function w(e) {
685
+ function K(e) {
269
686
  return e.overlays.length > 0;
270
687
  }
271
- function T(e) {
272
- return e.filter(w);
273
- }
274
- //#endregion
275
- //#region src/config.ts
276
- var E = h.enum([
277
- "cover",
278
- "history",
279
- "list",
280
- "screen",
281
- "reference"
282
- ]), ce = h.object({
283
- book: h.string().optional(),
284
- sheet: h.string().optional(),
285
- sheets: h.record(h.string(), h.string()).optional(),
286
- role: E.optional(),
287
- order: h.number().optional()
288
- }).strict().refine((e) => !(e.sheet && e.sheets), "Specify either `xlsx.sheet` (single sheet) or `xlsx.sheets` (multi-sheet), not both."), le = h.record(h.string(), h.unknown()), D = h.object({
289
- id: h.string().min(1, "`annot.id` is required."),
290
- title: h.string().optional(),
291
- purpose: h.string().optional(),
292
- meta: le.optional(),
293
- xlsx: ce.optional()
294
- }).strict(), ue = h.object({
295
- template: h.string().optional(),
296
- templateSheets: h.object({
297
- cover: h.string().optional(),
298
- history: h.string().optional(),
299
- list: h.string().optional(),
300
- screen: h.string().optional(),
301
- reference: h.string().optional()
302
- }).strict().optional()
303
- }).strict(), O = h.object({
304
- meta: h.record(h.string(), h.unknown()).optional(),
305
- xlsx: h.object({
306
- defaultBook: h.string().optional(),
307
- books: h.record(h.string(), ue).optional()
308
- }).strict().optional()
309
- }).strict();
310
- function de(e) {
311
- let t = O.safeParse(e);
312
- if (!t.success) {
313
- let e = t.error.issues.map((e) => ` - ${e.path.length ? e.path.join(".") + ": " : ""}${e.message}`).join("\n");
314
- throw Error(`Invalid \`annot-docs.config.ts\`:\n${e}`);
315
- }
316
- return t.data;
317
- }
318
- function fe(e) {
319
- return (e.xlsx?.role ?? "screen") === "screen";
320
- }
321
- //#endregion
322
- //#region src/mdx.ts
323
- var k = "annot:snapshot", pe = "/annot:snapshot", A = "annot:attributes", me = "/annot:attributes", he = /^\s*\/\*\s*([^\s*]+)\s*([\s\S]*?)\*\/\s*$/;
324
- async function j(e) {
325
- return M(await t(e, "utf8"), { filePath: e });
326
- }
327
- function M(e, t = {}) {
328
- let n = p().use(f).use(u, ["yaml"]).use(d).parse(e), r = N(n, t.filePath);
329
- if (!r) return null;
330
- let i = [], a = [], o = [], s = [], c = {};
331
- return m(n, (t) => {
332
- switch (t.type) {
333
- case "mdxJsxFlowElement":
334
- case "mdxJsxTextElement":
335
- F(t, e, {
336
- screens: i,
337
- transitions: a,
338
- history: o,
339
- screenLists: s
340
- });
341
- return;
342
- case "mdxFlowExpression":
343
- case "mdxTextExpression":
344
- _e(t, c);
345
- return;
346
- }
347
- }), {
348
- frontmatter: r,
349
- screens: i,
350
- transitions: a,
351
- history: o,
352
- screenLists: s,
353
- commentBlocks: c,
354
- source: e
355
- };
356
- }
357
- function N(e, t) {
358
- let n = e.children.find((e) => e.type === "yaml");
359
- if (!n || !n.value) return null;
360
- let r = l.load(n.value);
361
- if (!r || typeof r != "object") return null;
362
- let i = r.annot;
363
- if (!i || typeof i != "object") return null;
364
- let a = D.safeParse(i);
365
- if (!a.success) {
366
- let e = t ? ` in ${t}` : "";
367
- throw Error(`Invalid \`annot:\` frontmatter${e}:\n${P(a.error)}`);
368
- }
369
- return a.data;
370
- }
371
- function P(e) {
372
- return e.issues.map((e) => ` - ${e.path.length ? e.path.join(".") + ": " : ""}${e.message}`).join("\n");
373
- }
374
- function F(e, t, n) {
375
- let r = e;
376
- switch (r.name) {
377
- case "Screen":
378
- n.screens.push(I(r, t));
379
- return;
380
- case "Transition":
381
- n.transitions.push(R(r, t));
382
- return;
383
- case "HistoryEntry":
384
- n.history.push(ge(r, t));
385
- return;
386
- case "ScreenList":
387
- n.screenLists.push(z(r));
388
- return;
389
- }
390
- }
391
- function I(e, t) {
392
- let n = B(e), r = [], i = (n) => {
393
- let a = n;
394
- if (a.name === "Overlay") {
395
- r.push(L(a, t));
396
- return;
397
- }
398
- if (!(a.name === "Screen" && a !== e)) for (let e of a.children ?? []) i(e);
399
- };
400
- for (let t of e.children ?? []) i(t);
401
- let a = V(n.id);
402
- if (!a) throw Error("<Screen> requires an `id` prop.");
403
- return {
404
- id: a,
405
- src: V(n.src),
406
- overlays: r
407
- };
408
- }
409
- function L(e, t) {
410
- let n = B(e), r = n.match;
411
- if (!H(r)) throw Error("<Overlay> requires a `match` prop with at least `{ role, name }`.");
412
- return {
413
- match: r,
414
- intent: V(n.intent),
415
- number: ye(n.number),
416
- body: U(e, t)
417
- };
418
- }
419
- function R(e, t) {
420
- let n = B(e), r = n.trigger;
421
- if (!H(r)) throw Error("<Transition> requires a `trigger` prop with at least `{ role, name }`.");
422
- return {
423
- trigger: r,
424
- on: V(n.on),
425
- to: V(n.to),
426
- body: U(e, t)
427
- };
428
- }
429
- function ge(e, t) {
430
- let n = B(e), r = V(n.version) ?? "", i = V(n.date) ?? "", a = V(n.author) ?? "";
431
- if (!r || !i) throw Error("<HistoryEntry> requires `version` and `date` props.");
432
- return {
433
- version: r,
434
- date: i,
435
- author: a,
436
- body: U(e, t)
437
- };
438
- }
439
- function z(e) {
440
- let t = B(e);
441
- return {
442
- book: V(t.book),
443
- sort: V(t.sort)
444
- };
445
- }
446
- function _e(e, t) {
447
- let n = e.value;
448
- if (typeof n != "string") return;
449
- let r = n.match(he);
450
- if (!r) return;
451
- let i = (r[1] ?? "").trim(), a = (r[2] ?? "").trim();
452
- switch (i) {
453
- case k:
454
- t.snapshot = a;
455
- return;
456
- case A:
457
- t.attributes = a;
458
- return;
459
- case pe:
460
- case me: return;
461
- }
462
- }
463
- function B(e) {
464
- let t = {};
465
- for (let n of e.attributes ?? []) {
466
- let e = n;
467
- if (e.type !== "mdxJsxAttribute" || !e.name) continue;
468
- if (e.value === null || e.value === void 0) {
469
- t[e.name] = !0;
470
- continue;
471
- }
472
- if (typeof e.value == "string") {
473
- t[e.name] = e.value;
474
- continue;
475
- }
476
- let r = e.value;
477
- r.type === "mdxJsxAttributeValueExpression" && typeof r.value == "string" && (t[e.name] = ve(r.value));
478
- }
479
- return t;
480
- }
481
- function ve(e) {
482
- let t = e.trim();
483
- if (t) {
484
- if (t === "true") return !0;
485
- if (t === "false") return !1;
486
- if (t === "null") return null;
487
- if (/^-?\d+(\.\d+)?$/.test(t)) return Number.parseFloat(t);
488
- if (t.startsWith("\"") && t.endsWith("\"")) try {
489
- return JSON.parse(t);
490
- } catch {
491
- return t.slice(1, -1);
492
- }
493
- if (t.startsWith("'") && t.endsWith("'")) {
494
- let e = t.slice(1, -1), n = e.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
495
- try {
496
- return JSON.parse(`"${n}"`);
497
- } catch {
498
- return e;
499
- }
500
- }
501
- if (t.startsWith("{") && t.endsWith("}") || t.startsWith("[") && t.endsWith("]")) {
502
- let e = t.replace(/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\s*:)/g, "$1\"$2\"$3").replace(/'([^'\\]*)'/g, "\"$1\"").replace(/,(\s*[}\]])/g, "$1");
503
- try {
504
- return JSON.parse(e);
505
- } catch {
506
- return t;
507
- }
508
- }
509
- return t;
510
- }
511
- }
512
- function V(e) {
513
- return typeof e == "string" ? e : void 0;
514
- }
515
- function ye(e) {
516
- return typeof e == "number" ? e : void 0;
517
- }
518
- function H(e) {
519
- if (!e || typeof e != "object") return !1;
520
- let t = e;
521
- return !(typeof t.role != "string" || typeof t.name != "string" || t.under !== void 0 && !H(t.under));
522
- }
523
- function U(e, t) {
524
- let n = e.position;
525
- if (!n) return "";
526
- let r = t.slice(n.start.offset, n.end.offset);
527
- if (/\/>\s*$/.test(r)) return "";
528
- let i = r.indexOf(">"), a = r.lastIndexOf("</");
529
- return i < 0 || a < 0 || a <= i ? "" : r.slice(i + 1, a).trim();
530
- }
531
- function W(e, t) {
532
- let n = e;
533
- return t.snapshot !== void 0 && (n = G(n, k, t.snapshot)), t.attributes !== void 0 && (n = G(n, A, t.attributes)), n;
534
- }
535
- function G(e, t, n) {
536
- let r = new RegExp(String.raw`\{\s*/\*\s*` + xe(t) + String.raw`\s*[\s\S]*?\*/\s*\}`, "m"), i = be(t, n);
537
- return r.test(e) ? e.replace(r, i) : `${e.trimEnd()}\n\n${i}\n`;
538
- }
539
- function be(e, t) {
540
- let n = t.trim();
541
- return n ? `{/* ${e}\n${n}\n*/}` : `{/* ${e} */}`;
542
- }
543
- function xe(e) {
544
- return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
545
- }
546
- //#endregion
547
- //#region src/fixture.ts
548
- var K = [
549
- "type",
550
- "required",
551
- "placeholder",
552
- "maxlength",
553
- "minlength",
554
- "pattern",
555
- "min",
556
- "max",
557
- "step",
558
- "disabled",
559
- "readonly",
560
- "checked",
561
- "aria-required",
562
- "aria-disabled",
563
- "aria-readonly"
564
- ], Se = c.extend({ screen: async ({ page: e }, t) => {
565
- await t({ capture: (t) => q(e, t) });
566
- } });
567
- async function q(e, t) {
568
- let n = await j(t.mdxPath);
569
- if (!n) throw Error(`captureScreen: ${t.mdxPath} has no \`annot:\` frontmatter — refusing to write.`);
570
- let i = n.screens.find((e) => e.id === t.id);
571
- if (!i) throw Error(`captureScreen: ${t.mdxPath} has no <Screen id="${t.id}"> block.`);
572
- let a = await (t.rootLocator ?? e.locator("body")).ariaSnapshot({
573
- mode: "ai",
574
- boxes: !0
575
- }), o = await J(e, i.overlays, t.attributeWhitelist ?? K), s = W(n.source, {
576
- snapshot: a.trim(),
577
- attributes: o
578
- });
579
- await r(t.mdxPath, s, "utf8");
580
- }
581
- async function J(e, t, n) {
582
- let r = [];
583
- for (let i of t) {
584
- let t = e.getByRole(i.match.role, {
585
- name: i.match.name,
586
- exact: !0
587
- });
588
- if (await t.count() !== 1) continue;
589
- let a = await t.evaluate((e, t) => {
590
- let n = {};
591
- for (let r of t) {
592
- let t = e.getAttribute(r);
593
- t !== null && (n[r] = t);
594
- }
595
- return n;
596
- }, n), o = Object.keys(a);
597
- if (o.length !== 0) {
598
- r.push(`${i.match.role} "${i.match.name}":`);
599
- for (let e of o) r.push(` ${e}: ${a[e]}`);
600
- }
601
- }
602
- return r.join("\n");
688
+ function q(e) {
689
+ return e.filter(K);
603
690
  }
604
691
  //#endregion
605
692
  //#region src/cli.ts
606
- async function Ce(e, t = {}) {
693
+ async function Le(e, t = {}) {
607
694
  let n = t.stdout ?? ((e) => process.stdout.write(`${e}\n`)), r = t.stderr ?? ((e) => process.stderr.write(`${e}\n`)), i = t.cwd ?? process.cwd(), [, , a, ...o] = e;
608
- if (a !== "init" && a !== "sync" && a !== "lint") return r(we), +!!a;
695
+ if (a !== "init" && a !== "sync" && a !== "lint") return r(Re), +!!a;
609
696
  try {
610
697
  switch (a) {
611
- case "init": return await Te(o, {
698
+ case "init": return await ze(o, {
612
699
  cwd: i,
613
700
  stdout: n,
614
701
  stderr: r
615
702
  });
616
- case "sync": return await ke(o, {
703
+ case "sync": return await He(o, {
617
704
  ...t,
618
705
  cwd: i,
619
706
  stdout: n,
620
707
  stderr: r
621
708
  });
622
- case "lint": return await Ae(o, {
709
+ case "lint": return await Ue(o, {
623
710
  ...t,
624
711
  cwd: i,
625
712
  stdout: n,
@@ -630,7 +717,7 @@ async function Ce(e, t = {}) {
630
717
  return r(`annot docs ${a}: ${e.message}`), 1;
631
718
  }
632
719
  }
633
- var we = [
720
+ var Re = [
634
721
  "annot docs <command> [options]",
635
722
  "",
636
723
  "Commands:",
@@ -643,71 +730,71 @@ var we = [
643
730
  " --root <dir> Override MDX search root (default: docs/)",
644
731
  " --help Show this help"
645
732
  ].join("\n");
646
- async function Te(t, n) {
647
- let { cwd: a, stdout: o } = n, c = [
733
+ async function ze(e, t) {
734
+ let { cwd: r, stdout: i } = t, o = [
648
735
  {
649
736
  path: "annot-docs.config.ts",
650
- content: Ee
737
+ content: Be
651
738
  },
652
739
  {
653
740
  path: "tests/docs/example.spec.ts",
654
- content: De
741
+ content: J
655
742
  },
656
743
  {
657
744
  path: "docs/books/example/SC-001-login.mdx",
658
- content: Oe
745
+ content: Ve
659
746
  }
660
- ], l = 0;
661
- for (let t of c) {
662
- let n = s(a, t.path);
747
+ ], s = 0;
748
+ for (let e of o) {
749
+ let t = h(r, e.path);
663
750
  try {
664
- await e(i(n), { recursive: !0 }), await r(n, t.content, { flag: "wx" }), o(` created ${t.path}`), l++;
665
- } catch (e) {
666
- if (e.code === "EEXIST") o(` exists ${t.path} (skipped)`);
667
- else throw e;
751
+ await n(p(t), { recursive: !0 }), await a(t, e.content, { flag: "wx" }), i(` created ${e.path}`), s++;
752
+ } catch (t) {
753
+ if (t.code === "EEXIST") i(` exists ${e.path} (skipped)`);
754
+ else throw t;
668
755
  }
669
756
  }
670
- return o(l === 0 ? "annot docs init: nothing to do (all targets exist)" : `annot docs init: wrote ${l} file(s)`), 0;
757
+ return i(s === 0 ? "annot docs init: nothing to do (all targets exist)" : `annot docs init: wrote ${s} file(s)`), 0;
671
758
  }
672
- var Ee = "// Living product docs config for annot.\n// See https://github.com/ingcreators/annot/blob/main/docs/plans/living-product-docs.md\nimport { defineConfig } from \"@ingcreators/annot-product-docs\";\n\nexport default defineConfig({\n meta: {\n projectName: \"Example\",\n },\n xlsx: {\n defaultBook: \"Screen spec\",\n books: {\n \"Screen spec\": {\n // Drop your customer-supplied template here (Phase 3) and\n // the Excel adapter will fill it. Until then the OSS\n // default layout applies.\n // template: \"./templates/customer-screen-spec.xlsx\",\n },\n },\n },\n});\n", De = "// Tour file — runs through every screen and refreshes the\n// matching MDX's annot:snapshot / annot:attributes blocks.\n//\n// Run with: pnpm playwright test tests/docs/\n\nimport { test } from \"@ingcreators/annot-product-docs\";\n\ntest.describe.configure({ mode: \"serial\" });\n\ntest(\"login flow\", async ({ page, screen }) => {\n await page.goto(\"/login\");\n await screen.capture({\n id: \"login\",\n mdxPath: \"docs/books/example/SC-001-login.mdx\",\n });\n});\n", Oe = "---\nannot:\n id: SC-001\n title: Login screen\n meta:\n author: TODO\n xlsx:\n book: Screen spec\n sheet: SC-001 Login\n role: screen\n order: 100\n---\n\nimport { Screen, Overlay } from \"@ingcreators/annot-product-docs-astro\";\n\n# Login screen\n\nEnter your credentials to access the system.\n\n<Screen id=\"login\" src=\"./shots/login.png\">\n\n<Overlay match={{ role: \"textbox\", name: \"Email\" }} intent=\"required\" number={1}>\n**Email** — Enter your registered email address.\n</Overlay>\n\n<Overlay match={{ role: \"button\", name: \"Sign in\" }} intent=\"action\" number={2}>\nClick to sign in.\n</Overlay>\n\n</Screen>\n";
673
- async function ke(e, t) {
759
+ var Be = "// Living product docs config for annot.\n// See https://github.com/ingcreators/annot/blob/main/docs/plans/living-product-docs.md\nimport { defineConfig } from \"@ingcreators/annot-product-docs\";\n\nexport default defineConfig({\n meta: {\n projectName: \"Example\",\n },\n xlsx: {\n defaultBook: \"Screen spec\",\n books: {\n \"Screen spec\": {\n // Drop your customer-supplied template here (Phase 3) and\n // the Excel adapter will fill it. Until then the OSS\n // default layout applies.\n // template: \"./templates/customer-screen-spec.xlsx\",\n },\n },\n },\n});\n", J = "// Tour file — runs through every screen and refreshes the\n// matching MDX's annot:snapshot / annot:attributes blocks.\n//\n// Run with: pnpm playwright test tests/docs/\n\nimport { test } from \"@ingcreators/annot-product-docs\";\n\ntest.describe.configure({ mode: \"serial\" });\n\ntest(\"login flow\", async ({ page, productDocs }) => {\n await page.goto(\"/login\");\n await productDocs.sync({\n id: \"login\",\n mdxPath: \"docs/books/example/SC-001-login.mdx\",\n });\n});\n", Ve = "---\nannot:\n id: SC-001\n title: Login screen\n meta:\n author: TODO\n xlsx:\n book: Screen spec\n sheet: SC-001 Login\n role: screen\n order: 100\n---\n\nimport { Screen, Overlay } from \"@ingcreators/annot-product-docs-astro\";\n\n# Login screen\n\nEnter your credentials to access the system.\n\n<Screen id=\"login\" src=\"./shots/login.png\">\n\n<Overlay match={{ role: \"textbox\", name: \"Email\" }} intent=\"required\" number={1}>\n**Email** — Enter your registered email address.\n</Overlay>\n\n<Overlay match={{ role: \"button\", name: \"Sign in\" }} intent=\"action\" number={2}>\nClick to sign in.\n</Overlay>\n\n</Screen>\n";
760
+ async function He(e, t) {
674
761
  let { cwd: n, stdout: r, stderr: i } = t, a = Z(e);
675
762
  if (!a.url) return i("annot docs sync: --url <baseUrl> is required."), 1;
676
- let c = await $(await Q(s(n, a.root ?? "docs")));
677
- if (c.length === 0) return r(`annot docs sync: no MDX files with \`annot:\` frontmatter under ${a.root ?? "docs"}.`), 0;
678
- r(`annot docs sync: ${c.length} MDX file(s) → ${a.url}`);
679
- let { newPage: l, close: u } = await Y(a.url, t);
763
+ let o = await $(await Q(h(n, a.root ?? "docs")));
764
+ if (o.length === 0) return r(`annot docs sync: no MDX files with \`annot:\` frontmatter under ${a.root ?? "docs"}.`), 0;
765
+ r(`annot docs sync: ${o.length} MDX file(s) → ${a.url}`);
766
+ let { newPage: s, close: c } = await Y(a.url, t);
680
767
  try {
681
- for (let e of c) {
682
- let t = await j(e);
768
+ for (let e of o) {
769
+ let t = await x(e);
683
770
  if (!t) continue;
684
- let i = T(t.screens);
771
+ let i = q(t.screens);
685
772
  if (i.length === 0) {
686
- r(` skip ${o(n, e)} (no <Screen> blocks)`);
773
+ r(` skip ${m(n, e)} (no <Screen> blocks)`);
687
774
  continue;
688
775
  }
689
776
  for (let t of i) {
690
- let { page: i, dispose: a } = await l(t.src ?? "/");
777
+ let { page: i, dispose: a } = await s(t.src ?? "/");
691
778
  try {
692
- await q(i, {
779
+ await A(i, {
693
780
  id: t.id,
694
781
  mdxPath: e
695
- }), r(` synced ${o(n, e)} (screen=${t.id})`);
782
+ }), r(` synced ${m(n, e)} (screen=${t.id})`);
696
783
  } finally {
697
784
  await a();
698
785
  }
699
786
  }
700
787
  }
701
788
  } finally {
702
- await u();
789
+ await c();
703
790
  }
704
791
  return 0;
705
792
  }
706
- async function Ae(e, t) {
793
+ async function Ue(e, t) {
707
794
  let { cwd: n, stdout: r, stderr: i } = t, a = Z(e);
708
795
  if (!a.url) return i("annot docs lint: --url <baseUrl> is required."), 1;
709
- let c = await $(await Q(s(n, a.root ?? "docs")));
710
- if (c.length === 0) return a.json ? r(JSON.stringify({
796
+ let o = await $(await Q(h(n, a.root ?? "docs")));
797
+ if (o.length === 0) return a.json ? r(JSON.stringify({
711
798
  findings: [],
712
799
  summary: {
713
800
  errors: 0,
@@ -715,34 +802,34 @@ async function Ae(e, t) {
715
802
  infos: 0
716
803
  }
717
804
  })) : r(`annot docs lint: no MDX files with \`annot:\` frontmatter under ${a.root ?? "docs"}.`), 0;
718
- a.json || r(`annot docs lint: ${c.length} MDX file(s) → ${a.url}`);
719
- let l = [], u = /* @__PURE__ */ new Set(), { newPage: d, close: f } = await Y(a.url, t);
805
+ a.json || r(`annot docs lint: ${o.length} MDX file(s) → ${a.url}`);
806
+ let s = [], c = /* @__PURE__ */ new Set(), { newPage: l, close: u } = await Y(a.url, t);
720
807
  try {
721
- for (let e of c) {
722
- let t = await j(e);
723
- if (t) for (let r of T(t.screens)) {
724
- let { page: t, dispose: i } = await d(r.src ?? "/");
808
+ for (let e of o) {
809
+ let t = await x(e);
810
+ if (t) for (let r of q(t.screens)) {
811
+ let { page: t, dispose: i } = await l(r.src ?? "/");
725
812
  try {
726
- let i = b({
813
+ let i = H({
727
814
  screen: r,
728
- liveSnapshot: g(await t.locator("body").ariaSnapshot({ mode: "ai" }))
815
+ liveSnapshot: z(await t.locator("body").ariaSnapshot({ mode: "ai" }))
729
816
  });
730
- for (let t of i) l.push({
731
- file: o(n, e),
817
+ for (let t of i) s.push({
818
+ file: m(n, e),
732
819
  finding: t
733
- }), u.add(e);
820
+ }), c.add(e);
734
821
  } finally {
735
822
  await i();
736
823
  }
737
824
  }
738
825
  }
739
826
  } finally {
740
- await f();
827
+ await u();
741
828
  }
742
829
  if (a.json) {
743
- let e = x(l.map((e) => e.finding));
830
+ let e = U(s.map((e) => e.finding));
744
831
  r(JSON.stringify({
745
- findings: l.map(({ file: e, finding: t }) => ({
832
+ findings: s.map(({ file: e, finding: t }) => ({
746
833
  file: e,
747
834
  severity: t.severity,
748
835
  kind: t.kind,
@@ -754,23 +841,23 @@ async function Ae(e, t) {
754
841
  summary: e
755
842
  }));
756
843
  } else {
757
- for (let { file: e, finding: t } of l) r(`${je(t.severity)} ${e} [${t.screenId}] ${t.kind}: ${t.message}`);
758
- let e = x(l.map((e) => e.finding));
844
+ for (let { file: e, finding: t } of s) r(`${We(t.severity)} ${e} [${t.screenId}] ${t.kind}: ${t.message}`);
845
+ let e = U(s.map((e) => e.finding));
759
846
  r(`annot docs lint: ${e.errors} error(s), ${e.warnings} warning(s), ${e.infos} info(s).`);
760
847
  }
761
- let p = 0;
762
- if (a.fix && u.size > 0) {
848
+ let d = 0;
849
+ if (a.fix && c.size > 0) {
763
850
  let { newPage: e, close: n } = await Y(a.url, t);
764
851
  try {
765
- for (let t of u) {
766
- let n = await j(t);
767
- if (n) for (let r of T(n.screens)) {
852
+ for (let t of c) {
853
+ let n = await x(t);
854
+ if (n) for (let r of q(n.screens)) {
768
855
  let { page: n, dispose: i } = await e(r.src ?? "/");
769
856
  try {
770
- await q(n, {
857
+ await A(n, {
771
858
  id: r.id,
772
859
  mdxPath: t
773
- }), p++;
860
+ }), d++;
774
861
  } finally {
775
862
  await i();
776
863
  }
@@ -779,10 +866,10 @@ async function Ae(e, t) {
779
866
  } finally {
780
867
  await n();
781
868
  }
782
- a.json || r(`annot docs lint --fix: refreshed snapshot/attributes for ${p} screen(s).`);
869
+ a.json || r(`annot docs lint --fix: refreshed snapshot/attributes for ${d} screen(s).`);
783
870
  }
784
- let m = x(l.map((e) => e.finding));
785
- return a.ci ? +(m.errors + m.warnings > 0) : +(m.errors > 0);
871
+ let f = U(s.map((e) => e.finding));
872
+ return a.ci ? +(f.errors + f.warnings > 0) : +(f.errors > 0);
786
873
  }
787
874
  async function Y(e, t) {
788
875
  if (t.newPage) return {
@@ -823,21 +910,21 @@ function Z(e) {
823
910
  return t;
824
911
  }
825
912
  async function Q(e) {
826
- let t = [], r = [e];
827
- for (; r.length > 0;) {
828
- let e = r.pop(), i;
913
+ let t = [], n = [e];
914
+ for (; n.length > 0;) {
915
+ let e = n.pop(), r;
829
916
  try {
830
- i = await n(e, { withFileTypes: !0 });
917
+ r = await i(e, { withFileTypes: !0 });
831
918
  } catch (e) {
832
919
  if (e.code === "ENOENT") continue;
833
920
  throw e;
834
921
  }
835
- for (let n of i) {
836
- let i = a(e, n.name);
837
- if (n.isDirectory()) {
838
- if (n.name === "node_modules" || n.name.startsWith(".")) continue;
839
- r.push(i);
840
- } else n.isFile() && n.name.endsWith(".mdx") && t.push(i);
922
+ for (let i of r) {
923
+ let r = te(e, i.name);
924
+ if (i.isDirectory()) {
925
+ if (i.name === "node_modules" || i.name.startsWith(".")) continue;
926
+ n.push(r);
927
+ } else i.isFile() && i.name.endsWith(".mdx") && t.push(r);
841
928
  }
842
929
  }
843
930
  return t.sort();
@@ -845,11 +932,11 @@ async function Q(e) {
845
932
  async function $(e) {
846
933
  let t = [];
847
934
  for (let n of e) try {
848
- await j(n) && t.push(n);
935
+ await x(n) && t.push(n);
849
936
  } catch {}
850
937
  return t;
851
938
  }
852
- function je(e) {
939
+ function We(e) {
853
940
  switch (e) {
854
941
  case "error": return "ERROR ";
855
942
  case "warning": return "WARN ";
@@ -857,4 +944,4 @@ function je(e) {
857
944
  }
858
945
  }
859
946
  //#endregion
860
- export { K as DEFAULT_ATTR_WHITELIST, O as annotDocsConfigSchema, D as annotFrontmatterSchema, q as captureScreen, J as collectAttributesYaml, de as defineConfig, b as detectDrift, ie as detectDriftFromYaml, $ as filterAnnotMdxFiles, w as isLintableScreen, fe as isScreenRole, T as lintableScreens, Ce as main, M as parseMdx, j as parseMdxFile, g as parseSnapshot, _ as resolveMatch, ee as resolveOverlays, x as summariseDrift, Se as test, W as updateCommentBlocks, Q as walkMdx };
947
+ export { k as DEFAULT_ATTR_WHITELIST, v as annotDocsConfigSchema, _ as annotFrontmatterSchema, N as buildBadgeAnnotations, Te as captureScreen, j as collectAttributesYaml, oe as defineConfig, H as detectDrift, Ne as detectDriftFromYaml, F as emptyAnnotationsSvg, $ as filterAnnotMdxFiles, K as isLintableScreen, se as isScreenRole, q as lintableScreens, Le as main, S as parseMdx, x as parseMdxFile, z as parseSnapshot, M as parseSnapshotBoxes, B as resolveMatch, P as resolveMdxAnnotations, Oe as resolveOverlays, U as summariseDrift, Ee as svgFromBadges, De as svgFromBboxAnnotations, A as syncProductDocs, we as test, D as updateCommentBlocks, Q as walkMdx };