uidex 0.5.2 → 0.6.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.
@@ -1266,6 +1266,7 @@ function posAt(content, offset) {
1266
1266
 
1267
1267
  // src/scanner/scan/jsx-ancestry.ts
1268
1268
  var DATA_ATTR_RE = /\bdata-uidex(?:-(region|widget|primitive))?\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
1269
+ var PATTERN_ATTR_RE = /\bdata-uidex(?:-(region|widget|primitive))?\s*=\s*\{\s*`([^`$]+)\$\{/g;
1269
1270
  function parseDataAttrs(tagSource) {
1270
1271
  if (!tagSource.includes("data-uidex")) return [];
1271
1272
  const out2 = [];
@@ -1274,6 +1275,11 @@ function parseDataAttrs(tagSource) {
1274
1275
  const id = m[2] ?? m[3];
1275
1276
  if (id) out2.push({ kind, id });
1276
1277
  }
1278
+ for (const m of tagSource.matchAll(PATTERN_ATTR_RE)) {
1279
+ const kind = m[1] ?? "element";
1280
+ const prefix = m[2];
1281
+ if (prefix) out2.push({ kind, id: `${prefix}*` });
1282
+ }
1277
1283
  return out2;
1278
1284
  }
1279
1285
  function collectJSXAncestry(content) {
@@ -1623,6 +1629,7 @@ function freezeEntity(entity, flows) {
1623
1629
  function createRegistry() {
1624
1630
  const store = emptyStore();
1625
1631
  let flowsCache = null;
1632
+ const patternCache = /* @__PURE__ */ new Map();
1626
1633
  const getFlows = () => {
1627
1634
  if (flowsCache === null) flowsCache = Array.from(store.flow.values());
1628
1635
  return flowsCache;
@@ -1632,6 +1639,7 @@ function createRegistry() {
1632
1639
  const key = entityKey(entity);
1633
1640
  store[entity.kind].set(key, entity);
1634
1641
  flowsCache = null;
1642
+ patternCache.delete(entity.kind);
1635
1643
  };
1636
1644
  const get = (kind, id) => {
1637
1645
  assertEntityKind(kind);
@@ -1639,6 +1647,38 @@ function createRegistry() {
1639
1647
  if (raw === void 0) return void 0;
1640
1648
  return freezeEntity(raw, getFlows());
1641
1649
  };
1650
+ const getPatternsForKind = (kind) => {
1651
+ const cached = patternCache.get(kind);
1652
+ if (cached !== void 0)
1653
+ return cached;
1654
+ const patterns = [];
1655
+ for (const [key, entity] of store[kind]) {
1656
+ if (key.endsWith("*")) {
1657
+ patterns.push({
1658
+ prefix: key.slice(0, -1),
1659
+ entity
1660
+ });
1661
+ }
1662
+ }
1663
+ patternCache.set(
1664
+ kind,
1665
+ patterns
1666
+ );
1667
+ return patterns;
1668
+ };
1669
+ const matchPattern = (kind, id) => {
1670
+ assertEntityKind(kind);
1671
+ const patterns = getPatternsForKind(kind);
1672
+ if (patterns.length === 0) return void 0;
1673
+ let best;
1674
+ for (const entry of patterns) {
1675
+ if (id.startsWith(entry.prefix) && (best === void 0 || entry.prefix.length > best.prefix.length)) {
1676
+ best = entry;
1677
+ }
1678
+ }
1679
+ if (best === void 0) return void 0;
1680
+ return freezeEntity(best.entity, getFlows());
1681
+ };
1642
1682
  const list = (kind) => {
1643
1683
  assertEntityKind(kind);
1644
1684
  const flows = getFlows();
@@ -1689,6 +1729,7 @@ function createRegistry() {
1689
1729
  return {
1690
1730
  add,
1691
1731
  get,
1732
+ matchPattern,
1692
1733
  list,
1693
1734
  query,
1694
1735
  byScope,
@@ -2397,10 +2438,18 @@ function audit(opts) {
2397
2438
  }
2398
2439
  if (lint) {
2399
2440
  const dynamicAttrRe = /\bdata-uidex(?:-(region|widget|primitive))?\s*=\s*\{/g;
2441
+ const templateWithPrefixRe = /\bdata-uidex(?:-(region|widget|primitive))?\s*=\s*\{\s*`[^`$]+\$\{/g;
2400
2442
  for (const f of files) {
2443
+ const templatePrefixPositions = /* @__PURE__ */ new Set();
2444
+ templateWithPrefixRe.lastIndex = 0;
2445
+ let tm;
2446
+ while ((tm = templateWithPrefixRe.exec(f.content)) !== null) {
2447
+ templatePrefixPositions.add(tm.index);
2448
+ }
2401
2449
  let m;
2402
2450
  dynamicAttrRe.lastIndex = 0;
2403
2451
  while ((m = dynamicAttrRe.exec(f.content)) !== null) {
2452
+ if (templatePrefixPositions.has(m.index)) continue;
2404
2453
  const kind = m[1] ?? "element";
2405
2454
  let line = 1;
2406
2455
  for (let i = 0; i < m.index; i++) if (f.content[i] === "\n") line++;
@@ -2484,7 +2533,7 @@ function audit(opts) {
2484
2533
  if (lint && coverageEnabled) {
2485
2534
  for (const flow of registry.list("flow")) {
2486
2535
  for (const touchedId of flow.touches) {
2487
- const found = registry.get("element", touchedId) ?? registry.get("widget", touchedId) ?? registry.get("region", touchedId);
2536
+ const found = registry.get("element", touchedId) ?? registry.get("widget", touchedId) ?? registry.get("region", touchedId) ?? registry.matchPattern("element", touchedId) ?? registry.matchPattern("widget", touchedId) ?? registry.matchPattern("region", touchedId);
2488
2537
  if (!found) {
2489
2538
  diagnostics.push({
2490
2539
  code: "unknown-reference",