From 73ccfb31bfbd149268770793523e333a2e50fd3b Mon Sep 17 00:00:00 2001 From: jakiette Date: Thu, 20 Jul 2017 14:40:16 -0400 Subject: [PATCH] feat(IonicPage): add config option for module filename --- src/deep-linking/util.spec.ts | 27 ++++++++++++-------- src/deep-linking/util.ts | 26 ++++++++++++++----- src/upgrade-scripts/add-default-ngmodules.ts | 4 +-- src/util/helpers.ts | 7 +++++ src/util/interfaces.ts | 1 + 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/deep-linking/util.spec.ts b/src/deep-linking/util.spec.ts index b4bbbdf4..fea96c5f 100644 --- a/src/deep-linking/util.spec.ts +++ b/src/deep-linking/util.spec.ts @@ -59,6 +59,7 @@ import { IonicPage, NavController } from 'ionic-angular'; @IonicPage({ name: 'someName', + moduleName: 'someModuleName', segment: 'someSegmentBro', defaultHistory: ['page-one', 'page-two'], priority: 'high' @@ -100,8 +101,9 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('someName'); + expect(result.moduleName).toEqual('someModuleName'); expect(result.segment).toEqual('someSegmentBro'); expect(result.defaultHistory[0]).toEqual('page-one'); expect(result.defaultHistory[1]).toEqual('page-two'); @@ -158,7 +160,7 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('HomePage'); expect(result.segment).toEqual('someSegmentBro'); expect(result.defaultHistory[0]).toEqual('page-one'); @@ -215,7 +217,7 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('HomePage'); expect(result.segment).toEqual('path'); expect(result.defaultHistory[0]).toEqual('page-one'); @@ -271,7 +273,7 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('HomePage'); expect(result.segment).toEqual('about'); expect(result.defaultHistory).toBeTruthy(); @@ -326,7 +328,7 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('HomePage'); expect(result.segment).toEqual('path'); expect(result.defaultHistory).toBeTruthy(); @@ -380,7 +382,7 @@ export class HomePage { const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result.name).toEqual('HomePage'); expect(result.segment).toEqual('path'); expect(result.defaultHistory).toBeTruthy(); @@ -441,7 +443,7 @@ export class HomePage { try { - util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); throw new Error(knownErrorMsg); } catch (ex) { expect(ex.message).not.toEqual(knownErrorMsg); @@ -490,7 +492,7 @@ export class HomePage { const knownPath = join(process.cwd(), 'some', 'fake', 'path'); const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result).toEqual(null); }); @@ -533,7 +535,7 @@ export function removeDecorators(fileName: string, source: string): string { const knownPath = join(process.cwd(), 'some', 'fake', 'path'); const sourceFile = tsUtils.getTypescriptSourceFile(knownPath, knownContent); - const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile); + const result = util.getDeepLinkDecoratorContentForSourceFile(sourceFile, knownPath); expect(result).toEqual(null); }); }); @@ -546,7 +548,7 @@ export function removeDecorators(fileName: string, source: string): string { spyOn(helpers, helpers.getStringPropertyValue.name).and.returnValue('.module.ts'); - const result = util.getNgModulePathFromCorrespondingPage(pagePath); + const result = util.getNgModulePathFromCorrespondingPage(pagePath, null); expect(result).toEqual(ngModulePath); }); }); @@ -1542,6 +1544,7 @@ export class AppModule {} it('should convert to a flat string format', () => { const entry: DeepLinkConfigEntry = { name: 'HomePage', + moduleName: null, segment: null, defaultHistory: [], priority: 'low', @@ -1558,6 +1561,7 @@ export class AppModule {} it('should handle defaultHistory entries and segment', () => { const entry: DeepLinkConfigEntry = { name: 'HomePage', + moduleName: null, segment: 'idkMan', defaultHistory: ['page-two', 'page-three', 'page-four'], priority: 'low', @@ -1577,6 +1581,7 @@ export class AppModule {} const list: DeepLinkConfigEntry[] = []; list.push({ name: 'HomePage', + moduleName: 'someModuleName', segment: 'idkMan', defaultHistory: ['page-two', 'page-three', 'page-four'], priority: 'low', @@ -1587,6 +1592,7 @@ export class AppModule {} }); list.push({ name: 'PageTwo', + moduleName: null, segment: null, defaultHistory: [], priority: 'low', @@ -1597,6 +1603,7 @@ export class AppModule {} }); list.push({ name: 'SettingsPage', + moduleName: null, segment: null, defaultHistory: [], priority: 'low', diff --git a/src/deep-linking/util.ts b/src/deep-linking/util.ts index 686c4cae..7b7d0117 100644 --- a/src/deep-linking/util.ts +++ b/src/deep-linking/util.ts @@ -17,7 +17,7 @@ import { import { Logger } from '../logger/logger'; import * as Constants from '../util/constants'; import { FileCache } from '../util/file-cache'; -import { changeExtension, getStringPropertyValue, replaceAll, toUnixPath } from '../util/helpers'; +import { changeExtension, changeModuleName, getStringPropertyValue, replaceAll, toUnixPath } from '../util/helpers'; import { BuildContext, ChangedFile, DeepLinkConfigEntry, DeepLinkDecoratorAndClass, DeepLinkPathInfo, File } from '../util/interfaces'; import { appendAfter, @@ -38,11 +38,11 @@ export function getDeepLinkData(appNgModuleFilePath: string, fileCache: FileCach const deepLinkConfigEntries: DeepLinkConfigEntry[] = []; typescriptFiles.forEach(file => { const sourceFile = getTypescriptSourceFile(file.path, file.content); - const deepLinkDecoratorData = getDeepLinkDecoratorContentForSourceFile(sourceFile); + const deepLinkDecoratorData = getDeepLinkDecoratorContentForSourceFile(sourceFile, file.path); if (deepLinkDecoratorData) { // sweet, the page has a DeepLinkDecorator, which means it meets the criteria to process that bad boy - const pathInfo = getNgModuleDataFromPage(appNgModuleFilePath, file.path, deepLinkDecoratorData.className, fileCache, isAot); + const pathInfo = getNgModuleDataFromPage(appNgModuleFilePath, file.path, deepLinkDecoratorData.className, fileCache, isAot, deepLinkDecoratorData.moduleName); const deepLinkConfigEntry = Object.assign({}, deepLinkDecoratorData, pathInfo); deepLinkConfigEntries.push(deepLinkConfigEntry); } @@ -56,8 +56,13 @@ export function filterTypescriptFilesForDeepLinks(fileCache: FileCache): File[] return fileCache.getAll().filter(file => extname(file.path) === '.ts' && file.path.indexOf(moduleSuffix) === -1 && file.path.indexOf(deepLinksDir) >= 0); } -export function getNgModulePathFromCorrespondingPage(filePath: string) { +export function getNgModulePathFromCorrespondingPage(filePath: string, moduleName: string) { const newExtension = getStringPropertyValue(Constants.ENV_NG_MODULE_FILE_NAME_SUFFIX); + + if (moduleName) { + filePath = changeModuleName(filePath, moduleName); + } + return changeExtension(filePath, newExtension); } @@ -65,9 +70,10 @@ export function getRelativePathToPageNgModuleFromAppNgModule(pathToAppNgModule: return relative(dirname(pathToAppNgModule), pathToPageNgModule); } -export function getNgModuleDataFromPage(appNgModuleFilePath: string, filePath: string, className: string, fileCache: FileCache, isAot: boolean): DeepLinkPathInfo { - const ngModulePath = getNgModulePathFromCorrespondingPage(filePath); +export function getNgModuleDataFromPage(appNgModuleFilePath: string, filePath: string, className: string, fileCache: FileCache, isAot: boolean, moduleName?: string): DeepLinkPathInfo { + const ngModulePath = getNgModulePathFromCorrespondingPage(filePath, moduleName); let ngModuleFile = fileCache.get(ngModulePath); + if (!ngModuleFile) { throw new Error(`${filePath} has a @IonicPage decorator, but it does not have a corresponding "NgModule" at ${ngModulePath}`); } @@ -86,7 +92,7 @@ export function getNgModuleDataFromPage(appNgModuleFilePath: string, filePath: s }; } -export function getDeepLinkDecoratorContentForSourceFile(sourceFile: SourceFile): DeepLinkDecoratorAndClass { +export function getDeepLinkDecoratorContentForSourceFile(sourceFile: SourceFile, filePath: string): DeepLinkDecoratorAndClass { const classDeclarations = getClassDeclarations(sourceFile); const defaultSegment = basename(changeExtension(sourceFile.fileName, '')); const list: DeepLinkDecoratorAndClass[] = []; @@ -106,13 +112,18 @@ export function getDeepLinkDecoratorContentForSourceFile(sourceFile: SourceFile) propertyList = deepLinkObject.properties; } + const extension = extname(filePath); + const extensionlessfileName = basename(filePath, extension); + const deepLinkName = getStringValueFromDeepLinkDecorator(sourceFile, propertyList, className, DEEPLINK_DECORATOR_NAME_ATTRIBUTE); + const deepLinkModuleName = getStringValueFromDeepLinkDecorator(sourceFile, propertyList, extensionlessfileName, DEEPLINK_DECORATOR_MODULE_NAME_ATTRIBUTE); const deepLinkSegment = getStringValueFromDeepLinkDecorator(sourceFile, propertyList, defaultSegment, DEEPLINK_DECORATOR_SEGMENT_ATTRIBUTE); const deepLinkPriority = getStringValueFromDeepLinkDecorator(sourceFile, propertyList, 'low', DEEPLINK_DECORATOR_PRIORITY_ATTRIBUTE); const deepLinkDefaultHistory = getArrayValueFromDeepLinkDecorator(sourceFile, propertyList, [], DEEPLINK_DECORATOR_DEFAULT_HISTORY_ATTRIBUTE); const rawStringContent = getNodeStringContent(sourceFile, decorator.expression); list.push({ name: deepLinkName, + moduleName: deepLinkModuleName, segment: deepLinkSegment, priority: deepLinkPriority, defaultHistory: deepLinkDefaultHistory, @@ -378,6 +389,7 @@ export class ${className}Module {} const DEEPLINK_DECORATOR_TEXT = 'IonicPage'; const DEEPLINK_DECORATOR_NAME_ATTRIBUTE = 'name'; const DEEPLINK_DECORATOR_SEGMENT_ATTRIBUTE = 'segment'; +const DEEPLINK_DECORATOR_MODULE_NAME_ATTRIBUTE = 'moduleName'; const DEEPLINK_DECORATOR_PRIORITY_ATTRIBUTE = 'priority'; const DEEPLINK_DECORATOR_DEFAULT_HISTORY_ATTRIBUTE = 'defaultHistory'; diff --git a/src/upgrade-scripts/add-default-ngmodules.ts b/src/upgrade-scripts/add-default-ngmodules.ts index 57a21230..7b4b5f92 100644 --- a/src/upgrade-scripts/add-default-ngmodules.ts +++ b/src/upgrade-scripts/add-default-ngmodules.ts @@ -32,10 +32,10 @@ export function readTsFiles(context: BuildContext, tsFilePaths: string[]) { export function generateAndWriteNgModules(fileCache: FileCache) { fileCache.getAll().forEach(file => { const sourceFile = getTypescriptSourceFile(file.path, file.content); - const deepLinkDecoratorData = getDeepLinkDecoratorContentForSourceFile(sourceFile); + const deepLinkDecoratorData = getDeepLinkDecoratorContentForSourceFile(sourceFile, file.path); if (deepLinkDecoratorData) { // we have a valid DeepLink decorator - const correspondingNgModulePath = getNgModulePathFromCorrespondingPage(file.path); + const correspondingNgModulePath = getNgModulePathFromCorrespondingPage(file.path, deepLinkDecoratorData.moduleName); const ngModuleFile = fileCache.get(correspondingNgModulePath); if (!ngModuleFile) { // the ngModule file does not exist, so go ahead and create a default one diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 7353fd91..8b24d478 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -260,6 +260,13 @@ export function changeExtension(filePath: string, newExtension: string) { return join(dir, newFileName); } +export function changeModuleName(filePath: string, newModuleName: string) { + const dir = dirname(filePath); + const extension = extname(filePath); + const newFileName = newModuleName + extension; + return join(dir, newFileName); +} + export function escapeHtml(unsafe: string) { return unsafe .replace(/&/g, '&') diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts index 0fe6a515..be6474d6 100644 --- a/src/util/interfaces.ts +++ b/src/util/interfaces.ts @@ -164,6 +164,7 @@ export interface VirtualFileSystem { export interface DeepLinkDecoratorAndClass { name: string; + moduleName: string; segment: string; defaultHistory: string[]; priority: string;