From 4cd5a62895ce599de2b3961877336ae943c41a87 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Mon, 22 Nov 2021 01:23:09 +0900 Subject: [PATCH] feat: support sourcemap generation related #1 --- .../examples/legacy/main.ts | 8 ++- packages/vite-plugin-vue-i18n/package.json | 1 + packages/vite-plugin-vue-i18n/src/index.ts | 63 +++++++++++++------ .../test/__snapshots__/sourcemap.test.ts.snap | 15 +++++ .../test/fixtures/yml.vue | 3 + .../test/sourcemap.test.ts | 47 ++++++++++++++ packages/vite-plugin-vue-i18n/test/utils.ts | 14 ++++- 7 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 packages/vite-plugin-vue-i18n/test/__snapshots__/sourcemap.test.ts.snap create mode 100644 packages/vite-plugin-vue-i18n/test/fixtures/yml.vue create mode 100644 packages/vite-plugin-vue-i18n/test/sourcemap.test.ts diff --git a/packages/vite-plugin-vue-i18n/examples/legacy/main.ts b/packages/vite-plugin-vue-i18n/examples/legacy/main.ts index ad91211..0f96f59 100644 --- a/packages/vite-plugin-vue-i18n/examples/legacy/main.ts +++ b/packages/vite-plugin-vue-i18n/examples/legacy/main.ts @@ -1,12 +1,16 @@ import { createApp } from 'vue' import { createI18n } from 'vue-i18n' import App from './App.vue' -import messages from '@intlify/vite-plugin-vue-i18n/messages' +import en from './locales/en.yaml' +import ja from './locales/ja.json' const i18n = createI18n({ legacy: true, locale: 'ja', - messages + messages: { + en, + ja + } }) const app = createApp(App) diff --git a/packages/vite-plugin-vue-i18n/package.json b/packages/vite-plugin-vue-i18n/package.json index e311a37..a4f96c6 100644 --- a/packages/vite-plugin-vue-i18n/package.json +++ b/packages/vite-plugin-vue-i18n/package.json @@ -27,6 +27,7 @@ "@intlify/shared": "beta", "@rollup/pluginutils": "^4.1.0", "debug": "^4.3.1", + "source-map": "0.6.1", "fast-glob": "^3.2.5" }, "devDependencies": {}, diff --git a/packages/vite-plugin-vue-i18n/src/index.ts b/packages/vite-plugin-vue-i18n/src/index.ts index 9ed4341..1ea2041 100644 --- a/packages/vite-plugin-vue-i18n/src/index.ts +++ b/packages/vite-plugin-vue-i18n/src/index.ts @@ -10,6 +10,7 @@ import { import fg from 'fast-glob' import createDebug from 'debug' import { normalizePath } from 'vite' +import { RawSourceMap } from 'source-map' import { parseVueRequest } from './query' import type { Plugin, ResolvedConfig, UserConfig } from 'vite' @@ -70,7 +71,9 @@ function pluginI18n( ? 'vue-i18n' : `${installedPkg}` const forceStringify = !!options.forceStringify + let isProduction = false + let sourceMap = false return { name: 'vite-plugin-vue-i18n', @@ -129,6 +132,7 @@ function pluginI18n( configResolved(config: ResolvedConfig) { isProduction = config.isProduction + sourceMap = config.command === 'build' ? !!config.build.sourcemap : false // json transform handling const jsonPlugin = config.plugins.find(p => p.name === 'vite:json') @@ -167,13 +171,15 @@ function pluginI18n( for (const inc of includePaths) { resourcePaths = [...(await fg(inc))] } - // TODO: source-map const code = await generateBundleResources( resourcePaths, isProduction, forceStringify ) - return Promise.resolve(code) + return Promise.resolve({ + code, + map: { mappings: '' } + }) } }, @@ -194,17 +200,12 @@ function pluginI18n( debug('transform', id, JSON.stringify(query)) let langInfo = 'json' + let inSourceMap: RawSourceMap | undefined + if (!query.vue) { if (/\.(json5?|ya?ml)$/.test(id) && filter(id)) { langInfo = path.parse(filename).ext - // NOTE: - // `.json` is handled default in vite, and it's transformed to JS object. - let _source = code - if (langInfo === '.json') { - _source = await getRaw(id) - } - const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML @@ -213,17 +214,26 @@ function pluginI18n( filename, isProduction, query as Record, + sourceMap, + inSourceMap, globalSFCScope, forceStringify ) as CodeGenOptions debug('parseOptions', parseOptions) - const { code: generatedCode } = generate(_source, parseOptions) - debug('generated code', generatedCode) - // TODO: error handling & sourcempa - return Promise.resolve(generatedCode) + const { code: generatedCode, map } = generate(code, parseOptions) + debug('generated code', generatedCode, id) + debug('sourcemap', map, id) + + return Promise.resolve({ + code: generatedCode, + map: (sourceMap ? map : { mappings: '' }) as any // eslint-disable-line @typescript-eslint/no-explicit-any + }) } else { - return Promise.resolve(code) + return Promise.resolve({ + code, + map: sourceMap ? this.getCombinedSourcemap() : { mappings: '' } + }) } } else { // for Vue SFC @@ -246,17 +256,26 @@ function pluginI18n( filename, isProduction, query as Record, + sourceMap, + inSourceMap, globalSFCScope, forceStringify ) as CodeGenOptions debug('parseOptions', parseOptions) - const { code: generatedCode } = generate(code, parseOptions) - debug('generated code', generatedCode) - // TODO: error handling & sourcempa - return Promise.resolve(generatedCode) + const { code: generatedCode, map } = generate(code, parseOptions) + debug('generated code', generatedCode, id) + debug('sourcemap', map, id) + + return Promise.resolve({ + code: generatedCode, + map: (sourceMap ? map : { mappings: '' }) as any // eslint-disable-line @typescript-eslint/no-explicit-any + }) } else { - return Promise.resolve(code) + return Promise.resolve({ + code, + map: sourceMap ? this.getCombinedSourcemap() : { mappings: '' } + }) } } } @@ -295,6 +314,8 @@ function getOptions( filename: string, isProduction: boolean, query: Record, + sourceMap: boolean, + inSourceMap: RawSourceMap | undefined, isGlobal = false, forceStringify = false ): Record { @@ -302,6 +323,8 @@ function getOptions( const baseOptions = { filename, + sourceMap, + inSourceMap, forceStringify, env: mode, onWarn: (msg: string): void => { @@ -344,6 +367,8 @@ async function generateBundleResources( res, isProduction, {}, + false, + undefined, isGlobal, forceStringify ) as CodeGenOptions diff --git a/packages/vite-plugin-vue-i18n/test/__snapshots__/sourcemap.test.ts.snap b/packages/vite-plugin-vue-i18n/test/__snapshots__/sourcemap.test.ts.snap new file mode 100644 index 0000000..f7da430 --- /dev/null +++ b/packages/vite-plugin-vue-i18n/test/__snapshots__/sourcemap.test.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`custom blocks json 1`] = `";;;;;;;;;;;;;;;;;;;;;;AAIE;SACO;;;"`; + +exports[`custom blocks json5 1`] = `";;;;;;;;;;;;;;;;;;;;;;AAIE;SACO;;;"`; + +exports[`custom blocks yaml 1`] = `";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIE;SACO;;;"`; + +exports[`custom blocks yml 1`] = `";;;;;;;;;;;;;;;;;;;;AAIE;SACO;;;"`; + +exports[`resource files json 1`] = `";;;2EACYA,gDAAAC;;;;;wBAEAC;;;;;;;;;;;;;;;;;;;;;;ACCV;SACO;;;"`; + +exports[`resource files json5 1`] = `";;;;;;;;;;;AAIE;SACO;;;"`; + +exports[`resource files yaml 1`] = `";;;;;;;;;;;AAIE;SACO;;;"`; diff --git a/packages/vite-plugin-vue-i18n/test/fixtures/yml.vue b/packages/vite-plugin-vue-i18n/test/fixtures/yml.vue new file mode 100644 index 0000000..7c2291c --- /dev/null +++ b/packages/vite-plugin-vue-i18n/test/fixtures/yml.vue @@ -0,0 +1,3 @@ + + message: "@.caml:{'no apples'} | {0} apple | {n} apples" + diff --git a/packages/vite-plugin-vue-i18n/test/sourcemap.test.ts b/packages/vite-plugin-vue-i18n/test/sourcemap.test.ts new file mode 100644 index 0000000..299fecf --- /dev/null +++ b/packages/vite-plugin-vue-i18n/test/sourcemap.test.ts @@ -0,0 +1,47 @@ +import path from 'path' +import { bundleAndRun } from './utils' + +describe('resource files', () => { + const options = { + sourcemap: true, + target: './fixtures/locales/', + include: [path.resolve(__dirname, './fixtures/locales/**')] + } + + test('json', async () => { + const { map } = await bundleAndRun('ja.json', options) + expect(map.mappings).toMatchSnapshot() + }) + + test('json5', async () => { + const { map } = await bundleAndRun('en.json5', options) + expect(map.mappings).toMatchSnapshot() + }) + + test('yaml', async () => { + const { map } = await bundleAndRun('ko.yaml', options) + expect(map.mappings).toMatchSnapshot() + }) +}) + +describe('custom blocks', () => { + test('json', async () => { + const { map } = await bundleAndRun('basic.vue', { sourcemap: true }) + expect(map.mappings).toMatchSnapshot() + }) + + test('yaml', async () => { + const { map } = await bundleAndRun('yaml.vue', { sourcemap: true }) + expect(map.mappings).toMatchSnapshot() + }) + + test('yml', async () => { + const { map } = await bundleAndRun('yml.vue', { sourcemap: true }) + expect(map.mappings).toMatchSnapshot() + }) + + test('json5', async () => { + const { map } = await bundleAndRun('json5.vue', { sourcemap: true }) + expect(map.mappings).toMatchSnapshot() + }) +}) diff --git a/packages/vite-plugin-vue-i18n/test/utils.ts b/packages/vite-plugin-vue-i18n/test/utils.ts index b69379a..4ec60ea 100644 --- a/packages/vite-plugin-vue-i18n/test/utils.ts +++ b/packages/vite-plugin-vue-i18n/test/utils.ts @@ -13,6 +13,7 @@ async function bundle(fixture: string, options: Record = {}) { const include = (options.include as string[]) || [ path.resolve(__dirname, './fixtures/**') ] + const sourcemap = (options.sourcemap as boolean) || false const silent = isBoolean(options.silent) ? options.silent === false ? 'info' @@ -46,6 +47,7 @@ async function bundle(fixture: string, options: Record = {}) { }, plugins, build: { + sourcemap, write: false, minify: false, rollupOptions: { @@ -53,15 +55,19 @@ async function bundle(fixture: string, options: Record = {}) { } } }) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { code: (result as any).output[0].code } + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + code: (result as any).output[0].code, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + map: (result as any).output[0].map + } } export async function bundleAndRun( fixture: string, options: Record = {} ) { - const { code } = await bundle(fixture, options) + const { code, map } = await bundle(fixture, options) let dom: JSDOM | null = null let jsdomError @@ -87,6 +93,8 @@ export async function bundleAndRun( window, module, exports, + code, + map, jsdomError }) }