diff --git a/common/web/types/src/kpj/keyman-developer-project.ts b/common/web/types/src/kpj/keyman-developer-project.ts index 841111e00a..ce9f78cf59 100644 --- a/common/web/types/src/kpj/keyman-developer-project.ts +++ b/common/web/types/src/kpj/keyman-developer-project.ts @@ -127,51 +127,38 @@ export class KeymanDeveloperProjectOptions { } }; -export type KeymanDeveloperProjectFile = KeymanDeveloperProjectFile10 | KeymanDeveloperProjectFile20; - -export class KeymanDeveloperProjectFile10 { - readonly id: string; // 1.0 only - readonly filename: string; +export interface KeymanDeveloperProjectFile { + get filename(): string; + get fileType(): string; readonly filePath: string; - readonly fileVersion: string; // 1.0 only - /** - * file extension of filename; warning: .model.ts is technically not the fileType because of 2 periods - * @deprecated use `getFileType()` - */ - readonly fileType: KeymanFileTypes.Any; // 1.0 only +}; + +export class KeymanDeveloperProjectFile10 implements KeymanDeveloperProjectFile { + get filename(): string { + return this.callbacks.path.basename(this.filePath); + } + get fileType(): string { + return KeymanFileTypes.fromFilename(this.filename); + } details: KeymanDeveloperProjectFileDetail_Kmn & KeymanDeveloperProjectFileDetail_Kps; // 1.0 only childFiles: KeymanDeveloperProjectFile[]; // 1.0 only - constructor(id: string, filename: string, filePath: string, fileVersion:string, fileType: KeymanFileTypes.Any) { + + constructor(public readonly id: string, public readonly filePath: string, public readonly fileVersion:string, private readonly callbacks: CompilerCallbacks) { this.details = {}; this.childFiles = []; - this.id = id; - this.filename = filename; - this.filePath = filePath; - this.fileVersion = fileVersion; - this.fileType = fileType; - } - getFileType() { - return KeymanFileTypes.sourceTypeFromFilename(this.filename); } }; export type KeymanDeveloperProjectFileType20 = KeymanFileTypes.Source; -export class KeymanDeveloperProjectFile20 { - readonly filename: string; - readonly filePath: string; - /** - * file extension of filename, but .model.ts is technically not the ext because of 2 periods - * @deprecated TODO: remove this from 2.0 or make it private - */ - readonly fileType: KeymanFileTypes.Source; - constructor(filePath: string, private callbacks: CompilerCallbacks) { - this.filename = this.callbacks.path.basename(filePath); - this.filePath = filePath; - this.fileType = KeymanFileTypes.sourceTypeFromFilename(this.filename); +export class KeymanDeveloperProjectFile20 implements KeymanDeveloperProjectFile { + get filename(): string { + return this.callbacks.path.basename(this.filePath); } - getFileType() { - return this.fileType; + get fileType() { + return KeymanFileTypes.fromFilename(this.filename); + } + constructor(public readonly filePath: string, private readonly callbacks: CompilerCallbacks) { } }; diff --git a/common/web/types/src/kpj/kpj-file-reader.ts b/common/web/types/src/kpj/kpj-file-reader.ts index 9e3b934c35..2c8589b5c1 100644 --- a/common/web/types/src/kpj/kpj-file-reader.ts +++ b/common/web/types/src/kpj/kpj-file-reader.ts @@ -88,10 +88,9 @@ export class KPJFileReader { for (let sourceFile of project.Files?.File) { let file: KeymanDeveloperProjectFile10 = new KeymanDeveloperProjectFile10( sourceFile.ID || '', - sourceFile.Filename || '', (sourceFile.Filepath || '').replace(/\\/g, '/'), sourceFile.FileVersion || '', - sourceFile.FileType || '' + this.callbacks ); if (sourceFile.Details) { file.details.copyright = sourceFile.Details.Copyright; diff --git a/common/web/types/src/util/file-types.ts b/common/web/types/src/util/file-types.ts index 230792d9b7..ebad759638 100644 --- a/common/web/types/src/util/file-types.ts +++ b/common/web/types/src/util/file-types.ts @@ -68,6 +68,23 @@ export type All = Source | Binary; */ export type Any = string; +/** + * Gets the file type based on extension, dealing with multi-part file + * extensions. Does not sniff contents of file or assume file existence. Does + * transform upper-cased file extensions to lower-case. + * @param filename + * @returns file extension, or `""` if no extension. Note that this return value + * differs from the other, more-specific fromFilename functions below, + * which return `null` if a supported extension is not found. + */ +export function fromFilename(filename: string): Binary | Source | Any { + const result = + sourceOrBinaryTypeFromFilename(filename) ?? + filename.match(/\.[^\.]+$/)?.[0] ?? + ""; + return result; +} + /** * Gets the file type based on extension, dealing with multi-part file * extensions. Does not sniff contents of file or assume file existence. @@ -75,7 +92,7 @@ export type Any = string; * @param filename * @returns file type, or `null` if not found */ -export function fromFilename(filename: string): Binary | Source { +export function sourceOrBinaryTypeFromFilename(filename: string): Binary | Source { filename = filename.toLowerCase(); const result = ALL_SOURCE.find(type => filename.endsWith(type)) ?? diff --git a/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts b/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts index decc5197e5..14670c99b4 100644 --- a/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts +++ b/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts @@ -81,7 +81,7 @@ export class BuildKeyboardInfo extends BuildActivity { } function findProjectFile(callbacks: CompilerCallbacks, project: KeymanDeveloperProject, ext: KeymanFileTypes.Source) { - const file = project.files.find(file => file.getFileType() == ext); + const file = project.files.find(file => file.fileType == ext); if(!file) { callbacks.reportMessage(InfrastructureMessages.Error_FileTypeNotFound({ext})); } diff --git a/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts b/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts index c20f038369..bfb167bdcc 100644 --- a/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts +++ b/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts @@ -35,19 +35,19 @@ export class BuildModelInfo extends BuildActivity { return false; } - const metadata = project.files.find(file => file.getFileType() == KeymanFileTypes.Source.ModelInfo); + const metadata = project.files.find(file => file.fileType == KeymanFileTypes.Source.ModelInfo); if(!metadata) { callbacks.reportMessage(InfrastructureMessages.Error_FileTypeNotFound({ext: KeymanFileTypes.Source.ModelInfo})); return false; } - const model = project.files.find(file => file.getFileType() == KeymanFileTypes.Source.Model); + const model = project.files.find(file => file.fileType == KeymanFileTypes.Source.Model); if(!model) { callbacks.reportMessage(InfrastructureMessages.Error_FileTypeNotFound({ext: KeymanFileTypes.Source.Model})); return false; } - const kps = project.files.find(file => file.getFileType() == KeymanFileTypes.Source.Package); + const kps = project.files.find(file => file.fileType == KeymanFileTypes.Source.Package); if(!kps) { callbacks.reportMessage(InfrastructureMessages.Error_FileTypeNotFound({ext: KeymanFileTypes.Source.Package})); return false;