@babelize/engine 0.0.0-stage → 0.1.2
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/LICENSE +202 -0
- package/dist/BabelizeEngine.d.ts +12 -0
- package/dist/BabelizeEngine.js +47 -0
- package/dist/analysis/analyze.d.ts +106 -0
- package/dist/analysis/analyze.js +323 -0
- package/dist/config/env.d.ts +9 -0
- package/dist/config/env.js +16 -0
- package/dist/config.d.ts +74 -0
- package/dist/config.js +47 -0
- package/dist/detection/stack.d.ts +42 -0
- package/dist/detection/stack.js +277 -0
- package/dist/django/catalog.d.ts +92 -0
- package/dist/django/catalog.js +677 -0
- package/dist/django/extract.d.ts +20 -0
- package/dist/django/extract.js +79 -0
- package/dist/django/inject-file.d.ts +6 -0
- package/dist/django/inject-file.js +52 -0
- package/dist/django/inject.d.ts +11 -0
- package/dist/django/inject.js +205 -0
- package/dist/django/keys.d.ts +21 -0
- package/dist/django/keys.js +63 -0
- package/dist/django/locale-names.d.ts +13 -0
- package/dist/django/locale-names.js +60 -0
- package/dist/django/mo-file.d.ts +6 -0
- package/dist/django/mo-file.js +60 -0
- package/dist/django/plural-forms.d.ts +34 -0
- package/dist/django/plural-forms.js +216 -0
- package/dist/django/po-file.d.ts +38 -0
- package/dist/django/po-file.js +273 -0
- package/dist/django/python-extract.d.ts +34 -0
- package/dist/django/python-extract.js +619 -0
- package/dist/django/python-lexer.d.ts +65 -0
- package/dist/django/python-lexer.js +398 -0
- package/dist/django/template-extract.d.ts +32 -0
- package/dist/django/template-extract.js +680 -0
- package/dist/django/types.d.ts +49 -0
- package/dist/django/types.js +15 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +140 -0
- package/dist/injection/InjectionStrategy.d.ts +62 -0
- package/dist/injection/InjectionStrategy.js +2 -0
- package/dist/injection/StrategyFactory.d.ts +4 -0
- package/dist/injection/StrategyFactory.js +29 -0
- package/dist/injection/html/html-injector.d.ts +11 -0
- package/dist/injection/html/html-injector.js +173 -0
- package/dist/injection/strategies/NextIntlStrategy.d.ts +25 -0
- package/dist/injection/strategies/NextIntlStrategy.js +141 -0
- package/dist/injection/strategies/ReactI18nextStrategy.d.ts +19 -0
- package/dist/injection/strategies/ReactI18nextStrategy.js +116 -0
- package/dist/injection/strategies/VanillaStrategy.d.ts +11 -0
- package/dist/injection/strategies/VanillaStrategy.js +73 -0
- package/dist/injection/strategies/VueI18nStrategy.d.ts +11 -0
- package/dist/injection/strategies/VueI18nStrategy.js +84 -0
- package/dist/local/formatter.d.ts +26 -0
- package/dist/local/formatter.js +105 -0
- package/dist/local/git.d.ts +23 -0
- package/dist/local/git.js +136 -0
- package/dist/local/hosted-provider.d.ts +68 -0
- package/dist/local/hosted-provider.js +215 -0
- package/dist/local/index.d.ts +23 -0
- package/dist/local/index.js +75 -0
- package/dist/local/provider.d.ts +56 -0
- package/dist/local/provider.js +119 -0
- package/dist/local/pseudo-provider.d.ts +18 -0
- package/dist/local/pseudo-provider.js +208 -0
- package/dist/local/report.d.ts +177 -0
- package/dist/local/report.js +186 -0
- package/dist/local/translate-core.d.ts +218 -0
- package/dist/local/translate-core.js +499 -0
- package/dist/local/translate-messages.d.ts +49 -0
- package/dist/local/translate-messages.js +89 -0
- package/dist/local/workspace-copy.d.ts +91 -0
- package/dist/local/workspace-copy.js +355 -0
- package/dist/modules/extractor/extract.d.ts +20 -0
- package/dist/modules/extractor/extract.js +709 -0
- package/dist/modules/extractor/index.d.ts +2 -0
- package/dist/modules/extractor/index.js +63 -0
- package/dist/modules/finalization/django-finalize.d.ts +28 -0
- package/dist/modules/finalization/django-finalize.js +412 -0
- package/dist/modules/finalization/finalize.d.ts +38 -0
- package/dist/modules/finalization/finalize.js +745 -0
- package/dist/modules/finalization/index.d.ts +1 -0
- package/dist/modules/finalization/index.js +5 -0
- package/dist/modules/finalization/nextjs-finalize.d.ts +40 -0
- package/dist/modules/finalization/nextjs-finalize.js +328 -0
- package/dist/modules/finalization/static-runtime.d.ts +9 -0
- package/dist/modules/finalization/static-runtime.js +261 -0
- package/dist/modules/finalization/writes.d.ts +29 -0
- package/dist/modules/finalization/writes.js +78 -0
- package/dist/modules/format-injection/index.d.ts +19 -0
- package/dist/modules/format-injection/index.js +273 -0
- package/dist/modules/format-injection/inject-formats.d.ts +31 -0
- package/dist/modules/format-injection/inject-formats.js +208 -0
- package/dist/modules/glossary/index.d.ts +2 -0
- package/dist/modules/glossary/index.js +16 -0
- package/dist/modules/glossary/rules.d.ts +81 -0
- package/dist/modules/glossary/rules.js +244 -0
- package/dist/modules/glossary/types.d.ts +22 -0
- package/dist/modules/glossary/types.js +2 -0
- package/dist/modules/injection/index.d.ts +1 -0
- package/dist/modules/injection/index.js +6 -0
- package/dist/modules/injection/inject.d.ts +29 -0
- package/dist/modules/injection/inject.js +1050 -0
- package/dist/modules/keygen/index.d.ts +1 -0
- package/dist/modules/keygen/index.js +11 -0
- package/dist/modules/keygen/keygen.d.ts +4 -0
- package/dist/modules/keygen/keygen.js +123 -0
- package/dist/modules/keygen/locale-data.d.ts +7 -0
- package/dist/modules/keygen/locale-data.js +73 -0
- package/dist/modules/keygen/public.d.ts +2 -0
- package/dist/modules/keygen/public.js +12 -0
- package/dist/modules/locale-builder/index.d.ts +1 -0
- package/dist/modules/locale-builder/index.js +7 -0
- package/dist/modules/locale-builder/locales.d.ts +13 -0
- package/dist/modules/locale-builder/locales.js +130 -0
- package/dist/modules/lockfile/hasher.d.ts +7 -0
- package/dist/modules/lockfile/hasher.js +13 -0
- package/dist/modules/lockfile/index.d.ts +3 -0
- package/dist/modules/lockfile/index.js +22 -0
- package/dist/modules/lockfile/lockfile-manager.d.ts +99 -0
- package/dist/modules/lockfile/lockfile-manager.js +497 -0
- package/dist/modules/lockfile/schema.d.ts +196 -0
- package/dist/modules/lockfile/schema.js +56 -0
- package/dist/modules/parser/index.d.ts +2 -0
- package/dist/modules/parser/index.js +9 -0
- package/dist/modules/summary/index.d.ts +1 -0
- package/dist/modules/summary/index.js +7 -0
- package/dist/modules/summary/summary.d.ts +9 -0
- package/dist/modules/summary/summary.js +195 -0
- package/dist/modules/sync-detector/index.d.ts +2 -0
- package/dist/modules/sync-detector/index.js +7 -0
- package/dist/modules/sync-detector/reporter.d.ts +3 -0
- package/dist/modules/sync-detector/reporter.js +16 -0
- package/dist/modules/sync-detector/sync-detector.d.ts +39 -0
- package/dist/modules/sync-detector/sync-detector.js +374 -0
- package/dist/modules/translator/batch-optimizer.d.ts +12 -0
- package/dist/modules/translator/batch-optimizer.js +30 -0
- package/dist/modules/translator/client/byok.provider.d.ts +64 -0
- package/dist/modules/translator/client/byok.provider.js +319 -0
- package/dist/modules/translator/client/direct-translator.client.d.ts +12 -0
- package/dist/modules/translator/client/direct-translator.client.js +71 -0
- package/dist/modules/translator/client/gemini.provider.d.ts +1 -0
- package/dist/modules/translator/client/gemini.provider.js +110 -0
- package/dist/modules/translator/client/groq.provider.d.ts +1 -0
- package/dist/modules/translator/client/groq.provider.js +111 -0
- package/dist/modules/translator/client/request.types.d.ts +1 -0
- package/dist/modules/translator/client/request.types.js +2 -0
- package/dist/modules/translator/client/retry.d.ts +29 -0
- package/dist/modules/translator/client/retry.js +94 -0
- package/dist/modules/translator/client/test-utils/mock.client.d.ts +31 -0
- package/dist/modules/translator/client/test-utils/mock.client.js +59 -0
- package/dist/modules/translator/client/translator.interface.d.ts +1 -0
- package/dist/modules/translator/client/translator.interface.js +2 -0
- package/dist/modules/translator/icu-branches.d.ts +138 -0
- package/dist/modules/translator/icu-branches.js +393 -0
- package/dist/modules/translator/language-codes/errors.d.ts +10 -0
- package/dist/modules/translator/language-codes/errors.js +18 -0
- package/dist/modules/translator/language-codes/flores-map.d.ts +1 -0
- package/dist/modules/translator/language-codes/flores-map.js +107 -0
- package/dist/modules/translator/language-codes/index.d.ts +11 -0
- package/dist/modules/translator/language-codes/index.js +24 -0
- package/dist/modules/translator/language-codes/language-mapper.d.ts +25 -0
- package/dist/modules/translator/language-codes/language-mapper.js +132 -0
- package/dist/modules/translator/language-codes/rtl-languages.d.ts +2 -0
- package/dist/modules/translator/language-codes/rtl-languages.js +9 -0
- package/dist/modules/translator/memory/memory-matcher.d.ts +8 -0
- package/dist/modules/translator/memory/memory-matcher.js +218 -0
- package/dist/modules/translator/memory/types.d.ts +22 -0
- package/dist/modules/translator/memory/types.js +2 -0
- package/dist/modules/translator/translate.d.ts +74 -0
- package/dist/modules/translator/translate.js +1047 -0
- package/dist/modules/vue/migrate.d.ts +13 -0
- package/dist/modules/vue/migrate.js +40 -0
- package/dist/modules/vue/script-inject.d.ts +16 -0
- package/dist/modules/vue/script-inject.js +115 -0
- package/dist/modules/vue/sfc.d.ts +11 -0
- package/dist/modules/vue/sfc.js +51 -0
- package/dist/modules/vue/template-rewrite.d.ts +25 -0
- package/dist/modules/vue/template-rewrite.js +76 -0
- package/dist/modules/vue/template-scan.d.ts +29 -0
- package/dist/modules/vue/template-scan.js +264 -0
- package/dist/modules/workspace/index.d.ts +1 -0
- package/dist/modules/workspace/index.js +5 -0
- package/dist/modules/workspace/validate.d.ts +13 -0
- package/dist/modules/workspace/validate.js +333 -0
- package/dist/orchestrator.d.ts +13 -0
- package/dist/orchestrator.js +727 -0
- package/dist/providers/default-translation-provider.d.ts +20 -0
- package/dist/providers/default-translation-provider.js +30 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +21 -0
- package/dist/providers/types.d.ts +153 -0
- package/dist/providers/types.js +2 -0
- package/dist/qa/check-project.d.ts +50 -0
- package/dist/qa/check-project.js +193 -0
- package/dist/qa/gettext-files.d.ts +15 -0
- package/dist/qa/gettext-files.js +115 -0
- package/dist/qa/locale-files.d.ts +44 -0
- package/dist/qa/locale-files.js +159 -0
- package/dist/qa/locale-qa.d.ts +61 -0
- package/dist/qa/locale-qa.js +342 -0
- package/dist/qa/review.d.ts +43 -0
- package/dist/qa/review.js +175 -0
- package/dist/runtime/config.d.ts +8 -0
- package/dist/runtime/config.js +37 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/types.d.ts +427 -0
- package/dist/runtime/types.js +38 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.js +12 -0
- package/dist/utils/ast-helpers.d.ts +57 -0
- package/dist/utils/ast-helpers.js +608 -0
- package/dist/utils/cache-keys.d.ts +8 -0
- package/dist/utils/cache-keys.js +18 -0
- package/dist/utils/circuit-breaker.d.ts +43 -0
- package/dist/utils/circuit-breaker.js +119 -0
- package/dist/utils/concurrent-map.d.ts +4 -0
- package/dist/utils/concurrent-map.js +21 -0
- package/dist/utils/detect-format.d.ts +5 -0
- package/dist/utils/detect-format.js +125 -0
- package/dist/utils/extraction-options.d.ts +29 -0
- package/dist/utils/extraction-options.js +33 -0
- package/dist/utils/file-utils.d.ts +33 -0
- package/dist/utils/file-utils.js +267 -0
- package/dist/utils/glossary-match.d.ts +9 -0
- package/dist/utils/glossary-match.js +25 -0
- package/dist/utils/html-extractor.d.ts +8 -0
- package/dist/utils/html-extractor.js +317 -0
- package/dist/utils/i18next-icu.d.ts +38 -0
- package/dist/utils/i18next-icu.js +159 -0
- package/dist/utils/icu-message.d.ts +65 -0
- package/dist/utils/icu-message.js +346 -0
- package/dist/utils/icu-spans.d.ts +10 -0
- package/dist/utils/icu-spans.js +126 -0
- package/dist/utils/jsx-message.d.ts +93 -0
- package/dist/utils/jsx-message.js +628 -0
- package/dist/utils/key-usage.d.ts +35 -0
- package/dist/utils/key-usage.js +247 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.js +33 -0
- package/dist/utils/metadata.d.ts +82 -0
- package/dist/utils/metadata.js +261 -0
- package/dist/utils/module-constants.d.ts +30 -0
- package/dist/utils/module-constants.js +265 -0
- package/dist/utils/not-injected.d.ts +6 -0
- package/dist/utils/not-injected.js +38 -0
- package/dist/utils/placeholder-protection.d.ts +74 -0
- package/dist/utils/placeholder-protection.js +181 -0
- package/dist/utils/pseudo-markers.d.ts +9 -0
- package/dist/utils/pseudo-markers.js +16 -0
- package/dist/utils/string-utils.d.ts +52 -0
- package/dist/utils/string-utils.js +270 -0
- package/dist/utils/translation-quality.d.ts +34 -0
- package/dist/utils/translation-quality.js +156 -0
- package/dist/utils/translation-sanitizer.d.ts +11 -0
- package/dist/utils/translation-sanitizer.js +71 -0
- package/dist/utils/translator-caller.d.ts +32 -0
- package/dist/utils/translator-caller.js +217 -0
- package/dist/utils/translator-load-balancer.d.ts +73 -0
- package/dist/utils/translator-load-balancer.js +297 -0
- package/dist/utils/ui-copy.d.ts +32 -0
- package/dist/utils/ui-copy.js +126 -0
- package/dist/utils/untranslated.d.ts +15 -0
- package/dist/utils/untranslated.js +34 -0
- package/dist/utils/workspace.d.ts +14 -0
- package/dist/utils/workspace.js +89 -0
- package/package.json +64 -4
- package/schemas/translate-report.schema.json +297 -0
- package/README.md +0 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migrate legacy data-i18n attributes to $t() calls in Vue templates.
|
|
3
|
+
* Runs on raw text before parsing (malformed data-i18n won't parse).
|
|
4
|
+
*
|
|
5
|
+
* Converts:
|
|
6
|
+
* - data-i18n="key" → {{ $t('key') }} (for text content)
|
|
7
|
+
* - data-i18n-alt="key" → :alt="$t('key')" (for attributes)
|
|
8
|
+
* - data-i18n-title="key" → :title="$t('key')"
|
|
9
|
+
* - data-i18n-placeholder="key" → :placeholder="$t('key')"
|
|
10
|
+
*
|
|
11
|
+
* Reuses existing keys so translations survive the migration.
|
|
12
|
+
*/
|
|
13
|
+
export declare function migrateLegacyDataI18n(content: string): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.migrateLegacyDataI18n = migrateLegacyDataI18n;
|
|
4
|
+
/**
|
|
5
|
+
* Migrate legacy data-i18n attributes to $t() calls in Vue templates.
|
|
6
|
+
* Runs on raw text before parsing (malformed data-i18n won't parse).
|
|
7
|
+
*
|
|
8
|
+
* Converts:
|
|
9
|
+
* - data-i18n="key" → {{ $t('key') }} (for text content)
|
|
10
|
+
* - data-i18n-alt="key" → :alt="$t('key')" (for attributes)
|
|
11
|
+
* - data-i18n-title="key" → :title="$t('key')"
|
|
12
|
+
* - data-i18n-placeholder="key" → :placeholder="$t('key')"
|
|
13
|
+
*
|
|
14
|
+
* Reuses existing keys so translations survive the migration.
|
|
15
|
+
*/
|
|
16
|
+
function migrateLegacyDataI18n(content) {
|
|
17
|
+
// Only process if legacy attributes are present
|
|
18
|
+
if (!/data-i18n(?:-\w+)?=/.test(content))
|
|
19
|
+
return content;
|
|
20
|
+
let result = content;
|
|
21
|
+
// Migrate data-i18n="key" on elements with only text content
|
|
22
|
+
// This is a regex-based migration — safe because it only touches
|
|
23
|
+
// attribute patterns that the old engine wrote
|
|
24
|
+
result = result.replace(/<(\w+)([^>]*)\s+data-i18n="([^"]+)"([^>]*)>([^<]*)<\/\1>/g, (match, tag, before, key, after, text) => {
|
|
25
|
+
// If the element has only text content, replace with $t()
|
|
26
|
+
if (text.trim() && !/<\//.test(text)) {
|
|
27
|
+
return `<${tag}${before}${after}>{{ $t('${key}') }}</${tag}>`;
|
|
28
|
+
}
|
|
29
|
+
return match; // Leave complex content alone
|
|
30
|
+
});
|
|
31
|
+
// Migrate data-i18n-attr="key" → :attr="$t('key')"
|
|
32
|
+
const attrs = ['alt', 'title', 'placeholder', 'aria-label', 'aria-description'];
|
|
33
|
+
for (const attr of attrs) {
|
|
34
|
+
const regex = new RegExp(`data-i18n-${attr}="([^"]+)"`, 'g');
|
|
35
|
+
result = result.replace(regex, (match, key) => {
|
|
36
|
+
return `:${attr}="$t('${key}')"`;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InjectionLocation } from '../../runtime/types';
|
|
2
|
+
export interface VueScriptInjectOptions {
|
|
3
|
+
scriptContent: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
templateOffset: number;
|
|
6
|
+
isSetup: boolean;
|
|
7
|
+
hasTs: boolean;
|
|
8
|
+
hasI18nImport: boolean;
|
|
9
|
+
hasUseI18n: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function injectVueScript(options: VueScriptInjectOptions): {
|
|
12
|
+
content: string;
|
|
13
|
+
injections: InjectionLocation[];
|
|
14
|
+
importAdded: boolean;
|
|
15
|
+
hookAdded: boolean;
|
|
16
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.injectVueScript = injectVueScript;
|
|
40
|
+
const parser = __importStar(require("@babel/parser"));
|
|
41
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
42
|
+
const t = __importStar(require("@babel/types"));
|
|
43
|
+
function injectVueScript(options) {
|
|
44
|
+
const { scriptContent, isSetup, hasTs, hasI18nImport, hasUseI18n, } = options;
|
|
45
|
+
if (!isSetup) {
|
|
46
|
+
return {
|
|
47
|
+
content: scriptContent,
|
|
48
|
+
injections: [],
|
|
49
|
+
importAdded: false,
|
|
50
|
+
hookAdded: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const plugins = ['jsx'];
|
|
54
|
+
if (hasTs)
|
|
55
|
+
plugins.push('typescript');
|
|
56
|
+
plugins.push('decorators-legacy', 'classProperties', 'optionalChaining', 'objectRestSpread');
|
|
57
|
+
const ast = parser.parse(scriptContent, {
|
|
58
|
+
sourceType: 'module',
|
|
59
|
+
plugins,
|
|
60
|
+
errorRecovery: true,
|
|
61
|
+
});
|
|
62
|
+
let importAdded = false;
|
|
63
|
+
let hookAdded = false;
|
|
64
|
+
const injections = [];
|
|
65
|
+
let lastImportIndex = -1;
|
|
66
|
+
for (let i = 0; i < ast.program.body.length; i++) {
|
|
67
|
+
if (t.isImportDeclaration(ast.program.body[i])) {
|
|
68
|
+
lastImportIndex = i;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const needsI18nImport = !hasI18nImport && !hasUseI18n;
|
|
72
|
+
const needsHook = !hasUseI18n;
|
|
73
|
+
if (needsI18nImport) {
|
|
74
|
+
const importDecl = t.importDeclaration([t.importSpecifier(t.identifier('useI18n'), t.identifier('useI18n'))], t.stringLiteral('vue-i18n'));
|
|
75
|
+
if (lastImportIndex >= 0) {
|
|
76
|
+
ast.program.body.splice(lastImportIndex + 1, 0, importDecl);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
ast.program.body.unshift(importDecl);
|
|
80
|
+
}
|
|
81
|
+
importAdded = true;
|
|
82
|
+
}
|
|
83
|
+
if (needsHook) {
|
|
84
|
+
const hookDecl = t.variableDeclaration('const', [
|
|
85
|
+
t.variableDeclarator(t.objectPattern([
|
|
86
|
+
t.objectProperty(t.identifier('t'), t.identifier('t'), false, true),
|
|
87
|
+
]), t.callExpression(t.identifier('useI18n'), [])),
|
|
88
|
+
]);
|
|
89
|
+
let insertIndex;
|
|
90
|
+
if (needsI18nImport) {
|
|
91
|
+
insertIndex = lastImportIndex >= 0 ? lastImportIndex + 2 : 1;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
insertIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;
|
|
95
|
+
}
|
|
96
|
+
ast.program.body.splice(insertIndex, 0, hookDecl);
|
|
97
|
+
hookAdded = true;
|
|
98
|
+
}
|
|
99
|
+
const result = (0, generator_1.default)(ast, {
|
|
100
|
+
retainLines: true,
|
|
101
|
+
retainFunctionParens: true,
|
|
102
|
+
comments: true,
|
|
103
|
+
compact: false,
|
|
104
|
+
});
|
|
105
|
+
let code = result.code;
|
|
106
|
+
code = code.replace(/;import /g, ';\nimport ');
|
|
107
|
+
code = code.replace(/(^import .+;\n)([^i\n])/gm, '$1\n$2');
|
|
108
|
+
code = code.replace(/\n{3,}/g, '\n\n');
|
|
109
|
+
return {
|
|
110
|
+
content: code,
|
|
111
|
+
injections,
|
|
112
|
+
importAdded,
|
|
113
|
+
hookAdded,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SFCDescriptor } from '@vue/compiler-sfc';
|
|
2
|
+
export interface ParsedSfc {
|
|
3
|
+
descriptor: SFCDescriptor;
|
|
4
|
+
/** Absolute offset of <template> content start in the file */
|
|
5
|
+
templateOffset: number;
|
|
6
|
+
/** Absolute offset of <script> or <script setup> content start */
|
|
7
|
+
scriptOffset: number;
|
|
8
|
+
/** The script block chosen for injection (setup > regular) */
|
|
9
|
+
scriptBlock: 'setup' | 'regular' | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function parseSfc(content: string): ParsedSfc | null;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSfc = parseSfc;
|
|
4
|
+
const compiler_sfc_1 = require("@vue/compiler-sfc");
|
|
5
|
+
function parseSfc(content) {
|
|
6
|
+
const result = (0, compiler_sfc_1.parse)(content, { pad: 'line' });
|
|
7
|
+
if (result.errors.length > 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const { descriptor } = result;
|
|
11
|
+
let templateOffset = 0;
|
|
12
|
+
if (descriptor.template && typeof descriptor.template.loc?.start?.offset === 'number') {
|
|
13
|
+
const src = descriptor.template.loc.source;
|
|
14
|
+
if (src.startsWith('<template>')) {
|
|
15
|
+
const tagOpenLen = '<template>'.length;
|
|
16
|
+
const spaceAfterOpen = (src.match(/^<template>\s*\n?/) || [''])[0].length - tagOpenLen;
|
|
17
|
+
templateOffset = descriptor.template.loc.start.offset + tagOpenLen + spaceAfterOpen;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
templateOffset = descriptor.template.loc.start.offset;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
let scriptOffset = 0;
|
|
24
|
+
let scriptBlock = null;
|
|
25
|
+
if (descriptor.scriptSetup) {
|
|
26
|
+
scriptBlock = 'setup';
|
|
27
|
+
if (typeof descriptor.scriptSetup.loc?.start?.offset === 'number') {
|
|
28
|
+
const src = descriptor.scriptSetup.loc.source;
|
|
29
|
+
const langMatch = src.match(/<script[^>]*>/);
|
|
30
|
+
if (langMatch) {
|
|
31
|
+
scriptOffset = descriptor.scriptSetup.loc.start.offset + langMatch[0].length;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (descriptor.script) {
|
|
36
|
+
scriptBlock = 'regular';
|
|
37
|
+
if (typeof descriptor.script.loc?.start?.offset === 'number') {
|
|
38
|
+
const src = descriptor.script.loc.source;
|
|
39
|
+
const langMatch = src.match(/<script[^>]*>/);
|
|
40
|
+
if (langMatch) {
|
|
41
|
+
scriptOffset = descriptor.script.loc.start.offset + langMatch[0].length;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
descriptor,
|
|
47
|
+
templateOffset,
|
|
48
|
+
scriptOffset,
|
|
49
|
+
scriptBlock,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TemplateUnit } from './template-scan';
|
|
2
|
+
export interface RewriteInjections {
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
column: number;
|
|
6
|
+
original: string;
|
|
7
|
+
replacement: string;
|
|
8
|
+
key: string;
|
|
9
|
+
confidence: number;
|
|
10
|
+
}
|
|
11
|
+
export interface RewriteResult {
|
|
12
|
+
content: string;
|
|
13
|
+
injections: RewriteInjections[];
|
|
14
|
+
parseFailed: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rewrite Vue template text using MagicString for offset-based edits.
|
|
18
|
+
*
|
|
19
|
+
* Uses one MagicString over the whole file with absolute offsets — no splicing,
|
|
20
|
+
* no drift, no String.replace hazard. The <template> tag is never rebuilt.
|
|
21
|
+
*
|
|
22
|
+
* Post-condition: re-parses the emitted file with @vue/compiler-dom.
|
|
23
|
+
* On any parse error, discards every edit and returns the original content.
|
|
24
|
+
*/
|
|
25
|
+
export declare function rewriteTemplate(fileContent: string, templateContent: string, templateOffset: number, units: TemplateUnit[], keyMapping: Map<string, string>, filePath: string): RewriteResult;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.rewriteTemplate = rewriteTemplate;
|
|
7
|
+
const magic_string_1 = __importDefault(require("magic-string"));
|
|
8
|
+
const compiler_dom_1 = require("@vue/compiler-dom");
|
|
9
|
+
/**
|
|
10
|
+
* Rewrite Vue template text using MagicString for offset-based edits.
|
|
11
|
+
*
|
|
12
|
+
* Uses one MagicString over the whole file with absolute offsets — no splicing,
|
|
13
|
+
* no drift, no String.replace hazard. The <template> tag is never rebuilt.
|
|
14
|
+
*
|
|
15
|
+
* Post-condition: re-parses the emitted file with @vue/compiler-dom.
|
|
16
|
+
* On any parse error, discards every edit and returns the original content.
|
|
17
|
+
*/
|
|
18
|
+
function rewriteTemplate(fileContent, templateContent, templateOffset, units, keyMapping, filePath) {
|
|
19
|
+
if (units.length === 0) {
|
|
20
|
+
return { content: fileContent, injections: [], parseFailed: false };
|
|
21
|
+
}
|
|
22
|
+
const s = new magic_string_1.default(fileContent);
|
|
23
|
+
const injections = [];
|
|
24
|
+
const sorted = [...units].sort((a, b) => b.offset - a.offset);
|
|
25
|
+
for (const unit of sorted) {
|
|
26
|
+
const key = keyMapping.get(unit.id);
|
|
27
|
+
if (!key)
|
|
28
|
+
continue;
|
|
29
|
+
const line = fileContent.substring(0, unit.offset).split('\n').length;
|
|
30
|
+
const lastNewline = fileContent.lastIndexOf('\n', unit.offset);
|
|
31
|
+
const column = unit.offset - (lastNewline === -1 ? 0 : lastNewline + 1);
|
|
32
|
+
if (unit.type === 'text') {
|
|
33
|
+
const replacement = `{{ $t('${key}') }}`;
|
|
34
|
+
s.overwrite(unit.offset, unit.end, replacement);
|
|
35
|
+
injections.push({
|
|
36
|
+
file: filePath,
|
|
37
|
+
line,
|
|
38
|
+
column,
|
|
39
|
+
original: unit.text,
|
|
40
|
+
replacement,
|
|
41
|
+
key,
|
|
42
|
+
confidence: unit.confidence,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else if (unit.type === 'attr') {
|
|
46
|
+
let replacement;
|
|
47
|
+
if (unit.attrBoundLiteral) {
|
|
48
|
+
replacement = `:${unit.attrName}="$t('${key}')"`;
|
|
49
|
+
s.overwrite(unit.offset, unit.end, replacement);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const insertPos = unit.end;
|
|
53
|
+
const dataAttr = ` data-i18n-${unit.attrName}="${key}"`;
|
|
54
|
+
s.appendLeft(insertPos, dataAttr);
|
|
55
|
+
replacement = dataAttr;
|
|
56
|
+
}
|
|
57
|
+
injections.push({
|
|
58
|
+
file: filePath,
|
|
59
|
+
line,
|
|
60
|
+
column,
|
|
61
|
+
original: unit.text,
|
|
62
|
+
replacement,
|
|
63
|
+
key,
|
|
64
|
+
confidence: unit.confidence,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const rewritten = s.toString();
|
|
69
|
+
try {
|
|
70
|
+
(0, compiler_dom_1.parse)(rewritten);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return { content: fileContent, injections: [], parseFailed: true };
|
|
74
|
+
}
|
|
75
|
+
return { content: rewritten, injections, parseFailed: false };
|
|
76
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface TemplateUnit {
|
|
2
|
+
type: 'text' | 'attr' | 'v-text';
|
|
3
|
+
/** Original text content */
|
|
4
|
+
text: string;
|
|
5
|
+
/** File-absolute line number */
|
|
6
|
+
line: number;
|
|
7
|
+
/** Character offset from file start */
|
|
8
|
+
offset: number;
|
|
9
|
+
/** End offset (offset + length) */
|
|
10
|
+
end: number;
|
|
11
|
+
/** Length of the original text in the source */
|
|
12
|
+
length: number;
|
|
13
|
+
/** The extraction ID: ${filePath}:${line}:${hash(text)} */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Confidence score for this extraction */
|
|
16
|
+
confidence: number;
|
|
17
|
+
/** If attr: the attribute name */
|
|
18
|
+
attrName?: string;
|
|
19
|
+
/** If attr: the tag name */
|
|
20
|
+
tagName?: string;
|
|
21
|
+
/** If bound attr (:attr="literal"): whether the value is a bound literal string */
|
|
22
|
+
attrBoundLiteral?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface ScanResult {
|
|
25
|
+
units: TemplateUnit[];
|
|
26
|
+
/** Files that were skipped (v-pre, already translated, etc.) */
|
|
27
|
+
skippedElements: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function scanTemplate(templateContent: string, filePath: string, templateOffset: number, hashFn: (text: string) => string): ScanResult;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanTemplate = scanTemplate;
|
|
4
|
+
const compiler_dom_1 = require("@vue/compiler-dom");
|
|
5
|
+
const TRANSLATABLE_ATTRS = new Set([
|
|
6
|
+
'alt',
|
|
7
|
+
'title',
|
|
8
|
+
'placeholder',
|
|
9
|
+
'aria-label',
|
|
10
|
+
'aria-description',
|
|
11
|
+
'label',
|
|
12
|
+
'text',
|
|
13
|
+
]);
|
|
14
|
+
const ATTR_DENY_LIST = new Set([
|
|
15
|
+
'class',
|
|
16
|
+
'style',
|
|
17
|
+
'id',
|
|
18
|
+
'key',
|
|
19
|
+
'ref',
|
|
20
|
+
'src',
|
|
21
|
+
'href',
|
|
22
|
+
'to',
|
|
23
|
+
'target',
|
|
24
|
+
'rel',
|
|
25
|
+
'type',
|
|
26
|
+
'width',
|
|
27
|
+
'height',
|
|
28
|
+
'rows',
|
|
29
|
+
'cols',
|
|
30
|
+
'data-testid',
|
|
31
|
+
'role',
|
|
32
|
+
'as',
|
|
33
|
+
'name',
|
|
34
|
+
'value',
|
|
35
|
+
'disabled',
|
|
36
|
+
'required',
|
|
37
|
+
'checked',
|
|
38
|
+
'multiple',
|
|
39
|
+
'hidden',
|
|
40
|
+
'tabindex',
|
|
41
|
+
'autofocus',
|
|
42
|
+
'accesskey',
|
|
43
|
+
'contenteditable',
|
|
44
|
+
'draggable',
|
|
45
|
+
'translate',
|
|
46
|
+
'dir',
|
|
47
|
+
'lang',
|
|
48
|
+
'slot',
|
|
49
|
+
'is',
|
|
50
|
+
]);
|
|
51
|
+
function hasVPre(node) {
|
|
52
|
+
return node.props.some((p) => p.type === compiler_dom_1.NodeTypes.ATTRIBUTE && p.name === 'v-pre');
|
|
53
|
+
}
|
|
54
|
+
function hasVHtml(node) {
|
|
55
|
+
return node.props.some((p) => p.type === compiler_dom_1.NodeTypes.DIRECTIVE && p.name === 'html');
|
|
56
|
+
}
|
|
57
|
+
function isInsideI18nT(node, ancestors) {
|
|
58
|
+
return ancestors.some((a) => a.tag === 'i18n-t' && a.tagType === compiler_dom_1.ElementTypes.ELEMENT);
|
|
59
|
+
}
|
|
60
|
+
function hasDollarTBinding(node) {
|
|
61
|
+
return node.props.some((p) => p.type === compiler_dom_1.NodeTypes.ATTRIBUTE &&
|
|
62
|
+
p.value?.content.includes('$t('));
|
|
63
|
+
}
|
|
64
|
+
function locToOffset(loc, templateOffset) {
|
|
65
|
+
return templateOffset + loc.start.offset;
|
|
66
|
+
}
|
|
67
|
+
function locToLine(loc) {
|
|
68
|
+
return loc.start.line;
|
|
69
|
+
}
|
|
70
|
+
function isTranslatableAttr(name) {
|
|
71
|
+
if (ATTR_DENY_LIST.has(name))
|
|
72
|
+
return false;
|
|
73
|
+
if (TRANSLATABLE_ATTRS.has(name))
|
|
74
|
+
return true;
|
|
75
|
+
if (/^(aria-|data-)/.test(name))
|
|
76
|
+
return false;
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
function extractBoundLiteralString(dir) {
|
|
80
|
+
const exp = dir.exp;
|
|
81
|
+
if (!exp)
|
|
82
|
+
return null;
|
|
83
|
+
if (exp.type !== compiler_dom_1.NodeTypes.SIMPLE_EXPRESSION)
|
|
84
|
+
return null;
|
|
85
|
+
const raw = exp.content.trim();
|
|
86
|
+
// Matches: 'string' or "string"
|
|
87
|
+
const match = raw.match(/^['"](.*)['"]$/);
|
|
88
|
+
if (match)
|
|
89
|
+
return match[1];
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
function extractTextContent(node) {
|
|
93
|
+
if (node.type === compiler_dom_1.NodeTypes.TEXT) {
|
|
94
|
+
return node.content;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function isStaticAttribute(prop) {
|
|
99
|
+
return prop.type === compiler_dom_1.NodeTypes.ATTRIBUTE;
|
|
100
|
+
}
|
|
101
|
+
function processElement(node, templateContent, templateOffset, filePath, hashFn, ancestors, skippedElements) {
|
|
102
|
+
const units = [];
|
|
103
|
+
if (hasVPre(node)) {
|
|
104
|
+
skippedElements.push(`${node.tag}:v-pre`);
|
|
105
|
+
return units;
|
|
106
|
+
}
|
|
107
|
+
if (hasVHtml(node)) {
|
|
108
|
+
skippedElements.push(`${node.tag}:v-html`);
|
|
109
|
+
return units;
|
|
110
|
+
}
|
|
111
|
+
if (isInsideI18nT(node, ancestors)) {
|
|
112
|
+
skippedElements.push(`${node.tag}:inside-i18n-t`);
|
|
113
|
+
return units;
|
|
114
|
+
}
|
|
115
|
+
if (hasDollarTBinding(node)) {
|
|
116
|
+
skippedElements.push(`${node.tag}:already-translated`);
|
|
117
|
+
return units;
|
|
118
|
+
}
|
|
119
|
+
// Process text children — merge adjacent text nodes and interpolations
|
|
120
|
+
const textRuns = buildTextRuns(node);
|
|
121
|
+
for (const run of textRuns) {
|
|
122
|
+
const runText = run.map((n) => extractTextContent(n)).join('');
|
|
123
|
+
if (!runText.trim())
|
|
124
|
+
continue;
|
|
125
|
+
const firstNode = run[0];
|
|
126
|
+
const lastNode = run[run.length - 1];
|
|
127
|
+
const offset = locToOffset(firstNode.loc, templateOffset);
|
|
128
|
+
const length = locToOffset(lastNode.loc, templateOffset) +
|
|
129
|
+
lastNode.loc.source.length -
|
|
130
|
+
offset;
|
|
131
|
+
const line = locToLine(firstNode.loc);
|
|
132
|
+
const id = `${filePath}:${line}:${hashFn(runText)}`;
|
|
133
|
+
units.push({
|
|
134
|
+
type: 'text',
|
|
135
|
+
text: runText,
|
|
136
|
+
line,
|
|
137
|
+
offset,
|
|
138
|
+
end: offset + length,
|
|
139
|
+
length,
|
|
140
|
+
id,
|
|
141
|
+
confidence: 1.0,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Process attributes
|
|
145
|
+
for (const prop of node.props) {
|
|
146
|
+
if (isStaticAttribute(prop)) {
|
|
147
|
+
const name = prop.name.toLowerCase();
|
|
148
|
+
if (!isTranslatableAttr(name))
|
|
149
|
+
continue;
|
|
150
|
+
if (!prop.value)
|
|
151
|
+
continue;
|
|
152
|
+
const text = prop.value.content;
|
|
153
|
+
if (!text.trim())
|
|
154
|
+
continue;
|
|
155
|
+
const offset = locToOffset(prop.value.loc, templateOffset);
|
|
156
|
+
const length = prop.value.loc.source.length;
|
|
157
|
+
const line = locToLine(prop.value.loc);
|
|
158
|
+
const id = `${filePath}:${line}:${hashFn(text)}`;
|
|
159
|
+
units.push({
|
|
160
|
+
type: 'attr',
|
|
161
|
+
text,
|
|
162
|
+
line,
|
|
163
|
+
offset,
|
|
164
|
+
end: offset + length,
|
|
165
|
+
length,
|
|
166
|
+
id,
|
|
167
|
+
confidence: 1.0,
|
|
168
|
+
attrName: prop.name,
|
|
169
|
+
tagName: node.tag,
|
|
170
|
+
attrBoundLiteral: false,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else if (prop.type === compiler_dom_1.NodeTypes.DIRECTIVE &&
|
|
174
|
+
prop.name === 'bind' &&
|
|
175
|
+
prop.arg &&
|
|
176
|
+
prop.arg.type === compiler_dom_1.NodeTypes.SIMPLE_EXPRESSION &&
|
|
177
|
+
prop.arg.isStatic &&
|
|
178
|
+
!prop.modifiers.length) {
|
|
179
|
+
const attrName = prop.arg.content;
|
|
180
|
+
if (!isTranslatableAttr(attrName))
|
|
181
|
+
continue;
|
|
182
|
+
const literal = extractBoundLiteralString(prop);
|
|
183
|
+
if (literal === null)
|
|
184
|
+
continue;
|
|
185
|
+
const offset = locToOffset(prop.loc, templateOffset);
|
|
186
|
+
const length = prop.loc.source.length;
|
|
187
|
+
const line = locToLine(prop.loc);
|
|
188
|
+
const id = `${filePath}:${line}:${hashFn(literal)}`;
|
|
189
|
+
units.push({
|
|
190
|
+
type: 'attr',
|
|
191
|
+
text: literal,
|
|
192
|
+
line,
|
|
193
|
+
offset,
|
|
194
|
+
end: offset + length,
|
|
195
|
+
length,
|
|
196
|
+
id,
|
|
197
|
+
confidence: 1.0,
|
|
198
|
+
attrName,
|
|
199
|
+
tagName: node.tag,
|
|
200
|
+
attrBoundLiteral: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
else if (prop.type === compiler_dom_1.NodeTypes.DIRECTIVE &&
|
|
204
|
+
prop.name === 'text') {
|
|
205
|
+
// v-text is dynamic — skip
|
|
206
|
+
skippedElements.push(`${node.tag}:v-text`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return units;
|
|
210
|
+
}
|
|
211
|
+
function buildTextRuns(node) {
|
|
212
|
+
const runs = [];
|
|
213
|
+
let currentRun = [];
|
|
214
|
+
for (const child of node.children) {
|
|
215
|
+
if (child.type === compiler_dom_1.NodeTypes.TEXT ||
|
|
216
|
+
child.type === compiler_dom_1.NodeTypes.INTERPOLATION ||
|
|
217
|
+
child.type === compiler_dom_1.NodeTypes.COMPOUND_EXPRESSION) {
|
|
218
|
+
currentRun.push(child);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (currentRun.length > 0) {
|
|
222
|
+
runs.push(currentRun);
|
|
223
|
+
currentRun = [];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (currentRun.length > 0) {
|
|
228
|
+
runs.push(currentRun);
|
|
229
|
+
}
|
|
230
|
+
return runs;
|
|
231
|
+
}
|
|
232
|
+
function walkNode(node, templateContent, templateOffset, filePath, hashFn, units, skippedElements, ancestors) {
|
|
233
|
+
if (node.type === compiler_dom_1.NodeTypes.ELEMENT) {
|
|
234
|
+
const element = node;
|
|
235
|
+
ancestors.push(element);
|
|
236
|
+
const elementUnits = processElement(element, templateContent, templateOffset, filePath, hashFn, ancestors, skippedElements);
|
|
237
|
+
units.push(...elementUnits);
|
|
238
|
+
for (const child of element.children) {
|
|
239
|
+
walkNode(child, templateContent, templateOffset, filePath, hashFn, units, skippedElements, ancestors);
|
|
240
|
+
}
|
|
241
|
+
ancestors.pop();
|
|
242
|
+
}
|
|
243
|
+
else if (node.type === compiler_dom_1.NodeTypes.IF) {
|
|
244
|
+
for (const branch of node.branches) {
|
|
245
|
+
for (const child of branch.children) {
|
|
246
|
+
walkNode(child, templateContent, templateOffset, filePath, hashFn, units, skippedElements, ancestors);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (node.type === compiler_dom_1.NodeTypes.FOR) {
|
|
251
|
+
for (const child of node.children) {
|
|
252
|
+
walkNode(child, templateContent, templateOffset, filePath, hashFn, units, skippedElements, ancestors);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function scanTemplate(templateContent, filePath, templateOffset, hashFn) {
|
|
257
|
+
const units = [];
|
|
258
|
+
const skippedElements = [];
|
|
259
|
+
const root = (0, compiler_dom_1.parse)(templateContent);
|
|
260
|
+
for (const child of root.children) {
|
|
261
|
+
walkNode(child, templateContent, templateOffset, filePath, hashFn, units, skippedElements, []);
|
|
262
|
+
}
|
|
263
|
+
return { units, skippedElements };
|
|
264
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { validateWorkspace } from './validate';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateWorkspace = void 0;
|
|
4
|
+
var validate_1 = require("./validate");
|
|
5
|
+
Object.defineProperty(exports, "validateWorkspace", { enumerable: true, get: function () { return validate_1.validateWorkspace; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EngineConfigV2, Phase0Result } from '../../runtime/types';
|
|
2
|
+
interface PackageJson {
|
|
3
|
+
dependencies?: Record<string, string>;
|
|
4
|
+
devDependencies?: Record<string, string>;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateWorkspace(config: EngineConfigV2): Promise<Phase0Result>;
|
|
8
|
+
export declare function checkI18nDependencies(packageJson: PackageJson, framework?: string): Promise<{
|
|
9
|
+
hasReactI18next: boolean;
|
|
10
|
+
hasI18next: boolean;
|
|
11
|
+
recommendation: string | null;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|