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 @@
+
+
+
+
+ {{ message }}
+
\ 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 @@
+
+
+
+ 1st template
+ {{ firstMessage }}
+
+
+ 2nd template
+ {{ secondMessage }}
+
\ 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,