@intlify/vue-i18n-extensions 6.0.2 → 6.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/builder.js +60 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/report.js +41 -0
- package/dist/cjs/transform.js +363 -0
- package/dist/cjs/transpiler.js +134 -0
- package/dist/esm/builder.js +56 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/report.js +36 -0
- package/dist/esm/transform.js +359 -0
- package/dist/esm/transpiler.js +129 -0
- package/dist/vue-i18n-extensions.d.ts +97 -0
- package/package.json +34 -23
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContentBuilder = void 0;
|
|
4
|
+
const shared_1 = require("@intlify/shared");
|
|
5
|
+
/**
|
|
6
|
+
* Create a Content Builder
|
|
7
|
+
*
|
|
8
|
+
* @param options - Content Builder options
|
|
9
|
+
*
|
|
10
|
+
* @returns A {@link ContentBuilder} instance
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
function createContentBuilder(options = {}) {
|
|
15
|
+
let _indentLevel = options.indentLevel != null && (0, shared_1.isNumber)(options.indentLevel) ? options.indentLevel : 0;
|
|
16
|
+
let _content = '';
|
|
17
|
+
function push(content) {
|
|
18
|
+
_content += content;
|
|
19
|
+
}
|
|
20
|
+
function _newline(n) {
|
|
21
|
+
push('\n' + ` `.repeat(n));
|
|
22
|
+
}
|
|
23
|
+
function newline() {
|
|
24
|
+
_newline(_indentLevel);
|
|
25
|
+
}
|
|
26
|
+
function pushline(content) {
|
|
27
|
+
push(content);
|
|
28
|
+
newline();
|
|
29
|
+
}
|
|
30
|
+
function indent(withoutNewLine) {
|
|
31
|
+
if (withoutNewLine) {
|
|
32
|
+
++_indentLevel;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
_newline(++_indentLevel);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function deindent(withoutNewLine) {
|
|
39
|
+
if (withoutNewLine) {
|
|
40
|
+
--_indentLevel;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
_newline(--_indentLevel);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
get indentLevel() {
|
|
48
|
+
return _indentLevel;
|
|
49
|
+
},
|
|
50
|
+
get content() {
|
|
51
|
+
return String(_content);
|
|
52
|
+
},
|
|
53
|
+
push,
|
|
54
|
+
newline,
|
|
55
|
+
pushline,
|
|
56
|
+
indent,
|
|
57
|
+
deindent
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
exports.createContentBuilder = createContentBuilder;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformVTDirective = void 0;
|
|
4
|
+
var transform_1 = require("./transform");
|
|
5
|
+
Object.defineProperty(exports, "transformVTDirective", { enumerable: true, get: function () { return transform_1.transformVTDirective; } });
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.report = exports.getReportMessage = void 0;
|
|
4
|
+
const shared_1 = require("@intlify/shared");
|
|
5
|
+
// TODO: should be extracted as i18n resources (intlify project self hosting!)
|
|
6
|
+
const ReportMessages = {
|
|
7
|
+
[1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */]: `Unexpected directive expression: {0}`,
|
|
8
|
+
[2 /* ReportCodes.NOT_SUPPORTED */]: `Not supported transform: {0}`,
|
|
9
|
+
[3 /* ReportCodes.FAILED_VALUE_EVALUATION */]: `Failed value evaluation: {0}`,
|
|
10
|
+
[4 /* ReportCodes.REQUIRED_PARAMETER */]: `Required parameter: {0}`,
|
|
11
|
+
[5 /* ReportCodes.INVALID_PARAMETER_TYPE */]: `Required parameter: {0}`,
|
|
12
|
+
[6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */]: `v-t will override element children: {0}`,
|
|
13
|
+
[7 /* ReportCodes.NOT_RESOLVED_COMPOSER */]: `Not resolved vue-i18n composer: {0}`,
|
|
14
|
+
[8 /* ReportCodes.UNEXPECTED_ERROR */]: `Unexpected error: {0}`
|
|
15
|
+
};
|
|
16
|
+
function getReportMessage(code, ...args) {
|
|
17
|
+
return (0, shared_1.format)(ReportMessages[code], ...args);
|
|
18
|
+
}
|
|
19
|
+
exports.getReportMessage = getReportMessage;
|
|
20
|
+
function createExtensionsError(code, msg, loc) {
|
|
21
|
+
const error = new SyntaxError(msg);
|
|
22
|
+
error.code = code;
|
|
23
|
+
if (loc) {
|
|
24
|
+
error.loc = loc;
|
|
25
|
+
}
|
|
26
|
+
return error;
|
|
27
|
+
}
|
|
28
|
+
function report(code, options = {}) {
|
|
29
|
+
const mode = options.mode && (0, shared_1.isString)(options.mode) && ['warn', 'error'].includes(options.mode)
|
|
30
|
+
? options.mode
|
|
31
|
+
: 'warn';
|
|
32
|
+
const msg = getReportMessage(code, options.args);
|
|
33
|
+
if (mode === 'warn') {
|
|
34
|
+
console.warn('[vue-i18n-extensions] ' + msg);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// error
|
|
38
|
+
throw createExtensionsError(code, msg, options.loc);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.report = report;
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformVTDirective = void 0;
|
|
4
|
+
const compiler_dom_1 = require("@vue/compiler-dom");
|
|
5
|
+
const shared_1 = require("@intlify/shared");
|
|
6
|
+
const transpiler_1 = require("./transpiler");
|
|
7
|
+
const report_1 = require("./report");
|
|
8
|
+
const builder_1 = require("./builder");
|
|
9
|
+
/**
|
|
10
|
+
* Transform `v-t` custom directive
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Transform that `v-t` custom directive is optimized vue-i18n code by Vue compiler.
|
|
14
|
+
* This transform can improve the performance by pre-translating, and it does support SSR.
|
|
15
|
+
*
|
|
16
|
+
* @param options - `v-t` custom directive transform options, see {@link TransformVTDirectiveOptions}
|
|
17
|
+
* @returns Directive transform
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```js
|
|
21
|
+
* import { compile } from '@vue/compiler-dom'
|
|
22
|
+
* import { createI18n } from 'vue-i18n'
|
|
23
|
+
* import { transformVTDirective } from '@intlify/vue-i18n-extensions'
|
|
24
|
+
*
|
|
25
|
+
* // create i18n instance
|
|
26
|
+
* const i18n = createI18n({
|
|
27
|
+
* locale: 'ja',
|
|
28
|
+
* messages: {
|
|
29
|
+
* en: {
|
|
30
|
+
* hello: 'hello'
|
|
31
|
+
* },
|
|
32
|
+
* ja: {
|
|
33
|
+
* hello: 'こんにちは'
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* })
|
|
37
|
+
*
|
|
38
|
+
* // get transform from `transformVTDirective` function, with `i18n` option
|
|
39
|
+
* const transformVT = transformVTDirective({ i18n })
|
|
40
|
+
*
|
|
41
|
+
* const { code } = compile(`<p v-t="'hello'"></p>`, {
|
|
42
|
+
* mode: 'function',
|
|
43
|
+
* hoistStatic: true,
|
|
44
|
+
* prefixIdentifiers: true,
|
|
45
|
+
* directiveTransforms: { t: transformVT } // <- you need to specify to `directiveTransforms` option!
|
|
46
|
+
* })
|
|
47
|
+
*
|
|
48
|
+
* console.log(code)
|
|
49
|
+
* // output ->
|
|
50
|
+
* // const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
|
|
51
|
+
* // return function render(_ctx, _cache) {
|
|
52
|
+
* // return (_openBlock(), _createBlock(\\"div\\", null, \\"こんにちは!\\"))
|
|
53
|
+
* // }
|
|
54
|
+
* ```
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
function transformVTDirective(options = {}) {
|
|
58
|
+
const i18nInstance = options.i18n;
|
|
59
|
+
const mode = (0, shared_1.isString)(options.mode) && ['composition', 'legacy'].includes(options.mode)
|
|
60
|
+
? options.mode
|
|
61
|
+
: 'composition';
|
|
62
|
+
// prettier-ignore
|
|
63
|
+
const translationSignatures = (0, shared_1.isString)(options.translationSignatures)
|
|
64
|
+
? [options.translationSignatures]
|
|
65
|
+
: (0, shared_1.isArray)(options.translationSignatures)
|
|
66
|
+
? options.translationSignatures
|
|
67
|
+
: ['t'];
|
|
68
|
+
translationSignatures.push(`$t`); // fallback to global scope
|
|
69
|
+
return (dir, node, context) => {
|
|
70
|
+
const { exp, loc } = dir;
|
|
71
|
+
// console.log('v-t dir', dir)
|
|
72
|
+
// console.log('v-t node', node)
|
|
73
|
+
if (!exp) {
|
|
74
|
+
// TODO: throw error with context.OnError
|
|
75
|
+
// NOTE: We need to support from @vue/compiler-core
|
|
76
|
+
// https://github.com/vuejs/vue-next/issues/1147
|
|
77
|
+
(0, report_1.report)(1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */, {
|
|
78
|
+
mode: 'error',
|
|
79
|
+
args: [node.loc.source || ''],
|
|
80
|
+
loc: node.loc
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (node.children.length > 0) {
|
|
84
|
+
// TODO: throw error with context.OnError
|
|
85
|
+
// NOTE: We need to support from @vue/compiler-core
|
|
86
|
+
// https://github.com/vuejs/vue-next/issues/1147
|
|
87
|
+
(0, report_1.report)(6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */, {
|
|
88
|
+
mode: 'error',
|
|
89
|
+
args: [node.loc.source || ''],
|
|
90
|
+
loc: node.loc
|
|
91
|
+
});
|
|
92
|
+
node.children.length = 0;
|
|
93
|
+
}
|
|
94
|
+
if (isSimpleExpressionNode(exp)) {
|
|
95
|
+
if (isConstant(exp) && i18nInstance) {
|
|
96
|
+
const { status, value } = (0, transpiler_1.evaluateValue)(exp.content);
|
|
97
|
+
if (status === 'ng') {
|
|
98
|
+
(0, report_1.report)(3 /* ReportCodes.FAILED_VALUE_EVALUATION */, {
|
|
99
|
+
args: [node.loc.source || ''],
|
|
100
|
+
loc: node.loc
|
|
101
|
+
});
|
|
102
|
+
return { props: [] };
|
|
103
|
+
}
|
|
104
|
+
const [parsedValue, parseStatus] = parseValue(value);
|
|
105
|
+
if (parseStatus !== 0 /* ReportCodes.SUCCESS */) {
|
|
106
|
+
(0, report_1.report)(parseStatus, { args: [node.loc.source || ''], loc: node.loc });
|
|
107
|
+
return { props: [] };
|
|
108
|
+
}
|
|
109
|
+
if (parsedValue == null) {
|
|
110
|
+
(0, report_1.report)(8 /* ReportCodes.UNEXPECTED_ERROR */, {
|
|
111
|
+
args: [node.loc.source || ''],
|
|
112
|
+
loc: node.loc
|
|
113
|
+
});
|
|
114
|
+
return { props: [] };
|
|
115
|
+
}
|
|
116
|
+
const global = getComposer(i18nInstance);
|
|
117
|
+
if (global == null) {
|
|
118
|
+
(0, report_1.report)(7 /* ReportCodes.NOT_RESOLVED_COMPOSER */, {
|
|
119
|
+
args: [node.loc.source || ''],
|
|
120
|
+
loc: node.loc
|
|
121
|
+
});
|
|
122
|
+
return { props: [] };
|
|
123
|
+
}
|
|
124
|
+
const content = global.t(...makeParams(parsedValue));
|
|
125
|
+
node.children.push({
|
|
126
|
+
type: compiler_dom_1.NodeTypes.TEXT,
|
|
127
|
+
content
|
|
128
|
+
});
|
|
129
|
+
return { props: [] };
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const translationParams = (0, transpiler_1.parseVTExpression)(exp.content);
|
|
133
|
+
const code = generateTranslationCode(context, mode, translationParams, translationSignatures);
|
|
134
|
+
context.helper(compiler_dom_1.TO_DISPLAY_STRING);
|
|
135
|
+
node.children.push({
|
|
136
|
+
type: compiler_dom_1.NodeTypes.INTERPOLATION,
|
|
137
|
+
content: (0, compiler_dom_1.createCompoundExpression)([
|
|
138
|
+
(0, compiler_dom_1.createSimpleExpression)(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
|
|
139
|
+
])
|
|
140
|
+
});
|
|
141
|
+
return { props: [] };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else if (isCompoundExpressionNode(exp)) {
|
|
145
|
+
const content = exp.children.map(mapNodeContentHandler).join('');
|
|
146
|
+
const code = generateTranslationCode(context, mode, (0, transpiler_1.parseVTExpression)(content), translationSignatures);
|
|
147
|
+
context.helper(compiler_dom_1.TO_DISPLAY_STRING);
|
|
148
|
+
node.children.push({
|
|
149
|
+
type: compiler_dom_1.NodeTypes.INTERPOLATION,
|
|
150
|
+
content: (0, compiler_dom_1.createCompoundExpression)([
|
|
151
|
+
(0, compiler_dom_1.createSimpleExpression)(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
|
|
152
|
+
])
|
|
153
|
+
});
|
|
154
|
+
return { props: [] };
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
(0, report_1.report)(2 /* ReportCodes.NOT_SUPPORTED */, {
|
|
158
|
+
args: [node.loc.source || ''],
|
|
159
|
+
loc: node.loc
|
|
160
|
+
});
|
|
161
|
+
return { props: [] };
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
exports.transformVTDirective = transformVTDirective;
|
|
166
|
+
function getComposer(i18n) {
|
|
167
|
+
return isI18nInstance(i18n) ? getComposerInternal(i18n) : null;
|
|
168
|
+
}
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
+
function isI18nInstance(i18n) {
|
|
171
|
+
return i18n != null && 'global' in i18n && 'mode' in i18n;
|
|
172
|
+
}
|
|
173
|
+
function getComposerInternal(i18n) {
|
|
174
|
+
if (i18n.mode === 'composition') {
|
|
175
|
+
return isComposer(i18n.global) ? i18n.global : null;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
179
|
+
return isVueI18n(i18n.global) ? i18n.global.__composer : null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
183
|
+
function isComposer(target) {
|
|
184
|
+
return target != null && !('__composer' in target);
|
|
185
|
+
}
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
187
|
+
function isVueI18n(target) {
|
|
188
|
+
return target != null && '__composer' in target;
|
|
189
|
+
}
|
|
190
|
+
function isSimpleExpressionNode(node) {
|
|
191
|
+
return node != null && node.type === compiler_dom_1.NodeTypes.SIMPLE_EXPRESSION;
|
|
192
|
+
}
|
|
193
|
+
function isCompoundExpressionNode(node) {
|
|
194
|
+
return node != null && node.type === compiler_dom_1.NodeTypes.COMPOUND_EXPRESSION;
|
|
195
|
+
}
|
|
196
|
+
function isConstant(node) {
|
|
197
|
+
if ('isConstant' in node) {
|
|
198
|
+
// for v3.0.3 earlier
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
200
|
+
return node.isConstant;
|
|
201
|
+
}
|
|
202
|
+
else if ('constType' in node) {
|
|
203
|
+
// for v3.0.3 or later
|
|
204
|
+
return node.constType <= 3 /* ConstantTypes.CAN_STRINGIFY */;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
throw Error('unexpected error in Vue SimpleExpressionNode');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function mapNodeContentHandler(value) {
|
|
211
|
+
if ((0, shared_1.isString)(value)) {
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
else if ((0, shared_1.isSymbol)(value)) {
|
|
215
|
+
return value.description || '';
|
|
216
|
+
}
|
|
217
|
+
else if (isSimpleExpressionNode(value)) {
|
|
218
|
+
return value.content;
|
|
219
|
+
}
|
|
220
|
+
else if (isCompoundExpressionNode(value)) {
|
|
221
|
+
return value.children.map(mapNodeContentHandler).join('');
|
|
222
|
+
}
|
|
223
|
+
else if ((0, compiler_dom_1.isText)(value)) {
|
|
224
|
+
if ((0, shared_1.isString)(value.content)) {
|
|
225
|
+
return value.content;
|
|
226
|
+
}
|
|
227
|
+
else if (isSimpleExpressionNode(value.content)) {
|
|
228
|
+
return value.content.content;
|
|
229
|
+
}
|
|
230
|
+
else if (isCompoundExpressionNode(value.content)) {
|
|
231
|
+
return value.content.children.map(mapNodeContentHandler).join('');
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
return '';
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
return '';
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function parseValue(value) {
|
|
242
|
+
if ((0, shared_1.isString)(value)) {
|
|
243
|
+
return [{ path: value }, 0 /* ReportCodes.SUCCESS */];
|
|
244
|
+
}
|
|
245
|
+
else if ((0, shared_1.isObject)(value)) {
|
|
246
|
+
if (!('path' in value)) {
|
|
247
|
+
return [null, 4 /* ReportCodes.REQUIRED_PARAMETER */];
|
|
248
|
+
}
|
|
249
|
+
return [value, 0 /* ReportCodes.SUCCESS */];
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
return [null, 5 /* ReportCodes.INVALID_PARAMETER_TYPE */];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function makeParams(value) {
|
|
256
|
+
const { path, locale, args, choice, plural } = value;
|
|
257
|
+
const options = {};
|
|
258
|
+
const named = args || {};
|
|
259
|
+
if ((0, shared_1.isString)(locale)) {
|
|
260
|
+
options.locale = locale;
|
|
261
|
+
}
|
|
262
|
+
if ((0, shared_1.isNumber)(choice)) {
|
|
263
|
+
options.plural = choice;
|
|
264
|
+
}
|
|
265
|
+
if ((0, shared_1.isNumber)(plural)) {
|
|
266
|
+
options.plural = plural;
|
|
267
|
+
}
|
|
268
|
+
return [path, named, options];
|
|
269
|
+
}
|
|
270
|
+
function generateTranslationCode(context, mode, params, translationSignatures) {
|
|
271
|
+
return mode === 'composition'
|
|
272
|
+
? generateComposableCode(context, params, translationSignatures)
|
|
273
|
+
: generateLegacyCode(context, params);
|
|
274
|
+
}
|
|
275
|
+
function generateTranslationCallableSignatures(context, translationSignatures) {
|
|
276
|
+
const { prefixIdentifiers, bindingMetadata } = context;
|
|
277
|
+
return translationSignatures
|
|
278
|
+
.map(signature => {
|
|
279
|
+
const type = (0, shared_1.hasOwn)(bindingMetadata, signature) && bindingMetadata[signature];
|
|
280
|
+
const bindingContext = prefixIdentifiers
|
|
281
|
+
? (type && type.startsWith('setup')) || type === compiler_dom_1.BindingTypes.LITERAL_CONST
|
|
282
|
+
? '$setup.'
|
|
283
|
+
: '_ctx.'
|
|
284
|
+
: '';
|
|
285
|
+
return `${bindingContext}${signature}`;
|
|
286
|
+
})
|
|
287
|
+
.join(' || ');
|
|
288
|
+
}
|
|
289
|
+
function generateComposableCode(context, params, translationSignatures) {
|
|
290
|
+
const baseCode = `(${generateTranslationCallableSignatures(context, translationSignatures)})`;
|
|
291
|
+
const builder = (0, builder_1.createContentBuilder)();
|
|
292
|
+
builder.push(`${baseCode}(`);
|
|
293
|
+
// generate path
|
|
294
|
+
builder.push(`${(0, shared_1.toDisplayString)(params.path)}`);
|
|
295
|
+
// generate named
|
|
296
|
+
builder.push(`, { `);
|
|
297
|
+
generateNamedCode(builder, params.named);
|
|
298
|
+
builder.push(` }`);
|
|
299
|
+
// generate options
|
|
300
|
+
builder.push(`, { `);
|
|
301
|
+
if (params.options.locale) {
|
|
302
|
+
builder.push(`locale: ${(0, shared_1.toDisplayString)(params.options.locale)}`);
|
|
303
|
+
}
|
|
304
|
+
if (params.options.plural) {
|
|
305
|
+
if (params.options.locale) {
|
|
306
|
+
builder.push(', ');
|
|
307
|
+
}
|
|
308
|
+
builder.push(`plural: ${(0, shared_1.toDisplayString)(params.options.plural)}`);
|
|
309
|
+
}
|
|
310
|
+
builder.push(` }`);
|
|
311
|
+
builder.push(`)`);
|
|
312
|
+
const content = builder.content;
|
|
313
|
+
return content;
|
|
314
|
+
}
|
|
315
|
+
function generateNamedCode(builder, named) {
|
|
316
|
+
const keys = Object.keys(named);
|
|
317
|
+
keys.forEach(k => {
|
|
318
|
+
const v = named[k];
|
|
319
|
+
if ((0, shared_1.isObject)(v)) {
|
|
320
|
+
builder.push(`${k}: { `);
|
|
321
|
+
generateNamedCode(builder, v);
|
|
322
|
+
builder.push(` }`);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
builder.push(`${k}: ${(0, shared_1.toDisplayString)(v)}`);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function generateLegacyCode(context, params) {
|
|
330
|
+
const mode = !params.options.plural ? 'basic' : 'plural';
|
|
331
|
+
const baseCode = `${context.prefixIdentifiers ? '_ctx.' : ''}${mode === 'basic' ? '$t' : '$tc'}`;
|
|
332
|
+
const builder = (0, builder_1.createContentBuilder)();
|
|
333
|
+
builder.push(`${baseCode}(`);
|
|
334
|
+
// generate path
|
|
335
|
+
builder.push(`${(0, shared_1.toDisplayString)(params.path)}`);
|
|
336
|
+
if (mode === 'basic') {
|
|
337
|
+
// generate locale
|
|
338
|
+
if ((0, shared_1.isString)(params.options.locale)) {
|
|
339
|
+
builder.push(`, ${(0, shared_1.toDisplayString)(params.options.locale)}`);
|
|
340
|
+
}
|
|
341
|
+
// generate named
|
|
342
|
+
builder.push(`, { `);
|
|
343
|
+
generateNamedCode(builder, params.named);
|
|
344
|
+
builder.push(` }`);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// generate plural
|
|
348
|
+
builder.push(`, ${(0, shared_1.toDisplayString)(params.options.plural)}`);
|
|
349
|
+
if ((0, shared_1.isString)(params.options.locale)) {
|
|
350
|
+
// generate locale
|
|
351
|
+
builder.push(`, ${(0, shared_1.toDisplayString)(params.options.locale)}`);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
// generate named
|
|
355
|
+
builder.push(`, { `);
|
|
356
|
+
generateNamedCode(builder, params.named);
|
|
357
|
+
builder.push(` }`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
builder.push(`)`);
|
|
361
|
+
const content = builder.content;
|
|
362
|
+
return content;
|
|
363
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseVTExpression = exports.evaluateValue = void 0;
|
|
4
|
+
const parser_1 = require("@babel/parser");
|
|
5
|
+
function evaluateValue(expression) {
|
|
6
|
+
const ret = { status: 'ng', value: undefined };
|
|
7
|
+
try {
|
|
8
|
+
const ast = (0, parser_1.parse)(`const a = ${expression.trim()}`);
|
|
9
|
+
if (ast.program.body.length >= 1 &&
|
|
10
|
+
ast.program.body[0].type === 'VariableDeclaration' &&
|
|
11
|
+
ast.program.body[0].declarations.length >= 1) {
|
|
12
|
+
const node = ast.program.body[0].declarations[0].init;
|
|
13
|
+
if (node != null && (node.type === 'StringLiteral' || node.type === 'ObjectExpression')) {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
15
|
+
const val = new Function(`return ${expression.trim()} `)();
|
|
16
|
+
ret.status = 'ok';
|
|
17
|
+
ret.value = val;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// eslint-disable-next-line no-empty
|
|
21
|
+
}
|
|
22
|
+
catch (_e) { }
|
|
23
|
+
return ret;
|
|
24
|
+
}
|
|
25
|
+
exports.evaluateValue = evaluateValue;
|
|
26
|
+
function parseVTExpression(expression) {
|
|
27
|
+
const ret = {
|
|
28
|
+
path: '',
|
|
29
|
+
named: {},
|
|
30
|
+
options: {}
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
const ast = (0, parser_1.parse)(`const a = ${expression.trim()}`);
|
|
34
|
+
if (ast.program.body.length >= 1 &&
|
|
35
|
+
ast.program.body[0].type === 'VariableDeclaration' &&
|
|
36
|
+
ast.program.body[0].declarations.length >= 1) {
|
|
37
|
+
const node = ast.program.body[0].declarations[0].init;
|
|
38
|
+
if (node != null) {
|
|
39
|
+
if (node.type === 'StringLiteral' && node.extra) {
|
|
40
|
+
ret.path = node.extra.raw;
|
|
41
|
+
}
|
|
42
|
+
else if (node.type === 'Identifier') {
|
|
43
|
+
ret.path = node.name;
|
|
44
|
+
}
|
|
45
|
+
else if (node.type === 'MemberExpression') {
|
|
46
|
+
ret.path = getObjectMemberValue(node);
|
|
47
|
+
}
|
|
48
|
+
else if (node.type === 'ObjectExpression') {
|
|
49
|
+
node.properties.forEach(propNode => {
|
|
50
|
+
if (propNode.type === 'ObjectProperty') {
|
|
51
|
+
const propKeyNode = propNode.key;
|
|
52
|
+
if (propKeyNode.type !== 'Identifier') {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const propValueNode = propNode.value;
|
|
56
|
+
switch (propKeyNode.name) {
|
|
57
|
+
case 'path':
|
|
58
|
+
ret.path = getObjectMemberValue(propValueNode);
|
|
59
|
+
break;
|
|
60
|
+
case 'locale':
|
|
61
|
+
ret.options.locale = getObjectMemberValue(propValueNode);
|
|
62
|
+
break;
|
|
63
|
+
case 'choice':
|
|
64
|
+
case 'plural':
|
|
65
|
+
ret.options.plural = getObjectMemberValue(propValueNode);
|
|
66
|
+
break;
|
|
67
|
+
case 'args':
|
|
68
|
+
// console.log('args', propValueNode)
|
|
69
|
+
if (propValueNode.type === 'ObjectExpression') {
|
|
70
|
+
traverseObjectMember(propValueNode, ret.named);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// eslint-disable-next-line no-empty
|
|
82
|
+
}
|
|
83
|
+
catch (_e) { }
|
|
84
|
+
return ret;
|
|
85
|
+
}
|
|
86
|
+
exports.parseVTExpression = parseVTExpression;
|
|
87
|
+
function getObjectMemberValue(node) {
|
|
88
|
+
if ((node.type === 'StringLiteral' || node.type === 'NumericLiteral') && node.extra) {
|
|
89
|
+
return node.extra.raw;
|
|
90
|
+
}
|
|
91
|
+
else if (node.type === 'Identifier') {
|
|
92
|
+
return node.name;
|
|
93
|
+
}
|
|
94
|
+
else if (node.type === 'MemberExpression') {
|
|
95
|
+
const paths = [];
|
|
96
|
+
collectMemberPath(node, paths);
|
|
97
|
+
paths.reverse();
|
|
98
|
+
return paths.join('.');
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function traverseObjectMember(node, target) {
|
|
105
|
+
node.properties.forEach(propNode => {
|
|
106
|
+
if (propNode.type === 'ObjectProperty') {
|
|
107
|
+
const propKeyNode = propNode.key;
|
|
108
|
+
if (propKeyNode.type !== 'Identifier') {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (!(propKeyNode.name in target)) {
|
|
112
|
+
target[propKeyNode.name] = {};
|
|
113
|
+
}
|
|
114
|
+
// console.log('propNode', propNode)
|
|
115
|
+
const propValueNode = propNode.value;
|
|
116
|
+
if (propValueNode.type === 'ObjectExpression') {
|
|
117
|
+
traverseObjectMember(propValueNode, target[propKeyNode.name]);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
target[propKeyNode.name] = getObjectMemberValue(propValueNode);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function collectMemberPath(node, paths) {
|
|
126
|
+
if (node.type === 'Identifier') {
|
|
127
|
+
paths.push(node.name);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
else if (node.type === 'MemberExpression' && node.property.type === 'Identifier') {
|
|
131
|
+
paths.push(node.property.name);
|
|
132
|
+
return collectMemberPath(node.object, paths);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isNumber } from '@intlify/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Create a Content Builder
|
|
4
|
+
*
|
|
5
|
+
* @param options - Content Builder options
|
|
6
|
+
*
|
|
7
|
+
* @returns A {@link ContentBuilder} instance
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export function createContentBuilder(options = {}) {
|
|
12
|
+
let _indentLevel = options.indentLevel != null && isNumber(options.indentLevel) ? options.indentLevel : 0;
|
|
13
|
+
let _content = '';
|
|
14
|
+
function push(content) {
|
|
15
|
+
_content += content;
|
|
16
|
+
}
|
|
17
|
+
function _newline(n) {
|
|
18
|
+
push('\n' + ` `.repeat(n));
|
|
19
|
+
}
|
|
20
|
+
function newline() {
|
|
21
|
+
_newline(_indentLevel);
|
|
22
|
+
}
|
|
23
|
+
function pushline(content) {
|
|
24
|
+
push(content);
|
|
25
|
+
newline();
|
|
26
|
+
}
|
|
27
|
+
function indent(withoutNewLine) {
|
|
28
|
+
if (withoutNewLine) {
|
|
29
|
+
++_indentLevel;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
_newline(++_indentLevel);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function deindent(withoutNewLine) {
|
|
36
|
+
if (withoutNewLine) {
|
|
37
|
+
--_indentLevel;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
_newline(--_indentLevel);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
get indentLevel() {
|
|
45
|
+
return _indentLevel;
|
|
46
|
+
},
|
|
47
|
+
get content() {
|
|
48
|
+
return String(_content);
|
|
49
|
+
},
|
|
50
|
+
push,
|
|
51
|
+
newline,
|
|
52
|
+
pushline,
|
|
53
|
+
indent,
|
|
54
|
+
deindent
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { transformVTDirective } from './transform';
|