@intlayer/cli 9.0.0-canary.8 → 9.0.0
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/IntlayerEventListener.cjs +1 -1
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
- package/dist/cjs/_virtual/_utils_asset.cjs +4 -3
- package/dist/cjs/auth/login.cjs +2 -2
- package/dist/cjs/auth/login.cjs.map +1 -1
- package/dist/cjs/auth/sessionToken.cjs +0 -1
- package/dist/cjs/auth/sessionToken.cjs.map +1 -1
- package/dist/cjs/build.cjs +6 -7
- package/dist/cjs/build.cjs.map +1 -1
- package/dist/cjs/bundle.cjs +32 -1
- package/dist/cjs/bundle.cjs.map +1 -1
- package/dist/cjs/ci.cjs +96 -29
- package/dist/cjs/ci.cjs.map +1 -1
- package/dist/cjs/cli.cjs +163 -129
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +2 -3
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/editor.cjs +0 -1
- package/dist/cjs/editor.cjs.map +1 -1
- package/dist/cjs/extract.cjs +7 -7
- package/dist/cjs/extract.cjs.map +1 -1
- package/dist/cjs/fill/deepMergeContent.cjs.map +1 -1
- package/dist/cjs/fill/extractTranslatableContent.cjs.map +1 -1
- package/dist/cjs/fill/fill.cjs +11 -11
- package/dist/cjs/fill/fill.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +2 -3
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
- package/dist/cjs/fill/formatFillData.cjs +3 -4
- package/dist/cjs/fill/formatFillData.cjs.map +1 -1
- package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs.map +1 -1
- package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs.map +1 -1
- package/dist/cjs/fill/listTranslationsTasks.cjs +2 -2
- package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
- package/dist/cjs/fill/translateDictionary.cjs +7 -7
- package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
- package/dist/cjs/fill/writeFill.cjs +5 -6
- package/dist/cjs/fill/writeFill.cjs.map +1 -1
- package/dist/cjs/getTargetDictionary.cjs +2 -3
- package/dist/cjs/getTargetDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -3
- package/dist/cjs/init.cjs +171 -6
- package/dist/cjs/init.cjs.map +1 -1
- package/dist/cjs/initBuildOptimization.cjs +6 -6
- package/dist/cjs/initBuildOptimization.cjs.map +1 -1
- package/dist/cjs/initCompiler.cjs +3 -3
- package/dist/cjs/initCompiler.cjs.map +1 -1
- package/dist/cjs/initMCP.cjs +3 -3
- package/dist/cjs/initMCP.cjs.map +1 -1
- package/dist/cjs/initSkills.cjs +11 -11
- package/dist/cjs/initSkills.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +4 -5
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/listProjects.cjs +2 -3
- package/dist/cjs/listProjects.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +4 -4
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +7 -7
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/pullLog.cjs +2 -2
- package/dist/cjs/push/pullLog.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +13 -13
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +2 -3
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDoc.cjs +16 -16
- package/dist/cjs/reviewDoc/reviewDoc.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +11 -11
- package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDocLog.cjs +7 -8
- package/dist/cjs/reviewDoc/reviewDocLog.cjs.map +1 -1
- package/dist/cjs/scan.cjs +5 -5
- package/dist/cjs/scan.cjs.map +1 -1
- package/dist/cjs/searchDoc.cjs +2 -3
- package/dist/cjs/searchDoc.cjs.map +1 -1
- package/dist/cjs/test/listMissingTranslations.cjs +3 -4
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
- package/dist/cjs/test/test.cjs +11 -11
- package/dist/cjs/test/test.cjs.map +1 -1
- package/dist/cjs/translateDoc/translateDoc.cjs +6 -6
- package/dist/cjs/translateDoc/translateDoc.cjs.map +1 -1
- package/dist/cjs/translateDoc/translateFile.cjs +5 -5
- package/dist/cjs/translateDoc/translateFile.cjs.map +1 -1
- package/dist/cjs/translateDoc/validation.cjs.map +1 -1
- package/dist/cjs/utils/calculateChunks.cjs +4 -5
- package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/checkConfigConsistency.cjs.map +1 -1
- package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs +0 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +0 -1
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
- package/dist/cjs/utils/formatLineRanges.cjs.map +1 -1
- package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +1 -2
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
- package/dist/cjs/utils/getOutputFilePath.cjs +2 -3
- package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs +0 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
- package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs +4 -5
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
- package/dist/cjs/utils/openBrowser.cjs +0 -1
- package/dist/cjs/utils/openBrowser.cjs.map +1 -1
- package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
- package/dist/cjs/utils/selectCmsEnvironment.cjs.map +1 -1
- package/dist/cjs/utils/setupAI.cjs.map +1 -1
- package/dist/cjs/watch.cjs +28 -9
- package/dist/cjs/watch.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +1 -0
- package/dist/esm/IntlayerEventListener.mjs.map +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +4 -2
- package/dist/esm/auth/login.mjs +1 -1
- package/dist/esm/auth/login.mjs.map +1 -1
- package/dist/esm/auth/sessionToken.mjs.map +1 -1
- package/dist/esm/build.mjs +3 -3
- package/dist/esm/build.mjs.map +1 -1
- package/dist/esm/bundle.mjs +32 -1
- package/dist/esm/bundle.mjs.map +1 -1
- package/dist/esm/ci.mjs +95 -30
- package/dist/esm/ci.mjs.map +1 -1
- package/dist/esm/cli.mjs +141 -106
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +1 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/editor.mjs.map +1 -1
- package/dist/esm/extract.mjs +3 -3
- package/dist/esm/extract.mjs.map +1 -1
- package/dist/esm/fill/deepMergeContent.mjs.map +1 -1
- package/dist/esm/fill/extractTranslatableContent.mjs.map +1 -1
- package/dist/esm/fill/fill.mjs +3 -3
- package/dist/esm/fill/fill.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
- package/dist/esm/fill/formatFillData.mjs +1 -1
- package/dist/esm/fill/formatFillData.mjs.map +1 -1
- package/dist/esm/fill/getAvailableLocalesInDictionary.mjs.map +1 -1
- package/dist/esm/fill/getFilterMissingContentPerLocale.mjs.map +1 -1
- package/dist/esm/fill/listTranslationsTasks.mjs +1 -1
- package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -1
- package/dist/esm/fill/translateDictionary.mjs +1 -1
- package/dist/esm/fill/translateDictionary.mjs.map +1 -1
- package/dist/esm/fill/writeFill.mjs +2 -2
- package/dist/esm/fill/writeFill.mjs.map +1 -1
- package/dist/esm/getTargetDictionary.mjs +1 -1
- package/dist/esm/getTargetDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +3 -3
- package/dist/esm/init.mjs +167 -2
- package/dist/esm/init.mjs.map +1 -1
- package/dist/esm/initBuildOptimization.mjs +1 -1
- package/dist/esm/initBuildOptimization.mjs.map +1 -1
- package/dist/esm/initCompiler.mjs +1 -1
- package/dist/esm/initCompiler.mjs.map +1 -1
- package/dist/esm/initMCP.mjs +1 -1
- package/dist/esm/initMCP.mjs.map +1 -1
- package/dist/esm/initSkills.mjs +1 -1
- package/dist/esm/initSkills.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +2 -2
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/listProjects.mjs +1 -1
- package/dist/esm/listProjects.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +2 -2
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +4 -4
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/pullLog.mjs +2 -2
- package/dist/esm/push/pullLog.mjs.map +1 -1
- package/dist/esm/push/push.mjs +3 -3
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +1 -1
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDoc.mjs +3 -3
- package/dist/esm/reviewDoc/reviewDoc.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +2 -2
- package/dist/esm/reviewDoc/reviewDocBlockAware.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDocLog.mjs +2 -2
- package/dist/esm/reviewDoc/reviewDocLog.mjs.map +1 -1
- package/dist/esm/scan.mjs +1 -1
- package/dist/esm/scan.mjs.map +1 -1
- package/dist/esm/searchDoc.mjs +1 -1
- package/dist/esm/searchDoc.mjs.map +1 -1
- package/dist/esm/test/listMissingTranslations.mjs +2 -2
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
- package/dist/esm/test/test.mjs +2 -2
- package/dist/esm/test/test.mjs.map +1 -1
- package/dist/esm/translateDoc/translateDoc.mjs +2 -2
- package/dist/esm/translateDoc/translateDoc.mjs.map +1 -1
- package/dist/esm/translateDoc/translateFile.mjs +1 -1
- package/dist/esm/translateDoc/translateFile.mjs.map +1 -1
- package/dist/esm/translateDoc/validation.mjs.map +1 -1
- package/dist/esm/utils/calculateChunks.mjs +1 -1
- package/dist/esm/utils/calculateChunks.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/checkConfigConsistency.mjs.map +1 -1
- package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
- package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
- package/dist/esm/utils/formatLineRanges.mjs.map +1 -1
- package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
- package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
- package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
- package/dist/esm/utils/openBrowser.mjs.map +1 -1
- package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
- package/dist/esm/utils/selectCmsEnvironment.mjs.map +1 -1
- package/dist/esm/utils/setupAI.mjs.map +1 -1
- package/dist/esm/watch.mjs +25 -5
- package/dist/esm/watch.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +0 -1
- package/dist/types/IntlayerEventListener.d.ts.map +1 -1
- package/dist/types/auth/login.d.ts +0 -1
- package/dist/types/auth/login.d.ts.map +1 -1
- package/dist/types/auth/sessionToken.d.ts +0 -1
- package/dist/types/auth/sessionToken.d.ts.map +1 -1
- package/dist/types/build.d.ts +0 -1
- package/dist/types/build.d.ts.map +1 -1
- package/dist/types/bundle.d.ts +0 -1
- package/dist/types/bundle.d.ts.map +1 -1
- package/dist/types/ci.d.ts +40 -1
- package/dist/types/ci.d.ts.map +1 -1
- package/dist/types/cli.d.ts +0 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +0 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/editor.d.ts.map +1 -1
- package/dist/types/extract.d.ts +0 -1
- package/dist/types/extract.d.ts.map +1 -1
- package/dist/types/fill/deepMergeContent.d.ts.map +1 -1
- package/dist/types/fill/extractTranslatableContent.d.ts.map +1 -1
- package/dist/types/fill/fill.d.ts +1 -2
- package/dist/types/fill/fill.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +0 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
- package/dist/types/fill/formatFillData.d.ts +0 -1
- package/dist/types/fill/formatFillData.d.ts.map +1 -1
- package/dist/types/fill/getAvailableLocalesInDictionary.d.ts +0 -1
- package/dist/types/fill/getAvailableLocalesInDictionary.d.ts.map +1 -1
- package/dist/types/fill/getFilterMissingContentPerLocale.d.ts +0 -1
- package/dist/types/fill/getFilterMissingContentPerLocale.d.ts.map +1 -1
- package/dist/types/fill/listTranslationsTasks.d.ts +1 -2
- package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -1
- package/dist/types/fill/translateDictionary.d.ts +1 -3
- package/dist/types/fill/translateDictionary.d.ts.map +1 -1
- package/dist/types/fill/writeFill.d.ts +0 -1
- package/dist/types/fill/writeFill.d.ts.map +1 -1
- package/dist/types/getTargetDictionary.d.ts +1 -2
- package/dist/types/getTargetDictionary.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/init.d.ts +1 -2
- package/dist/types/init.d.ts.map +1 -1
- package/dist/types/initBuildOptimization.d.ts.map +1 -1
- package/dist/types/initCompiler.d.ts.map +1 -1
- package/dist/types/initMCP.d.ts +1 -2
- package/dist/types/initMCP.d.ts.map +1 -1
- package/dist/types/initSkills.d.ts +1 -2
- package/dist/types/initSkills.d.ts.map +1 -1
- package/dist/types/listContentDeclaration.d.ts +0 -1
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/listProjects.d.ts +1 -2
- package/dist/types/listProjects.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +0 -1
- package/dist/types/liveSync.d.ts.map +1 -1
- package/dist/types/pull.d.ts +0 -1
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push/pullLog.d.ts +1 -2
- package/dist/types/push/pullLog.d.ts.map +1 -1
- package/dist/types/push/push.d.ts +1 -2
- package/dist/types/push/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +0 -1
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDoc.d.ts +2 -17
- package/dist/types/reviewDoc/reviewDoc.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDocBlockAware.d.ts +0 -1
- package/dist/types/reviewDoc/reviewDocBlockAware.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDocLog.d.ts +1 -2
- package/dist/types/reviewDoc/reviewDocLog.d.ts.map +1 -1
- package/dist/types/scan.d.ts +3 -2
- package/dist/types/scan.d.ts.map +1 -1
- package/dist/types/searchDoc.d.ts +1 -6
- package/dist/types/searchDoc.d.ts.map +1 -1
- package/dist/types/test/listMissingTranslations.d.ts +0 -1
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
- package/dist/types/test/test.d.ts +0 -1
- package/dist/types/test/test.d.ts.map +1 -1
- package/dist/types/translateDoc/translateDoc.d.ts +1 -16
- package/dist/types/translateDoc/translateDoc.d.ts.map +1 -1
- package/dist/types/translateDoc/translateFile.d.ts +1 -16
- package/dist/types/translateDoc/translateFile.d.ts.map +1 -1
- package/dist/types/translateDoc/types.d.ts +1 -2
- package/dist/types/translateDoc/types.d.ts.map +1 -1
- package/dist/types/translateDoc/validation.d.ts +0 -1
- package/dist/types/translateDoc/validation.d.ts.map +1 -1
- package/dist/types/utils/calculateChunks.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts +0 -1
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/checkConfigConsistency.d.ts.map +1 -1
- package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +0 -1
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
- package/dist/types/utils/formatLineRanges.d.ts.map +1 -1
- package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
- package/dist/types/utils/getOutputFilePath.d.ts +0 -1
- package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
- package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
- package/dist/types/utils/listSpecialChars.d.ts +4 -2
- package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts +0 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
- package/dist/types/utils/openBrowser.d.ts.map +1 -1
- package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
- package/dist/types/utils/selectCmsEnvironment.d.ts +0 -1
- package/dist/types/utils/selectCmsEnvironment.d.ts.map +1 -1
- package/dist/types/utils/setupAI.d.ts +1 -3
- package/dist/types/utils/setupAI.d.ts.map +1 -1
- package/dist/types/watch.d.ts +0 -1
- package/dist/types/watch.d.ts.map +1 -1
- package/package.json +17 -17
|
@@ -8,14 +8,14 @@ const require_reviewDoc_reviewDocBlockAware = require('./reviewDocBlockAware.cjs
|
|
|
8
8
|
const require_reviewDoc_reviewDocLog = require('./reviewDocLog.cjs');
|
|
9
9
|
let node_fs = require("node:fs");
|
|
10
10
|
let node_path = require("node:path");
|
|
11
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
12
|
-
let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
|
|
13
11
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
14
12
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
15
13
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
16
14
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
15
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
16
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
17
17
|
let node_fs_promises = require("node:fs/promises");
|
|
18
|
-
let
|
|
18
|
+
let _intlayer_engine_docReview = require("@intlayer/engine/docReview");
|
|
19
19
|
let fast_glob = require("fast-glob");
|
|
20
20
|
fast_glob = require_runtime.__toESM(fast_glob);
|
|
21
21
|
|
|
@@ -26,7 +26,7 @@ fast_glob = require_runtime.__toESM(fast_glob);
|
|
|
26
26
|
*/
|
|
27
27
|
const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale, aiOptions, nbSimultaneousFileProcessed, configOptions, customInstructions, skipIfModifiedBefore, skipIfModifiedAfter, skipIfExists, gitOptions, log }) => {
|
|
28
28
|
const configuration = (0, _intlayer_config_node.getConfiguration)(configOptions);
|
|
29
|
-
(0,
|
|
29
|
+
(0, _intlayer_engine_cli.logConfigDetails)(configOptions);
|
|
30
30
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)({ log: {
|
|
31
31
|
...configuration.log,
|
|
32
32
|
prefix: ""
|
|
@@ -52,20 +52,20 @@ const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale,
|
|
|
52
52
|
}
|
|
53
53
|
let docList = await (0, fast_glob.default)(docPattern, { ignore: excludedGlobPattern });
|
|
54
54
|
if (gitOptions) {
|
|
55
|
-
const gitChangedFiles = await (0,
|
|
55
|
+
const gitChangedFiles = await (0, _intlayer_engine_cli.listGitFiles)(gitOptions);
|
|
56
56
|
if (gitChangedFiles) docList = docList.filter((path) => gitChangedFiles.some((gitFile) => (0, node_path.join)(process.cwd(), path) === gitFile));
|
|
57
57
|
}
|
|
58
|
-
appLogger(`Base locale is ${(0,
|
|
59
|
-
appLogger(`Reviewing ${(0, _intlayer_config_logger.colorizeNumber)(locales.length)} locales: [ ${(0,
|
|
58
|
+
appLogger(`Base locale is ${(0, _intlayer_engine_utils.formatLocale)(baseLocale)}`);
|
|
59
|
+
appLogger(`Reviewing ${(0, _intlayer_config_logger.colorizeNumber)(locales.length)} locales: [ ${(0, _intlayer_engine_utils.formatLocale)(locales)} ]`);
|
|
60
60
|
appLogger(`Reviewing ${(0, _intlayer_config_logger.colorizeNumber)(docList.length)} files:`);
|
|
61
|
-
appLogger(docList.map((path) => ` - ${(0,
|
|
62
|
-
await (0,
|
|
63
|
-
appLogger(`Reviewing file: ${(0,
|
|
61
|
+
appLogger(docList.map((path) => ` - ${(0, _intlayer_engine_utils.formatPath)(path)}\n`));
|
|
62
|
+
await (0, _intlayer_engine_utils.parallelize)(docList.flatMap((docPath) => locales.map((locale) => async () => {
|
|
63
|
+
appLogger(`Reviewing file: ${(0, _intlayer_engine_utils.formatPath)(docPath)} to ${(0, _intlayer_engine_utils.formatLocale)(locale)}`);
|
|
64
64
|
const absoluteBaseFilePath = (0, node_path.join)(configuration.system.baseDir, docPath);
|
|
65
65
|
const outputFilePath = require_utils_getOutputFilePath.getOutputFilePath(absoluteBaseFilePath, locale, baseLocale);
|
|
66
66
|
if (skipIfExists && (0, node_fs.existsSync)(outputFilePath)) {
|
|
67
67
|
const relativePath = (0, node_path.relative)(configuration.system.baseDir, outputFilePath);
|
|
68
|
-
appLogger(`${(0, _intlayer_config_logger.colorize)("⊘", _intlayer_config_colors.YELLOW)} File ${(0,
|
|
68
|
+
appLogger(`${(0, _intlayer_config_logger.colorize)("⊘", _intlayer_config_colors.YELLOW)} File ${(0, _intlayer_engine_utils.formatPath)(relativePath)} already exists, skipping.`);
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
if ((0, node_fs.existsSync)(outputFilePath)) {
|
|
@@ -77,13 +77,13 @@ const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale,
|
|
|
77
77
|
appLogger(fileModificationData.message);
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
|
-
} else if (skipIfModifiedBefore || skipIfModifiedAfter) appLogger(`${(0, _intlayer_config_logger.colorize)("!", _intlayer_config_colors.YELLOW)} File ${(0,
|
|
80
|
+
} else if (skipIfModifiedBefore || skipIfModifiedAfter) appLogger(`${(0, _intlayer_config_logger.colorize)("!", _intlayer_config_colors.YELLOW)} File ${(0, _intlayer_engine_utils.formatPath)(outputFilePath)} does not exist, skipping modification date check.`);
|
|
81
81
|
let changedLines;
|
|
82
82
|
if (gitOptions) {
|
|
83
|
-
const gitChangedLines = await (0,
|
|
83
|
+
const gitChangedLines = await (0, _intlayer_engine_cli.listGitLines)(absoluteBaseFilePath, gitOptions);
|
|
84
84
|
changedLines = gitChangedLines;
|
|
85
|
-
appLogger(`Changed lines (${(0,
|
|
86
|
-
const { blocks } = (0,
|
|
85
|
+
appLogger(`Changed lines (${(0, _intlayer_engine_utils.formatLocale)(baseLocale)}): ${require_utils_formatLineRanges.formatLineRanges(gitChangedLines)}`);
|
|
86
|
+
const { blocks } = (0, _intlayer_engine_docReview.buildReviewReport)({
|
|
87
87
|
baseText: await (0, node_fs_promises.readFile)(absoluteBaseFilePath, "utf-8").catch(() => ""),
|
|
88
88
|
targetText: (0, node_fs.existsSync)(outputFilePath) ? await (0, node_fs_promises.readFile)(outputFilePath, "utf-8").catch(() => "") : "",
|
|
89
89
|
changedLines: gitChangedLines
|
|
@@ -93,7 +93,7 @@ const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale,
|
|
|
93
93
|
const { start, end } = block.targetLineRange;
|
|
94
94
|
return Array.from({ length: end - start + 1 }, (_unused, offset) => start + offset);
|
|
95
95
|
});
|
|
96
|
-
appLogger(`Corresponding block (${(0,
|
|
96
|
+
appLogger(`Corresponding block (${(0, _intlayer_engine_utils.formatLocale)(locale)}): ${require_utils_formatLineRanges.formatLineRanges(correspondingTargetLines)}`);
|
|
97
97
|
}
|
|
98
98
|
if (log) {
|
|
99
99
|
await require_reviewDoc_reviewDocLog.logReviewFileBlocks(absoluteBaseFilePath, outputFilePath, locale, baseLocale, configOptions, changedLines);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDoc.cjs","names":["setupAI","x","getOutputFilePath","ANSIColors","checkFileModifiedRange","formatLineRanges","logReviewFileBlocks","reviewFileBlockAware"],"sources":["../../../src/reviewDoc/reviewDoc.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n logConfigDetails,\n} from '@intlayer/chokidar/cli';\nimport { buildReviewReport } from '@intlayer/chokidar/docReview';\nimport {\n formatLocale,\n formatPath,\n parallelize,\n} from '@intlayer/chokidar/utils';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colorize,\n colorizeNumber,\n getAppLogger,\n x,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport fg from 'fast-glob';\nimport { checkFileModifiedRange } from '../utils/checkFileModifiedRange';\nimport { formatLineRanges } from '../utils/formatLineRanges';\nimport { getOutputFilePath } from '../utils/getOutputFilePath';\nimport { type AIClient, setupAI } from '../utils/setupAI';\nimport { reviewFileBlockAware } from './reviewDocBlockAware';\nimport { logReviewFileBlocks } from './reviewDocLog';\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locale[];\n excludedGlobPattern: string[];\n baseLocale: Locale;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n skipIfExists?: boolean;\n gitOptions?: ListGitFilesOptions;\n /**\n * Log-only mode. Instead of translating the changed blocks with AI, log the\n * blocks that need attention (with line numbers and content) for the base and\n * target locales, so another agent can generate the translations.\n */\n log?: boolean;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n skipIfExists,\n gitOptions,\n log,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n logConfigDetails(configOptions);\n\n const appLogger = getAppLogger({ log: { ...configuration.log, prefix: '' } });\n\n // Log-only mode does not call any AI, so the AI access checks are skipped.\n let aiClient: AIClient | undefined;\n let aiConfig: AIConfig | undefined;\n\n if (!log) {\n const aiResult = await setupAI(configuration, aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n aiClient = aiResult.aiClient;\n aiConfig = aiResult.aiConfig;\n\n if (aiResult.isCustomAI && aiClient && aiConfig) {\n const { hasAIAccess, error } = await aiClient.checkAISDKAccess(aiConfig);\n if (!hasAIAccess) {\n appLogger(`${x} ${error}`);\n return;\n }\n }\n }\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = await fg(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.system.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // Skip if file exists and skipIfExists option is enabled\n if (skipIfExists && existsSync(outputFilePath)) {\n const relativePath = relative(\n configuration.system.baseDir,\n outputFilePath\n );\n appLogger(\n `${colorize('⊘', ANSIColors.YELLOW)} File ${formatPath(relativePath)} already exists, skipping.`\n );\n return;\n }\n\n // Check modification range only if the file exists\n if (existsSync(outputFilePath)) {\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n } else if (skipIfModifiedBefore || skipIfModifiedAfter) {\n // Log if we intended to check modification time but couldn't because the file doesn't exist\n appLogger(\n `${colorize('!', ANSIColors.YELLOW)} File ${formatPath(outputFilePath)} does not exist, skipping modification date check.`\n );\n }\n\n let changedLines: number[] | undefined;\n // FIXED: Enable git optimization that was previously commented out\n if (gitOptions) {\n const gitChangedLines = await listGitLines(\n absoluteBaseFilePath,\n gitOptions\n );\n changedLines = gitChangedLines;\n\n // Report the base lines that changed, then the corresponding line span\n // in the target document — i.e. the blocks the alignment will actually\n // re-translate. `review` blocks are exactly the aligned base blocks the\n // changed lines touched, so their `targetLineRange` is the matching span\n // in the existing translation.\n appLogger(\n `Changed lines (${formatLocale(baseLocale)}): ${formatLineRanges(gitChangedLines)}`\n );\n\n const baseText = await readFile(absoluteBaseFilePath, 'utf-8').catch(\n () => ''\n );\n const targetText = existsSync(outputFilePath)\n ? await readFile(outputFilePath, 'utf-8').catch(() => '')\n : '';\n\n const { blocks } = buildReviewReport({\n baseText,\n targetText,\n changedLines: gitChangedLines,\n });\n\n const correspondingTargetLines = blocks.flatMap((block) => {\n if (block.action !== 'review' || !block.targetLineRange) return [];\n\n const { start, end } = block.targetLineRange;\n return Array.from(\n { length: end - start + 1 },\n (_unused, offset) => start + offset\n );\n });\n\n appLogger(\n `Corresponding block (${formatLocale(locale)}): ${formatLineRanges(correspondingTargetLines)}`\n );\n }\n\n if (log) {\n await logReviewFileBlocks(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n configOptions,\n changedLines\n );\n return;\n }\n\n await reviewFileBlockAware(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines,\n aiClient,\n aiConfig\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reviewDoc.cjs","names":["setupAI","x","getOutputFilePath","ANSIColors","checkFileModifiedRange","formatLineRanges","logReviewFileBlocks","reviewFileBlockAware"],"sources":["../../../src/reviewDoc/reviewDoc.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colorize,\n colorizeNumber,\n getAppLogger,\n x,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n logConfigDetails,\n} from '@intlayer/engine/cli';\nimport { buildReviewReport } from '@intlayer/engine/docReview';\nimport { formatLocale, formatPath, parallelize } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport fg from 'fast-glob';\nimport { checkFileModifiedRange } from '../utils/checkFileModifiedRange';\nimport { formatLineRanges } from '../utils/formatLineRanges';\nimport { getOutputFilePath } from '../utils/getOutputFilePath';\nimport { type AIClient, setupAI } from '../utils/setupAI';\nimport { reviewFileBlockAware } from './reviewDocBlockAware';\nimport { logReviewFileBlocks } from './reviewDocLog';\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locale[];\n excludedGlobPattern: string[];\n baseLocale: Locale;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n skipIfExists?: boolean;\n gitOptions?: ListGitFilesOptions;\n /**\n * Log-only mode. Instead of translating the changed blocks with AI, log the\n * blocks that need attention (with line numbers and content) for the base and\n * target locales, so another agent can generate the translations.\n */\n log?: boolean;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n skipIfExists,\n gitOptions,\n log,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n logConfigDetails(configOptions);\n\n const appLogger = getAppLogger({ log: { ...configuration.log, prefix: '' } });\n\n // Log-only mode does not call any AI, so the AI access checks are skipped.\n let aiClient: AIClient | undefined;\n let aiConfig: AIConfig | undefined;\n\n if (!log) {\n const aiResult = await setupAI(configuration, aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n aiClient = aiResult.aiClient;\n aiConfig = aiResult.aiConfig;\n\n if (aiResult.isCustomAI && aiClient && aiConfig) {\n const { hasAIAccess, error } = await aiClient.checkAISDKAccess(aiConfig);\n if (!hasAIAccess) {\n appLogger(`${x} ${error}`);\n return;\n }\n }\n }\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = await fg(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.system.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // Skip if file exists and skipIfExists option is enabled\n if (skipIfExists && existsSync(outputFilePath)) {\n const relativePath = relative(\n configuration.system.baseDir,\n outputFilePath\n );\n appLogger(\n `${colorize('⊘', ANSIColors.YELLOW)} File ${formatPath(relativePath)} already exists, skipping.`\n );\n return;\n }\n\n // Check modification range only if the file exists\n if (existsSync(outputFilePath)) {\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n } else if (skipIfModifiedBefore || skipIfModifiedAfter) {\n // Log if we intended to check modification time but couldn't because the file doesn't exist\n appLogger(\n `${colorize('!', ANSIColors.YELLOW)} File ${formatPath(outputFilePath)} does not exist, skipping modification date check.`\n );\n }\n\n let changedLines: number[] | undefined;\n // FIXED: Enable git optimization that was previously commented out\n if (gitOptions) {\n const gitChangedLines = await listGitLines(\n absoluteBaseFilePath,\n gitOptions\n );\n changedLines = gitChangedLines;\n\n // Report the base lines that changed, then the corresponding line span\n // in the target document — i.e. the blocks the alignment will actually\n // re-translate. `review` blocks are exactly the aligned base blocks the\n // changed lines touched, so their `targetLineRange` is the matching span\n // in the existing translation.\n appLogger(\n `Changed lines (${formatLocale(baseLocale)}): ${formatLineRanges(gitChangedLines)}`\n );\n\n const baseText = await readFile(absoluteBaseFilePath, 'utf-8').catch(\n () => ''\n );\n const targetText = existsSync(outputFilePath)\n ? await readFile(outputFilePath, 'utf-8').catch(() => '')\n : '';\n\n const { blocks } = buildReviewReport({\n baseText,\n targetText,\n changedLines: gitChangedLines,\n });\n\n const correspondingTargetLines = blocks.flatMap((block) => {\n if (block.action !== 'review' || !block.targetLineRange) return [];\n\n const { start, end } = block.targetLineRange;\n return Array.from(\n { length: end - start + 1 },\n (_unused, offset) => start + offset\n );\n });\n\n appLogger(\n `Corresponding block (${formatLocale(locale)}): ${formatLineRanges(correspondingTargetLines)}`\n );\n }\n\n if (log) {\n await logReviewFileBlocks(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n configOptions,\n changedLines\n );\n return;\n }\n\n await reviewFileBlockAware(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines,\n aiClient,\n aiConfig\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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"}
|
|
@@ -6,14 +6,14 @@ const require_utils_chunkInference = require('../utils/chunkInference.cjs');
|
|
|
6
6
|
const require_utils_fixChunkStartEndChars = require('../utils/fixChunkStartEndChars.cjs');
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
|
-
let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
|
|
10
9
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
11
10
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
12
11
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
13
12
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
13
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
14
14
|
let node_fs_promises = require("node:fs/promises");
|
|
15
15
|
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
16
|
-
let
|
|
16
|
+
let _intlayer_engine_docReview = require("@intlayer/engine/docReview");
|
|
17
17
|
let _intlayer_core_localization = require("@intlayer/core/localization");
|
|
18
18
|
let _intlayer_types_locales = require("@intlayer/types/locales");
|
|
19
19
|
|
|
@@ -37,10 +37,10 @@ const reviewFileBlockAware = async (baseFilePath, outputFilePath, locale, baseLo
|
|
|
37
37
|
} });
|
|
38
38
|
const baseText = await (0, node_fs_promises.readFile)(baseFilePath, "utf-8");
|
|
39
39
|
const targetText = await (0, node_fs_promises.readFile)(outputFilePath, "utf-8").catch(() => "");
|
|
40
|
-
const basePrompt = require__utils_asset.readAsset("./prompts/REVIEW_PROMPT.md", "utf-8").replaceAll("{{localeName}}", `${(0,
|
|
41
|
-
const filePrefix = [(0, _intlayer_config_logger.colon)(`${_intlayer_config_colors.GREY_DARK}[${(0,
|
|
42
|
-
const prefix = [(0, _intlayer_config_logger.colon)(`${_intlayer_config_colors.GREY_DARK}[${(0,
|
|
43
|
-
const { baseBlocks, targetBlocks, plan, segmentsToReview } = (0,
|
|
40
|
+
const basePrompt = require__utils_asset.readAsset("./prompts/REVIEW_PROMPT.md", "utf-8").replaceAll("{{localeName}}", `${(0, _intlayer_engine_utils.formatLocale)(locale, false)}`).replaceAll("{{baseLocaleName}}", `${(0, _intlayer_engine_utils.formatLocale)(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
41
|
+
const filePrefix = [(0, _intlayer_config_logger.colon)(`${_intlayer_config_colors.GREY_DARK}[${(0, _intlayer_engine_utils.formatPath)(baseFilePath)}${_intlayer_config_colors.GREY_DARK}] `, { colSize: 40 }), `→ ${_intlayer_config_colors.RESET}`].join("");
|
|
42
|
+
const prefix = [(0, _intlayer_config_logger.colon)(`${_intlayer_config_colors.GREY_DARK}[${(0, _intlayer_engine_utils.formatPath)(baseFilePath)}${_intlayer_config_colors.GREY_DARK}][${(0, _intlayer_engine_utils.formatLocale)(locale)}${_intlayer_config_colors.GREY_DARK}] `, { colSize: 40 }), `→ ${_intlayer_config_colors.RESET}`].join("");
|
|
43
|
+
const { baseBlocks, targetBlocks, plan, segmentsToReview } = (0, _intlayer_engine_docReview.buildAlignmentPlan)({
|
|
44
44
|
baseText,
|
|
45
45
|
targetText,
|
|
46
46
|
changedLines
|
|
@@ -51,7 +51,7 @@ const reviewFileBlockAware = async (baseFilePath, outputFilePath, locale, baseLo
|
|
|
51
51
|
const reviewedSegmentsMap = /* @__PURE__ */ new Map();
|
|
52
52
|
for (const [actionIndex, action] of plan.actions.entries()) if (action.kind === "delete") reviewedSegmentsMap.set(actionIndex, "");
|
|
53
53
|
const writeCurrentState = () => {
|
|
54
|
-
const output = (0,
|
|
54
|
+
const output = (0, _intlayer_engine_docReview.mergeReviewedSegments)(plan, targetBlocks, reviewedSegmentsMap);
|
|
55
55
|
(0, node_fs.mkdirSync)((0, node_path.dirname)(outputFilePath), { recursive: true });
|
|
56
56
|
(0, node_fs.writeFileSync)(outputFilePath, output);
|
|
57
57
|
};
|
|
@@ -64,7 +64,7 @@ const reviewFileBlockAware = async (baseFilePath, outputFilePath, locale, baseLo
|
|
|
64
64
|
applicationLogger(`${filePrefix}No segments need review, reusing existing translation`);
|
|
65
65
|
writeCurrentState();
|
|
66
66
|
}
|
|
67
|
-
applicationLogger(`${(0, _intlayer_config_logger.colorize)("✔", _intlayer_config_colors.GREEN)} File ${(0,
|
|
67
|
+
applicationLogger(`${(0, _intlayer_config_logger.colorize)("✔", _intlayer_config_colors.GREEN)} File ${(0, _intlayer_engine_utils.formatPath)(outputFilePath)} updated successfully (no AI changes needed).`);
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
applicationLogger(`${filePrefix}Segments to review: ${(0, _intlayer_config_logger.colorizeNumber)(segmentsToReview.length)} (processing bottom-up)`);
|
|
@@ -74,8 +74,8 @@ const reviewFileBlockAware = async (baseFilePath, outputFilePath, locale, baseLo
|
|
|
74
74
|
})).reverse();
|
|
75
75
|
for (const { segment, displayNumber } of segmentsBottomUp) {
|
|
76
76
|
const baseBlock = segment.baseBlock;
|
|
77
|
-
const getBaseChunkContextPrompt = () => `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the base block in ${(0,
|
|
78
|
-
const getTargetChunkPrompt = () => `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the current block to review in ${(0,
|
|
77
|
+
const getBaseChunkContextPrompt = () => `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the base block in ${(0, _intlayer_engine_utils.formatLocale)(baseLocale, false)} as reference.\n///chunksStart///\n` + baseBlock.content + `///chunksEnd///`;
|
|
78
|
+
const getTargetChunkPrompt = () => `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the current block to review in ${(0, _intlayer_engine_utils.formatLocale)(locale, false)}.\n///chunksStart///\n` + (segment.targetBlockText ?? "") + `///chunksEnd///`;
|
|
79
79
|
const reviewedChunkResult = await (0, _intlayer_config_utils.retryManager)(async () => {
|
|
80
80
|
const result = await require_utils_chunkInference.chunkInference([
|
|
81
81
|
{
|
|
@@ -107,7 +107,7 @@ const reviewFileBlockAware = async (baseFilePath, outputFilePath, locale, baseLo
|
|
|
107
107
|
reviewedSegmentsMap.set(segment.actionIndex, reviewedChunkResult);
|
|
108
108
|
writeCurrentState();
|
|
109
109
|
}
|
|
110
|
-
applicationLogger(`${(0, _intlayer_config_logger.colorize)("✔", _intlayer_config_colors.GREEN)} File ${(0,
|
|
110
|
+
applicationLogger(`${(0, _intlayer_config_logger.colorize)("✔", _intlayer_config_colors.GREEN)} File ${(0, _intlayer_engine_utils.formatPath)(outputFilePath)} created/updated successfully.`);
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDocBlockAware.cjs","names":["readAsset","ANSIColors","chunkInference","ENGLISH","sanitizeChunk","fixChunkStartEndChars","validateTranslation"],"sources":["../../../src/reviewDoc/reviewDocBlockAware.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n buildAlignmentPlan,\n mergeReviewedSegments,\n} from '@intlayer/chokidar/docReview';\nimport { formatLocale, formatPath } from '@intlayer/chokidar/utils';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { retryManager } from '@intlayer/config/utils';\nimport { getLocaleName } from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport { sanitizeChunk, validateTranslation } from '../translateDoc/validation';\nimport { chunkInference } from '../utils/chunkInference';\nimport { fixChunkStartEndChars } from '../utils/fixChunkStartEndChars';\nimport type { AIClient } from '../utils/setupAI';\n\n/**\n * Review a file using block-aware alignment.\n *\n * 1. Segments both base and target documents into semantic blocks.\n * 2. Aligns blocks using structure (special chars, numbers) and context.\n * 3. Detects which blocks changed, were added, or deleted.\n * 4. Applies deletions immediately without AI.\n * 5. Sends changed/new blocks to AI in bottom-up order (last block first), so\n * line numbers of earlier blocks are not shifted by edits below them.\n * 6. Rewrites the file after each block so progress is persisted incrementally.\n */\nexport const reviewFileBlockAware = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locale,\n baseLocale: Locale,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string,\n changedLines?: number[],\n aiClient?: AIClient,\n aiConfig?: AIConfig\n) => {\n const configuration = getConfiguration(configOptions);\n const applicationLogger = getAppLogger({\n log: { ...configuration.log, prefix: '' },\n });\n\n const baseText = await readFile(baseFilePath, 'utf-8');\n const targetText = await readFile(outputFilePath, 'utf-8').catch(() => '');\n\n const basePrompt = readAsset('./prompts/REVIEW_PROMPT.md', 'utf-8')\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // Build block-aware alignment and plan\n const { baseBlocks, targetBlocks, plan, segmentsToReview } =\n buildAlignmentPlan({\n baseText,\n targetText,\n changedLines,\n });\n\n const deleteCount = plan.actions.filter((a) => a.kind === 'delete').length;\n\n applicationLogger(\n `${filePrefix}Block-aware alignment complete. Total blocks: base=${colorizeNumber(baseBlocks.length)}, target=${colorizeNumber(targetBlocks.length)}`\n );\n applicationLogger(\n `${filePrefix}Actions: reuse=${colorizeNumber(plan.actions.filter((a) => a.kind === 'reuse').length)}, review=${colorizeNumber(plan.actions.filter((a) => a.kind === 'review').length)}, new=${colorizeNumber(plan.actions.filter((a) => a.kind === 'insert_new').length)}, delete=${colorizeNumber(deleteCount)}`\n );\n\n // Map shared across the entire run: each entry overrides the default behavior\n // of mergeReviewedSegments for that action index.\n const reviewedSegmentsMap = new Map<number, string>();\n\n // --- Step 1: apply deletions immediately (no AI needed) ---\n for (const [actionIndex, action] of plan.actions.entries()) {\n if (action.kind === 'delete') {\n reviewedSegmentsMap.set(actionIndex, '');\n }\n }\n\n const writeCurrentState = (): void => {\n const output = mergeReviewedSegments(\n plan,\n targetBlocks,\n reviewedSegmentsMap\n );\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, output);\n };\n\n if (deleteCount > 0) {\n writeCurrentState();\n applicationLogger(\n `${filePrefix}${colorizeNumber(deleteCount)} block(s) deleted without AI.`\n );\n }\n\n if (segmentsToReview.length === 0) {\n if (deleteCount === 0) {\n applicationLogger(\n `${filePrefix}No segments need review, reusing existing translation`\n );\n writeCurrentState();\n }\n applicationLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(outputFilePath)} updated successfully (no AI changes needed).`\n );\n return;\n }\n\n applicationLogger(\n `${filePrefix}Segments to review: ${colorizeNumber(segmentsToReview.length)} (processing bottom-up)`\n );\n\n // --- Step 2: process AI segments in bottom-up order ---\n // Reversing ensures edits near the end of the file don't shift line numbers\n // that matter for blocks higher up, and each intermediate file write is valid.\n const segmentsBottomUp = segmentsToReview\n .map((segment, originalIndex) => ({\n segment,\n displayNumber: originalIndex + 1,\n }))\n .reverse();\n\n for (const { segment, displayNumber } of segmentsBottomUp) {\n const baseBlock = segment.baseBlock;\n\n const getBaseChunkContextPrompt = () =>\n `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the base block in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///\\n` +\n baseBlock.content +\n `///chunksEnd///`;\n\n const getTargetChunkPrompt = () =>\n `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the current block to review in ${formatLocale(locale, false)}.\\n` +\n `///chunksStart///\\n` +\n (segment.targetBlockText ?? '') +\n `///chunksEnd///`;\n\n const reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getTargetChunkPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **BLOCK ${colorizeNumber(displayNumber)} of ${colorizeNumber(segmentsToReview.length)}** that should be translated in ${getLocaleName(locale, ENGLISH)} (${locale}).`,\n },\n ],\n [{ role: 'user', content: baseBlock.content }],\n aiOptions,\n configuration,\n aiClient,\n aiConfig\n );\n\n applicationLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Block ${colorizeNumber(displayNumber)} of ${colorizeNumber(segmentsToReview.length)}`\n );\n\n let processedChunk = sanitizeChunk(\n result?.fileContent,\n baseBlock.content\n );\n processedChunk = fixChunkStartEndChars(processedChunk, baseBlock.content);\n\n const isValid = validateTranslation(\n baseBlock.content,\n processedChunk,\n applicationLogger\n );\n\n if (!isValid) {\n throw new Error(\n 'Validation failed for chunk (structure or length mismatch). Retrying...'\n );\n }\n\n return processedChunk;\n })();\n\n reviewedSegmentsMap.set(segment.actionIndex, reviewedChunkResult);\n\n // Rewrite the file after every block so progress is never lost.\n writeCurrentState();\n }\n\n applicationLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(outputFilePath)} created/updated successfully.`\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAa,uBAAuB,OAClC,cACA,gBACA,QACA,YACA,WACA,eACA,oBACA,cACA,UACA,aACG;CACH,MAAM,4DAAiC,cAAc;CACrD,MAAM,8DAAiC,EACrC,KAAK;EAAE,GAAG,cAAc;EAAK,QAAQ;EAAI,EAC1C,CAAC;CAEF,MAAM,WAAW,qCAAe,cAAc,QAAQ;CACtD,MAAM,aAAa,qCAAe,gBAAgB,QAAQ,CAAC,YAAY,GAAG;CAE1E,MAAM,aAAaA,+BAAU,8BAA8B,QAAQ,CAChE,WAAW,kBAAkB,8CAAgB,QAAQ,MAAM,GAAG,CAC9D,WAAW,sBAAsB,8CAAgB,YAAY,MAAM,GAAG,CACtE,QAAQ,0BAA0B,WAAW,sBAAsB,IAAI,CACvE,QAAQ,0BAA0B,sBAAsB,IAAI;CAG/D,MAAM,aAAa,oCACX,GAFkBC,wBAAW,UAAU,4CAAc,aAAa,GAAGA,wBAAW,UAAU,KAE1E,EAAE,SAAS,IAAI,CAAC,EACtC,KAAKA,wBAAW,QACjB,CAAC,KAAK,GAAG;CAEV,MAAM,SAAS,oCACP,GAFcA,wBAAW,UAAU,4CAAc,aAAa,GAAGA,wBAAW,UAAU,+CAAiB,OAAO,GAAGA,wBAAW,UAAU,KAE1H,EAAE,SAAS,IAAI,CAAC,EAClC,KAAKA,wBAAW,QACjB,CAAC,KAAK,GAAG;CAGV,MAAM,EAAE,YAAY,cAAc,MAAM,0EACnB;EACjB;EACA;EACA;EACD,CAAC;CAEJ,MAAM,cAAc,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC;AAEpE,mBACE,GAAG,WAAW,iGAAoE,WAAW,OAAO,CAAC,uDAA0B,aAAa,OAAO,GACpJ;AACD,mBACE,GAAG,WAAW,6DAAgC,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,OAAO,CAAC,uDAA0B,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC,OAAO,CAAC,oDAAuB,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,aAAa,CAAC,OAAO,CAAC,uDAA0B,YAAY,GACjT;CAID,MAAM,sCAAsB,IAAI,KAAqB;AAGrD,MAAK,MAAM,CAAC,aAAa,WAAW,KAAK,QAAQ,SAAS,CACxD,KAAI,OAAO,SAAS,SAClB,qBAAoB,IAAI,aAAa,GAAG;CAI5C,MAAM,0BAAgC;EACpC,MAAM,iEACJ,MACA,cACA,oBACD;AACD,gDAAkB,eAAe,EAAE,EAAE,WAAW,MAAM,CAAC;AACvD,6BAAc,gBAAgB,OAAO;;AAGvC,KAAI,cAAc,GAAG;AACnB,qBAAmB;AACnB,oBACE,GAAG,yDAA4B,YAAY,CAAC,+BAC7C;;AAGH,KAAI,iBAAiB,WAAW,GAAG;AACjC,MAAI,gBAAgB,GAAG;AACrB,qBACE,GAAG,WAAW,uDACf;AACD,sBAAmB;;AAErB,oBACE,yCAAY,KAAKA,wBAAW,MAAM,CAAC,iDAAmB,eAAe,CAAC,+CACvE;AACD;;AAGF,mBACE,GAAG,WAAW,kEAAqC,iBAAiB,OAAO,CAAC,yBAC7E;CAKD,MAAM,mBAAmB,iBACtB,KAAK,SAAS,mBAAmB;EAChC;EACA,eAAe,gBAAgB;EAChC,EAAE,CACF,SAAS;AAEZ,MAAK,MAAM,EAAE,SAAS,mBAAmB,kBAAkB;EACzD,MAAM,YAAY,QAAQ;EAE1B,MAAM,kCACJ,WAAW,cAAc,MAAM,iBAAiB,OAAO,qEAAuC,YAAY,MAAM,CAAC,uCAEjH,UAAU,UACV;EAEF,MAAM,6BACJ,WAAW,cAAc,MAAM,iBAAiB,OAAO,kFAAoD,QAAQ,MAAM,CAAC,2BAEzH,QAAQ,mBAAmB,MAC5B;EAEF,MAAM,sBAAsB,+CAAmB,YAAY;GACzD,MAAM,SAAS,MAAMC,4CACnB;IACE;KAAE,MAAM;KAAU,SAAS;KAAY;IACvC;KAAE,MAAM;KAAU,SAAS,2BAA2B;KAAE;IACxD;KAAE,MAAM;KAAU,SAAS,sBAAsB;KAAE;IACnD;KACE,MAAM;KACN,SAAS,yFAA4D,cAAc,CAAC,kDAAqB,iBAAiB,OAAO,CAAC,iFAAgD,QAAQC,gCAAQ,CAAC,IAAI,OAAO;KAC/M;IACF,EACD,CAAC;IAAE,MAAM;IAAQ,SAAS,UAAU;IAAS,CAAC,EAC9C,WACA,eACA,UACA,SACD;AAED,qBACE,GAAG,qDAAwB,OAAO,UAAU,CAAC,mEAAsC,cAAc,CAAC,kDAAqB,iBAAiB,OAAO,GAChJ;GAED,IAAI,iBAAiBC,8CACnB,QAAQ,aACR,UAAU,QACX;AACD,oBAAiBC,0DAAsB,gBAAgB,UAAU,QAAQ;AAQzE,OAAI,CANYC,oDACd,UAAU,SACV,gBACA,kBAGU,CACV,OAAM,IAAI,MACR,0EACD;AAGH,UAAO;IACP,EAAE;AAEJ,sBAAoB,IAAI,QAAQ,aAAa,oBAAoB;AAGjE,qBAAmB;;AAGrB,mBACE,yCAAY,KAAKL,wBAAW,MAAM,CAAC,iDAAmB,eAAe,CAAC,gCACvE"}
|
|
1
|
+
{"version":3,"file":"reviewDocBlockAware.cjs","names":["readAsset","ANSIColors","chunkInference","ENGLISH","sanitizeChunk","fixChunkStartEndChars","validateTranslation"],"sources":["../../../src/reviewDoc/reviewDocBlockAware.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { retryManager } from '@intlayer/config/utils';\nimport { getLocaleName } from '@intlayer/core/localization';\nimport {\n buildAlignmentPlan,\n mergeReviewedSegments,\n} from '@intlayer/engine/docReview';\nimport { formatLocale, formatPath } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport { sanitizeChunk, validateTranslation } from '../translateDoc/validation';\nimport { chunkInference } from '../utils/chunkInference';\nimport { fixChunkStartEndChars } from '../utils/fixChunkStartEndChars';\nimport type { AIClient } from '../utils/setupAI';\n\n/**\n * Review a file using block-aware alignment.\n *\n * 1. Segments both base and target documents into semantic blocks.\n * 2. Aligns blocks using structure (special chars, numbers) and context.\n * 3. Detects which blocks changed, were added, or deleted.\n * 4. Applies deletions immediately without AI.\n * 5. Sends changed/new blocks to AI in bottom-up order (last block first), so\n * line numbers of earlier blocks are not shifted by edits below them.\n * 6. Rewrites the file after each block so progress is persisted incrementally.\n */\nexport const reviewFileBlockAware = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locale,\n baseLocale: Locale,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string,\n changedLines?: number[],\n aiClient?: AIClient,\n aiConfig?: AIConfig\n) => {\n const configuration = getConfiguration(configOptions);\n const applicationLogger = getAppLogger({\n log: { ...configuration.log, prefix: '' },\n });\n\n const baseText = await readFile(baseFilePath, 'utf-8');\n const targetText = await readFile(outputFilePath, 'utf-8').catch(() => '');\n\n const basePrompt = readAsset('./prompts/REVIEW_PROMPT.md', 'utf-8')\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // Build block-aware alignment and plan\n const { baseBlocks, targetBlocks, plan, segmentsToReview } =\n buildAlignmentPlan({\n baseText,\n targetText,\n changedLines,\n });\n\n const deleteCount = plan.actions.filter((a) => a.kind === 'delete').length;\n\n applicationLogger(\n `${filePrefix}Block-aware alignment complete. Total blocks: base=${colorizeNumber(baseBlocks.length)}, target=${colorizeNumber(targetBlocks.length)}`\n );\n applicationLogger(\n `${filePrefix}Actions: reuse=${colorizeNumber(plan.actions.filter((a) => a.kind === 'reuse').length)}, review=${colorizeNumber(plan.actions.filter((a) => a.kind === 'review').length)}, new=${colorizeNumber(plan.actions.filter((a) => a.kind === 'insert_new').length)}, delete=${colorizeNumber(deleteCount)}`\n );\n\n // Map shared across the entire run: each entry overrides the default behavior\n // of mergeReviewedSegments for that action index.\n const reviewedSegmentsMap = new Map<number, string>();\n\n // --- Step 1: apply deletions immediately (no AI needed) ---\n for (const [actionIndex, action] of plan.actions.entries()) {\n if (action.kind === 'delete') {\n reviewedSegmentsMap.set(actionIndex, '');\n }\n }\n\n const writeCurrentState = (): void => {\n const output = mergeReviewedSegments(\n plan,\n targetBlocks,\n reviewedSegmentsMap\n );\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, output);\n };\n\n if (deleteCount > 0) {\n writeCurrentState();\n applicationLogger(\n `${filePrefix}${colorizeNumber(deleteCount)} block(s) deleted without AI.`\n );\n }\n\n if (segmentsToReview.length === 0) {\n if (deleteCount === 0) {\n applicationLogger(\n `${filePrefix}No segments need review, reusing existing translation`\n );\n writeCurrentState();\n }\n applicationLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(outputFilePath)} updated successfully (no AI changes needed).`\n );\n return;\n }\n\n applicationLogger(\n `${filePrefix}Segments to review: ${colorizeNumber(segmentsToReview.length)} (processing bottom-up)`\n );\n\n // --- Step 2: process AI segments in bottom-up order ---\n // Reversing ensures edits near the end of the file don't shift line numbers\n // that matter for blocks higher up, and each intermediate file write is valid.\n const segmentsBottomUp = segmentsToReview\n .map((segment, originalIndex) => ({\n segment,\n displayNumber: originalIndex + 1,\n }))\n .reverse();\n\n for (const { segment, displayNumber } of segmentsBottomUp) {\n const baseBlock = segment.baseBlock;\n\n const getBaseChunkContextPrompt = () =>\n `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the base block in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///\\n` +\n baseBlock.content +\n `///chunksEnd///`;\n\n const getTargetChunkPrompt = () =>\n `**BLOCK ${displayNumber} of ${segmentsToReview.length}** is the current block to review in ${formatLocale(locale, false)}.\\n` +\n `///chunksStart///\\n` +\n (segment.targetBlockText ?? '') +\n `///chunksEnd///`;\n\n const reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getTargetChunkPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **BLOCK ${colorizeNumber(displayNumber)} of ${colorizeNumber(segmentsToReview.length)}** that should be translated in ${getLocaleName(locale, ENGLISH)} (${locale}).`,\n },\n ],\n [{ role: 'user', content: baseBlock.content }],\n aiOptions,\n configuration,\n aiClient,\n aiConfig\n );\n\n applicationLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Block ${colorizeNumber(displayNumber)} of ${colorizeNumber(segmentsToReview.length)}`\n );\n\n let processedChunk = sanitizeChunk(\n result?.fileContent,\n baseBlock.content\n );\n processedChunk = fixChunkStartEndChars(processedChunk, baseBlock.content);\n\n const isValid = validateTranslation(\n baseBlock.content,\n processedChunk,\n applicationLogger\n );\n\n if (!isValid) {\n throw new Error(\n 'Validation failed for chunk (structure or length mismatch). Retrying...'\n );\n }\n\n return processedChunk;\n })();\n\n reviewedSegmentsMap.set(segment.actionIndex, reviewedChunkResult);\n\n // Rewrite the file after every block so progress is never lost.\n writeCurrentState();\n }\n\n applicationLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(outputFilePath)} created/updated successfully.`\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAa,uBAAuB,OAClC,cACA,gBACA,QACA,YACA,WACA,eACA,oBACA,cACA,UACA,aACG;CACH,MAAM,4DAAiC,aAAa;CACpD,MAAM,8DAAiC,EACrC,KAAK;EAAE,GAAG,cAAc;EAAK,QAAQ;CAAG,EAC1C,CAAC;CAED,MAAM,WAAW,qCAAe,cAAc,OAAO;CACrD,MAAM,aAAa,qCAAe,gBAAgB,OAAO,CAAC,CAAC,YAAY,EAAE;CAEzE,MAAM,aAAaA,+BAAU,8BAA8B,OAAO,CAAC,CAChE,WAAW,kBAAkB,4CAAgB,QAAQ,KAAK,GAAG,CAAC,CAC9D,WAAW,sBAAsB,4CAAgB,YAAY,KAAK,GAAG,CAAC,CACtE,QAAQ,0BAA0B,WAAW,sBAAsB,GAAG,CAAC,CACvE,QAAQ,0BAA0B,sBAAsB,GAAG;CAG9D,MAAM,aAAa,oCACX,GAFkBC,wBAAW,UAAU,0CAAc,YAAY,IAAIA,wBAAW,UAAU,KAE1E,EAAE,SAAS,GAAG,CAAC,GACrC,KAAKA,wBAAW,OAClB,CAAC,CAAC,KAAK,EAAE;CAET,MAAM,SAAS,oCACP,GAFcA,wBAAW,UAAU,0CAAc,YAAY,IAAIA,wBAAW,UAAU,6CAAiB,MAAM,IAAIA,wBAAW,UAAU,KAE1H,EAAE,SAAS,GAAG,CAAC,GACjC,KAAKA,wBAAW,OAClB,CAAC,CAAC,KAAK,EAAE;CAGT,MAAM,EAAE,YAAY,cAAc,MAAM,wEACnB;EACjB;EACA;EACA;CACF,CAAC;CAEH,MAAM,cAAc,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,CAAC;CAEpE,kBACE,GAAG,WAAW,iGAAoE,WAAW,MAAM,EAAE,uDAA0B,aAAa,MAAM,GACpJ;CACA,kBACE,GAAG,WAAW,6DAAgC,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,OAAO,CAAC,CAAC,MAAM,EAAE,uDAA0B,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,CAAC,MAAM,EAAE,oDAAuB,KAAK,QAAQ,QAAQ,MAAM,EAAE,SAAS,YAAY,CAAC,CAAC,MAAM,EAAE,uDAA0B,WAAW,GACjT;CAIA,MAAM,sCAAsB,IAAI,IAAoB;CAGpD,KAAK,MAAM,CAAC,aAAa,WAAW,KAAK,QAAQ,QAAQ,GACvD,IAAI,OAAO,SAAS,UAClB,oBAAoB,IAAI,aAAa,EAAE;CAI3C,MAAM,0BAAgC;EACpC,MAAM,+DACJ,MACA,cACA,mBACF;EACA,8CAAkB,cAAc,GAAG,EAAE,WAAW,KAAK,CAAC;EACtD,2BAAc,gBAAgB,MAAM;CACtC;CAEA,IAAI,cAAc,GAAG;EACnB,kBAAkB;EAClB,kBACE,GAAG,yDAA4B,WAAW,EAAE,8BAC9C;CACF;CAEA,IAAI,iBAAiB,WAAW,GAAG;EACjC,IAAI,gBAAgB,GAAG;GACrB,kBACE,GAAG,WAAW,sDAChB;GACA,kBAAkB;EACpB;EACA,kBACE,yCAAY,KAAKA,wBAAW,KAAK,EAAE,+CAAmB,cAAc,EAAE,8CACxE;EACA;CACF;CAEA,kBACE,GAAG,WAAW,kEAAqC,iBAAiB,MAAM,EAAE,wBAC9E;CAKA,MAAM,mBAAmB,iBACtB,KAAK,SAAS,mBAAmB;EAChC;EACA,eAAe,gBAAgB;CACjC,EAAE,CAAC,CACF,QAAQ;CAEX,KAAK,MAAM,EAAE,SAAS,mBAAmB,kBAAkB;EACzD,MAAM,YAAY,QAAQ;EAE1B,MAAM,kCACJ,WAAW,cAAc,MAAM,iBAAiB,OAAO,mEAAuC,YAAY,KAAK,EAAE,uCAEjH,UAAU,UACV;EAEF,MAAM,6BACJ,WAAW,cAAc,MAAM,iBAAiB,OAAO,gFAAoD,QAAQ,KAAK,EAAE,2BAEzH,QAAQ,mBAAmB,MAC5B;EAEF,MAAM,sBAAsB,+CAAmB,YAAY;GACzD,MAAM,SAAS,MAAMC,4CACnB;IACE;KAAE,MAAM;KAAU,SAAS;IAAW;IACtC;KAAE,MAAM;KAAU,SAAS,0BAA0B;IAAE;IACvD;KAAE,MAAM;KAAU,SAAS,qBAAqB;IAAE;IAClD;KACE,MAAM;KACN,SAAS,yFAA4D,aAAa,EAAE,kDAAqB,iBAAiB,MAAM,EAAE,iFAAgD,QAAQC,+BAAO,EAAE,IAAI,OAAO;IAChN;GACF,GACA,CAAC;IAAE,MAAM;IAAQ,SAAS,UAAU;GAAQ,CAAC,GAC7C,WACA,eACA,UACA,QACF;GAEA,kBACE,GAAG,qDAAwB,OAAO,SAAS,EAAE,mEAAsC,aAAa,EAAE,kDAAqB,iBAAiB,MAAM,GAChJ;GAEA,IAAI,iBAAiBC,8CACnB,QAAQ,aACR,UAAU,OACZ;GACA,iBAAiBC,0DAAsB,gBAAgB,UAAU,OAAO;GAQxE,IAAI,CANYC,oDACd,UAAU,SACV,gBACA,iBAGS,GACT,MAAM,IAAI,MACR,yEACF;GAGF,OAAO;EACT,CAAC,CAAC,CAAC;EAEH,oBAAoB,IAAI,QAAQ,aAAa,mBAAmB;EAGhE,kBAAkB;CACpB;CAEA,kBACE,yCAAY,KAAKL,wBAAW,KAAK,EAAE,+CAAmB,cAAc,EAAE,+BACxE;AACF"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
2
|
let node_fs = require("node:fs");
|
|
4
|
-
let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
|
|
5
3
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
6
4
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
5
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
7
6
|
let node_fs_promises = require("node:fs/promises");
|
|
8
|
-
let
|
|
7
|
+
let _intlayer_engine_docReview = require("@intlayer/engine/docReview");
|
|
9
8
|
|
|
10
9
|
//#region src/reviewDoc/reviewDocLog.ts
|
|
11
10
|
/**
|
|
@@ -29,16 +28,16 @@ const logReviewFileBlocks = async (baseFilePath, outputFilePath, locale, baseLoc
|
|
|
29
28
|
...(0, _intlayer_config_node.getConfiguration)(configOptions).log,
|
|
30
29
|
prefix: ""
|
|
31
30
|
} });
|
|
32
|
-
const report = (0,
|
|
31
|
+
const report = (0, _intlayer_engine_docReview.buildReviewReport)({
|
|
33
32
|
baseText: await (0, node_fs_promises.readFile)(baseFilePath, "utf-8"),
|
|
34
33
|
targetText: (0, node_fs.existsSync)(outputFilePath) ? await (0, node_fs_promises.readFile)(outputFilePath, "utf-8").catch(() => "") : "",
|
|
35
34
|
changedLines
|
|
36
35
|
});
|
|
37
|
-
const formatted = (0,
|
|
38
|
-
baseLabel: (0,
|
|
39
|
-
targetLabel: (0,
|
|
36
|
+
const formatted = (0, _intlayer_engine_docReview.formatReviewReport)(report, {
|
|
37
|
+
baseLabel: (0, _intlayer_engine_utils.formatLocale)(baseLocale),
|
|
38
|
+
targetLabel: (0, _intlayer_engine_utils.formatLocale)(locale)
|
|
40
39
|
});
|
|
41
|
-
appLogger(`${(0,
|
|
40
|
+
appLogger(`${(0, _intlayer_engine_utils.formatPath)(baseFilePath)} → ${(0, _intlayer_engine_utils.formatLocale)(locale)}`);
|
|
42
41
|
for (const line of formatted.split("\n")) appLogger(line);
|
|
43
42
|
return report;
|
|
44
43
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDocLog.cjs","names":[],"sources":["../../../src/reviewDoc/reviewDocLog.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport {
|
|
1
|
+
{"version":3,"file":"reviewDocLog.cjs","names":[],"sources":["../../../src/reviewDoc/reviewDocLog.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n buildReviewReport,\n formatReviewReport,\n type ReviewReport,\n} from '@intlayer/engine/docReview';\nimport { formatLocale, formatPath } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\n\n/**\n * Log-only review of a single file/locale pair.\n *\n * Instead of calling an AI to translate the changed blocks, this compares the\n * base document with its translation and logs the blocks that need attention\n * (with their line ranges and content) so another agent or a human can generate\n * the missing translations.\n *\n * @param baseFilePath - Absolute path of the base (source) document.\n * @param outputFilePath - Absolute path of the target (translated) document.\n * @param locale - The target locale being reviewed.\n * @param baseLocale - The base locale used as reference.\n * @param configOptions - Optional Intlayer configuration overrides.\n * @param changedLines - 1-based base line numbers that changed (from git), if any.\n * @returns The structured review report.\n */\nexport const logReviewFileBlocks = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locale,\n baseLocale: Locale,\n configOptions?: GetConfigurationOptions,\n changedLines?: number[]\n): Promise<ReviewReport> => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger({ log: { ...configuration.log, prefix: '' } });\n\n const baseText = await readFile(baseFilePath, 'utf-8');\n const targetText = existsSync(outputFilePath)\n ? await readFile(outputFilePath, 'utf-8').catch(() => '')\n : '';\n\n const report = buildReviewReport({ baseText, targetText, changedLines });\n\n const formatted = formatReviewReport(report, {\n baseLabel: formatLocale(baseLocale),\n targetLabel: formatLocale(locale),\n });\n\n appLogger(`${formatPath(baseFilePath)} → ${formatLocale(locale)}`);\n for (const line of formatted.split('\\n')) {\n appLogger(line);\n }\n\n return report;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,sBAAsB,OACjC,cACA,gBACA,QACA,YACA,eACA,iBAC0B;CAE1B,MAAM,sDAAyB,EAAE,KAAK;EAAE,+CADD,aACgB,CAAC,CAAC;EAAK,QAAQ;CAAG,EAAE,CAAC;CAO5E,MAAM,2DAA2B;EAAE,+CALH,cAAc,OAAO;EAKR,oCAJf,cAAc,IACxC,qCAAe,gBAAgB,OAAO,CAAC,CAAC,YAAY,EAAE,IACtD;EAEqD;CAAa,CAAC;CAEvE,MAAM,+DAA+B,QAAQ;EAC3C,oDAAwB,UAAU;EAClC,sDAA0B,MAAM;CAClC,CAAC;CAED,UAAU,0CAAc,YAAY,EAAE,8CAAkB,MAAM,GAAG;CACjE,KAAK,MAAM,QAAQ,UAAU,MAAM,IAAI,GACrC,UAAU,IAAI;CAGhB,OAAO;AACT"}
|
package/dist/cjs/scan.cjs
CHANGED
|
@@ -4,7 +4,7 @@ let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
|
4
4
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
5
5
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
6
6
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
7
|
-
let
|
|
7
|
+
let _intlayer_engine_scan = require("@intlayer/engine/scan");
|
|
8
8
|
|
|
9
9
|
//#region src/scan.ts
|
|
10
10
|
/** Human-readable labels for each scorable check type. */
|
|
@@ -46,14 +46,14 @@ const scoreColor = (score) => {
|
|
|
46
46
|
*/
|
|
47
47
|
const scan = async (url, options = {}) => {
|
|
48
48
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)((0, _intlayer_config_node.getConfiguration)(options.configOptions));
|
|
49
|
-
const result = await (0,
|
|
49
|
+
const result = await (0, _intlayer_engine_scan.scanWebsite)(url, { deep: options.deep });
|
|
50
50
|
if (options.json) {
|
|
51
51
|
appLogger(JSON.stringify(result, null, 2));
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
appLogger(`\n🔍 Scanned ${(0, _intlayer_config_logger.colorize)(result.url, _intlayer_config_colors.GREY_LIGHT)} ${(0, _intlayer_config_logger.colorize)(`(${result.mode} mode)`, _intlayer_config_colors.GREY)}\n`);
|
|
55
55
|
appLogger(`Score: ${(0, _intlayer_config_logger.colorize)(`${result.score}/100`, scoreColor(result.score))}`);
|
|
56
|
-
appLogger(`Page size: ${(0, _intlayer_config_logger.colorize)((0,
|
|
56
|
+
appLogger(`Page size: ${(0, _intlayer_config_logger.colorize)((0, _intlayer_engine_scan.formatSize)(result.totalPageSize), _intlayer_config_colors.BLUE)} ${(0, _intlayer_config_logger.colorize)(`(HTML ${(0, _intlayer_engine_scan.formatSize)(result.htmlSize)})`, _intlayer_config_colors.GREY)}`);
|
|
57
57
|
if (result.locales.length > 0) appLogger(`Locales: ${(0, _intlayer_config_logger.colorize)(result.locales.join(", "), _intlayer_config_colors.GREEN)}`);
|
|
58
58
|
appLogger("\nChecks:");
|
|
59
59
|
for (const event of result.events) {
|
|
@@ -65,8 +65,8 @@ const scan = async (url, options = {}) => {
|
|
|
65
65
|
if (result.bundle && result.bundle.totalLocaleSize > 0) {
|
|
66
66
|
const { bundle } = result;
|
|
67
67
|
appLogger("\nBundle locale weight:");
|
|
68
|
-
appLogger(` Translations shipped: ${(0, _intlayer_config_logger.colorize)((0,
|
|
69
|
-
appLogger(` Unused (other locales): ${(0, _intlayer_config_logger.colorize)(`${(0,
|
|
68
|
+
appLogger(` Translations shipped: ${(0, _intlayer_config_logger.colorize)((0, _intlayer_engine_scan.formatSize)(bundle.totalLocaleSize), _intlayer_config_colors.BLUE)}`);
|
|
69
|
+
appLogger(` Unused (other locales): ${(0, _intlayer_config_logger.colorize)(`${(0, _intlayer_engine_scan.formatSize)(bundle.totalUnusedLocaleSize)} (${bundle.unusedPercentOfLocale}%)`, bundle.unusedPercentOfLocale > 30 ? _intlayer_config_colors.RED : bundle.unusedPercentOfLocale > 0 ? _intlayer_config_colors.YELLOW : _intlayer_config_colors.GREEN)}`);
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
|
package/dist/cjs/scan.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.cjs","names":["ANSIColors"],"sources":["../../src/scan.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"scan.cjs","names":["ANSIColors"],"sources":["../../src/scan.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { formatSize, type ScanEvent, scanWebsite } from '@intlayer/engine/scan';\nimport type { ConfigurationOptions } from './cli';\n\n/** Options accepted by the {@link scan} command. */\nexport type ScanCommandOptions = {\n /** Disable the deeper puppeteer-based render scan. */\n deep?: boolean;\n /** Output the raw {@link ScanResult} as JSON instead of formatted text. */\n json?: boolean;\n configOptions?: ConfigurationOptions;\n};\n\n/** Human-readable labels for each scorable check type. */\nconst checkLabels: Record<string, string> = {\n robots_robotsPresent: 'robots.txt present',\n robots_noLocalizedUrlsForgotten: 'robots.txt keeps locale paths crawlable',\n sitemap_sitemapPresent: 'sitemap.xml present',\n sitemap_noLocalizedUrlsForgotten: 'sitemap lists every locale',\n sitemap_hasAlternates: 'sitemap has alternate links',\n sitemap_hasXDefault: 'sitemap has x-default',\n url_htmlLang: 'html lang attribute',\n url_htmlDir: 'html dir attribute',\n url_hasCanonical: 'canonical link',\n url_hreflang: 'hreflang tags',\n url_hasLocalizedLinks: 'localized internal links',\n url_hasXDefault: 'x-default hreflang',\n url_allAnchorsLocalized: 'all internal links localized',\n url_currentLocale: 'current locale detected',\n url_unusedBundleContent: 'unused bundle locale content',\n};\n\nconst statusIcon = (status: ScanEvent['status']): string => {\n if (status === 'success') return colorize('✓', ANSIColors.GREEN);\n if (status === 'warning') return colorize('⚠', ANSIColors.YELLOW);\n return colorize('✗', ANSIColors.RED);\n};\n\nconst scoreColor = (score: number) => {\n if (score >= 80) return ANSIColors.GREEN;\n if (score >= 50) return ANSIColors.YELLOW;\n return ANSIColors.RED;\n};\n\n/**\n * Scan a website for i18n/SEO health and bundle weight, printing a formatted\n * report (or JSON with `--json`).\n *\n * @example\n * ```sh\n * npx intlayer scan https://intlayer.org\n * ```\n */\nexport const scan = async (\n url: string,\n options: ScanCommandOptions = {}\n): Promise<void> => {\n const configuration = getConfiguration(options.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const result = await scanWebsite(url, { deep: options.deep });\n\n if (options.json) {\n appLogger(JSON.stringify(result, null, 2));\n return;\n }\n\n appLogger(\n `\\n🔍 Scanned ${colorize(result.url, ANSIColors.GREY_LIGHT)} ${colorize(\n `(${result.mode} mode)`,\n ANSIColors.GREY\n )}\\n`\n );\n\n appLogger(\n `Score: ${colorize(`${result.score}/100`, scoreColor(result.score))}`\n );\n appLogger(\n `Page size: ${colorize(formatSize(result.totalPageSize), ANSIColors.BLUE)} ${colorize(\n `(HTML ${formatSize(result.htmlSize)})`,\n ANSIColors.GREY\n )}`\n );\n if (result.locales.length > 0) {\n appLogger(\n `Locales: ${colorize(result.locales.join(', '), ANSIColors.GREEN)}`\n );\n }\n\n appLogger('\\nChecks:');\n for (const event of result.events) {\n const type = event.type.split('\\\\')[0];\n\n if (!type) continue;\n\n const label = checkLabels[type] ?? type;\n appLogger(` ${statusIcon(event.status)} ${label}`);\n }\n\n if (result.bundle && result.bundle.totalLocaleSize > 0) {\n const { bundle } = result;\n appLogger('\\nBundle locale weight:');\n appLogger(\n ` Translations shipped: ${colorize(formatSize(bundle.totalLocaleSize), ANSIColors.BLUE)}`\n );\n appLogger(\n ` Unused (other locales): ${colorize(\n `${formatSize(bundle.totalUnusedLocaleSize)} (${bundle.unusedPercentOfLocale}%)`,\n bundle.unusedPercentOfLocale > 30\n ? ANSIColors.RED\n : bundle.unusedPercentOfLocale > 0\n ? ANSIColors.YELLOW\n : ANSIColors.GREEN\n )}`\n );\n }\n};\n"],"mappings":";;;;;;;;;;AAgBA,MAAM,cAAsC;CAC1C,sBAAsB;CACtB,iCAAiC;CACjC,wBAAwB;CACxB,kCAAkC;CAClC,uBAAuB;CACvB,qBAAqB;CACrB,cAAc;CACd,aAAa;CACb,kBAAkB;CAClB,cAAc;CACd,uBAAuB;CACvB,iBAAiB;CACjB,yBAAyB;CACzB,mBAAmB;CACnB,yBAAyB;AAC3B;AAEA,MAAM,cAAc,WAAwC;CAC1D,IAAI,WAAW,WAAW,6CAAgB,KAAKA,wBAAW,KAAK;CAC/D,IAAI,WAAW,WAAW,6CAAgB,KAAKA,wBAAW,MAAM;CAChE,6CAAgB,KAAKA,wBAAW,GAAG;AACrC;AAEA,MAAM,cAAc,UAAkB;CACpC,IAAI,SAAS,IAAI,OAAOA,wBAAW;CACnC,IAAI,SAAS,IAAI,OAAOA,wBAAW;CACnC,OAAOA,wBAAW;AACpB;;;;;;;;;;AAWA,MAAa,OAAO,OAClB,KACA,UAA8B,CAAC,MACb;CAElB,MAAM,kGADiC,QAAQ,aACJ,CAAC;CAE5C,MAAM,SAAS,6CAAkB,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;CAE5D,IAAI,QAAQ,MAAM;EAChB,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;EACzC;CACF;CAEA,UACE,sDAAyB,OAAO,KAAKA,wBAAW,UAAU,EAAE,yCAC1D,IAAI,OAAO,KAAK,SAChBA,wBAAW,IACb,EAAE,GACJ;CAEA,UACE,gDAAmB,GAAG,OAAO,MAAM,OAAO,WAAW,OAAO,KAAK,CAAC,GACpE;CACA,UACE,0FAAkC,OAAO,aAAa,GAAGA,wBAAW,IAAI,EAAE,yCACxE,+CAAoB,OAAO,QAAQ,EAAE,IACrCA,wBAAW,IACb,GACF;CACA,IAAI,OAAO,QAAQ,SAAS,GAC1B,UACE,kDAAqB,OAAO,QAAQ,KAAK,IAAI,GAAGA,wBAAW,KAAK,GAClE;CAGF,UAAU,WAAW;CACrB,KAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,OAAO,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC;EAEpC,IAAI,CAAC,MAAM;EAEX,MAAM,QAAQ,YAAY,SAAS;EACnC,UAAU,KAAK,WAAW,MAAM,MAAM,EAAE,GAAG,OAAO;CACpD;CAEA,IAAI,OAAO,UAAU,OAAO,OAAO,kBAAkB,GAAG;EACtD,MAAM,EAAE,WAAW;EACnB,UAAU,yBAAyB;EACnC,UACE,uGAA+C,OAAO,eAAe,GAAGA,wBAAW,IAAI,GACzF;EACA,UACE,mEACE,yCAAc,OAAO,qBAAqB,EAAE,IAAI,OAAO,sBAAsB,KAC7E,OAAO,wBAAwB,KAC3BA,wBAAW,MACX,OAAO,wBAAwB,IAC7BA,wBAAW,SACXA,wBAAW,KACnB,GACF;CACF;AACF"}
|
package/dist/cjs/searchDoc.cjs
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
4
2
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
5
3
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
4
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
6
5
|
let _intlayer_api = require("@intlayer/api");
|
|
7
6
|
|
|
8
7
|
//#region src/searchDoc.ts
|
|
9
8
|
const searchDoc = async ({ query, limit = 10, configOptions }) => {
|
|
10
9
|
const config = (0, _intlayer_config_node.getConfiguration)(configOptions);
|
|
11
|
-
(0,
|
|
10
|
+
(0, _intlayer_engine_cli.logConfigDetails)(configOptions);
|
|
12
11
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)(config);
|
|
13
12
|
try {
|
|
14
13
|
const { searchDoc } = (0, _intlayer_api.getSearchAPI)(void 0, config);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchDoc.cjs","names":[],"sources":["../../src/searchDoc.ts"],"sourcesContent":["import { getSearchAPI } from '@intlayer/api';\nimport {
|
|
1
|
+
{"version":3,"file":"searchDoc.cjs","names":[],"sources":["../../src/searchDoc.ts"],"sourcesContent":["import { getSearchAPI } from '@intlayer/api';\nimport {\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { logConfigDetails } from '@intlayer/engine/cli';\n\ninterface SearchDocOptions {\n query: string;\n limit?: number;\n configOptions?: GetConfigurationOptions;\n}\n\nexport const searchDoc = async ({\n query,\n limit = 10,\n configOptions,\n}: SearchDocOptions) => {\n const config = getConfiguration(configOptions);\n logConfigDetails(configOptions);\n\n const appLogger = getAppLogger(config);\n\n try {\n const { searchDoc } = getSearchAPI(undefined, config);\n const response = await searchDoc({\n input: query,\n limit: limit.toString(),\n returnContent: 'true',\n });\n\n if (!response.data || !Array.isArray(response.data)) {\n appLogger('No relevant chunks found.');\n return;\n }\n\n const chunks = response.data;\n\n appLogger(`Found ${colorizeNumber(chunks.length)} relevant chunks:`);\n\n chunks.forEach((chunk: any) => {\n appLogger('---');\n appLogger(`${colorizeKey('File')}: ${chunk.fileKey}`);\n appLogger(`${colorizeKey('Title')}: ${chunk.docName}`);\n appLogger(`${colorizeKey('URL')}: ${chunk.docUrl}`);\n appLogger(`${colorizeKey('Chunk')}: ${chunk.chunkNumber}`);\n appLogger(`${colorizeKey('Content')}:`);\n appLogger(chunk.content);\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n appLogger(`Search failed: ${errorMessage}`, { level: 'error' });\n }\n};\n"],"mappings":";;;;;;;AAkBA,MAAa,YAAY,OAAO,EAC9B,OACA,QAAQ,IACR,oBACsB;CACtB,MAAM,qDAA0B,aAAa;CAC7C,2CAAiB,aAAa;CAE9B,MAAM,sDAAyB,MAAM;CAErC,IAAI;EACF,MAAM,EAAE,8CAA2B,QAAW,MAAM;EACpD,MAAM,WAAW,MAAM,UAAU;GAC/B,OAAO;GACP,OAAO,MAAM,SAAS;GACtB,eAAe;EACjB,CAAC;EAED,IAAI,CAAC,SAAS,QAAQ,CAAC,MAAM,QAAQ,SAAS,IAAI,GAAG;GACnD,UAAU,2BAA2B;GACrC;EACF;EAEA,MAAM,SAAS,SAAS;EAExB,UAAU,qDAAwB,OAAO,MAAM,EAAE,kBAAkB;EAEnE,OAAO,SAAS,UAAe;GAC7B,UAAU,KAAK;GACf,UAAU,4CAAe,MAAM,EAAE,IAAI,MAAM,SAAS;GACpD,UAAU,4CAAe,OAAO,EAAE,IAAI,MAAM,SAAS;GACrD,UAAU,4CAAe,KAAK,EAAE,IAAI,MAAM,QAAQ;GAClD,UAAU,4CAAe,OAAO,EAAE,IAAI,MAAM,aAAa;GACzD,UAAU,4CAAe,SAAS,EAAE,EAAE;GACtC,UAAU,MAAM,OAAO;EACzB,CAAC;CACH,SAAS,OAAO;EAGd,UAAU,kBADR,iBAAiB,QAAQ,MAAM,UAAU,+BACC,EAAE,OAAO,QAAQ,CAAC;CAChE;AACF"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
4
2
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
3
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
5
4
|
let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
|
|
6
5
|
let _intlayer_core_plugins = require("@intlayer/core/plugins");
|
|
7
6
|
let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
|
|
@@ -12,7 +11,7 @@ const listMissingTranslationsWithConfig = (configuration) => {
|
|
|
12
11
|
const mergedDictionaries = (0, _intlayer_dictionaries_entry.getDictionaries)(configuration);
|
|
13
12
|
const missingTranslations = [];
|
|
14
13
|
const { locales, requiredLocales } = configuration.internationalization;
|
|
15
|
-
const dictionariesKeys = new Set([...Object.keys(unmergedDictionariesRecord), ...Object.keys(mergedDictionaries)]);
|
|
14
|
+
const dictionariesKeys = /* @__PURE__ */ new Set([...Object.keys(unmergedDictionariesRecord), ...Object.keys(mergedDictionaries)]);
|
|
16
15
|
for (const dictionaryKey of dictionariesKeys) {
|
|
17
16
|
const dictionaries = unmergedDictionariesRecord[dictionaryKey] ?? [];
|
|
18
17
|
const multilingualDictionary = dictionaries.filter((dictionary) => !dictionary.locale);
|
|
@@ -57,7 +56,7 @@ const listMissingTranslationsWithConfig = (configuration) => {
|
|
|
57
56
|
};
|
|
58
57
|
const listMissingTranslations = (configurationOptions) => {
|
|
59
58
|
const configuration = (0, _intlayer_config_node.getConfiguration)(configurationOptions);
|
|
60
|
-
(0,
|
|
59
|
+
(0, _intlayer_engine_cli.logConfigDetails)(configurationOptions);
|
|
61
60
|
return listMissingTranslationsWithConfig(configuration);
|
|
62
61
|
};
|
|
63
62
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listMissingTranslations.cjs","names":[],"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"listMissingTranslations.cjs","names":[],"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getMissingLocalesContentFromDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\nexport const listMissingTranslationsWithConfig = (\n configuration: IntlayerConfig\n) => {\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n const mergedDictionaries = getDictionaries(configuration);\n\n const missingTranslations: {\n key: string;\n filePath?: string;\n id?: string;\n locales: Locale[];\n }[] = [];\n\n const { locales, requiredLocales } = configuration.internationalization;\n\n // Use the union of keys from both unmerged and merged dictionaries so that\n // dictionaries compiled only as merged (no per-locale split) are still checked.\n const dictionariesKeys = new Set([\n ...Object.keys(unmergedDictionariesRecord),\n ...Object.keys(mergedDictionaries),\n ]);\n\n for (const dictionaryKey of dictionariesKeys) {\n const dictionaries: Dictionary[] =\n unmergedDictionariesRecord[dictionaryKey] ?? [];\n\n const multilingualDictionary: Dictionary[] = dictionaries.filter(\n (dictionary) => !dictionary.locale\n );\n\n // Test all by merging all dictionaries to ensure no per-locale dictionary is missing\n for (const dictionary of multilingualDictionary) {\n const missingLocales = getMissingLocalesContentFromDictionary(\n dictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n id: dictionary.id,\n filePath: dictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n\n const perLocaleDictionary: Dictionary[] = dictionaries.filter(\n (dictionary) => dictionary.locale\n );\n\n // If there are no unmerged dictionaries for this key, fall back to the\n // merged dictionary directly (covers the case where the dict was compiled\n // as merged-only and unmerged_dictionaries.cjs is empty for this key).\n if (dictionaries.length === 0) {\n const mergedDictionary = mergedDictionaries[dictionaryKey];\n\n if (mergedDictionary) {\n const missingLocales = getMissingLocalesContentFromDictionary(\n mergedDictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n id: mergedDictionary.id,\n filePath: mergedDictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n\n continue;\n }\n\n if (perLocaleDictionary.length === 0) {\n continue;\n }\n\n const mergedDictionary = mergedDictionaries[dictionaryKey];\n\n const missingLocales = getMissingLocalesContentFromDictionary(\n mergedDictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n locales: missingLocales,\n });\n }\n }\n\n const missingLocalesSet = new Set(\n missingTranslations.flatMap(\n (missingTranslation) => missingTranslation.locales\n )\n );\n const missingLocales = Array.from(missingLocalesSet);\n\n const missingRequiredLocales = missingLocales.filter((locale) =>\n (requiredLocales ?? locales).includes(locale)\n );\n\n return { missingTranslations, missingLocales, missingRequiredLocales };\n};\n\nexport const listMissingTranslations = (\n configurationOptions?: GetConfigurationOptions\n) => {\n const configuration = getConfiguration(configurationOptions);\n logConfigDetails(configurationOptions);\n\n return listMissingTranslationsWithConfig(configuration);\n};\n"],"mappings":";;;;;;;;AAYA,MAAa,qCACX,kBACG;CACH,MAAM,gGAAqD,aAAa;CACxE,MAAM,uEAAqC,aAAa;CAExD,MAAM,sBAKA,CAAC;CAEP,MAAM,EAAE,SAAS,oBAAoB,cAAc;CAInD,MAAM,mCAAmB,IAAI,IAAI,CAC/B,GAAG,OAAO,KAAK,0BAA0B,GACzC,GAAG,OAAO,KAAK,kBAAkB,CACnC,CAAC;CAED,KAAK,MAAM,iBAAiB,kBAAkB;EAC5C,MAAM,eACJ,2BAA2B,kBAAkB,CAAC;EAEhD,MAAM,yBAAuC,aAAa,QACvD,eAAe,CAAC,WAAW,MAC9B;EAGA,KAAK,MAAM,cAAc,wBAAwB;GAC/C,MAAM,oFACJ,YACA,OACF;GAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;IACvB,KAAK;IACL,IAAI,WAAW;IACf,UAAU,WAAW;IACrB,SAAS;GACX,CAAC;EAEL;EAEA,MAAM,sBAAoC,aAAa,QACpD,eAAe,WAAW,MAC7B;EAKA,IAAI,aAAa,WAAW,GAAG;GAC7B,MAAM,mBAAmB,mBAAmB;GAE5C,IAAI,kBAAkB;IACpB,MAAM,oFACJ,kBACA,OACF;IAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;KACvB,KAAK;KACL,IAAI,iBAAiB;KACrB,UAAU,iBAAiB;KAC3B,SAAS;IACX,CAAC;GAEL;GAEA;EACF;EAEA,IAAI,oBAAoB,WAAW,GACjC;EAGF,MAAM,mBAAmB,mBAAmB;EAE5C,MAAM,oFACJ,kBACA,OACF;EAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;GACvB,KAAK;GACL,SAAS;EACX,CAAC;CAEL;CAEA,MAAM,oBAAoB,IAAI,IAC5B,oBAAoB,SACjB,uBAAuB,mBAAmB,OAC7C,CACF;CACA,MAAM,iBAAiB,MAAM,KAAK,iBAAiB;CAMnD,OAAO;EAAE;EAAqB;EAAgB,wBAJf,eAAe,QAAQ,YACnD,mBAAmB,QAAO,CAAE,SAAS,MAAM,CAGqB;CAAE;AACvE;AAEA,MAAa,2BACX,yBACG;CACH,MAAM,4DAAiC,oBAAoB;CAC3D,2CAAiB,oBAAoB;CAErC,OAAO,kCAAkC,aAAa;AACxD"}
|
package/dist/cjs/test/test.cjs
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_test_listMissingTranslations = require('./listMissingTranslations.cjs');
|
|
4
|
-
let _intlayer_chokidar_build = require("@intlayer/chokidar/build");
|
|
5
|
-
let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
|
|
6
4
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
7
5
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
8
6
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
9
7
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
8
|
+
let _intlayer_engine_build = require("@intlayer/engine/build");
|
|
9
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
10
10
|
|
|
11
11
|
//#region src/test/test.ts
|
|
12
12
|
const testMissingTranslations = async (options) => {
|
|
13
13
|
const config = (0, _intlayer_config_node.getConfiguration)(options?.configOptions);
|
|
14
14
|
const { locales, requiredLocales } = config.internationalization;
|
|
15
15
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)(config);
|
|
16
|
-
if (options?.build === true) await (0,
|
|
17
|
-
else if (typeof options?.build === "undefined") await (0,
|
|
16
|
+
if (options?.build === true) await (0, _intlayer_engine_build.prepareIntlayer)(config, { forceRun: true });
|
|
17
|
+
else if (typeof options?.build === "undefined") await (0, _intlayer_engine_build.prepareIntlayer)(config);
|
|
18
18
|
const result = require_test_listMissingTranslations.listMissingTranslations(options?.configOptions);
|
|
19
19
|
const maxKeyColSize = result.missingTranslations.map((t) => ` - ${t.key}`).reduce((max, t) => Math.max(max, t.length), 0);
|
|
20
|
-
const maxLocalesColSize = result.missingTranslations.map((t) => (0,
|
|
20
|
+
const maxLocalesColSize = result.missingTranslations.map((t) => (0, _intlayer_engine_utils.formatLocale)(t.locales, false)).reduce((max, t) => Math.max(max, t.length), 0);
|
|
21
21
|
const formattedMissingTranslations = result.missingTranslations.map((translation) => [
|
|
22
22
|
(0, _intlayer_config_logger.colon)(` - ${(0, _intlayer_config_logger.colorizeKey)(translation.key)}`, {
|
|
23
23
|
colSize: maxKeyColSize,
|
|
24
24
|
maxSize: 40
|
|
25
25
|
}),
|
|
26
26
|
" - ",
|
|
27
|
-
(0, _intlayer_config_logger.colon)((0,
|
|
27
|
+
(0, _intlayer_config_logger.colon)((0, _intlayer_engine_utils.formatLocale)(translation.locales, _intlayer_config_colors.RED), {
|
|
28
28
|
colSize: maxLocalesColSize,
|
|
29
29
|
maxSize: 40
|
|
30
30
|
}),
|
|
31
|
-
translation.filePath ? ` - ${(0,
|
|
31
|
+
translation.filePath ? ` - ${(0, _intlayer_engine_utils.formatPath)(translation.filePath)}` : "",
|
|
32
32
|
translation.id ? " - remote" : ""
|
|
33
33
|
].join(""));
|
|
34
34
|
appLogger(`Missing translations:`, { level: "info" });
|
|
35
35
|
formattedMissingTranslations.forEach((t) => {
|
|
36
36
|
appLogger(t, { level: "info" });
|
|
37
37
|
});
|
|
38
|
-
appLogger(`Locales: ${(0,
|
|
39
|
-
appLogger(`Required locales: ${(0,
|
|
40
|
-
appLogger(`Missing locales: ${result.missingLocales.length === 0 ? (0, _intlayer_config_logger.colorize)("-", _intlayer_config_colors.GREEN) : (0,
|
|
41
|
-
appLogger(`Missing required locales: ${result.missingRequiredLocales.length === 0 ? (0, _intlayer_config_logger.colorize)("-", _intlayer_config_colors.GREEN) : (0,
|
|
38
|
+
appLogger(`Locales: ${(0, _intlayer_engine_utils.formatLocale)(locales)}`);
|
|
39
|
+
appLogger(`Required locales: ${(0, _intlayer_engine_utils.formatLocale)(requiredLocales ?? locales)}`);
|
|
40
|
+
appLogger(`Missing locales: ${result.missingLocales.length === 0 ? (0, _intlayer_config_logger.colorize)("-", _intlayer_config_colors.GREEN) : (0, _intlayer_engine_utils.formatLocale)(result.missingLocales, _intlayer_config_colors.RED)}`);
|
|
41
|
+
appLogger(`Missing required locales: ${result.missingRequiredLocales.length === 0 ? (0, _intlayer_config_logger.colorize)("-", _intlayer_config_colors.GREEN) : (0, _intlayer_engine_utils.formatLocale)(result.missingRequiredLocales, _intlayer_config_colors.RED)}`);
|
|
42
42
|
appLogger(`Total missing locales: ${(0, _intlayer_config_logger.colorizeNumber)(result.missingLocales.length, {
|
|
43
43
|
one: _intlayer_config_colors.RED,
|
|
44
44
|
other: _intlayer_config_colors.RED,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.cjs","names":["listMissingTranslations","ANSIColors"],"sources":["../../../src/test/test.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"test.cjs","names":["listMissingTranslations","ANSIColors"],"sources":["../../../src/test/test.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { formatLocale, formatPath } from '@intlayer/engine/utils';\nimport { listMissingTranslations } from './listMissingTranslations';\n\ntype ListMissingTranslationsOptions = {\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\nexport const testMissingTranslations = async (\n options?: ListMissingTranslationsOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n const { locales, requiredLocales } = config.internationalization;\n\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n const result = listMissingTranslations(options?.configOptions);\n\n const maxKeyColSize = result.missingTranslations\n .map((t) => ` - ${t.key}`)\n .reduce((max, t) => Math.max(max, t.length), 0);\n const maxLocalesColSize = result.missingTranslations\n .map((t) => formatLocale(t.locales, false))\n .reduce((max, t) => Math.max(max, t.length), 0);\n\n const formattedMissingTranslations = result.missingTranslations.map(\n (translation) =>\n [\n colon(` - ${colorizeKey(translation.key)}`, {\n colSize: maxKeyColSize,\n maxSize: 40,\n }),\n ' - ',\n colon(formatLocale(translation.locales, ANSIColors.RED), {\n colSize: maxLocalesColSize,\n maxSize: 40,\n }),\n\n translation.filePath ? ` - ${formatPath(translation.filePath)}` : '',\n translation.id ? ' - remote' : '',\n ].join('')\n );\n\n appLogger(`Missing translations:`, {\n level: 'info',\n });\n\n formattedMissingTranslations.forEach((t) => {\n appLogger(t, {\n level: 'info',\n });\n });\n\n appLogger(`Locales: ${formatLocale(locales)}`);\n appLogger(`Required locales: ${formatLocale(requiredLocales ?? locales)}`);\n appLogger(\n `Missing locales: ${result.missingLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingLocales, ANSIColors.RED)}`\n );\n\n appLogger(\n `Missing required locales: ${result.missingRequiredLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingRequiredLocales, ANSIColors.RED)}`\n );\n appLogger(\n `Total missing locales: ${colorizeNumber(result.missingLocales.length, {\n one: ANSIColors.RED,\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n })}`\n );\n appLogger(\n `Total missing required locales: ${colorizeNumber(\n result.missingRequiredLocales.length,\n {\n one: ANSIColors.RED,\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n }\n )}`\n );\n\n if (result.missingRequiredLocales.length > 0) {\n process.exit(1);\n }\n};\n"],"mappings":";;;;;;;;;;;AAqBA,MAAa,0BAA0B,OACrC,YACG;CACH,MAAM,qDAA0B,SAAS,aAAa;CACtD,MAAM,EAAE,SAAS,oBAAoB,OAAO;CAE5C,MAAM,sDAAyB,MAAM;CAErC,IAAI,SAAS,UAAU,MACrB,kDAAsB,QAAQ,EAAE,UAAU,KAAK,CAAC;MAC3C,IAAI,OAAO,SAAS,UAAU,aACnC,kDAAsB,MAAM;CAG9B,MAAM,SAASA,6DAAwB,SAAS,aAAa;CAE7D,MAAM,gBAAgB,OAAO,oBAC1B,KAAK,MAAM,MAAM,EAAE,KAAK,CAAC,CACzB,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;CAChD,MAAM,oBAAoB,OAAO,oBAC9B,KAAK,+CAAmB,EAAE,SAAS,KAAK,CAAC,CAAC,CAC1C,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;CAEhD,MAAM,+BAA+B,OAAO,oBAAoB,KAC7D,gBACC;qCACQ,+CAAkB,YAAY,GAAG,KAAK;GAC1C,SAAS;GACT,SAAS;EACX,CAAC;EACD;8EACmB,YAAY,SAASC,wBAAW,GAAG,GAAG;GACvD,SAAS;GACT,SAAS;EACX,CAAC;EAED,YAAY,WAAW,6CAAiB,YAAY,QAAQ,MAAM;EAClE,YAAY,KAAK,cAAc;CACjC,CAAC,CAAC,KAAK,EAAE,CACb;CAEA,UAAU,yBAAyB,EACjC,OAAO,OACT,CAAC;CAED,6BAA6B,SAAS,MAAM;EAC1C,UAAU,GAAG,EACX,OAAO,OACT,CAAC;CACH,CAAC;CAED,UAAU,qDAAyB,OAAO,GAAG;CAC7C,UAAU,8DAAkC,mBAAmB,OAAO,GAAG;CACzE,UACE,oBAAoB,OAAO,eAAe,WAAW,0CAAa,KAAKA,wBAAW,KAAK,6CAAiB,OAAO,gBAAgBA,wBAAW,GAAG,GAC/I;CAEA,UACE,6BAA6B,OAAO,uBAAuB,WAAW,0CAAa,KAAKA,wBAAW,KAAK,6CAAiB,OAAO,wBAAwBA,wBAAW,GAAG,GACxK;CACA,UACE,sEAAyC,OAAO,eAAe,QAAQ;EACrE,KAAKA,wBAAW;EAChB,OAAOA,wBAAW;EAClB,MAAMA,wBAAW;CACnB,CAAC,GACH;CACA,UACE,+EACE,OAAO,uBAAuB,QAC9B;EACE,KAAKA,wBAAW;EAChB,OAAOA,wBAAW;EAClB,MAAMA,wBAAW;CACnB,CACF,GACF;CAEA,IAAI,OAAO,uBAAuB,SAAS,GACzC,QAAQ,KAAK,CAAC;AAElB"}
|