@decantr/verifier 3.5.3 → 3.5.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/dist/index.js CHANGED
@@ -2363,6 +2363,8 @@ var STYLE_EXTENSIONS = /* @__PURE__ */ new Set([".css", ".scss", ".sass", ".less
2363
2363
  var PAGE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".vue", ".svelte", ".html"]);
2364
2364
  var ROUTE_VARIABLE_NAMES = "(?:path|pathname|route|currentPath|currentRoute|locationPath|activePath)";
2365
2365
  var ROUTE_ASSET_EXTENSION_RE = /\.(?:avif|bmp|css|gif|ico|jpeg|jpg|js|json|map|mp4|pdf|png|svg|webp|woff2?)$/i;
2366
+ var JSX_ROUTE_PATH_RE = /<(?:Route|[A-Z][\w.]*Route)\b[^>]*\bpath\s*=\s*(?:"([^"]+)"|'([^']+)'|{\s*"([^"]+)"\s*}|{\s*'([^']+)'\s*}|{\s*`([^`]+)`\s*})/g;
2367
+ var OBJECT_ROUTE_PATH_RE = /\bpath\s*:\s*(?:"([^"]+)"|'([^']+)'|`([^`]+)`)/g;
2366
2368
  var MAX_FILE_READ_BYTES = 512 * 1024;
2367
2369
  var MAX_WALK_FILES = 5e3;
2368
2370
  var MAX_REPORT_ROUTES = 80;
@@ -2629,9 +2631,12 @@ function fileRouteFromPath(file, baseDir) {
2629
2631
  function scanFileRoutes(projectRoot, baseDir, extensions = PAGE_EXTENSIONS) {
2630
2632
  const fullBase = join3(projectRoot, baseDir);
2631
2633
  if (!existsSync3(fullBase)) return [];
2632
- return walkFiles(fullBase, { extensions }).map((file) => {
2634
+ return walkFiles(fullBase, { extensions }).flatMap((file) => {
2635
+ const baseName = file.split("/").pop() ?? file;
2636
+ const routeFileName = baseName.slice(0, -extname3(baseName).length);
2637
+ if (routeFileName.startsWith("_")) return [];
2633
2638
  const rel = relative3(projectRoot, join3(fullBase, file)).replace(/\\/g, "/");
2634
- return { path: fileRouteFromPath(rel, baseDir), file: rel, hasLayout: false };
2639
+ return [{ path: fileRouteFromPath(rel, baseDir), file: rel, hasLayout: false }];
2635
2640
  });
2636
2641
  }
2637
2642
  function scanReactRouter(projectRoot) {
@@ -2642,15 +2647,17 @@ function scanReactRouter(projectRoot) {
2642
2647
  const content = readTextFile(join3(projectRoot, file));
2643
2648
  if (!content) continue;
2644
2649
  if (content.includes("HashRouter") || content.includes("createHashRouter")) hashRouting = true;
2645
- const jsxRouteRegex = /<Route\b[^>]*\bpath\s*=\s*["']([^"']+)["']/g;
2646
- for (const match of content.matchAll(jsxRouteRegex)) {
2647
- const route = normalizeDetectedRouteLiteral(match[1] || "/");
2648
- if (route) routes.set(route, { path: route, file, hasLayout: false });
2650
+ for (const match of content.matchAll(JSX_ROUTE_PATH_RE)) {
2651
+ const literal = firstRouteLiteralMatch(match);
2652
+ for (const route of normalizeDetectedRouteLiterals(literal || "/")) {
2653
+ routes.set(route, { path: route, file, hasLayout: false });
2654
+ }
2649
2655
  }
2650
- const objectRouteRegex = /\bpath\s*:\s*["']([^"']+)["']/g;
2651
- for (const match of content.matchAll(objectRouteRegex)) {
2652
- const route = normalizeDetectedRouteLiteral(match[1] || "/");
2653
- if (route) routes.set(route, { path: route, file, hasLayout: false });
2656
+ for (const match of content.matchAll(OBJECT_ROUTE_PATH_RE)) {
2657
+ const literal = firstRouteLiteralMatch(match);
2658
+ for (const route of normalizeDetectedRouteLiterals(literal || "/")) {
2659
+ routes.set(route, { path: route, file, hasLayout: false });
2660
+ }
2654
2661
  }
2655
2662
  for (const route of detectPathnameBranchRoutes(content)) {
2656
2663
  routes.set(route, { path: route, file, hasLayout: false });
@@ -2661,21 +2668,36 @@ function scanReactRouter(projectRoot) {
2661
2668
  }
2662
2669
  return { routes: [...routes.values()], hashRouting };
2663
2670
  }
2664
- function normalizeDetectedRouteLiteral(value) {
2665
- const cleaned = value.trim().split(/[?#]/)[0];
2666
- if (!cleaned || cleaned === "/") return "/";
2667
- if (cleaned === "*" || cleaned === "**" || cleaned.startsWith("#")) return null;
2668
- if (!cleaned.startsWith("/") || cleaned.startsWith("//")) return null;
2669
- if (ROUTE_ASSET_EXTENSION_RE.test(cleaned)) return null;
2670
- return cleaned.replace(/\/+$/g, "") || "/";
2671
+ function firstRouteLiteralMatch(match) {
2672
+ return match.slice(1).find((value) => typeof value === "string") ?? null;
2673
+ }
2674
+ function normalizeDetectedRouteLiterals(value) {
2675
+ const withoutHash = value.trim().split("#")[0];
2676
+ const cleaned = withoutHash.includes("?") && !withoutHash.endsWith(")?") ? withoutHash.split("?")[0] : withoutHash;
2677
+ if (!cleaned || cleaned === "/") return ["/"];
2678
+ if (cleaned === "*" || cleaned === "**" || cleaned.startsWith("#")) return [];
2679
+ if (cleaned === "/*" || cleaned === "/**") return [];
2680
+ if (!cleaned.startsWith("/") || cleaned.startsWith("//")) return [];
2681
+ if (ROUTE_ASSET_EXTENSION_RE.test(cleaned)) return [];
2682
+ const optionalGroup = cleaned.match(/^\/\(([^()]+)\)\?$/);
2683
+ if (optionalGroup) {
2684
+ return [
2685
+ "/",
2686
+ ...optionalGroup[1].split("|").map((segment) => segment.trim()).filter(Boolean).map((segment) => `/${segment}`)
2687
+ ];
2688
+ }
2689
+ const withoutTrailingWildcard = cleaned.endsWith("*") && !cleaned.endsWith("/*") && !/:\w+\*$/.test(cleaned) ? cleaned.slice(0, -1) : cleaned;
2690
+ const normalized = withoutTrailingWildcard.replace(/\/+$/g, "") || "/";
2691
+ if (normalized === "/*" || normalized === "/**") return [];
2692
+ return [normalized];
2671
2693
  }
2672
2694
  function collectRouteLiterals(pattern, content, routes) {
2673
2695
  let count = 0;
2674
2696
  for (const match of content.matchAll(pattern)) {
2675
- const route = normalizeDetectedRouteLiteral(match[1] ?? "");
2676
- if (!route) continue;
2677
- routes.add(route);
2678
- count += 1;
2697
+ for (const route of normalizeDetectedRouteLiterals(match[1] ?? "")) {
2698
+ routes.add(route);
2699
+ count += 1;
2700
+ }
2679
2701
  }
2680
2702
  return count;
2681
2703
  }