uidex 0.5.0 → 0.5.1
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/cli/cli.cjs +115 -14
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/headless/index.cjs +3 -0
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.js +3 -0
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +3 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +110 -9
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +1 -1
- package/dist/scan/index.d.ts +1 -1
- package/dist/scan/index.js +110 -9
- package/dist/scan/index.js.map +1 -1
- package/package.json +19 -26
package/dist/scan/index.d.cts
CHANGED
|
@@ -155,7 +155,7 @@ interface Annotation {
|
|
|
155
155
|
/** JSX ancestor chain, outermost to innermost. Only populated for DOM-attribute kinds. */
|
|
156
156
|
ancestors?: AnnotationAncestor[];
|
|
157
157
|
}
|
|
158
|
-
type MetadataExportKind = "page" | "feature" | "primitive" | "widget" | "flow";
|
|
158
|
+
type MetadataExportKind = "page" | "feature" | "primitive" | "widget" | "region" | "flow";
|
|
159
159
|
interface MetadataExport {
|
|
160
160
|
source: "ts-export";
|
|
161
161
|
kind: MetadataExportKind;
|
package/dist/scan/index.d.ts
CHANGED
|
@@ -155,7 +155,7 @@ interface Annotation {
|
|
|
155
155
|
/** JSX ancestor chain, outermost to innermost. Only populated for DOM-attribute kinds. */
|
|
156
156
|
ancestors?: AnnotationAncestor[];
|
|
157
157
|
}
|
|
158
|
-
type MetadataExportKind = "page" | "feature" | "primitive" | "widget" | "flow";
|
|
158
|
+
type MetadataExportKind = "page" | "feature" | "primitive" | "widget" | "region" | "flow";
|
|
159
159
|
interface MetadataExport {
|
|
160
160
|
source: "ts-export";
|
|
161
161
|
kind: MetadataExportKind;
|
package/dist/scan/index.js
CHANGED
|
@@ -356,6 +356,7 @@ var KIND_DISCRIMINATORS = [
|
|
|
356
356
|
"feature",
|
|
357
357
|
"primitive",
|
|
358
358
|
"widget",
|
|
359
|
+
"region",
|
|
359
360
|
"flow",
|
|
360
361
|
"notFlow"
|
|
361
362
|
];
|
|
@@ -377,12 +378,14 @@ var ALLOWED_FIELDS = {
|
|
|
377
378
|
]),
|
|
378
379
|
primitive: /* @__PURE__ */ new Set(["primitive", "name", "description"]),
|
|
379
380
|
widget: /* @__PURE__ */ new Set(["widget", "name", "acceptance", "description"]),
|
|
381
|
+
region: /* @__PURE__ */ new Set(["region", "name", "description"]),
|
|
380
382
|
flow: /* @__PURE__ */ new Set(["flow", "notFlow", "name", "description"])
|
|
381
383
|
};
|
|
382
384
|
var FALSEABLE = /* @__PURE__ */ new Set([
|
|
383
385
|
"page",
|
|
384
386
|
"feature",
|
|
385
|
-
"primitive"
|
|
387
|
+
"primitive",
|
|
388
|
+
"region"
|
|
386
389
|
]);
|
|
387
390
|
var ExtractError = class extends Error {
|
|
388
391
|
code;
|
|
@@ -2014,6 +2017,21 @@ function resolve2(ctx) {
|
|
|
2014
2017
|
};
|
|
2015
2018
|
registry.add(region);
|
|
2016
2019
|
}
|
|
2020
|
+
for (const ef of ctx.extracted) {
|
|
2021
|
+
const exp = exportFor(ef.file.displayPath, "region");
|
|
2022
|
+
if (!exp) continue;
|
|
2023
|
+
if (exp.id === false) continue;
|
|
2024
|
+
if (typeof exp.id === "string" && !registry.get("region", exp.id)) {
|
|
2025
|
+
const meta = buildMetaFromExport(exp);
|
|
2026
|
+
const region = {
|
|
2027
|
+
kind: "region",
|
|
2028
|
+
id: exp.id,
|
|
2029
|
+
loc: { file: ef.file.displayPath, line: exp.loc.line },
|
|
2030
|
+
...meta ? { meta } : {}
|
|
2031
|
+
};
|
|
2032
|
+
registry.add(region);
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2017
2035
|
const primitiveConventions = conventions.primitives;
|
|
2018
2036
|
for (const ef of ctx.extracted) {
|
|
2019
2037
|
const file = ef.file.displayPath;
|
|
@@ -2322,17 +2340,38 @@ function audit(opts) {
|
|
|
2322
2340
|
}
|
|
2323
2341
|
}
|
|
2324
2342
|
if (lint) {
|
|
2343
|
+
const dynamicAttrRe = /\bdata-uidex(?:-(region|widget|primitive))?\s*=\s*\{/g;
|
|
2325
2344
|
for (const f of files) {
|
|
2326
|
-
const lines = f.content.split("\n");
|
|
2327
|
-
const candidateRe = /<(button|a|input|select|textarea)(?=[\s/>])([^>]*)>/g;
|
|
2328
2345
|
let m;
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
const idx = m.index;
|
|
2346
|
+
dynamicAttrRe.lastIndex = 0;
|
|
2347
|
+
while ((m = dynamicAttrRe.exec(f.content)) !== null) {
|
|
2348
|
+
const kind = m[1] ?? "element";
|
|
2333
2349
|
let line = 1;
|
|
2334
|
-
for (let i = 0; i <
|
|
2335
|
-
|
|
2350
|
+
for (let i = 0; i < m.index; i++) if (f.content[i] === "\n") line++;
|
|
2351
|
+
const attrName = m[1] ? `data-uidex-${m[1]}` : "data-uidex";
|
|
2352
|
+
diagnostics.push({
|
|
2353
|
+
code: "dynamic-attr",
|
|
2354
|
+
severity: "warning",
|
|
2355
|
+
message: `\`${attrName}={\u2026}\` uses a dynamic expression; the scanner cannot resolve the ${kind} id statically`,
|
|
2356
|
+
file: f.displayPath,
|
|
2357
|
+
line,
|
|
2358
|
+
hint: dynamicAttrHint(kind)
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
if (lint) {
|
|
2364
|
+
for (const f of files) {
|
|
2365
|
+
const tagRe = /<(button|a|input|select|textarea)(?=[\s/>])/g;
|
|
2366
|
+
let m;
|
|
2367
|
+
while ((m = tagRe.exec(f.content)) !== null) {
|
|
2368
|
+
const afterTag = m.index + m[0].length;
|
|
2369
|
+
const closeIdx = findJsxOpeningEnd(f.content, afterTag);
|
|
2370
|
+
if (closeIdx === -1) continue;
|
|
2371
|
+
const attrs = f.content.slice(afterTag, closeIdx);
|
|
2372
|
+
if (attrs.includes("data-uidex")) continue;
|
|
2373
|
+
let line = 1;
|
|
2374
|
+
for (let i = 0; i < m.index; i++) if (f.content[i] === "\n") line++;
|
|
2336
2375
|
diagnostics.push({
|
|
2337
2376
|
code: "missing-element-annotation",
|
|
2338
2377
|
severity: "info",
|
|
@@ -2542,6 +2581,63 @@ function extractEntitiesArray(source) {
|
|
|
2542
2581
|
}
|
|
2543
2582
|
return null;
|
|
2544
2583
|
}
|
|
2584
|
+
function findJsxOpeningEnd(src, start) {
|
|
2585
|
+
let i = start;
|
|
2586
|
+
while (i < src.length) {
|
|
2587
|
+
const ch = src[i];
|
|
2588
|
+
if (ch === ">" || ch === "/" && src[i + 1] === ">") return i;
|
|
2589
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
2590
|
+
i = skipString2(src, i);
|
|
2591
|
+
} else if (ch === "{") {
|
|
2592
|
+
i = skipBraces(src, i);
|
|
2593
|
+
} else {
|
|
2594
|
+
i++;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
return -1;
|
|
2598
|
+
}
|
|
2599
|
+
function skipString2(src, start) {
|
|
2600
|
+
const quote = src[start];
|
|
2601
|
+
let i = start + 1;
|
|
2602
|
+
while (i < src.length) {
|
|
2603
|
+
if (src[i] === "\\" && quote !== "`") {
|
|
2604
|
+
i += 2;
|
|
2605
|
+
continue;
|
|
2606
|
+
}
|
|
2607
|
+
if (quote === "`" && src[i] === "$" && src[i + 1] === "{") {
|
|
2608
|
+
i = skipBraces(src, i + 1);
|
|
2609
|
+
continue;
|
|
2610
|
+
}
|
|
2611
|
+
if (src[i] === quote) return i + 1;
|
|
2612
|
+
i++;
|
|
2613
|
+
}
|
|
2614
|
+
return i;
|
|
2615
|
+
}
|
|
2616
|
+
function skipBraces(src, start) {
|
|
2617
|
+
let depth = 1;
|
|
2618
|
+
let i = start + 1;
|
|
2619
|
+
while (i < src.length && depth > 0) {
|
|
2620
|
+
const ch = src[i];
|
|
2621
|
+
if (ch === "{") {
|
|
2622
|
+
depth++;
|
|
2623
|
+
i++;
|
|
2624
|
+
} else if (ch === "}") {
|
|
2625
|
+
depth--;
|
|
2626
|
+
i++;
|
|
2627
|
+
} else if (ch === '"' || ch === "'" || ch === "`") {
|
|
2628
|
+
i = skipString2(src, i);
|
|
2629
|
+
} else {
|
|
2630
|
+
i++;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
return i;
|
|
2634
|
+
}
|
|
2635
|
+
function dynamicAttrHint(kind) {
|
|
2636
|
+
if (kind === "region") {
|
|
2637
|
+
return `Use a string literal: \`data-uidex-region="id"\`, or declare the region via \`export const uidex = { region: "id" } as const satisfies Uidex.Region\` on the file that passes the region value`;
|
|
2638
|
+
}
|
|
2639
|
+
return `The scanner requires string-literal attribute values. If this component forwards the annotation via a prop, restructure so the caller provides the annotated element directly (e.g. via a slot or render prop) with a string-literal \`data-uidex\` attribute`;
|
|
2640
|
+
}
|
|
2545
2641
|
function stableStringify(value) {
|
|
2546
2642
|
return JSON.stringify(value, stableReplacer);
|
|
2547
2643
|
}
|
|
@@ -2695,6 +2791,11 @@ function emit(opts) {
|
|
|
2695
2791
|
lines.push(" acceptance?: readonly string[]");
|
|
2696
2792
|
lines.push(" description?: string");
|
|
2697
2793
|
lines.push(" }");
|
|
2794
|
+
lines.push(" export interface Region {");
|
|
2795
|
+
lines.push(" region: RegionId | false");
|
|
2796
|
+
lines.push(" name?: string");
|
|
2797
|
+
lines.push(" description?: string");
|
|
2798
|
+
lines.push(" }");
|
|
2698
2799
|
lines.push(" export interface Flow {");
|
|
2699
2800
|
lines.push(" flow: FlowId");
|
|
2700
2801
|
lines.push(" name?: string");
|