Достаем все строки из javascript-файла
package.json:
{
"name": "extract-strings",
"version": "1.0.0",
"description": "",
"license": "ISC",
"author": "",
"type": "commonjs",
"main": "extract-strings.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@babel/parser": "^7.28.5",
"@babel/traverse": "^7.28.5"
}
}
extract-strings.js:
#!/usr/bin/env node
/**
* extract-strings.js
* ------------------
* Скрипт читает один (или несколько) .js/.jsx/.ts/.tsx файлов,
* разбирает их в AST и выводит все найденные литералы‑строки.
*
* Поддерживает:
* • обычные строки: "text", 'text'
* • шаблоны без интерполяций: `pure template`
* • шаблоны с интерполяциями: `${expr}` – выводит только «сырые» части,
* а также сохраняет выражения, если нужно.
*
* Запуск:
* node extract-strings.js path/to/file.js […другие файлы]
*/
const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
// ------------------------------------------------------------------
// 1. Чтение и парсинг файла
// ------------------------------------------------------------------
function parseFile(filePath) {
const code = fs.readFileSync(filePath, 'utf8');
// Опции парсера: поддерживаем почти любой современный синтаксис.
const ast = parser.parse(code, {
sourceType: 'unambiguous', // auto-detect module vs script
plugins: [
'jsx',
'typescript',
'classProperties',
'objectRestSpread',
'optionalChaining',
'nullishCoalescingOperator',
'decorators-legacy',
'dynamicImport',
'numericSeparator',
// добавить, если нужен, например, "exportDefaultFrom"
],
});
return ast;
}
// ------------------------------------------------------------------
// 2. Обход AST и сбор строк
// ------------------------------------------------------------------
function collectStrings(ast) {
const strings = [];
traverse(ast, {
// Обычные строковые литералы: "abc", 'abc'
StringLiteral({ node }) {
strings.push(node.value);
},
// Шаблонные литералы: `abc`, `a${b}c`
TemplateLiteral({ node }) {
// Мы хотим собрать «сырые» части (quasis)
// и, при желании, отдельные выражения.
const rawParts = node.quasis.map(q => q.value.cooked);
const exprCount = node.expressions.length;
if (exprCount === 0) {
// Чистый шаблон без интерполяций – просто строка
strings.push(rawParts.join(''));
} else {
// Содержит выражения. Можно решить, как их представлять.
// Ниже – вариант, где мы сохраняем шаблон с placeholder'ами.
const placeholder = '${...}';
const combined = rawParts.reduce((acc, cur, i) => {
acc += cur;
if (i < exprCount) acc += placeholder;
return acc;
}, '');
strings.push(combined);
}
},
// Если нужно собирать строки из импортов вроде:
// import msg from "./locales/ru.json";
// То можно добавить обработку ImportDeclaration, но обычно это не требуется.
});
return strings;
}
// ------------------------------------------------------------------
// 3. Основная часть: обработка аргументов командной строки
// ------------------------------------------------------------------
function main(output_file_name) {
const args = process.argv.slice(2);
if (args.length === 0) {
console.error('Usage: node extract-strings.js <file1.js> [file2.js …]');
process.exit(1);
}
const allStrings = [];
for (const arg of args) {
const absolute = path.resolve(arg);
if (!fs.existsSync(absolute)) {
console.warn(`File not found: ${absolute}`);
continue;
}
try {
const ast = parseFile(absolute);
const strings = collectStrings(ast);
allStrings.push(...strings);
} catch (e) {
console.error(`Error parsing ${absolute}:`, e.message);
}
}
// Убираем дубликаты (по желанию)
const uniq = Array.from(new Set(allStrings));
// Выводим каждый элемент в отдельной строке (удобно для дальнейших пайпов)
// uniq.forEach(str => console.log(str));
const map = uniq.reduce((acc, str, idx) => {
// Генерируем простой ключ: msg_001, msg_002 …
const key = `msg_${String(idx + 1).padStart(3, '0')}`;
acc[key] = str;
return acc;
}, {});
// Записываем JSON
fs.writeFileSync(output_file_name, JSON.stringify(map, null, 2), 'utf8');
}
// Usage: node extract-strings.js path/to/file.js […другие файлы]
// Usage: node extract-strings.js src/**/*.{js,jsx,ts,tsx}
main('output.json');
Last updated