@eui/core 23.0.0-alpha.7 → 23.0.0-alpha.9

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.
@@ -909,12 +909,12 @@
909
909
  },
910
910
  {
911
911
  "name": "Edit",
912
- "id": "interface-Edit-d36032102ed30a7ada1e3d36bb9ca41b7234b855760cac9783a25818f7ffe2097e1ebd8e808b574ddec0760f827272f6cd561f45f3eb1578f87f39ee2633730a-2",
913
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
912
+ "id": "interface-Edit-e1cd02924eb82a618c71a0b26c081bdd020519d2699aa0e2dc98640c4e0f347c3649b967c5fc87543e41bbbfabd1304835850ccc38f40684d6521c242b2030ed-2",
913
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
914
914
  "deprecated": false,
915
915
  "deprecationMessage": "",
916
916
  "type": "interface",
917
- "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nconst OLD_CLASS = 'EuiTooltipConfig';\nconst NEW_INTERFACE = 'EuiTooltipInterface';\n\nexport function migrateEuiTooltip(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_CLASS)) return;\n\n const result = migrateTypeScript(original, path, context);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate EuiTooltipConfig → EuiTooltipInterface in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated EuiTooltipConfig → EuiTooltipInterface in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiTooltipInterface is already imported\n let hasInterfaceImport = false;\n let classImportDecl: ts.ImportDeclaration | null = null;\n let classImportModuleSpecifier: string | null = null;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE) {\n hasInterfaceImport = true;\n }\n if (specifier.name.text === OLD_CLASS) {\n classImportDecl = stmt;\n classImportModuleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n }\n }\n }\n\n // Second pass: handle import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const specifiers = namedBindings.elements;\n const classSpecifier = specifiers.find((s) => s.name.text === OLD_CLASS);\n if (!classSpecifier) continue;\n\n if (hasInterfaceImport) {\n // EuiTooltipInterface is already imported elsewhere → remove EuiTooltipConfig from this import\n removeImportSpecifier(namedBindings, classSpecifier, sourceFile, edits);\n } else {\n // Rename EuiTooltipConfig → EuiTooltipInterface in the import\n edits.push({\n start: classSpecifier.name.getStart(sourceFile),\n end: classSpecifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n hasInterfaceImport = true;\n }\n }\n\n // Third pass: replace `new EuiTooltipConfig(...)` → spread/cast to interface\n const visitNewExpressions = (node: ts.Node): void => {\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === OLD_CLASS) {\n const args = node.arguments;\n if (args && args.length === 1) {\n const arg = args[0];\n // `new EuiTooltipConfig({ ... })` → `{ ... } as EuiTooltipInterface`\n // But if the argument is just a variable, we keep it: `varName as EuiTooltipInterface`\n const argText = source.slice(arg.getStart(sourceFile), arg.getEnd());\n\n if (ts.isObjectLiteralExpression(arg)) {\n // Inline object: `new EuiTooltipConfig({ x: 1 })` → `{ x: 1 }`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: argText,\n });\n } else {\n // Variable or expression: `new EuiTooltipConfig(opts)` → `opts`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: argText,\n });\n }\n } else if (!args || args.length === 0) {\n // `new EuiTooltipConfig()` → `{} as EuiTooltipInterface`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: `{} as ${NEW_INTERFACE}`,\n });\n }\n return; // don't recurse into children we've already replaced\n }\n ts.forEachChild(node, visitNewExpressions);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitNewExpressions(stmt);\n }\n }\n\n // Fourth pass: rename all remaining identifier references (type annotations, etc.)\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return;\n // Skip nodes we already covered in new expressions\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === OLD_CLASS) return;\n\n if (ts.isIdentifier(node) && node.text === OLD_CLASS) {\n // Ensure this is not part of an import declaration\n if (!isPartOfImport(node)) {\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n return applyEdits(source, edits);\n}\n\nfunction isPartOfImport(node: ts.Node): boolean {\n let current: ts.Node | undefined = node.parent;\n while (current) {\n if (ts.isImportDeclaration(current)) return true;\n current = current.parent;\n }\n return false;\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n let end = importDecl.getEnd();\n // Also remove trailing newline if present\n const fullText = sourceFile.getFullText();\n if (fullText[end] === '\\n') end++;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end,\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n // Not the last → remove from this specifier start to next specifier start\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n // Last element → remove from previous element end to this end\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
917
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst OLD_TAG = 'eui-toolbar-menu';\nconst NEW_TAG = 'eui-toolbar-mega-menu';\nconst OLD_COMPONENT = 'EuiToolbarMenuComponent';\nconst NEW_COMPONENT = 'EuiToolbarMegaMenuComponent';\nconst OLD_INTERFACE = 'ToolbarItem';\nconst NEW_INTERFACE = 'EuiMenuItem';\nconst NEW_COMPONENT_PATH = '@eui/components/layout';\nconst NEW_INTERFACE_PATH = '@eui/core';\nconst REMOVED_OUTPUT = 'menuItemClick';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nexport function migrateEuiToolbarMenu(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_TAG) && !original.includes(OLD_COMPONENT) && !original.includes(OLD_INTERFACE)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original, path, context);\n } else {\n result = migrateTypeScript(original, path, context);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-toolbar-menu → eui-toolbar-mega-menu in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated eui-toolbar-menu → eui-toolbar-mega-menu in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n\n visitNodes(parsed.nodes, source, edits, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n let result = migrateInlineTemplates(source, filePath, context);\n result = migrateImportsAndTypes(result, filePath, context);\n return result;\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(OLD_TAG)) {\n ts.forEachChild(node, visit); return; \n}\n const migrated = migrateTemplate(rawTemplate, filePath, context);\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, changes);\n}\n\nfunction migrateImportsAndTypes(source: string, filePath: string, context: SchematicContext): string {\n if (!source.includes(OLD_COMPONENT) && !source.includes(OLD_INTERFACE)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiMenuItem is already imported from @eui/core\n let hasEuiMenuItemImport = false;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpec = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE && moduleSpec === NEW_INTERFACE_PATH) {\n hasEuiMenuItemImport = true;\n }\n }\n }\n\n // Second pass: collect edits for import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const moduleSpec = stmt.moduleSpecifier as ts.StringLiteral;\n const specifiers = namedBindings.elements;\n const hasComponent = specifiers.some((s) => s.name.text === OLD_COMPONENT);\n const hasInterface = specifiers.some((s) => s.name.text === OLD_INTERFACE);\n\n if (hasComponent && hasInterface) {\n // Both are in the same import → must split into two different paths\n const others = specifiers.filter((s) => s.name.text !== OLD_COMPONENT && s.name.text !== OLD_INTERFACE);\n const lines: string[] = [];\n lines.push(`import { ${NEW_COMPONENT} } from '${NEW_COMPONENT_PATH}';`);\n if (!hasEuiMenuItemImport) {\n lines.push(`import { ${NEW_INTERFACE} } from '${NEW_INTERFACE_PATH}';`);\n }\n if (others.length > 0) {\n const otherNames = others.map((s) => s.name.text).join(', ');\n lines.push(`import { ${otherNames} } from '${moduleSpec.text}';`);\n }\n edits.push({\n start: stmt.getStart(sourceFile),\n end: stmt.getEnd(),\n replacement: lines.join('\\n'),\n });\n } else if (hasComponent) {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_COMPONENT_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_COMPONENT) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_COMPONENT,\n });\n }\n }\n } else if (hasInterface) {\n if (hasEuiMenuItemImport) {\n removeImportSpecifier(namedBindings, specifiers.find((s) => s.name.text === OLD_INTERFACE)!, sourceFile, edits);\n } else {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_INTERFACE_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_INTERFACE) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n }\n }\n }\n\n // Third pass: rename identifier references in non-import positions\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return; // skip imports (already handled)\n if (ts.isIdentifier(node)) {\n if (node.text === OLD_COMPONENT) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_COMPONENT });\n }\n if (node.text === OLD_INTERFACE) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_INTERFACE });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n // Warn about ToolbarItem-specific properties\n warnRemovedProperties(sourceFile, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end: importDecl.getEnd(),\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction warnRemovedProperties(sourceFile: ts.SourceFile, filePath: string, context: SchematicContext): void {\n const deprecated = ['isHome', 'isSeparator'];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === OLD_TAG) {\n collectTagRenames(node, source, edits);\n collectOutputRemovals(node, source, edits, filePath, context);\n }\n visitNodes(node.children, source, edits, filePath, context);\n }\n }\n}\n\nfunction collectTagRenames(element: TmplAstElement, source: string, edits: Edit[]): void {\n // Rename opening tag\n const openStart = element.startSourceSpan.start.offset + 1; // skip '<'\n edits.push({ start: openStart, end: openStart + OLD_TAG.length, replacement: NEW_TAG });\n\n // Rename closing tag\n if (element.endSourceSpan) {\n const closeStart = element.endSourceSpan.start.offset + 2; // skip '</'\n edits.push({ start: closeStart, end: closeStart + OLD_TAG.length, replacement: NEW_TAG });\n }\n}\n\nfunction collectOutputRemovals(\n element: TmplAstElement,\n source: string,\n edits: Edit[],\n filePath: string,\n context: SchematicContext,\n): void {\n for (const output of element.outputs) {\n if (output.name === REMOVED_OUTPUT) {\n let start = output.sourceSpan.start.offset;\n // Remove leading whitespace\n while (start > 0 && (source[start - 1] === ' ' || source[start - 1] === '\\t')) {\n start--;\n }\n edits.push({ start, end: output.sourceSpan.end.offset, replacement: '' });\n\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(menuItemClick)\" has been removed. There is no equivalent on eui-toolbar-mega-menu.`,\n );\n }\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n // Deduplicate edits at same position (e.g. module path edits when both Component and ToolbarItem are from same source)\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n // Last wins for same range\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
918
918
  "displayName": "Edit",
919
919
  "properties": [
920
920
  {
@@ -926,7 +926,7 @@
926
926
  "indexKey": "",
927
927
  "optional": false,
928
928
  "description": "",
929
- "line": 12,
929
+ "line": 23,
930
930
  "rawdescription": "\n"
931
931
  },
932
932
  {
@@ -938,7 +938,7 @@
938
938
  "indexKey": "",
939
939
  "optional": false,
940
940
  "description": "",
941
- "line": 13,
941
+ "line": 24,
942
942
  "rawdescription": "\n"
943
943
  },
944
944
  {
@@ -950,7 +950,7 @@
950
950
  "indexKey": "",
951
951
  "optional": false,
952
952
  "description": "",
953
- "line": 11,
953
+ "line": 22,
954
954
  "rawdescription": "\n"
955
955
  }
956
956
  ],
@@ -968,12 +968,12 @@
968
968
  },
969
969
  {
970
970
  "name": "Edit",
971
- "id": "interface-Edit-e1cd02924eb82a618c71a0b26c081bdd020519d2699aa0e2dc98640c4e0f347c3649b967c5fc87543e41bbbfabd1304835850ccc38f40684d6521c242b2030ed-3",
972
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
971
+ "id": "interface-Edit-d36032102ed30a7ada1e3d36bb9ca41b7234b855760cac9783a25818f7ffe2097e1ebd8e808b574ddec0760f827272f6cd561f45f3eb1578f87f39ee2633730a-3",
972
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
973
973
  "deprecated": false,
974
974
  "deprecationMessage": "",
975
975
  "type": "interface",
976
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst OLD_TAG = 'eui-toolbar-menu';\nconst NEW_TAG = 'eui-toolbar-mega-menu';\nconst OLD_COMPONENT = 'EuiToolbarMenuComponent';\nconst NEW_COMPONENT = 'EuiToolbarMegaMenuComponent';\nconst OLD_INTERFACE = 'ToolbarItem';\nconst NEW_INTERFACE = 'EuiMenuItem';\nconst NEW_COMPONENT_PATH = '@eui/components/layout';\nconst NEW_INTERFACE_PATH = '@eui/core';\nconst REMOVED_OUTPUT = 'menuItemClick';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nexport function migrateEuiToolbarMenu(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_TAG) && !original.includes(OLD_COMPONENT) && !original.includes(OLD_INTERFACE)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original, path, context);\n } else {\n result = migrateTypeScript(original, path, context);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-toolbar-menu → eui-toolbar-mega-menu in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated eui-toolbar-menu → eui-toolbar-mega-menu in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n\n visitNodes(parsed.nodes, source, edits, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n let result = migrateInlineTemplates(source, filePath, context);\n result = migrateImportsAndTypes(result, filePath, context);\n return result;\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(OLD_TAG)) {\n ts.forEachChild(node, visit); return; \n}\n const migrated = migrateTemplate(rawTemplate, filePath, context);\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, changes);\n}\n\nfunction migrateImportsAndTypes(source: string, filePath: string, context: SchematicContext): string {\n if (!source.includes(OLD_COMPONENT) && !source.includes(OLD_INTERFACE)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiMenuItem is already imported from @eui/core\n let hasEuiMenuItemImport = false;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpec = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE && moduleSpec === NEW_INTERFACE_PATH) {\n hasEuiMenuItemImport = true;\n }\n }\n }\n\n // Second pass: collect edits for import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const moduleSpec = stmt.moduleSpecifier as ts.StringLiteral;\n const specifiers = namedBindings.elements;\n const hasComponent = specifiers.some((s) => s.name.text === OLD_COMPONENT);\n const hasInterface = specifiers.some((s) => s.name.text === OLD_INTERFACE);\n\n if (hasComponent && hasInterface) {\n // Both are in the same import → must split into two different paths\n const others = specifiers.filter((s) => s.name.text !== OLD_COMPONENT && s.name.text !== OLD_INTERFACE);\n const lines: string[] = [];\n lines.push(`import { ${NEW_COMPONENT} } from '${NEW_COMPONENT_PATH}';`);\n if (!hasEuiMenuItemImport) {\n lines.push(`import { ${NEW_INTERFACE} } from '${NEW_INTERFACE_PATH}';`);\n }\n if (others.length > 0) {\n const otherNames = others.map((s) => s.name.text).join(', ');\n lines.push(`import { ${otherNames} } from '${moduleSpec.text}';`);\n }\n edits.push({\n start: stmt.getStart(sourceFile),\n end: stmt.getEnd(),\n replacement: lines.join('\\n'),\n });\n } else if (hasComponent) {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_COMPONENT_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_COMPONENT) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_COMPONENT,\n });\n }\n }\n } else if (hasInterface) {\n if (hasEuiMenuItemImport) {\n removeImportSpecifier(namedBindings, specifiers.find((s) => s.name.text === OLD_INTERFACE)!, sourceFile, edits);\n } else {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_INTERFACE_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_INTERFACE) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n }\n }\n }\n\n // Third pass: rename identifier references in non-import positions\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return; // skip imports (already handled)\n if (ts.isIdentifier(node)) {\n if (node.text === OLD_COMPONENT) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_COMPONENT });\n }\n if (node.text === OLD_INTERFACE) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_INTERFACE });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n // Warn about ToolbarItem-specific properties\n warnRemovedProperties(sourceFile, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end: importDecl.getEnd(),\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction warnRemovedProperties(sourceFile: ts.SourceFile, filePath: string, context: SchematicContext): void {\n const deprecated = ['isHome', 'isSeparator'];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === OLD_TAG) {\n collectTagRenames(node, source, edits);\n collectOutputRemovals(node, source, edits, filePath, context);\n }\n visitNodes(node.children, source, edits, filePath, context);\n }\n }\n}\n\nfunction collectTagRenames(element: TmplAstElement, source: string, edits: Edit[]): void {\n // Rename opening tag\n const openStart = element.startSourceSpan.start.offset + 1; // skip '<'\n edits.push({ start: openStart, end: openStart + OLD_TAG.length, replacement: NEW_TAG });\n\n // Rename closing tag\n if (element.endSourceSpan) {\n const closeStart = element.endSourceSpan.start.offset + 2; // skip '</'\n edits.push({ start: closeStart, end: closeStart + OLD_TAG.length, replacement: NEW_TAG });\n }\n}\n\nfunction collectOutputRemovals(\n element: TmplAstElement,\n source: string,\n edits: Edit[],\n filePath: string,\n context: SchematicContext,\n): void {\n for (const output of element.outputs) {\n if (output.name === REMOVED_OUTPUT) {\n let start = output.sourceSpan.start.offset;\n // Remove leading whitespace\n while (start > 0 && (source[start - 1] === ' ' || source[start - 1] === '\\t')) {\n start--;\n }\n edits.push({ start, end: output.sourceSpan.end.offset, replacement: '' });\n\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(menuItemClick)\" has been removed. There is no equivalent on eui-toolbar-mega-menu.`,\n );\n }\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n // Deduplicate edits at same position (e.g. module path edits when both Component and ToolbarItem are from same source)\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n // Last wins for same range\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
976
+ "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nconst OLD_CLASS = 'EuiTooltipConfig';\nconst NEW_INTERFACE = 'EuiTooltipInterface';\n\nexport function migrateEuiTooltip(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_CLASS)) return;\n\n const result = migrateTypeScript(original, path, context);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate EuiTooltipConfig → EuiTooltipInterface in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated EuiTooltipConfig → EuiTooltipInterface in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiTooltipInterface is already imported\n let hasInterfaceImport = false;\n let classImportDecl: ts.ImportDeclaration | null = null;\n let classImportModuleSpecifier: string | null = null;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE) {\n hasInterfaceImport = true;\n }\n if (specifier.name.text === OLD_CLASS) {\n classImportDecl = stmt;\n classImportModuleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n }\n }\n }\n\n // Second pass: handle import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const specifiers = namedBindings.elements;\n const classSpecifier = specifiers.find((s) => s.name.text === OLD_CLASS);\n if (!classSpecifier) continue;\n\n if (hasInterfaceImport) {\n // EuiTooltipInterface is already imported elsewhere → remove EuiTooltipConfig from this import\n removeImportSpecifier(namedBindings, classSpecifier, sourceFile, edits);\n } else {\n // Rename EuiTooltipConfig → EuiTooltipInterface in the import\n edits.push({\n start: classSpecifier.name.getStart(sourceFile),\n end: classSpecifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n hasInterfaceImport = true;\n }\n }\n\n // Third pass: replace `new EuiTooltipConfig(...)` → spread/cast to interface\n const visitNewExpressions = (node: ts.Node): void => {\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === OLD_CLASS) {\n const args = node.arguments;\n if (args && args.length === 1) {\n const arg = args[0];\n // `new EuiTooltipConfig({ ... })` → `{ ... } as EuiTooltipInterface`\n // But if the argument is just a variable, we keep it: `varName as EuiTooltipInterface`\n const argText = source.slice(arg.getStart(sourceFile), arg.getEnd());\n\n if (ts.isObjectLiteralExpression(arg)) {\n // Inline object: `new EuiTooltipConfig({ x: 1 })` → `{ x: 1 }`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: argText,\n });\n } else {\n // Variable or expression: `new EuiTooltipConfig(opts)` → `opts`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: argText,\n });\n }\n } else if (!args || args.length === 0) {\n // `new EuiTooltipConfig()` → `{} as EuiTooltipInterface`\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: `{} as ${NEW_INTERFACE}`,\n });\n }\n return; // don't recurse into children we've already replaced\n }\n ts.forEachChild(node, visitNewExpressions);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitNewExpressions(stmt);\n }\n }\n\n // Fourth pass: rename all remaining identifier references (type annotations, etc.)\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return;\n // Skip nodes we already covered in new expressions\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === OLD_CLASS) return;\n\n if (ts.isIdentifier(node) && node.text === OLD_CLASS) {\n // Ensure this is not part of an import declaration\n if (!isPartOfImport(node)) {\n edits.push({\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n return applyEdits(source, edits);\n}\n\nfunction isPartOfImport(node: ts.Node): boolean {\n let current: ts.Node | undefined = node.parent;\n while (current) {\n if (ts.isImportDeclaration(current)) return true;\n current = current.parent;\n }\n return false;\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n let end = importDecl.getEnd();\n // Also remove trailing newline if present\n const fullText = sourceFile.getFullText();\n if (fullText[end] === '\\n') end++;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end,\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n // Not the last → remove from this specifier start to next specifier start\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n // Last element → remove from previous element end to this end\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
977
977
  "displayName": "Edit",
978
978
  "properties": [
979
979
  {
@@ -985,7 +985,7 @@
985
985
  "indexKey": "",
986
986
  "optional": false,
987
987
  "description": "",
988
- "line": 23,
988
+ "line": 12,
989
989
  "rawdescription": "\n"
990
990
  },
991
991
  {
@@ -997,7 +997,7 @@
997
997
  "indexKey": "",
998
998
  "optional": false,
999
999
  "description": "",
1000
- "line": 24,
1000
+ "line": 13,
1001
1001
  "rawdescription": "\n"
1002
1002
  },
1003
1003
  {
@@ -1009,7 +1009,7 @@
1009
1009
  "indexKey": "",
1010
1010
  "optional": false,
1011
1011
  "description": "",
1012
- "line": 22,
1012
+ "line": 11,
1013
1013
  "rawdescription": "\n"
1014
1014
  }
1015
1015
  ],
@@ -2036,12 +2036,12 @@
2036
2036
  },
2037
2037
  {
2038
2038
  "name": "Schema",
2039
- "id": "interface-Schema-9c5e016857e1416ac7bbb881973e644c0f578a53bd432bb951c1676ac3f2a6631bfe3344860346a081b841217278723e0bb0bf2fa35fb869de67cb0cc8d99849",
2040
- "file": "packages/core/schematics/add-eui-imports/index.ts",
2039
+ "id": "interface-Schema-5cd6db1920bd5b70a44c0b8a7f7e30f600bfd16a9950f218e6d451a1755ced95b462ef9a62ee87e39bcb8c392981b8d2597895bf0a272fd8aea71f03429ed976",
2040
+ "file": "packages/core/schematics/icon-migrate/schema.ts",
2041
2041
  "deprecated": false,
2042
2042
  "deprecationMessage": "",
2043
2043
  "type": "interface",
2044
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode, TmplAstTemplate } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\nimport { SELECTOR_MAP, SelectorEntry, getClassNamesForArray } from './selector-map';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n useClassArray?: boolean;\n}\n\ninterface ImportToAdd {\n /** The symbol to add to imports array (class name or array name for spread) */\n symbol: string;\n /** Whether this should be spread (...EUI_BUTTON) */\n isSpread: boolean;\n /** ES import path */\n importPath: string;\n}\n\nexport function addEuiImports(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const useClassArray = options.useClassArray ?? false;\n let filesUpdated = 0;\n\n // Index NgModules for standalone:false support\n const ngModuleIndex = buildNgModuleIndex(tree, tree.getDir(scanPath || '/'));\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts') || path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n const source = buffer.toString('utf-8');\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const components = findComponentDecorators(sourceFile);\n if (components.length === 0) return;\n\n let modified = false;\n\n for (const { decorator, className: componentClassName, isNonStandalone } of components) {\n const templateHtml = getTemplateContent(tree, path, decorator, source);\n if (!templateHtml) continue;\n\n const matched = matchSelectorsInTemplate(templateHtml);\n if (matched.length === 0) continue;\n\n const importsToAdd = resolveImports(matched, useClassArray);\n if (importsToAdd.length === 0) continue;\n\n if (isNonStandalone) {\n // Find the NgModule that declares this component and add imports there\n const moduleInfo = findDeclaringModule(ngModuleIndex, componentClassName);\n if (!moduleInfo) {\n context.logger.warn(`⚠ Could not find declaring NgModule for ${componentClassName} in ${path}`);\n continue;\n }\n const moduleBuffer = tree.read(moduleInfo.path);\n if (!moduleBuffer) continue;\n const moduleSource = moduleBuffer.toString('utf-8');\n const result = addImportsToFile(moduleSource, moduleInfo.path, moduleInfo.decoratorPos, importsToAdd, useClassArray);\n if (result !== moduleSource) {\n if (options.dryRun) {\n logDryRun(context, `Would add EUI imports to NgModule in ${moduleInfo.path} for component ${componentClassName}`);\n } else {\n tree.overwrite(moduleInfo.path, result);\n }\n modified = true;\n }\n } else {\n // Standalone component — add imports directly\n const currentSource = tree.read(path)!.toString('utf-8');\n const result = addImportsToFile(currentSource, path, decorator.getStart(), importsToAdd, useClassArray);\n if (result !== currentSource) {\n if (options.dryRun) {\n logDryRun(context, `Would add EUI imports to ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n modified = true;\n }\n }\n }\n\n if (modified) filesUpdated++;\n });\n\n context.logger.info(`add-eui-imports: ${filesUpdated} file(s) updated.`);\n if (options.dryRun) logDryRunNote(context);\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\n// --- Selector Matching ---\n\nfunction matchSelectorsInTemplate(html: string): SelectorEntry[] {\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n if (parsed.errors?.length) return [];\n\n const matched: SelectorEntry[] = [];\n visitTemplateNodes(parsed.nodes, matched);\n return matched;\n}\n\nfunction visitTemplateNodes(nodes: TmplAstNode[], matched: SelectorEntry[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n matchElement(node, matched);\n visitTemplateNodes(node.children, matched);\n } else if (node instanceof TmplAstTemplate) {\n visitTemplateNodes(node.children, matched);\n }\n }\n}\n\nfunction matchElement(element: TmplAstElement, matched: SelectorEntry[]): void {\n const tagName = element.name;\n const attrNames = new Set([\n ...element.attributes.map(a => a.name),\n ...element.inputs.map(i => i.name),\n ]);\n\n for (const entry of SELECTOR_MAP) {\n if (entry.element && entry.element !== tagName) continue;\n if (!entry.element && entry.attributes.length === 0) continue;\n if (!entry.attributes.every(attr => attrNames.has(attr))) continue;\n // If no element specified, at least one attribute must match on this element\n if (!entry.element && entry.attributes.length > 0 && !entry.attributes.some(attr => attrNames.has(attr))) continue;\n matched.push(entry);\n }\n}\n\n// --- Import Resolution ---\n\nfunction resolveImports(matched: SelectorEntry[], useClassArray: boolean): ImportToAdd[] {\n const seen = new Set<string>();\n const result: ImportToAdd[] = [];\n\n for (const entry of matched) {\n if (useClassArray && entry.classArray) {\n if (seen.has(entry.classArray)) continue;\n seen.add(entry.classArray);\n result.push({ symbol: entry.classArray, isSpread: true, importPath: entry.importPath });\n } else {\n if (seen.has(entry.className)) continue;\n seen.add(entry.className);\n result.push({ symbol: entry.className, isSpread: false, importPath: entry.importPath });\n }\n }\n\n return result;\n}\n\n// --- Template Extraction ---\n\nfunction getTemplateContent(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): string | null {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return null;\n const metadata = call.arguments[0];\n\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue;\n if (prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return init.text;\n }\n }\n if (prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) return templateBuffer.toString('utf-8');\n }\n }\n }\n return null;\n}\n\n// --- Component Decorator Detection ---\n\ninterface ComponentInfo {\n decorator: ts.Decorator;\n className: string;\n isNonStandalone: boolean;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ComponentInfo[] {\n const results: ComponentInfo[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node) && node.name) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n const isNonStandalone = hasStandaloneFalse(dec);\n results.push({ decorator: dec, className: node.name.text, isNonStandalone });\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return results;\n}\n\nfunction hasStandaloneFalse(decorator: ts.Decorator): boolean {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return false;\n for (const prop of call.arguments[0].properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'standalone') {\n return prop.initializer.kind === ts.SyntaxKind.FalseKeyword;\n }\n }\n return false;\n}\n\n// --- NgModule Index ---\n\ninterface NgModuleInfo {\n path: string;\n declarations: string[];\n decoratorPos: number;\n}\n\nfunction buildNgModuleIndex(tree: Tree, dir: DirEntry): NgModuleInfo[] {\n const modules: NgModuleInfo[] = [];\n\n visitDir(dir, (path) => {\n if (!path.endsWith('.ts') || path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n const source = buffer.toString('utf-8');\n if (!source.includes('NgModule')) return;\n\n const sf = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'NgModule') {\n const declarations = extractArrayProperty(dec, 'declarations', source);\n modules.push({ path, declarations, decoratorPos: dec.getStart() });\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n });\n\n return modules;\n}\n\nfunction extractArrayProperty(decorator: ts.Decorator, propName: string, source: string): string[] {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return [];\n for (const prop of call.arguments[0].properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === propName) {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer.elements\n .filter(ts.isIdentifier)\n .map(id => id.text);\n }\n }\n }\n return [];\n}\n\nfunction findDeclaringModule(modules: NgModuleInfo[], componentClassName: string): NgModuleInfo | undefined {\n return modules.find(m => m.declarations.includes(componentClassName));\n}\n\n// --- Import Addition ---\n\nfunction addImportsToFile(source: string, filePath: string, decoratorStartHint: number, imports: ImportToAdd[], useClassArray: boolean): string {\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n // Find the imports array in the decorator closest to decoratorStartHint\n const importsArrayInfo = findDecoratorImportsArray(sf, source, decoratorStartHint);\n if (!importsArrayInfo) return source;\n\n const { arrayNode, decoratorType } = importsArrayInfo;\n\n // Determine what's already in the imports array\n const existingSymbols = new Set<string>();\n const existingSpreads = new Set<string>();\n for (const el of arrayNode.elements) {\n if (ts.isSpreadElement(el) && ts.isIdentifier(el.expression)) {\n existingSpreads.add(el.expression.text);\n } else if (ts.isIdentifier(el)) {\n existingSymbols.add(el.text);\n }\n }\n\n // Filter out already-present imports and compute what to add/remove\n const toAdd: ImportToAdd[] = [];\n const toRemoveFromArray: string[] = []; // individual class names to consolidate\n\n for (const imp of imports) {\n if (imp.isSpread) {\n if (existingSpreads.has(imp.symbol)) continue; // Already has ...EUI_X\n toAdd.push(imp);\n // Consolidate: remove individual class names covered by this array\n if (useClassArray) {\n const coveredClasses = getClassNamesForArray(imp.symbol);\n for (const cls of coveredClasses) {\n if (existingSymbols.has(cls)) toRemoveFromArray.push(cls);\n }\n }\n } else {\n if (existingSymbols.has(imp.symbol)) continue;\n // Also skip if a spread already covers this class\n const coveringArray = imports.find(i => i.isSpread && getClassNamesForArray(i.symbol).includes(imp.symbol));\n if (coveringArray && (existingSpreads.has(coveringArray.symbol) || toAdd.some(a => a.symbol === coveringArray.symbol))) continue;\n toAdd.push(imp);\n }\n }\n\n if (toAdd.length === 0 && toRemoveFromArray.length === 0) return source;\n\n // Build new array content\n let result = source;\n result = updateDecoratorImportsArray(result, filePath, arrayNode, toAdd, toRemoveFromArray);\n\n // Add ES imports\n result = addEsImports(result, filePath, toAdd);\n\n // Remove consolidated class names from ES imports\n if (toRemoveFromArray.length > 0) {\n result = removeFromEsImports(result, filePath, toRemoveFromArray);\n }\n\n return result;\n}\n\ninterface ImportsArrayInfo {\n arrayNode: ts.ArrayLiteralExpression;\n decoratorType: 'Component' | 'NgModule';\n}\n\nfunction findDecoratorImportsArray(sf: ts.SourceFile, source: string, decoratorStartHint: number): ImportsArrayInfo | null {\n let found: ImportsArrayInfo | null = null;\n\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression)) continue;\n if (!ts.isIdentifier(dec.expression.expression)) continue;\n const decName = dec.expression.expression.text;\n if (decName !== 'Component' && decName !== 'NgModule') continue;\n if (Math.abs(dec.getStart() - decoratorStartHint) > 5) continue; // Match by position\n\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n found = { arrayNode: prop.initializer, decoratorType: decName as 'Component' | 'NgModule' };\n return;\n }\n }\n }\n\n // No imports array found — create one\n if (!found && decName === 'Component') {\n // We need to add `imports: []` to the decorator\n // Insert after the last property\n const lastProp = metadata.properties[metadata.properties.length - 1];\n if (lastProp) {\n const insertPos = lastProp.getEnd();\n const indent = detectIndent(source, metadata.getStart());\n const insertion = `,\\n${indent} imports: []`;\n const newSource = source.slice(0, insertPos) + insertion + source.slice(insertPos);\n // Re-parse to get the array node\n const newSf = ts.createSourceFile('', newSource, ts.ScriptTarget.Latest, true);\n const newArray = findImportsArrayInSource(newSf);\n if (newArray) {\n // We can't return a node from a different source file in the general case.\n // Instead, we'll handle the \"no imports array\" case by adding it inline.\n found = null; // Will be handled separately\n }\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return found;\n}\n\nfunction findImportsArrayInSource(sf: ts.SourceFile): ts.ArrayLiteralExpression | null {\n let found: ts.ArrayLiteralExpression | null = null;\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'imports' && ts.isArrayLiteralExpression(node.initializer)) {\n found = node.initializer;\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return found;\n}\n\nfunction updateDecoratorImportsArray(source: string, filePath: string, arrayNode: ts.ArrayLiteralExpression, toAdd: ImportToAdd[], toRemove: string[]): string {\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n // Rebuild the array content\n const existingElements: string[] = [];\n for (const el of arrayNode.elements) {\n const text = source.slice(el.getStart(sf), el.getEnd()).trim();\n // Check if this element should be removed (consolidation)\n if (ts.isIdentifier(el) && toRemove.includes(el.text)) continue;\n existingElements.push(text);\n }\n\n // Add new entries\n for (const imp of toAdd) {\n const entry = imp.isSpread ? `...${imp.symbol}` : imp.symbol;\n if (!existingElements.includes(entry)) {\n existingElements.push(entry);\n }\n }\n\n // Determine formatting\n const arrayStart = arrayNode.getStart(sf);\n const arrayEnd = arrayNode.getEnd();\n const originalText = source.slice(arrayStart, arrayEnd);\n const isMultiline = originalText.includes('\\n');\n\n let newArrayText: string;\n if (isMultiline || existingElements.length > 3) {\n const indent = detectIndent(source, arrayStart);\n const itemIndent = indent + ' ';\n newArrayText = `[\\n${existingElements.map(e => `${itemIndent}${e},`).join('\\n')}\\n${indent}]`;\n } else {\n newArrayText = `[${existingElements.join(', ')}]`;\n }\n\n return source.slice(0, arrayStart) + newArrayText + source.slice(arrayEnd);\n}\n\nfunction addEsImports(source: string, filePath: string, imports: ImportToAdd[]): string {\n let result = source;\n\n // Group by import path\n const byPath = new Map<string, string[]>();\n for (const imp of imports) {\n const existing = byPath.get(imp.importPath) || [];\n existing.push(imp.symbol);\n byPath.set(imp.importPath, existing);\n }\n\n for (const [importPath, symbols] of byPath) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n // Check if there's already an import from this path\n const existingImport = sf.statements.find(\n (s): s is ts.ImportDeclaration =>\n ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n );\n\n if (existingImport?.importClause?.namedBindings && ts.isNamedImports(existingImport.importClause.namedBindings)) {\n // Extend existing import\n const namedBindings = existingImport.importClause.namedBindings;\n const existingNames = namedBindings.elements.map(el => el.name.text);\n const newNames = symbols.filter(s => !existingNames.includes(s));\n if (newNames.length === 0) continue;\n\n const allNames = [...existingNames, ...newNames].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n // Add new import statement\n const sortedSymbols = [...symbols].sort();\n const newImport = `import { ${sortedSymbols.join(', ')} } from '${importPath}';\\n`;\n\n // Insert after the last existing import\n const lastImport = [...sf.statements].reverse().find(ts.isImportDeclaration);\n if (lastImport) {\n const pos = lastImport.getEnd();\n result = result.slice(0, pos) + '\\n' + newImport.trimEnd() + result.slice(pos);\n } else {\n result = newImport + result;\n }\n }\n }\n\n return result;\n}\n\nfunction detectIndent(source: string, pos: number): string {\n const lineStart = source.lastIndexOf('\\n', pos - 1) + 1;\n const match = source.slice(lineStart, pos).match(/^(\\s*)/);\n return match ? match[1] : '';\n}\n\nfunction removeFromEsImports(source: string, filePath: string, symbolsToRemove: string[]): string {\n let result = source;\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const existingNames = namedBindings.elements.map(el => el.name.text);\n const remaining = existingNames.filter(n => !symbolsToRemove.includes(n));\n\n if (remaining.length === existingNames.length) continue; // Nothing to remove from this import\n\n if (remaining.length === 0) {\n // Remove the entire import statement\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n } else {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n }\n break; // Only process the first matching import for the consolidated symbols\n }\n\n return result;\n}\n",
2044
+ "sourceCode": "export interface Schema {\n /** The path to scan for files to migrate */\n path?: string;\n /** Whether to perform a dry run without making changes */\n dryRun?: boolean;\n}\n",
2045
2045
  "displayName": "Schema",
2046
2046
  "properties": [
2047
2047
  {
@@ -2052,9 +2052,9 @@
2052
2052
  "type": "boolean",
2053
2053
  "indexKey": "",
2054
2054
  "optional": true,
2055
- "description": "",
2056
- "line": 9,
2057
- "rawdescription": "\n"
2055
+ "description": "<p>Whether to perform a dry run without making changes</p>\n",
2056
+ "line": 5,
2057
+ "rawdescription": "\nWhether to perform a dry run without making changes"
2058
2058
  },
2059
2059
  {
2060
2060
  "name": "path",
@@ -2064,21 +2064,9 @@
2064
2064
  "type": "string",
2065
2065
  "indexKey": "",
2066
2066
  "optional": true,
2067
- "description": "",
2068
- "line": 8,
2069
- "rawdescription": "\n"
2070
- },
2071
- {
2072
- "name": "useClassArray",
2073
- "coverageIgnore": false,
2074
- "deprecated": false,
2075
- "deprecationMessage": "",
2076
- "type": "boolean",
2077
- "indexKey": "",
2078
- "optional": true,
2079
- "description": "",
2080
- "line": 10,
2081
- "rawdescription": "\n"
2067
+ "description": "<p>The path to scan for files to migrate</p>\n",
2068
+ "line": 3,
2069
+ "rawdescription": "\nThe path to scan for files to migrate"
2082
2070
  }
2083
2071
  ],
2084
2072
  "indexSignatures": [],
@@ -2092,12 +2080,12 @@
2092
2080
  },
2093
2081
  {
2094
2082
  "name": "Schema",
2095
- "id": "interface-Schema-4fe31ff3e9f1d34845a6b865d605e215f33552094b88c3d0eab0b180187fe64ce4d68d687516cb3d62c57d2678a103969b2dacbb18a49b26060f78096678fcce-1",
2096
- "file": "packages/core/schematics/fix-no-multiple-empty-lines/index.ts",
2083
+ "id": "interface-Schema-9c5e016857e1416ac7bbb881973e644c0f578a53bd432bb951c1676ac3f2a6631bfe3344860346a081b841217278723e0bb0bf2fa35fb869de67cb0cc8d99849-1",
2084
+ "file": "packages/core/schematics/add-eui-imports/index.ts",
2097
2085
  "deprecated": false,
2098
2086
  "deprecationMessage": "",
2099
2087
  "type": "interface",
2100
- "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst MULTIPLE_EMPTY_LINES = /\\n{3,}/g;\n\nexport function fixNoMultipleEmptyLines(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (filePath) => {\n const buffer = tree.read(filePath);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n const result = original.replace(MULTIPLE_EMPTY_LINES, '\\n\\n');\n\n if (result !== original) {\n if (filePath.endsWith('.ts')) {\n const sourceFile = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((sourceFile as any).parseDiagnostics?.length) {\n context.logger.warn(`Skipping ${filePath}: file would not parse after transformation.`);\n return;\n }\n }\n if (options.dryRun) {\n logDryRun(context, `Would collapse multiple empty lines in ${filePath}`);\n } else {\n tree.overwrite(filePath, result);\n }\n count++;\n }\n });\n\n context.logger.info(`Fixed multiple empty lines in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts') && !file.endsWith('.html') && !file.endsWith('.scss') && !file.endsWith('.css')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2088
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode, TmplAstTemplate } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\nimport { SELECTOR_MAP, SelectorEntry, getClassNamesForArray } from './selector-map';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n useClassArray?: boolean;\n}\n\ninterface ImportToAdd {\n /** The symbol to add to imports array (class name or array name for spread) */\n symbol: string;\n /** Whether this should be spread (...EUI_BUTTON) */\n isSpread: boolean;\n /** ES import path */\n importPath: string;\n}\n\nexport function addEuiImports(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const useClassArray = options.useClassArray ?? false;\n let filesUpdated = 0;\n\n // Index NgModules for standalone:false support\n const ngModuleIndex = buildNgModuleIndex(tree, tree.getDir(scanPath || '/'));\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts') || path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n const source = buffer.toString('utf-8');\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const components = findComponentDecorators(sourceFile);\n if (components.length === 0) return;\n\n let modified = false;\n\n for (const { decorator, className: componentClassName, isNonStandalone } of components) {\n const templateHtml = getTemplateContent(tree, path, decorator, source);\n if (!templateHtml) continue;\n\n const matched = matchSelectorsInTemplate(templateHtml);\n if (matched.length === 0) continue;\n\n const importsToAdd = resolveImports(matched, useClassArray);\n if (importsToAdd.length === 0) continue;\n\n if (isNonStandalone) {\n // Find the NgModule that declares this component and add imports there\n const moduleInfo = findDeclaringModule(ngModuleIndex, componentClassName);\n if (!moduleInfo) {\n context.logger.warn(`⚠ Could not find declaring NgModule for ${componentClassName} in ${path}`);\n continue;\n }\n const moduleBuffer = tree.read(moduleInfo.path);\n if (!moduleBuffer) continue;\n const moduleSource = moduleBuffer.toString('utf-8');\n const result = addImportsToFile(moduleSource, moduleInfo.path, moduleInfo.decoratorPos, importsToAdd, useClassArray);\n if (result !== moduleSource) {\n if (options.dryRun) {\n logDryRun(context, `Would add EUI imports to NgModule in ${moduleInfo.path} for component ${componentClassName}`);\n } else {\n tree.overwrite(moduleInfo.path, result);\n }\n modified = true;\n }\n } else {\n // Standalone component — add imports directly\n const currentSource = tree.read(path)!.toString('utf-8');\n const result = addImportsToFile(currentSource, path, decorator.getStart(), importsToAdd, useClassArray);\n if (result !== currentSource) {\n if (options.dryRun) {\n logDryRun(context, `Would add EUI imports to ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n modified = true;\n }\n }\n }\n\n if (modified) filesUpdated++;\n });\n\n context.logger.info(`add-eui-imports: ${filesUpdated} file(s) updated.`);\n if (options.dryRun) logDryRunNote(context);\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\n// --- Selector Matching ---\n\nfunction matchSelectorsInTemplate(html: string): SelectorEntry[] {\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n if (parsed.errors?.length) return [];\n\n const matched: SelectorEntry[] = [];\n visitTemplateNodes(parsed.nodes, matched);\n return matched;\n}\n\nfunction visitTemplateNodes(nodes: TmplAstNode[], matched: SelectorEntry[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n matchElement(node, matched);\n visitTemplateNodes(node.children, matched);\n } else if (node instanceof TmplAstTemplate) {\n visitTemplateNodes(node.children, matched);\n }\n }\n}\n\nfunction matchElement(element: TmplAstElement, matched: SelectorEntry[]): void {\n const tagName = element.name;\n const attrNames = new Set([\n ...element.attributes.map(a => a.name),\n ...element.inputs.map(i => i.name),\n ]);\n\n for (const entry of SELECTOR_MAP) {\n if (entry.element && entry.element !== tagName) continue;\n if (!entry.element && entry.attributes.length === 0) continue;\n if (!entry.attributes.every(attr => attrNames.has(attr))) continue;\n // If no element specified, at least one attribute must match on this element\n if (!entry.element && entry.attributes.length > 0 && !entry.attributes.some(attr => attrNames.has(attr))) continue;\n matched.push(entry);\n }\n}\n\n// --- Import Resolution ---\n\nfunction resolveImports(matched: SelectorEntry[], useClassArray: boolean): ImportToAdd[] {\n const seen = new Set<string>();\n const result: ImportToAdd[] = [];\n\n for (const entry of matched) {\n if (useClassArray && entry.classArray) {\n if (seen.has(entry.classArray)) continue;\n seen.add(entry.classArray);\n result.push({ symbol: entry.classArray, isSpread: true, importPath: entry.importPath });\n } else {\n if (seen.has(entry.className)) continue;\n seen.add(entry.className);\n result.push({ symbol: entry.className, isSpread: false, importPath: entry.importPath });\n }\n }\n\n return result;\n}\n\n// --- Template Extraction ---\n\nfunction getTemplateContent(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): string | null {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return null;\n const metadata = call.arguments[0];\n\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue;\n if (prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return init.text;\n }\n }\n if (prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) return templateBuffer.toString('utf-8');\n }\n }\n }\n return null;\n}\n\n// --- Component Decorator Detection ---\n\ninterface ComponentInfo {\n decorator: ts.Decorator;\n className: string;\n isNonStandalone: boolean;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ComponentInfo[] {\n const results: ComponentInfo[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node) && node.name) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n const isNonStandalone = hasStandaloneFalse(dec);\n results.push({ decorator: dec, className: node.name.text, isNonStandalone });\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return results;\n}\n\nfunction hasStandaloneFalse(decorator: ts.Decorator): boolean {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return false;\n for (const prop of call.arguments[0].properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'standalone') {\n return prop.initializer.kind === ts.SyntaxKind.FalseKeyword;\n }\n }\n return false;\n}\n\n// --- NgModule Index ---\n\ninterface NgModuleInfo {\n path: string;\n declarations: string[];\n decoratorPos: number;\n}\n\nfunction buildNgModuleIndex(tree: Tree, dir: DirEntry): NgModuleInfo[] {\n const modules: NgModuleInfo[] = [];\n\n visitDir(dir, (path) => {\n if (!path.endsWith('.ts') || path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n const source = buffer.toString('utf-8');\n if (!source.includes('NgModule')) return;\n\n const sf = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'NgModule') {\n const declarations = extractArrayProperty(dec, 'declarations', source);\n modules.push({ path, declarations, decoratorPos: dec.getStart() });\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n });\n\n return modules;\n}\n\nfunction extractArrayProperty(decorator: ts.Decorator, propName: string, source: string): string[] {\n const call = decorator.expression as ts.CallExpression;\n if (!call.arguments[0] || !ts.isObjectLiteralExpression(call.arguments[0])) return [];\n for (const prop of call.arguments[0].properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === propName) {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer.elements\n .filter(ts.isIdentifier)\n .map(id => id.text);\n }\n }\n }\n return [];\n}\n\nfunction findDeclaringModule(modules: NgModuleInfo[], componentClassName: string): NgModuleInfo | undefined {\n return modules.find(m => m.declarations.includes(componentClassName));\n}\n\n// --- Import Addition ---\n\nfunction addImportsToFile(source: string, filePath: string, decoratorStartHint: number, imports: ImportToAdd[], useClassArray: boolean): string {\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n // Find the imports array in the decorator closest to decoratorStartHint\n const importsArrayInfo = findDecoratorImportsArray(sf, source, decoratorStartHint);\n if (!importsArrayInfo) return source;\n\n const { arrayNode, decoratorType } = importsArrayInfo;\n\n // Determine what's already in the imports array\n const existingSymbols = new Set<string>();\n const existingSpreads = new Set<string>();\n for (const el of arrayNode.elements) {\n if (ts.isSpreadElement(el) && ts.isIdentifier(el.expression)) {\n existingSpreads.add(el.expression.text);\n } else if (ts.isIdentifier(el)) {\n existingSymbols.add(el.text);\n }\n }\n\n // Filter out already-present imports and compute what to add/remove\n const toAdd: ImportToAdd[] = [];\n const toRemoveFromArray: string[] = []; // individual class names to consolidate\n\n for (const imp of imports) {\n if (imp.isSpread) {\n if (existingSpreads.has(imp.symbol)) continue; // Already has ...EUI_X\n toAdd.push(imp);\n // Consolidate: remove individual class names covered by this array\n if (useClassArray) {\n const coveredClasses = getClassNamesForArray(imp.symbol);\n for (const cls of coveredClasses) {\n if (existingSymbols.has(cls)) toRemoveFromArray.push(cls);\n }\n }\n } else {\n if (existingSymbols.has(imp.symbol)) continue;\n // Also skip if a spread already covers this class\n const coveringArray = imports.find(i => i.isSpread && getClassNamesForArray(i.symbol).includes(imp.symbol));\n if (coveringArray && (existingSpreads.has(coveringArray.symbol) || toAdd.some(a => a.symbol === coveringArray.symbol))) continue;\n toAdd.push(imp);\n }\n }\n\n if (toAdd.length === 0 && toRemoveFromArray.length === 0) return source;\n\n // Build new array content\n let result = source;\n result = updateDecoratorImportsArray(result, filePath, arrayNode, toAdd, toRemoveFromArray);\n\n // Add ES imports\n result = addEsImports(result, filePath, toAdd);\n\n // Remove consolidated class names from ES imports\n if (toRemoveFromArray.length > 0) {\n result = removeFromEsImports(result, filePath, toRemoveFromArray);\n }\n\n return result;\n}\n\ninterface ImportsArrayInfo {\n arrayNode: ts.ArrayLiteralExpression;\n decoratorType: 'Component' | 'NgModule';\n}\n\nfunction findDecoratorImportsArray(sf: ts.SourceFile, source: string, decoratorStartHint: number): ImportsArrayInfo | null {\n let found: ImportsArrayInfo | null = null;\n\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression)) continue;\n if (!ts.isIdentifier(dec.expression.expression)) continue;\n const decName = dec.expression.expression.text;\n if (decName !== 'Component' && decName !== 'NgModule') continue;\n if (Math.abs(dec.getStart() - decoratorStartHint) > 5) continue; // Match by position\n\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n found = { arrayNode: prop.initializer, decoratorType: decName as 'Component' | 'NgModule' };\n return;\n }\n }\n }\n\n // No imports array found — create one\n if (!found && decName === 'Component') {\n // We need to add `imports: []` to the decorator\n // Insert after the last property\n const lastProp = metadata.properties[metadata.properties.length - 1];\n if (lastProp) {\n const insertPos = lastProp.getEnd();\n const indent = detectIndent(source, metadata.getStart());\n const insertion = `,\\n${indent} imports: []`;\n const newSource = source.slice(0, insertPos) + insertion + source.slice(insertPos);\n // Re-parse to get the array node\n const newSf = ts.createSourceFile('', newSource, ts.ScriptTarget.Latest, true);\n const newArray = findImportsArrayInSource(newSf);\n if (newArray) {\n // We can't return a node from a different source file in the general case.\n // Instead, we'll handle the \"no imports array\" case by adding it inline.\n found = null; // Will be handled separately\n }\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return found;\n}\n\nfunction findImportsArrayInSource(sf: ts.SourceFile): ts.ArrayLiteralExpression | null {\n let found: ts.ArrayLiteralExpression | null = null;\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'imports' && ts.isArrayLiteralExpression(node.initializer)) {\n found = node.initializer;\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return found;\n}\n\nfunction updateDecoratorImportsArray(source: string, filePath: string, arrayNode: ts.ArrayLiteralExpression, toAdd: ImportToAdd[], toRemove: string[]): string {\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n // Rebuild the array content\n const existingElements: string[] = [];\n for (const el of arrayNode.elements) {\n const text = source.slice(el.getStart(sf), el.getEnd()).trim();\n // Check if this element should be removed (consolidation)\n if (ts.isIdentifier(el) && toRemove.includes(el.text)) continue;\n existingElements.push(text);\n }\n\n // Add new entries\n for (const imp of toAdd) {\n const entry = imp.isSpread ? `...${imp.symbol}` : imp.symbol;\n if (!existingElements.includes(entry)) {\n existingElements.push(entry);\n }\n }\n\n // Determine formatting\n const arrayStart = arrayNode.getStart(sf);\n const arrayEnd = arrayNode.getEnd();\n const originalText = source.slice(arrayStart, arrayEnd);\n const isMultiline = originalText.includes('\\n');\n\n let newArrayText: string;\n if (isMultiline || existingElements.length > 3) {\n const indent = detectIndent(source, arrayStart);\n const itemIndent = indent + ' ';\n newArrayText = `[\\n${existingElements.map(e => `${itemIndent}${e},`).join('\\n')}\\n${indent}]`;\n } else {\n newArrayText = `[${existingElements.join(', ')}]`;\n }\n\n return source.slice(0, arrayStart) + newArrayText + source.slice(arrayEnd);\n}\n\nfunction addEsImports(source: string, filePath: string, imports: ImportToAdd[]): string {\n let result = source;\n\n // Group by import path\n const byPath = new Map<string, string[]>();\n for (const imp of imports) {\n const existing = byPath.get(imp.importPath) || [];\n existing.push(imp.symbol);\n byPath.set(imp.importPath, existing);\n }\n\n for (const [importPath, symbols] of byPath) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n // Check if there's already an import from this path\n const existingImport = sf.statements.find(\n (s): s is ts.ImportDeclaration =>\n ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n );\n\n if (existingImport?.importClause?.namedBindings && ts.isNamedImports(existingImport.importClause.namedBindings)) {\n // Extend existing import\n const namedBindings = existingImport.importClause.namedBindings;\n const existingNames = namedBindings.elements.map(el => el.name.text);\n const newNames = symbols.filter(s => !existingNames.includes(s));\n if (newNames.length === 0) continue;\n\n const allNames = [...existingNames, ...newNames].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n // Add new import statement\n const sortedSymbols = [...symbols].sort();\n const newImport = `import { ${sortedSymbols.join(', ')} } from '${importPath}';\\n`;\n\n // Insert after the last existing import\n const lastImport = [...sf.statements].reverse().find(ts.isImportDeclaration);\n if (lastImport) {\n const pos = lastImport.getEnd();\n result = result.slice(0, pos) + '\\n' + newImport.trimEnd() + result.slice(pos);\n } else {\n result = newImport + result;\n }\n }\n }\n\n return result;\n}\n\nfunction detectIndent(source: string, pos: number): string {\n const lineStart = source.lastIndexOf('\\n', pos - 1) + 1;\n const match = source.slice(lineStart, pos).match(/^(\\s*)/);\n return match ? match[1] : '';\n}\n\nfunction removeFromEsImports(source: string, filePath: string, symbolsToRemove: string[]): string {\n let result = source;\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const existingNames = namedBindings.elements.map(el => el.name.text);\n const remaining = existingNames.filter(n => !symbolsToRemove.includes(n));\n\n if (remaining.length === existingNames.length) continue; // Nothing to remove from this import\n\n if (remaining.length === 0) {\n // Remove the entire import statement\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n } else {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n }\n break; // Only process the first matching import for the consolidated symbols\n }\n\n return result;\n}\n",
2101
2089
  "displayName": "Schema",
2102
2090
  "properties": [
2103
2091
  {
@@ -2109,7 +2097,7 @@
2109
2097
  "indexKey": "",
2110
2098
  "optional": true,
2111
2099
  "description": "",
2112
- "line": 7,
2100
+ "line": 9,
2113
2101
  "rawdescription": "\n"
2114
2102
  },
2115
2103
  {
@@ -2121,7 +2109,19 @@
2121
2109
  "indexKey": "",
2122
2110
  "optional": true,
2123
2111
  "description": "",
2124
- "line": 6,
2112
+ "line": 8,
2113
+ "rawdescription": "\n"
2114
+ },
2115
+ {
2116
+ "name": "useClassArray",
2117
+ "coverageIgnore": false,
2118
+ "deprecated": false,
2119
+ "deprecationMessage": "",
2120
+ "type": "boolean",
2121
+ "indexKey": "",
2122
+ "optional": true,
2123
+ "description": "",
2124
+ "line": 10,
2125
2125
  "rawdescription": "\n"
2126
2126
  }
2127
2127
  ],
@@ -2139,12 +2139,12 @@
2139
2139
  },
2140
2140
  {
2141
2141
  "name": "Schema",
2142
- "id": "interface-Schema-5cd6db1920bd5b70a44c0b8a7f7e30f600bfd16a9950f218e6d451a1755ced95b462ef9a62ee87e39bcb8c392981b8d2597895bf0a272fd8aea71f03429ed976-2",
2143
- "file": "packages/core/schematics/icon-migrate/schema.ts",
2142
+ "id": "interface-Schema-4fe31ff3e9f1d34845a6b865d605e215f33552094b88c3d0eab0b180187fe64ce4d68d687516cb3d62c57d2678a103969b2dacbb18a49b26060f78096678fcce-2",
2143
+ "file": "packages/core/schematics/fix-no-multiple-empty-lines/index.ts",
2144
2144
  "deprecated": false,
2145
2145
  "deprecationMessage": "",
2146
2146
  "type": "interface",
2147
- "sourceCode": "export interface Schema {\n /** The path to scan for files to migrate */\n path?: string;\n /** Whether to perform a dry run without making changes */\n dryRun?: boolean;\n}\n",
2147
+ "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst MULTIPLE_EMPTY_LINES = /\\n{3,}/g;\n\nexport function fixNoMultipleEmptyLines(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (filePath) => {\n const buffer = tree.read(filePath);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n const result = original.replace(MULTIPLE_EMPTY_LINES, '\\n\\n');\n\n if (result !== original) {\n if (filePath.endsWith('.ts')) {\n const sourceFile = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((sourceFile as any).parseDiagnostics?.length) {\n context.logger.warn(`Skipping ${filePath}: file would not parse after transformation.`);\n return;\n }\n }\n if (options.dryRun) {\n logDryRun(context, `Would collapse multiple empty lines in ${filePath}`);\n } else {\n tree.overwrite(filePath, result);\n }\n count++;\n }\n });\n\n context.logger.info(`Fixed multiple empty lines in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts') && !file.endsWith('.html') && !file.endsWith('.scss') && !file.endsWith('.css')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2148
2148
  "displayName": "Schema",
2149
2149
  "properties": [
2150
2150
  {
@@ -2155,9 +2155,9 @@
2155
2155
  "type": "boolean",
2156
2156
  "indexKey": "",
2157
2157
  "optional": true,
2158
- "description": "<p>Whether to perform a dry run without making changes</p>\n",
2159
- "line": 5,
2160
- "rawdescription": "\nWhether to perform a dry run without making changes"
2158
+ "description": "",
2159
+ "line": 7,
2160
+ "rawdescription": "\n"
2161
2161
  },
2162
2162
  {
2163
2163
  "name": "path",
@@ -2167,9 +2167,9 @@
2167
2167
  "type": "string",
2168
2168
  "indexKey": "",
2169
2169
  "optional": true,
2170
- "description": "<p>The path to scan for files to migrate</p>\n",
2171
- "line": 3,
2172
- "rawdescription": "\nThe path to scan for files to migrate"
2170
+ "description": "",
2171
+ "line": 6,
2172
+ "rawdescription": "\n"
2173
2173
  }
2174
2174
  ],
2175
2175
  "indexSignatures": [],
@@ -2527,12 +2527,12 @@
2527
2527
  },
2528
2528
  {
2529
2529
  "name": "Schema",
2530
- "id": "interface-Schema-375dc0924084a2acbafe4a6a32577d59f631c9a386d151180d8fb1c89e7e7cd23da9fd459e597592ed823692adb6ad2633c50baf16621f003246e8c9bb1c6ce0-10",
2531
- "file": "packages/core/schematics/migrate-eui-editor/index.ts",
2530
+ "id": "interface-Schema-869dfc324e9111966817cbebb3553eabfe200acfe33bb77efa71a6c46e1cba0ff5852de7b9ade3060f87264035b99591361331a9e0622daaac22b8d59146c761-10",
2531
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
2532
2532
  "deprecated": false,
2533
2533
  "deprecationMessage": "",
2534
2534
  "type": "interface",
2535
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst COMPONENT_TAG = 'eui-editor';\nconst OLD_NAME = 'onEditorChanged';\nconst NEW_NAME = 'contentChange';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateEuiEditor(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n if (path.endsWith('.html')) {\n if (!original.includes(COMPONENT_TAG)) return;\n const result = migrateTemplate(original);\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n return;\n }\n\n // .ts file handle both migration and warnings in one pass\n const hasTag = original.includes(COMPONENT_TAG);\n const hasOldName = original.includes(OLD_NAME);\n if (!hasTag && !hasOldName) return;\n\n if (hasTag) {\n const result = migrateInlineTemplates(original);\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n }\n\n // Warn about TS property access usages (skip spec files)\n if (hasOldName && !path.endsWith('.spec.ts')) {\n warnPropertyAccesses(path, original, context);\n }\n });\n\n context.logger.info(`Renamed '(${OLD_NAME})' '(${NEW_NAME})' on ${COMPONENT_TAG} in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(COMPONENT_TAG)) {\n ts.forEachChild(node, visit); return;\n}\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) changes.push({ start, end, text: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction warnPropertyAccesses(path: string, source: string, context: SchematicContext): void {\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === OLD_NAME) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(`${path}:${line + 1} - \"${OLD_NAME}\" has been renamed to \"${NEW_NAME}\" on ${COMPONENT_TAG}. Update this reference manually.`);\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) collectRenames(node, edits);\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const output of element.outputs) {\n if (output.name === OLD_NAME) {\n edits.push({ start: output.keySpan!.start.offset, end: output.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
2535
+ "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst COMPONENT_TAG = 'eui-discussion-thread';\n\nexport function migrateEuiDiscussionThread(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(COMPONENT_TAG)) return;\n\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would remove [trackBy] binding in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n\n // Warn about TS usages inline\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts') && original.includes('trackByFn')) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === 'trackByFn') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(`${path}:${line + 1} - \"trackByFn\" has been removed from ${COMPONENT_TAG}. Remove this reference manually.`);\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n });\n\n context.logger.info(`Removed trackByFn-based [trackBy] bindings from ${COMPONENT_TAG} in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const removals: { start: number; end: number }[] = [];\n\n visitNodes(parsed.nodes, source, removals);\n\n let result = source;\n for (const { start, end } of removals.sort((a, b) => b.start - a.start)) {\n let adjustedStart = start;\n while (adjustedStart > 0 && (result[adjustedStart - 1] === ' ' || result[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n result = result.slice(0, adjustedStart) + result.slice(end);\n }\n\n return result;\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const templateRegex = /template\\s*:\\s*`([^`]*)`/gs;\n return source.replace(templateRegex, (match, templateContent: string) => {\n if (!templateContent.includes(COMPONENT_TAG)) return match;\n const migrated = migrateTemplate(templateContent);\n if (migrated === templateContent) return match;\n return match.replace(templateContent, migrated);\n });\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, removals: { start: number; end: number }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) collectRemovals(node, source, removals);\n visitNodes(node.children, source, removals);\n }\n }\n}\n\nfunction collectRemovals(element: TmplAstElement, source: string, removals: { start: number; end: number }[]): void {\n for (const input of element.inputs) {\n if (input.name === 'trackBy') {\n const valueSource = source.slice(input.sourceSpan.start.offset, input.sourceSpan.end.offset);\n if (valueSource.includes('trackByFn')) {\n removals.push({ start: input.sourceSpan.start.offset, end: input.sourceSpan.end.offset });\n }\n }\n }\n}\n",
2536
2536
  "displayName": "Schema",
2537
2537
  "properties": [
2538
2538
  {
@@ -2544,7 +2544,7 @@
2544
2544
  "indexKey": "",
2545
2545
  "optional": true,
2546
2546
  "description": "",
2547
- "line": 12,
2547
+ "line": 8,
2548
2548
  "rawdescription": "\n"
2549
2549
  },
2550
2550
  {
@@ -2556,7 +2556,7 @@
2556
2556
  "indexKey": "",
2557
2557
  "optional": true,
2558
2558
  "description": "",
2559
- "line": 11,
2559
+ "line": 7,
2560
2560
  "rawdescription": "\n"
2561
2561
  }
2562
2562
  ],
@@ -2574,12 +2574,12 @@
2574
2574
  },
2575
2575
  {
2576
2576
  "name": "Schema",
2577
- "id": "interface-Schema-869dfc324e9111966817cbebb3553eabfe200acfe33bb77efa71a6c46e1cba0ff5852de7b9ade3060f87264035b99591361331a9e0622daaac22b8d59146c761-11",
2578
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
2577
+ "id": "interface-Schema-375dc0924084a2acbafe4a6a32577d59f631c9a386d151180d8fb1c89e7e7cd23da9fd459e597592ed823692adb6ad2633c50baf16621f003246e8c9bb1c6ce0-11",
2578
+ "file": "packages/core/schematics/migrate-eui-editor/index.ts",
2579
2579
  "deprecated": false,
2580
2580
  "deprecationMessage": "",
2581
2581
  "type": "interface",
2582
- "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst COMPONENT_TAG = 'eui-discussion-thread';\n\nexport function migrateEuiDiscussionThread(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(COMPONENT_TAG)) return;\n\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would remove [trackBy] binding in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n\n // Warn about TS usages inline\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts') && original.includes('trackByFn')) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === 'trackByFn') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(`${path}:${line + 1} - \"trackByFn\" has been removed from ${COMPONENT_TAG}. Remove this reference manually.`);\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n });\n\n context.logger.info(`Removed trackByFn-based [trackBy] bindings from ${COMPONENT_TAG} in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const removals: { start: number; end: number }[] = [];\n\n visitNodes(parsed.nodes, source, removals);\n\n let result = source;\n for (const { start, end } of removals.sort((a, b) => b.start - a.start)) {\n let adjustedStart = start;\n while (adjustedStart > 0 && (result[adjustedStart - 1] === ' ' || result[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n result = result.slice(0, adjustedStart) + result.slice(end);\n }\n\n return result;\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const templateRegex = /template\\s*:\\s*`([^`]*)`/gs;\n return source.replace(templateRegex, (match, templateContent: string) => {\n if (!templateContent.includes(COMPONENT_TAG)) return match;\n const migrated = migrateTemplate(templateContent);\n if (migrated === templateContent) return match;\n return match.replace(templateContent, migrated);\n });\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, removals: { start: number; end: number }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) collectRemovals(node, source, removals);\n visitNodes(node.children, source, removals);\n }\n }\n}\n\nfunction collectRemovals(element: TmplAstElement, source: string, removals: { start: number; end: number }[]): void {\n for (const input of element.inputs) {\n if (input.name === 'trackBy') {\n const valueSource = source.slice(input.sourceSpan.start.offset, input.sourceSpan.end.offset);\n if (valueSource.includes('trackByFn')) {\n removals.push({ start: input.sourceSpan.start.offset, end: input.sourceSpan.end.offset });\n }\n }\n }\n}\n",
2582
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst COMPONENT_TAG = 'eui-editor';\nconst OLD_NAME = 'onEditorChanged';\nconst NEW_NAME = 'contentChange';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateEuiEditor(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n if (path.endsWith('.html')) {\n if (!original.includes(COMPONENT_TAG)) return;\n const result = migrateTemplate(original);\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n return;\n }\n\n // .ts file handle both migration and warnings in one pass\n const hasTag = original.includes(COMPONENT_TAG);\n const hasOldName = original.includes(OLD_NAME);\n if (!hasTag && !hasOldName) return;\n\n if (hasTag) {\n const result = migrateInlineTemplates(original);\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n }\n\n // Warn about TS property access usages (skip spec files)\n if (hasOldName && !path.endsWith('.spec.ts')) {\n warnPropertyAccesses(path, original, context);\n }\n });\n\n context.logger.info(`Renamed '(${OLD_NAME})' '(${NEW_NAME})' on ${COMPONENT_TAG} in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(COMPONENT_TAG)) {\n ts.forEachChild(node, visit); return;\n}\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) changes.push({ start, end, text: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction warnPropertyAccesses(path: string, source: string, context: SchematicContext): void {\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === OLD_NAME) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(`${path}:${line + 1} - \"${OLD_NAME}\" has been renamed to \"${NEW_NAME}\" on ${COMPONENT_TAG}. Update this reference manually.`);\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) collectRenames(node, edits);\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const output of element.outputs) {\n if (output.name === OLD_NAME) {\n edits.push({ start: output.keySpan!.start.offset, end: output.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
2583
2583
  "displayName": "Schema",
2584
2584
  "properties": [
2585
2585
  {
@@ -2591,7 +2591,7 @@
2591
2591
  "indexKey": "",
2592
2592
  "optional": true,
2593
2593
  "description": "",
2594
- "line": 8,
2594
+ "line": 12,
2595
2595
  "rawdescription": "\n"
2596
2596
  },
2597
2597
  {
@@ -2603,7 +2603,7 @@
2603
2603
  "indexKey": "",
2604
2604
  "optional": true,
2605
2605
  "description": "",
2606
- "line": 7,
2606
+ "line": 11,
2607
2607
  "rawdescription": "\n"
2608
2608
  }
2609
2609
  ],
@@ -2715,12 +2715,12 @@
2715
2715
  },
2716
2716
  {
2717
2717
  "name": "Schema",
2718
- "id": "interface-Schema-21147930d3fbc38fbb3052a2ed9e7aa2b7505e6ed8c88c28796ce7101bd2ad914726eb230dda5826647036190edec6dae7e7e1d172387cd3803aa00bcdf790be-14",
2719
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
2718
+ "id": "interface-Schema-a806c1769fb526271565003a6a3ef9ab4c67e421d93ee0cb54e1f6de223807afc1f16ad294656ef614a77a91a38cc914ce41ac97ed3a8a4195a1e74a729c0c08-14",
2719
+ "file": "packages/core/schematics/migrate-eui-popover/index.ts",
2720
2720
  "deprecated": false,
2721
2721
  "deprecationMessage": "",
2722
2722
  "type": "interface",
2723
- "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst OLD_NAME = 'iconSet';\nconst NEW_NAME = 'iconSvgName';\nconst COMPONENT_TAG = 'eui-icon-toggle';\n\nexport function migrateEuiIconToggle(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let templateCount = 0;\n let tsCount = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(COMPONENT_TAG)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original);\n } else {\n result = migrateInlineTemplates(original);\n result = renameTsPropertyAccesses(result);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n if (path.endsWith('.html')) templateCount++;\n else tsCount++;\n }\n });\n\n context.logger.info(`Renamed '${OLD_NAME}' '${NEW_NAME}' on ${COMPONENT_TAG} in ${templateCount + tsCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(COMPONENT_TAG)) {\n ts.forEachChild(node, visit);\n return;\n }\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) {\n changes.push({ start, end, text: migrated });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction renameTsPropertyAccesses(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === OLD_NAME) {\n edits.push({ start: node.name.getStart(sourceFile), end: node.name.getEnd(), replacement: NEW_NAME });\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return applyEdits(source, edits);\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) {\n collectRenames(node, edits);\n }\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const attr of element.attributes) {\n if (attr.name === OLD_NAME) {\n edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n for (const input of element.inputs) {\n if (input.name === OLD_NAME) {\n edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
2723
+ "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst REMOVED_INPUTS = new Set(['type']);\n\nexport function migrateEuiPopover(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes('eui-popover')) return;\n\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would remove 'type' input in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n\n // Warn about TS usages inline\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts') && (original.includes('eui-popover') || original.includes('euiPopover') || original.includes('EuiPopover'))) {\n if (original.includes('type')) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === 'type') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${path}:${line + 1} - Manual action needed: \"type\" is no longer a valid input on eui-popover. Remove this assignment.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n }\n });\n\n context.logger.info(`Removed deprecated eui-popover 'type' input from ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const removals: { start: number; end: number }[] = [];\n\n visitNodes(parsed.nodes, removals);\n\n let result = source;\n for (const { start, end } of removals.sort((a, b) => b.start - a.start)) {\n // Extend start backwards to consume leading whitespace\n let adjustedStart = start;\n while (adjustedStart > 0 && (result[adjustedStart - 1] === ' ' || result[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n result = result.slice(0, adjustedStart) + result.slice(end);\n }\n\n return result;\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const templateRegex = /template\\s*:\\s*`([^`]*)`/gs;\n return source.replace(templateRegex, (match, templateContent: string) => {\n if (!templateContent.includes('eui-popover')) return match;\n const migrated = migrateTemplate(templateContent);\n if (migrated === templateContent) return match;\n return match.replace(templateContent, migrated);\n });\n}\n\nfunction visitNodes(nodes: TmplAstNode[], removals: { start: number; end: number }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === 'eui-popover') {\n collectRemovals(node, removals);\n }\n visitNodes(node.children, removals);\n }\n }\n}\n\nfunction collectRemovals(element: TmplAstElement, removals: { start: number; end: number }[]): void {\n for (const attr of element.attributes) {\n if (REMOVED_INPUTS.has(attr.name)) {\n removals.push(getAttributeSpan(attr));\n }\n }\n for (const input of element.inputs) {\n if (REMOVED_INPUTS.has(input.name)) {\n removals.push(getAttributeSpan(input));\n }\n }\n}\n\nfunction getAttributeSpan(attr: TmplAstTextAttribute | TmplAstBoundAttribute): { start: number; end: number } {\n return { start: attr.sourceSpan.start.offset, end: attr.sourceSpan.end.offset };\n}\n",
2724
2724
  "displayName": "Schema",
2725
2725
  "properties": [
2726
2726
  {
@@ -2762,12 +2762,12 @@
2762
2762
  },
2763
2763
  {
2764
2764
  "name": "Schema",
2765
- "id": "interface-Schema-a806c1769fb526271565003a6a3ef9ab4c67e421d93ee0cb54e1f6de223807afc1f16ad294656ef614a77a91a38cc914ce41ac97ed3a8a4195a1e74a729c0c08-15",
2766
- "file": "packages/core/schematics/migrate-eui-popover/index.ts",
2765
+ "id": "interface-Schema-90e62c16ce9ada881e8d434336bb633dae9745236106ddf60964afbd11de6aa579255a13d6036b384281860eb6ed2ee329194b519c51fdaf20f79bc511d0f64f-15",
2766
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
2767
2767
  "deprecated": false,
2768
2768
  "deprecationMessage": "",
2769
2769
  "type": "interface",
2770
- "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst REMOVED_INPUTS = new Set(['type']);\n\nexport function migrateEuiPopover(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes('eui-popover')) return;\n\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would remove 'type' input in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n\n // Warn about TS usages inline\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts') && (original.includes('eui-popover') || original.includes('euiPopover') || original.includes('EuiPopover'))) {\n if (original.includes('type')) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === 'type') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${path}:${line + 1} - Manual action needed: \"type\" is no longer a valid input on eui-popover. Remove this assignment.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n }\n });\n\n context.logger.info(`Removed deprecated eui-popover 'type' input from ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const removals: { start: number; end: number }[] = [];\n\n visitNodes(parsed.nodes, removals);\n\n let result = source;\n for (const { start, end } of removals.sort((a, b) => b.start - a.start)) {\n // Extend start backwards to consume leading whitespace\n let adjustedStart = start;\n while (adjustedStart > 0 && (result[adjustedStart - 1] === ' ' || result[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n result = result.slice(0, adjustedStart) + result.slice(end);\n }\n\n return result;\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const templateRegex = /template\\s*:\\s*`([^`]*)`/gs;\n return source.replace(templateRegex, (match, templateContent: string) => {\n if (!templateContent.includes('eui-popover')) return match;\n const migrated = migrateTemplate(templateContent);\n if (migrated === templateContent) return match;\n return match.replace(templateContent, migrated);\n });\n}\n\nfunction visitNodes(nodes: TmplAstNode[], removals: { start: number; end: number }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === 'eui-popover') {\n collectRemovals(node, removals);\n }\n visitNodes(node.children, removals);\n }\n }\n}\n\nfunction collectRemovals(element: TmplAstElement, removals: { start: number; end: number }[]): void {\n for (const attr of element.attributes) {\n if (REMOVED_INPUTS.has(attr.name)) {\n removals.push(getAttributeSpan(attr));\n }\n }\n for (const input of element.inputs) {\n if (REMOVED_INPUTS.has(input.name)) {\n removals.push(getAttributeSpan(input));\n }\n }\n}\n\nfunction getAttributeSpan(attr: TmplAstTextAttribute | TmplAstBoundAttribute): { start: number; end: number } {\n return { start: attr.sourceSpan.start.offset, end: attr.sourceSpan.end.offset };\n}\n",
2770
+ "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst INPUT_RENAMES = new Map([\n ['iconLabelClass', 'icon'],\n ['iconLabelStyleClass', 'fillColor'],\n]);\n\nexport function migrateEuiProgressCircle(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n const oldNames = [...INPUT_RENAMES.keys()];\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n if (original.includes('eui-progress-circle')) {\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename deprecated inputs in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n }\n\n // Warn about TS property access usages (merged from warnTsUsages)\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts')) {\n if (oldNames.some((name) => original.includes(name))) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && INPUT_RENAMES.has(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const newName = INPUT_RENAMES.get(node.name.text);\n context.logger.warn(\n `${path}:${line + 1} - \"${node.name.text}\" has been renamed to \"${newName}\" on eui-progress-circle. Update this reference manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n }\n });\n\n context.logger.info(`Renamed deprecated eui-progress-circle inputs in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes('eui-progress-circle')) {\n ts.forEachChild(node, visit);\n return;\n }\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) {\n changes.push({ start, end, text: migrated });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === 'eui-progress-circle') {\n collectRenames(node, edits);\n }\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const attr of element.attributes) {\n const newName = INPUT_RENAMES.get(attr.name);\n if (newName) {\n edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n }\n for (const input of element.inputs) {\n const newName = INPUT_RENAMES.get(input.name);\n if (newName) {\n edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
2771
2771
  "displayName": "Schema",
2772
2772
  "properties": [
2773
2773
  {
@@ -2809,12 +2809,12 @@
2809
2809
  },
2810
2810
  {
2811
2811
  "name": "Schema",
2812
- "id": "interface-Schema-90e62c16ce9ada881e8d434336bb633dae9745236106ddf60964afbd11de6aa579255a13d6036b384281860eb6ed2ee329194b519c51fdaf20f79bc511d0f64f-16",
2813
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
2812
+ "id": "interface-Schema-91c9f900bf3ebb82488fb65644938ef486ceaa447cff8bfd9d710df9595d82acb267b26f3c252173bc684353f362473120226426ed7ee5d98b33e30011dd9383-16",
2813
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
2814
2814
  "deprecated": false,
2815
2815
  "deprecationMessage": "",
2816
2816
  "type": "interface",
2817
- "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst INPUT_RENAMES = new Map([\n ['iconLabelClass', 'icon'],\n ['iconLabelStyleClass', 'fillColor'],\n]);\n\nexport function migrateEuiProgressCircle(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n const oldNames = [...INPUT_RENAMES.keys()];\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n if (original.includes('eui-progress-circle')) {\n const result = path.endsWith('.html')\n ? migrateTemplate(original)\n : migrateInlineTemplates(original);\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename deprecated inputs in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n }\n\n // Warn about TS property access usages (merged from warnTsUsages)\n if (path.endsWith('.ts') && !path.endsWith('.spec.ts')) {\n if (oldNames.some((name) => original.includes(name))) {\n const sourceFile = ts.createSourceFile(path, original, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && INPUT_RENAMES.has(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const newName = INPUT_RENAMES.get(node.name.text);\n context.logger.warn(\n `${path}:${line + 1} - \"${node.name.text}\" has been renamed to \"${newName}\" on eui-progress-circle. Update this reference manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n }\n }\n });\n\n context.logger.info(`Renamed deprecated eui-progress-circle inputs in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes('eui-progress-circle')) {\n ts.forEachChild(node, visit);\n return;\n }\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) {\n changes.push({ start, end, text: migrated });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === 'eui-progress-circle') {\n collectRenames(node, edits);\n }\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const attr of element.attributes) {\n const newName = INPUT_RENAMES.get(attr.name);\n if (newName) {\n edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n }\n for (const input of element.inputs) {\n const newName = INPUT_RENAMES.get(input.name);\n if (newName) {\n edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
2817
+ "sourceCode": "import { BindingPipe, parseTemplate, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstTemplate, TmplAstTextAttribute, AST, ASTWithSource, Interpolation } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Edit { start: number; end: number; replacement: string; }\n\n// --- Table-level input renames (on elements with euiTable attribute) ---\nconst TABLE_INPUT_RENAMES = new Map([\n ['rows', 'data'],\n ['loading', 'isLoading'],\n ['asyncTable', 'isAsync'],\n ['euiTableResponsive', 'isTableResponsive'],\n ['euiTableFixedLayout', 'isTableFixedLayout'],\n ['euiTableCompact', 'isTableCompact'],\n ['hasStickyColumns', 'hasStickyCols'],\n]);\n\n// --- Child element input renames (scoped to euiTable context) ---\nconst TH_TD_INPUT_RENAMES = new Map([\n ['isStickyColumn', 'isStickyCol'],\n ['sortable', 'isSortable'],\n]);\n\nconst TR_INPUT_RENAMES = new Map([\n ['isSelectableHeader', 'isHeaderSelectable'],\n ['isSelectable', 'isDataSelectable'],\n]);\n\n// --- Removed inputs ---\nconst REMOVED_INPUTS = new Set(['euiTableBordered', 'isHoverable', 'defaultMultiOrder', 'paginable']);\n\n// --- Output renames/removals ---\nconst OUTPUT_RENAMES = new Map([['selectedRows', 'rowsSelect']]);\nconst REMOVED_OUTPUTS = new Set(['multiSortChange']);\n\n// --- Pipe rename ---\nconst OLD_PIPE = 'euiTableHighlightFilter';\nconst NEW_PIPE = 'euiTableHighlight';\n\n// --- TS property renames ---\nconst TS_PROPERTY_RENAMES = new Map([['filteredRows', 'getFilteredData']]);\n\nconst PAGINATOR_IMPORT_PATH = '@eui/components/eui-paginator';\nconst PAGINATOR_COMPONENT = 'EuiPaginatorComponent';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateEuiTable(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n const paginatorHtmlFiles = new Set<string>();\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes('euiTable') && !original.includes(OLD_PIPE) && !original.includes('filteredRows') && !original.includes('setSort')) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n const { output, hasPaginator } = migrateTemplateWithPaginator(original, path, context);\n result = output;\n if (hasPaginator) paginatorHtmlFiles.add(path);\n } else {\n const { output, hasPaginator } = migrateTypeScript(original, path, context);\n result = output;\n if (hasPaginator) {\n result = addPaginatorImport(result, path);\n }\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-table breaking changes in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n });\n\n // Handle paginator imports for external templates\n if (paginatorHtmlFiles.size > 0) {\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!source.includes('templateUrl')) return;\n\n for (const htmlFile of paginatorHtmlFiles) {\n const htmlFileName = htmlFile.split('/').pop()!;\n if (source.includes(htmlFileName)) {\n const updated = addPaginatorImport(source, path);\n if (updated !== source) {\n if (options.dryRun) {\n logDryRun(context, `Would add paginator import in ${path}`);\n } else {\n tree.overwrite(path, updated);\n }\n count++;\n }\n break;\n }\n }\n });\n }\n\n context.logger.info(`Migrated eui-table in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplateWithPaginator(source: string, filePath: string, context: SchematicContext): { output: string; hasPaginator: boolean } {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n let hasPaginator = false;\n\n const paginatorResult = visitNodesForTable(parsed.nodes, source, edits, false, filePath, context);\n if (paginatorResult) hasPaginator = true;\n\n collectPipeRenames(parsed.nodes, source, edits);\n\n return { output: applyEdits(source, edits), hasPaginator };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n return migrateTemplateWithPaginator(source, filePath, context).output;\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): { output: string; hasPaginator: boolean } {\n let result = source;\n let hasPaginator = false;\n\n // Migrate inline templates\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = result.slice(start, end);\n if (!rawTemplate.includes('euiTable') && !rawTemplate.includes(OLD_PIPE)) {\n ts.forEachChild(node, visit); return;\n}\n const { output: migrated, hasPaginator: pag } = migrateTemplateWithPaginator(rawTemplate, filePath, context);\n if (pag) hasPaginator = true;\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n result = applyEdits(result, changes);\n\n // Rename TS property accesses\n result = renameTsProperties(result);\n\n // Warn about setSort\n warnSetSort(result, filePath, context);\n\n return { output: result, hasPaginator };\n}\n\nfunction renameTsProperties(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && TS_PROPERTY_RENAMES.has(node.name.text)) {\n edits.push({ start: node.name.getStart(sourceFile), end: node.name.getEnd(), replacement: TS_PROPERTY_RENAMES.get(node.name.text)! });\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, edits);\n}\n\nfunction warnSetSort(source: string, filePath: string, context: SchematicContext): void {\n if (!source.includes('setSort')) return;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.name) && node.expression.name.text === 'setSort') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"setSort\" signature changed from setSort(sort: string, order: \"asc\" | \"desc\") to setSort(Sort[]). Update manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\n// --- Template AST visitors ---\n\nfunction visitNodesForTable(\n nodes: TmplAstNode[], source: string, edits: Edit[], insideEuiTable: boolean, filePath: string, context: SchematicContext,\n): boolean {\n let hasPaginator = false;\n\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n const isEuiTable = hasEuiTableAttribute(node);\n\n if (isEuiTable) {\n collectTableInputRenames(node, edits);\n collectInputRemovals(node, source, edits, filePath, context);\n collectOutputChanges(node, source, edits, filePath, context);\n if (collectPaginatorMigration(node, source, edits)) hasPaginator = true;\n }\n\n if (isEuiTable || insideEuiTable) {\n collectChildElementRenames(node, edits);\n collectChildInputRemovals(node, source, edits, filePath, context);\n collectEmptyMessageRename(node, edits);\n }\n\n const childResult = visitNodesForTable(node.children, source, edits, isEuiTable || insideEuiTable, filePath, context);\n if (childResult) hasPaginator = true;\n }\n\n if (node instanceof TmplAstTemplate) {\n if (insideEuiTable) {\n collectTemplateEmptyMessageRename(node, edits);\n }\n const childResult = visitNodesForTable(node.children, source, edits, insideEuiTable, filePath, context);\n if (childResult) hasPaginator = true;\n }\n }\n\n return hasPaginator;\n}\n\nfunction hasEuiTableAttribute(element: TmplAstElement): boolean {\n return element.attributes.some((a) => a.name === 'euiTable') ||\n element.inputs.some((i) => i.name === 'euiTable');\n}\n\nfunction collectTableInputRenames(element: TmplAstElement, edits: Edit[]): void {\n for (const attr of element.attributes) {\n const newName = TABLE_INPUT_RENAMES.get(attr.name);\n if (newName) edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n for (const input of element.inputs) {\n const newName = TABLE_INPUT_RENAMES.get(input.name);\n if (newName) edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n}\n\nfunction collectChildElementRenames(element: TmplAstElement, edits: Edit[]): void {\n const renames = (element.name === 'th' || element.name === 'td') ? TH_TD_INPUT_RENAMES\n : element.name === 'tr' ? TR_INPUT_RENAMES : null;\n if (!renames) return;\n\n for (const attr of element.attributes) {\n const newName = renames.get(attr.name);\n if (newName) edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n for (const input of element.inputs) {\n const newName = renames.get(input.name);\n if (newName) edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n}\n\nfunction collectChildInputRemovals(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n const childRemovedInputs = new Set(['defaultMultiOrder']);\n\n for (const attr of element.attributes) {\n if (childRemovedInputs.has(attr.name)) {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n logRemovalWarning(attr.name, filePath, element, context);\n }\n }\n for (const input of element.inputs) {\n if (childRemovedInputs.has(input.name)) {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n logRemovalWarning(input.name, filePath, element, context);\n }\n }\n}\n\nfunction collectInputRemovals(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const attr of element.attributes) {\n if (REMOVED_INPUTS.has(attr.name) && attr.name !== 'paginable') {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n logRemovalWarning(attr.name, filePath, element, context);\n }\n }\n for (const input of element.inputs) {\n if (REMOVED_INPUTS.has(input.name) && input.name !== 'paginable') {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n logRemovalWarning(input.name, filePath, element, context);\n }\n }\n}\n\nfunction collectOutputChanges(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const output of element.outputs) {\n const newName = OUTPUT_RENAMES.get(output.name);\n if (newName) {\n edits.push({ start: output.keySpan!.start.offset, end: output.keySpan!.end.offset, replacement: newName });\n }\n if (REMOVED_OUTPUTS.has(output.name)) {\n removeAttribute(output.sourceSpan.start.offset, output.sourceSpan.end.offset, source, edits);\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(${output.name})\" removed. Multi-sort is now supported by (sortChange) output.`,\n );\n }\n }\n}\n\nfunction collectPaginatorMigration(element: TmplAstElement, source: string, edits: Edit[]): boolean {\n let found = false;\n\n for (const attr of element.attributes) {\n if (attr.name === 'paginable') {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n found = true;\n }\n }\n for (const input of element.inputs) {\n if (input.name === 'paginable') {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n found = true;\n }\n }\n\n if (found) {\n // Add [paginator]=\"paginator\" before closing > of opening tag\n const insertPos = element.startSourceSpan.end.offset - 1;\n edits.push({ start: insertPos, end: insertPos, replacement: ' [paginator]=\"paginator\"' });\n\n // Add eui-paginator after </table>\n if (element.endSourceSpan) {\n const afterTable = element.endSourceSpan.end.offset;\n edits.push({\n start: afterTable,\n end: afterTable,\n replacement: '\\n<!-- TODO: Configure paginator and implement onPageChange handler -->\\n<eui-paginator #paginator [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\" />',\n });\n }\n }\n\n return found;\n}\n\nfunction collectEmptyMessageRename(element: TmplAstElement, edits: Edit[]): void {\n // Handle direct attribute on elements (unlikely but handle)\n for (const attr of element.attributes) {\n if (attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n}\n\nfunction collectTemplateEmptyMessageRename(template: TmplAstTemplate, edits: Edit[]): void {\n for (const attr of template.templateAttrs) {\n if (attr instanceof TmplAstTextAttribute && attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n for (const attr of template.attributes) {\n if (attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n}\n\n// --- Pipe rename via AST ---\n\nfunction collectPipeRenames(nodes: TmplAstNode[], source: string, edits: Edit[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n for (const input of node.inputs) {\n visitExpressionForPipes(input.value, edits);\n }\n for (const output of node.outputs) {\n if (output.handler) visitExpressionForPipes(output.handler, edits);\n }\n collectPipeRenames(node.children, source, edits);\n }\n if (node instanceof TmplAstTemplate) {\n for (const input of node.inputs) {\n visitExpressionForPipes(input.value, edits);\n }\n collectPipeRenames(node.children, source, edits);\n }\n if (node instanceof TmplAstBoundText) {\n visitExpressionForPipes(node.value, edits);\n }\n }\n}\n\nfunction visitExpressionForPipes(expr: AST, edits: Edit[]): void {\n if (expr instanceof ASTWithSource && expr.ast) {\n visitAstForPipes(expr.ast, edits);\n } else {\n visitAstForPipes(expr, edits);\n }\n}\n\nfunction visitAstForPipes(ast: AST, edits: Edit[]): void {\n if (ast instanceof BindingPipe) {\n if (ast.name === OLD_PIPE && ast.nameSpan) {\n edits.push({ start: ast.nameSpan.start, end: ast.nameSpan.end, replacement: NEW_PIPE });\n }\n visitAstForPipes(ast.exp, edits);\n for (const arg of ast.args) {\n visitAstForPipes(arg, edits);\n }\n return;\n }\n\n if (ast instanceof Interpolation) {\n for (const expr of ast.expressions) {\n visitAstForPipes(expr, edits);\n }\n return;\n }\n\n // Recursively visit all properties that could contain AST nodes\n for (const key of Object.keys(ast)) {\n // eslint-disable-next-line\n const val = (ast as any)[key];\n if (val instanceof AST) {\n visitAstForPipes(val, edits);\n } else if (Array.isArray(val)) {\n for (const item of val) {\n if (item instanceof AST) visitAstForPipes(item, edits);\n }\n }\n }\n}\n\n// --- Import handling for paginator ---\n\nfunction addPaginatorImport(source: string, filePath: string): string {\n if (source.includes(PAGINATOR_COMPONENT)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Add import statement after last import\n let lastImportEnd = 0;\n for (const stmt of sourceFile.statements) {\n if (ts.isImportDeclaration(stmt)) {\n lastImportEnd = stmt.getEnd();\n }\n }\n\n if (lastImportEnd > 0) {\n edits.push({\n start: lastImportEnd,\n end: lastImportEnd,\n replacement: `\\nimport { ${PAGINATOR_COMPONENT} } from '${PAGINATOR_IMPORT_PATH}';`,\n });\n }\n\n // Add to component imports array\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'imports' && isComponentMetadataProperty(node)) {\n if (ts.isArrayLiteralExpression(node.initializer)) {\n const arr = node.initializer;\n const elements = arr.elements;\n if (elements.length > 0) {\n const lastElement = elements[elements.length - 1];\n edits.push({\n start: lastElement.getEnd(),\n end: lastElement.getEnd(),\n replacement: `, ${PAGINATOR_COMPONENT}`,\n });\n } else {\n const insertPos = arr.getStart(sourceFile) + 1;\n edits.push({ start: insertPos, end: insertPos, replacement: PAGINATOR_COMPONENT });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return applyEdits(source, edits);\n}\n\n// --- Helpers ---\n\nfunction removeAttribute(start: number, end: number, source: string, edits: Edit[]): void {\n let adjustedStart = start;\n while (adjustedStart > 0 && (source[adjustedStart - 1] === ' ' || source[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n edits.push({ start: adjustedStart, end, replacement: '' });\n}\n\nfunction logRemovalWarning(name: string, filePath: string, element: TmplAstElement, context: SchematicContext): void {\n const { line } = element.startSourceSpan.start;\n if (name === 'defaultMultiOrder') {\n context.logger.warn(`${filePath}:${line + 1} - \"[${name}]\" removed. Use setSort(Sort[]) to initialize sorting.`);\n } else {\n context.logger.warn(`${filePath}:${line + 1} - \"[${name}]\" removed to align to Design System.`);\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n unique.set(key, edit);\n }\n let result = source;\n for (const edit of [...unique.values()].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2818
2818
  "displayName": "Schema",
2819
2819
  "properties": [
2820
2820
  {
@@ -2826,7 +2826,7 @@
2826
2826
  "indexKey": "",
2827
2827
  "optional": true,
2828
2828
  "description": "",
2829
- "line": 8,
2829
+ "line": 49,
2830
2830
  "rawdescription": "\n"
2831
2831
  },
2832
2832
  {
@@ -2838,7 +2838,7 @@
2838
2838
  "indexKey": "",
2839
2839
  "optional": true,
2840
2840
  "description": "",
2841
- "line": 7,
2841
+ "line": 48,
2842
2842
  "rawdescription": "\n"
2843
2843
  }
2844
2844
  ],
@@ -2856,12 +2856,12 @@
2856
2856
  },
2857
2857
  {
2858
2858
  "name": "Schema",
2859
- "id": "interface-Schema-91c9f900bf3ebb82488fb65644938ef486ceaa447cff8bfd9d710df9595d82acb267b26f3c252173bc684353f362473120226426ed7ee5d98b33e30011dd9383-17",
2860
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
2859
+ "id": "interface-Schema-760dec88d3f709d5b38226e55f7cbfb1e5fabcea6c004fd46e611be1dd563b8b247e9e6c77667e5582fe7b443374ba2c4facd2b2db2985edb46c9a4a37a8a876-17",
2860
+ "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
2861
2861
  "deprecated": false,
2862
2862
  "deprecationMessage": "",
2863
2863
  "type": "interface",
2864
- "sourceCode": "import { BindingPipe, parseTemplate, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstTemplate, TmplAstTextAttribute, AST, ASTWithSource, Interpolation } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Edit { start: number; end: number; replacement: string; }\n\n// --- Table-level input renames (on elements with euiTable attribute) ---\nconst TABLE_INPUT_RENAMES = new Map([\n ['rows', 'data'],\n ['loading', 'isLoading'],\n ['asyncTable', 'isAsync'],\n ['euiTableResponsive', 'isTableResponsive'],\n ['euiTableFixedLayout', 'isTableFixedLayout'],\n ['euiTableCompact', 'isTableCompact'],\n ['hasStickyColumns', 'hasStickyCols'],\n]);\n\n// --- Child element input renames (scoped to euiTable context) ---\nconst TH_TD_INPUT_RENAMES = new Map([\n ['isStickyColumn', 'isStickyCol'],\n ['sortable', 'isSortable'],\n]);\n\nconst TR_INPUT_RENAMES = new Map([\n ['isSelectableHeader', 'isHeaderSelectable'],\n ['isSelectable', 'isDataSelectable'],\n]);\n\n// --- Removed inputs ---\nconst REMOVED_INPUTS = new Set(['euiTableBordered', 'isHoverable', 'defaultMultiOrder', 'paginable']);\n\n// --- Output renames/removals ---\nconst OUTPUT_RENAMES = new Map([['selectedRows', 'rowsSelect']]);\nconst REMOVED_OUTPUTS = new Set(['multiSortChange']);\n\n// --- Pipe rename ---\nconst OLD_PIPE = 'euiTableHighlightFilter';\nconst NEW_PIPE = 'euiTableHighlight';\n\n// --- TS property renames ---\nconst TS_PROPERTY_RENAMES = new Map([['filteredRows', 'getFilteredData']]);\n\nconst PAGINATOR_IMPORT_PATH = '@eui/components/eui-paginator';\nconst PAGINATOR_COMPONENT = 'EuiPaginatorComponent';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateEuiTable(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let count = 0;\n const paginatorHtmlFiles = new Set<string>();\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes('euiTable') && !original.includes(OLD_PIPE) && !original.includes('filteredRows') && !original.includes('setSort')) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n const { output, hasPaginator } = migrateTemplateWithPaginator(original, path, context);\n result = output;\n if (hasPaginator) paginatorHtmlFiles.add(path);\n } else {\n const { output, hasPaginator } = migrateTypeScript(original, path, context);\n result = output;\n if (hasPaginator) {\n result = addPaginatorImport(result, path);\n }\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-table breaking changes in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n count++;\n }\n });\n\n // Handle paginator imports for external templates\n if (paginatorHtmlFiles.size > 0) {\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!source.includes('templateUrl')) return;\n\n for (const htmlFile of paginatorHtmlFiles) {\n const htmlFileName = htmlFile.split('/').pop()!;\n if (source.includes(htmlFileName)) {\n const updated = addPaginatorImport(source, path);\n if (updated !== source) {\n if (options.dryRun) {\n logDryRun(context, `Would add paginator import in ${path}`);\n } else {\n tree.overwrite(path, updated);\n }\n count++;\n }\n break;\n }\n }\n });\n }\n\n context.logger.info(`Migrated eui-table in ${count} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplateWithPaginator(source: string, filePath: string, context: SchematicContext): { output: string; hasPaginator: boolean } {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n let hasPaginator = false;\n\n const paginatorResult = visitNodesForTable(parsed.nodes, source, edits, false, filePath, context);\n if (paginatorResult) hasPaginator = true;\n\n collectPipeRenames(parsed.nodes, source, edits);\n\n return { output: applyEdits(source, edits), hasPaginator };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n return migrateTemplateWithPaginator(source, filePath, context).output;\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): { output: string; hasPaginator: boolean } {\n let result = source;\n let hasPaginator = false;\n\n // Migrate inline templates\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = result.slice(start, end);\n if (!rawTemplate.includes('euiTable') && !rawTemplate.includes(OLD_PIPE)) {\n ts.forEachChild(node, visit); return;\n}\n const { output: migrated, hasPaginator: pag } = migrateTemplateWithPaginator(rawTemplate, filePath, context);\n if (pag) hasPaginator = true;\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n result = applyEdits(result, changes);\n\n // Rename TS property accesses\n result = renameTsProperties(result);\n\n // Warn about setSort\n warnSetSort(result, filePath, context);\n\n return { output: result, hasPaginator };\n}\n\nfunction renameTsProperties(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && TS_PROPERTY_RENAMES.has(node.name.text)) {\n edits.push({ start: node.name.getStart(sourceFile), end: node.name.getEnd(), replacement: TS_PROPERTY_RENAMES.get(node.name.text)! });\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, edits);\n}\n\nfunction warnSetSort(source: string, filePath: string, context: SchematicContext): void {\n if (!source.includes('setSort')) return;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.name) && node.expression.name.text === 'setSort') {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"setSort\" signature changed from setSort(sort: string, order: \"asc\" | \"desc\") to setSort(Sort[]). Update manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\n// --- Template AST visitors ---\n\nfunction visitNodesForTable(\n nodes: TmplAstNode[], source: string, edits: Edit[], insideEuiTable: boolean, filePath: string, context: SchematicContext,\n): boolean {\n let hasPaginator = false;\n\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n const isEuiTable = hasEuiTableAttribute(node);\n\n if (isEuiTable) {\n collectTableInputRenames(node, edits);\n collectInputRemovals(node, source, edits, filePath, context);\n collectOutputChanges(node, source, edits, filePath, context);\n if (collectPaginatorMigration(node, source, edits)) hasPaginator = true;\n }\n\n if (isEuiTable || insideEuiTable) {\n collectChildElementRenames(node, edits);\n collectChildInputRemovals(node, source, edits, filePath, context);\n collectEmptyMessageRename(node, edits);\n }\n\n const childResult = visitNodesForTable(node.children, source, edits, isEuiTable || insideEuiTable, filePath, context);\n if (childResult) hasPaginator = true;\n }\n\n if (node instanceof TmplAstTemplate) {\n if (insideEuiTable) {\n collectTemplateEmptyMessageRename(node, edits);\n }\n const childResult = visitNodesForTable(node.children, source, edits, insideEuiTable, filePath, context);\n if (childResult) hasPaginator = true;\n }\n }\n\n return hasPaginator;\n}\n\nfunction hasEuiTableAttribute(element: TmplAstElement): boolean {\n return element.attributes.some((a) => a.name === 'euiTable') ||\n element.inputs.some((i) => i.name === 'euiTable');\n}\n\nfunction collectTableInputRenames(element: TmplAstElement, edits: Edit[]): void {\n for (const attr of element.attributes) {\n const newName = TABLE_INPUT_RENAMES.get(attr.name);\n if (newName) edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n for (const input of element.inputs) {\n const newName = TABLE_INPUT_RENAMES.get(input.name);\n if (newName) edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n}\n\nfunction collectChildElementRenames(element: TmplAstElement, edits: Edit[]): void {\n const renames = (element.name === 'th' || element.name === 'td') ? TH_TD_INPUT_RENAMES\n : element.name === 'tr' ? TR_INPUT_RENAMES : null;\n if (!renames) return;\n\n for (const attr of element.attributes) {\n const newName = renames.get(attr.name);\n if (newName) edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: newName });\n }\n for (const input of element.inputs) {\n const newName = renames.get(input.name);\n if (newName) edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: newName });\n }\n}\n\nfunction collectChildInputRemovals(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n const childRemovedInputs = new Set(['defaultMultiOrder']);\n\n for (const attr of element.attributes) {\n if (childRemovedInputs.has(attr.name)) {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n logRemovalWarning(attr.name, filePath, element, context);\n }\n }\n for (const input of element.inputs) {\n if (childRemovedInputs.has(input.name)) {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n logRemovalWarning(input.name, filePath, element, context);\n }\n }\n}\n\nfunction collectInputRemovals(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const attr of element.attributes) {\n if (REMOVED_INPUTS.has(attr.name) && attr.name !== 'paginable') {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n logRemovalWarning(attr.name, filePath, element, context);\n }\n }\n for (const input of element.inputs) {\n if (REMOVED_INPUTS.has(input.name) && input.name !== 'paginable') {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n logRemovalWarning(input.name, filePath, element, context);\n }\n }\n}\n\nfunction collectOutputChanges(element: TmplAstElement, source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const output of element.outputs) {\n const newName = OUTPUT_RENAMES.get(output.name);\n if (newName) {\n edits.push({ start: output.keySpan!.start.offset, end: output.keySpan!.end.offset, replacement: newName });\n }\n if (REMOVED_OUTPUTS.has(output.name)) {\n removeAttribute(output.sourceSpan.start.offset, output.sourceSpan.end.offset, source, edits);\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(${output.name})\" removed. Multi-sort is now supported by (sortChange) output.`,\n );\n }\n }\n}\n\nfunction collectPaginatorMigration(element: TmplAstElement, source: string, edits: Edit[]): boolean {\n let found = false;\n\n for (const attr of element.attributes) {\n if (attr.name === 'paginable') {\n removeAttribute(attr.sourceSpan.start.offset, attr.sourceSpan.end.offset, source, edits);\n found = true;\n }\n }\n for (const input of element.inputs) {\n if (input.name === 'paginable') {\n removeAttribute(input.sourceSpan.start.offset, input.sourceSpan.end.offset, source, edits);\n found = true;\n }\n }\n\n if (found) {\n // Add [paginator]=\"paginator\" before closing > of opening tag\n const insertPos = element.startSourceSpan.end.offset - 1;\n edits.push({ start: insertPos, end: insertPos, replacement: ' [paginator]=\"paginator\"' });\n\n // Add eui-paginator after </table>\n if (element.endSourceSpan) {\n const afterTable = element.endSourceSpan.end.offset;\n edits.push({\n start: afterTable,\n end: afterTable,\n replacement: '\\n<!-- TODO: Configure paginator and implement onPageChange handler -->\\n<eui-paginator #paginator [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\" />',\n });\n }\n }\n\n return found;\n}\n\nfunction collectEmptyMessageRename(element: TmplAstElement, edits: Edit[]): void {\n // Handle direct attribute on elements (unlikely but handle)\n for (const attr of element.attributes) {\n if (attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n}\n\nfunction collectTemplateEmptyMessageRename(template: TmplAstTemplate, edits: Edit[]): void {\n for (const attr of template.templateAttrs) {\n if (attr instanceof TmplAstTextAttribute && attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n for (const attr of template.attributes) {\n if (attr.name === 'euiTemplate' && attr.value === 'emptyMessage' && attr.valueSpan) {\n edits.push({ start: attr.valueSpan.start.offset, end: attr.valueSpan.end.offset, replacement: 'footer' });\n }\n }\n}\n\n// --- Pipe rename via AST ---\n\nfunction collectPipeRenames(nodes: TmplAstNode[], source: string, edits: Edit[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n for (const input of node.inputs) {\n visitExpressionForPipes(input.value, edits);\n }\n for (const output of node.outputs) {\n if (output.handler) visitExpressionForPipes(output.handler, edits);\n }\n collectPipeRenames(node.children, source, edits);\n }\n if (node instanceof TmplAstTemplate) {\n for (const input of node.inputs) {\n visitExpressionForPipes(input.value, edits);\n }\n collectPipeRenames(node.children, source, edits);\n }\n if (node instanceof TmplAstBoundText) {\n visitExpressionForPipes(node.value, edits);\n }\n }\n}\n\nfunction visitExpressionForPipes(expr: AST, edits: Edit[]): void {\n if (expr instanceof ASTWithSource && expr.ast) {\n visitAstForPipes(expr.ast, edits);\n } else {\n visitAstForPipes(expr, edits);\n }\n}\n\nfunction visitAstForPipes(ast: AST, edits: Edit[]): void {\n if (ast instanceof BindingPipe) {\n if (ast.name === OLD_PIPE && ast.nameSpan) {\n edits.push({ start: ast.nameSpan.start, end: ast.nameSpan.end, replacement: NEW_PIPE });\n }\n visitAstForPipes(ast.exp, edits);\n for (const arg of ast.args) {\n visitAstForPipes(arg, edits);\n }\n return;\n }\n\n if (ast instanceof Interpolation) {\n for (const expr of ast.expressions) {\n visitAstForPipes(expr, edits);\n }\n return;\n }\n\n // Recursively visit all properties that could contain AST nodes\n for (const key of Object.keys(ast)) {\n // eslint-disable-next-line\n const val = (ast as any)[key];\n if (val instanceof AST) {\n visitAstForPipes(val, edits);\n } else if (Array.isArray(val)) {\n for (const item of val) {\n if (item instanceof AST) visitAstForPipes(item, edits);\n }\n }\n }\n}\n\n// --- Import handling for paginator ---\n\nfunction addPaginatorImport(source: string, filePath: string): string {\n if (source.includes(PAGINATOR_COMPONENT)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Add import statement after last import\n let lastImportEnd = 0;\n for (const stmt of sourceFile.statements) {\n if (ts.isImportDeclaration(stmt)) {\n lastImportEnd = stmt.getEnd();\n }\n }\n\n if (lastImportEnd > 0) {\n edits.push({\n start: lastImportEnd,\n end: lastImportEnd,\n replacement: `\\nimport { ${PAGINATOR_COMPONENT} } from '${PAGINATOR_IMPORT_PATH}';`,\n });\n }\n\n // Add to component imports array\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'imports' && isComponentMetadataProperty(node)) {\n if (ts.isArrayLiteralExpression(node.initializer)) {\n const arr = node.initializer;\n const elements = arr.elements;\n if (elements.length > 0) {\n const lastElement = elements[elements.length - 1];\n edits.push({\n start: lastElement.getEnd(),\n end: lastElement.getEnd(),\n replacement: `, ${PAGINATOR_COMPONENT}`,\n });\n } else {\n const insertPos = arr.getStart(sourceFile) + 1;\n edits.push({ start: insertPos, end: insertPos, replacement: PAGINATOR_COMPONENT });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return applyEdits(source, edits);\n}\n\n// --- Helpers ---\n\nfunction removeAttribute(start: number, end: number, source: string, edits: Edit[]): void {\n let adjustedStart = start;\n while (adjustedStart > 0 && (source[adjustedStart - 1] === ' ' || source[adjustedStart - 1] === '\\t')) {\n adjustedStart--;\n }\n edits.push({ start: adjustedStart, end, replacement: '' });\n}\n\nfunction logRemovalWarning(name: string, filePath: string, element: TmplAstElement, context: SchematicContext): void {\n const { line } = element.startSourceSpan.start;\n if (name === 'defaultMultiOrder') {\n context.logger.warn(`${filePath}:${line + 1} - \"[${name}]\" removed. Use setSort(Sort[]) to initialize sorting.`);\n } else {\n context.logger.warn(`${filePath}:${line + 1} - \"[${name}]\" removed to align to Design System.`);\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n unique.set(key, edit);\n }\n let result = source;\n for (const edit of [...unique.values()].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2864
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface TextChange {\n start: number;\n end: number;\n text: string;\n}\n\ninterface MigrationResult {\n content: string;\n migrated: number;\n skipped: number;\n}\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst OLD_LABEL = 'eui-tab-label';\nconst OLD_SUB_LABEL = 'euiTabSubLabel';\nconst OLD_CONTENT = 'eui-tab-content';\nconst NEW_HEADER = 'eui-tab-header';\nconst NEW_HEADER_LABEL = 'eui-tab-header-label';\nconst NEW_HEADER_SUB_LABEL = 'eui-tab-header-sub-label';\nconst NEW_BODY = 'eui-tab-body';\n\nexport function migrateEuiTabs(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let migrated = 0;\n let skipped = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) {\n return;\n }\n\n const original = buffer.toString('utf-8');\n const result = path.endsWith('.html')\n ? migrateTemplate(original, path, context)\n : migrateInlineTemplates(original, path, context);\n\n migrated += result.migrated;\n skipped += result.skipped;\n\n if (result.content !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate ${result.migrated} tab block(s) in ${path}`);\n } else {\n tree.overwrite(path, result.content);\n }\n }\n });\n\n context.logger.info(`Migrated ${migrated} EUI tab template block(s).`);\n if (skipped > 0) {\n context.logger.warn(`Skipped ${skipped} malformed EUI tab template block(s).`);\n }\n if (options.dryRun) {\n logDryRunNote(context);\n }\n\n return tree;\n };\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): MigrationResult {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: TextChange[] = [];\n let migrated = 0;\n let skipped = 0;\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const initializer = unwrapExpression(node.initializer);\n\n if (ts.isStringLiteral(initializer) || ts.isNoSubstitutionTemplateLiteral(initializer)) {\n const start = initializer.getStart(sourceFile) + 1;\n const end = initializer.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n const result = migrateTemplate(rawTemplate, `${filePath}@inline-template`, context);\n\n migrated += result.migrated;\n skipped += result.skipped;\n\n if (result.content !== rawTemplate) {\n changes.push({ start, end, text: result.content });\n }\n } else if (ts.isTemplateExpression(initializer)) {\n context.logger.warn(`Skipping interpolated inline template in ${filePath}.`);\n skipped++;\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return {\n content: applyChanges(source, changes),\n migrated,\n skipped,\n };\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (\n (ts.isIdentifier(name) && name.text === 'template') ||\n (ts.isStringLiteral(name) && name.text === 'template')\n );\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n\n return current;\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) {\n return false;\n }\n\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) {\n return false;\n }\n\n return (\n ts.isDecorator(callExpression.parent) &&\n ts.isIdentifier(callExpression.expression) &&\n callExpression.expression.text === 'Component'\n );\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): MigrationResult {\n const parsed = parseTemplate(source, filePath, { preserveWhitespaces: true });\n const changes: TextChange[] = [];\n let migrated = 0;\n let skipped = 0;\n\n for (const error of parsed.errors ?? []) {\n context.logger.warn(`Template parse warning in ${filePath}: ${error.msg}`);\n }\n\n for (const tab of findElements(parsed.nodes, 'eui-tab')) {\n const label = findDirectChild(tab, OLD_LABEL);\n const content = findDirectChild(tab, OLD_CONTENT);\n const hasOldMarkup = Boolean(label || content);\n const hasNewMarkup = Boolean(findDirectChild(tab, NEW_HEADER) || findDirectChild(tab, NEW_BODY));\n\n if (!hasOldMarkup || hasNewMarkup) {\n continue;\n }\n\n if (!label || !content) {\n context.logger.warn(`Skipping malformed <eui-tab> in ${filePath}.`);\n skipped++;\n continue;\n }\n\n changes.push({\n start: label.sourceSpan.start.offset,\n end: label.sourceSpan.end.offset,\n text: buildHeaderReplacement(source, label),\n });\n changes.push({\n start: content.sourceSpan.start.offset,\n end: content.sourceSpan.end.offset,\n text: buildBodyReplacement(source, content),\n });\n migrated++;\n }\n\n return {\n content: applyChanges(source, withoutOverlaps(changes)),\n migrated,\n skipped,\n };\n}\n\nfunction findElements(nodes: readonly TmplAstNode[], name: string): TmplAstElement[] {\n const matches: TmplAstElement[] = [];\n\n for (const node of nodes) {\n if (isElement(node)) {\n if (node.name === name) {\n matches.push(node);\n }\n matches.push(...findElements(node.children, name));\n }\n }\n\n return matches;\n}\n\nfunction findDirectChild(element: TmplAstElement, name: string): TmplAstElement | undefined {\n return element.children.find((child): child is TmplAstElement => isElement(child) && child.name === name);\n}\n\nfunction isElement(node: TmplAstNode): node is TmplAstElement {\n return node instanceof TmplAstElement;\n}\n\nfunction buildHeaderReplacement(source: string, label: TmplAstElement): string {\n const indent = getIndent(source, label.sourceSpan.start.offset);\n const labelAttributes = getAttributeText(source, label, OLD_LABEL);\n const subLabels = findElements(label.children, OLD_SUB_LABEL);\n const mainLabelContent = removeElementRanges(getInnerText(source, label), label, subLabels);\n const lines = [\n `<${NEW_HEADER}>`,\n `${indent} <${NEW_HEADER_LABEL}${labelAttributes}>`,\n ...formatInnerLines(mainLabelContent, `${indent} `),\n `${indent} </${NEW_HEADER_LABEL}>`,\n ];\n\n for (const subLabel of subLabels) {\n const subLabelAttributes = getAttributeText(source, subLabel, OLD_SUB_LABEL);\n lines.push(\n `${indent} <${NEW_HEADER_SUB_LABEL}${subLabelAttributes}>`,\n ...formatInnerLines(getInnerText(source, subLabel), `${indent} `),\n `${indent} </${NEW_HEADER_SUB_LABEL}>`,\n );\n }\n\n lines.push(`${indent}</${NEW_HEADER}>`);\n\n return lines.join('\\n');\n}\n\nfunction buildBodyReplacement(source: string, content: TmplAstElement): string {\n const indent = getIndent(source, content.sourceSpan.start.offset);\n const attributes = getAttributeText(source, content, OLD_CONTENT);\n const innerText = getInnerText(source, content);\n const trimmed = innerText.trim();\n\n if (trimmed && !trimmed.includes('\\n')) {\n return `<${NEW_BODY}${attributes}>${trimmed}</${NEW_BODY}>`;\n }\n\n return [\n `<${NEW_BODY}${attributes}>`,\n ...formatInnerLines(innerText, `${indent} `),\n `${indent}</${NEW_BODY}>`,\n ].join('\\n');\n}\n\nfunction getInnerText(source: string, element: TmplAstElement): string {\n if (!element.endSourceSpan) {\n return '';\n }\n\n return source.slice(element.startSourceSpan.end.offset, element.endSourceSpan.start.offset);\n}\n\nfunction removeElementRanges(source: string, parent: TmplAstElement, elements: readonly TmplAstElement[]): string {\n const parentContentStart = parent.startSourceSpan.end.offset;\n let result = source;\n\n for (const element of [...elements].sort((a, b) => b.sourceSpan.start.offset - a.sourceSpan.start.offset)) {\n const start = element.sourceSpan.start.offset - parentContentStart;\n const end = element.sourceSpan.end.offset - parentContentStart;\n result = result.slice(0, start) + result.slice(end);\n }\n\n return result;\n}\n\nfunction getAttributeText(source: string, element: TmplAstElement, tagName: string): string {\n const startTag = source.slice(element.startSourceSpan.start.offset, element.startSourceSpan.end.offset);\n const tagStart = startTag.indexOf(tagName);\n\n if (tagStart === -1) {\n return '';\n }\n\n const contentEnd = startTag.endsWith('/>') ? startTag.length - 2 : startTag.length - 1;\n return startTag.slice(tagStart + tagName.length, contentEnd).trimEnd();\n}\n\nfunction getIndent(source: string, offset: number): string {\n const lineStart = source.lastIndexOf('\\n', offset - 1) + 1;\n const prefix = source.slice(lineStart, offset);\n return prefix.match(/^\\s*/)?.[0] ?? '';\n}\n\nfunction formatInnerLines(source: string, indent: string): string[] {\n const trimmed = source.trim();\n\n if (!trimmed) {\n return [];\n }\n\n return trimmed.split(/\\r?\\n/).map((line) => `${indent}${line.trim()}`);\n}\n\nfunction withoutOverlaps(changes: TextChange[]): TextChange[] {\n const accepted: TextChange[] = [];\n\n for (const change of [...changes].sort((a, b) => a.start - b.start || b.end - a.end)) {\n if (!accepted.some((current) => change.start < current.end && current.start < change.end)) {\n accepted.push(change);\n }\n }\n\n return accepted;\n}\n\nfunction applyChanges(source: string, changes: readonly TextChange[]): string {\n let result = source;\n\n for (const change of [...changes].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n\n return result;\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2865
2865
  "displayName": "Schema",
2866
2866
  "properties": [
2867
2867
  {
@@ -2873,7 +2873,7 @@
2873
2873
  "indexKey": "",
2874
2874
  "optional": true,
2875
2875
  "description": "",
2876
- "line": 49,
2876
+ "line": 20,
2877
2877
  "rawdescription": "\n"
2878
2878
  },
2879
2879
  {
@@ -2885,7 +2885,7 @@
2885
2885
  "indexKey": "",
2886
2886
  "optional": true,
2887
2887
  "description": "",
2888
- "line": 48,
2888
+ "line": 19,
2889
2889
  "rawdescription": "\n"
2890
2890
  }
2891
2891
  ],
@@ -2903,12 +2903,12 @@
2903
2903
  },
2904
2904
  {
2905
2905
  "name": "Schema",
2906
- "id": "interface-Schema-760dec88d3f709d5b38226e55f7cbfb1e5fabcea6c004fd46e611be1dd563b8b247e9e6c77667e5582fe7b443374ba2c4facd2b2db2985edb46c9a4a37a8a876-18",
2907
- "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
2906
+ "id": "interface-Schema-e1cd02924eb82a618c71a0b26c081bdd020519d2699aa0e2dc98640c4e0f347c3649b967c5fc87543e41bbbfabd1304835850ccc38f40684d6521c242b2030ed-18",
2907
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
2908
2908
  "deprecated": false,
2909
2909
  "deprecationMessage": "",
2910
2910
  "type": "interface",
2911
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface TextChange {\n start: number;\n end: number;\n text: string;\n}\n\ninterface MigrationResult {\n content: string;\n migrated: number;\n skipped: number;\n}\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst OLD_LABEL = 'eui-tab-label';\nconst OLD_SUB_LABEL = 'euiTabSubLabel';\nconst OLD_CONTENT = 'eui-tab-content';\nconst NEW_HEADER = 'eui-tab-header';\nconst NEW_HEADER_LABEL = 'eui-tab-header-label';\nconst NEW_HEADER_SUB_LABEL = 'eui-tab-header-sub-label';\nconst NEW_BODY = 'eui-tab-body';\n\nexport function migrateEuiTabs(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let migrated = 0;\n let skipped = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) {\n return;\n }\n\n const original = buffer.toString('utf-8');\n const result = path.endsWith('.html')\n ? migrateTemplate(original, path, context)\n : migrateInlineTemplates(original, path, context);\n\n migrated += result.migrated;\n skipped += result.skipped;\n\n if (result.content !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate ${result.migrated} tab block(s) in ${path}`);\n } else {\n tree.overwrite(path, result.content);\n }\n }\n });\n\n context.logger.info(`Migrated ${migrated} EUI tab template block(s).`);\n if (skipped > 0) {\n context.logger.warn(`Skipped ${skipped} malformed EUI tab template block(s).`);\n }\n if (options.dryRun) {\n logDryRunNote(context);\n }\n\n return tree;\n };\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): MigrationResult {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: TextChange[] = [];\n let migrated = 0;\n let skipped = 0;\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const initializer = unwrapExpression(node.initializer);\n\n if (ts.isStringLiteral(initializer) || ts.isNoSubstitutionTemplateLiteral(initializer)) {\n const start = initializer.getStart(sourceFile) + 1;\n const end = initializer.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n const result = migrateTemplate(rawTemplate, `${filePath}@inline-template`, context);\n\n migrated += result.migrated;\n skipped += result.skipped;\n\n if (result.content !== rawTemplate) {\n changes.push({ start, end, text: result.content });\n }\n } else if (ts.isTemplateExpression(initializer)) {\n context.logger.warn(`Skipping interpolated inline template in ${filePath}.`);\n skipped++;\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return {\n content: applyChanges(source, changes),\n migrated,\n skipped,\n };\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (\n (ts.isIdentifier(name) && name.text === 'template') ||\n (ts.isStringLiteral(name) && name.text === 'template')\n );\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n\n return current;\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) {\n return false;\n }\n\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) {\n return false;\n }\n\n return (\n ts.isDecorator(callExpression.parent) &&\n ts.isIdentifier(callExpression.expression) &&\n callExpression.expression.text === 'Component'\n );\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): MigrationResult {\n const parsed = parseTemplate(source, filePath, { preserveWhitespaces: true });\n const changes: TextChange[] = [];\n let migrated = 0;\n let skipped = 0;\n\n for (const error of parsed.errors ?? []) {\n context.logger.warn(`Template parse warning in ${filePath}: ${error.msg}`);\n }\n\n for (const tab of findElements(parsed.nodes, 'eui-tab')) {\n const label = findDirectChild(tab, OLD_LABEL);\n const content = findDirectChild(tab, OLD_CONTENT);\n const hasOldMarkup = Boolean(label || content);\n const hasNewMarkup = Boolean(findDirectChild(tab, NEW_HEADER) || findDirectChild(tab, NEW_BODY));\n\n if (!hasOldMarkup || hasNewMarkup) {\n continue;\n }\n\n if (!label || !content) {\n context.logger.warn(`Skipping malformed <eui-tab> in ${filePath}.`);\n skipped++;\n continue;\n }\n\n changes.push({\n start: label.sourceSpan.start.offset,\n end: label.sourceSpan.end.offset,\n text: buildHeaderReplacement(source, label),\n });\n changes.push({\n start: content.sourceSpan.start.offset,\n end: content.sourceSpan.end.offset,\n text: buildBodyReplacement(source, content),\n });\n migrated++;\n }\n\n return {\n content: applyChanges(source, withoutOverlaps(changes)),\n migrated,\n skipped,\n };\n}\n\nfunction findElements(nodes: readonly TmplAstNode[], name: string): TmplAstElement[] {\n const matches: TmplAstElement[] = [];\n\n for (const node of nodes) {\n if (isElement(node)) {\n if (node.name === name) {\n matches.push(node);\n }\n matches.push(...findElements(node.children, name));\n }\n }\n\n return matches;\n}\n\nfunction findDirectChild(element: TmplAstElement, name: string): TmplAstElement | undefined {\n return element.children.find((child): child is TmplAstElement => isElement(child) && child.name === name);\n}\n\nfunction isElement(node: TmplAstNode): node is TmplAstElement {\n return node instanceof TmplAstElement;\n}\n\nfunction buildHeaderReplacement(source: string, label: TmplAstElement): string {\n const indent = getIndent(source, label.sourceSpan.start.offset);\n const labelAttributes = getAttributeText(source, label, OLD_LABEL);\n const subLabels = findElements(label.children, OLD_SUB_LABEL);\n const mainLabelContent = removeElementRanges(getInnerText(source, label), label, subLabels);\n const lines = [\n `<${NEW_HEADER}>`,\n `${indent} <${NEW_HEADER_LABEL}${labelAttributes}>`,\n ...formatInnerLines(mainLabelContent, `${indent} `),\n `${indent} </${NEW_HEADER_LABEL}>`,\n ];\n\n for (const subLabel of subLabels) {\n const subLabelAttributes = getAttributeText(source, subLabel, OLD_SUB_LABEL);\n lines.push(\n `${indent} <${NEW_HEADER_SUB_LABEL}${subLabelAttributes}>`,\n ...formatInnerLines(getInnerText(source, subLabel), `${indent} `),\n `${indent} </${NEW_HEADER_SUB_LABEL}>`,\n );\n }\n\n lines.push(`${indent}</${NEW_HEADER}>`);\n\n return lines.join('\\n');\n}\n\nfunction buildBodyReplacement(source: string, content: TmplAstElement): string {\n const indent = getIndent(source, content.sourceSpan.start.offset);\n const attributes = getAttributeText(source, content, OLD_CONTENT);\n const innerText = getInnerText(source, content);\n const trimmed = innerText.trim();\n\n if (trimmed && !trimmed.includes('\\n')) {\n return `<${NEW_BODY}${attributes}>${trimmed}</${NEW_BODY}>`;\n }\n\n return [\n `<${NEW_BODY}${attributes}>`,\n ...formatInnerLines(innerText, `${indent} `),\n `${indent}</${NEW_BODY}>`,\n ].join('\\n');\n}\n\nfunction getInnerText(source: string, element: TmplAstElement): string {\n if (!element.endSourceSpan) {\n return '';\n }\n\n return source.slice(element.startSourceSpan.end.offset, element.endSourceSpan.start.offset);\n}\n\nfunction removeElementRanges(source: string, parent: TmplAstElement, elements: readonly TmplAstElement[]): string {\n const parentContentStart = parent.startSourceSpan.end.offset;\n let result = source;\n\n for (const element of [...elements].sort((a, b) => b.sourceSpan.start.offset - a.sourceSpan.start.offset)) {\n const start = element.sourceSpan.start.offset - parentContentStart;\n const end = element.sourceSpan.end.offset - parentContentStart;\n result = result.slice(0, start) + result.slice(end);\n }\n\n return result;\n}\n\nfunction getAttributeText(source: string, element: TmplAstElement, tagName: string): string {\n const startTag = source.slice(element.startSourceSpan.start.offset, element.startSourceSpan.end.offset);\n const tagStart = startTag.indexOf(tagName);\n\n if (tagStart === -1) {\n return '';\n }\n\n const contentEnd = startTag.endsWith('/>') ? startTag.length - 2 : startTag.length - 1;\n return startTag.slice(tagStart + tagName.length, contentEnd).trimEnd();\n}\n\nfunction getIndent(source: string, offset: number): string {\n const lineStart = source.lastIndexOf('\\n', offset - 1) + 1;\n const prefix = source.slice(lineStart, offset);\n return prefix.match(/^\\s*/)?.[0] ?? '';\n}\n\nfunction formatInnerLines(source: string, indent: string): string[] {\n const trimmed = source.trim();\n\n if (!trimmed) {\n return [];\n }\n\n return trimmed.split(/\\r?\\n/).map((line) => `${indent}${line.trim()}`);\n}\n\nfunction withoutOverlaps(changes: TextChange[]): TextChange[] {\n const accepted: TextChange[] = [];\n\n for (const change of [...changes].sort((a, b) => a.start - b.start || b.end - a.end)) {\n if (!accepted.some((current) => change.start < current.end && current.start < change.end)) {\n accepted.push(change);\n }\n }\n\n return accepted;\n}\n\nfunction applyChanges(source: string, changes: readonly TextChange[]): string {\n let result = source;\n\n for (const change of [...changes].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n\n return result;\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2911
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst OLD_TAG = 'eui-toolbar-menu';\nconst NEW_TAG = 'eui-toolbar-mega-menu';\nconst OLD_COMPONENT = 'EuiToolbarMenuComponent';\nconst NEW_COMPONENT = 'EuiToolbarMegaMenuComponent';\nconst OLD_INTERFACE = 'ToolbarItem';\nconst NEW_INTERFACE = 'EuiMenuItem';\nconst NEW_COMPONENT_PATH = '@eui/components/layout';\nconst NEW_INTERFACE_PATH = '@eui/core';\nconst REMOVED_OUTPUT = 'menuItemClick';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nexport function migrateEuiToolbarMenu(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_TAG) && !original.includes(OLD_COMPONENT) && !original.includes(OLD_INTERFACE)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original, path, context);\n } else {\n result = migrateTypeScript(original, path, context);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-toolbar-menu → eui-toolbar-mega-menu in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated eui-toolbar-menu → eui-toolbar-mega-menu in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n\n visitNodes(parsed.nodes, source, edits, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n let result = migrateInlineTemplates(source, filePath, context);\n result = migrateImportsAndTypes(result, filePath, context);\n return result;\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(OLD_TAG)) {\n ts.forEachChild(node, visit); return; \n}\n const migrated = migrateTemplate(rawTemplate, filePath, context);\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, changes);\n}\n\nfunction migrateImportsAndTypes(source: string, filePath: string, context: SchematicContext): string {\n if (!source.includes(OLD_COMPONENT) && !source.includes(OLD_INTERFACE)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiMenuItem is already imported from @eui/core\n let hasEuiMenuItemImport = false;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpec = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE && moduleSpec === NEW_INTERFACE_PATH) {\n hasEuiMenuItemImport = true;\n }\n }\n }\n\n // Second pass: collect edits for import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const moduleSpec = stmt.moduleSpecifier as ts.StringLiteral;\n const specifiers = namedBindings.elements;\n const hasComponent = specifiers.some((s) => s.name.text === OLD_COMPONENT);\n const hasInterface = specifiers.some((s) => s.name.text === OLD_INTERFACE);\n\n if (hasComponent && hasInterface) {\n // Both are in the same import → must split into two different paths\n const others = specifiers.filter((s) => s.name.text !== OLD_COMPONENT && s.name.text !== OLD_INTERFACE);\n const lines: string[] = [];\n lines.push(`import { ${NEW_COMPONENT} } from '${NEW_COMPONENT_PATH}';`);\n if (!hasEuiMenuItemImport) {\n lines.push(`import { ${NEW_INTERFACE} } from '${NEW_INTERFACE_PATH}';`);\n }\n if (others.length > 0) {\n const otherNames = others.map((s) => s.name.text).join(', ');\n lines.push(`import { ${otherNames} } from '${moduleSpec.text}';`);\n }\n edits.push({\n start: stmt.getStart(sourceFile),\n end: stmt.getEnd(),\n replacement: lines.join('\\n'),\n });\n } else if (hasComponent) {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_COMPONENT_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_COMPONENT) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_COMPONENT,\n });\n }\n }\n } else if (hasInterface) {\n if (hasEuiMenuItemImport) {\n removeImportSpecifier(namedBindings, specifiers.find((s) => s.name.text === OLD_INTERFACE)!, sourceFile, edits);\n } else {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_INTERFACE_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_INTERFACE) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n }\n }\n }\n\n // Third pass: rename identifier references in non-import positions\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return; // skip imports (already handled)\n if (ts.isIdentifier(node)) {\n if (node.text === OLD_COMPONENT) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_COMPONENT });\n }\n if (node.text === OLD_INTERFACE) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_INTERFACE });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n // Warn about ToolbarItem-specific properties\n warnRemovedProperties(sourceFile, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end: importDecl.getEnd(),\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction warnRemovedProperties(sourceFile: ts.SourceFile, filePath: string, context: SchematicContext): void {\n const deprecated = ['isHome', 'isSeparator'];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === OLD_TAG) {\n collectTagRenames(node, source, edits);\n collectOutputRemovals(node, source, edits, filePath, context);\n }\n visitNodes(node.children, source, edits, filePath, context);\n }\n }\n}\n\nfunction collectTagRenames(element: TmplAstElement, source: string, edits: Edit[]): void {\n // Rename opening tag\n const openStart = element.startSourceSpan.start.offset + 1; // skip '<'\n edits.push({ start: openStart, end: openStart + OLD_TAG.length, replacement: NEW_TAG });\n\n // Rename closing tag\n if (element.endSourceSpan) {\n const closeStart = element.endSourceSpan.start.offset + 2; // skip '</'\n edits.push({ start: closeStart, end: closeStart + OLD_TAG.length, replacement: NEW_TAG });\n }\n}\n\nfunction collectOutputRemovals(\n element: TmplAstElement,\n source: string,\n edits: Edit[],\n filePath: string,\n context: SchematicContext,\n): void {\n for (const output of element.outputs) {\n if (output.name === REMOVED_OUTPUT) {\n let start = output.sourceSpan.start.offset;\n // Remove leading whitespace\n while (start > 0 && (source[start - 1] === ' ' || source[start - 1] === '\\t')) {\n start--;\n }\n edits.push({ start, end: output.sourceSpan.end.offset, replacement: '' });\n\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(menuItemClick)\" has been removed. There is no equivalent on eui-toolbar-mega-menu.`,\n );\n }\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n // Deduplicate edits at same position (e.g. module path edits when both Component and ToolbarItem are from same source)\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n // Last wins for same range\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
2912
2912
  "displayName": "Schema",
2913
2913
  "properties": [
2914
2914
  {
@@ -2920,7 +2920,7 @@
2920
2920
  "indexKey": "",
2921
2921
  "optional": true,
2922
2922
  "description": "",
2923
- "line": 20,
2923
+ "line": 18,
2924
2924
  "rawdescription": "\n"
2925
2925
  },
2926
2926
  {
@@ -2932,7 +2932,7 @@
2932
2932
  "indexKey": "",
2933
2933
  "optional": true,
2934
2934
  "description": "",
2935
- "line": 19,
2935
+ "line": 17,
2936
2936
  "rawdescription": "\n"
2937
2937
  }
2938
2938
  ],
@@ -2997,12 +2997,12 @@
2997
2997
  },
2998
2998
  {
2999
2999
  "name": "Schema",
3000
- "id": "interface-Schema-817c4b549cc3eab9fcf4936acab2e71182d90a4480369f5c003cbbda10792efa587ad99d65acf049f64e7030e32589e4fabc4a6d7a5621e4fe54725ef91dc9e8-20",
3001
- "file": "packages/core/schematics/migrate-to-standalone/index.ts",
3000
+ "id": "interface-Schema-21147930d3fbc38fbb3052a2ed9e7aa2b7505e6ed8c88c28796ce7101bd2ad914726eb230dda5826647036190edec6dae7e7e1d172387cd3803aa00bcdf790be-20",
3001
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
3002
3002
  "deprecated": false,
3003
3003
  "deprecationMessage": "",
3004
3004
  "type": "interface",
3005
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface ModuleMapping {\n importPath: string;\n selectors: Record<string, string>;\n}\n\nconst MODULE_MAPPINGS: Record<string, ModuleMapping> = {\n EuiAccordionModule: {\n importPath: '@eui/components/eui-accordion',\n selectors: {\n 'eui-accordion': 'EuiAccordionComponent',\n 'eui-accordion-item': 'EuiAccordionItemComponent',\n euiAccordionItemHeader: 'EuiAccordionItemHeaderDirective',\n },\n },\n EuiAlertModule: {\n importPath: '@eui/components/eui-alert',\n selectors: {\n 'eui-alert': 'EuiAlertComponent',\n euiAlert: 'EuiAlertComponent',\n 'eui-alert-title': 'EuiAlertTitleComponent',\n },\n },\n EuiAutocompleteModule: {\n importPath: '@eui/components/eui-autocomplete',\n selectors: {\n 'eui-autocomplete': 'EuiAutocompleteComponent',\n euiAutocomplete: 'EuiAutocompleteComponent',\n 'eui-autocomplete-option': 'EuiAutocompleteOptionComponent',\n 'eui-autocomplete-option-group': 'EuiAutocompleteOptionGroupComponent',\n 'eui-autocomplete-panel': 'EuiAutocompletePanelComponent',\n },\n },\n EuiAvatarModule: {\n importPath: '@eui/components/eui-avatar',\n selectors: {\n 'eui-avatar': 'EuiAvatarComponent',\n euiAvatar: 'EuiAvatarComponent',\n },\n },\n EuiBadgeModule: {\n importPath: '@eui/components/eui-badge',\n selectors: {\n 'eui-badge': 'EuiBadgeComponent',\n euiBadge: 'EuiBadgeComponent',\n },\n },\n EuiBlockContentModule: {\n importPath: '@eui/components/eui-block-content',\n selectors: {\n 'eui-block-content': 'EuiBlockContentComponent',\n },\n },\n EuiBreadcrumbModule: {\n importPath: '@eui/components/eui-breadcrumb',\n selectors: {\n 'eui-breadcrumb': 'EuiBreadcrumbComponent',\n },\n },\n EuiButtonModule: {\n importPath: '@eui/components/eui-button',\n selectors: {\n euiButton: 'EuiButtonComponent',\n },\n },\n EuiButtonGroupModule: {\n importPath: '@eui/components/eui-button-group',\n selectors: {\n 'eui-button-group': 'EuiButtonGroupComponent',\n },\n },\n EuiCardModule: {\n importPath: '@eui/components/eui-card',\n selectors: {\n 'eui-card': 'EuiCardComponent',\n 'eui-card-header': 'EuiCardHeaderComponent',\n 'eui-card-header-title': 'EuiCardHeaderTitleComponent',\n 'eui-card-content': 'EuiCardContentComponent',\n 'eui-card-footer': 'EuiCardFooterComponent',\n 'eui-card-media': 'EuiCardMediaComponent',\n },\n },\n EuiChipModule: {\n importPath: '@eui/components/eui-chip',\n selectors: {\n 'eui-chip': 'EuiChipComponent',\n euiChip: 'EuiChipComponent',\n },\n },\n EuiChipListModule: {\n importPath: '@eui/components/eui-chip-list',\n selectors: {\n 'eui-chip-list': 'EuiChipListComponent',\n },\n },\n EuiChipGroupModule: {\n importPath: '@eui/components/eui-chip-group',\n selectors: {\n 'eui-chip-group': 'EuiChipGroupComponent',\n },\n },\n EuiDashboardCardModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDashboardButtonModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDatepickerModule: {\n importPath: '@eui/components/eui-datepicker',\n selectors: {\n 'eui-datepicker': 'EuiDatepickerComponent',\n },\n },\n EuiDateRangeSelectorModule: {\n importPath: '@eui/components/eui-date-range-selector',\n selectors: {\n 'eui-date-range-selector': 'EuiDateRangeSelectorComponent',\n },\n },\n EuiDialogModule: {\n importPath: '@eui/components/eui-dialog',\n selectors: {\n 'eui-dialog': 'EuiDialogComponent',\n 'eui-dialog-header': 'EuiDialogHeaderDirective',\n 'eui-dialog-footer': 'EuiDialogFooterDirective',\n 'eui-dialog-container': 'EuiDialogContainerComponent',\n },\n },\n EuiDisableContentModule: {\n importPath: '@eui/components/eui-disable-content',\n selectors: {\n 'eui-disable-content': 'EuiDisableContentComponent',\n },\n },\n EuiDiscussionThreadModule: {\n importPath: '@eui/components/eui-discussion-thread',\n selectors: {\n 'eui-discussion-thread': 'EuiDiscussionThreadComponent',\n 'eui-discussion-thread-item': 'EuiDiscussionThreadItemComponent',\n },\n },\n EuiDropdownModule: {\n importPath: '@eui/components/eui-dropdown',\n selectors: {\n 'eui-dropdown': 'EuiDropdownComponent',\n },\n },\n EuiFeedbackMessageModule: {\n importPath: '@eui/components/eui-feedback-message',\n selectors: {\n 'eui-feedback-message': 'EuiFeedbackMessageComponent',\n },\n },\n EuiFieldsetModule: {\n importPath: '@eui/components/eui-fieldset',\n selectors: {\n 'eui-fieldset': 'EuiFieldsetComponent',\n euiFieldsetLabelRightContent: 'EuiFieldsetLabelRightContentTagDirective',\n euiFieldsetLabelExtraContent: 'EuiFieldsetLabelExtraContentTagDirective',\n },\n },\n EuiFileUploadModule: {\n importPath: '@eui/components/eui-file-upload',\n selectors: {\n 'eui-file-upload': 'EuiFileUploadComponent',\n },\n },\n EuiGrowlModule: {\n importPath: '@eui/components/eui-growl',\n selectors: {\n 'eui-growl': 'EuiGrowlComponent',\n },\n },\n EuiIconModule: {\n importPath: '@eui/components/eui-icon',\n selectors: {\n 'eui-icon-svg': 'EuiIconSvgComponent',\n euiIconSvg: 'EuiIconSvgComponent',\n },\n },\n EuiIconButtonModule: {\n importPath: '@eui/components/eui-icon-button',\n selectors: {\n 'eui-icon-button': 'EuiIconButtonComponent',\n },\n },\n EuiIconToggleModule: {\n importPath: '@eui/components/eui-icon-toggle',\n selectors: {\n 'eui-icon-toggle': 'EuiIconToggleComponent',\n },\n },\n EuiInputCheckboxModule: {\n importPath: '@eui/components/eui-input-checkbox',\n selectors: {\n euiInputCheckBox: 'EuiInputCheckboxComponent',\n },\n },\n EuiInputGroupModule: {\n importPath: '@eui/components/eui-input-group',\n selectors: {\n euiInputGroup: 'EuiInputGroupComponent',\n 'eui-input-group-addon': 'EuiInputGroupAddOnComponent',\n euiInputGroupAddOn: 'EuiInputGroupAddOnComponent',\n 'eui-input-group-addon-item': 'EuiInputGroupAddOnItemComponent',\n euiInputGroupAddOnItem: 'EuiInputGroupAddOnItemComponent',\n },\n },\n EuiInputNumberModule: {\n importPath: '@eui/components/eui-input-number',\n selectors: {\n euiInputNumber: 'EuiInputNumberComponent',\n },\n },\n EuiInputRadioModule: {\n importPath: '@eui/components/eui-input-radio',\n selectors: {\n euiInputRadio: 'EuiInputRadioComponent',\n },\n },\n EuiInputTextModule: {\n importPath: '@eui/components/eui-input-text',\n selectors: {\n euiInputText: 'EuiInputTextComponent',\n },\n },\n EuiLabelModule: {\n importPath: '@eui/components/eui-label',\n selectors: {\n 'eui-label': 'EuiLabelComponent',\n euiLabel: 'EuiLabelComponent',\n },\n },\n EuiListModule: {\n importPath: '@eui/components/eui-list',\n selectors: {\n 'eui-list': 'EuiListComponent',\n euiList: 'EuiListComponent',\n 'eui-list-item': 'EuiListItemComponent',\n euiListItem: 'EuiListItemComponent',\n },\n },\n EuiMenuModule: {\n importPath: '@eui/components/eui-menu',\n selectors: {\n 'eui-menu': 'EuiMenuComponent',\n 'eui-menu-item': 'EuiMenuItemComponent',\n },\n },\n EuiMessageBoxModule: {\n importPath: '@eui/components/eui-message-box',\n selectors: {\n 'eui-message-box': 'EuiMessageBoxComponent',\n 'eui-message-box-footer': 'EuiMessageBoxFooterDirective',\n },\n },\n EuiOverlayModule: {\n importPath: '@eui/components/eui-overlay',\n selectors: {\n 'eui-overlay': 'EuiOverlayComponent',\n },\n },\n EuiPageModule: {\n importPath: '@eui/components/eui-page',\n selectors: {\n 'eui-page': 'EuiPageComponent',\n },\n },\n EuiPaginatorModule: {\n importPath: '@eui/components/eui-paginator',\n selectors: {\n 'eui-paginator': 'EuiPaginatorComponent',\n },\n },\n EuiPopoverModule: {\n importPath: '@eui/components/eui-popover',\n selectors: {\n 'eui-popover': 'EuiPopoverComponent',\n },\n },\n EuiProgressBarModule: {\n importPath: '@eui/components/eui-progress-bar',\n selectors: {\n 'eui-progress-bar': 'EuiProgressBarComponent',\n },\n },\n EuiProgressCircleModule: {\n importPath: '@eui/components/eui-progress-circle',\n selectors: {\n 'eui-progress-circle': 'EuiProgressCircleComponent',\n },\n },\n EuiSelectModule: {\n importPath: '@eui/components/eui-select',\n selectors: {\n euiSelect: 'EuiSelectComponent',\n },\n },\n EuiSidebarMenuModule: {\n importPath: '@eui/components/eui-sidebar-menu',\n selectors: {\n 'eui-sidebar-menu': 'EuiSidebarMenuComponent',\n },\n },\n EuiSkeletonModule: {\n importPath: '@eui/components/eui-skeleton',\n selectors: {\n 'eui-skeleton': 'EuiSkeletonComponent',\n },\n },\n EuiSlideToggleModule: {\n importPath: '@eui/components/eui-slide-toggle',\n selectors: {\n 'eui-slide-toggle': 'EuiSlideToggleComponent',\n },\n },\n EuiTableModule: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTableV2Module: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTabsModule: {\n importPath: '@eui/components/eui-tabs',\n selectors: {\n 'eui-tabs': 'EuiTabsComponent',\n 'eui-tab': 'EuiTabComponent',\n 'eui-tab-header': 'EuiTabHeaderComponent',\n 'eui-tab-body': 'EuiTabBodyComponent',\n },\n },\n EuiTextAreaModule: {\n importPath: '@eui/components/eui-textarea',\n selectors: {\n euiTextArea: 'EuiTextareaComponent',\n },\n },\n EuiTimelineModule: {\n importPath: '@eui/components/eui-timeline',\n selectors: {\n 'eui-timeline': 'EuiTimelineComponent',\n 'eui-timeline-item': 'EuiTimelineItemComponent',\n },\n },\n EuiTimepickerModule: {\n importPath: '@eui/components/eui-timepicker',\n selectors: {\n 'eui-timepicker': 'EuiTimepickerComponent',\n },\n },\n EuiTreeModule: {\n importPath: '@eui/components/eui-tree',\n selectors: {\n 'eui-tree': 'EuiTreeComponent',\n },\n },\n EuiTreeListModule: {\n importPath: '@eui/components/eui-tree-list',\n selectors: {\n 'eui-tree-list': 'EuiTreeListComponent',\n 'eui-tree-list-item': 'EuiTreeListItemComponent',\n },\n },\n EuiUserProfileModule: {\n importPath: '@eui/components/eui-user-profile',\n selectors: {\n 'eui-user-profile': 'EuiUserProfileComponent',\n },\n },\n EuiWizardModule: {\n importPath: '@eui/components/eui-wizard',\n selectors: {\n 'eui-wizard': 'EuiWizardComponent',\n 'eui-wizard-step': 'EuiWizardStepComponent',\n },\n },\n EuiTooltipDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTooltip: 'EuiTooltipDirective',\n },\n },\n EuiTemplateDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTemplate: 'EuiTemplateDirective',\n },\n },\n EuiResizableDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiResizable: 'EuiResizableDirective',\n 'eui-resizable': 'EuiResizableComponent',\n },\n },\n EuiMaxLengthDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiEditorMaxlength: 'EuiMaxLengthDirective',\n },\n },\n EuiTruncatePipeModule: {\n importPath: '@eui/components/pipes',\n selectors: {\n euiTruncate: 'EuiTruncatePipe',\n },\n },\n EuiLayoutModule: {\n importPath: '@eui/components/layout',\n selectors: {\n 'eui-app': 'EuiAppComponent',\n 'eui-header': 'EuiHeaderComponent',\n 'eui-footer': 'EuiFooterComponent',\n 'eui-toolbar': 'EuiToolbarComponent',\n 'eui-sidebar-toggle': 'EuiSidebarToggleComponent',\n },\n },\n};\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateToStandalone(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const allModuleNames = Object.keys(MODULE_MAPPINGS);\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!allModuleNames.some((m) => source.includes(m))) return;\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const componentDecorators = findComponentDecorators(sourceFile);\n\n for (const decorator of componentDecorators) {\n const importsNode = findImportsArrayNode(decorator);\n if (!importsNode) continue;\n\n const currentSource = tree.read(path)!.toString('utf-8');\n const modulesInArray = allModuleNames.filter((m) => hasModuleInArray(importsNode, m, source));\n if (modulesInArray.length === 0) continue;\n\n const templateSelectors = getTemplateSelectors(tree, path, decorator, source);\n const replacements = buildReplacements(modulesInArray, templateSelectors);\n if (replacements.size === 0) continue;\n\n const result = applyReplacements(currentSource, path, replacements);\n if (options.dryRun) {\n logDryRun(context, `Would replace module imports with standalone imports in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n }\n });\n\n context.logger.info('Migration to standalone imports complete.');\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction buildReplacements(moduleNames: string[], templateSelectors: Set<string>): Map<string, { components: string[]; importPath: string }> {\n const map = new Map<string, { components: string[]; importPath: string }>();\n\n for (const moduleName of moduleNames) {\n const mapping = MODULE_MAPPINGS[moduleName];\n const components: string[] = [];\n\n for (const [selector, component] of Object.entries(mapping.selectors)) {\n if (templateSelectors.has(selector)) {\n components.push(component);\n }\n }\n\n if (components.length > 0) {\n map.set(moduleName, { components: [...new Set(components)].sort(), importPath: mapping.importPath });\n }\n }\n\n return map;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ts.Decorator[] {\n const decorators: ts.Decorator[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n decorators.push(dec);\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return decorators;\n}\n\nfunction findImportsArrayNode(decorator: ts.Decorator): ts.ArrayLiteralExpression | undefined {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) return undefined;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer;\n }\n }\n }\n return undefined;\n}\n\nfunction hasModuleInArray(array: ts.ArrayLiteralExpression, moduleName: string, source: string): boolean {\n return array.elements.some((el) => source.slice(el.getStart(), el.getEnd()).trim() === moduleName);\n}\n\nfunction getTemplateSelectors(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): Set<string> {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0] as ts.ObjectLiteralExpression;\n const allSelectors = Object.values(MODULE_MAPPINGS).flatMap((m) => Object.keys(m.selectors));\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return findSelectorsInTemplate(init.text, allSelectors);\n }\n }\n }\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) {\n return findSelectorsInTemplate(templateBuffer.toString('utf-8'), allSelectors);\n }\n }\n }\n }\n\n return new Set();\n}\n\nfunction findSelectorsInTemplate(html: string, knownSelectors: string[]): Set<string> {\n const selectors = new Set<string>();\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n\n const visit = (nodes: TmplAstNode[]): void => {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (knownSelectors.includes(node.name)) selectors.add(node.name);\n for (const attr of node.attributes) {\n if (knownSelectors.includes(attr.name)) selectors.add(attr.name);\n }\n visit(node.children);\n }\n }\n };\n visit(parsed.nodes);\n return selectors;\n}\n\nfunction applyReplacements(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n let result = replaceInImportsArray(source, sourceFile, replacements);\n result = updateEsImports(result, filePath, replacements);\n return result;\n}\n\nfunction replaceInImportsArray(source: string, sourceFile: ts.SourceFile, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression) || !ts.isIdentifier(dec.expression.expression) || dec.expression.expression.text !== 'Component') continue;\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'imports') continue;\n if (!ts.isArrayLiteralExpression(prop.initializer)) continue;\n const newElements = prop.initializer.elements\n .map((el) => {\n const text = result.slice(el.getStart(sourceFile), el.getEnd()).trim();\n const replacement = replacements.get(text);\n return replacement ? replacement.components.join(', ') : text;\n })\n .join(', ');\n result = result.slice(0, prop.initializer.getStart(sourceFile) + 1) + newElements + result.slice(prop.initializer.getEnd() - 1);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return result;\n}\n\nfunction updateEsImports(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n\n for (const [moduleName, { components, importPath }] of replacements) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const importNames = namedBindings.elements.map((el) => el.name.text);\n if (!importNames.includes(moduleName)) continue;\n\n const moduleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const remaining = importNames.filter((n) => n !== moduleName);\n const toAdd = components.filter((c) => !importNames.includes(c));\n\n if (moduleSpecifier === importPath) {\n const newNames = [...remaining, ...toAdd].sort();\n const newClause = `{ ${newNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n if (remaining.length > 0) {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n }\n\n if (toAdd.length > 0) {\n const updatedSf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n const existing = updatedSf.statements.find(\n (s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n ) as ts.ImportDeclaration | undefined;\n\n if (existing?.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {\n const existingNames = existing.importClause.namedBindings.elements.map((el) => el.name.text);\n const allNames = [...new Set([...existingNames, ...toAdd])].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, existing.importClause.namedBindings.getStart(updatedSf)) + newClause + result.slice(existing.importClause.namedBindings.getEnd());\n } else {\n const newImport = `import { ${toAdd.join(', ')} } from '${importPath}';\\n`;\n result = newImport + result;\n }\n }\n }\n break;\n }\n }\n\n return result;\n}\n",
3005
+ "sourceCode": "import { parseTemplate, TmplAstBoundAttribute, TmplAstElement, TmplAstNode, TmplAstTextAttribute } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nconst OLD_NAME = 'iconSet';\nconst NEW_NAME = 'iconSvgName';\nconst COMPONENT_TAG = 'eui-icon-toggle';\n\nexport function migrateEuiIconToggle(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let templateCount = 0;\n let tsCount = 0;\n\n const dir = tree.getDir(scanPath || '/');\n visitDir(dir, (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(COMPONENT_TAG)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original);\n } else {\n result = migrateInlineTemplates(original);\n result = renameTsPropertyAccesses(result);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would rename '${OLD_NAME}' → '${NEW_NAME}' in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n if (path.endsWith('.html')) templateCount++;\n else tsCount++;\n }\n });\n\n context.logger.info(`Renamed '${OLD_NAME}' → '${NEW_NAME}' on ${COMPONENT_TAG} in ${templateCount + tsCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction migrateTemplate(source: string): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n visitNodes(parsed.nodes, edits);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateInlineTemplates(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: { start: number; end: number; text: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(COMPONENT_TAG)) {\n ts.forEachChild(node, visit);\n return;\n }\n const migrated = migrateTemplate(rawTemplate);\n if (migrated !== rawTemplate) {\n changes.push({ start, end, text: migrated });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n let result = source;\n for (const change of changes.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, change.start) + change.text + result.slice(change.end);\n }\n return result;\n}\n\nfunction renameTsPropertyAccesses(source: string): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: { start: number; end: number; replacement: string }[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && node.name.text === OLD_NAME) {\n edits.push({ start: node.name.getStart(sourceFile), end: node.name.getEnd(), replacement: NEW_NAME });\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n return applyEdits(source, edits);\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n return current;\n}\n\nfunction visitNodes(nodes: TmplAstNode[], edits: { start: number; end: number; replacement: string }[]): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === COMPONENT_TAG) {\n collectRenames(node, edits);\n }\n visitNodes(node.children, edits);\n }\n }\n}\n\nfunction collectRenames(element: TmplAstElement, edits: { start: number; end: number; replacement: string }[]): void {\n for (const attr of element.attributes) {\n if (attr.name === OLD_NAME) {\n edits.push({ start: attr.keySpan!.start.offset, end: attr.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n for (const input of element.inputs) {\n if (input.name === OLD_NAME) {\n edits.push({ start: input.keySpan!.start.offset, end: input.keySpan!.end.offset, replacement: NEW_NAME });\n }\n }\n}\n\nfunction applyEdits(source: string, edits: { start: number; end: number; replacement: string }[]): string {\n let result = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n",
3006
3006
  "displayName": "Schema",
3007
3007
  "properties": [
3008
3008
  {
@@ -3014,7 +3014,7 @@
3014
3014
  "indexKey": "",
3015
3015
  "optional": true,
3016
3016
  "description": "",
3017
- "line": 460,
3017
+ "line": 8,
3018
3018
  "rawdescription": "\n"
3019
3019
  },
3020
3020
  {
@@ -3026,7 +3026,7 @@
3026
3026
  "indexKey": "",
3027
3027
  "optional": true,
3028
3028
  "description": "",
3029
- "line": 459,
3029
+ "line": 7,
3030
3030
  "rawdescription": "\n"
3031
3031
  }
3032
3032
  ],
@@ -3044,12 +3044,12 @@
3044
3044
  },
3045
3045
  {
3046
3046
  "name": "Schema",
3047
- "id": "interface-Schema-e1cd02924eb82a618c71a0b26c081bdd020519d2699aa0e2dc98640c4e0f347c3649b967c5fc87543e41bbbfabd1304835850ccc38f40684d6521c242b2030ed-21",
3048
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
3047
+ "id": "interface-Schema-817c4b549cc3eab9fcf4936acab2e71182d90a4480369f5c003cbbda10792efa587ad99d65acf049f64e7030e32589e4fabc4a6d7a5621e4fe54725ef91dc9e8-21",
3048
+ "file": "packages/core/schematics/migrate-to-standalone/index.ts",
3049
3049
  "deprecated": false,
3050
3050
  "deprecationMessage": "",
3051
3051
  "type": "interface",
3052
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\nconst OLD_TAG = 'eui-toolbar-menu';\nconst NEW_TAG = 'eui-toolbar-mega-menu';\nconst OLD_COMPONENT = 'EuiToolbarMenuComponent';\nconst NEW_COMPONENT = 'EuiToolbarMegaMenuComponent';\nconst OLD_INTERFACE = 'ToolbarItem';\nconst NEW_INTERFACE = 'EuiMenuItem';\nconst NEW_COMPONENT_PATH = '@eui/components/layout';\nconst NEW_INTERFACE_PATH = '@eui/core';\nconst REMOVED_OUTPUT = 'menuItemClick';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\nexport function migrateEuiToolbarMenu(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n if (!original.includes(OLD_TAG) && !original.includes(OLD_COMPONENT) && !original.includes(OLD_INTERFACE)) return;\n\n let result: string;\n\n if (path.endsWith('.html')) {\n result = migrateTemplate(original, path, context);\n } else {\n result = migrateTypeScript(original, path, context);\n }\n\n if (result !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate eui-toolbar-menu → eui-toolbar-mega-menu in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n fileCount++;\n }\n });\n\n context.logger.info(`Migrated eui-toolbar-menu → eui-toolbar-mega-menu in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction migrateTemplate(source: string, filePath: string, context: SchematicContext): string {\n const parsed = parseTemplate(source, '', { preserveWhitespaces: true });\n const edits: Edit[] = [];\n\n visitNodes(parsed.nodes, source, edits, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction migrateTypeScript(source: string, filePath: string, context: SchematicContext): string {\n let result = migrateInlineTemplates(source, filePath, context);\n result = migrateImportsAndTypes(result, filePath, context);\n return result;\n}\n\nfunction migrateInlineTemplates(source: string, filePath: string, context: SchematicContext): string {\n const sourceFile = ts.createSourceFile('', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const changes: Edit[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node) && isTemplateProperty(node) && isComponentMetadataProperty(node)) {\n const init = unwrapExpression(node.initializer);\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const start = init.getStart(sourceFile) + 1;\n const end = init.getEnd() - 1;\n const rawTemplate = source.slice(start, end);\n if (!rawTemplate.includes(OLD_TAG)) {\n ts.forEachChild(node, visit); return; \n}\n const migrated = migrateTemplate(rawTemplate, filePath, context);\n if (migrated !== rawTemplate) changes.push({ start, end, replacement: migrated });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return applyEdits(source, changes);\n}\n\nfunction migrateImportsAndTypes(source: string, filePath: string, context: SchematicContext): string {\n if (!source.includes(OLD_COMPONENT) && !source.includes(OLD_INTERFACE)) return source;\n\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Track if EuiMenuItem is already imported from @eui/core\n let hasEuiMenuItemImport = false;\n\n // First pass: analyze imports\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpec = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n for (const specifier of namedBindings.elements) {\n if (specifier.name.text === NEW_INTERFACE && moduleSpec === NEW_INTERFACE_PATH) {\n hasEuiMenuItemImport = true;\n }\n }\n }\n\n // Second pass: collect edits for import declarations\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const namedBindings = stmt.importClause?.namedBindings;\n if (!namedBindings || !ts.isNamedImports(namedBindings)) continue;\n\n const moduleSpec = stmt.moduleSpecifier as ts.StringLiteral;\n const specifiers = namedBindings.elements;\n const hasComponent = specifiers.some((s) => s.name.text === OLD_COMPONENT);\n const hasInterface = specifiers.some((s) => s.name.text === OLD_INTERFACE);\n\n if (hasComponent && hasInterface) {\n // Both are in the same import → must split into two different paths\n const others = specifiers.filter((s) => s.name.text !== OLD_COMPONENT && s.name.text !== OLD_INTERFACE);\n const lines: string[] = [];\n lines.push(`import { ${NEW_COMPONENT} } from '${NEW_COMPONENT_PATH}';`);\n if (!hasEuiMenuItemImport) {\n lines.push(`import { ${NEW_INTERFACE} } from '${NEW_INTERFACE_PATH}';`);\n }\n if (others.length > 0) {\n const otherNames = others.map((s) => s.name.text).join(', ');\n lines.push(`import { ${otherNames} } from '${moduleSpec.text}';`);\n }\n edits.push({\n start: stmt.getStart(sourceFile),\n end: stmt.getEnd(),\n replacement: lines.join('\\n'),\n });\n } else if (hasComponent) {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_COMPONENT_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_COMPONENT) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_COMPONENT,\n });\n }\n }\n } else if (hasInterface) {\n if (hasEuiMenuItemImport) {\n removeImportSpecifier(namedBindings, specifiers.find((s) => s.name.text === OLD_INTERFACE)!, sourceFile, edits);\n } else {\n edits.push({\n start: moduleSpec.getStart(sourceFile) + 1,\n end: moduleSpec.getEnd() - 1,\n replacement: NEW_INTERFACE_PATH,\n });\n for (const specifier of specifiers) {\n if (specifier.name.text === OLD_INTERFACE) {\n edits.push({\n start: specifier.name.getStart(sourceFile),\n end: specifier.name.getEnd(),\n replacement: NEW_INTERFACE,\n });\n }\n }\n }\n }\n }\n\n // Third pass: rename identifier references in non-import positions\n const visitRefs = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) return; // skip imports (already handled)\n if (ts.isIdentifier(node)) {\n if (node.text === OLD_COMPONENT) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_COMPONENT });\n }\n if (node.text === OLD_INTERFACE) {\n edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), replacement: NEW_INTERFACE });\n }\n }\n ts.forEachChild(node, visitRefs);\n };\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) {\n visitRefs(stmt);\n }\n }\n\n // Warn about ToolbarItem-specific properties\n warnRemovedProperties(sourceFile, filePath, context);\n\n return applyEdits(source, edits);\n}\n\nfunction removeImportSpecifier(\n namedImports: ts.NamedImports,\n specifier: ts.ImportSpecifier,\n sourceFile: ts.SourceFile,\n edits: Edit[],\n): void {\n const elements = namedImports.elements;\n if (elements.length === 1) {\n // Remove the entire import declaration\n const importDecl = namedImports.parent.parent;\n edits.push({\n start: importDecl.getStart(sourceFile),\n end: importDecl.getEnd(),\n replacement: '',\n });\n } else {\n // Remove just this specifier with surrounding comma/whitespace\n const idx = elements.indexOf(specifier);\n let start: number;\n let end: number;\n if (idx < elements.length - 1) {\n start = specifier.getStart(sourceFile);\n end = elements[idx + 1].getStart(sourceFile);\n } else {\n start = elements[idx - 1].getEnd();\n end = specifier.getEnd();\n }\n edits.push({ start, end, replacement: '' });\n }\n}\n\nfunction warnRemovedProperties(sourceFile: ts.SourceFile, filePath: string, context: SchematicContext): void {\n const deprecated = ['isHome', 'isSeparator'];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && deprecated.includes(node.name.text)) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n context.logger.warn(\n `${filePath}:${line + 1} - \"${node.name.text}\" was part of ToolbarItem but does not exist on EuiMenuItem. Review manually.`,\n );\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n}\n\nfunction visitNodes(nodes: TmplAstNode[], source: string, edits: Edit[], filePath: string, context: SchematicContext): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.name === OLD_TAG) {\n collectTagRenames(node, source, edits);\n collectOutputRemovals(node, source, edits, filePath, context);\n }\n visitNodes(node.children, source, edits, filePath, context);\n }\n }\n}\n\nfunction collectTagRenames(element: TmplAstElement, source: string, edits: Edit[]): void {\n // Rename opening tag\n const openStart = element.startSourceSpan.start.offset + 1; // skip '<'\n edits.push({ start: openStart, end: openStart + OLD_TAG.length, replacement: NEW_TAG });\n\n // Rename closing tag\n if (element.endSourceSpan) {\n const closeStart = element.endSourceSpan.start.offset + 2; // skip '</'\n edits.push({ start: closeStart, end: closeStart + OLD_TAG.length, replacement: NEW_TAG });\n }\n}\n\nfunction collectOutputRemovals(\n element: TmplAstElement,\n source: string,\n edits: Edit[],\n filePath: string,\n context: SchematicContext,\n): void {\n for (const output of element.outputs) {\n if (output.name === REMOVED_OUTPUT) {\n let start = output.sourceSpan.start.offset;\n // Remove leading whitespace\n while (start > 0 && (source[start - 1] === ' ' || source[start - 1] === '\\t')) {\n start--;\n }\n edits.push({ start, end: output.sourceSpan.end.offset, replacement: '' });\n\n const { line } = element.startSourceSpan.start;\n context.logger.warn(\n `${filePath}:${line + 1} - \"(menuItemClick)\" has been removed. There is no equivalent on eui-toolbar-mega-menu.`,\n );\n }\n }\n}\n\nfunction isTemplateProperty(node: ts.PropertyAssignment): boolean {\n const name = node.name;\n return (ts.isIdentifier(name) && name.text === 'template') || (ts.isStringLiteral(name) && name.text === 'template');\n}\n\nfunction isComponentMetadataProperty(node: ts.PropertyAssignment): boolean {\n const objectLiteral = node.parent;\n if (!ts.isObjectLiteralExpression(objectLiteral)) return false;\n const callExpression = objectLiteral.parent;\n if (!ts.isCallExpression(callExpression) || callExpression.arguments[0] !== objectLiteral) return false;\n return ts.isDecorator(callExpression.parent) && ts.isIdentifier(callExpression.expression) && callExpression.expression.text === 'Component';\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n // Deduplicate edits at same position (e.g. module path edits when both Component and ToolbarItem are from same source)\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n // Last wins for same range\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.html') && !file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
3052
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface ModuleMapping {\n importPath: string;\n selectors: Record<string, string>;\n}\n\nconst MODULE_MAPPINGS: Record<string, ModuleMapping> = {\n EuiAccordionModule: {\n importPath: '@eui/components/eui-accordion',\n selectors: {\n 'eui-accordion': 'EuiAccordionComponent',\n 'eui-accordion-item': 'EuiAccordionItemComponent',\n euiAccordionItemHeader: 'EuiAccordionItemHeaderDirective',\n },\n },\n EuiAlertModule: {\n importPath: '@eui/components/eui-alert',\n selectors: {\n 'eui-alert': 'EuiAlertComponent',\n euiAlert: 'EuiAlertComponent',\n 'eui-alert-title': 'EuiAlertTitleComponent',\n },\n },\n EuiAutocompleteModule: {\n importPath: '@eui/components/eui-autocomplete',\n selectors: {\n 'eui-autocomplete': 'EuiAutocompleteComponent',\n euiAutocomplete: 'EuiAutocompleteComponent',\n 'eui-autocomplete-option': 'EuiAutocompleteOptionComponent',\n 'eui-autocomplete-option-group': 'EuiAutocompleteOptionGroupComponent',\n 'eui-autocomplete-panel': 'EuiAutocompletePanelComponent',\n },\n },\n EuiAvatarModule: {\n importPath: '@eui/components/eui-avatar',\n selectors: {\n 'eui-avatar': 'EuiAvatarComponent',\n euiAvatar: 'EuiAvatarComponent',\n },\n },\n EuiBadgeModule: {\n importPath: '@eui/components/eui-badge',\n selectors: {\n 'eui-badge': 'EuiBadgeComponent',\n euiBadge: 'EuiBadgeComponent',\n },\n },\n EuiBlockContentModule: {\n importPath: '@eui/components/eui-block-content',\n selectors: {\n 'eui-block-content': 'EuiBlockContentComponent',\n },\n },\n EuiBreadcrumbModule: {\n importPath: '@eui/components/eui-breadcrumb',\n selectors: {\n 'eui-breadcrumb': 'EuiBreadcrumbComponent',\n },\n },\n EuiButtonModule: {\n importPath: '@eui/components/eui-button',\n selectors: {\n euiButton: 'EuiButtonComponent',\n },\n },\n EuiButtonGroupModule: {\n importPath: '@eui/components/eui-button-group',\n selectors: {\n 'eui-button-group': 'EuiButtonGroupComponent',\n },\n },\n EuiCardModule: {\n importPath: '@eui/components/eui-card',\n selectors: {\n 'eui-card': 'EuiCardComponent',\n 'eui-card-header': 'EuiCardHeaderComponent',\n 'eui-card-header-title': 'EuiCardHeaderTitleComponent',\n 'eui-card-content': 'EuiCardContentComponent',\n 'eui-card-footer': 'EuiCardFooterComponent',\n 'eui-card-media': 'EuiCardMediaComponent',\n },\n },\n EuiChipModule: {\n importPath: '@eui/components/eui-chip',\n selectors: {\n 'eui-chip': 'EuiChipComponent',\n euiChip: 'EuiChipComponent',\n },\n },\n EuiChipListModule: {\n importPath: '@eui/components/eui-chip-list',\n selectors: {\n 'eui-chip-list': 'EuiChipListComponent',\n },\n },\n EuiChipGroupModule: {\n importPath: '@eui/components/eui-chip-group',\n selectors: {\n 'eui-chip-group': 'EuiChipGroupComponent',\n },\n },\n EuiDashboardCardModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDashboardButtonModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDatepickerModule: {\n importPath: '@eui/components/eui-datepicker',\n selectors: {\n 'eui-datepicker': 'EuiDatepickerComponent',\n },\n },\n EuiDateRangeSelectorModule: {\n importPath: '@eui/components/eui-date-range-selector',\n selectors: {\n 'eui-date-range-selector': 'EuiDateRangeSelectorComponent',\n },\n },\n EuiDialogModule: {\n importPath: '@eui/components/eui-dialog',\n selectors: {\n 'eui-dialog': 'EuiDialogComponent',\n 'eui-dialog-header': 'EuiDialogHeaderDirective',\n 'eui-dialog-footer': 'EuiDialogFooterDirective',\n 'eui-dialog-container': 'EuiDialogContainerComponent',\n },\n },\n EuiDisableContentModule: {\n importPath: '@eui/components/eui-disable-content',\n selectors: {\n 'eui-disable-content': 'EuiDisableContentComponent',\n },\n },\n EuiDiscussionThreadModule: {\n importPath: '@eui/components/eui-discussion-thread',\n selectors: {\n 'eui-discussion-thread': 'EuiDiscussionThreadComponent',\n 'eui-discussion-thread-item': 'EuiDiscussionThreadItemComponent',\n },\n },\n EuiDropdownModule: {\n importPath: '@eui/components/eui-dropdown',\n selectors: {\n 'eui-dropdown': 'EuiDropdownComponent',\n },\n },\n EuiFeedbackMessageModule: {\n importPath: '@eui/components/eui-feedback-message',\n selectors: {\n 'eui-feedback-message': 'EuiFeedbackMessageComponent',\n },\n },\n EuiFieldsetModule: {\n importPath: '@eui/components/eui-fieldset',\n selectors: {\n 'eui-fieldset': 'EuiFieldsetComponent',\n euiFieldsetLabelRightContent: 'EuiFieldsetLabelRightContentTagDirective',\n euiFieldsetLabelExtraContent: 'EuiFieldsetLabelExtraContentTagDirective',\n },\n },\n EuiFileUploadModule: {\n importPath: '@eui/components/eui-file-upload',\n selectors: {\n 'eui-file-upload': 'EuiFileUploadComponent',\n },\n },\n EuiGrowlModule: {\n importPath: '@eui/components/eui-growl',\n selectors: {\n 'eui-growl': 'EuiGrowlComponent',\n },\n },\n EuiIconModule: {\n importPath: '@eui/components/eui-icon',\n selectors: {\n 'eui-icon-svg': 'EuiIconSvgComponent',\n euiIconSvg: 'EuiIconSvgComponent',\n },\n },\n EuiIconButtonModule: {\n importPath: '@eui/components/eui-icon-button',\n selectors: {\n 'eui-icon-button': 'EuiIconButtonComponent',\n },\n },\n EuiIconToggleModule: {\n importPath: '@eui/components/eui-icon-toggle',\n selectors: {\n 'eui-icon-toggle': 'EuiIconToggleComponent',\n },\n },\n EuiInputCheckboxModule: {\n importPath: '@eui/components/eui-input-checkbox',\n selectors: {\n euiInputCheckBox: 'EuiInputCheckboxComponent',\n },\n },\n EuiInputGroupModule: {\n importPath: '@eui/components/eui-input-group',\n selectors: {\n euiInputGroup: 'EuiInputGroupComponent',\n 'eui-input-group-addon': 'EuiInputGroupAddOnComponent',\n euiInputGroupAddOn: 'EuiInputGroupAddOnComponent',\n 'eui-input-group-addon-item': 'EuiInputGroupAddOnItemComponent',\n euiInputGroupAddOnItem: 'EuiInputGroupAddOnItemComponent',\n },\n },\n EuiInputNumberModule: {\n importPath: '@eui/components/eui-input-number',\n selectors: {\n euiInputNumber: 'EuiInputNumberComponent',\n },\n },\n EuiInputRadioModule: {\n importPath: '@eui/components/eui-input-radio',\n selectors: {\n euiInputRadio: 'EuiInputRadioComponent',\n },\n },\n EuiInputTextModule: {\n importPath: '@eui/components/eui-input-text',\n selectors: {\n euiInputText: 'EuiInputTextComponent',\n },\n },\n EuiLabelModule: {\n importPath: '@eui/components/eui-label',\n selectors: {\n 'eui-label': 'EuiLabelComponent',\n euiLabel: 'EuiLabelComponent',\n },\n },\n EuiListModule: {\n importPath: '@eui/components/eui-list',\n selectors: {\n 'eui-list': 'EuiListComponent',\n euiList: 'EuiListComponent',\n 'eui-list-item': 'EuiListItemComponent',\n euiListItem: 'EuiListItemComponent',\n },\n },\n EuiMenuModule: {\n importPath: '@eui/components/eui-menu',\n selectors: {\n 'eui-menu': 'EuiMenuComponent',\n 'eui-menu-item': 'EuiMenuItemComponent',\n },\n },\n EuiMessageBoxModule: {\n importPath: '@eui/components/eui-message-box',\n selectors: {\n 'eui-message-box': 'EuiMessageBoxComponent',\n 'eui-message-box-footer': 'EuiMessageBoxFooterDirective',\n },\n },\n EuiOverlayModule: {\n importPath: '@eui/components/eui-overlay',\n selectors: {\n 'eui-overlay': 'EuiOverlayComponent',\n },\n },\n EuiPageModule: {\n importPath: '@eui/components/eui-page',\n selectors: {\n 'eui-page': 'EuiPageComponent',\n },\n },\n EuiPaginatorModule: {\n importPath: '@eui/components/eui-paginator',\n selectors: {\n 'eui-paginator': 'EuiPaginatorComponent',\n },\n },\n EuiPopoverModule: {\n importPath: '@eui/components/eui-popover',\n selectors: {\n 'eui-popover': 'EuiPopoverComponent',\n },\n },\n EuiProgressBarModule: {\n importPath: '@eui/components/eui-progress-bar',\n selectors: {\n 'eui-progress-bar': 'EuiProgressBarComponent',\n },\n },\n EuiProgressCircleModule: {\n importPath: '@eui/components/eui-progress-circle',\n selectors: {\n 'eui-progress-circle': 'EuiProgressCircleComponent',\n },\n },\n EuiSelectModule: {\n importPath: '@eui/components/eui-select',\n selectors: {\n euiSelect: 'EuiSelectComponent',\n },\n },\n EuiSidebarMenuModule: {\n importPath: '@eui/components/eui-sidebar-menu',\n selectors: {\n 'eui-sidebar-menu': 'EuiSidebarMenuComponent',\n },\n },\n EuiSkeletonModule: {\n importPath: '@eui/components/eui-skeleton',\n selectors: {\n 'eui-skeleton': 'EuiSkeletonComponent',\n },\n },\n EuiSlideToggleModule: {\n importPath: '@eui/components/eui-slide-toggle',\n selectors: {\n 'eui-slide-toggle': 'EuiSlideToggleComponent',\n },\n },\n EuiTableModule: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTableV2Module: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTabsModule: {\n importPath: '@eui/components/eui-tabs',\n selectors: {\n 'eui-tabs': 'EuiTabsComponent',\n 'eui-tab': 'EuiTabComponent',\n 'eui-tab-header': 'EuiTabHeaderComponent',\n 'eui-tab-body': 'EuiTabBodyComponent',\n },\n },\n EuiTextAreaModule: {\n importPath: '@eui/components/eui-textarea',\n selectors: {\n euiTextArea: 'EuiTextareaComponent',\n },\n },\n EuiTimelineModule: {\n importPath: '@eui/components/eui-timeline',\n selectors: {\n 'eui-timeline': 'EuiTimelineComponent',\n 'eui-timeline-item': 'EuiTimelineItemComponent',\n },\n },\n EuiTimepickerModule: {\n importPath: '@eui/components/eui-timepicker',\n selectors: {\n 'eui-timepicker': 'EuiTimepickerComponent',\n },\n },\n EuiTreeModule: {\n importPath: '@eui/components/eui-tree',\n selectors: {\n 'eui-tree': 'EuiTreeComponent',\n },\n },\n EuiTreeListModule: {\n importPath: '@eui/components/eui-tree-list',\n selectors: {\n 'eui-tree-list': 'EuiTreeListComponent',\n 'eui-tree-list-item': 'EuiTreeListItemComponent',\n },\n },\n EuiUserProfileModule: {\n importPath: '@eui/components/eui-user-profile',\n selectors: {\n 'eui-user-profile': 'EuiUserProfileComponent',\n },\n },\n EuiWizardModule: {\n importPath: '@eui/components/eui-wizard',\n selectors: {\n 'eui-wizard': 'EuiWizardComponent',\n 'eui-wizard-step': 'EuiWizardStepComponent',\n },\n },\n EuiTooltipDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTooltip: 'EuiTooltipDirective',\n },\n },\n EuiTemplateDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTemplate: 'EuiTemplateDirective',\n },\n },\n EuiResizableDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiResizable: 'EuiResizableDirective',\n 'eui-resizable': 'EuiResizableComponent',\n },\n },\n EuiMaxLengthDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiEditorMaxlength: 'EuiMaxLengthDirective',\n },\n },\n EuiTruncatePipeModule: {\n importPath: '@eui/components/pipes',\n selectors: {\n euiTruncate: 'EuiTruncatePipe',\n },\n },\n EuiLayoutModule: {\n importPath: '@eui/components/layout',\n selectors: {\n 'eui-app': 'EuiAppComponent',\n 'eui-header': 'EuiHeaderComponent',\n 'eui-footer': 'EuiFooterComponent',\n 'eui-toolbar': 'EuiToolbarComponent',\n 'eui-sidebar-toggle': 'EuiSidebarToggleComponent',\n },\n },\n};\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateToStandalone(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const allModuleNames = Object.keys(MODULE_MAPPINGS);\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!allModuleNames.some((m) => source.includes(m))) return;\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const componentDecorators = findComponentDecorators(sourceFile);\n\n for (const decorator of componentDecorators) {\n const importsNode = findImportsArrayNode(decorator);\n if (!importsNode) continue;\n\n const currentSource = tree.read(path)!.toString('utf-8');\n const modulesInArray = allModuleNames.filter((m) => hasModuleInArray(importsNode, m, source));\n if (modulesInArray.length === 0) continue;\n\n const templateSelectors = getTemplateSelectors(tree, path, decorator, source);\n const replacements = buildReplacements(modulesInArray, templateSelectors);\n if (replacements.size === 0) continue;\n\n const result = applyReplacements(currentSource, path, replacements);\n if (options.dryRun) {\n logDryRun(context, `Would replace module imports with standalone imports in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n }\n });\n\n context.logger.info('Migration to standalone imports complete.');\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction buildReplacements(moduleNames: string[], templateSelectors: Set<string>): Map<string, { components: string[]; importPath: string }> {\n const map = new Map<string, { components: string[]; importPath: string }>();\n\n for (const moduleName of moduleNames) {\n const mapping = MODULE_MAPPINGS[moduleName];\n const components: string[] = [];\n\n for (const [selector, component] of Object.entries(mapping.selectors)) {\n if (templateSelectors.has(selector)) {\n components.push(component);\n }\n }\n\n if (components.length > 0) {\n map.set(moduleName, { components: [...new Set(components)].sort(), importPath: mapping.importPath });\n }\n }\n\n return map;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ts.Decorator[] {\n const decorators: ts.Decorator[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n decorators.push(dec);\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return decorators;\n}\n\nfunction findImportsArrayNode(decorator: ts.Decorator): ts.ArrayLiteralExpression | undefined {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) return undefined;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer;\n }\n }\n }\n return undefined;\n}\n\nfunction hasModuleInArray(array: ts.ArrayLiteralExpression, moduleName: string, source: string): boolean {\n return array.elements.some((el) => source.slice(el.getStart(), el.getEnd()).trim() === moduleName);\n}\n\nfunction getTemplateSelectors(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): Set<string> {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0] as ts.ObjectLiteralExpression;\n const allSelectors = Object.values(MODULE_MAPPINGS).flatMap((m) => Object.keys(m.selectors));\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return findSelectorsInTemplate(init.text, allSelectors);\n }\n }\n }\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) {\n return findSelectorsInTemplate(templateBuffer.toString('utf-8'), allSelectors);\n }\n }\n }\n }\n\n return new Set();\n}\n\nfunction findSelectorsInTemplate(html: string, knownSelectors: string[]): Set<string> {\n const selectors = new Set<string>();\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n\n const visit = (nodes: TmplAstNode[]): void => {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (knownSelectors.includes(node.name)) selectors.add(node.name);\n for (const attr of node.attributes) {\n if (knownSelectors.includes(attr.name)) selectors.add(attr.name);\n }\n visit(node.children);\n }\n }\n };\n visit(parsed.nodes);\n return selectors;\n}\n\nfunction applyReplacements(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n let result = replaceInImportsArray(source, sourceFile, replacements);\n result = updateEsImports(result, filePath, replacements);\n return result;\n}\n\nfunction replaceInImportsArray(source: string, sourceFile: ts.SourceFile, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression) || !ts.isIdentifier(dec.expression.expression) || dec.expression.expression.text !== 'Component') continue;\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'imports') continue;\n if (!ts.isArrayLiteralExpression(prop.initializer)) continue;\n const newElements = prop.initializer.elements\n .map((el) => {\n const text = result.slice(el.getStart(sourceFile), el.getEnd()).trim();\n const replacement = replacements.get(text);\n return replacement ? replacement.components.join(', ') : text;\n })\n .join(', ');\n result = result.slice(0, prop.initializer.getStart(sourceFile) + 1) + newElements + result.slice(prop.initializer.getEnd() - 1);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return result;\n}\n\nfunction updateEsImports(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n\n for (const [moduleName, { components, importPath }] of replacements) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const importNames = namedBindings.elements.map((el) => el.name.text);\n if (!importNames.includes(moduleName)) continue;\n\n const moduleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const remaining = importNames.filter((n) => n !== moduleName);\n const toAdd = components.filter((c) => !importNames.includes(c));\n\n if (moduleSpecifier === importPath) {\n const newNames = [...remaining, ...toAdd].sort();\n const newClause = `{ ${newNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n if (remaining.length > 0) {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n }\n\n if (toAdd.length > 0) {\n const updatedSf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n const existing = updatedSf.statements.find(\n (s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n ) as ts.ImportDeclaration | undefined;\n\n if (existing?.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {\n const existingNames = existing.importClause.namedBindings.elements.map((el) => el.name.text);\n const allNames = [...new Set([...existingNames, ...toAdd])].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, existing.importClause.namedBindings.getStart(updatedSf)) + newClause + result.slice(existing.importClause.namedBindings.getEnd());\n } else {\n const newImport = `import { ${toAdd.join(', ')} } from '${importPath}';\\n`;\n result = newImport + result;\n }\n }\n }\n break;\n }\n }\n\n return result;\n}\n",
3053
3053
  "displayName": "Schema",
3054
3054
  "properties": [
3055
3055
  {
@@ -3061,7 +3061,7 @@
3061
3061
  "indexKey": "",
3062
3062
  "optional": true,
3063
3063
  "description": "",
3064
- "line": 18,
3064
+ "line": 460,
3065
3065
  "rawdescription": "\n"
3066
3066
  },
3067
3067
  {
@@ -3073,7 +3073,7 @@
3073
3073
  "indexKey": "",
3074
3074
  "optional": true,
3075
3075
  "description": "",
3076
- "line": 17,
3076
+ "line": 459,
3077
3077
  "rawdescription": "\n"
3078
3078
  }
3079
3079
  ],
@@ -22081,23 +22081,23 @@
22081
22081
  "name": "COMPONENT_TAG",
22082
22082
  "ctype": "miscellaneous",
22083
22083
  "subtype": "variable",
22084
- "file": "packages/core/schematics/migrate-eui-editor/index.ts",
22084
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
22085
22085
  "coverageIgnore": false,
22086
22086
  "deprecated": false,
22087
22087
  "deprecationMessage": "",
22088
22088
  "type": "string",
22089
- "defaultValue": "'eui-editor'"
22089
+ "defaultValue": "'eui-discussion-thread'"
22090
22090
  },
22091
22091
  {
22092
22092
  "name": "COMPONENT_TAG",
22093
22093
  "ctype": "miscellaneous",
22094
22094
  "subtype": "variable",
22095
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
22095
+ "file": "packages/core/schematics/migrate-eui-editor/index.ts",
22096
22096
  "coverageIgnore": false,
22097
22097
  "deprecated": false,
22098
22098
  "deprecationMessage": "",
22099
22099
  "type": "string",
22100
- "defaultValue": "'eui-discussion-thread'"
22100
+ "defaultValue": "'eui-editor'"
22101
22101
  },
22102
22102
  {
22103
22103
  "name": "COMPONENT_TAG",
@@ -22976,23 +22976,23 @@
22976
22976
  "name": "NEW_INTERFACE",
22977
22977
  "ctype": "miscellaneous",
22978
22978
  "subtype": "variable",
22979
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
22979
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
22980
22980
  "coverageIgnore": false,
22981
22981
  "deprecated": false,
22982
22982
  "deprecationMessage": "",
22983
22983
  "type": "string",
22984
- "defaultValue": "'EuiTooltipInterface'"
22984
+ "defaultValue": "'EuiMenuItem'"
22985
22985
  },
22986
22986
  {
22987
22987
  "name": "NEW_INTERFACE",
22988
22988
  "ctype": "miscellaneous",
22989
22989
  "subtype": "variable",
22990
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
22990
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
22991
22991
  "coverageIgnore": false,
22992
22992
  "deprecated": false,
22993
22993
  "deprecationMessage": "",
22994
22994
  "type": "string",
22995
- "defaultValue": "'EuiMenuItem'"
22995
+ "defaultValue": "'EuiTooltipInterface'"
22996
22996
  },
22997
22997
  {
22998
22998
  "name": "NEW_INTERFACE_PATH",
@@ -24416,7 +24416,7 @@
24416
24416
  },
24417
24417
  {
24418
24418
  "name": "applyEdits",
24419
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
24419
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
24420
24420
  "ctype": "miscellaneous",
24421
24421
  "subtype": "function",
24422
24422
  "coverageIgnore": false,
@@ -24461,7 +24461,7 @@
24461
24461
  },
24462
24462
  {
24463
24463
  "name": "applyEdits",
24464
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
24464
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
24465
24465
  "ctype": "miscellaneous",
24466
24466
  "subtype": "function",
24467
24467
  "coverageIgnore": false,
@@ -24506,7 +24506,7 @@
24506
24506
  },
24507
24507
  {
24508
24508
  "name": "applyEdits",
24509
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
24509
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
24510
24510
  "ctype": "miscellaneous",
24511
24511
  "subtype": "function",
24512
24512
  "coverageIgnore": false,
@@ -24596,7 +24596,7 @@
24596
24596
  },
24597
24597
  {
24598
24598
  "name": "applyEdits",
24599
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
24599
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
24600
24600
  "ctype": "miscellaneous",
24601
24601
  "subtype": "function",
24602
24602
  "coverageIgnore": false,
@@ -25998,7 +25998,7 @@
25998
25998
  },
25999
25999
  {
26000
26000
  "name": "collectRenames",
26001
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
26001
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
26002
26002
  "ctype": "miscellaneous",
26003
26003
  "subtype": "function",
26004
26004
  "coverageIgnore": false,
@@ -26043,7 +26043,7 @@
26043
26043
  },
26044
26044
  {
26045
26045
  "name": "collectRenames",
26046
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
26046
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
26047
26047
  "ctype": "miscellaneous",
26048
26048
  "subtype": "function",
26049
26049
  "coverageIgnore": false,
@@ -26576,7 +26576,7 @@
26576
26576
  },
26577
26577
  {
26578
26578
  "name": "deduplicateEdits",
26579
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
26579
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
26580
26580
  "ctype": "miscellaneous",
26581
26581
  "subtype": "function",
26582
26582
  "coverageIgnore": false,
@@ -26606,7 +26606,7 @@
26606
26606
  },
26607
26607
  {
26608
26608
  "name": "deduplicateEdits",
26609
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
26609
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
26610
26610
  "ctype": "miscellaneous",
26611
26611
  "subtype": "function",
26612
26612
  "coverageIgnore": false,
@@ -29339,7 +29339,7 @@
29339
29339
  },
29340
29340
  {
29341
29341
  "name": "isComponentMetadataProperty",
29342
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
29342
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
29343
29343
  "ctype": "miscellaneous",
29344
29344
  "subtype": "function",
29345
29345
  "coverageIgnore": false,
@@ -29369,7 +29369,7 @@
29369
29369
  },
29370
29370
  {
29371
29371
  "name": "isComponentMetadataProperty",
29372
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
29372
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
29373
29373
  "ctype": "miscellaneous",
29374
29374
  "subtype": "function",
29375
29375
  "coverageIgnore": false,
@@ -29399,7 +29399,7 @@
29399
29399
  },
29400
29400
  {
29401
29401
  "name": "isComponentMetadataProperty",
29402
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
29402
+ "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
29403
29403
  "ctype": "miscellaneous",
29404
29404
  "subtype": "function",
29405
29405
  "coverageIgnore": false,
@@ -29429,7 +29429,7 @@
29429
29429
  },
29430
29430
  {
29431
29431
  "name": "isComponentMetadataProperty",
29432
- "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
29432
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
29433
29433
  "ctype": "miscellaneous",
29434
29434
  "subtype": "function",
29435
29435
  "coverageIgnore": false,
@@ -29459,7 +29459,7 @@
29459
29459
  },
29460
29460
  {
29461
29461
  "name": "isComponentMetadataProperty",
29462
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
29462
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
29463
29463
  "ctype": "miscellaneous",
29464
29464
  "subtype": "function",
29465
29465
  "coverageIgnore": false,
@@ -29884,7 +29884,7 @@
29884
29884
  },
29885
29885
  {
29886
29886
  "name": "isTemplateProperty",
29887
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
29887
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
29888
29888
  "ctype": "miscellaneous",
29889
29889
  "subtype": "function",
29890
29890
  "coverageIgnore": false,
@@ -29914,7 +29914,7 @@
29914
29914
  },
29915
29915
  {
29916
29916
  "name": "isTemplateProperty",
29917
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
29917
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
29918
29918
  "ctype": "miscellaneous",
29919
29919
  "subtype": "function",
29920
29920
  "coverageIgnore": false,
@@ -29944,7 +29944,7 @@
29944
29944
  },
29945
29945
  {
29946
29946
  "name": "isTemplateProperty",
29947
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
29947
+ "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
29948
29948
  "ctype": "miscellaneous",
29949
29949
  "subtype": "function",
29950
29950
  "coverageIgnore": false,
@@ -29974,7 +29974,7 @@
29974
29974
  },
29975
29975
  {
29976
29976
  "name": "isTemplateProperty",
29977
- "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
29977
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
29978
29978
  "ctype": "miscellaneous",
29979
29979
  "subtype": "function",
29980
29980
  "coverageIgnore": false,
@@ -30004,7 +30004,7 @@
30004
30004
  },
30005
30005
  {
30006
30006
  "name": "isTemplateProperty",
30007
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
30007
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
30008
30008
  "ctype": "miscellaneous",
30009
30009
  "subtype": "function",
30010
30010
  "coverageIgnore": false,
@@ -31728,7 +31728,7 @@
31728
31728
  },
31729
31729
  {
31730
31730
  "name": "migrateInlineTemplates",
31731
- "file": "packages/core/schematics/migrate-eui-editor/index.ts",
31731
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
31732
31732
  "ctype": "miscellaneous",
31733
31733
  "subtype": "function",
31734
31734
  "coverageIgnore": false,
@@ -31760,7 +31760,7 @@
31760
31760
  },
31761
31761
  {
31762
31762
  "name": "migrateInlineTemplates",
31763
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
31763
+ "file": "packages/core/schematics/migrate-eui-editor/index.ts",
31764
31764
  "ctype": "miscellaneous",
31765
31765
  "subtype": "function",
31766
31766
  "coverageIgnore": false,
@@ -31854,38 +31854,6 @@
31854
31854
  }
31855
31855
  ]
31856
31856
  },
31857
- {
31858
- "name": "migrateInlineTemplates",
31859
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
31860
- "ctype": "miscellaneous",
31861
- "subtype": "function",
31862
- "coverageIgnore": false,
31863
- "deprecated": false,
31864
- "deprecationMessage": "",
31865
- "rawdescription": "",
31866
- "description": "",
31867
- "displayName": "migrateInlineTemplates",
31868
- "args": [
31869
- {
31870
- "name": "source",
31871
- "type": "string",
31872
- "deprecated": false,
31873
- "deprecationMessage": ""
31874
- }
31875
- ],
31876
- "returnType": "string",
31877
- "jsdoctags": [
31878
- {
31879
- "name": "source",
31880
- "type": "string",
31881
- "deprecated": false,
31882
- "deprecationMessage": "",
31883
- "tagName": {
31884
- "text": "param"
31885
- }
31886
- }
31887
- ]
31888
- },
31889
31857
  {
31890
31858
  "name": "migrateInlineTemplates",
31891
31859
  "file": "packages/core/schematics/migrate-eui-popover/index.ts",
@@ -32075,8 +32043,8 @@
32075
32043
  ]
32076
32044
  },
32077
32045
  {
32078
- "name": "migrateTemplate",
32079
- "file": "packages/core/schematics/migrate-eui-accent/index.ts",
32046
+ "name": "migrateInlineTemplates",
32047
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
32080
32048
  "ctype": "miscellaneous",
32081
32049
  "subtype": "function",
32082
32050
  "coverageIgnore": false,
@@ -32084,7 +32052,7 @@
32084
32052
  "deprecationMessage": "",
32085
32053
  "rawdescription": "",
32086
32054
  "description": "",
32087
- "displayName": "migrateTemplate",
32055
+ "displayName": "migrateInlineTemplates",
32088
32056
  "args": [
32089
32057
  {
32090
32058
  "name": "source",
@@ -32108,7 +32076,7 @@
32108
32076
  },
32109
32077
  {
32110
32078
  "name": "migrateTemplate",
32111
- "file": "packages/core/schematics/migrate-eui-alert/index.ts",
32079
+ "file": "packages/core/schematics/migrate-eui-accent/index.ts",
32112
32080
  "ctype": "miscellaneous",
32113
32081
  "subtype": "function",
32114
32082
  "coverageIgnore": false,
@@ -32140,7 +32108,7 @@
32140
32108
  },
32141
32109
  {
32142
32110
  "name": "migrateTemplate",
32143
- "file": "packages/core/schematics/migrate-eui-avatar/index.ts",
32111
+ "file": "packages/core/schematics/migrate-eui-alert/index.ts",
32144
32112
  "ctype": "miscellaneous",
32145
32113
  "subtype": "function",
32146
32114
  "coverageIgnore": false,
@@ -32172,7 +32140,7 @@
32172
32140
  },
32173
32141
  {
32174
32142
  "name": "migrateTemplate",
32175
- "file": "packages/core/schematics/migrate-eui-button/index.ts",
32143
+ "file": "packages/core/schematics/migrate-eui-avatar/index.ts",
32176
32144
  "ctype": "miscellaneous",
32177
32145
  "subtype": "function",
32178
32146
  "coverageIgnore": false,
@@ -32204,7 +32172,7 @@
32204
32172
  },
32205
32173
  {
32206
32174
  "name": "migrateTemplate",
32207
- "file": "packages/core/schematics/migrate-eui-chip/index.ts",
32175
+ "file": "packages/core/schematics/migrate-eui-button/index.ts",
32208
32176
  "ctype": "miscellaneous",
32209
32177
  "subtype": "function",
32210
32178
  "coverageIgnore": false,
@@ -32236,7 +32204,7 @@
32236
32204
  },
32237
32205
  {
32238
32206
  "name": "migrateTemplate",
32239
- "file": "packages/core/schematics/migrate-eui-chip-list/index.ts",
32207
+ "file": "packages/core/schematics/migrate-eui-chip/index.ts",
32240
32208
  "ctype": "miscellaneous",
32241
32209
  "subtype": "function",
32242
32210
  "coverageIgnore": false,
@@ -32268,7 +32236,7 @@
32268
32236
  },
32269
32237
  {
32270
32238
  "name": "migrateTemplate",
32271
- "file": "packages/core/schematics/migrate-eui-editor/index.ts",
32239
+ "file": "packages/core/schematics/migrate-eui-chip-list/index.ts",
32272
32240
  "ctype": "miscellaneous",
32273
32241
  "subtype": "function",
32274
32242
  "coverageIgnore": false,
@@ -32332,7 +32300,7 @@
32332
32300
  },
32333
32301
  {
32334
32302
  "name": "migrateTemplate",
32335
- "file": "packages/core/schematics/migrate-eui-fieldset/index.ts",
32303
+ "file": "packages/core/schematics/migrate-eui-editor/index.ts",
32336
32304
  "ctype": "miscellaneous",
32337
32305
  "subtype": "function",
32338
32306
  "coverageIgnore": false,
@@ -32364,7 +32332,7 @@
32364
32332
  },
32365
32333
  {
32366
32334
  "name": "migrateTemplate",
32367
- "file": "packages/core/schematics/migrate-eui-icon-svg/index.ts",
32335
+ "file": "packages/core/schematics/migrate-eui-fieldset/index.ts",
32368
32336
  "ctype": "miscellaneous",
32369
32337
  "subtype": "function",
32370
32338
  "coverageIgnore": false,
@@ -32396,7 +32364,7 @@
32396
32364
  },
32397
32365
  {
32398
32366
  "name": "migrateTemplate",
32399
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
32367
+ "file": "packages/core/schematics/migrate-eui-icon-svg/index.ts",
32400
32368
  "ctype": "miscellaneous",
32401
32369
  "subtype": "function",
32402
32370
  "coverageIgnore": false,
@@ -32676,6 +32644,38 @@
32676
32644
  }
32677
32645
  ]
32678
32646
  },
32647
+ {
32648
+ "name": "migrateTemplate",
32649
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
32650
+ "ctype": "miscellaneous",
32651
+ "subtype": "function",
32652
+ "coverageIgnore": false,
32653
+ "deprecated": false,
32654
+ "deprecationMessage": "",
32655
+ "rawdescription": "",
32656
+ "description": "",
32657
+ "displayName": "migrateTemplate",
32658
+ "args": [
32659
+ {
32660
+ "name": "source",
32661
+ "type": "string",
32662
+ "deprecated": false,
32663
+ "deprecationMessage": ""
32664
+ }
32665
+ ],
32666
+ "returnType": "string",
32667
+ "jsdoctags": [
32668
+ {
32669
+ "name": "source",
32670
+ "type": "string",
32671
+ "deprecated": false,
32672
+ "deprecationMessage": "",
32673
+ "tagName": {
32674
+ "text": "param"
32675
+ }
32676
+ }
32677
+ ]
32678
+ },
32679
32679
  {
32680
32680
  "name": "migrateTemplateWithPaginator",
32681
32681
  "file": "packages/core/schematics/migrate-eui-table/index.ts",
@@ -32836,7 +32836,7 @@
32836
32836
  },
32837
32837
  {
32838
32838
  "name": "migrateTypeScript",
32839
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
32839
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
32840
32840
  "ctype": "miscellaneous",
32841
32841
  "subtype": "function",
32842
32842
  "coverageIgnore": false,
@@ -32898,7 +32898,7 @@
32898
32898
  },
32899
32899
  {
32900
32900
  "name": "migrateTypeScript",
32901
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
32901
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
32902
32902
  "ctype": "miscellaneous",
32903
32903
  "subtype": "function",
32904
32904
  "coverageIgnore": false,
@@ -33337,7 +33337,7 @@
33337
33337
  },
33338
33338
  {
33339
33339
  "name": "removeImportSpecifier",
33340
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
33340
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
33341
33341
  "ctype": "miscellaneous",
33342
33342
  "subtype": "function",
33343
33343
  "coverageIgnore": false,
@@ -33406,7 +33406,7 @@
33406
33406
  },
33407
33407
  {
33408
33408
  "name": "removeImportSpecifier",
33409
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
33409
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
33410
33410
  "ctype": "miscellaneous",
33411
33411
  "subtype": "function",
33412
33412
  "coverageIgnore": false,
@@ -34486,7 +34486,7 @@
34486
34486
  },
34487
34487
  {
34488
34488
  "name": "unwrapExpression",
34489
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
34489
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
34490
34490
  "ctype": "miscellaneous",
34491
34491
  "subtype": "function",
34492
34492
  "coverageIgnore": false,
@@ -34516,7 +34516,7 @@
34516
34516
  },
34517
34517
  {
34518
34518
  "name": "unwrapExpression",
34519
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
34519
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
34520
34520
  "ctype": "miscellaneous",
34521
34521
  "subtype": "function",
34522
34522
  "coverageIgnore": false,
@@ -34546,7 +34546,7 @@
34546
34546
  },
34547
34547
  {
34548
34548
  "name": "unwrapExpression",
34549
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
34549
+ "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
34550
34550
  "ctype": "miscellaneous",
34551
34551
  "subtype": "function",
34552
34552
  "coverageIgnore": false,
@@ -34576,7 +34576,7 @@
34576
34576
  },
34577
34577
  {
34578
34578
  "name": "unwrapExpression",
34579
- "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
34579
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
34580
34580
  "ctype": "miscellaneous",
34581
34581
  "subtype": "function",
34582
34582
  "coverageIgnore": false,
@@ -34606,7 +34606,7 @@
34606
34606
  },
34607
34607
  {
34608
34608
  "name": "unwrapExpression",
34609
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
34609
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
34610
34610
  "ctype": "miscellaneous",
34611
34611
  "subtype": "function",
34612
34612
  "coverageIgnore": false,
@@ -35189,7 +35189,7 @@
35189
35189
  },
35190
35190
  {
35191
35191
  "name": "visitDir",
35192
- "file": "packages/core/schematics/migrate-eui-editor/index.ts",
35192
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
35193
35193
  "ctype": "miscellaneous",
35194
35194
  "subtype": "function",
35195
35195
  "coverageIgnore": false,
@@ -35234,7 +35234,7 @@
35234
35234
  },
35235
35235
  {
35236
35236
  "name": "visitDir",
35237
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
35237
+ "file": "packages/core/schematics/migrate-eui-editor/index.ts",
35238
35238
  "ctype": "miscellaneous",
35239
35239
  "subtype": "function",
35240
35240
  "coverageIgnore": false,
@@ -35369,7 +35369,7 @@
35369
35369
  },
35370
35370
  {
35371
35371
  "name": "visitDir",
35372
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
35372
+ "file": "packages/core/schematics/migrate-eui-popover/index.ts",
35373
35373
  "ctype": "miscellaneous",
35374
35374
  "subtype": "function",
35375
35375
  "coverageIgnore": false,
@@ -35414,7 +35414,7 @@
35414
35414
  },
35415
35415
  {
35416
35416
  "name": "visitDir",
35417
- "file": "packages/core/schematics/migrate-eui-popover/index.ts",
35417
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
35418
35418
  "ctype": "miscellaneous",
35419
35419
  "subtype": "function",
35420
35420
  "coverageIgnore": false,
@@ -35459,7 +35459,7 @@
35459
35459
  },
35460
35460
  {
35461
35461
  "name": "visitDir",
35462
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
35462
+ "file": "packages/core/schematics/migrate-eui-table/index.ts",
35463
35463
  "ctype": "miscellaneous",
35464
35464
  "subtype": "function",
35465
35465
  "coverageIgnore": false,
@@ -35504,7 +35504,7 @@
35504
35504
  },
35505
35505
  {
35506
35506
  "name": "visitDir",
35507
- "file": "packages/core/schematics/migrate-eui-table/index.ts",
35507
+ "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
35508
35508
  "ctype": "miscellaneous",
35509
35509
  "subtype": "function",
35510
35510
  "coverageIgnore": false,
@@ -35549,7 +35549,7 @@
35549
35549
  },
35550
35550
  {
35551
35551
  "name": "visitDir",
35552
- "file": "packages/core/schematics/migrate-eui-tabs/index.ts",
35552
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
35553
35553
  "ctype": "miscellaneous",
35554
35554
  "subtype": "function",
35555
35555
  "coverageIgnore": false,
@@ -35639,7 +35639,7 @@
35639
35639
  },
35640
35640
  {
35641
35641
  "name": "visitDir",
35642
- "file": "packages/core/schematics/migrate-to-standalone/index.ts",
35642
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
35643
35643
  "ctype": "miscellaneous",
35644
35644
  "subtype": "function",
35645
35645
  "coverageIgnore": false,
@@ -35684,7 +35684,7 @@
35684
35684
  },
35685
35685
  {
35686
35686
  "name": "visitDir",
35687
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
35687
+ "file": "packages/core/schematics/migrate-to-standalone/index.ts",
35688
35688
  "ctype": "miscellaneous",
35689
35689
  "subtype": "function",
35690
35690
  "coverageIgnore": false,
@@ -36045,6 +36045,64 @@
36045
36045
  }
36046
36046
  ]
36047
36047
  },
36048
+ {
36049
+ "name": "visitNodes",
36050
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
36051
+ "ctype": "miscellaneous",
36052
+ "subtype": "function",
36053
+ "coverageIgnore": false,
36054
+ "deprecated": false,
36055
+ "deprecationMessage": "",
36056
+ "rawdescription": "",
36057
+ "description": "",
36058
+ "displayName": "visitNodes",
36059
+ "args": [
36060
+ {
36061
+ "name": "nodes",
36062
+ "deprecated": false,
36063
+ "deprecationMessage": ""
36064
+ },
36065
+ {
36066
+ "name": "source",
36067
+ "type": "string",
36068
+ "deprecated": false,
36069
+ "deprecationMessage": ""
36070
+ },
36071
+ {
36072
+ "name": "removals",
36073
+ "deprecated": false,
36074
+ "deprecationMessage": ""
36075
+ }
36076
+ ],
36077
+ "returnType": "void",
36078
+ "jsdoctags": [
36079
+ {
36080
+ "name": "nodes",
36081
+ "deprecated": false,
36082
+ "deprecationMessage": "",
36083
+ "tagName": {
36084
+ "text": "param"
36085
+ }
36086
+ },
36087
+ {
36088
+ "name": "source",
36089
+ "type": "string",
36090
+ "deprecated": false,
36091
+ "deprecationMessage": "",
36092
+ "tagName": {
36093
+ "text": "param"
36094
+ }
36095
+ },
36096
+ {
36097
+ "name": "removals",
36098
+ "deprecated": false,
36099
+ "deprecationMessage": "",
36100
+ "tagName": {
36101
+ "text": "param"
36102
+ }
36103
+ }
36104
+ ]
36105
+ },
36048
36106
  {
36049
36107
  "name": "visitNodes",
36050
36108
  "file": "packages/core/schematics/migrate-eui-editor/index.ts",
@@ -36090,7 +36148,7 @@
36090
36148
  },
36091
36149
  {
36092
36150
  "name": "visitNodes",
36093
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
36151
+ "file": "packages/core/schematics/migrate-eui-fieldset/index.ts",
36094
36152
  "ctype": "miscellaneous",
36095
36153
  "subtype": "function",
36096
36154
  "coverageIgnore": false,
@@ -36106,13 +36164,50 @@
36106
36164
  "deprecationMessage": ""
36107
36165
  },
36108
36166
  {
36109
- "name": "source",
36110
- "type": "string",
36167
+ "name": "edits",
36111
36168
  "deprecated": false,
36112
36169
  "deprecationMessage": ""
36170
+ }
36171
+ ],
36172
+ "returnType": "void",
36173
+ "jsdoctags": [
36174
+ {
36175
+ "name": "nodes",
36176
+ "deprecated": false,
36177
+ "deprecationMessage": "",
36178
+ "tagName": {
36179
+ "text": "param"
36180
+ }
36113
36181
  },
36114
36182
  {
36115
- "name": "removals",
36183
+ "name": "edits",
36184
+ "deprecated": false,
36185
+ "deprecationMessage": "",
36186
+ "tagName": {
36187
+ "text": "param"
36188
+ }
36189
+ }
36190
+ ]
36191
+ },
36192
+ {
36193
+ "name": "visitNodes",
36194
+ "file": "packages/core/schematics/migrate-eui-icon-svg/index.ts",
36195
+ "ctype": "miscellaneous",
36196
+ "subtype": "function",
36197
+ "coverageIgnore": false,
36198
+ "deprecated": false,
36199
+ "deprecationMessage": "",
36200
+ "rawdescription": "",
36201
+ "description": "",
36202
+ "displayName": "visitNodes",
36203
+ "args": [
36204
+ {
36205
+ "name": "nodes",
36206
+ "deprecated": false,
36207
+ "deprecationMessage": ""
36208
+ },
36209
+ {
36210
+ "name": "edits",
36116
36211
  "deprecated": false,
36117
36212
  "deprecationMessage": ""
36118
36213
  }
@@ -36128,8 +36223,42 @@
36128
36223
  }
36129
36224
  },
36130
36225
  {
36131
- "name": "source",
36132
- "type": "string",
36226
+ "name": "edits",
36227
+ "deprecated": false,
36228
+ "deprecationMessage": "",
36229
+ "tagName": {
36230
+ "text": "param"
36231
+ }
36232
+ }
36233
+ ]
36234
+ },
36235
+ {
36236
+ "name": "visitNodes",
36237
+ "file": "packages/core/schematics/migrate-eui-popover/index.ts",
36238
+ "ctype": "miscellaneous",
36239
+ "subtype": "function",
36240
+ "coverageIgnore": false,
36241
+ "deprecated": false,
36242
+ "deprecationMessage": "",
36243
+ "rawdescription": "",
36244
+ "description": "",
36245
+ "displayName": "visitNodes",
36246
+ "args": [
36247
+ {
36248
+ "name": "nodes",
36249
+ "deprecated": false,
36250
+ "deprecationMessage": ""
36251
+ },
36252
+ {
36253
+ "name": "removals",
36254
+ "deprecated": false,
36255
+ "deprecationMessage": ""
36256
+ }
36257
+ ],
36258
+ "returnType": "void",
36259
+ "jsdoctags": [
36260
+ {
36261
+ "name": "nodes",
36133
36262
  "deprecated": false,
36134
36263
  "deprecationMessage": "",
36135
36264
  "tagName": {
@@ -36148,7 +36277,7 @@
36148
36277
  },
36149
36278
  {
36150
36279
  "name": "visitNodes",
36151
- "file": "packages/core/schematics/migrate-eui-fieldset/index.ts",
36280
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
36152
36281
  "ctype": "miscellaneous",
36153
36282
  "subtype": "function",
36154
36283
  "coverageIgnore": false,
@@ -36191,7 +36320,7 @@
36191
36320
  },
36192
36321
  {
36193
36322
  "name": "visitNodes",
36194
- "file": "packages/core/schematics/migrate-eui-icon-svg/index.ts",
36323
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
36195
36324
  "ctype": "miscellaneous",
36196
36325
  "subtype": "function",
36197
36326
  "coverageIgnore": false,
@@ -36206,10 +36335,28 @@
36206
36335
  "deprecated": false,
36207
36336
  "deprecationMessage": ""
36208
36337
  },
36338
+ {
36339
+ "name": "source",
36340
+ "type": "string",
36341
+ "deprecated": false,
36342
+ "deprecationMessage": ""
36343
+ },
36209
36344
  {
36210
36345
  "name": "edits",
36211
36346
  "deprecated": false,
36212
36347
  "deprecationMessage": ""
36348
+ },
36349
+ {
36350
+ "name": "filePath",
36351
+ "type": "string",
36352
+ "deprecated": false,
36353
+ "deprecationMessage": ""
36354
+ },
36355
+ {
36356
+ "name": "context",
36357
+ "type": "SchematicContext",
36358
+ "deprecated": false,
36359
+ "deprecationMessage": ""
36213
36360
  }
36214
36361
  ],
36215
36362
  "returnType": "void",
@@ -36222,6 +36369,15 @@
36222
36369
  "text": "param"
36223
36370
  }
36224
36371
  },
36372
+ {
36373
+ "name": "source",
36374
+ "type": "string",
36375
+ "deprecated": false,
36376
+ "deprecationMessage": "",
36377
+ "tagName": {
36378
+ "text": "param"
36379
+ }
36380
+ },
36225
36381
  {
36226
36382
  "name": "edits",
36227
36383
  "deprecated": false,
@@ -36229,6 +36385,24 @@
36229
36385
  "tagName": {
36230
36386
  "text": "param"
36231
36387
  }
36388
+ },
36389
+ {
36390
+ "name": "filePath",
36391
+ "type": "string",
36392
+ "deprecated": false,
36393
+ "deprecationMessage": "",
36394
+ "tagName": {
36395
+ "text": "param"
36396
+ }
36397
+ },
36398
+ {
36399
+ "name": "context",
36400
+ "type": "SchematicContext",
36401
+ "deprecated": false,
36402
+ "deprecationMessage": "",
36403
+ "tagName": {
36404
+ "text": "param"
36405
+ }
36232
36406
  }
36233
36407
  ]
36234
36408
  },
@@ -36275,180 +36449,6 @@
36275
36449
  }
36276
36450
  ]
36277
36451
  },
36278
- {
36279
- "name": "visitNodes",
36280
- "file": "packages/core/schematics/migrate-eui-popover/index.ts",
36281
- "ctype": "miscellaneous",
36282
- "subtype": "function",
36283
- "coverageIgnore": false,
36284
- "deprecated": false,
36285
- "deprecationMessage": "",
36286
- "rawdescription": "",
36287
- "description": "",
36288
- "displayName": "visitNodes",
36289
- "args": [
36290
- {
36291
- "name": "nodes",
36292
- "deprecated": false,
36293
- "deprecationMessage": ""
36294
- },
36295
- {
36296
- "name": "removals",
36297
- "deprecated": false,
36298
- "deprecationMessage": ""
36299
- }
36300
- ],
36301
- "returnType": "void",
36302
- "jsdoctags": [
36303
- {
36304
- "name": "nodes",
36305
- "deprecated": false,
36306
- "deprecationMessage": "",
36307
- "tagName": {
36308
- "text": "param"
36309
- }
36310
- },
36311
- {
36312
- "name": "removals",
36313
- "deprecated": false,
36314
- "deprecationMessage": "",
36315
- "tagName": {
36316
- "text": "param"
36317
- }
36318
- }
36319
- ]
36320
- },
36321
- {
36322
- "name": "visitNodes",
36323
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
36324
- "ctype": "miscellaneous",
36325
- "subtype": "function",
36326
- "coverageIgnore": false,
36327
- "deprecated": false,
36328
- "deprecationMessage": "",
36329
- "rawdescription": "",
36330
- "description": "",
36331
- "displayName": "visitNodes",
36332
- "args": [
36333
- {
36334
- "name": "nodes",
36335
- "deprecated": false,
36336
- "deprecationMessage": ""
36337
- },
36338
- {
36339
- "name": "edits",
36340
- "deprecated": false,
36341
- "deprecationMessage": ""
36342
- }
36343
- ],
36344
- "returnType": "void",
36345
- "jsdoctags": [
36346
- {
36347
- "name": "nodes",
36348
- "deprecated": false,
36349
- "deprecationMessage": "",
36350
- "tagName": {
36351
- "text": "param"
36352
- }
36353
- },
36354
- {
36355
- "name": "edits",
36356
- "deprecated": false,
36357
- "deprecationMessage": "",
36358
- "tagName": {
36359
- "text": "param"
36360
- }
36361
- }
36362
- ]
36363
- },
36364
- {
36365
- "name": "visitNodes",
36366
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
36367
- "ctype": "miscellaneous",
36368
- "subtype": "function",
36369
- "coverageIgnore": false,
36370
- "deprecated": false,
36371
- "deprecationMessage": "",
36372
- "rawdescription": "",
36373
- "description": "",
36374
- "displayName": "visitNodes",
36375
- "args": [
36376
- {
36377
- "name": "nodes",
36378
- "deprecated": false,
36379
- "deprecationMessage": ""
36380
- },
36381
- {
36382
- "name": "source",
36383
- "type": "string",
36384
- "deprecated": false,
36385
- "deprecationMessage": ""
36386
- },
36387
- {
36388
- "name": "edits",
36389
- "deprecated": false,
36390
- "deprecationMessage": ""
36391
- },
36392
- {
36393
- "name": "filePath",
36394
- "type": "string",
36395
- "deprecated": false,
36396
- "deprecationMessage": ""
36397
- },
36398
- {
36399
- "name": "context",
36400
- "type": "SchematicContext",
36401
- "deprecated": false,
36402
- "deprecationMessage": ""
36403
- }
36404
- ],
36405
- "returnType": "void",
36406
- "jsdoctags": [
36407
- {
36408
- "name": "nodes",
36409
- "deprecated": false,
36410
- "deprecationMessage": "",
36411
- "tagName": {
36412
- "text": "param"
36413
- }
36414
- },
36415
- {
36416
- "name": "source",
36417
- "type": "string",
36418
- "deprecated": false,
36419
- "deprecationMessage": "",
36420
- "tagName": {
36421
- "text": "param"
36422
- }
36423
- },
36424
- {
36425
- "name": "edits",
36426
- "deprecated": false,
36427
- "deprecationMessage": "",
36428
- "tagName": {
36429
- "text": "param"
36430
- }
36431
- },
36432
- {
36433
- "name": "filePath",
36434
- "type": "string",
36435
- "deprecated": false,
36436
- "deprecationMessage": "",
36437
- "tagName": {
36438
- "text": "param"
36439
- }
36440
- },
36441
- {
36442
- "name": "context",
36443
- "type": "SchematicContext",
36444
- "deprecated": false,
36445
- "deprecationMessage": "",
36446
- "tagName": {
36447
- "text": "param"
36448
- }
36449
- }
36450
- ]
36451
- },
36452
36452
  {
36453
36453
  "name": "visitNodesForTable",
36454
36454
  "file": "packages/core/schematics/migrate-eui-table/index.ts",
@@ -38006,6 +38006,19 @@
38006
38006
  "description": "<p>Provides read-only equivalent of jQuery&#39;s position function:\n<a href=\"http://api.jquery.com/position/\">http://api.jquery.com/position/</a></p>\n"
38007
38007
  }
38008
38008
  ],
38009
+ "packages/core/schematics/migrate-eui-discussion-thread/index.ts": [
38010
+ {
38011
+ "name": "COMPONENT_TAG",
38012
+ "ctype": "miscellaneous",
38013
+ "subtype": "variable",
38014
+ "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
38015
+ "coverageIgnore": false,
38016
+ "deprecated": false,
38017
+ "deprecationMessage": "",
38018
+ "type": "string",
38019
+ "defaultValue": "'eui-discussion-thread'"
38020
+ }
38021
+ ],
38009
38022
  "packages/core/schematics/migrate-eui-editor/index.ts": [
38010
38023
  {
38011
38024
  "name": "COMPONENT_TAG",
@@ -38041,19 +38054,6 @@
38041
38054
  "defaultValue": "'onEditorChanged'"
38042
38055
  }
38043
38056
  ],
38044
- "packages/core/schematics/migrate-eui-discussion-thread/index.ts": [
38045
- {
38046
- "name": "COMPONENT_TAG",
38047
- "ctype": "miscellaneous",
38048
- "subtype": "variable",
38049
- "file": "packages/core/schematics/migrate-eui-discussion-thread/index.ts",
38050
- "coverageIgnore": false,
38051
- "deprecated": false,
38052
- "deprecationMessage": "",
38053
- "type": "string",
38054
- "defaultValue": "'eui-discussion-thread'"
38055
- }
38056
- ],
38057
38057
  "packages/core/schematics/migrate-eui-fieldset/index.ts": [
38058
38058
  {
38059
38059
  "name": "COMPONENT_TAG",
@@ -45663,10 +45663,10 @@
45663
45663
  ]
45664
45664
  }
45665
45665
  ],
45666
- "packages/core/schematics/migrate-eui-icon-toggle/index.ts": [
45666
+ "packages/core/schematics/migrate-eui-progress-circle/index.ts": [
45667
45667
  {
45668
45668
  "name": "applyEdits",
45669
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45669
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45670
45670
  "ctype": "miscellaneous",
45671
45671
  "subtype": "function",
45672
45672
  "coverageIgnore": false,
@@ -45711,7 +45711,7 @@
45711
45711
  },
45712
45712
  {
45713
45713
  "name": "collectRenames",
45714
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45714
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45715
45715
  "ctype": "miscellaneous",
45716
45716
  "subtype": "function",
45717
45717
  "coverageIgnore": false,
@@ -45756,7 +45756,7 @@
45756
45756
  },
45757
45757
  {
45758
45758
  "name": "isComponentMetadataProperty",
45759
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45759
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45760
45760
  "ctype": "miscellaneous",
45761
45761
  "subtype": "function",
45762
45762
  "coverageIgnore": false,
@@ -45786,7 +45786,7 @@
45786
45786
  },
45787
45787
  {
45788
45788
  "name": "isTemplateProperty",
45789
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45789
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45790
45790
  "ctype": "miscellaneous",
45791
45791
  "subtype": "function",
45792
45792
  "coverageIgnore": false,
@@ -45815,8 +45815,8 @@
45815
45815
  ]
45816
45816
  },
45817
45817
  {
45818
- "name": "migrateEuiIconToggle",
45819
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45818
+ "name": "migrateEuiProgressCircle",
45819
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45820
45820
  "ctype": "miscellaneous",
45821
45821
  "subtype": "function",
45822
45822
  "coverageIgnore": false,
@@ -45824,7 +45824,7 @@
45824
45824
  "deprecationMessage": "",
45825
45825
  "rawdescription": "",
45826
45826
  "description": "",
45827
- "displayName": "migrateEuiIconToggle",
45827
+ "displayName": "migrateEuiProgressCircle",
45828
45828
  "args": [
45829
45829
  {
45830
45830
  "name": "options",
@@ -45850,7 +45850,7 @@
45850
45850
  },
45851
45851
  {
45852
45852
  "name": "migrateInlineTemplates",
45853
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45853
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45854
45854
  "ctype": "miscellaneous",
45855
45855
  "subtype": "function",
45856
45856
  "coverageIgnore": false,
@@ -45882,7 +45882,7 @@
45882
45882
  },
45883
45883
  {
45884
45884
  "name": "migrateTemplate",
45885
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45885
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45886
45886
  "ctype": "miscellaneous",
45887
45887
  "subtype": "function",
45888
45888
  "coverageIgnore": false,
@@ -45912,41 +45912,9 @@
45912
45912
  }
45913
45913
  ]
45914
45914
  },
45915
- {
45916
- "name": "renameTsPropertyAccesses",
45917
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45918
- "ctype": "miscellaneous",
45919
- "subtype": "function",
45920
- "coverageIgnore": false,
45921
- "deprecated": false,
45922
- "deprecationMessage": "",
45923
- "rawdescription": "",
45924
- "description": "",
45925
- "displayName": "renameTsPropertyAccesses",
45926
- "args": [
45927
- {
45928
- "name": "source",
45929
- "type": "string",
45930
- "deprecated": false,
45931
- "deprecationMessage": ""
45932
- }
45933
- ],
45934
- "returnType": "string",
45935
- "jsdoctags": [
45936
- {
45937
- "name": "source",
45938
- "type": "string",
45939
- "deprecated": false,
45940
- "deprecationMessage": "",
45941
- "tagName": {
45942
- "text": "param"
45943
- }
45944
- }
45945
- ]
45946
- },
45947
45915
  {
45948
45916
  "name": "unwrapExpression",
45949
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45917
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45950
45918
  "ctype": "miscellaneous",
45951
45919
  "subtype": "function",
45952
45920
  "coverageIgnore": false,
@@ -45976,7 +45944,7 @@
45976
45944
  },
45977
45945
  {
45978
45946
  "name": "visitDir",
45979
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45947
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
45980
45948
  "ctype": "miscellaneous",
45981
45949
  "subtype": "function",
45982
45950
  "coverageIgnore": false,
@@ -46021,7 +45989,7 @@
46021
45989
  },
46022
45990
  {
46023
45991
  "name": "visitNodes",
46024
- "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
45992
+ "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46025
45993
  "ctype": "miscellaneous",
46026
45994
  "subtype": "function",
46027
45995
  "coverageIgnore": false,
@@ -46063,10 +46031,10 @@
46063
46031
  ]
46064
46032
  }
46065
46033
  ],
46066
- "packages/core/schematics/migrate-eui-progress-circle/index.ts": [
46034
+ "packages/core/schematics/migrate-eui-toolbar-menu/index.ts": [
46067
46035
  {
46068
46036
  "name": "applyEdits",
46069
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46037
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46070
46038
  "ctype": "miscellaneous",
46071
46039
  "subtype": "function",
46072
46040
  "coverageIgnore": false,
@@ -46110,8 +46078,8 @@
46110
46078
  ]
46111
46079
  },
46112
46080
  {
46113
- "name": "collectRenames",
46114
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46081
+ "name": "collectOutputRemovals",
46082
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46115
46083
  "ctype": "miscellaneous",
46116
46084
  "subtype": "function",
46117
46085
  "coverageIgnore": false,
@@ -46119,7 +46087,7 @@
46119
46087
  "deprecationMessage": "",
46120
46088
  "rawdescription": "",
46121
46089
  "description": "",
46122
- "displayName": "collectRenames",
46090
+ "displayName": "collectOutputRemovals",
46123
46091
  "args": [
46124
46092
  {
46125
46093
  "name": "element",
@@ -46127,10 +46095,28 @@
46127
46095
  "deprecated": false,
46128
46096
  "deprecationMessage": ""
46129
46097
  },
46098
+ {
46099
+ "name": "source",
46100
+ "type": "string",
46101
+ "deprecated": false,
46102
+ "deprecationMessage": ""
46103
+ },
46130
46104
  {
46131
46105
  "name": "edits",
46132
46106
  "deprecated": false,
46133
46107
  "deprecationMessage": ""
46108
+ },
46109
+ {
46110
+ "name": "filePath",
46111
+ "type": "string",
46112
+ "deprecated": false,
46113
+ "deprecationMessage": ""
46114
+ },
46115
+ {
46116
+ "name": "context",
46117
+ "type": "SchematicContext",
46118
+ "deprecated": false,
46119
+ "deprecationMessage": ""
46134
46120
  }
46135
46121
  ],
46136
46122
  "returnType": "void",
@@ -46144,6 +46130,15 @@
46144
46130
  "text": "param"
46145
46131
  }
46146
46132
  },
46133
+ {
46134
+ "name": "source",
46135
+ "type": "string",
46136
+ "deprecated": false,
46137
+ "deprecationMessage": "",
46138
+ "tagName": {
46139
+ "text": "param"
46140
+ }
46141
+ },
46147
46142
  {
46148
46143
  "name": "edits",
46149
46144
  "deprecated": false,
@@ -46151,31 +46146,19 @@
46151
46146
  "tagName": {
46152
46147
  "text": "param"
46153
46148
  }
46154
- }
46155
- ]
46156
- },
46157
- {
46158
- "name": "isComponentMetadataProperty",
46159
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46160
- "ctype": "miscellaneous",
46161
- "subtype": "function",
46162
- "coverageIgnore": false,
46163
- "deprecated": false,
46164
- "deprecationMessage": "",
46165
- "rawdescription": "",
46166
- "description": "",
46167
- "displayName": "isComponentMetadataProperty",
46168
- "args": [
46149
+ },
46169
46150
  {
46170
- "name": "node",
46151
+ "name": "filePath",
46152
+ "type": "string",
46171
46153
  "deprecated": false,
46172
- "deprecationMessage": ""
46173
- }
46174
- ],
46175
- "returnType": "boolean",
46176
- "jsdoctags": [
46154
+ "deprecationMessage": "",
46155
+ "tagName": {
46156
+ "text": "param"
46157
+ }
46158
+ },
46177
46159
  {
46178
- "name": "node",
46160
+ "name": "context",
46161
+ "type": "SchematicContext",
46179
46162
  "deprecated": false,
46180
46163
  "deprecationMessage": "",
46181
46164
  "tagName": {
@@ -46185,8 +46168,8 @@
46185
46168
  ]
46186
46169
  },
46187
46170
  {
46188
- "name": "isTemplateProperty",
46189
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46171
+ "name": "collectTagRenames",
46172
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46190
46173
  "ctype": "miscellaneous",
46191
46174
  "subtype": "function",
46192
46175
  "coverageIgnore": false,
@@ -46194,54 +46177,50 @@
46194
46177
  "deprecationMessage": "",
46195
46178
  "rawdescription": "",
46196
46179
  "description": "",
46197
- "displayName": "isTemplateProperty",
46180
+ "displayName": "collectTagRenames",
46198
46181
  "args": [
46199
46182
  {
46200
- "name": "node",
46183
+ "name": "element",
46184
+ "type": "TmplAstElement",
46185
+ "deprecated": false,
46186
+ "deprecationMessage": ""
46187
+ },
46188
+ {
46189
+ "name": "source",
46190
+ "type": "string",
46191
+ "deprecated": false,
46192
+ "deprecationMessage": ""
46193
+ },
46194
+ {
46195
+ "name": "edits",
46201
46196
  "deprecated": false,
46202
46197
  "deprecationMessage": ""
46203
46198
  }
46204
46199
  ],
46205
- "returnType": "boolean",
46200
+ "returnType": "void",
46206
46201
  "jsdoctags": [
46207
46202
  {
46208
- "name": "node",
46203
+ "name": "element",
46204
+ "type": "TmplAstElement",
46209
46205
  "deprecated": false,
46210
46206
  "deprecationMessage": "",
46211
46207
  "tagName": {
46212
46208
  "text": "param"
46213
46209
  }
46214
- }
46215
- ]
46216
- },
46217
- {
46218
- "name": "migrateEuiProgressCircle",
46219
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46220
- "ctype": "miscellaneous",
46221
- "subtype": "function",
46222
- "coverageIgnore": false,
46223
- "deprecated": false,
46224
- "deprecationMessage": "",
46225
- "rawdescription": "",
46226
- "description": "",
46227
- "displayName": "migrateEuiProgressCircle",
46228
- "args": [
46210
+ },
46229
46211
  {
46230
- "name": "options",
46231
- "type": "Schema",
46212
+ "name": "source",
46213
+ "type": "string",
46232
46214
  "deprecated": false,
46233
46215
  "deprecationMessage": "",
46234
- "defaultValue": "{}"
46235
- }
46236
- ],
46237
- "returnType": "Rule",
46238
- "jsdoctags": [
46216
+ "tagName": {
46217
+ "text": "param"
46218
+ }
46219
+ },
46239
46220
  {
46240
- "name": "options",
46241
- "type": "Schema",
46221
+ "name": "edits",
46242
46222
  "deprecated": false,
46243
46223
  "deprecationMessage": "",
46244
- "defaultValue": "{}",
46245
46224
  "tagName": {
46246
46225
  "text": "param"
46247
46226
  }
@@ -46249,8 +46228,8 @@
46249
46228
  ]
46250
46229
  },
46251
46230
  {
46252
- "name": "migrateInlineTemplates",
46253
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46231
+ "name": "deduplicateEdits",
46232
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46254
46233
  "ctype": "miscellaneous",
46255
46234
  "subtype": "function",
46256
46235
  "coverageIgnore": false,
@@ -46258,20 +46237,18 @@
46258
46237
  "deprecationMessage": "",
46259
46238
  "rawdescription": "",
46260
46239
  "description": "",
46261
- "displayName": "migrateInlineTemplates",
46240
+ "displayName": "deduplicateEdits",
46262
46241
  "args": [
46263
46242
  {
46264
- "name": "source",
46265
- "type": "string",
46243
+ "name": "edits",
46266
46244
  "deprecated": false,
46267
46245
  "deprecationMessage": ""
46268
46246
  }
46269
46247
  ],
46270
- "returnType": "string",
46248
+ "returnType": "Edit[]",
46271
46249
  "jsdoctags": [
46272
46250
  {
46273
- "name": "source",
46274
- "type": "string",
46251
+ "name": "edits",
46275
46252
  "deprecated": false,
46276
46253
  "deprecationMessage": "",
46277
46254
  "tagName": {
@@ -46281,8 +46258,8 @@
46281
46258
  ]
46282
46259
  },
46283
46260
  {
46284
- "name": "migrateTemplate",
46285
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46261
+ "name": "isComponentMetadataProperty",
46262
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46286
46263
  "ctype": "miscellaneous",
46287
46264
  "subtype": "function",
46288
46265
  "coverageIgnore": false,
@@ -46290,20 +46267,18 @@
46290
46267
  "deprecationMessage": "",
46291
46268
  "rawdescription": "",
46292
46269
  "description": "",
46293
- "displayName": "migrateTemplate",
46270
+ "displayName": "isComponentMetadataProperty",
46294
46271
  "args": [
46295
46272
  {
46296
- "name": "source",
46297
- "type": "string",
46273
+ "name": "node",
46298
46274
  "deprecated": false,
46299
46275
  "deprecationMessage": ""
46300
46276
  }
46301
46277
  ],
46302
- "returnType": "string",
46278
+ "returnType": "boolean",
46303
46279
  "jsdoctags": [
46304
46280
  {
46305
- "name": "source",
46306
- "type": "string",
46281
+ "name": "node",
46307
46282
  "deprecated": false,
46308
46283
  "deprecationMessage": "",
46309
46284
  "tagName": {
@@ -46313,8 +46288,8 @@
46313
46288
  ]
46314
46289
  },
46315
46290
  {
46316
- "name": "unwrapExpression",
46317
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46291
+ "name": "isTemplateProperty",
46292
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46318
46293
  "ctype": "miscellaneous",
46319
46294
  "subtype": "function",
46320
46295
  "coverageIgnore": false,
@@ -46322,18 +46297,18 @@
46322
46297
  "deprecationMessage": "",
46323
46298
  "rawdescription": "",
46324
46299
  "description": "",
46325
- "displayName": "unwrapExpression",
46300
+ "displayName": "isTemplateProperty",
46326
46301
  "args": [
46327
46302
  {
46328
- "name": "expression",
46303
+ "name": "node",
46329
46304
  "deprecated": false,
46330
46305
  "deprecationMessage": ""
46331
46306
  }
46332
46307
  ],
46333
- "returnType": "ts.Expression",
46308
+ "returnType": "boolean",
46334
46309
  "jsdoctags": [
46335
46310
  {
46336
- "name": "expression",
46311
+ "name": "node",
46337
46312
  "deprecated": false,
46338
46313
  "deprecationMessage": "",
46339
46314
  "tagName": {
@@ -46343,8 +46318,8 @@
46343
46318
  ]
46344
46319
  },
46345
46320
  {
46346
- "name": "visitDir",
46347
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46321
+ "name": "migrateEuiToolbarMenu",
46322
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46348
46323
  "ctype": "miscellaneous",
46349
46324
  "subtype": "function",
46350
46325
  "coverageIgnore": false,
@@ -46352,35 +46327,24 @@
46352
46327
  "deprecationMessage": "",
46353
46328
  "rawdescription": "",
46354
46329
  "description": "",
46355
- "displayName": "visitDir",
46330
+ "displayName": "migrateEuiToolbarMenu",
46356
46331
  "args": [
46357
46332
  {
46358
- "name": "dir",
46359
- "type": "DirEntry",
46360
- "deprecated": false,
46361
- "deprecationMessage": ""
46362
- },
46363
- {
46364
- "name": "callback",
46333
+ "name": "options",
46334
+ "type": "Schema",
46365
46335
  "deprecated": false,
46366
- "deprecationMessage": ""
46336
+ "deprecationMessage": "",
46337
+ "defaultValue": "{}"
46367
46338
  }
46368
46339
  ],
46369
- "returnType": "void",
46340
+ "returnType": "Rule",
46370
46341
  "jsdoctags": [
46371
46342
  {
46372
- "name": "dir",
46373
- "type": "DirEntry",
46374
- "deprecated": false,
46375
- "deprecationMessage": "",
46376
- "tagName": {
46377
- "text": "param"
46378
- }
46379
- },
46380
- {
46381
- "name": "callback",
46343
+ "name": "options",
46344
+ "type": "Schema",
46382
46345
  "deprecated": false,
46383
46346
  "deprecationMessage": "",
46347
+ "defaultValue": "{}",
46384
46348
  "tagName": {
46385
46349
  "text": "param"
46386
46350
  }
@@ -46388,8 +46352,8 @@
46388
46352
  ]
46389
46353
  },
46390
46354
  {
46391
- "name": "visitNodes",
46392
- "file": "packages/core/schematics/migrate-eui-progress-circle/index.ts",
46355
+ "name": "migrateImportsAndTypes",
46356
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46393
46357
  "ctype": "miscellaneous",
46394
46358
  "subtype": "function",
46395
46359
  "coverageIgnore": false,
@@ -46397,23 +46361,32 @@
46397
46361
  "deprecationMessage": "",
46398
46362
  "rawdescription": "",
46399
46363
  "description": "",
46400
- "displayName": "visitNodes",
46364
+ "displayName": "migrateImportsAndTypes",
46401
46365
  "args": [
46402
46366
  {
46403
- "name": "nodes",
46367
+ "name": "source",
46368
+ "type": "string",
46404
46369
  "deprecated": false,
46405
46370
  "deprecationMessage": ""
46406
46371
  },
46407
46372
  {
46408
- "name": "edits",
46373
+ "name": "filePath",
46374
+ "type": "string",
46375
+ "deprecated": false,
46376
+ "deprecationMessage": ""
46377
+ },
46378
+ {
46379
+ "name": "context",
46380
+ "type": "SchematicContext",
46409
46381
  "deprecated": false,
46410
46382
  "deprecationMessage": ""
46411
46383
  }
46412
46384
  ],
46413
- "returnType": "void",
46385
+ "returnType": "string",
46414
46386
  "jsdoctags": [
46415
46387
  {
46416
- "name": "nodes",
46388
+ "name": "source",
46389
+ "type": "string",
46417
46390
  "deprecated": false,
46418
46391
  "deprecationMessage": "",
46419
46392
  "tagName": {
@@ -46421,7 +46394,17 @@
46421
46394
  }
46422
46395
  },
46423
46396
  {
46424
- "name": "edits",
46397
+ "name": "filePath",
46398
+ "type": "string",
46399
+ "deprecated": false,
46400
+ "deprecationMessage": "",
46401
+ "tagName": {
46402
+ "text": "param"
46403
+ }
46404
+ },
46405
+ {
46406
+ "name": "context",
46407
+ "type": "SchematicContext",
46425
46408
  "deprecated": false,
46426
46409
  "deprecationMessage": "",
46427
46410
  "tagName": {
@@ -46429,12 +46412,10 @@
46429
46412
  }
46430
46413
  }
46431
46414
  ]
46432
- }
46433
- ],
46434
- "packages/core/schematics/migrate-eui-tooltip/index.ts": [
46415
+ },
46435
46416
  {
46436
- "name": "applyEdits",
46437
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46417
+ "name": "migrateInlineTemplates",
46418
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46438
46419
  "ctype": "miscellaneous",
46439
46420
  "subtype": "function",
46440
46421
  "coverageIgnore": false,
@@ -46442,7 +46423,7 @@
46442
46423
  "deprecationMessage": "",
46443
46424
  "rawdescription": "",
46444
46425
  "description": "",
46445
- "displayName": "applyEdits",
46426
+ "displayName": "migrateInlineTemplates",
46446
46427
  "args": [
46447
46428
  {
46448
46429
  "name": "source",
@@ -46451,7 +46432,14 @@
46451
46432
  "deprecationMessage": ""
46452
46433
  },
46453
46434
  {
46454
- "name": "edits",
46435
+ "name": "filePath",
46436
+ "type": "string",
46437
+ "deprecated": false,
46438
+ "deprecationMessage": ""
46439
+ },
46440
+ {
46441
+ "name": "context",
46442
+ "type": "SchematicContext",
46455
46443
  "deprecated": false,
46456
46444
  "deprecationMessage": ""
46457
46445
  }
@@ -46468,37 +46456,17 @@
46468
46456
  }
46469
46457
  },
46470
46458
  {
46471
- "name": "edits",
46459
+ "name": "filePath",
46460
+ "type": "string",
46472
46461
  "deprecated": false,
46473
46462
  "deprecationMessage": "",
46474
46463
  "tagName": {
46475
46464
  "text": "param"
46476
46465
  }
46477
- }
46478
- ]
46479
- },
46480
- {
46481
- "name": "deduplicateEdits",
46482
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46483
- "ctype": "miscellaneous",
46484
- "subtype": "function",
46485
- "coverageIgnore": false,
46486
- "deprecated": false,
46487
- "deprecationMessage": "",
46488
- "rawdescription": "",
46489
- "description": "",
46490
- "displayName": "deduplicateEdits",
46491
- "args": [
46492
- {
46493
- "name": "edits",
46494
- "deprecated": false,
46495
- "deprecationMessage": ""
46496
- }
46497
- ],
46498
- "returnType": "Edit[]",
46499
- "jsdoctags": [
46466
+ },
46500
46467
  {
46501
- "name": "edits",
46468
+ "name": "context",
46469
+ "type": "SchematicContext",
46502
46470
  "deprecated": false,
46503
46471
  "deprecationMessage": "",
46504
46472
  "tagName": {
@@ -46508,8 +46476,8 @@
46508
46476
  ]
46509
46477
  },
46510
46478
  {
46511
- "name": "isPartOfImport",
46512
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46479
+ "name": "migrateTemplate",
46480
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46513
46481
  "ctype": "miscellaneous",
46514
46482
  "subtype": "function",
46515
46483
  "coverageIgnore": false,
@@ -46517,54 +46485,52 @@
46517
46485
  "deprecationMessage": "",
46518
46486
  "rawdescription": "",
46519
46487
  "description": "",
46520
- "displayName": "isPartOfImport",
46488
+ "displayName": "migrateTemplate",
46521
46489
  "args": [
46522
46490
  {
46523
- "name": "node",
46491
+ "name": "source",
46492
+ "type": "string",
46493
+ "deprecated": false,
46494
+ "deprecationMessage": ""
46495
+ },
46496
+ {
46497
+ "name": "filePath",
46498
+ "type": "string",
46499
+ "deprecated": false,
46500
+ "deprecationMessage": ""
46501
+ },
46502
+ {
46503
+ "name": "context",
46504
+ "type": "SchematicContext",
46524
46505
  "deprecated": false,
46525
46506
  "deprecationMessage": ""
46526
46507
  }
46527
46508
  ],
46528
- "returnType": "boolean",
46509
+ "returnType": "string",
46529
46510
  "jsdoctags": [
46530
46511
  {
46531
- "name": "node",
46512
+ "name": "source",
46513
+ "type": "string",
46532
46514
  "deprecated": false,
46533
46515
  "deprecationMessage": "",
46534
46516
  "tagName": {
46535
46517
  "text": "param"
46536
46518
  }
46537
- }
46538
- ]
46539
- },
46540
- {
46541
- "name": "migrateEuiTooltip",
46542
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46543
- "ctype": "miscellaneous",
46544
- "subtype": "function",
46545
- "coverageIgnore": false,
46546
- "deprecated": false,
46547
- "deprecationMessage": "",
46548
- "rawdescription": "",
46549
- "description": "",
46550
- "displayName": "migrateEuiTooltip",
46551
- "args": [
46519
+ },
46552
46520
  {
46553
- "name": "options",
46554
- "type": "Schema",
46521
+ "name": "filePath",
46522
+ "type": "string",
46555
46523
  "deprecated": false,
46556
46524
  "deprecationMessage": "",
46557
- "defaultValue": "{}"
46558
- }
46559
- ],
46560
- "returnType": "Rule",
46561
- "jsdoctags": [
46525
+ "tagName": {
46526
+ "text": "param"
46527
+ }
46528
+ },
46562
46529
  {
46563
- "name": "options",
46564
- "type": "Schema",
46530
+ "name": "context",
46531
+ "type": "SchematicContext",
46565
46532
  "deprecated": false,
46566
46533
  "deprecationMessage": "",
46567
- "defaultValue": "{}",
46568
46534
  "tagName": {
46569
46535
  "text": "param"
46570
46536
  }
@@ -46573,7 +46539,7 @@
46573
46539
  },
46574
46540
  {
46575
46541
  "name": "migrateTypeScript",
46576
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46542
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46577
46543
  "ctype": "miscellaneous",
46578
46544
  "subtype": "function",
46579
46545
  "coverageIgnore": false,
@@ -46635,7 +46601,7 @@
46635
46601
  },
46636
46602
  {
46637
46603
  "name": "removeImportSpecifier",
46638
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46604
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46639
46605
  "ctype": "miscellaneous",
46640
46606
  "subtype": "function",
46641
46607
  "coverageIgnore": false,
@@ -46703,8 +46669,8 @@
46703
46669
  ]
46704
46670
  },
46705
46671
  {
46706
- "name": "visitDir",
46707
- "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46672
+ "name": "unwrapExpression",
46673
+ "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46708
46674
  "ctype": "miscellaneous",
46709
46675
  "subtype": "function",
46710
46676
  "coverageIgnore": false,
@@ -46712,33 +46678,18 @@
46712
46678
  "deprecationMessage": "",
46713
46679
  "rawdescription": "",
46714
46680
  "description": "",
46715
- "displayName": "visitDir",
46681
+ "displayName": "unwrapExpression",
46716
46682
  "args": [
46717
46683
  {
46718
- "name": "dir",
46719
- "type": "DirEntry",
46720
- "deprecated": false,
46721
- "deprecationMessage": ""
46722
- },
46723
- {
46724
- "name": "callback",
46684
+ "name": "expression",
46725
46685
  "deprecated": false,
46726
46686
  "deprecationMessage": ""
46727
46687
  }
46728
46688
  ],
46729
- "returnType": "void",
46689
+ "returnType": "ts.Expression",
46730
46690
  "jsdoctags": [
46731
46691
  {
46732
- "name": "dir",
46733
- "type": "DirEntry",
46734
- "deprecated": false,
46735
- "deprecationMessage": "",
46736
- "tagName": {
46737
- "text": "param"
46738
- }
46739
- },
46740
- {
46741
- "name": "callback",
46692
+ "name": "expression",
46742
46693
  "deprecated": false,
46743
46694
  "deprecationMessage": "",
46744
46695
  "tagName": {
@@ -46746,11 +46697,9 @@
46746
46697
  }
46747
46698
  }
46748
46699
  ]
46749
- }
46750
- ],
46751
- "packages/core/schematics/migrate-eui-toolbar-menu/index.ts": [
46700
+ },
46752
46701
  {
46753
- "name": "applyEdits",
46702
+ "name": "visitDir",
46754
46703
  "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46755
46704
  "ctype": "miscellaneous",
46756
46705
  "subtype": "function",
@@ -46759,25 +46708,25 @@
46759
46708
  "deprecationMessage": "",
46760
46709
  "rawdescription": "",
46761
46710
  "description": "",
46762
- "displayName": "applyEdits",
46711
+ "displayName": "visitDir",
46763
46712
  "args": [
46764
46713
  {
46765
- "name": "source",
46766
- "type": "string",
46714
+ "name": "dir",
46715
+ "type": "DirEntry",
46767
46716
  "deprecated": false,
46768
46717
  "deprecationMessage": ""
46769
46718
  },
46770
46719
  {
46771
- "name": "edits",
46720
+ "name": "callback",
46772
46721
  "deprecated": false,
46773
46722
  "deprecationMessage": ""
46774
46723
  }
46775
46724
  ],
46776
- "returnType": "string",
46725
+ "returnType": "void",
46777
46726
  "jsdoctags": [
46778
46727
  {
46779
- "name": "source",
46780
- "type": "string",
46728
+ "name": "dir",
46729
+ "type": "DirEntry",
46781
46730
  "deprecated": false,
46782
46731
  "deprecationMessage": "",
46783
46732
  "tagName": {
@@ -46785,7 +46734,7 @@
46785
46734
  }
46786
46735
  },
46787
46736
  {
46788
- "name": "edits",
46737
+ "name": "callback",
46789
46738
  "deprecated": false,
46790
46739
  "deprecationMessage": "",
46791
46740
  "tagName": {
@@ -46795,7 +46744,7 @@
46795
46744
  ]
46796
46745
  },
46797
46746
  {
46798
- "name": "collectOutputRemovals",
46747
+ "name": "visitNodes",
46799
46748
  "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46800
46749
  "ctype": "miscellaneous",
46801
46750
  "subtype": "function",
@@ -46804,11 +46753,10 @@
46804
46753
  "deprecationMessage": "",
46805
46754
  "rawdescription": "",
46806
46755
  "description": "",
46807
- "displayName": "collectOutputRemovals",
46756
+ "displayName": "visitNodes",
46808
46757
  "args": [
46809
46758
  {
46810
- "name": "element",
46811
- "type": "TmplAstElement",
46759
+ "name": "nodes",
46812
46760
  "deprecated": false,
46813
46761
  "deprecationMessage": ""
46814
46762
  },
@@ -46839,8 +46787,7 @@
46839
46787
  "returnType": "void",
46840
46788
  "jsdoctags": [
46841
46789
  {
46842
- "name": "element",
46843
- "type": "TmplAstElement",
46790
+ "name": "nodes",
46844
46791
  "deprecated": false,
46845
46792
  "deprecationMessage": "",
46846
46793
  "tagName": {
@@ -46885,7 +46832,7 @@
46885
46832
  ]
46886
46833
  },
46887
46834
  {
46888
- "name": "collectTagRenames",
46835
+ "name": "warnRemovedProperties",
46889
46836
  "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46890
46837
  "ctype": "miscellaneous",
46891
46838
  "subtype": "function",
@@ -46894,22 +46841,22 @@
46894
46841
  "deprecationMessage": "",
46895
46842
  "rawdescription": "",
46896
46843
  "description": "",
46897
- "displayName": "collectTagRenames",
46844
+ "displayName": "warnRemovedProperties",
46898
46845
  "args": [
46899
46846
  {
46900
- "name": "element",
46901
- "type": "TmplAstElement",
46847
+ "name": "sourceFile",
46902
46848
  "deprecated": false,
46903
46849
  "deprecationMessage": ""
46904
46850
  },
46905
46851
  {
46906
- "name": "source",
46852
+ "name": "filePath",
46907
46853
  "type": "string",
46908
46854
  "deprecated": false,
46909
46855
  "deprecationMessage": ""
46910
46856
  },
46911
46857
  {
46912
- "name": "edits",
46858
+ "name": "context",
46859
+ "type": "SchematicContext",
46913
46860
  "deprecated": false,
46914
46861
  "deprecationMessage": ""
46915
46862
  }
@@ -46917,8 +46864,7 @@
46917
46864
  "returnType": "void",
46918
46865
  "jsdoctags": [
46919
46866
  {
46920
- "name": "element",
46921
- "type": "TmplAstElement",
46867
+ "name": "sourceFile",
46922
46868
  "deprecated": false,
46923
46869
  "deprecationMessage": "",
46924
46870
  "tagName": {
@@ -46926,7 +46872,7 @@
46926
46872
  }
46927
46873
  },
46928
46874
  {
46929
- "name": "source",
46875
+ "name": "filePath",
46930
46876
  "type": "string",
46931
46877
  "deprecated": false,
46932
46878
  "deprecationMessage": "",
@@ -46935,7 +46881,8 @@
46935
46881
  }
46936
46882
  },
46937
46883
  {
46938
- "name": "edits",
46884
+ "name": "context",
46885
+ "type": "SchematicContext",
46939
46886
  "deprecated": false,
46940
46887
  "deprecationMessage": "",
46941
46888
  "tagName": {
@@ -46943,10 +46890,12 @@
46943
46890
  }
46944
46891
  }
46945
46892
  ]
46946
- },
46893
+ }
46894
+ ],
46895
+ "packages/core/schematics/migrate-eui-tooltip/index.ts": [
46947
46896
  {
46948
- "name": "deduplicateEdits",
46949
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46897
+ "name": "applyEdits",
46898
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46950
46899
  "ctype": "miscellaneous",
46951
46900
  "subtype": "function",
46952
46901
  "coverageIgnore": false,
@@ -46954,16 +46903,31 @@
46954
46903
  "deprecationMessage": "",
46955
46904
  "rawdescription": "",
46956
46905
  "description": "",
46957
- "displayName": "deduplicateEdits",
46906
+ "displayName": "applyEdits",
46958
46907
  "args": [
46908
+ {
46909
+ "name": "source",
46910
+ "type": "string",
46911
+ "deprecated": false,
46912
+ "deprecationMessage": ""
46913
+ },
46959
46914
  {
46960
46915
  "name": "edits",
46961
46916
  "deprecated": false,
46962
46917
  "deprecationMessage": ""
46963
46918
  }
46964
46919
  ],
46965
- "returnType": "Edit[]",
46920
+ "returnType": "string",
46966
46921
  "jsdoctags": [
46922
+ {
46923
+ "name": "source",
46924
+ "type": "string",
46925
+ "deprecated": false,
46926
+ "deprecationMessage": "",
46927
+ "tagName": {
46928
+ "text": "param"
46929
+ }
46930
+ },
46967
46931
  {
46968
46932
  "name": "edits",
46969
46933
  "deprecated": false,
@@ -46975,8 +46939,8 @@
46975
46939
  ]
46976
46940
  },
46977
46941
  {
46978
- "name": "isComponentMetadataProperty",
46979
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46942
+ "name": "deduplicateEdits",
46943
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
46980
46944
  "ctype": "miscellaneous",
46981
46945
  "subtype": "function",
46982
46946
  "coverageIgnore": false,
@@ -46984,18 +46948,18 @@
46984
46948
  "deprecationMessage": "",
46985
46949
  "rawdescription": "",
46986
46950
  "description": "",
46987
- "displayName": "isComponentMetadataProperty",
46951
+ "displayName": "deduplicateEdits",
46988
46952
  "args": [
46989
46953
  {
46990
- "name": "node",
46954
+ "name": "edits",
46991
46955
  "deprecated": false,
46992
46956
  "deprecationMessage": ""
46993
46957
  }
46994
46958
  ],
46995
- "returnType": "boolean",
46959
+ "returnType": "Edit[]",
46996
46960
  "jsdoctags": [
46997
46961
  {
46998
- "name": "node",
46962
+ "name": "edits",
46999
46963
  "deprecated": false,
47000
46964
  "deprecationMessage": "",
47001
46965
  "tagName": {
@@ -47005,8 +46969,8 @@
47005
46969
  ]
47006
46970
  },
47007
46971
  {
47008
- "name": "isTemplateProperty",
47009
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
46972
+ "name": "isPartOfImport",
46973
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
47010
46974
  "ctype": "miscellaneous",
47011
46975
  "subtype": "function",
47012
46976
  "coverageIgnore": false,
@@ -47014,7 +46978,7 @@
47014
46978
  "deprecationMessage": "",
47015
46979
  "rawdescription": "",
47016
46980
  "description": "",
47017
- "displayName": "isTemplateProperty",
46981
+ "displayName": "isPartOfImport",
47018
46982
  "args": [
47019
46983
  {
47020
46984
  "name": "node",
@@ -47035,8 +46999,8 @@
47035
46999
  ]
47036
47000
  },
47037
47001
  {
47038
- "name": "migrateEuiToolbarMenu",
47039
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47002
+ "name": "migrateEuiTooltip",
47003
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
47040
47004
  "ctype": "miscellaneous",
47041
47005
  "subtype": "function",
47042
47006
  "coverageIgnore": false,
@@ -47044,7 +47008,7 @@
47044
47008
  "deprecationMessage": "",
47045
47009
  "rawdescription": "",
47046
47010
  "description": "",
47047
- "displayName": "migrateEuiToolbarMenu",
47011
+ "displayName": "migrateEuiTooltip",
47048
47012
  "args": [
47049
47013
  {
47050
47014
  "name": "options",
@@ -47069,8 +47033,8 @@
47069
47033
  ]
47070
47034
  },
47071
47035
  {
47072
- "name": "migrateImportsAndTypes",
47073
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47036
+ "name": "migrateTypeScript",
47037
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
47074
47038
  "ctype": "miscellaneous",
47075
47039
  "subtype": "function",
47076
47040
  "coverageIgnore": false,
@@ -47078,7 +47042,7 @@
47078
47042
  "deprecationMessage": "",
47079
47043
  "rawdescription": "",
47080
47044
  "description": "",
47081
- "displayName": "migrateImportsAndTypes",
47045
+ "displayName": "migrateTypeScript",
47082
47046
  "args": [
47083
47047
  {
47084
47048
  "name": "source",
@@ -47131,8 +47095,8 @@
47131
47095
  ]
47132
47096
  },
47133
47097
  {
47134
- "name": "migrateInlineTemplates",
47135
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47098
+ "name": "removeImportSpecifier",
47099
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
47136
47100
  "ctype": "miscellaneous",
47137
47101
  "subtype": "function",
47138
47102
  "coverageIgnore": false,
@@ -47140,32 +47104,33 @@
47140
47104
  "deprecationMessage": "",
47141
47105
  "rawdescription": "",
47142
47106
  "description": "",
47143
- "displayName": "migrateInlineTemplates",
47107
+ "displayName": "removeImportSpecifier",
47144
47108
  "args": [
47145
47109
  {
47146
- "name": "source",
47147
- "type": "string",
47110
+ "name": "namedImports",
47148
47111
  "deprecated": false,
47149
47112
  "deprecationMessage": ""
47150
47113
  },
47151
47114
  {
47152
- "name": "filePath",
47153
- "type": "string",
47115
+ "name": "specifier",
47154
47116
  "deprecated": false,
47155
47117
  "deprecationMessage": ""
47156
47118
  },
47157
47119
  {
47158
- "name": "context",
47159
- "type": "SchematicContext",
47120
+ "name": "sourceFile",
47121
+ "deprecated": false,
47122
+ "deprecationMessage": ""
47123
+ },
47124
+ {
47125
+ "name": "edits",
47160
47126
  "deprecated": false,
47161
47127
  "deprecationMessage": ""
47162
47128
  }
47163
47129
  ],
47164
- "returnType": "string",
47130
+ "returnType": "void",
47165
47131
  "jsdoctags": [
47166
47132
  {
47167
- "name": "source",
47168
- "type": "string",
47133
+ "name": "namedImports",
47169
47134
  "deprecated": false,
47170
47135
  "deprecationMessage": "",
47171
47136
  "tagName": {
@@ -47173,8 +47138,7 @@
47173
47138
  }
47174
47139
  },
47175
47140
  {
47176
- "name": "filePath",
47177
- "type": "string",
47141
+ "name": "specifier",
47178
47142
  "deprecated": false,
47179
47143
  "deprecationMessage": "",
47180
47144
  "tagName": {
@@ -47182,8 +47146,15 @@
47182
47146
  }
47183
47147
  },
47184
47148
  {
47185
- "name": "context",
47186
- "type": "SchematicContext",
47149
+ "name": "sourceFile",
47150
+ "deprecated": false,
47151
+ "deprecationMessage": "",
47152
+ "tagName": {
47153
+ "text": "param"
47154
+ }
47155
+ },
47156
+ {
47157
+ "name": "edits",
47187
47158
  "deprecated": false,
47188
47159
  "deprecationMessage": "",
47189
47160
  "tagName": {
@@ -47193,8 +47164,8 @@
47193
47164
  ]
47194
47165
  },
47195
47166
  {
47196
- "name": "migrateTemplate",
47197
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47167
+ "name": "visitDir",
47168
+ "file": "packages/core/schematics/migrate-eui-tooltip/index.ts",
47198
47169
  "ctype": "miscellaneous",
47199
47170
  "subtype": "function",
47200
47171
  "coverageIgnore": false,
@@ -47202,41 +47173,25 @@
47202
47173
  "deprecationMessage": "",
47203
47174
  "rawdescription": "",
47204
47175
  "description": "",
47205
- "displayName": "migrateTemplate",
47176
+ "displayName": "visitDir",
47206
47177
  "args": [
47207
47178
  {
47208
- "name": "source",
47209
- "type": "string",
47210
- "deprecated": false,
47211
- "deprecationMessage": ""
47212
- },
47213
- {
47214
- "name": "filePath",
47215
- "type": "string",
47179
+ "name": "dir",
47180
+ "type": "DirEntry",
47216
47181
  "deprecated": false,
47217
47182
  "deprecationMessage": ""
47218
47183
  },
47219
47184
  {
47220
- "name": "context",
47221
- "type": "SchematicContext",
47185
+ "name": "callback",
47222
47186
  "deprecated": false,
47223
47187
  "deprecationMessage": ""
47224
47188
  }
47225
47189
  ],
47226
- "returnType": "string",
47190
+ "returnType": "void",
47227
47191
  "jsdoctags": [
47228
47192
  {
47229
- "name": "source",
47230
- "type": "string",
47231
- "deprecated": false,
47232
- "deprecationMessage": "",
47233
- "tagName": {
47234
- "text": "param"
47235
- }
47236
- },
47237
- {
47238
- "name": "filePath",
47239
- "type": "string",
47193
+ "name": "dir",
47194
+ "type": "DirEntry",
47240
47195
  "deprecated": false,
47241
47196
  "deprecationMessage": "",
47242
47197
  "tagName": {
@@ -47244,8 +47199,7 @@
47244
47199
  }
47245
47200
  },
47246
47201
  {
47247
- "name": "context",
47248
- "type": "SchematicContext",
47202
+ "name": "callback",
47249
47203
  "deprecated": false,
47250
47204
  "deprecationMessage": "",
47251
47205
  "tagName": {
@@ -47253,10 +47207,12 @@
47253
47207
  }
47254
47208
  }
47255
47209
  ]
47256
- },
47210
+ }
47211
+ ],
47212
+ "packages/core/schematics/migrate-eui-icon-toggle/index.ts": [
47257
47213
  {
47258
- "name": "migrateTypeScript",
47259
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47214
+ "name": "applyEdits",
47215
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47260
47216
  "ctype": "miscellaneous",
47261
47217
  "subtype": "function",
47262
47218
  "coverageIgnore": false,
@@ -47264,7 +47220,7 @@
47264
47220
  "deprecationMessage": "",
47265
47221
  "rawdescription": "",
47266
47222
  "description": "",
47267
- "displayName": "migrateTypeScript",
47223
+ "displayName": "applyEdits",
47268
47224
  "args": [
47269
47225
  {
47270
47226
  "name": "source",
@@ -47273,14 +47229,7 @@
47273
47229
  "deprecationMessage": ""
47274
47230
  },
47275
47231
  {
47276
- "name": "filePath",
47277
- "type": "string",
47278
- "deprecated": false,
47279
- "deprecationMessage": ""
47280
- },
47281
- {
47282
- "name": "context",
47283
- "type": "SchematicContext",
47232
+ "name": "edits",
47284
47233
  "deprecated": false,
47285
47234
  "deprecationMessage": ""
47286
47235
  }
@@ -47297,17 +47246,7 @@
47297
47246
  }
47298
47247
  },
47299
47248
  {
47300
- "name": "filePath",
47301
- "type": "string",
47302
- "deprecated": false,
47303
- "deprecationMessage": "",
47304
- "tagName": {
47305
- "text": "param"
47306
- }
47307
- },
47308
- {
47309
- "name": "context",
47310
- "type": "SchematicContext",
47249
+ "name": "edits",
47311
47250
  "deprecated": false,
47312
47251
  "deprecationMessage": "",
47313
47252
  "tagName": {
@@ -47317,8 +47256,8 @@
47317
47256
  ]
47318
47257
  },
47319
47258
  {
47320
- "name": "removeImportSpecifier",
47321
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47259
+ "name": "collectRenames",
47260
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47322
47261
  "ctype": "miscellaneous",
47323
47262
  "subtype": "function",
47324
47263
  "coverageIgnore": false,
@@ -47326,20 +47265,11 @@
47326
47265
  "deprecationMessage": "",
47327
47266
  "rawdescription": "",
47328
47267
  "description": "",
47329
- "displayName": "removeImportSpecifier",
47268
+ "displayName": "collectRenames",
47330
47269
  "args": [
47331
47270
  {
47332
- "name": "namedImports",
47333
- "deprecated": false,
47334
- "deprecationMessage": ""
47335
- },
47336
- {
47337
- "name": "specifier",
47338
- "deprecated": false,
47339
- "deprecationMessage": ""
47340
- },
47341
- {
47342
- "name": "sourceFile",
47271
+ "name": "element",
47272
+ "type": "TmplAstElement",
47343
47273
  "deprecated": false,
47344
47274
  "deprecationMessage": ""
47345
47275
  },
@@ -47352,7 +47282,8 @@
47352
47282
  "returnType": "void",
47353
47283
  "jsdoctags": [
47354
47284
  {
47355
- "name": "namedImports",
47285
+ "name": "element",
47286
+ "type": "TmplAstElement",
47356
47287
  "deprecated": false,
47357
47288
  "deprecationMessage": "",
47358
47289
  "tagName": {
@@ -47360,23 +47291,37 @@
47360
47291
  }
47361
47292
  },
47362
47293
  {
47363
- "name": "specifier",
47294
+ "name": "edits",
47364
47295
  "deprecated": false,
47365
47296
  "deprecationMessage": "",
47366
47297
  "tagName": {
47367
47298
  "text": "param"
47368
47299
  }
47369
- },
47300
+ }
47301
+ ]
47302
+ },
47303
+ {
47304
+ "name": "isComponentMetadataProperty",
47305
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47306
+ "ctype": "miscellaneous",
47307
+ "subtype": "function",
47308
+ "coverageIgnore": false,
47309
+ "deprecated": false,
47310
+ "deprecationMessage": "",
47311
+ "rawdescription": "",
47312
+ "description": "",
47313
+ "displayName": "isComponentMetadataProperty",
47314
+ "args": [
47370
47315
  {
47371
- "name": "sourceFile",
47316
+ "name": "node",
47372
47317
  "deprecated": false,
47373
- "deprecationMessage": "",
47374
- "tagName": {
47375
- "text": "param"
47376
- }
47377
- },
47318
+ "deprecationMessage": ""
47319
+ }
47320
+ ],
47321
+ "returnType": "boolean",
47322
+ "jsdoctags": [
47378
47323
  {
47379
- "name": "edits",
47324
+ "name": "node",
47380
47325
  "deprecated": false,
47381
47326
  "deprecationMessage": "",
47382
47327
  "tagName": {
@@ -47386,8 +47331,8 @@
47386
47331
  ]
47387
47332
  },
47388
47333
  {
47389
- "name": "unwrapExpression",
47390
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47334
+ "name": "isTemplateProperty",
47335
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47391
47336
  "ctype": "miscellaneous",
47392
47337
  "subtype": "function",
47393
47338
  "coverageIgnore": false,
@@ -47395,18 +47340,18 @@
47395
47340
  "deprecationMessage": "",
47396
47341
  "rawdescription": "",
47397
47342
  "description": "",
47398
- "displayName": "unwrapExpression",
47343
+ "displayName": "isTemplateProperty",
47399
47344
  "args": [
47400
47345
  {
47401
- "name": "expression",
47346
+ "name": "node",
47402
47347
  "deprecated": false,
47403
47348
  "deprecationMessage": ""
47404
47349
  }
47405
47350
  ],
47406
- "returnType": "ts.Expression",
47351
+ "returnType": "boolean",
47407
47352
  "jsdoctags": [
47408
47353
  {
47409
- "name": "expression",
47354
+ "name": "node",
47410
47355
  "deprecated": false,
47411
47356
  "deprecationMessage": "",
47412
47357
  "tagName": {
@@ -47416,8 +47361,8 @@
47416
47361
  ]
47417
47362
  },
47418
47363
  {
47419
- "name": "visitDir",
47420
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47364
+ "name": "migrateEuiIconToggle",
47365
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47421
47366
  "ctype": "miscellaneous",
47422
47367
  "subtype": "function",
47423
47368
  "coverageIgnore": false,
@@ -47425,33 +47370,54 @@
47425
47370
  "deprecationMessage": "",
47426
47371
  "rawdescription": "",
47427
47372
  "description": "",
47428
- "displayName": "visitDir",
47373
+ "displayName": "migrateEuiIconToggle",
47429
47374
  "args": [
47430
47375
  {
47431
- "name": "dir",
47432
- "type": "DirEntry",
47433
- "deprecated": false,
47434
- "deprecationMessage": ""
47435
- },
47436
- {
47437
- "name": "callback",
47376
+ "name": "options",
47377
+ "type": "Schema",
47438
47378
  "deprecated": false,
47439
- "deprecationMessage": ""
47379
+ "deprecationMessage": "",
47380
+ "defaultValue": "{}"
47440
47381
  }
47441
47382
  ],
47442
- "returnType": "void",
47383
+ "returnType": "Rule",
47443
47384
  "jsdoctags": [
47444
47385
  {
47445
- "name": "dir",
47446
- "type": "DirEntry",
47386
+ "name": "options",
47387
+ "type": "Schema",
47447
47388
  "deprecated": false,
47448
47389
  "deprecationMessage": "",
47390
+ "defaultValue": "{}",
47449
47391
  "tagName": {
47450
47392
  "text": "param"
47451
47393
  }
47452
- },
47394
+ }
47395
+ ]
47396
+ },
47397
+ {
47398
+ "name": "migrateInlineTemplates",
47399
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47400
+ "ctype": "miscellaneous",
47401
+ "subtype": "function",
47402
+ "coverageIgnore": false,
47403
+ "deprecated": false,
47404
+ "deprecationMessage": "",
47405
+ "rawdescription": "",
47406
+ "description": "",
47407
+ "displayName": "migrateInlineTemplates",
47408
+ "args": [
47453
47409
  {
47454
- "name": "callback",
47410
+ "name": "source",
47411
+ "type": "string",
47412
+ "deprecated": false,
47413
+ "deprecationMessage": ""
47414
+ }
47415
+ ],
47416
+ "returnType": "string",
47417
+ "jsdoctags": [
47418
+ {
47419
+ "name": "source",
47420
+ "type": "string",
47455
47421
  "deprecated": false,
47456
47422
  "deprecationMessage": "",
47457
47423
  "tagName": {
@@ -47461,8 +47427,8 @@
47461
47427
  ]
47462
47428
  },
47463
47429
  {
47464
- "name": "visitNodes",
47465
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47430
+ "name": "migrateTemplate",
47431
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47466
47432
  "ctype": "miscellaneous",
47467
47433
  "subtype": "function",
47468
47434
  "coverageIgnore": false,
@@ -47470,67 +47436,119 @@
47470
47436
  "deprecationMessage": "",
47471
47437
  "rawdescription": "",
47472
47438
  "description": "",
47473
- "displayName": "visitNodes",
47439
+ "displayName": "migrateTemplate",
47474
47440
  "args": [
47475
47441
  {
47476
- "name": "nodes",
47442
+ "name": "source",
47443
+ "type": "string",
47477
47444
  "deprecated": false,
47478
47445
  "deprecationMessage": ""
47479
- },
47446
+ }
47447
+ ],
47448
+ "returnType": "string",
47449
+ "jsdoctags": [
47480
47450
  {
47481
47451
  "name": "source",
47482
47452
  "type": "string",
47483
47453
  "deprecated": false,
47484
- "deprecationMessage": ""
47485
- },
47454
+ "deprecationMessage": "",
47455
+ "tagName": {
47456
+ "text": "param"
47457
+ }
47458
+ }
47459
+ ]
47460
+ },
47461
+ {
47462
+ "name": "renameTsPropertyAccesses",
47463
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47464
+ "ctype": "miscellaneous",
47465
+ "subtype": "function",
47466
+ "coverageIgnore": false,
47467
+ "deprecated": false,
47468
+ "deprecationMessage": "",
47469
+ "rawdescription": "",
47470
+ "description": "",
47471
+ "displayName": "renameTsPropertyAccesses",
47472
+ "args": [
47486
47473
  {
47487
- "name": "edits",
47474
+ "name": "source",
47475
+ "type": "string",
47488
47476
  "deprecated": false,
47489
47477
  "deprecationMessage": ""
47490
- },
47478
+ }
47479
+ ],
47480
+ "returnType": "string",
47481
+ "jsdoctags": [
47491
47482
  {
47492
- "name": "filePath",
47483
+ "name": "source",
47493
47484
  "type": "string",
47494
47485
  "deprecated": false,
47495
- "deprecationMessage": ""
47496
- },
47486
+ "deprecationMessage": "",
47487
+ "tagName": {
47488
+ "text": "param"
47489
+ }
47490
+ }
47491
+ ]
47492
+ },
47493
+ {
47494
+ "name": "unwrapExpression",
47495
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47496
+ "ctype": "miscellaneous",
47497
+ "subtype": "function",
47498
+ "coverageIgnore": false,
47499
+ "deprecated": false,
47500
+ "deprecationMessage": "",
47501
+ "rawdescription": "",
47502
+ "description": "",
47503
+ "displayName": "unwrapExpression",
47504
+ "args": [
47497
47505
  {
47498
- "name": "context",
47499
- "type": "SchematicContext",
47506
+ "name": "expression",
47500
47507
  "deprecated": false,
47501
47508
  "deprecationMessage": ""
47502
47509
  }
47503
47510
  ],
47504
- "returnType": "void",
47511
+ "returnType": "ts.Expression",
47505
47512
  "jsdoctags": [
47506
47513
  {
47507
- "name": "nodes",
47514
+ "name": "expression",
47508
47515
  "deprecated": false,
47509
47516
  "deprecationMessage": "",
47510
47517
  "tagName": {
47511
47518
  "text": "param"
47512
47519
  }
47513
- },
47520
+ }
47521
+ ]
47522
+ },
47523
+ {
47524
+ "name": "visitDir",
47525
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47526
+ "ctype": "miscellaneous",
47527
+ "subtype": "function",
47528
+ "coverageIgnore": false,
47529
+ "deprecated": false,
47530
+ "deprecationMessage": "",
47531
+ "rawdescription": "",
47532
+ "description": "",
47533
+ "displayName": "visitDir",
47534
+ "args": [
47514
47535
  {
47515
- "name": "source",
47516
- "type": "string",
47536
+ "name": "dir",
47537
+ "type": "DirEntry",
47517
47538
  "deprecated": false,
47518
- "deprecationMessage": "",
47519
- "tagName": {
47520
- "text": "param"
47521
- }
47539
+ "deprecationMessage": ""
47522
47540
  },
47523
47541
  {
47524
- "name": "edits",
47542
+ "name": "callback",
47525
47543
  "deprecated": false,
47526
- "deprecationMessage": "",
47527
- "tagName": {
47528
- "text": "param"
47529
- }
47530
- },
47544
+ "deprecationMessage": ""
47545
+ }
47546
+ ],
47547
+ "returnType": "void",
47548
+ "jsdoctags": [
47531
47549
  {
47532
- "name": "filePath",
47533
- "type": "string",
47550
+ "name": "dir",
47551
+ "type": "DirEntry",
47534
47552
  "deprecated": false,
47535
47553
  "deprecationMessage": "",
47536
47554
  "tagName": {
@@ -47538,8 +47556,7 @@
47538
47556
  }
47539
47557
  },
47540
47558
  {
47541
- "name": "context",
47542
- "type": "SchematicContext",
47559
+ "name": "callback",
47543
47560
  "deprecated": false,
47544
47561
  "deprecationMessage": "",
47545
47562
  "tagName": {
@@ -47549,8 +47566,8 @@
47549
47566
  ]
47550
47567
  },
47551
47568
  {
47552
- "name": "warnRemovedProperties",
47553
- "file": "packages/core/schematics/migrate-eui-toolbar-menu/index.ts",
47569
+ "name": "visitNodes",
47570
+ "file": "packages/core/schematics/migrate-eui-icon-toggle/index.ts",
47554
47571
  "ctype": "miscellaneous",
47555
47572
  "subtype": "function",
47556
47573
  "coverageIgnore": false,
@@ -47558,22 +47575,15 @@
47558
47575
  "deprecationMessage": "",
47559
47576
  "rawdescription": "",
47560
47577
  "description": "",
47561
- "displayName": "warnRemovedProperties",
47578
+ "displayName": "visitNodes",
47562
47579
  "args": [
47563
47580
  {
47564
- "name": "sourceFile",
47565
- "deprecated": false,
47566
- "deprecationMessage": ""
47567
- },
47568
- {
47569
- "name": "filePath",
47570
- "type": "string",
47581
+ "name": "nodes",
47571
47582
  "deprecated": false,
47572
47583
  "deprecationMessage": ""
47573
47584
  },
47574
47585
  {
47575
- "name": "context",
47576
- "type": "SchematicContext",
47586
+ "name": "edits",
47577
47587
  "deprecated": false,
47578
47588
  "deprecationMessage": ""
47579
47589
  }
@@ -47581,16 +47591,7 @@
47581
47591
  "returnType": "void",
47582
47592
  "jsdoctags": [
47583
47593
  {
47584
- "name": "sourceFile",
47585
- "deprecated": false,
47586
- "deprecationMessage": "",
47587
- "tagName": {
47588
- "text": "param"
47589
- }
47590
- },
47591
- {
47592
- "name": "filePath",
47593
- "type": "string",
47594
+ "name": "nodes",
47594
47595
  "deprecated": false,
47595
47596
  "deprecationMessage": "",
47596
47597
  "tagName": {
@@ -47598,8 +47599,7 @@
47598
47599
  }
47599
47600
  },
47600
47601
  {
47601
- "name": "context",
47602
- "type": "SchematicContext",
47602
+ "name": "edits",
47603
47603
  "deprecated": false,
47604
47604
  "deprecationMessage": "",
47605
47605
  "tagName": {