Skip to content
This repository was archived by the owner on Jul 4, 2021. It is now read-only.

Commit 5532122

Browse files
authored
experimental: intlify meta info injection plugin (#71)
1 parent 9d64f24 commit 5532122

File tree

4 files changed

+146
-1
lines changed

4 files changed

+146
-1
lines changed

src/injection.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { debug as Debug } from 'debug'
2+
import MagicString from 'magic-string'
3+
import { isObject, isFunction, isRegExp, isString } from '@intlify/shared'
4+
5+
import type { Plugin, ResolvedConfig } from 'vite'
6+
7+
const debug = Debug('vite-plugin-vue-i18n:intlify-vue')
8+
9+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10+
export type InjectionValues = Record<string, any>
11+
12+
console.warn(
13+
`[@intlify/vite-i18n-vue-i18n] IntlifyVue plugin is experimental! This plugin is used for Intlify tools. Don't use this plugin to enhancement Component options of your application.`
14+
)
15+
16+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
17+
function stringifyObj(obj: Record<string, any>): string {
18+
return `Object({${Object.keys(obj)
19+
.map(key => {
20+
const code = obj[key]
21+
return `${JSON.stringify(key)}:${toCode(code)}`
22+
})
23+
.join(',')}})`
24+
}
25+
26+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
27+
function toCode(code: any): string {
28+
if (code === null) {
29+
return 'null'
30+
}
31+
32+
if (code === undefined) {
33+
return 'undefined'
34+
}
35+
36+
if (isString(code)) {
37+
return JSON.stringify(code)
38+
}
39+
40+
if (isRegExp(code) && code.toString) {
41+
return code.toString()
42+
}
43+
44+
if (isFunction(code) && code.toString) {
45+
return '(' + code.toString() + ')'
46+
}
47+
48+
if (isObject(code)) {
49+
return stringifyObj(code)
50+
}
51+
52+
return code + ''
53+
}
54+
55+
function generateCode(
56+
values: InjectionValues,
57+
indentifier: string,
58+
id: string,
59+
config: ResolvedConfig
60+
): string {
61+
const injectionCodes = ['']
62+
Object.keys(values).forEach(key => {
63+
const code = values[key]
64+
if (isFunction(code)) {
65+
injectionCodes.push(
66+
`${indentifier}.${key} = ${JSON.stringify(code(id, config))}`
67+
)
68+
} else {
69+
injectionCodes.push(`${indentifier}.${key} = ${toCode(code)}`)
70+
}
71+
})
72+
73+
const ret = injectionCodes.join('\n')
74+
return ret.length > 0 ? `\n${ret}\n` : ''
75+
}
76+
77+
export default function IntlifyVue(values: InjectionValues = {}): Plugin {
78+
let config: ResolvedConfig | null = null
79+
80+
return {
81+
enforce: 'post',
82+
name: 'vite-plugin-vue-i18n:intlify-vue',
83+
configResolved(_config: ResolvedConfig) {
84+
config = _config
85+
},
86+
transform(code: string, id: string) {
87+
debug('transform', id)
88+
if (id.endsWith('.vue')) {
89+
const magic = new MagicString(code)
90+
const indentifier = '_sfc_main'
91+
const index = code.indexOf(`export default ${indentifier}`)
92+
magic.appendLeft(index, generateCode(values, indentifier, id, config!))
93+
return {
94+
code: magic.toString(),
95+
map: magic.generateMap()
96+
}
97+
}
98+
}
99+
}
100+
}

test/fixtures/injections/basic.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
export default {
3+
name: 'Meta'
4+
}
5+
</script>
6+
7+
<i18n>
8+
{
9+
"ja": "hello"
10+
}
11+
</i18n>

test/injection.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { bundleAndRun } from './utils'
2+
3+
const values = {
4+
a: 1,
5+
b: 'hello',
6+
c: {
7+
a: 1,
8+
nest: {
9+
foo: 'hello'
10+
}
11+
},
12+
d: () => {
13+
return 'hello'
14+
}
15+
}
16+
17+
test('basic', async () => {
18+
const { module } = await bundleAndRun('./injections/basic.vue', {
19+
intlify: values
20+
})
21+
expect(module.a).toEqual(1)
22+
expect(module.b).toEqual('hello')
23+
expect(module.c.a).toEqual(1)
24+
expect(module.c.nest.foo).toEqual('hello')
25+
expect(module.d).toEqual('hello')
26+
})

test/utils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import vue from '@vitejs/plugin-vue'
55
import { JSDOM, VirtualConsole } from 'jsdom'
66
import vueI18n from '../src/index'
77

8+
import type { InjectionValues } from '../src/injection'
9+
810
async function bundle(fixture: string, options: Record<string, unknown> = {}) {
911
const input = (options.input as string) || './fixtures/entry.ts'
1012
const target = (options.target as string) || './fixtures'
@@ -24,12 +26,18 @@ async function bundle(fixture: string, options: Record<string, unknown> = {}) {
2426
alias['~target'] = path.resolve(__dirname, target, fixture)
2527
}
2628

29+
const plugins = [vue(), vueI18n({ include })]
30+
if (options.intlify) {
31+
const intlifyVue = (await import('../src/injection')).default
32+
plugins.push(intlifyVue(options.intlify as InjectionValues))
33+
}
34+
2735
const result = await build({
2836
logLevel: silent,
2937
resolve: {
3038
alias
3139
},
32-
plugins: [vue(), vueI18n({ include })],
40+
plugins,
3341
build: {
3442
write: false,
3543
minify: false,

0 commit comments

Comments
 (0)