Skip to content

Commit 36c62a5

Browse files
committed
⭐ new: support lang attribute
closes #52
1 parent 2505a83 commit 36c62a5

File tree

9 files changed

+187
-66
lines changed

9 files changed

+187
-66
lines changed

lib/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
33
var querystring_1 = require("querystring");
4-
var loader = function (source) {
4+
var loader = function (source, sourceMap) {
55
if (this.version && Number(this.version) >= 2) {
66
try {
77
this.cacheable && this.cacheable();
8-
this.callback(null, "module.exports = " + generateCode(source, querystring_1.parse(this.resourceQuery)));
8+
this.callback(null, "module.exports = " + generateCode(source, querystring_1.parse(this.resourceQuery)), sourceMap);
99
}
1010
catch (err) {
1111
this.emitError(err.message);

package.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@
99
"bugs": {
1010
"url": "https://github.com/kazupon/vue-i18n-loader/issues"
1111
},
12+
"dependencies": {
13+
"js-yaml": "^3.13.1",
14+
"json5": "^2.1.0"
15+
},
1216
"devDependencies": {
1317
"@types/jest": "^24.0.15",
18+
"@types/js-yaml": "^3.12.1",
1419
"@types/jsdom": "^12.2.4",
20+
"@types/json5": "^0.0.30",
1521
"@types/memory-fs": "^0.3.2",
1622
"@types/node": "^12.6.8",
1723
"@types/webpack": "^4.4.35",
24+
"@types/webpack-merge": "^4.1.5",
1825
"@typescript-eslint/eslint-plugin": "^1.12.0",
1926
"@typescript-eslint/parser": "^1.12.0",
2027
"@typescript-eslint/typescript-estree": "^1.12.0",
@@ -31,7 +38,8 @@
3138
"typescript": "^3.5.3",
3239
"vue-loader": "^15.7.0",
3340
"vue-template-compiler": "^2.6.10",
34-
"webpack": "^4.35.3"
41+
"webpack": "^4.35.3",
42+
"webpack-merge": "^4.2.1"
3543
},
3644
"engines": {
3745
"node": ">= 8"

src/index.ts

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import webpack from 'webpack'
22
import { ParsedUrlQuery, parse } from 'querystring'
33
import { RawSourceMap } from 'source-map'
4+
import JSON5 from 'json5'
5+
import yaml from 'js-yaml'
46

57
const loader: webpack.loader.Loader = function (
68
source: string | Buffer, sourceMap: RawSourceMap | undefined): void {
@@ -20,14 +22,8 @@ const loader: webpack.loader.Loader = function (
2022
}
2123

2224
function generateCode (source: string | Buffer, query: ParsedUrlQuery): string {
23-
let code = ''
24-
25-
let value = typeof source === 'string'
26-
? JSON.parse(source)
27-
: Buffer.isBuffer(source)
28-
? JSON.parse(source.toString())
29-
: null
30-
if (value === null) { throw new Error('invalid source!') }
25+
const data = convert(source, query.lang as string)
26+
let value = JSON.parse(data)
3127

3228
if (query.locale && typeof query.locale === 'string') {
3329
value = Object.assign({}, { [query.locale]: value })
@@ -38,6 +34,7 @@ function generateCode (source: string | Buffer, query: ParsedUrlQuery): string {
3834
.replace(/\u2029/g, '\\u2029')
3935
.replace(/\\/g, '\\\\')
4036

37+
let code = ''
4138
code += `function (Component) {
4239
Component.options.__i18n = Component.options.__i18n || []
4340
Component.options.__i18n.push('${value.replace(/\u0027/g, '\\u0027')}')
@@ -46,4 +43,19 @@ function generateCode (source: string | Buffer, query: ParsedUrlQuery): string {
4643
return code
4744
}
4845

46+
function convert (source: string | Buffer, lang: string): string {
47+
const value = Buffer.isBuffer(source) ? source.toString() : source
48+
49+
switch (lang) {
50+
case 'yaml':
51+
case 'yml':
52+
const data = yaml.safeLoad(value)
53+
return JSON.stringify(data, undefined, '\t')
54+
case 'json5':
55+
return JSON.stringify(JSON5.parse(value))
56+
default:
57+
return value
58+
}
59+
}
60+
4961
export default loader

test/__snapshots__/index.test.ts.snap

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ Array [
1212
]
1313
`;
1414

15+
exports[`json5 1`] = `
16+
Array [
17+
"{\\"en\\":{\\"hello\\":\\"hello world!\\"}}",
18+
]
19+
`;
20+
1521
exports[`locale attr 1`] = `
1622
Array [
1723
"{\\"ja\\":{\\"hello\\":\\"こんにちは、世界!\\"}}",
@@ -43,3 +49,10 @@ Array [
4349
"{\\"en\\":{\\"hello\\":\\"hello\\\\ngreat\\\\t\\\\\\"world\\\\\\"\\"}}",
4450
]
4551
`;
52+
53+
exports[`yaml 1`] = `
54+
Array [
55+
"{\\"en\\":{\\"hello\\":\\"hello world!\\"}}",
56+
"{\\"ja\\":{\\"hello\\":\\"こんにちは、世界!\\"}}",
57+
]
58+
`;

test/fixtures/json5.vue

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<i18n lang="json5">
2+
{
3+
"en": {
4+
// comments
5+
"hello": "hello world!"
6+
}
7+
}
8+
</i18n>

test/fixtures/yaml.vue

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<i18n locale="en" lang="yaml">
2+
hello: "hello world!"
3+
</i18n>
4+
5+
<i18n locale="ja" lang="yml">
6+
hello: "こんにちは、世界!"
7+
</i18n>

test/index.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,13 @@ test('locale attr and import', async () => {
3434
const { module } = await bundleAndRun('locale-import.vue')
3535
expect(module.__i18n).toMatchSnapshot()
3636
})
37+
38+
test('yaml', async () => {
39+
const { module } = await bundleAndRun('yaml.vue')
40+
expect(module.__i18n).toMatchSnapshot()
41+
})
42+
43+
test('json5', async () => {
44+
const { module } = await bundleAndRun('json5.vue')
45+
expect(module.__i18n).toMatchSnapshot()
46+
})

test/utils.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from 'path'
22
import webpack from 'webpack'
3+
import merge from 'webpack-merge'
34
import memoryfs from 'memory-fs'
45
import { JSDOM, VirtualConsole, DOMWindow } from 'jsdom'
56
import { VueLoaderPlugin } from 'vue-loader'
@@ -17,8 +18,8 @@ type BundleResolveResolve = BundleResolve & {
1718
exports: any
1819
}
1920

20-
export function bundle (fixture: string): Promise<BundleResolve> {
21-
const compiler = webpack({
21+
export function bundle (fixture: string, options = {}): Promise<BundleResolve> {
22+
const baseConfig: webpack.Configuration = {
2223
mode: 'development',
2324
devtool: false,
2425
entry: path.resolve(__dirname, './fixtures/entry.js'),
@@ -38,13 +39,18 @@ export function bundle (fixture: string): Promise<BundleResolve> {
3839
}, {
3940
resourceQuery: /blockType=i18n/,
4041
type: 'javascript/auto',
41-
loader: path.resolve(__dirname, '../src/index.ts')
42+
use: [
43+
path.resolve(__dirname, '../src/index.ts')
44+
]
4245
}]
4346
},
4447
plugins: [
4548
new VueLoaderPlugin()
4649
]
47-
})
50+
}
51+
52+
const config = merge({}, baseConfig, options)
53+
const compiler = webpack(config)
4854

4955
const mfs = new memoryfs() // eslint-disable-line
5056
compiler.outputFileSystem = mfs
@@ -58,8 +64,8 @@ export function bundle (fixture: string): Promise<BundleResolve> {
5864
})
5965
}
6066

61-
export async function bundleAndRun (fixture: string): Promise<BundleResolveResolve> {
62-
const { code, stats } = await bundle(fixture)
67+
export async function bundleAndRun (fixture: string, config = {}): Promise<BundleResolveResolve> {
68+
const { code, stats } = await bundle(fixture, config)
6369

6470
let dom: JSDOM | null = null
6571
let jsdomError

0 commit comments

Comments
 (0)