From 3750f61b848b1d4ed5fb07044192380ec15e3201 Mon Sep 17 00:00:00 2001 From: Fahri Gedik Date: Tue, 21 Oct 2025 08:25:24 +0300 Subject: [PATCH 1/2] Refactor theme import and provider insertion logic --- .../src/commands/change-theme/index.ts | 89 ++++++++++++++----- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts index 6c7897eb65..bb455103f7 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -80,11 +80,11 @@ function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsE isStandalone ? removeImportsFromStandaloneProviders(appModulePath, targetThemeName) : removeProviderFromNgModuleMetadata(appModulePath, targetThemeName), + insertHelperImports(appModulePath, targetThemeName), insertImports(selectedProject, targetThemeName), insertProviders(selectedProject, targetThemeName), adjustProvideAbpThemeShared(appModulePath, targetThemeName), updateIndexHtml(selectedProject, targetThemeName), - formatFile(appModulePath), cleanEmptyExpressions(appModulePath, isStandalone), ]); }; @@ -318,39 +318,82 @@ export function removeProviderFromNgModuleMetadata( }; } -export function insertImports(projectName: string, selectedTheme: ThemeOptionsEnum): Rule { - return addRootImport(projectName, code => { +export function insertHelperImports(filePath: string, selectedTheme: ThemeOptionsEnum): Rule { + return (host: Tree) => { const selectedThemeImports = importMap.get(selectedTheme); - const selected = selectedThemeImports?.filter(s => !s.doNotImport); - if (!selected?.length) return code.code``; + const helpers = selectedThemeImports?.filter( + s => !s.doNotImport && s.importName && s.path && !s.expression && !s.provider + ); + + if (!helpers || helpers.length === 0) { + return host; + } - const expressions: string[] = []; + const buffer = host.read(filePath); + if (!buffer) return host; - for (const { importName, path, expression } of selected) { + const sourceText = buffer.toString('utf-8'); + const source = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true); + const recorder = host.beginUpdate(filePath); + + for (const { importName, path } of helpers) { + const existingImport = findNodes(source, ts.isImportDeclaration).find(node => { + const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text; + const namedBindings = node.importClause?.namedBindings; + + if (moduleSpecifier === path && namedBindings && ts.isNamedImports(namedBindings)) { + return namedBindings.elements.some(e => e.name.text === importName); + } + return false; + }); + + if (!existingImport) { + const importStatement = `import { ${importName} } from '${path}';\n`; + recorder.insertLeft(0, importStatement); + } + } + + host.commitUpdate(recorder); + return host; + }; +} + +export function insertImports(projectName: string, selectedTheme: ThemeOptionsEnum): Rule { + const selectedThemeImports = importMap.get(selectedTheme); + const selected = selectedThemeImports?.filter(s => !s.doNotImport && !!s.expression); + + if (!selected || selected.length === 0) { + return () => {}; + } + + return addRootImport(projectName, code => { + const expressions = selected.map(({ importName, path, expression }) => { if (importName && path) { code.external(importName, path); } - if (expression) { - expressions.push(expression.trim()); - } - } - return code.code`${expressions}`; + return expression!.trim(); + }); + + return code.code` +${expressions.join(',\n')}`; }); } export function insertProviders(projectName: string, selectedTheme: ThemeOptionsEnum): Rule { - return addRootProvider(projectName, code => { - const selectedThemeImports = importMap.get(selectedTheme); - const selected = selectedThemeImports?.filter(s => !s.doNotImport); - if (!selected || selected.length === 0) return code.code``; + const selectedThemeImports = importMap.get(selectedTheme); + const selected = selectedThemeImports?.filter(s => !s.doNotImport && !!s.provider); + + if (!selected || selected.length === 0) { + return () => {}; + } - const providers = selected - .filter(s => !!s.provider) - .map(({ provider, path, importName }) => { - code.external(importName, path); - return `${provider}`; - }); + return addRootProvider(projectName, code => { + const providers = selected.map(({ provider, path, importName }) => { + code.external(importName, path); + return provider; + }); - return code.code`${providers}`; + return code.code` +${providers.join(',\n')}`; }); } From 2b152e05f2050fa30cd318b4fa04459458d6b2c4 Mon Sep 17 00:00:00 2001 From: Fahri Gedik Date: Tue, 21 Oct 2025 08:25:31 +0300 Subject: [PATCH 2/2] Update style-map.ts --- .../src/commands/change-theme/style-map.ts | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts index 49cde5070f..b401c42f4d 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts @@ -272,16 +272,13 @@ importMap.set(ThemeOptionsEnum.Basic, [ path: '@abp/ng.theme.basic', importName: 'ThemeBasicModule', expression: 'ThemeBasicModule', - }, - { - path: '@abp/ng.theme.basic', - importName: 'provideThemeBasicConfig', - provider: 'provideThemeBasicConfig()', + doNotImport: true, }, { path: '@abp/ng.theme.shared', importName: 'ThemeSharedModule', expression: 'ThemeSharedModule', + doNotImport: true, }, { path: '@abp/ng.theme.shared', @@ -292,18 +289,24 @@ importMap.set(ThemeOptionsEnum.Basic, [ importName: 'provideAbpThemeShared', provider: 'provideAbpThemeShared()', }, + { + path: '@abp/ng.theme.basic', + importName: 'provideThemeBasicConfig', + provider: 'provideThemeBasicConfig()', + }, ]); importMap.set(ThemeOptionsEnum.Lepton, [ - { - path: '@volo/abp.ng.theme.lepton', - importName: 'provideThemeLepton', - provider: 'provideThemeLepton()', - }, { path: '@abp/ng.theme.shared', importName: 'ThemeSharedModule', expression: 'ThemeSharedModule', + doNotImport: true, + }, + { + path: '@volo/abp.ng.theme.lepton', + importName: 'provideThemeLepton', + provider: 'provideThemeLepton()', }, { path: '@abp/ng.theme.shared', @@ -325,21 +328,31 @@ importMap.set(ThemeOptionsEnum.LeptonXLite, [ path: '@abp/ng.theme.lepton-x', importName: 'ThemeLeptonXModule', expression: 'ThemeLeptonXModule.forRoot()', + doNotImport: true, }, { path: '@abp/ng.theme.lepton-x/layouts', importName: 'SideMenuLayoutModule', expression: 'SideMenuLayoutModule.forRoot()', + doNotImport: true, + }, + { + path: '@abp/ng.theme.lepton-x/layouts', + importName: 'TopMenuLayoutModule', + expression: 'TopMenuLayoutModule.forRoot()', + doNotImport: true, }, { path: '@abp/ng.theme.lepton-x/account', importName: 'AccountLayoutModule', expression: 'AccountLayoutModule.forRoot()', + doNotImport: true, }, { path: '@abp/ng.theme.shared', importName: 'ThemeSharedModule', expression: 'ThemeSharedModule', + doNotImport: true, }, { path: '@abp/ng.theme.shared', @@ -354,6 +367,22 @@ importMap.set(ThemeOptionsEnum.LeptonXLite, [ importName: 'provideAbpThemeShared', provider: 'provideAbpThemeShared()', }, + { + path: '@abp/ng.theme.lepton-x', + importName: 'provideThemeLeptonX', + provider: 'provideThemeLeptonX()', + }, + { + path: '@abp/ng.theme.lepton-x/layouts', + importName: 'provideSideMenuLayout', + provider: 'provideSideMenuLayout()', + }, + { + path: '@abp/ng.theme.lepton-x/layouts', + importName: 'provideTopMenuLayout', + provider: 'provideTopMenuLayout()', + doNotImport: true, + }, ]); importMap.set(ThemeOptionsEnum.LeptonX, [ @@ -361,11 +390,13 @@ importMap.set(ThemeOptionsEnum.LeptonX, [ path: '@volosoft/abp.ng.theme.lepton-x', importName: 'ThemeLeptonXModule', expression: 'ThemeLeptonXModule.forRoot()', + doNotImport: true, }, { path: '@volosoft/abp.ng.theme.lepton-x/layouts', importName: 'SideMenuLayoutModule', expression: 'SideMenuLayoutModule.forRoot()', + doNotImport: true, }, { path: '@volosoft/abp.ng.theme.lepton-x/layouts', @@ -377,6 +408,7 @@ importMap.set(ThemeOptionsEnum.LeptonX, [ path: '@abp/ng.theme.shared', importName: 'ThemeSharedModule', expression: 'ThemeSharedModule', + doNotImport: true, }, { path: '@volosoft/abp.ng.theme.lepton-x', @@ -390,6 +422,22 @@ importMap.set(ThemeOptionsEnum.LeptonX, [ path: '@abp/ng.theme.shared', importName: 'withValidationBluePrint', }, + { + path: '@volosoft/abp.ng.theme.lepton-x', + importName: 'provideThemeLeptonX', + provider: 'provideThemeLeptonX()', + }, + { + path: '@volosoft/abp.ng.theme.lepton-x/layouts', + importName: 'provideSideMenuLayout', + provider: 'provideSideMenuLayout()', + }, + { + path: '@volosoft/abp.ng.theme.lepton-x/layouts', + importName: 'provideTopMenuLayout', + provider: 'provideTopMenuLayout()', + doNotImport: true, + }, { path: '@abp/ng.theme.shared', importName: 'provideAbpThemeShared',