From 44dc073c16d3cfeba026d8ca3ffaed76dda9a1ab Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Tue, 19 Sep 2023 16:51:17 +0900 Subject: [PATCH] feat: `format` and `ast` option for compile command (#67) --- locales/en.json | 1 + locales/ja.json | 1 + src/api/compile.ts | 8 + src/commands/compile.ts | 10 + .../__snapshots__/compile.test.ts.snap | 252 ++++++++++++++++++ test/commands/compile.test.ts | 23 +- test/fixtures/commands/compile-ast.json | 26 ++ 7 files changed, 316 insertions(+), 5 deletions(-) create mode 100644 test/commands/__snapshots__/compile.test.ts.snap create mode 100644 test/fixtures/commands/compile-ast.json diff --git a/locales/en.json b/locales/en.json index 9567190..096bb99 100644 --- a/locales/en.json +++ b/locales/en.json @@ -5,6 +5,7 @@ "the i18n resource source path": "the i18n resource source path", "the compiled i18n resource output path": "the compiled i18n resource output path", "the compiled i18n resource mode, 'production' or 'development' (default: 'production')": "the compiled i18n resource mode, 'production' or 'development' (default: 'production')", + "resource compilation format, 'function' or 'ast' (default: 'function')": "resource compilation format, 'function' or 'ast' (default: 'function')", "Success compilation: {source} -> {output}": "Success compilation: {source} -> {output}", "{source}: Ignore compilation due to not supported '{ext}'": "{source}: Ignore compilation due to not supported '{ext}'", "Warning compilation: {source} -> {output}, {msg}": "Warning compilation: {source} -> {output}, {msg}", diff --git a/locales/ja.json b/locales/ja.json index a453d9f..ca5b48f 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -4,6 +4,7 @@ "the i18n resource source path": "コンパイルされる i18n リソースのパス", "the compiled i18n resource output path": "コンパイルされた i18n リソースの出力先パス", "the compiled i18n resource mode, 'production' or 'development' (default: 'production')": "コンパイルされる i18n リソースのモード, 'production' または 'development' (デフォルト: 'production')", + "resource compilation format, 'function' or 'ast' (default: 'function')": "コンパイルされるリソースフォーマット, 'function' または 'ast' (デフォルト: 'function')", "Success compilation: {source} -> {output}": "コンパイル成功: {source} -> {output}", "{source}: Ignore compilation due to not supported '{ext}'": "{source}: '{ext}' がサポートされていないためコンパイルされません", "Warning compilation: {source} -> {output}, {msg}": "コンパイル警告: {source} -> {output}, {msg}", diff --git a/src/api/compile.ts b/src/api/compile.ts index ff8dbb6..2fe5f1d 100644 --- a/src/api/compile.ts +++ b/src/api/compile.ts @@ -57,6 +57,13 @@ export interface CompileOptions { * The mode of code generation. Default `production` for optimization. If `development`, code generated with meta information from i18n resources. */ mode?: DevEnv + /** + * Whether to generate AST format + * + * @remarks + * default `false`, it will output the function format. + */ + ast?: boolean } const COMPILE_MODE = ['production', 'development'] as const @@ -114,6 +121,7 @@ export async function compile( const { code } = generate(source, { type: 'plain', filename: target, + jit: !!options.ast, env, onError: (msg: string): void => { occuredError = true diff --git a/src/commands/compile.ts b/src/commands/compile.ts index d56fbb6..bd88454 100644 --- a/src/commands/compile.ts +++ b/src/commands/compile.ts @@ -13,6 +13,7 @@ type CompileOptions = { source: string output?: string mode?: string + format?: string } export default function defineCommand() { @@ -41,6 +42,14 @@ export default function defineCommand() { "the compiled i18n resource mode, 'production' or 'development' (default: 'production')" ) }) + .option('format', { + type: 'string', + alias: 'f', + default: 'function', + describe: t( + "resource compilation format, 'function' or 'ast' (default: 'function')" + ) + }) } const handler = async (args: Arguments): Promise => { @@ -50,6 +59,7 @@ export default function defineCommand() { : process.cwd() const ret = await compile(args.source, output, { mode: args.mode as DevEnv, + ast: args.format === 'ast', onCompile: (source: string, output: string): void => { console.log( green( diff --git a/test/commands/__snapshots__/compile.test.ts.snap b/test/commands/__snapshots__/compile.test.ts.snap new file mode 100644 index 0000000..3d757a2 --- /dev/null +++ b/test/commands/__snapshots__/compile.test.ts.snap @@ -0,0 +1,252 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`compile > ast format 1`] = ` +{ + "backslash-backslash": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "\\\\\\\\", + "t": 2, + }, + "t": 0, + }, + "backslash-single-quote": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "\\\\'", + "t": 2, + }, + "t": 0, + }, + "complex": { + "warnings": [ + { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "NOTE: This is warning", + "t": 2, + }, + "t": 0, + }, + { + "named-waring": { + "b": { + "i": [ + { + "t": 3, + "v": "this is ", + }, + { + "k": "type", + "t": 4, + }, + { + "t": 3, + "v": " warining", + }, + ], + "t": 2, + }, + "t": 0, + }, + }, + ], + }, + "emoji": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "😺", + "t": 2, + }, + "t": 0, + }, + "errors": [ + { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "ERROR1001", + "t": 2, + }, + "t": 0, + }, + { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "ERROR1002", + "t": 2, + }, + "t": 0, + }, + ], + "hi": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "hi there!", + "t": 2, + }, + "t": 0, + }, + "nested": { + "hello": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "hello world!", + "t": 2, + }, + "t": 0, + }, + "list": { + "b": { + "i": [ + { + "t": 3, + "v": "hi, ", + }, + { + "i": 0, + "t": 5, + }, + { + "t": 3, + "v": " !", + }, + ], + "t": 2, + }, + "t": 0, + }, + "more": { + "plural": { + "b": { + "c": [ + { + "i": [ + { + "k": { + "t": 9, + "v": "no apples", + }, + "m": { + "t": 8, + "v": "caml", + }, + "t": 6, + }, + ], + "t": 2, + }, + { + "i": [ + { + "i": 0, + "t": 5, + }, + { + "t": 3, + "v": " apple", + }, + ], + "t": 2, + }, + { + "i": [ + { + "k": "n", + "t": 4, + }, + { + "t": 3, + "v": " apples", + }, + ], + "t": 2, + }, + ], + "t": 1, + }, + "t": 0, + }, + }, + }, + "single-quote": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "I don't know!", + "t": 2, + }, + "t": 0, + }, + "unicode": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "A", + "t": 2, + }, + "t": 0, + }, + "unicode-escape": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "\\\\u0041", + "t": 2, + }, + "t": 0, + }, + "こんにちは": { + "b": { + "i": [ + { + "t": 3, + }, + ], + "s": "こんにちは!", + "t": 2, + }, + "t": 0, + }, +} +`; diff --git a/test/commands/compile.test.ts b/test/commands/compile.test.ts index 7e03d44..6f5d5d7 100644 --- a/test/commands/compile.test.ts +++ b/test/commands/compile.test.ts @@ -11,18 +11,18 @@ const __dirname = dirname(fileURLToPath(import.meta.url)) const CWD = resolve(__dirname, '../../') let orgCwd -beforeEach(async function () { +beforeEach(async () => { await initI18n() orgCwd = process.cwd process.cwd = vi.fn().mockImplementation(() => CWD) }) -afterEach(function () { +afterEach(() => { process.cwd = orgCwd }) -describe('compile', function () { - it('basic', async function () { +describe('compile', () => { + it('basic', async () => { const cmd = yargs() // @ts-expect-error cmd.command(compile()) @@ -40,7 +40,7 @@ describe('compile', function () { expect(await prettier(compiled)).toBe(await prettier(expected)) }) - it('--mode development', async function () { + it('--mode development', async () => { const cmd = yargs() // @ts-expect-error cmd.command(compile()) @@ -57,4 +57,17 @@ describe('compile', function () { ) expect(await prettier(compiled)).toBe(await prettier(expected)) }) + + it('ast format', async () => { + const cmd = yargs() + // @ts-expect-error + cmd.command(compile()) + await cmd.parse( + `compile --source ./test/fixtures/commands/compile-ast.json --output ./temp --format ast` + ) + const code = await import( + resolve(__dirname, '../../temp/compile-ast.js') + ).then(m => m.default || m) + expect(code).toMatchSnapshot() + }) }) diff --git a/test/fixtures/commands/compile-ast.json b/test/fixtures/commands/compile-ast.json new file mode 100644 index 0000000..9699cd9 --- /dev/null +++ b/test/fixtures/commands/compile-ast.json @@ -0,0 +1,26 @@ +{ + "hi": "hi there!", + "nested": { + "hello": "hello world!", + "more": { + "plural": "@.caml:{'no apples'} | {0} apple | {n} apples" + }, + "list": "hi, {0} !" + }, + "こんにちは": "こんにちは!", + "single-quote": "I don't know!", + "emoji": "😺", + "unicode": "\u0041", + "unicode-escape": "\\u0041", + "backslash-single-quote": "\\'", + "backslash-backslash": "\\\\", + "errors": ["ERROR1001", "ERROR1002"], + "complex": { + "warnings": [ + "NOTE: This is warning", + { + "named-waring": "this is {type} warining" + } + ] + } +}