{"version":3,"file":"getRouteNodes.cjs","names":[],"sources":["../../../../src/filesystem/physical/getRouteNodes.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport {\n  cleanPath,\n  determineInitialRoutePath,\n  escapeRegExp,\n  hasEscapedLeadingUnderscore,\n  removeExt,\n  replaceBackslash,\n  routePathToVariable,\n  unwrapBracketWrappedSegment,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesVirtual } from '../virtual/getRouteNodes'\nimport { loadConfigFile } from '../virtual/loadConfigFile'\nimport { logging } from '../../logger'\nimport { rootPathId } from './rootPathId'\nimport type {\n  VirtualRootRoute,\n  VirtualRouteSubtreeConfig,\n} from '@tanstack/virtual-file-routes'\nimport type { FsRouteType, GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\n/**\n * Pre-compiled segment regexes for matching token patterns against route segments.\n * These are created once (in Generator constructor) and passed through to avoid\n * repeated regex compilation during route crawling.\n */\nexport interface TokenRegexBundle {\n  indexTokenSegmentRegex: RegExp\n  routeTokenSegmentRegex: RegExp\n}\n\nconst disallowedRouteGroupConfiguration = /\\(([^)]+)\\).(ts|js|tsx|jsx|vue)/\n\nconst virtualConfigFileRegExp = /__virtual\\.[mc]?[jt]s$/\nexport function isVirtualConfigFile(fileName: string): boolean {\n  return virtualConfigFileRegExp.test(fileName)\n}\n\nexport async function getRouteNodes(\n  config: Pick<\n    Config,\n    | 'routesDirectory'\n    | 'routeFilePrefix'\n    | 'routeFileIgnorePrefix'\n    | 'routeFileIgnorePattern'\n    | 'disableLogging'\n    | 'routeToken'\n    | 'indexToken'\n  >,\n  root: string,\n  tokenRegexes: TokenRegexBundle,\n): Promise<GetRouteNodesResult> {\n  const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } =\n    config\n\n  const logger = logging({ disabled: config.disableLogging })\n  const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')\n\n  const routeNodes: Array<RouteNode> = []\n  const allPhysicalDirectories: Array<string> = []\n\n  async function recurse(dir: string) {\n    const fullDir = path.resolve(config.routesDirectory, dir)\n    let dirList = await fsp.readdir(fullDir, { withFileTypes: true })\n\n    dirList = dirList.filter((d) => {\n      if (\n        d.name.startsWith('.') ||\n        (routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix))\n      ) {\n        return false\n      }\n\n      if (routeFilePrefix) {\n        if (routeFileIgnorePattern) {\n          return (\n            d.name.startsWith(routeFilePrefix) &&\n            !d.name.match(routeFileIgnoreRegExp)\n          )\n        }\n\n        return d.name.startsWith(routeFilePrefix)\n      }\n\n      if (routeFileIgnorePattern) {\n        return !d.name.match(routeFileIgnoreRegExp)\n      }\n\n      return true\n    })\n\n    const virtualConfigFile = dirList.find((dirent) => {\n      return dirent.isFile() && isVirtualConfigFile(dirent.name)\n    })\n\n    if (virtualConfigFile !== undefined) {\n      const virtualRouteConfigExport = await loadConfigFile(\n        path.resolve(fullDir, virtualConfigFile.name),\n      )\n      let virtualRouteSubtreeConfig: VirtualRouteSubtreeConfig\n      if (typeof virtualRouteConfigExport.default === 'function') {\n        virtualRouteSubtreeConfig = await virtualRouteConfigExport.default()\n      } else {\n        virtualRouteSubtreeConfig = virtualRouteConfigExport.default\n      }\n      const dummyRoot: VirtualRootRoute = {\n        type: 'root',\n        file: '',\n        children: virtualRouteSubtreeConfig,\n      }\n      const { routeNodes: virtualRouteNodes, physicalDirectories } =\n        await getRouteNodesVirtual(\n          {\n            ...config,\n            routesDirectory: fullDir,\n            virtualRouteConfig: dummyRoot,\n          },\n          root,\n          tokenRegexes,\n        )\n      allPhysicalDirectories.push(...physicalDirectories)\n      virtualRouteNodes.forEach((node) => {\n        const normalizedDir = dir === './' ? '' : dir\n        const filePath = replaceBackslash(\n          path.join(normalizedDir, node.filePath),\n        )\n        const routePath = cleanPath(`/${normalizedDir}${node.routePath}`)\n\n        node.variableName = routePathToVariable(\n          cleanPath(`/${normalizedDir}/${removeExt(node.filePath)}`),\n        )\n        node.routePath = routePath\n        // Keep originalRoutePath aligned with routePath for escape detection\n        if (node.originalRoutePath) {\n          node.originalRoutePath = cleanPath(\n            `/${normalizedDir}${node.originalRoutePath}`,\n          )\n        }\n        node.filePath = filePath\n        // Virtual subtree nodes (from __virtual.ts) are embedded in a\n        // physical directory tree. They should use path-based parent\n        // inference, not the explicit virtual parent tracking. Clear any\n        // _virtualParentRoutePath that was set at construction time.\n        delete node._virtualParentRoutePath\n      })\n\n      routeNodes.push(...virtualRouteNodes)\n\n      return\n    }\n\n    await Promise.all(\n      dirList.map(async (dirent) => {\n        const fullPath = replaceBackslash(path.join(fullDir, dirent.name))\n        const relativePath = path.posix.join(dir, dirent.name)\n\n        if (dirent.isDirectory()) {\n          await recurse(relativePath)\n        } else if (fullPath.match(/\\.(tsx|ts|jsx|js|vue)$/)) {\n          const filePath = replaceBackslash(path.join(dir, dirent.name))\n          const filePathNoExt = removeExt(filePath)\n          const {\n            routePath: initialRoutePath,\n            originalRoutePath: initialOriginalRoutePath,\n          } = determineInitialRoutePath(filePathNoExt)\n\n          let routePath = initialRoutePath\n          let originalRoutePath = initialOriginalRoutePath\n\n          if (routeFilePrefix) {\n            routePath = routePath.replaceAll(routeFilePrefix, '')\n            originalRoutePath = originalRoutePath.replaceAll(\n              routeFilePrefix,\n              '',\n            )\n          }\n\n          if (disallowedRouteGroupConfiguration.test(dirent.name)) {\n            const errorMessage = `A route configuration for a route group was found at \\`${filePath}\\`. This is not supported. Did you mean to use a layout/pathless route instead?`\n            logger.error(`ERROR: ${errorMessage}`)\n            throw new Error(errorMessage)\n          }\n\n          const meta = getRouteMeta(routePath, originalRoutePath, tokenRegexes)\n          const variableName = meta.variableName\n          let routeType: FsRouteType = meta.fsRouteType\n\n          if (routeType === 'lazy') {\n            routePath = routePath.replace(/\\/lazy$/, '')\n            originalRoutePath = originalRoutePath.replace(/\\/lazy$/, '')\n          }\n\n          // this check needs to happen after the lazy route has been cleaned up\n          // since the routePath is used to determine if a route is pathless\n          if (\n            isValidPathlessLayoutRoute(\n              routePath,\n              originalRoutePath,\n              routeType,\n              tokenRegexes,\n            )\n          ) {\n            routeType = 'pathless_layout'\n          }\n\n          // Only show deprecation warning for .tsx/.ts files, not .vue files\n          // Vue files using .component.vue is the Vue-native way\n          const isVueFile = filePath.endsWith('.vue')\n          if (!isVueFile) {\n            ;(\n              [\n                ['component', 'component'],\n                ['errorComponent', 'errorComponent'],\n                ['notFoundComponent', 'notFoundComponent'],\n                ['pendingComponent', 'pendingComponent'],\n                ['loader', 'loader'],\n              ] satisfies Array<[FsRouteType, string]>\n            ).forEach(([matcher, type]) => {\n              if (routeType === matcher) {\n                logger.warn(\n                  `WARNING: The \\`.${type}.tsx\\` suffix used for the ${filePath} file is deprecated. Use the new \\`.lazy.tsx\\` suffix instead.`,\n                )\n              }\n            })\n          }\n\n          // Get the last segment of originalRoutePath to check for escaping\n          const originalSegments = originalRoutePath.split('/').filter(Boolean)\n          const lastOriginalSegmentForSuffix =\n            originalSegments[originalSegments.length - 1] || ''\n\n          const { routeTokenSegmentRegex, indexTokenSegmentRegex } =\n            tokenRegexes\n\n          // List of special suffixes that can be escaped\n          const specialSuffixes = [\n            'component',\n            'errorComponent',\n            'notFoundComponent',\n            'pendingComponent',\n            'loader',\n            'lazy',\n          ]\n\n          const routePathSegments = routePath.split('/').filter(Boolean)\n          const lastRouteSegment =\n            routePathSegments[routePathSegments.length - 1] || ''\n\n          const suffixToStrip = specialSuffixes.find((suffix) => {\n            const endsWithSuffix = routePath.endsWith(`/${suffix}`)\n            // A suffix is escaped if wrapped in brackets in the original: [lazy] means literal \"lazy\"\n            const isEscaped =\n              lastOriginalSegmentForSuffix.startsWith('[') &&\n              lastOriginalSegmentForSuffix.endsWith(']') &&\n              unwrapBracketWrappedSegment(lastOriginalSegmentForSuffix) ===\n                suffix\n            return endsWithSuffix && !isEscaped\n          })\n\n          const routeTokenCandidate = unwrapBracketWrappedSegment(\n            lastOriginalSegmentForSuffix,\n          )\n          const isRouteTokenEscaped =\n            lastOriginalSegmentForSuffix !== routeTokenCandidate &&\n            routeTokenSegmentRegex.test(routeTokenCandidate)\n\n          const shouldStripRouteToken =\n            routeTokenSegmentRegex.test(lastRouteSegment) &&\n            !isRouteTokenEscaped\n\n          if (suffixToStrip || shouldStripRouteToken) {\n            const stripSegment = suffixToStrip ?? lastRouteSegment\n            routePath = routePath.replace(\n              new RegExp(`/${escapeRegExp(stripSegment)}$`),\n              '',\n            )\n            originalRoutePath = originalRoutePath.replace(\n              new RegExp(`/${escapeRegExp(stripSegment)}$`),\n              '',\n            )\n          }\n\n          // Check if the index token should be treated specially or as a literal path\n          // Escaping stays literal-only: if the last original segment is bracket-wrapped,\n          // treat it as literal even if it matches the token regex.\n          const lastOriginalSegment =\n            originalRoutePath.split('/').filter(Boolean).pop() || ''\n\n          const indexTokenCandidate =\n            unwrapBracketWrappedSegment(lastOriginalSegment)\n          const isIndexEscaped =\n            lastOriginalSegment !== indexTokenCandidate &&\n            indexTokenSegmentRegex.test(indexTokenCandidate)\n\n          if (!isIndexEscaped) {\n            const updatedRouteSegments = routePath.split('/').filter(Boolean)\n            const updatedLastRouteSegment =\n              updatedRouteSegments[updatedRouteSegments.length - 1] || ''\n\n            if (indexTokenSegmentRegex.test(updatedLastRouteSegment)) {\n              if (routePathSegments.length === 1) {\n                routePath = '/'\n              }\n\n              if (lastOriginalSegment === updatedLastRouteSegment) {\n                originalRoutePath = '/'\n              }\n\n              // For layout routes, don't use '/' fallback - an empty path means\n              // \"layout for the parent path\" which is important for physical() mounts\n              // where route.tsx at root should have empty path, not '/'\n              const isLayoutRoute = routeType === 'layout'\n\n              routePath =\n                routePath.replace(\n                  new RegExp(`/${escapeRegExp(updatedLastRouteSegment)}$`),\n                  '/',\n                ) || (isLayoutRoute ? '' : '/')\n\n              originalRoutePath =\n                originalRoutePath.replace(\n                  new RegExp(`/${escapeRegExp(indexTokenCandidate)}$`),\n                  '/',\n                ) || (isLayoutRoute ? '' : '/')\n            }\n          }\n\n          routeNodes.push({\n            filePath,\n            fullPath,\n            routePath,\n            variableName,\n            _fsRouteType: routeType,\n            originalRoutePath,\n          })\n        }\n      }),\n    )\n\n    return routeNodes\n  }\n\n  await recurse('./')\n\n  // Find the root route node - prefer the actual route file over component/loader files\n  const rootRouteNode =\n    routeNodes.find(\n      (d) =>\n        d.routePath === `/${rootPathId}` &&\n        ![\n          'component',\n          'errorComponent',\n          'notFoundComponent',\n          'pendingComponent',\n          'loader',\n          'lazy',\n        ].includes(d._fsRouteType),\n    ) ?? routeNodes.find((d) => d.routePath === `/${rootPathId}`)\n  if (rootRouteNode) {\n    rootRouteNode._fsRouteType = '__root'\n    rootRouteNode.variableName = 'root'\n  }\n\n  return {\n    rootRouteNode,\n    routeNodes,\n    physicalDirectories: allPhysicalDirectories,\n  }\n}\n\n/**\n * Determines the metadata for a given route path based on the provided configuration.\n *\n * @param routePath - The determined initial routePath (with brackets removed).\n * @param originalRoutePath - The original route path (may contain brackets for escaped content).\n * @param tokenRegexes - Pre-compiled token regexes for matching.\n * @returns An object containing the type of the route and the variable name derived from the route path.\n */\nexport function getRouteMeta(\n  routePath: string,\n  originalRoutePath: string,\n  tokenRegexes: TokenRegexBundle,\n): {\n  // `__root` is can be more easily determined by filtering down to routePath === /${rootPathId}\n  // `pathless` is needs to determined after `lazy` has been cleaned up from the routePath\n  fsRouteType: Extract<\n    FsRouteType,\n    | 'static'\n    | 'layout'\n    | 'api'\n    | 'lazy'\n    | 'loader'\n    | 'component'\n    | 'pendingComponent'\n    | 'errorComponent'\n    | 'notFoundComponent'\n  >\n  variableName: string\n} {\n  let fsRouteType: FsRouteType = 'static'\n\n  // Get the last segment from the original path to check for escaping\n  const originalSegments = originalRoutePath.split('/').filter(Boolean)\n  const lastOriginalSegment =\n    originalSegments[originalSegments.length - 1] || ''\n\n  const { routeTokenSegmentRegex } = tokenRegexes\n\n  // Helper to check if a specific suffix is escaped (literal-only)\n  // A suffix is escaped if the original segment is wrapped in brackets: [lazy] means literal \"lazy\"\n  const isSuffixEscaped = (suffix: string): boolean => {\n    return (\n      lastOriginalSegment.startsWith('[') &&\n      lastOriginalSegment.endsWith(']') &&\n      unwrapBracketWrappedSegment(lastOriginalSegment) === suffix\n    )\n  }\n\n  const routeSegments = routePath.split('/').filter(Boolean)\n  const lastRouteSegment = routeSegments[routeSegments.length - 1] || ''\n\n  const routeTokenCandidate = unwrapBracketWrappedSegment(lastOriginalSegment)\n  const isRouteTokenEscaped =\n    lastOriginalSegment !== routeTokenCandidate &&\n    routeTokenSegmentRegex.test(routeTokenCandidate)\n\n  if (routeTokenSegmentRegex.test(lastRouteSegment) && !isRouteTokenEscaped) {\n    // layout routes, i.e `/foo/route.tsx` or `/foo/_layout/route.tsx`\n    fsRouteType = 'layout'\n  } else if (routePath.endsWith('/lazy') && !isSuffixEscaped('lazy')) {\n    // lazy routes, i.e. `/foo.lazy.tsx`\n    fsRouteType = 'lazy'\n  } else if (routePath.endsWith('/loader') && !isSuffixEscaped('loader')) {\n    // loader routes, i.e. `/foo.loader.tsx`\n    fsRouteType = 'loader'\n  } else if (\n    routePath.endsWith('/component') &&\n    !isSuffixEscaped('component')\n  ) {\n    // component routes, i.e. `/foo.component.tsx`\n    fsRouteType = 'component'\n  } else if (\n    routePath.endsWith('/pendingComponent') &&\n    !isSuffixEscaped('pendingComponent')\n  ) {\n    // pending component routes, i.e. `/foo.pendingComponent.tsx`\n    fsRouteType = 'pendingComponent'\n  } else if (\n    routePath.endsWith('/errorComponent') &&\n    !isSuffixEscaped('errorComponent')\n  ) {\n    // error component routes, i.e. `/foo.errorComponent.tsx`\n    fsRouteType = 'errorComponent'\n  } else if (\n    routePath.endsWith('/notFoundComponent') &&\n    !isSuffixEscaped('notFoundComponent')\n  ) {\n    // not found component routes, i.e. `/foo.notFoundComponent.tsx`\n    fsRouteType = 'notFoundComponent'\n  }\n\n  // Use originalRoutePath for variable name when any segment is fully\n  // bracket-wrapped (e.g. [index], [route], [_]auth) to avoid collisions\n  // with their non-escaped counterparts that get special token treatment\n  const hasFullyEscapedSegment = originalSegments.some(\n    (seg) =>\n      seg.startsWith('[') &&\n      seg.endsWith(']') &&\n      !seg.slice(1, -1).includes('[') &&\n      !seg.slice(1, -1).includes(']'),\n  )\n  const variableName = routePathToVariable(\n    hasFullyEscapedSegment ? originalRoutePath : routePath,\n  )\n\n  return { fsRouteType, variableName }\n}\n\n/**\n * Used to validate if a route is a pathless layout route\n * @param normalizedRoutePath Normalized route path, i.e `/foo/_layout/route.tsx` and `/foo._layout.route.tsx` to `/foo/_layout/route`\n * @param originalRoutePath Original route path with brackets for escaped content\n * @param routeType The route type determined from file extension\n * @param tokenRegexes Pre-compiled token regexes for matching\n * @returns Boolean indicating if the route is a pathless layout route\n */\nfunction isValidPathlessLayoutRoute(\n  normalizedRoutePath: string,\n  originalRoutePath: string,\n  routeType: FsRouteType,\n  tokenRegexes: TokenRegexBundle,\n): boolean {\n  if (routeType === 'lazy') {\n    return false\n  }\n\n  const segments = normalizedRoutePath.split('/').filter(Boolean)\n  const originalSegments = originalRoutePath.split('/').filter(Boolean)\n\n  if (segments.length === 0) {\n    return false\n  }\n\n  const lastRouteSegment = segments[segments.length - 1]!\n  const lastOriginalSegment =\n    originalSegments[originalSegments.length - 1] || ''\n  const secondToLastRouteSegment = segments[segments.length - 2]\n  const secondToLastOriginalSegment =\n    originalSegments[originalSegments.length - 2]\n\n  // If segment === __root, then exit as false\n  if (lastRouteSegment === rootPathId) {\n    return false\n  }\n\n  const { routeTokenSegmentRegex, indexTokenSegmentRegex } = tokenRegexes\n\n  // If segment matches routeToken and secondToLastSegment is a string that starts with _, then exit as true\n  // Since the route is actually a configuration route for a layout/pathless route\n  // i.e. /foo/_layout/route.tsx === /foo/_layout.tsx\n  // But if the underscore is escaped, it's not a pathless layout\n  if (\n    routeTokenSegmentRegex.test(lastRouteSegment) &&\n    typeof secondToLastRouteSegment === 'string' &&\n    typeof secondToLastOriginalSegment === 'string'\n  ) {\n    // Check if the underscore is escaped\n    if (hasEscapedLeadingUnderscore(secondToLastOriginalSegment)) {\n      return false\n    }\n    return secondToLastRouteSegment.startsWith('_')\n  }\n\n  // Segment starts with _ but check if it's escaped\n  // If the original segment has [_] at the start, the underscore is escaped and it's not a pathless layout\n  if (hasEscapedLeadingUnderscore(lastOriginalSegment)) {\n    return false\n  }\n\n  return (\n    !indexTokenSegmentRegex.test(lastRouteSegment) &&\n    !routeTokenSegmentRegex.test(lastRouteSegment) &&\n    lastRouteSegment.startsWith('_')\n  )\n}\n"],"mappings":";;;;;;;;;;;AAiCA,IAAM,oCAAoC;AAE1C,IAAM,0BAA0B;AAChC,SAAgB,oBAAoB,UAA2B;AAC7D,QAAO,wBAAwB,KAAK,SAAS;;AAG/C,eAAsB,cACpB,QAUA,MACA,cAC8B;CAC9B,MAAM,EAAE,iBAAiB,uBAAuB,2BAC9C;CAEF,MAAM,SAAS,eAAA,QAAQ,EAAE,UAAU,OAAO,gBAAgB,CAAC;CAC3D,MAAM,wBAAwB,IAAI,OAAO,0BAA0B,IAAI,IAAI;CAE3E,MAAM,aAA+B,EAAE;CACvC,MAAM,yBAAwC,EAAE;CAEhD,eAAe,QAAQ,KAAa;EAClC,MAAM,UAAU,UAAA,QAAK,QAAQ,OAAO,iBAAiB,IAAI;EACzD,IAAI,UAAU,MAAM,iBAAI,QAAQ,SAAS,EAAE,eAAe,MAAM,CAAC;AAEjE,YAAU,QAAQ,QAAQ,MAAM;AAC9B,OACE,EAAE,KAAK,WAAW,IAAI,IACrB,yBAAyB,EAAE,KAAK,WAAW,sBAAsB,CAElE,QAAO;AAGT,OAAI,iBAAiB;AACnB,QAAI,uBACF,QACE,EAAE,KAAK,WAAW,gBAAgB,IAClC,CAAC,EAAE,KAAK,MAAM,sBAAsB;AAIxC,WAAO,EAAE,KAAK,WAAW,gBAAgB;;AAG3C,OAAI,uBACF,QAAO,CAAC,EAAE,KAAK,MAAM,sBAAsB;AAG7C,UAAO;IACP;EAEF,MAAM,oBAAoB,QAAQ,MAAM,WAAW;AACjD,UAAO,OAAO,QAAQ,IAAI,oBAAoB,OAAO,KAAK;IAC1D;AAEF,MAAI,sBAAsB,KAAA,GAAW;GACnC,MAAM,2BAA2B,MAAM,uBAAA,eACrC,UAAA,QAAK,QAAQ,SAAS,kBAAkB,KAAK,CAC9C;GACD,IAAI;AACJ,OAAI,OAAO,yBAAyB,YAAY,WAC9C,6BAA4B,MAAM,yBAAyB,SAAS;OAEpE,6BAA4B,yBAAyB;GAEvD,MAAM,YAA8B;IAClC,MAAM;IACN,MAAM;IACN,UAAU;IACX;GACD,MAAM,EAAE,YAAY,mBAAmB,wBACrC,MAAM,sBAAA,cACJ;IACE,GAAG;IACH,iBAAiB;IACjB,oBAAoB;IACrB,EACD,MACA,aACD;AACH,0BAAuB,KAAK,GAAG,oBAAoB;AACnD,qBAAkB,SAAS,SAAS;IAClC,MAAM,gBAAgB,QAAQ,OAAO,KAAK;IAC1C,MAAM,WAAW,cAAA,iBACf,UAAA,QAAK,KAAK,eAAe,KAAK,SAAS,CACxC;IACD,MAAM,YAAY,cAAA,UAAU,IAAI,gBAAgB,KAAK,YAAY;AAEjE,SAAK,eAAe,cAAA,oBAClB,cAAA,UAAU,IAAI,cAAc,GAAG,cAAA,UAAU,KAAK,SAAS,GAAG,CAC3D;AACD,SAAK,YAAY;AAEjB,QAAI,KAAK,kBACP,MAAK,oBAAoB,cAAA,UACvB,IAAI,gBAAgB,KAAK,oBAC1B;AAEH,SAAK,WAAW;AAKhB,WAAO,KAAK;KACZ;AAEF,cAAW,KAAK,GAAG,kBAAkB;AAErC;;AAGF,QAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,WAAW;GAC5B,MAAM,WAAW,cAAA,iBAAiB,UAAA,QAAK,KAAK,SAAS,OAAO,KAAK,CAAC;GAClE,MAAM,eAAe,UAAA,QAAK,MAAM,KAAK,KAAK,OAAO,KAAK;AAEtD,OAAI,OAAO,aAAa,CACtB,OAAM,QAAQ,aAAa;YAClB,SAAS,MAAM,yBAAyB,EAAE;IACnD,MAAM,WAAW,cAAA,iBAAiB,UAAA,QAAK,KAAK,KAAK,OAAO,KAAK,CAAC;IAE9D,MAAM,EACJ,WAAW,kBACX,mBAAmB,6BACjB,cAAA,0BAJkB,cAAA,UAAU,SAAS,CAIG;IAE5C,IAAI,YAAY;IAChB,IAAI,oBAAoB;AAExB,QAAI,iBAAiB;AACnB,iBAAY,UAAU,WAAW,iBAAiB,GAAG;AACrD,yBAAoB,kBAAkB,WACpC,iBACA,GACD;;AAGH,QAAI,kCAAkC,KAAK,OAAO,KAAK,EAAE;KACvD,MAAM,eAAe,0DAA0D,SAAS;AACxF,YAAO,MAAM,UAAU,eAAe;AACtC,WAAM,IAAI,MAAM,aAAa;;IAG/B,MAAM,OAAO,aAAa,WAAW,mBAAmB,aAAa;IACrE,MAAM,eAAe,KAAK;IAC1B,IAAI,YAAyB,KAAK;AAElC,QAAI,cAAc,QAAQ;AACxB,iBAAY,UAAU,QAAQ,WAAW,GAAG;AAC5C,yBAAoB,kBAAkB,QAAQ,WAAW,GAAG;;AAK9D,QACE,2BACE,WACA,mBACA,WACA,aACD,CAED,aAAY;AAMd,QAAI,CADc,SAAS,SAAS,OAAO,CAGvC;KACE,CAAC,aAAa,YAAY;KAC1B,CAAC,kBAAkB,iBAAiB;KACpC,CAAC,qBAAqB,oBAAoB;KAC1C,CAAC,oBAAoB,mBAAmB;KACxC,CAAC,UAAU,SAAS;KACrB,CACD,SAAS,CAAC,SAAS,UAAU;AAC7B,SAAI,cAAc,QAChB,QAAO,KACL,mBAAmB,KAAK,6BAA6B,SAAS,gEAC/D;MAEH;IAIJ,MAAM,mBAAmB,kBAAkB,MAAM,IAAI,CAAC,OAAO,QAAQ;IACrE,MAAM,+BACJ,iBAAiB,iBAAiB,SAAS,MAAM;IAEnD,MAAM,EAAE,wBAAwB,2BAC9B;IAGF,MAAM,kBAAkB;KACtB;KACA;KACA;KACA;KACA;KACA;KACD;IAED,MAAM,oBAAoB,UAAU,MAAM,IAAI,CAAC,OAAO,QAAQ;IAC9D,MAAM,mBACJ,kBAAkB,kBAAkB,SAAS,MAAM;IAErD,MAAM,gBAAgB,gBAAgB,MAAM,WAAW;KACrD,MAAM,iBAAiB,UAAU,SAAS,IAAI,SAAS;KAEvD,MAAM,YACJ,6BAA6B,WAAW,IAAI,IAC5C,6BAA6B,SAAS,IAAI,IAC1C,cAAA,4BAA4B,6BAA6B,KACvD;AACJ,YAAO,kBAAkB,CAAC;MAC1B;IAEF,MAAM,sBAAsB,cAAA,4BAC1B,6BACD;IACD,MAAM,sBACJ,iCAAiC,uBACjC,uBAAuB,KAAK,oBAAoB;IAElD,MAAM,wBACJ,uBAAuB,KAAK,iBAAiB,IAC7C,CAAC;AAEH,QAAI,iBAAiB,uBAAuB;KAC1C,MAAM,eAAe,iBAAiB;AACtC,iBAAY,UAAU,QACpB,IAAI,OAAO,IAAI,cAAA,aAAa,aAAa,CAAC,GAAG,EAC7C,GACD;AACD,yBAAoB,kBAAkB,QACpC,IAAI,OAAO,IAAI,cAAA,aAAa,aAAa,CAAC,GAAG,EAC7C,GACD;;IAMH,MAAM,sBACJ,kBAAkB,MAAM,IAAI,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;IAExD,MAAM,sBACJ,cAAA,4BAA4B,oBAAoB;AAKlD,QAAI,EAHF,wBAAwB,uBACxB,uBAAuB,KAAK,oBAAoB,GAE7B;KACnB,MAAM,uBAAuB,UAAU,MAAM,IAAI,CAAC,OAAO,QAAQ;KACjE,MAAM,0BACJ,qBAAqB,qBAAqB,SAAS,MAAM;AAE3D,SAAI,uBAAuB,KAAK,wBAAwB,EAAE;AACxD,UAAI,kBAAkB,WAAW,EAC/B,aAAY;AAGd,UAAI,wBAAwB,wBAC1B,qBAAoB;MAMtB,MAAM,gBAAgB,cAAc;AAEpC,kBACE,UAAU,QACR,IAAI,OAAO,IAAI,cAAA,aAAa,wBAAwB,CAAC,GAAG,EACxD,IACD,KAAK,gBAAgB,KAAK;AAE7B,0BACE,kBAAkB,QAChB,IAAI,OAAO,IAAI,cAAA,aAAa,oBAAoB,CAAC,GAAG,EACpD,IACD,KAAK,gBAAgB,KAAK;;;AAIjC,eAAW,KAAK;KACd;KACA;KACA;KACA;KACA,cAAc;KACd;KACD,CAAC;;IAEJ,CACH;AAED,SAAO;;AAGT,OAAM,QAAQ,KAAK;CAGnB,MAAM,gBACJ,WAAW,MACR,MACC,EAAE,cAAc,aAChB,CAAC;EACC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,SAAS,EAAE,aAAa,CAC7B,IAAI,WAAW,MAAM,MAAM,EAAE,cAAc,UAAiB;AAC/D,KAAI,eAAe;AACjB,gBAAc,eAAe;AAC7B,gBAAc,eAAe;;AAG/B,QAAO;EACL;EACA;EACA,qBAAqB;EACtB;;;;;;;;;;AAWH,SAAgB,aACd,WACA,mBACA,cAiBA;CACA,IAAI,cAA2B;CAG/B,MAAM,mBAAmB,kBAAkB,MAAM,IAAI,CAAC,OAAO,QAAQ;CACrE,MAAM,sBACJ,iBAAiB,iBAAiB,SAAS,MAAM;CAEnD,MAAM,EAAE,2BAA2B;CAInC,MAAM,mBAAmB,WAA4B;AACnD,SACE,oBAAoB,WAAW,IAAI,IACnC,oBAAoB,SAAS,IAAI,IACjC,cAAA,4BAA4B,oBAAoB,KAAK;;CAIzD,MAAM,gBAAgB,UAAU,MAAM,IAAI,CAAC,OAAO,QAAQ;CAC1D,MAAM,mBAAmB,cAAc,cAAc,SAAS,MAAM;CAEpE,MAAM,sBAAsB,cAAA,4BAA4B,oBAAoB;CAC5E,MAAM,sBACJ,wBAAwB,uBACxB,uBAAuB,KAAK,oBAAoB;AAElD,KAAI,uBAAuB,KAAK,iBAAiB,IAAI,CAAC,oBAEpD,eAAc;UACL,UAAU,SAAS,QAAQ,IAAI,CAAC,gBAAgB,OAAO,CAEhE,eAAc;UACL,UAAU,SAAS,UAAU,IAAI,CAAC,gBAAgB,SAAS,CAEpE,eAAc;UAEd,UAAU,SAAS,aAAa,IAChC,CAAC,gBAAgB,YAAY,CAG7B,eAAc;UAEd,UAAU,SAAS,oBAAoB,IACvC,CAAC,gBAAgB,mBAAmB,CAGpC,eAAc;UAEd,UAAU,SAAS,kBAAkB,IACrC,CAAC,gBAAgB,iBAAiB,CAGlC,eAAc;UAEd,UAAU,SAAS,qBAAqB,IACxC,CAAC,gBAAgB,oBAAoB,CAGrC,eAAc;CAahB,MAAM,eAAe,cAAA,oBAPU,iBAAiB,MAC7C,QACC,IAAI,WAAW,IAAI,IACnB,IAAI,SAAS,IAAI,IACjB,CAAC,IAAI,MAAM,GAAG,GAAG,CAAC,SAAS,IAAI,IAC/B,CAAC,IAAI,MAAM,GAAG,GAAG,CAAC,SAAS,IAAI,CAClC,GAE0B,oBAAoB,UAC9C;AAED,QAAO;EAAE;EAAa;EAAc;;;;;;;;;;AAWtC,SAAS,2BACP,qBACA,mBACA,WACA,cACS;AACT,KAAI,cAAc,OAChB,QAAO;CAGT,MAAM,WAAW,oBAAoB,MAAM,IAAI,CAAC,OAAO,QAAQ;CAC/D,MAAM,mBAAmB,kBAAkB,MAAM,IAAI,CAAC,OAAO,QAAQ;AAErE,KAAI,SAAS,WAAW,EACtB,QAAO;CAGT,MAAM,mBAAmB,SAAS,SAAS,SAAS;CACpD,MAAM,sBACJ,iBAAiB,iBAAiB,SAAS,MAAM;CACnD,MAAM,2BAA2B,SAAS,SAAS,SAAS;CAC5D,MAAM,8BACJ,iBAAiB,iBAAiB,SAAS;AAG7C,KAAI,qBAAA,SACF,QAAO;CAGT,MAAM,EAAE,wBAAwB,2BAA2B;AAM3D,KACE,uBAAuB,KAAK,iBAAiB,IAC7C,OAAO,6BAA6B,YACpC,OAAO,gCAAgC,UACvC;AAEA,MAAI,cAAA,4BAA4B,4BAA4B,CAC1D,QAAO;AAET,SAAO,yBAAyB,WAAW,IAAI;;AAKjD,KAAI,cAAA,4BAA4B,oBAAoB,CAClD,QAAO;AAGT,QACE,CAAC,uBAAuB,KAAK,iBAAiB,IAC9C,CAAC,uBAAuB,KAAK,iBAAiB,IAC9C,iBAAiB,WAAW,IAAI"}