diff --git a/packages/extractor-vue/src/__snapshots__/extractor.test.ts.snap b/packages/extractor-vue/src/__snapshots__/extractor.test.ts.snap index 646453824..ef0980c48 100644 --- a/packages/extractor-vue/src/__snapshots__/extractor.test.ts.snap +++ b/packages/extractor-vue/src/__snapshots__/extractor.test.ts.snap @@ -1,5 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`vue extractor should catch template errors 1`] = `[Error: Vue template compilation failed]`; + +exports[`vue extractor should catch warnings during parsing 1`] = `[Error: Vue parsing failed]`; + exports[`vue extractor should extract message from functional component 1`] = ` [ { diff --git a/packages/extractor-vue/src/extractor.test.ts b/packages/extractor-vue/src/extractor.test.ts index 4a0a37323..d9dc21c16 100644 --- a/packages/extractor-vue/src/extractor.test.ts +++ b/packages/extractor-vue/src/extractor.test.ts @@ -1,8 +1,8 @@ +import type { ExtractedMessage } from "@lingui/babel-plugin-extract-messages" import { makeConfig } from "@lingui/conf" import fs from "fs" import path from "path" import { vueExtractor } from "." -import type { ExtractedMessage } from "@lingui/babel-plugin-extract-messages" function normalizePath(entries: ExtractedMessage[]): ExtractedMessage[] { return entries.map((entry) => { @@ -16,6 +16,11 @@ function normalizePath(entries: ExtractedMessage[]): ExtractedMessage[] { }) } +function getFixtureCode(filename: string) { + const filePath = path.resolve(__dirname, "fixtures", filename) + return fs.readFileSync(filePath, "utf-8") +} + describe("vue extractor", () => { const linguiConfig = makeConfig({ locales: ["en", "nb"], @@ -41,8 +46,7 @@ describe("vue extractor", () => { }) it("should extract message from vue file", async () => { - const filePath = path.resolve(__dirname, "fixtures/test.vue") - const code = fs.readFileSync(filePath, "utf-8") + const code = getFixtureCode("test.vue") let messages: ExtractedMessage[] = [] @@ -63,8 +67,7 @@ describe("vue extractor", () => { }) it("should extract message from functional component", async () => { - const filePath = path.resolve(__dirname, "fixtures/functional.vue") - const code = fs.readFileSync(filePath, "utf-8") + const code = getFixtureCode("functional.vue") let messages: ExtractedMessage[] = [] @@ -83,4 +86,44 @@ describe("vue extractor", () => { expect(messages).toMatchSnapshot() }) + + it("should catch warnings during parsing", async () => { + // ref: https://github.com/vuejs/core/blob/main/packages/compiler-sfc/__tests__/parse.spec.ts + const code = getFixtureCode("test-parse.vue") + + let messages: ExtractedMessage[] = [] + + expect( + vueExtractor.extract( + "test-parse.vue", + code, + (res) => messages.push(res), + { + linguiConfig, + } + ) + ).rejects.toMatchSnapshot() + + expect(messages).toHaveLength(0) + }) + + it("should catch template errors", async () => { + // ref: https://github.com/vuejs/core/blob/main/packages/compiler-sfc/__tests__/compileTemplate.spec.ts + const source = getFixtureCode("test-compile.vue") + + let messages: ExtractedMessage[] = [] + + expect( + vueExtractor.extract( + "test-compile.vue", + source, + (res) => messages.push(res), + { + linguiConfig, + } + ) + ).rejects.toMatchSnapshot() + + expect(messages).toHaveLength(0) + }) }) diff --git a/packages/extractor-vue/src/fixtures/test-compile.vue b/packages/extractor-vue/src/fixtures/test-compile.vue new file mode 100644 index 000000000..d9e1930c2 --- /dev/null +++ b/packages/extractor-vue/src/fixtures/test-compile.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/packages/extractor-vue/src/fixtures/test-parse.vue b/packages/extractor-vue/src/fixtures/test-parse.vue new file mode 100644 index 000000000..b9961efe0 --- /dev/null +++ b/packages/extractor-vue/src/fixtures/test-parse.vue @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/packages/extractor-vue/src/vue-extractor.ts b/packages/extractor-vue/src/vue-extractor.ts index 155ec8d84..c56b1c18a 100644 --- a/packages/extractor-vue/src/vue-extractor.ts +++ b/packages/extractor-vue/src/vue-extractor.ts @@ -1,6 +1,6 @@ -import { parse, compileTemplate, SFCBlock } from "@vue/compiler-sfc" import { extractor } from "@lingui/cli/api" import type { ExtractorCtx, ExtractorType } from "@lingui/conf" +import { SFCBlock, compileTemplate, parse } from "@vue/compiler-sfc" export const vueExtractor: ExtractorType = { match(filename: string) { @@ -12,12 +12,17 @@ export const vueExtractor: ExtractorType = { onMessageExtracted, ctx: ExtractorCtx ) { - const { descriptor } = parse(code, { + const { descriptor, errors: parsedErrors } = parse(code, { sourceMap: true, filename, ignoreEmpty: true, }) + if (parsedErrors.length) { + parsedErrors.forEach(console.log) + throw new Error("Vue parsing failed") + } + const isTsBlock = (block: SFCBlock) => block?.lang === "ts" const compiledTemplate = @@ -33,6 +38,11 @@ export const vueExtractor: ExtractorType = { }, }) + if (compiledTemplate?.errors?.length) { + compiledTemplate.errors.forEach(console.log) + throw new Error("Vue template compilation failed") + } + const targets = [ [ descriptor.script?.content,