svelte-qa-ids 1.0.0 → 1.0.2

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.
@@ -113,7 +113,7 @@ function enhanceAst(node, parent = null) {
113
113
  function buildPathSegments(node, abbreviations = DEFAULT_ABBREVIATIONS) {
114
114
  const pathSegments = [];
115
115
  let tempNode = node;
116
- while (tempNode && tempNode.parent) {
116
+ while (tempNode?.parent) {
117
117
  if (tempNode.type === "Element" && tempNode.siblingIndex !== void 0) {
118
118
  const tagName = getTagAbbreviation(tempNode.name, abbreviations);
119
119
  let segment = tagName;
@@ -401,4 +401,4 @@ export {
401
401
  inject,
402
402
  injectPromise
403
403
  };
404
- //# sourceMappingURL=chunk-7MRS72CP.js.map
404
+ //# sourceMappingURL=chunk-XHMXW33M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * svelte-qa-ids\n * Automatically inject stable data-qa-id attributes into Svelte components\n */\n\nimport { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join, relative } from \"node:path\";\nimport { Data, Effect } from \"effect\";\nimport { parse, preprocess } from \"svelte/compiler\";\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\nexport class FileReadError extends Data.TaggedError(\"FileReadError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class FileWriteError extends Data.TaggedError(\"FileWriteError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class SvelteParseError extends Data.TaggedError(\"SvelteParseError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class FileSystemError extends Data.TaggedError(\"FileSystemError\")<{\n readonly path: string;\n readonly cause: unknown;\n}> {}\n\nexport class ValidationError extends Data.TaggedError(\"ValidationError\")<{\n readonly field: string;\n readonly value: unknown;\n readonly message: string;\n}> {}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Options {\n /**\n * Custom abbreviations for HTML tags\n * @default { common abbreviations }\n */\n abbreviations?: Record<string, string>;\n\n /**\n * Number of characters from component name to use for ID prefix\n * @default 3\n * @throws {ValidationError} When value is outside 2-10 range\n * @validation Must be between 2 and 10 characters\n */\n prefixLength?: number;\n\n /**\n * Custom prefix generator function\n * @default built-in prefix generator\n */\n prefixGenerator?: (filePath: string) => string;\n\n /**\n * Component names to skip (e.g., icon libraries)\n * @default lucide-svelte components\n */\n skipComponents?: Set<string> | string[];\n\n /**\n * Include files matching these patterns\n */\n include?: string[];\n\n /**\n * Exclude files matching these patterns\n * @default {string[]} []\n */\n exclude?: string[];\n\n /**\n * Whether to preserve original content for files with parsing errors\n * @default true\n */\n preserveOnError?: boolean;\n\n /**\n * Dry run - don't modify files\n * @default false\n */\n dryRun?: boolean;\n\n /**\n * Verbose logging\n * @default false\n */\n verbose?: boolean;\n}\n\nexport interface Result {\n file: string;\n success: boolean;\n error?: string;\n injectedCount?: number;\n skipped?: boolean;\n}\n\n// ============================================================================\n// AST Types\n// ============================================================================\n\ninterface SvelteAstNode {\n type: string;\n name?: string;\n start?: number;\n end?: number;\n parent?: SvelteAstNode | null;\n siblingIndex?: number;\n siblingCount?: number;\n children?: SvelteAstNode[];\n consequent?: SvelteAstNode | SvelteAstNode[];\n alternate?: SvelteAstNode | SvelteAstNode[];\n blocks?: SvelteAstNode[];\n fragment?: SvelteAstNode[];\n [key: string]: unknown;\n}\n\ninterface ElementToModify {\n qaId: string;\n insertionPoint: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_ABBREVIATIONS: Record<string, string> = {\n div: \"d\",\n span: \"sp\",\n section: \"sec\",\n button: \"btn\",\n a: \"a\",\n p: \"p\",\n img: \"img\",\n ul: \"ul\",\n li: \"li\",\n form: \"f\",\n input: \"in\",\n label: \"lbl\",\n h1: \"h1\",\n h2: \"h2\",\n h3: \"h3\",\n h4: \"h4\",\n h5: \"h5\",\n h6: \"h6\",\n};\n\nconst ROUTE_PREFIX_REGEX = /^src\\/routes\\/?/;\n\n// ============================================================================\n// Core Functions\n// ============================================================================\n\n/**\n * Validates prefixLength is within acceptable range (2-10).\n */\nconst validatePrefixLength = (\n prefixLength?: number\n): Effect.Effect<void, ValidationError> =>\n prefixLength !== undefined && (prefixLength < 2 || prefixLength > 10)\n ? Effect.fail(\n new ValidationError({\n field: \"prefixLength\",\n value: prefixLength,\n message: \"prefixLength must be between 2 and 10 characters\",\n })\n )\n : Effect.void;\n\n/**\n * Returns the abbreviation for a given HTML tag.\n */\nexport { getTagAbbreviation };\n\nfunction getTagAbbreviation(\n tagName: string,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): string {\n return abbreviations[tagName] || tagName;\n}\n\n/**\n * Default component prefix generator based on file path.\n */\nconst ROOT_ROUTE_PREFIX = \"rt\" as const;\n\nexport { defaultPrefixGenerator };\n\nfunction defaultPrefixGenerator(filePath: string, prefixLength = 3): string {\n const projectRoot = process.cwd();\n const relativePath = relative(projectRoot, filePath);\n\n if (relativePath.startsWith(\"src/routes\")) {\n const routeDir = dirname(relativePath).replace(ROUTE_PREFIX_REGEX, \"\");\n if (routeDir === \"\") {\n return ROOT_ROUTE_PREFIX;\n }\n const lastPart = routeDir.split(\"/\").pop() || \"\";\n return lastPart.substring(0, Math.min(prefixLength, lastPart.length));\n }\n if (relativePath.startsWith(\"src/lib/\")) {\n const fileName = basename(filePath, \".svelte\");\n return fileName\n .split(\"-\")\n .map((part: string) =>\n part.substring(0, Math.min(prefixLength, part.length))\n )\n .join(\"-\");\n }\n\n const baseName = basename(filePath, \".svelte\");\n return baseName.substring(0, Math.min(prefixLength, baseName.length));\n}\n\n/**\n * Walks the Svelte AST and enhances nodes with parent pointers and sibling info.\n */\nfunction enhanceAst(\n node: SvelteAstNode,\n parent: SvelteAstNode | null = null\n): void {\n if (typeof node !== \"object\" || node === null) {\n return;\n }\n node.parent = parent;\n\n const childrenProps = [\n \"children\",\n \"consequent\",\n \"alternate\",\n \"blocks\",\n \"fragment\",\n ];\n const allElementChildren: SvelteAstNode[] = [];\n const allChildrenNodes: SvelteAstNode[] = [];\n\n for (const prop of childrenProps) {\n if (node[prop]) {\n const childrenArray = Array.isArray(node[prop])\n ? node[prop]\n : [node[prop]];\n for (const child of childrenArray) {\n if (child && typeof child === \"object\" && \"type\" in child) {\n allChildrenNodes.push(child);\n if (child.type === \"Element\") {\n allElementChildren.push(child);\n }\n }\n }\n }\n }\n\n const childElementsGroupedByTagName: { [tagName: string]: SvelteAstNode[] } =\n {};\n for (const child of allElementChildren) {\n if (!childElementsGroupedByTagName[child.name!]) {\n childElementsGroupedByTagName[child.name!] = [];\n }\n childElementsGroupedByTagName[child.name!].push(child);\n }\n\n for (const child of allChildrenNodes) {\n if (child.type === \"Element\") {\n const siblingsOfType = childElementsGroupedByTagName[child.name!];\n child.siblingIndex = siblingsOfType.indexOf(child);\n child.siblingCount = siblingsOfType.length;\n }\n enhanceAst(child, node);\n }\n}\n\n/**\n * Builds the path segments for a data-qa-id by traversing up the AST.\n */\nfunction buildPathSegments(\n node: SvelteAstNode,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): string[] {\n const pathSegments: string[] = [];\n let tempNode: SvelteAstNode | null = node;\n while (tempNode?.parent) {\n if (tempNode.type === \"Element\" && tempNode.siblingIndex !== undefined) {\n const tagName = getTagAbbreviation(tempNode.name!, abbreviations);\n let segment = tagName;\n if (tempNode.siblingCount! > 1) {\n segment += `-${tempNode.siblingIndex}`;\n }\n pathSegments.unshift(segment);\n }\n tempNode = tempNode.parent;\n }\n return pathSegments;\n}\n\n/**\n * Extracts names of components imported from 'lucide-svelte'.\n */\nfunction getLucideComponentNames(ast: unknown): Set<string> {\n const lucideComponents = new Set<string>();\n if (\n !(\n ast &&\n typeof ast === \"object\" &&\n \"instance\" in ast &&\n ast.instance &&\n typeof ast.instance === \"object\" &&\n \"content\" in ast.instance &&\n ast.instance.content &&\n typeof ast.instance.content === \"object\" &&\n \"body\" in ast.instance.content &&\n Array.isArray(ast.instance.content.body)\n )\n ) {\n return lucideComponents;\n }\n\n const instanceBody = (ast.instance as { content: { body: unknown[] } })\n .content.body;\n\n for (const node of instanceBody) {\n if (\n typeof node === \"object\" &&\n node !== null &&\n \"type\" in node &&\n node.type === \"ImportDeclaration\" &&\n \"source\" in node &&\n typeof node.source === \"object\" &&\n node.source !== null &&\n \"value\" in node.source &&\n node.source.value === \"lucide-svelte\" &&\n \"specifiers\" in node &&\n Array.isArray(node.specifiers)\n ) {\n for (const specifier of node.specifiers) {\n if (\n typeof specifier === \"object\" &&\n specifier !== null &&\n \"type\" in specifier &&\n specifier.type === \"ImportSpecifier\" &&\n \"imported\" in specifier &&\n specifier.imported &&\n typeof specifier.imported === \"object\" &&\n \"name\" in specifier.imported &&\n typeof specifier.imported.name === \"string\"\n ) {\n lucideComponents.add(specifier.imported.name);\n }\n }\n }\n }\n return lucideComponents;\n}\n\n/**\n * Collects modifications to be made to the Svelte file.\n */\nfunction collectModifications(\n node: SvelteAstNode,\n componentPrefix: string,\n content: string,\n lucideComponentNames: Set<string>,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): ElementToModify[] {\n const modifications: ElementToModify[] = [];\n const usedInsertionPoints = new Set<number>();\n\n function traverse(currentNode: SvelteAstNode): void {\n if (typeof currentNode !== \"object\" || currentNode === null) {\n return;\n }\n\n // Skip Lucide Svelte components (both Element and InlineComponent types)\n if (\n (currentNode.type === \"Element\" ||\n currentNode.type === \"InlineComponent\") &&\n lucideComponentNames.has(currentNode.name!)\n ) {\n return;\n }\n\n // Skip SVG and path elements (icon internals) - only for Element type\n if (\n currentNode.type === \"Element\" &&\n (currentNode.name === \"svg\" || currentNode.name === \"path\")\n ) {\n return;\n }\n\n if (currentNode.type === \"Element\") {\n const pathSegments = buildPathSegments(currentNode, abbreviations);\n const qaId = `${componentPrefix}${\n pathSegments.length > 0 ? \"-\" : \"\"\n }${pathSegments.join(\"-\")}`;\n\n // Determine insertion point for data-qa-id attribute\n // First, find the end of the opening tag (first unquoted '>')\n let pos = currentNode.start!;\n let inQuotes = false;\n let quoteChar = \"\";\n let inBraces = 0; // Track {} for event handlers like onclick={() =>}\n\n while (pos < currentNode.end!) {\n const char = content[pos];\n const prevChar = pos > 0 ? content[pos - 1] : \"\";\n\n if (!inQuotes && (char === '\"' || char === \"'\")) {\n if (prevChar !== \"\\\\\") {\n inQuotes = true;\n quoteChar = char;\n }\n } else if (inQuotes && char === quoteChar && prevChar !== \"\\\\\") {\n inQuotes = false;\n quoteChar = \"\";\n } else if (!inQuotes) {\n if (char === \"{\") {\n inBraces++;\n } else if (char === \"}\") {\n inBraces--;\n } else if (char === \">\" && inBraces === 0) {\n // Found the closing '>' of the opening tag\n break;\n }\n }\n pos++;\n }\n\n // Now check if this is a self-closing tag (looks for '/>' before the '>')\n let insertionPoint = pos; // Default: insert before the '>'\n if (pos > currentNode.start! + 1 && content[pos - 1] === \"/\") {\n // Self-closing tag: insert before the '/'\n insertionPoint = pos - 1;\n }\n\n if (insertionPoint !== -1 && !usedInsertionPoints.has(insertionPoint)) {\n usedInsertionPoints.add(insertionPoint);\n modifications.push({ qaId, insertionPoint });\n }\n }\n\n const childrenProps = [\n \"children\",\n \"consequent\",\n \"alternate\",\n \"blocks\",\n \"fragment\",\n ];\n for (const prop of childrenProps) {\n if (currentNode[prop]) {\n const childrenArray = Array.isArray(currentNode[prop])\n ? currentNode[prop]\n : [currentNode[prop]];\n for (const child of childrenArray) {\n traverse(child);\n }\n }\n }\n }\n\n traverse(node);\n return modifications;\n}\n\n// ============================================================================\n// Effect-based File Operations\n// ============================================================================\n\n/**\n * Reads a file's content as an Effect.\n */\nconst readFile = (filePath: string): Effect.Effect<string, FileReadError> =>\n Effect.try({\n try: () => readFileSync(filePath, \"utf-8\"),\n catch: (cause) => new FileReadError({ filePath, cause }),\n });\n\n/**\n * Writes content to a file as an Effect.\n */\nconst writeFile = (\n filePath: string,\n content: string\n): Effect.Effect<void, FileWriteError> =>\n Effect.try({\n try: () => writeFileSync(filePath, content, \"utf-8\"),\n catch: (cause) => new FileWriteError({ filePath, cause }),\n });\n\n/**\n * Gets file stats as an Effect.\n */\nconst getStats = (\n path: string\n): Effect.Effect<ReturnType<typeof statSync>, FileSystemError> =>\n Effect.try({\n try: () => statSync(path),\n catch: (cause) => new FileSystemError({ path, cause }),\n });\n\n/**\n * Reads directory contents as an Effect.\n */\nconst readDirectory = (\n path: string\n): Effect.Effect<string[], FileSystemError> =>\n Effect.try({\n try: () => readdirSync(path),\n catch: (cause) => new FileSystemError({ path, cause }),\n });\n\n// ============================================================================\n// Processing Functions\n// ============================================================================\n\n/**\n * Processes a single Svelte component file to inject `data-qa-id` attributes.\n */\nexport const processFile = (\n filePath: string,\n options: Options = {}\n): Effect.Effect<\n Result,\n FileReadError | FileWriteError | SvelteParseError | ValidationError\n> =>\n Effect.gen(function* () {\n const {\n abbreviations = DEFAULT_ABBREVIATIONS,\n prefixLength,\n prefixGenerator = defaultPrefixGenerator,\n skipComponents,\n preserveOnError = true,\n dryRun = false,\n verbose = false,\n } = options;\n\n // Validate prefixLength if provided\n yield* validatePrefixLength(prefixLength);\n\n if (verbose) {\n yield* Effect.log(`Processing file: ${filePath}`);\n }\n\n const originalContent = yield* readFile(filePath);\n\n // Use defaultPrefixGenerator with prefixLength if no custom generator provided\n const componentPrefix =\n prefixGenerator === defaultPrefixGenerator\n ? prefixGenerator(filePath, prefixLength)\n : prefixGenerator(filePath);\n\n const processed = yield* Effect.tryPromise({\n try: () =>\n preprocess(\n originalContent,\n {\n markup: ({ content, filename }) => {\n const originalContentForFallback = content;\n const cleanContent = content.replace(\n /\\s*data-qa-id=\"[^\"]*\"/g,\n \"\"\n );\n let modifiedContent = cleanContent;\n\n try {\n const ast = parse(cleanContent, { filename });\n const lucideComponentNames = getLucideComponentNames(ast);\n\n // Add custom skip components\n if (skipComponents) {\n const skipSet =\n skipComponents instanceof Set\n ? skipComponents\n : new Set(skipComponents);\n for (const comp of skipSet) {\n lucideComponentNames.add(comp);\n }\n }\n\n enhanceAst(ast.html);\n const modifications = collectModifications(\n ast.html,\n componentPrefix,\n cleanContent,\n lucideComponentNames,\n abbreviations\n );\n\n modifications.sort(\n (a, b) => b.insertionPoint - a.insertionPoint\n );\n\n modifiedContent = cleanContent;\n for (const mod of modifications) {\n modifiedContent =\n modifiedContent.substring(0, mod.insertionPoint) +\n ` data-qa-id=\"${mod.qaId}\"` +\n modifiedContent.substring(mod.insertionPoint);\n }\n\n // Note: Verbose logging handled after processing completes\n } catch (parseError: unknown) {\n const isLetBlockError =\n (parseError as { code?: string }).code ===\n \"expected_block_type\" ||\n (parseError as { message?: string }).message?.includes(\n \"{#let\"\n ) ||\n (parseError as { message?: string }).message?.includes(\n \"Expected 'if', 'each', 'await', 'key' or 'snippet'\"\n );\n\n if (isLetBlockError) {\n // Note: Verbose logging handled after processing completes\n return {\n code: preserveOnError\n ? originalContentForFallback\n : cleanContent,\n };\n }\n throw parseError;\n }\n return { code: modifiedContent };\n },\n },\n { filename: filePath }\n ),\n catch: (cause) => new SvelteParseError({ filePath, cause }),\n });\n\n if (!dryRun) {\n yield* writeFile(filePath, processed.code);\n }\n\n const injectedCount = (processed.code.match(/data-qa-id=\"[^\"]*\"/g) || [])\n .length;\n\n if (verbose && injectedCount > 0) {\n yield* Effect.log(` Injected ${injectedCount} data-qa-id attributes`);\n }\n\n yield* Effect.log(\n `Successfully updated data-qa-id attributes in ${filePath}.`\n );\n\n return {\n file: filePath,\n success: true,\n injectedCount,\n };\n }).pipe(\n Effect.catchTag(\"FileReadError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Error reading file: ${error.filePath}`,\n })\n ),\n Effect.catchTag(\"FileWriteError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Error writing file: ${error.filePath}`,\n })\n ),\n Effect.catchTag(\"SvelteParseError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Parse error in ${error.filePath}: ${\n error.cause instanceof Error\n ? error.cause.message\n : String(error.cause)\n }`,\n })\n ),\n Effect.catchTag(\"ValidationError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: error.message,\n })\n )\n );\n\n/**\n * Recursively finds and processes all Svelte files in a given path.\n */\nexport const processPath = (\n path: string,\n options: Options = {}\n): Effect.Effect<\n Result[],\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n> =>\n Effect.gen(function* () {\n const results: Result[] = [];\n\n const traverse = (\n currentPath: string\n ): Effect.Effect<\n void,\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n > =>\n Effect.gen(function* () {\n const stats = yield* getStats(currentPath);\n\n if (stats.isFile()) {\n if (currentPath.endsWith(\".svelte\")) {\n const result = yield* processFile(currentPath, options);\n results.push(result);\n }\n } else if (stats.isDirectory()) {\n const files = yield* readDirectory(currentPath);\n for (const file of files) {\n yield* traverse(join(currentPath, file));\n }\n }\n });\n\n yield* traverse(path);\n return results;\n });\n\n/**\n * Main API - inject data-qa-id attributes into Svelte files\n */\nexport const inject = (\n path: string,\n options: Options = {}\n): Effect.Effect<\n Result[],\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n> =>\n Effect.gen(function* () {\n const stats = yield* getStats(path);\n\n if (stats.isFile()) {\n const result = yield* processFile(path, options);\n return [result];\n }\n if (stats.isDirectory()) {\n return yield* processPath(path, options);\n }\n\n throw new FileSystemError({\n path,\n cause: \"Path does not exist\",\n });\n }).pipe(\n Effect.catchTag(\"FileSystemError\", (error) => Effect.die(error.cause))\n );\n\n/**\n * Promise-based API for compatibility\n */\nexport async function injectPromise(\n path: string,\n options: Options = {}\n): Promise<Result[]> {\n return Effect.runPromise(inject(path, options));\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
  import {
4
3
  injectPromise
5
- } from "./chunk-7MRS72CP.js";
4
+ } from "./chunk-XHMXW33M.js";
6
5
 
7
6
  // src/cli.ts
8
7
  import { resolve } from "path";
@@ -90,7 +89,7 @@ For more information, visit: https://github.com/your-org/svelte-qa-ids
90
89
  `);
91
90
  }
92
91
  async function showVersion() {
93
- const pkg = await import("./package-QZOBPTUC.js");
92
+ const pkg = await import("./package-RVLMZF3O.js");
94
93
  console.log(`svelte-qa-ids v${pkg.default.version}`);
95
94
  }
96
95
  async function main() {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI for svelte-qa-ids\n */\n\nimport { resolve } from \"node:path\";\nimport { injectPromise, type Options } from \"./index.js\";\n\ninterface CliOptions {\n dryRun: boolean;\n verbose: boolean;\n help: boolean;\n version: boolean;\n componentLength?: number;\n}\n\nfunction parseArgs(args: string[]): { path: string; options: CliOptions } {\n const options: CliOptions = {\n dryRun: false,\n verbose: false,\n help: false,\n version: false,\n };\n\n let path = \"\";\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n switch (arg) {\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n case \"-v\":\n case \"--version\":\n options.version = true;\n break;\n case \"-n\":\n case \"--dry-run\":\n options.dryRun = true;\n break;\n case \"--verbose\":\n options.verbose = true;\n break;\n case \"-c\":\n case \"--component\": {\n const nextArg = args[i + 1];\n if (nextArg && !nextArg.startsWith(\"-\")) {\n options.componentLength = Number.parseInt(nextArg, 10);\n i++; // Skip next arg\n }\n break;\n }\n default:\n if (!arg.startsWith(\"-\")) {\n path = arg;\n }\n break;\n }\n }\n\n return { path, options };\n}\n\nfunction showHelp(): void {\n console.log(`\nsvelte-qa-ids - Automatically inject data-qa-id attributes into Svelte components\n\nUSAGE:\n svelte-qa-ids <path> [options]\n\nARGUMENTS:\n <path> Path to a Svelte file or directory to process\n\nOPTIONS:\n -h, --help Show this help message\n -v, --version Show version number\n -n, --dry-run Process files without modifying them\n --verbose Show detailed logging\n -c, --component <N> Number of characters for component prefix (2-10, default: 3)\n\nEXAMPLES:\n # Process all Svelte files in src/\n svelte-qa-ids src/\n\n # Dry run to see what would be changed\n svelte-qa-ids src/ --dry-run\n\n # Process a single file\n svelte-qa-ids src/routes/+page.svelte\n\n # Verbose output\n svelte-qa-ids src/ --verbose\n\n # Use 4-character component prefixes\n svelte-qa-ids src/ --component 4\n\n # Use 2-character component prefixes\n svelte-qa-ids src/ -c 2\n\nFor more information, visit: https://github.com/your-org/svelte-qa-ids\n`);\n}\n\nasync function showVersion(): Promise<void> {\n const pkg = await import(\"../package.json\", {\n assert: { type: \"json\" },\n });\n console.log(`svelte-qa-ids v${pkg.default.version}`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const { path, options } = parseArgs(args);\n\n if (options.help) {\n showHelp();\n process.exit(0);\n }\n\n if (options.version) {\n await showVersion();\n process.exit(0);\n }\n\n if (!path) {\n console.error(\"Error: Please provide a path to process\");\n console.error(\"Run 'svelte-qa-ids --help' for usage information\");\n process.exit(1);\n }\n\n const resolvedPath = resolve(path);\n const injectOptions: Options = {\n dryRun: options.dryRun,\n verbose: options.verbose,\n prefixLength: options.componentLength,\n };\n\n if (options.dryRun) {\n console.log(\"DRY RUN MODE - No files will be modified\\n\");\n }\n\n try {\n const results = await injectPromise(resolvedPath, injectOptions);\n\n const successCount = results.filter((r) => r.success).length;\n const failCount = results.filter((r) => !r.success).length;\n\n console.log(`\\nProcessed ${results.length} file(s)`);\n console.log(` Success: ${successCount}`);\n console.log(` Failed: ${failCount}`);\n\n if (failCount > 0) {\n console.log(\"\\nErrors:\");\n for (const result of results) {\n if (!result.success) {\n console.error(` ${result.file}: ${result.error}`);\n }\n }\n process.exit(1);\n }\n } catch (error) {\n console.error(\"Error:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/**\n * CLI for svelte-qa-ids\n */\n\nimport { resolve } from \"node:path\";\nimport { injectPromise, type Options } from \"./index.js\";\n\ninterface CliOptions {\n dryRun: boolean;\n verbose: boolean;\n help: boolean;\n version: boolean;\n componentLength?: number;\n}\n\nfunction parseArgs(args: string[]): { path: string; options: CliOptions } {\n const options: CliOptions = {\n dryRun: false,\n verbose: false,\n help: false,\n version: false,\n };\n\n let path = \"\";\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n switch (arg) {\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n case \"-v\":\n case \"--version\":\n options.version = true;\n break;\n case \"-n\":\n case \"--dry-run\":\n options.dryRun = true;\n break;\n case \"--verbose\":\n options.verbose = true;\n break;\n case \"-c\":\n case \"--component\": {\n const nextArg = args[i + 1];\n if (nextArg && !nextArg.startsWith(\"-\")) {\n options.componentLength = Number.parseInt(nextArg, 10);\n i++; // Skip next arg\n }\n break;\n }\n default:\n if (!arg.startsWith(\"-\")) {\n path = arg;\n }\n break;\n }\n }\n\n return { path, options };\n}\n\nfunction showHelp(): void {\n console.log(`\nsvelte-qa-ids - Automatically inject data-qa-id attributes into Svelte components\n\nUSAGE:\n svelte-qa-ids <path> [options]\n\nARGUMENTS:\n <path> Path to a Svelte file or directory to process\n\nOPTIONS:\n -h, --help Show this help message\n -v, --version Show version number\n -n, --dry-run Process files without modifying them\n --verbose Show detailed logging\n -c, --component <N> Number of characters for component prefix (2-10, default: 3)\n\nEXAMPLES:\n # Process all Svelte files in src/\n svelte-qa-ids src/\n\n # Dry run to see what would be changed\n svelte-qa-ids src/ --dry-run\n\n # Process a single file\n svelte-qa-ids src/routes/+page.svelte\n\n # Verbose output\n svelte-qa-ids src/ --verbose\n\n # Use 4-character component prefixes\n svelte-qa-ids src/ --component 4\n\n # Use 2-character component prefixes\n svelte-qa-ids src/ -c 2\n\nFor more information, visit: https://github.com/your-org/svelte-qa-ids\n`);\n}\n\nasync function showVersion(): Promise<void> {\n const pkg = await import(\"../package.json\", {\n assert: { type: \"json\" },\n });\n console.log(`svelte-qa-ids v${pkg.default.version}`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const { path, options } = parseArgs(args);\n\n if (options.help) {\n showHelp();\n process.exit(0);\n }\n\n if (options.version) {\n await showVersion();\n process.exit(0);\n }\n\n if (!path) {\n console.error(\"Error: Please provide a path to process\");\n console.error(\"Run 'svelte-qa-ids --help' for usage information\");\n process.exit(1);\n }\n\n const resolvedPath = resolve(path);\n const injectOptions: Options = {\n dryRun: options.dryRun,\n verbose: options.verbose,\n prefixLength: options.componentLength,\n };\n\n if (options.dryRun) {\n console.log(\"DRY RUN MODE - No files will be modified\\n\");\n }\n\n try {\n const results = await injectPromise(resolvedPath, injectOptions);\n\n const successCount = results.filter((r) => r.success).length;\n const failCount = results.filter((r) => !r.success).length;\n\n console.log(`\\nProcessed ${results.length} file(s)`);\n console.log(` Success: ${successCount}`);\n console.log(` Failed: ${failCount}`);\n\n if (failCount > 0) {\n console.log(\"\\nErrors:\");\n for (const result of results) {\n if (!result.success) {\n console.error(` ${result.file}: ${result.error}`);\n }\n }\n process.exit(1);\n }\n } catch (error) {\n console.error(\"Error:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  injectPromise,
12
12
  processFile,
13
13
  processPath
14
- } from "./chunk-7MRS72CP.js";
14
+ } from "./chunk-XHMXW33M.js";
15
15
  export {
16
16
  FileReadError,
17
17
  FileSystemError,
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var name = "svelte-qa-ids";
5
- var version = "1.0.0";
5
+ var version = "1.0.2";
6
6
  var description = "Automatically inject stable data-qa-id attributes into Svelte components for testing and automation";
7
7
  var type = "module";
8
8
  var main = "./dist/index.js";
@@ -104,4 +104,4 @@ export {
104
104
  type,
105
105
  version
106
106
  };
107
- //# sourceMappingURL=package-QZOBPTUC.js.map
107
+ //# sourceMappingURL=package-RVLMZF3O.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"svelte-qa-ids\",\n \"version\": \"1.0.0\",\n \"description\": \"Automatically inject stable data-qa-id attributes into Svelte components for testing and automation\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"bin\": {\n \"svelte-qa-ids\": \"dist/cli.js\"\n },\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"bun test\",\n \"lint\": \"bun x ultracite check src\",\n \"format\": \"bun x ultracite fix src\",\n \"prepublishOnly\": \"bun run build\",\n \"check\": \"ultracite check\",\n \"fix\": \"ultracite fix\",\n \"prepare\": \"lefthook install\"\n },\n \"keywords\": [\n \"svelte\",\n \"testing\",\n \"automation\",\n \"qa\",\n \"data-qa-id\",\n \"e2e\",\n \"playwright\",\n \"selectors\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/edut/svelte-qa-ids.git\"\n },\n \"peerDependencies\": {\n \"svelte\": \"^3.0.0 || ^4.0.0 || ^5.0.0\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.3.13\",\n \"@types/node\": \"^20.17.6\",\n \"lefthook\": \"^2.0.16\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"ultracite\": \"7.1.3\"\n },\n \"dependencies\": {\n \"effect\": \"^3.19.15\",\n \"svelte\": \"^5.3.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n"],"mappings":";;;AACE,WAAQ;AACR,cAAW;AACX,kBAAe;AACf,WAAQ;AACR,WAAQ;AACR,UAAO;AAAA,EACL,iBAAiB;AACnB;AACA,cAAW;AAAA,EACT,KAAK;AAAA,IACH,QAAU;AAAA,IACV,OAAS;AAAA,EACX;AACF;AACA,YAAS;AAAA,EACP;AAAA,EACA;AAAA,EACA;AACF;AACA,cAAW;AAAA,EACT,OAAS;AAAA,EACT,KAAO;AAAA,EACP,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,gBAAkB;AAAA,EAClB,OAAS;AAAA,EACT,KAAO;AAAA,EACP,SAAW;AACb;AACA,eAAY;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,aAAU;AACV,cAAW;AACX,iBAAc;AAAA,EACZ,MAAQ;AAAA,EACR,KAAO;AACT;AACA,uBAAoB;AAAA,EAClB,QAAU;AACZ;AACA,sBAAmB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,UAAY;AAAA,EACZ,MAAQ;AAAA,EACR,YAAc;AAAA,EACd,WAAa;AACf;AACA,mBAAgB;AAAA,EACd,QAAU;AAAA,EACV,QAAU;AACZ;AACA,cAAW;AAAA,EACT,MAAQ;AACV;AAhEF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAMA;AAAA,EAKA;AAAA,EAWA;AAAA,EAUA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EAGA;AAAA,EAQA;AAAA,EAIA;AAGF;","names":[]}
1
+ {"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"svelte-qa-ids\",\n \"version\": \"1.0.2\",\n \"description\": \"Automatically inject stable data-qa-id attributes into Svelte components for testing and automation\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"bin\": {\n \"svelte-qa-ids\": \"dist/cli.js\"\n },\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"bun test\",\n \"lint\": \"bun x ultracite check src\",\n \"format\": \"bun x ultracite fix src\",\n \"prepublishOnly\": \"bun run build\",\n \"check\": \"ultracite check\",\n \"fix\": \"ultracite fix\",\n \"prepare\": \"lefthook install\"\n },\n \"keywords\": [\n \"svelte\",\n \"testing\",\n \"automation\",\n \"qa\",\n \"data-qa-id\",\n \"e2e\",\n \"playwright\",\n \"selectors\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/edut/svelte-qa-ids.git\"\n },\n \"peerDependencies\": {\n \"svelte\": \"^3.0.0 || ^4.0.0 || ^5.0.0\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.3.13\",\n \"@types/node\": \"^20.17.6\",\n \"lefthook\": \"^2.0.16\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"ultracite\": \"7.1.3\"\n },\n \"dependencies\": {\n \"effect\": \"^3.19.15\",\n \"svelte\": \"^5.3.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n"],"mappings":";;;AACE,WAAQ;AACR,cAAW;AACX,kBAAe;AACf,WAAQ;AACR,WAAQ;AACR,UAAO;AAAA,EACL,iBAAiB;AACnB;AACA,cAAW;AAAA,EACT,KAAK;AAAA,IACH,QAAU;AAAA,IACV,OAAS;AAAA,EACX;AACF;AACA,YAAS;AAAA,EACP;AAAA,EACA;AAAA,EACA;AACF;AACA,cAAW;AAAA,EACT,OAAS;AAAA,EACT,KAAO;AAAA,EACP,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,gBAAkB;AAAA,EAClB,OAAS;AAAA,EACT,KAAO;AAAA,EACP,SAAW;AACb;AACA,eAAY;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,aAAU;AACV,cAAW;AACX,iBAAc;AAAA,EACZ,MAAQ;AAAA,EACR,KAAO;AACT;AACA,uBAAoB;AAAA,EAClB,QAAU;AACZ;AACA,sBAAmB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,UAAY;AAAA,EACZ,MAAQ;AAAA,EACR,YAAc;AAAA,EACd,WAAa;AACf;AACA,mBAAgB;AAAA,EACd,QAAU;AAAA,EACV,QAAU;AACZ;AACA,cAAW;AAAA,EACT,MAAQ;AACV;AAhEF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAMA;AAAA,EAKA;AAAA,EAWA;AAAA,EAUA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EAGA;AAAA,EAQA;AAAA,EAIA;AAGF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-qa-ids",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Automatically inject stable data-qa-id attributes into Svelte components for testing and automation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * svelte-qa-ids\n * Automatically inject stable data-qa-id attributes into Svelte components\n */\n\nimport { readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join, relative } from \"node:path\";\nimport { Data, Effect } from \"effect\";\nimport { parse, preprocess } from \"svelte/compiler\";\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\nexport class FileReadError extends Data.TaggedError(\"FileReadError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class FileWriteError extends Data.TaggedError(\"FileWriteError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class SvelteParseError extends Data.TaggedError(\"SvelteParseError\")<{\n readonly filePath: string;\n readonly cause: unknown;\n}> {}\n\nexport class FileSystemError extends Data.TaggedError(\"FileSystemError\")<{\n readonly path: string;\n readonly cause: unknown;\n}> {}\n\nexport class ValidationError extends Data.TaggedError(\"ValidationError\")<{\n readonly field: string;\n readonly value: unknown;\n readonly message: string;\n}> {}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Options {\n /**\n * Custom abbreviations for HTML tags\n * @default { common abbreviations }\n */\n abbreviations?: Record<string, string>;\n\n /**\n * Number of characters from component name to use for ID prefix\n * @default 3\n * @throws {ValidationError} When value is outside 2-10 range\n * @validation Must be between 2 and 10 characters\n */\n prefixLength?: number;\n\n /**\n * Custom prefix generator function\n * @default built-in prefix generator\n */\n prefixGenerator?: (filePath: string) => string;\n\n /**\n * Component names to skip (e.g., icon libraries)\n * @default lucide-svelte components\n */\n skipComponents?: Set<string> | string[];\n\n /**\n * Include files matching these patterns\n */\n include?: string[];\n\n /**\n * Exclude files matching these patterns\n * @default {string[]} []\n */\n exclude?: string[];\n\n /**\n * Whether to preserve original content for files with parsing errors\n * @default true\n */\n preserveOnError?: boolean;\n\n /**\n * Dry run - don't modify files\n * @default false\n */\n dryRun?: boolean;\n\n /**\n * Verbose logging\n * @default false\n */\n verbose?: boolean;\n}\n\nexport interface Result {\n file: string;\n success: boolean;\n error?: string;\n injectedCount?: number;\n skipped?: boolean;\n}\n\n// ============================================================================\n// AST Types\n// ============================================================================\n\ninterface SvelteAstNode {\n type: string;\n name?: string;\n start?: number;\n end?: number;\n parent?: SvelteAstNode | null;\n siblingIndex?: number;\n siblingCount?: number;\n children?: SvelteAstNode[];\n consequent?: SvelteAstNode | SvelteAstNode[];\n alternate?: SvelteAstNode | SvelteAstNode[];\n blocks?: SvelteAstNode[];\n fragment?: SvelteAstNode[];\n [key: string]: unknown;\n}\n\ninterface ElementToModify {\n qaId: string;\n insertionPoint: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_ABBREVIATIONS: Record<string, string> = {\n div: \"d\",\n span: \"sp\",\n section: \"sec\",\n button: \"btn\",\n a: \"a\",\n p: \"p\",\n img: \"img\",\n ul: \"ul\",\n li: \"li\",\n form: \"f\",\n input: \"in\",\n label: \"lbl\",\n h1: \"h1\",\n h2: \"h2\",\n h3: \"h3\",\n h4: \"h4\",\n h5: \"h5\",\n h6: \"h6\",\n};\n\nconst ROUTE_PREFIX_REGEX = /^src\\/routes\\/?/;\n\n// ============================================================================\n// Core Functions\n// ============================================================================\n\n/**\n * Validates prefixLength is within acceptable range (2-10).\n */\nconst validatePrefixLength = (\n prefixLength?: number\n): Effect.Effect<void, ValidationError> =>\n prefixLength !== undefined && (prefixLength < 2 || prefixLength > 10)\n ? Effect.fail(\n new ValidationError({\n field: \"prefixLength\",\n value: prefixLength,\n message: \"prefixLength must be between 2 and 10 characters\",\n })\n )\n : Effect.void;\n\n/**\n * Returns the abbreviation for a given HTML tag.\n */\nexport { getTagAbbreviation };\n\nfunction getTagAbbreviation(\n tagName: string,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): string {\n return abbreviations[tagName] || tagName;\n}\n\n/**\n * Default component prefix generator based on file path.\n */\nconst ROOT_ROUTE_PREFIX = \"rt\" as const;\n\nexport { defaultPrefixGenerator };\n\nfunction defaultPrefixGenerator(filePath: string, prefixLength = 3): string {\n const projectRoot = process.cwd();\n const relativePath = relative(projectRoot, filePath);\n\n if (relativePath.startsWith(\"src/routes\")) {\n const routeDir = dirname(relativePath).replace(ROUTE_PREFIX_REGEX, \"\");\n if (routeDir === \"\") {\n return ROOT_ROUTE_PREFIX;\n }\n const lastPart = routeDir.split(\"/\").pop() || \"\";\n return lastPart.substring(0, Math.min(prefixLength, lastPart.length));\n }\n if (relativePath.startsWith(\"src/lib/\")) {\n const fileName = basename(filePath, \".svelte\");\n return fileName\n .split(\"-\")\n .map((part: string) =>\n part.substring(0, Math.min(prefixLength, part.length))\n )\n .join(\"-\");\n }\n\n const baseName = basename(filePath, \".svelte\");\n return baseName.substring(0, Math.min(prefixLength, baseName.length));\n}\n\n/**\n * Walks the Svelte AST and enhances nodes with parent pointers and sibling info.\n */\nfunction enhanceAst(\n node: SvelteAstNode,\n parent: SvelteAstNode | null = null\n): void {\n if (typeof node !== \"object\" || node === null) {\n return;\n }\n node.parent = parent;\n\n const childrenProps = [\n \"children\",\n \"consequent\",\n \"alternate\",\n \"blocks\",\n \"fragment\",\n ];\n const allElementChildren: SvelteAstNode[] = [];\n const allChildrenNodes: SvelteAstNode[] = [];\n\n for (const prop of childrenProps) {\n if (node[prop]) {\n const childrenArray = Array.isArray(node[prop])\n ? node[prop]\n : [node[prop]];\n for (const child of childrenArray) {\n if (child && typeof child === \"object\" && \"type\" in child) {\n allChildrenNodes.push(child);\n if (child.type === \"Element\") {\n allElementChildren.push(child);\n }\n }\n }\n }\n }\n\n const childElementsGroupedByTagName: { [tagName: string]: SvelteAstNode[] } =\n {};\n for (const child of allElementChildren) {\n if (!childElementsGroupedByTagName[child.name!]) {\n childElementsGroupedByTagName[child.name!] = [];\n }\n childElementsGroupedByTagName[child.name!].push(child);\n }\n\n for (const child of allChildrenNodes) {\n if (child.type === \"Element\") {\n const siblingsOfType = childElementsGroupedByTagName[child.name!];\n child.siblingIndex = siblingsOfType.indexOf(child);\n child.siblingCount = siblingsOfType.length;\n }\n enhanceAst(child, node);\n }\n}\n\n/**\n * Builds the path segments for a data-qa-id by traversing up the AST.\n */\nfunction buildPathSegments(\n node: SvelteAstNode,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): string[] {\n const pathSegments: string[] = [];\n let tempNode: SvelteAstNode | null = node;\n while (tempNode && tempNode.parent) {\n if (tempNode.type === \"Element\" && tempNode.siblingIndex !== undefined) {\n const tagName = getTagAbbreviation(tempNode.name!, abbreviations);\n let segment = tagName;\n if (tempNode.siblingCount! > 1) {\n segment += `-${tempNode.siblingIndex}`;\n }\n pathSegments.unshift(segment);\n }\n tempNode = tempNode.parent;\n }\n return pathSegments;\n}\n\n/**\n * Extracts names of components imported from 'lucide-svelte'.\n */\nfunction getLucideComponentNames(ast: unknown): Set<string> {\n const lucideComponents = new Set<string>();\n if (\n !(\n ast &&\n typeof ast === \"object\" &&\n \"instance\" in ast &&\n ast.instance &&\n typeof ast.instance === \"object\" &&\n \"content\" in ast.instance &&\n ast.instance.content &&\n typeof ast.instance.content === \"object\" &&\n \"body\" in ast.instance.content &&\n Array.isArray(ast.instance.content.body)\n )\n ) {\n return lucideComponents;\n }\n\n const instanceBody = (ast.instance as { content: { body: unknown[] } })\n .content.body;\n\n for (const node of instanceBody) {\n if (\n typeof node === \"object\" &&\n node !== null &&\n \"type\" in node &&\n node.type === \"ImportDeclaration\" &&\n \"source\" in node &&\n typeof node.source === \"object\" &&\n node.source !== null &&\n \"value\" in node.source &&\n node.source.value === \"lucide-svelte\" &&\n \"specifiers\" in node &&\n Array.isArray(node.specifiers)\n ) {\n for (const specifier of node.specifiers) {\n if (\n typeof specifier === \"object\" &&\n specifier !== null &&\n \"type\" in specifier &&\n specifier.type === \"ImportSpecifier\" &&\n \"imported\" in specifier &&\n specifier.imported &&\n typeof specifier.imported === \"object\" &&\n \"name\" in specifier.imported &&\n typeof specifier.imported.name === \"string\"\n ) {\n lucideComponents.add(specifier.imported.name);\n }\n }\n }\n }\n return lucideComponents;\n}\n\n/**\n * Collects modifications to be made to the Svelte file.\n */\nfunction collectModifications(\n node: SvelteAstNode,\n componentPrefix: string,\n content: string,\n lucideComponentNames: Set<string>,\n abbreviations: Record<string, string> = DEFAULT_ABBREVIATIONS\n): ElementToModify[] {\n const modifications: ElementToModify[] = [];\n const usedInsertionPoints = new Set<number>();\n\n function traverse(currentNode: SvelteAstNode): void {\n if (typeof currentNode !== \"object\" || currentNode === null) {\n return;\n }\n\n // Skip Lucide Svelte components (both Element and InlineComponent types)\n if (\n (currentNode.type === \"Element\" ||\n currentNode.type === \"InlineComponent\") &&\n lucideComponentNames.has(currentNode.name!)\n ) {\n return;\n }\n\n // Skip SVG and path elements (icon internals) - only for Element type\n if (\n currentNode.type === \"Element\" &&\n (currentNode.name === \"svg\" || currentNode.name === \"path\")\n ) {\n return;\n }\n\n if (currentNode.type === \"Element\") {\n const pathSegments = buildPathSegments(currentNode, abbreviations);\n const qaId = `${componentPrefix}${\n pathSegments.length > 0 ? \"-\" : \"\"\n }${pathSegments.join(\"-\")}`;\n\n // Determine insertion point for data-qa-id attribute\n // First, find the end of the opening tag (first unquoted '>')\n let pos = currentNode.start!;\n let inQuotes = false;\n let quoteChar = \"\";\n let inBraces = 0; // Track {} for event handlers like onclick={() =>}\n\n while (pos < currentNode.end!) {\n const char = content[pos];\n const prevChar = pos > 0 ? content[pos - 1] : \"\";\n\n if (!inQuotes && (char === '\"' || char === \"'\")) {\n if (prevChar !== \"\\\\\") {\n inQuotes = true;\n quoteChar = char;\n }\n } else if (inQuotes && char === quoteChar && prevChar !== \"\\\\\") {\n inQuotes = false;\n quoteChar = \"\";\n } else if (!inQuotes) {\n if (char === \"{\") {\n inBraces++;\n } else if (char === \"}\") {\n inBraces--;\n } else if (char === \">\" && inBraces === 0) {\n // Found the closing '>' of the opening tag\n break;\n }\n }\n pos++;\n }\n\n // Now check if this is a self-closing tag (looks for '/>' before the '>')\n let insertionPoint = pos; // Default: insert before the '>'\n if (pos > currentNode.start! + 1 && content[pos - 1] === \"/\") {\n // Self-closing tag: insert before the '/'\n insertionPoint = pos - 1;\n }\n\n if (insertionPoint !== -1 && !usedInsertionPoints.has(insertionPoint)) {\n usedInsertionPoints.add(insertionPoint);\n modifications.push({ qaId, insertionPoint });\n }\n }\n\n const childrenProps = [\n \"children\",\n \"consequent\",\n \"alternate\",\n \"blocks\",\n \"fragment\",\n ];\n for (const prop of childrenProps) {\n if (currentNode[prop]) {\n const childrenArray = Array.isArray(currentNode[prop])\n ? currentNode[prop]\n : [currentNode[prop]];\n for (const child of childrenArray) {\n traverse(child);\n }\n }\n }\n }\n\n traverse(node);\n return modifications;\n}\n\n// ============================================================================\n// Effect-based File Operations\n// ============================================================================\n\n/**\n * Reads a file's content as an Effect.\n */\nconst readFile = (filePath: string): Effect.Effect<string, FileReadError> =>\n Effect.try({\n try: () => readFileSync(filePath, \"utf-8\"),\n catch: (cause) => new FileReadError({ filePath, cause }),\n });\n\n/**\n * Writes content to a file as an Effect.\n */\nconst writeFile = (\n filePath: string,\n content: string\n): Effect.Effect<void, FileWriteError> =>\n Effect.try({\n try: () => writeFileSync(filePath, content, \"utf-8\"),\n catch: (cause) => new FileWriteError({ filePath, cause }),\n });\n\n/**\n * Gets file stats as an Effect.\n */\nconst getStats = (\n path: string\n): Effect.Effect<ReturnType<typeof statSync>, FileSystemError> =>\n Effect.try({\n try: () => statSync(path),\n catch: (cause) => new FileSystemError({ path, cause }),\n });\n\n/**\n * Reads directory contents as an Effect.\n */\nconst readDirectory = (\n path: string\n): Effect.Effect<string[], FileSystemError> =>\n Effect.try({\n try: () => readdirSync(path),\n catch: (cause) => new FileSystemError({ path, cause }),\n });\n\n// ============================================================================\n// Processing Functions\n// ============================================================================\n\n/**\n * Processes a single Svelte component file to inject `data-qa-id` attributes.\n */\nexport const processFile = (\n filePath: string,\n options: Options = {}\n): Effect.Effect<\n Result,\n FileReadError | FileWriteError | SvelteParseError | ValidationError\n> =>\n Effect.gen(function* () {\n const {\n abbreviations = DEFAULT_ABBREVIATIONS,\n prefixLength,\n prefixGenerator = defaultPrefixGenerator,\n skipComponents,\n preserveOnError = true,\n dryRun = false,\n verbose = false,\n } = options;\n\n // Validate prefixLength if provided\n yield* validatePrefixLength(prefixLength);\n\n if (verbose) {\n yield* Effect.log(`Processing file: ${filePath}`);\n }\n\n const originalContent = yield* readFile(filePath);\n\n // Use defaultPrefixGenerator with prefixLength if no custom generator provided\n const componentPrefix =\n prefixGenerator === defaultPrefixGenerator\n ? prefixGenerator(filePath, prefixLength)\n : prefixGenerator(filePath);\n\n const processed = yield* Effect.tryPromise({\n try: () =>\n preprocess(\n originalContent,\n {\n markup: ({ content, filename }) => {\n const originalContentForFallback = content;\n const cleanContent = content.replace(\n /\\s*data-qa-id=\"[^\"]*\"/g,\n \"\"\n );\n let modifiedContent = cleanContent;\n\n try {\n const ast = parse(cleanContent, { filename });\n const lucideComponentNames = getLucideComponentNames(ast);\n\n // Add custom skip components\n if (skipComponents) {\n const skipSet =\n skipComponents instanceof Set\n ? skipComponents\n : new Set(skipComponents);\n for (const comp of skipSet) {\n lucideComponentNames.add(comp);\n }\n }\n\n enhanceAst(ast.html);\n const modifications = collectModifications(\n ast.html,\n componentPrefix,\n cleanContent,\n lucideComponentNames,\n abbreviations\n );\n\n modifications.sort(\n (a, b) => b.insertionPoint - a.insertionPoint\n );\n\n modifiedContent = cleanContent;\n for (const mod of modifications) {\n modifiedContent =\n modifiedContent.substring(0, mod.insertionPoint) +\n ` data-qa-id=\"${mod.qaId}\"` +\n modifiedContent.substring(mod.insertionPoint);\n }\n\n // Note: Verbose logging handled after processing completes\n } catch (parseError: unknown) {\n const isLetBlockError =\n (parseError as { code?: string }).code ===\n \"expected_block_type\" ||\n (parseError as { message?: string }).message?.includes(\n \"{#let\"\n ) ||\n (parseError as { message?: string }).message?.includes(\n \"Expected 'if', 'each', 'await', 'key' or 'snippet'\"\n );\n\n if (isLetBlockError) {\n // Note: Verbose logging handled after processing completes\n return {\n code: preserveOnError\n ? originalContentForFallback\n : cleanContent,\n };\n }\n throw parseError;\n }\n return { code: modifiedContent };\n },\n },\n { filename: filePath }\n ),\n catch: (cause) => new SvelteParseError({ filePath, cause }),\n });\n\n if (!dryRun) {\n yield* writeFile(filePath, processed.code);\n }\n\n const injectedCount = (processed.code.match(/data-qa-id=\"[^\"]*\"/g) || [])\n .length;\n\n if (verbose && injectedCount > 0) {\n yield* Effect.log(` Injected ${injectedCount} data-qa-id attributes`);\n }\n\n yield* Effect.log(\n `Successfully updated data-qa-id attributes in ${filePath}.`\n );\n\n return {\n file: filePath,\n success: true,\n injectedCount,\n };\n }).pipe(\n Effect.catchTag(\"FileReadError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Error reading file: ${error.filePath}`,\n })\n ),\n Effect.catchTag(\"FileWriteError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Error writing file: ${error.filePath}`,\n })\n ),\n Effect.catchTag(\"SvelteParseError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: `Parse error in ${error.filePath}: ${\n error.cause instanceof Error\n ? error.cause.message\n : String(error.cause)\n }`,\n })\n ),\n Effect.catchTag(\"ValidationError\", (error) =>\n Effect.succeed({\n file: filePath,\n success: false,\n error: error.message,\n })\n )\n );\n\n/**\n * Recursively finds and processes all Svelte files in a given path.\n */\nexport const processPath = (\n path: string,\n options: Options = {}\n): Effect.Effect<\n Result[],\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n> =>\n Effect.gen(function* () {\n const results: Result[] = [];\n\n const traverse = (\n currentPath: string\n ): Effect.Effect<\n void,\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n > =>\n Effect.gen(function* () {\n const stats = yield* getStats(currentPath);\n\n if (stats.isFile()) {\n if (currentPath.endsWith(\".svelte\")) {\n const result = yield* processFile(currentPath, options);\n results.push(result);\n }\n } else if (stats.isDirectory()) {\n const files = yield* readDirectory(currentPath);\n for (const file of files) {\n yield* traverse(join(currentPath, file));\n }\n }\n });\n\n yield* traverse(path);\n return results;\n });\n\n/**\n * Main API - inject data-qa-id attributes into Svelte files\n */\nexport const inject = (\n path: string,\n options: Options = {}\n): Effect.Effect<\n Result[],\n | FileSystemError\n | FileReadError\n | FileWriteError\n | SvelteParseError\n | ValidationError\n> =>\n Effect.gen(function* () {\n const stats = yield* getStats(path);\n\n if (stats.isFile()) {\n const result = yield* processFile(path, options);\n return [result];\n }\n if (stats.isDirectory()) {\n return yield* processPath(path, options);\n }\n\n throw new FileSystemError({\n path,\n cause: \"Path does not exist\",\n });\n }).pipe(\n Effect.catchTag(\"FileSystemError\", (error) => Effect.die(error.cause))\n );\n\n/**\n * Promise-based API for compatibility\n */\nexport async function injectPromise(\n path: string,\n options: Options = {}\n): Promise<Result[]> {\n return Effect.runPromise(inject(path, options));\n}\n"],"mappings":"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","names":[]}