Skip to content

Commit df999f5

Browse files
committed
Add an option to parse FTL during build
1 parent a39a9e2 commit df999f5

File tree

9 files changed

+173
-54
lines changed

9 files changed

+173
-54
lines changed

__tests__/fixtures/errors.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ shared-photos =
1919
[female] her stream
2020
*[other] their stream
2121
}.
22+
23+
entry-without-error = Hello, World!
2224
</fluent>
4.91 KB
Binary file not shown.

__tests__/frameworks/vite/sfc.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,46 @@ describe('Vite SFC', () => {
2323
expect(code).toMatchSnapshot()
2424
})
2525

26+
describe('parseFtl', () => {
27+
it('parses ftl syntax during compilation', async () => {
28+
// Arrange
29+
// Act
30+
const code = await compile({
31+
plugins: [
32+
vue3({
33+
compiler,
34+
}),
35+
SFCFluentPlugin({
36+
parseFtl: true,
37+
checkSyntax: false,
38+
}),
39+
],
40+
}, '/fixtures/test.vue')
41+
42+
// Assert
43+
expect(code).toMatchSnapshot()
44+
})
45+
46+
it('generates block code even if it has errors', async () => {
47+
// Arrange
48+
// Act
49+
const code = await compile({
50+
plugins: [
51+
vue3({
52+
compiler,
53+
}),
54+
SFCFluentPlugin({
55+
parseFtl: true,
56+
checkSyntax: false,
57+
}),
58+
],
59+
}, '/fixtures/errors.vue')
60+
61+
// Assert
62+
expect(code).toMatchSnapshot()
63+
})
64+
})
65+
2666
it('supports custom blockType', async () => {
2767
// Arrange
2868
// Act

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"release": "dotenv release-it"
9696
},
9797
"peerDependencies": {
98+
"@fluent/bundle": "*",
9899
"@nuxt/kit": "^3"
99100
},
100101
"peerDependenciesMeta": {
@@ -111,6 +112,7 @@
111112
},
112113
"devDependencies": {
113114
"@antfu/eslint-config": "^3.8.0",
115+
"@fluent/bundle": "^0.18.0",
114116
"@nuxt/kit": "^3.14.159",
115117
"@nuxt/schema": "^3.14.159",
116118
"@release-it-plugins/lerna-changelog": "7.0.0",

pnpm-lock.yaml

Lines changed: 45 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/external-plugin.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import MagicString from 'magic-string'
77

88
import { createUnplugin } from 'unplugin'
99
import { isCustomBlock, parseVueRequest } from '../loader-query'
10+
import { getInjectFtl } from './ftl/inject'
1011
import { getSyntaxErrors } from './ftl/parse'
1112

1213
const isVue = createFilter(['**/*.vue'])
@@ -137,20 +138,15 @@ export const unplugin = createUnplugin((options: ExternalPluginOptions) => {
137138
this.error(errorsText)
138139
}
139140

140-
const magic = new MagicString(source, { filename: id })
141+
const injectFtl = getInjectFtl(resolvedOptions)
141142

142-
if (source.length > 0)
143-
magic.update(0, source.length, JSON.stringify(source))
144-
else
145-
magic.append('""')
146-
magic.prepend(`
147-
import { FluentResource } from '@fluent/bundle'
148-
export default /*#__PURE__*/ new FluentResource(`)
149-
magic.append(')\n')
143+
const result = injectFtl`
144+
export default /*#__PURE__*/ new FluentResource(${source})
145+
`
150146

151147
return {
152-
code: magic.toString(),
153-
map: magic.generateMap(),
148+
code: result.toString(),
149+
map: result.generateMap(),
154150
}
155151
}
156152

src/plugins/ftl/inject.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { SFCPluginOptions } from 'src/types'
2+
3+
import { FluentResource } from '@fluent/bundle'
4+
import MagicString from 'magic-string'
5+
6+
type InjectFtlFn = (template: TemplateStringsArray, locale?: string, source?: string) => MagicString
7+
8+
export function getInjectFtl(options: SFCPluginOptions): InjectFtlFn {
9+
return (template, locale, source) => {
10+
if (source == null) {
11+
source = locale
12+
locale = undefined
13+
}
14+
15+
if (source == null)
16+
throw new Error('Missing source')
17+
18+
let magic = new MagicString(source)
19+
const importString = options.parseFtl === true ? '' : '\nimport { FluentResource } from \'@fluent/bundle\'\n'
20+
const localeString = locale == null ? '' : locale
21+
22+
if (options.parseFtl === true) {
23+
const resource = new FluentResource(source)
24+
magic.overwrite(0, source.length, JSON.stringify(resource))
25+
}
26+
else {
27+
// Escape string
28+
magic.replace(/"/g, '\\"')
29+
magic.replace(/\n/g, '\\n')
30+
magic = magic.snip(1, -1)
31+
magic.prepend('new FluentResource("')
32+
magic.append('")')
33+
}
34+
35+
magic.prepend(importString + template[0] + localeString + template[1])
36+
if (template[2] != null)
37+
magic.append(template[2])
38+
39+
return magic
40+
}
41+
}

0 commit comments

Comments
 (0)