diff --git a/README.md b/README.md index edf384a..2a9454d 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,16 @@ The check command will check if the yaml files in your current working directory ## generate -Generate provides typescript language files according to your specification. It only works in your current working directoy's `language` folder and will output to `ssrc/locales` by default. +Generate provides typescript language files according to your specification. It only works in your current working directory's `language` folder and will output to `ssrc/locales` by default. Options: -- `--strict-types` apply strict types, so that typescript will error on build if the structures missmatch +- `--strict-types` apply strict types, so that typescript will error on build if the structures mismatch - `--verbatim-module-syntax` will export the type as a named export instead of a default one -- `--split` splits the language files at the top level keys.. Thhis leads to smaller files when using dynamic imports. Usually you want `--no-translations-file` as well in case of splitting. -- `--no-translations-file` dissables the creation of a translation object containing all languages +- `--simplified-hash-map` will convert the multi tiered object to a single level hash map for speed reasons. +- `--inject-default-language` will create a file based on the default language. Only works with `--simplified-hash-map` active at the same time. +- `--split` splits the language files at the top level keys. This leads to smaller files when using dynamic imports. Usually you want `--no-translations-file` as well in case of splitting. +- `--no-translations-file` disables the creation of a translation object containing all languages ## watch diff --git a/package.json b/package.json index 7075083..0f5409e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@idrinth-api-bench/typescript-language-from-yaml", - "version": "1.3.1", + "version": "1.4.0", "description": "Translates yaml files to ts for translation autocompletion, autocorrection and better developer support", "bin": { "itlfy": "bin/itlfy.js" diff --git a/src/build-translation-file.ts b/src/build-translation-file.ts index 7576e4e..30ce45d 100644 --- a/src/build-translation-file.ts +++ b/src/build-translation-file.ts @@ -1,7 +1,8 @@ import toTypescriptObject from './to-typescript-object.js'; import Config from './config.js'; +import simplifyObject from './simplify-object.js'; -export default (config: Config, data: object,) => { +export default (config: Config, data: object, def: object,) => { const head = (() => { if (! config.isStrictTypes) { return 'const lang = '; @@ -12,5 +13,6 @@ export default (config: Config, data: object,) => { return 'import {\n lang as langType,\n} from \'./type.js\';' + '\nconst lang: langType = '; })(); - return `/* eslint max-len:0 */\n${ head }${ toTypescriptObject(data,) };\n\nexport default lang;\n`; + const tsObj = toTypescriptObject(simplifyObject(config, data, def,),); + return `/* eslint max-len:0 */\n${ head }${ tsObj };\n\nexport default lang;\n`; }; diff --git a/src/config.ts b/src/config.ts index a037d2c..3a60a20 100644 --- a/src/config.ts +++ b/src/config.ts @@ -26,8 +26,14 @@ export default class Config { public readonly isSplit: boolean; + public readonly isSimplifiedHashMap: boolean; + + public readonly shouldInjectDefaultLanguage: boolean; + public readonly folders: string[]; + public readonly overwrites: string[] = []; + // eslint-disable-next-line complexity constructor(cwd: string, args: string[] = [],) { const file = `${ cwd }/${ CONFIG_FILE }`; @@ -38,6 +44,8 @@ export default class Config { this.targetDirectory = 'src/locales'; this.isStrictTypes = false; this.isVerbatimModuleSyntax = false; + this.isSimplifiedHashMap = false; + this.shouldInjectDefaultLanguage = false; if (existsSync(file,)) { const data = parse(readFileSync(file, 'utf8',),); if (typeof data.hasNoTranslationsFile === 'boolean') { @@ -61,21 +69,40 @@ export default class Config { if (typeof data.hasNoTranslationsFile === 'boolean') { this.isVerbatimModuleSyntax = data.isVerbatimModuleSyntax; } + if (typeof data.shouldInjectDefaultLanguage === 'boolean') { + this.shouldInjectDefaultLanguage = data.shouldInjectDefaultLanguage; + } + if (typeof data.isSimplifiedHashMap === 'boolean') { + this.isSimplifiedHashMap = data.isSimplifiedHashMap; + } } if (args.includes('--no-translation-files',)) { this.hasNoTranslationsFile = true; + this.overwrites.push('--no-translation-files',); } if (args.includes('--split',)) { this.isSplit = true; + this.overwrites.push('--split',); } if (args.includes('--fail-on-warning',)) { this.isFailOnWarning = true; + this.overwrites.push('--fail-on-warning',); } if (args.includes('--strict-types',)) { this.isStrictTypes = true; + this.overwrites.push('--strict-types',); } if (args.includes('--verbatim-module-syntax',)) { this.isVerbatimModuleSyntax = true; + this.overwrites.push('--verbatim-module-syntax',); + } + if (args.includes('--inject-default-language',)) { + this.shouldInjectDefaultLanguage = true; + this.overwrites.push('--inject-default-language',); + } + if (args.includes('--simplified-hash-map',)) { + this.isSimplifiedHashMap = true; + this.overwrites.push('--simplified-hash-map',); } this.folders = args .slice(SECOND_ARGUMENT,) diff --git a/src/generate.ts b/src/generate.ts index 7d5f642..59db7a2 100644 --- a/src/generate.ts +++ b/src/generate.ts @@ -24,7 +24,7 @@ export default ( config: Config, ) => { for (const folder of config.folders) { - const localConfig = new Config(`${ folder }`,); + const localConfig = new Config(`${ folder }`, config.overwrites,); if (existsSync(`${ folder }/${ localConfig.targetDirectory }`,)) { for (const file of readdirSync( `${ folder }/${ localConfig.targetDirectory }`, @@ -34,7 +34,12 @@ export default ( } } const yamlFiles = findYamlFiles(folder, localConfig,); - + const def = localConfig.shouldInjectDefaultLanguage + ? parse(readFileSync( + `${ folder }/${ localConfig.originDirectory }/en.yml`, + 'utf8', + ),) + : {}; const files = []; const out = `${ folder }/${ localConfig.targetDirectory }`; if (! existsSync(out,)) { @@ -50,7 +55,7 @@ export default ( for (const key of Object.keys(data,)) { writeFileSync( `${ out }/${ yamlFile.language }-${ key }.ts`, - buildTranslationFile(localConfig, data[key],), + buildTranslationFile(localConfig, data[key], def[key],), 'utf8', ); files.push(`${ yamlFile.language }-${ key }`,); @@ -67,7 +72,7 @@ export default ( } else { writeFileSync( `${ out }/${ yamlFile.language }.ts`, - buildTranslationFile(localConfig, data,), + buildTranslationFile(localConfig, data, def,), 'utf8', ); files.push(`${ yamlFile.language }`,); diff --git a/src/simplify-object.ts b/src/simplify-object.ts new file mode 100644 index 0000000..2a55d4f --- /dev/null +++ b/src/simplify-object.ts @@ -0,0 +1,22 @@ +import Config from './config.js'; + +export default (config: Config, data: object, def: object,): object => { + if (! config.isSimplifiedHashMap) { + return data; + } + const simplified = {}; + const simplify = (prefix: string, obj: object,) => { + for (const key of Object.keys(obj,)) { + if (typeof obj[key] === 'string') { + simplified[prefix + key] = obj[key]; + } else if (typeof obj[key] === 'object') { + simplify(prefix + key + '.', obj[key],); + } + } + }; + if (config.shouldInjectDefaultLanguage) { + simplify('', def,); + } + simplify('', data,); + return simplified; +}; diff --git a/src/to-typescript-object.ts b/src/to-typescript-object.ts index dc7b7aa..916cb56 100644 --- a/src/to-typescript-object.ts +++ b/src/to-typescript-object.ts @@ -5,7 +5,7 @@ import { export default (data: object,): string => JSON .stringify(data, null, DEFAULT_INDENTATION,) .replace(/'/ug, '\\\\\'',) - .replace(/"([a-z][^"-]+?)":/ug, '$1:',) + .replace(/"([a-z][^a-z0-9A-Z_]+?)":/ug, '$1:',) .replace(/"([^"]+?)":/ug, '\'$1\':',) .replace(/\n/ug, ',\n',) .replace(/"([^"]+?)",/ug, '\'$1\',',) diff --git a/src/watch.ts b/src/watch.ts index cf3542d..b9b0e7d 100644 --- a/src/watch.ts +++ b/src/watch.ts @@ -20,7 +20,7 @@ export default async( while (true) { const now = Date.now(); for (const folder of config.folders) { - const localConfig = new Config(folder,); + const localConfig = new Config(folder, config.overwrites,); let modified = false; for (const file of readdirSync( `${ folder }/${ localConfig.originDirectory }`,