@wp-blocks/make-pot 0.0.1

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.
Files changed (68) hide show
  1. package/ .prettierignore +3 -0
  2. package/.editorconfig +15 -0
  3. package/.eslintrc.json +12 -0
  4. package/.github/workflows/node.js.yml +33 -0
  5. package/jest.config.json +14 -0
  6. package/lib/cliArgs.d.ts +4 -0
  7. package/lib/cliArgs.js +177 -0
  8. package/lib/cliArgs.js.map +1 -0
  9. package/lib/consolidate.d.ts +2 -0
  10. package/lib/consolidate.js +27 -0
  11. package/lib/consolidate.js.map +1 -0
  12. package/lib/const.d.ts +26 -0
  13. package/lib/const.js +56 -0
  14. package/lib/const.js.map +1 -0
  15. package/lib/extractors-json.d.ts +9 -0
  16. package/lib/extractors-json.js +53 -0
  17. package/lib/extractors-json.js.map +1 -0
  18. package/lib/extractors-maps.d.ts +109 -0
  19. package/lib/extractors-maps.js +139 -0
  20. package/lib/extractors-maps.js.map +1 -0
  21. package/lib/extractors-php.d.ts +1 -0
  22. package/lib/extractors-php.js +24 -0
  23. package/lib/extractors-php.js.map +1 -0
  24. package/lib/extractors-text.d.ts +1 -0
  25. package/lib/extractors-text.js +21 -0
  26. package/lib/extractors-text.js.map +1 -0
  27. package/lib/extractors.d.ts +17 -0
  28. package/lib/extractors.js +128 -0
  29. package/lib/extractors.js.map +1 -0
  30. package/lib/fs.d.ts +2 -0
  31. package/lib/fs.js +51 -0
  32. package/lib/fs.js.map +1 -0
  33. package/lib/glob.d.ts +13 -0
  34. package/lib/glob.js +60 -0
  35. package/lib/glob.js.map +1 -0
  36. package/lib/index.d.ts +2 -0
  37. package/lib/index.js +25 -0
  38. package/lib/index.js.map +1 -0
  39. package/lib/makePot.d.ts +2 -0
  40. package/lib/makePot.js +56 -0
  41. package/lib/makePot.js.map +1 -0
  42. package/lib/parser.d.ts +6 -0
  43. package/lib/parser.js +93 -0
  44. package/lib/parser.js.map +1 -0
  45. package/lib/tree.d.ts +2 -0
  46. package/lib/tree.js +77 -0
  47. package/lib/tree.js.map +1 -0
  48. package/lib/types.d.ts +46 -0
  49. package/lib/types.js +3 -0
  50. package/lib/types.js.map +1 -0
  51. package/lib/utils.d.ts +8 -0
  52. package/lib/utils.js +74 -0
  53. package/lib/utils.js.map +1 -0
  54. package/package.json +50 -0
  55. package/tests/consolidate.test.ts +77 -0
  56. package/tests/extract-2.test.ts +97 -0
  57. package/tests/extract.test.ts +380 -0
  58. package/tests/getFiles.test.ts +114 -0
  59. package/tests/getStrings.test.ts +149 -0
  60. package/tests/index.html +78 -0
  61. package/tests/ingnoreFunction.test.ts +177 -0
  62. package/tests/jsonParse.test.ts +60 -0
  63. package/tests/makePot.ts +46 -0
  64. package/tests/treeJs.test.ts +15 -0
  65. package/tests/treePhp.test.ts +30 -0
  66. package/tests/treeTs.test.ts +15 -0
  67. package/tests/utils.test.ts +28 -0
  68. package/tsconfig.json +35 -0
package/lib/parser.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runExtract = exports.getStrings = void 0;
7
+ const cli_progress_1 = __importDefault(require("cli-progress"));
8
+ const extractors_1 = require("./extractors");
9
+ const const_1 = require("./const");
10
+ const glob_1 = require("./glob");
11
+ const consolidate_1 = require("./consolidate");
12
+ function initProgress(args, filesCount) {
13
+ if (args.options?.silent)
14
+ return null;
15
+ const progressBar = new cli_progress_1.default.SingleBar({
16
+ clearOnComplete: true,
17
+ etaBuffer: 1000,
18
+ hideCursor: true,
19
+ format: ' {bar} {percentage}% | ETA: {eta}s | {filename} | {value}/{total}',
20
+ }, cli_progress_1.default.Presets.shades_classic);
21
+ progressBar.start(filesCount, 0);
22
+ return progressBar;
23
+ }
24
+ async function getStrings(args, files) {
25
+ const tasks = [];
26
+ let progressBar = null;
27
+ progressBar = initProgress(args, Array.from(files.iterateSync()).length);
28
+ for (const file of files) {
29
+ const ext = file.split('.').pop() || undefined;
30
+ if (!ext || !const_1.allowedFiles.includes(ext)) {
31
+ if (progressBar) {
32
+ progressBar.increment(1, {
33
+ filename: `Skipping ${ext} (not a valid file extension)`,
34
+ });
35
+ }
36
+ continue;
37
+ }
38
+ const task = (0, extractors_1.parseFile)(file, args.paths.cwd);
39
+ if (progressBar) {
40
+ progressBar.increment(1, {
41
+ filename: file,
42
+ });
43
+ }
44
+ if (task !== null) {
45
+ tasks.push(task);
46
+ }
47
+ }
48
+ const results = await Promise.all(tasks).finally(() => {
49
+ if (progressBar)
50
+ progressBar.stop();
51
+ });
52
+ const mergedResult = (0, consolidate_1.consolidate)(results.filter((r) => r !== null));
53
+ if (!args.options?.silent) {
54
+ console.log('📝 Found', Object.values(mergedResult).length, 'group of strings in', results.length, 'files.\n', 'In total ' +
55
+ Object.values(mergedResult)
56
+ .map((v) => Object.keys(v).length)
57
+ .reduce((acc, val) => acc + val, 0) +
58
+ ' strings were found');
59
+ }
60
+ return mergedResult;
61
+ }
62
+ exports.getStrings = getStrings;
63
+ async function runExtract(args) {
64
+ const pattern = {
65
+ include: args.patterns.include || [],
66
+ exclude: args.patterns.exclude || [],
67
+ mergePaths: args.patterns.mergePaths,
68
+ subtractPaths: args.patterns.subtractPaths,
69
+ subtractAndMerge: args.patterns.subtractAndMerge,
70
+ };
71
+ if (args.options?.skip.php !== undefined ||
72
+ args.options?.skip.blade !== undefined) {
73
+ if (args.options?.skip.blade !== undefined) {
74
+ pattern.include.push('**/*.php');
75
+ }
76
+ else {
77
+ pattern.include.push('**/*.php', '!**/blade.php');
78
+ }
79
+ }
80
+ if (args.options?.skip.js !== undefined) {
81
+ pattern.include.push('**/*.{js,jsx,ts,tsx,mjs,cjs}');
82
+ }
83
+ if (args.options?.skip.blockJson !== undefined) {
84
+ pattern.include.push('block.json');
85
+ }
86
+ if (args.options?.skip.themeJson !== undefined) {
87
+ pattern.include.push('theme.json');
88
+ }
89
+ const files = await (0, glob_1.getFiles)(args, pattern);
90
+ return await getStrings(args, files);
91
+ }
92
+ exports.runExtract = runExtract;
93
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/lib/tree.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { type TranslationStrings } from './types';
2
+ export declare function doTree(sourceCode: string, filepath: string): TranslationStrings;
package/lib/tree.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.doTree = void 0;
7
+ const tree_sitter_1 = __importDefault(require("tree-sitter"));
8
+ const const_1 = require("./const");
9
+ const utils_1 = require("./utils");
10
+ const glob_1 = require("./glob");
11
+ function collectComments(node, typeToMatch) {
12
+ let currentNode = node;
13
+ let depth = 0;
14
+ while (currentNode && depth < 10) {
15
+ if (currentNode?.previousSibling?.type === 'comment') {
16
+ return (0, utils_1.stripTranslationMarkup)(currentNode?.previousSibling.text);
17
+ }
18
+ depth++;
19
+ currentNode = currentNode.parent;
20
+ }
21
+ }
22
+ function doTree(sourceCode, filepath) {
23
+ const parser = new tree_sitter_1.default();
24
+ parser.setLanguage((0, glob_1.getParser)(filepath));
25
+ const tree = parser.parse(sourceCode);
26
+ const gettextTranslations = {};
27
+ const typeToMatch = filepath.split('.').pop()?.toLowerCase() !== 'php'
28
+ ? 'call_expression'
29
+ : 'function_call_expression';
30
+ function traverse(node) {
31
+ if (node?.children.length)
32
+ for (const child of node.children) {
33
+ traverse(child);
34
+ }
35
+ if (node?.type === typeToMatch) {
36
+ const functionName = node.firstChild?.text ?? null;
37
+ if (functionName === null ||
38
+ !Object.keys(const_1.i18nFunctions).includes(functionName)) {
39
+ return;
40
+ }
41
+ const argsNode = node.lastChild;
42
+ if (argsNode === null ||
43
+ argsNode.childCount === 0 ||
44
+ argsNode.type !== 'arguments') {
45
+ return;
46
+ }
47
+ const rawI18nStrnig = node.text;
48
+ const [fn, raw] = node.children;
49
+ const translation = [];
50
+ raw.children.slice(1, -1).forEach((child) => {
51
+ if (/^["|']/.exec(child.text[0]))
52
+ translation.push(child.text.slice(1, -1));
53
+ });
54
+ const gettext = {
55
+ msgid: translation[0],
56
+ msgid_plural: translation[1],
57
+ msgstr: [],
58
+ comments: {
59
+ previous: '',
60
+ reference: `${filepath}:${node.startPosition.row + 1}`,
61
+ comment: '',
62
+ translator: collectComments(node, typeToMatch),
63
+ extracted: '',
64
+ flag: '',
65
+ },
66
+ };
67
+ gettextTranslations[gettext.msgctxt ?? ''] = {
68
+ ...(gettextTranslations[gettext.msgctxt ?? ''] || {}),
69
+ [gettext.msgid]: gettext,
70
+ };
71
+ }
72
+ }
73
+ traverse(tree.rootNode);
74
+ return gettextTranslations;
75
+ }
76
+ exports.doTree = doTree;
77
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { pkgJsonHeaders, pluginHeaders, themeHeaders } from './extractors-maps';
2
+ import { GetTextTranslation } from 'gettext-parser';
3
+ export type ThemeHeadersType = keyof typeof themeHeaders;
4
+ export type PluginHeadersType = keyof typeof pluginHeaders;
5
+ export type PkgHeadersType = keyof typeof pkgJsonHeaders;
6
+ export type PotHeaders = (typeof pkgJsonHeaders)[PkgHeadersType] | (typeof pluginHeaders)[PluginHeadersType] | (typeof themeHeaders)[ThemeHeadersType] | 'fileComment' | 'packageName';
7
+ export type DomainType = 'plugin' | 'theme' | 'block' | 'theme-block' | 'generic';
8
+ export interface Patterns {
9
+ mergePaths?: string[];
10
+ subtractPaths?: string[];
11
+ subtractAndMerge?: boolean;
12
+ include: string[];
13
+ exclude: string[];
14
+ }
15
+ export interface Args {
16
+ slug: string;
17
+ domain: DomainType;
18
+ paths: {
19
+ cwd: string;
20
+ out: string;
21
+ root?: string;
22
+ };
23
+ options?: {
24
+ ignoreDomain?: boolean;
25
+ silent?: boolean;
26
+ json?: boolean;
27
+ location?: boolean;
28
+ packageName?: string;
29
+ skip: {
30
+ js?: boolean;
31
+ php?: boolean;
32
+ blade?: boolean;
33
+ blockJson?: boolean;
34
+ themeJson?: boolean;
35
+ audit?: boolean;
36
+ };
37
+ };
38
+ headers?: Record<PotHeaders, string>;
39
+ patterns: Patterns;
40
+ }
41
+ export interface TranslationStrings {
42
+ [msgctxt: string]: {
43
+ [msgId: string]: GetTextTranslation;
44
+ };
45
+ }
46
+ export type JsonData = Record<string, any>;
package/lib/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/lib/utils.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { type Args } from './types';
2
+ export declare function generateHeaderComments(args: Args): string;
3
+ export declare function getCommentBlock(input: string): string;
4
+ export declare function removeCommentMarkup(input: string): string;
5
+ export declare function stripTranslationMarkup(comment: string): string;
6
+ export declare function stringstring(string: string | string[] | undefined): string[] | null;
7
+ export declare function detectPatternType(pattern: string): 'file' | 'directory' | 'glob';
8
+ export declare function includeFunction(includePath: string[]): string[];
package/lib/utils.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.includeFunction = exports.detectPatternType = exports.stringstring = exports.stripTranslationMarkup = exports.removeCommentMarkup = exports.getCommentBlock = exports.generateHeaderComments = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ function generateHeaderComments(args) {
9
+ const { author, email, license } = {
10
+ author: args.headers?.author ?? 'AUTHOR',
11
+ email: args.headers?.email ?? 'EMAIL',
12
+ license: args.headers?.license ?? 'gpl-2.0 or later',
13
+ };
14
+ return `# Copyright (C) ${new Date().getFullYear()} ${author} (${email})
15
+ # This file is distributed under the ${license}.`;
16
+ }
17
+ exports.generateHeaderComments = generateHeaderComments;
18
+ function getCommentBlock(input) {
19
+ const commentBlock = input.match(/\/\*\*?[\s\S]*?\*\//);
20
+ return commentBlock !== null ? commentBlock[0] : input;
21
+ }
22
+ exports.getCommentBlock = getCommentBlock;
23
+ function removeCommentMarkup(input) {
24
+ return input.replace(/\/\*[\s\S]*?\*\/|\/\/.*/gm, '');
25
+ }
26
+ exports.removeCommentMarkup = removeCommentMarkup;
27
+ function stripTranslationMarkup(comment) {
28
+ const commentPattern = /\/\*\*?\s*translators:\s*([\s\S]*?)\s*\*\/|\/\/\s*translators:\s*(.*)$/i;
29
+ const matches = comment.match(commentPattern);
30
+ return matches ? matches[1] : comment;
31
+ }
32
+ exports.stripTranslationMarkup = stripTranslationMarkup;
33
+ function stringstring(string) {
34
+ if (typeof string === 'string') {
35
+ if (string.includes(',')) {
36
+ return string.split(',');
37
+ }
38
+ return [string];
39
+ }
40
+ return null;
41
+ }
42
+ exports.stringstring = stringstring;
43
+ function detectPatternType(pattern) {
44
+ const containsFileExtension = pattern.includes('.');
45
+ const containsDirectorySeparator = pattern.includes(path_1.default.sep) || pattern.endsWith(path_1.default.sep);
46
+ if (pattern.includes('*')) {
47
+ return 'glob';
48
+ }
49
+ else if (!containsFileExtension && !containsDirectorySeparator) {
50
+ return 'directory';
51
+ }
52
+ else if (containsFileExtension && !containsDirectorySeparator) {
53
+ return 'file';
54
+ }
55
+ else {
56
+ return 'glob';
57
+ }
58
+ }
59
+ exports.detectPatternType = detectPatternType;
60
+ function includeFunction(includePath) {
61
+ return includePath.map((path) => {
62
+ const type = detectPatternType(path);
63
+ switch (type) {
64
+ case 'directory':
65
+ return path + '/**';
66
+ case 'file':
67
+ return '**/' + path;
68
+ default:
69
+ return path;
70
+ }
71
+ });
72
+ }
73
+ exports.includeFunction = includeFunction;
74
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AACA,gDAAuB;AAiBvB,SAAgB,sBAAsB,CAAC,IAAU;IAChD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG;QAClC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,QAAQ;QACxC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO;QACrC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,kBAAkB;KACpD,CAAA;IAED,OAAO,mBAAmB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,KAAK,KAAK;uCAChC,OAAO,GAAG,CAAA;AACjD,CAAC;AATD,wDASC;AAQD,SAAgB,eAAe,CAAC,KAAa;IAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAA;IACvD,OAAO,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AACvD,CAAC;AAHD,0CAGC;AAQD,SAAgB,mBAAmB,CAAC,KAAa;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAA;AACtD,CAAC;AAFD,kDAEC;AAQD,SAAgB,sBAAsB,CAAC,OAAe;IACrD,MAAM,cAAc,GACnB,yEAAyE,CAAA;IAC1E,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAC7C,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;AACtC,CAAC;AALD,wDAKC;AAQD,SAAgB,YAAY,CAC3B,MAAqC;IAErC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,CAAA;IAChB,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAVD,oCAUC;AAOD,SAAgB,iBAAiB,CAChC,OAAe;IAEf,MAAM,qBAAqB,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IACnD,MAAM,0BAA0B,GAC/B,OAAO,CAAC,QAAQ,CAAC,cAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAI,CAAC,GAAG,CAAC,CAAA;IAEzD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAA;IACd,CAAC;SAAM,IAAI,CAAC,qBAAqB,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAClE,OAAO,WAAW,CAAA;IACnB,CAAC;SAAM,IAAI,qBAAqB,IAAI,CAAC,0BAA0B,EAAE,CAAC;QACjE,OAAO,MAAM,CAAA;IACd,CAAC;SAAM,CAAC;QACP,OAAO,MAAM,CAAA;IACd,CAAC;AACF,CAAC;AAhBD,8CAgBC;AAQD,SAAgB,eAAe,CAAC,WAAqB;IACpD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACpC,QAAQ,IAAI,EAAE,CAAC;YACd,KAAK,WAAW;gBACf,OAAO,IAAI,GAAG,KAAK,CAAA;YACpB,KAAK,MAAM;gBACV,OAAO,KAAK,GAAG,IAAI,CAAA;YACpB;gBACC,OAAO,IAAI,CAAA;QACb,CAAC;IACF,CAAC,CAAC,CAAA;AACH,CAAC;AAZD,0CAYC"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@wp-blocks/make-pot",
3
+ "version": "0.0.1",
4
+ "description": "A Node.js script for generating a POT file from source code",
5
+ "author": "Erik Golinelli <https://github.com/erikyo>",
6
+ "scripts": {
7
+ "build": "tsc --build",
8
+ "watch": "tsc --watch",
9
+ "clean": "tsc --build --clean",
10
+ "lint": "eslint ./src ./tests --fix",
11
+ "test": "jest --detectOpenHandles",
12
+ "update-snapshops": "jest -u",
13
+ "run": "node ./lib/index.js"
14
+ },
15
+ "bin": {
16
+ "make-pot": "lib/index.js **"
17
+ },
18
+ "dependencies": {
19
+ "cli-progress": "^3.12.0",
20
+ "gettext-parser": "^7.0.1",
21
+ "glob": "^10.3.10",
22
+ "tree-sitter": "^0.20.6",
23
+ "tree-sitter-javascript": "^0.20.1",
24
+ "tree-sitter-php": "^0.20.0",
25
+ "tree-sitter-typescript": "^0.20.3",
26
+ "yargs": "^17.7.2"
27
+ },
28
+ "devDependencies": {
29
+ "@jest/globals": "^29.7.0",
30
+ "@types/cli-progress": "^3.11.5",
31
+ "@types/gettext-parser": "^4.0.4",
32
+ "@types/jest": "^29.5.11",
33
+ "@types/node": "^20.10.4",
34
+ "@types/yargs": "^17.0.32",
35
+ "@typescript-eslint/eslint-plugin": "^6.18.1",
36
+ "@typescript-eslint/parser": "^6.14.0",
37
+ "eslint": "^8.56.0",
38
+ "eslint-config-standard": "^17.1.0",
39
+ "eslint-config-standard-with-typescript": "^43.0.0",
40
+ "eslint-plugin-import": "^2.29.1",
41
+ "eslint-plugin-n": "^16.6.1",
42
+ "eslint-plugin-promise": "^6.1.1",
43
+ "husky": "^8.0.3",
44
+ "jest": "^29.7.0",
45
+ "lint-staged": "^15.2.0",
46
+ "prettier": "3.2.2",
47
+ "ts-jest": "^29.1.1",
48
+ "typescript": "^5.3.3"
49
+ }
50
+ }
@@ -0,0 +1,77 @@
1
+ import { describe, expect } from '@jest/globals'
2
+ import { consolidate } from '../src/consolidate'
3
+ import { GetTextComment } from 'gettext-parser'
4
+
5
+ describe('consolidate', () => {
6
+ it('should consolidate strings with translator comments', () => {
7
+ const translationStrings = {
8
+ '': {
9
+ '': {
10
+ msgid: '',
11
+ msgstr: [
12
+ 'Content-Type: text/plain; charset=iso-8859-1\n...',
13
+ ],
14
+ },
15
+ },
16
+ '': {
17
+ a: {
18
+ msgid: '',
19
+ msgstr: ['a'],
20
+ },
21
+ },
22
+ 'another context': {
23
+ '%s example': {
24
+ msgctxt: 'another context',
25
+ msgid: '%s example',
26
+ msgid_plural: '%s examples',
27
+ msgstr: ['% näide', '%s näidet'],
28
+ comments: {
29
+ translator: 'This is a regular comment',
30
+ reference: '/path/to/file:123',
31
+ } as GetTextComment,
32
+ },
33
+ },
34
+ }
35
+ const translationStrings2 = {
36
+ '': {
37
+ '': {
38
+ msgid: '',
39
+ msgstr: [
40
+ 'Content-Type: text/plain; charset=iso-8859-1\n...',
41
+ ],
42
+ },
43
+ },
44
+ }
45
+ // eslint-disable-next-line
46
+ const expected = {
47
+ '': {
48
+ '': {
49
+ msgid: '',
50
+ msgstr: [
51
+ 'Content-Type: text/plain; charset=iso-8859-1\n...',
52
+ ],
53
+ },
54
+ a: {
55
+ msgid: 'a',
56
+ msgstr: ['a'],
57
+ },
58
+ },
59
+ 'another context': {
60
+ '%s example': {
61
+ comments: {
62
+ reference: '/path/to/file:123',
63
+ translator: 'This is a regular comment',
64
+ },
65
+ msgctxt: 'another context',
66
+ msgid: '%s example',
67
+ msgid_plural: '%s examples',
68
+ msgstr: ['% näide', '%s näidet'],
69
+ },
70
+ },
71
+ }
72
+
73
+ const result = consolidate([translationStrings, translationStrings2])
74
+
75
+ expect(result).toMatchObject(expected)
76
+ })
77
+ })
@@ -0,0 +1,97 @@
1
+ import { describe, expect } from '@jest/globals'
2
+ import { doTree } from '../src/tree'
3
+
4
+ describe('getStrings-extra', () => {
5
+ /** see wp cli tests */
6
+ it('should extract translations and comments from code content', () => {
7
+ const content = `<?php
8
+
9
+ // translators: Foo Bar Comment
10
+ __( 'Foo Bar', 'foo-plugin' );
11
+
12
+ // TrANslAtORs: Bar Baz Comment
13
+ __( 'Bar Baz', 'foo-plugin' );
14
+
15
+ // translators: Software name
16
+ const string = __( 'WordPress', 'foo-plugin' );
17
+
18
+ // translators: So much space
19
+
20
+ __( 'Spacey text', 'foo-plugin' );
21
+
22
+ /* translators: Long comment
23
+ spanning multiple
24
+ lines */
25
+ const string = __( 'Short text', 'foo-plugin' );
26
+
27
+ ReactDOM.render(
28
+ <h1>{__( 'Hello JSX', 'foo-plugin' )}</h1>,
29
+ document.getElementById('root')
30
+ );
31
+
32
+ wp.i18n.__( 'wp.i18n.__', 'foo-plugin' );
33
+ wp.i18n._n( 'wp.i18n._n_single', 'wp.i18n._n_plural', number, 'foo-plugin' );
34
+
35
+ const translate = wp.i18n;
36
+ translate.__( 'translate.__', 'foo-plugin' );
37
+
38
+ Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__["__"])( 'webpack.__', 'foo-plugin' );
39
+ Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__[/* __ */ "a"])( 'webpack.mangle.__', 'foo-plugin' );
40
+
41
+ Object(u.__)( 'minified.__', 'foo-plugin' );
42
+ Object(j._x)( 'minified._x', 'minified._x_context', 'foo-plugin' );
43
+
44
+ /* translators: babel */
45
+ (0, __)( 'babel.__', 'foo-plugin' );
46
+ (0, _i18n.__)( 'babel-i18n.__', 'foo-plugin' );
47
+ (0, _i18n._x)( 'babel-i18n._x', 'babel-i18n._x_context', 'foo-plugin' );
48
+
49
+ eval( "__( 'Hello Eval World', 'foo-plugin' );" );
50
+
51
+ __( \`This is a \${bug}\`, 'foo-plugin' );
52
+
53
+ /**
54
+ * Plugin Name: Plugin name
55
+ */
56
+
57
+ /* translators: Translators 1! */
58
+ _e( 'hello world', 'foo-plugin' );
59
+
60
+ /* Translators: Translators 2! */
61
+ $foo = __( 'foo', 'foo-plugin' );
62
+
63
+ /* translators: localized date and time format, see https://secure.php.net/date */
64
+ __( 'F j, Y g:i a', 'foo-plugin' );
65
+
66
+ // translators: let your ears fly!
67
+ __( 'on', 'foo-plugin' );
68
+
69
+ /*
70
+ * Translators: If there are characters in your language that are not supported
71
+ * by Lato, translate this to 'off'. Do not translate into your own language.
72
+ */
73
+ __( 'off', 'foo-plugin' );
74
+
75
+ /* translators: this should get extracted. */ $foo = __( 'baba', 'foo-plugin' );
76
+
77
+ /* translators: boo */ /* translators: this should get extracted too. */ /* some other comment */ $bar = g( __( 'bubu', 'foo-plugin' ) );
78
+
79
+ {TAB}/*
80
+ {TAB} * translators: this comment block is indented with a tab and should get extracted too.
81
+ {TAB} */
82
+ {TAB}__( 'yolo', 'foo-plugin' );
83
+
84
+ /* translators: This is a comment */
85
+ __( 'Plugin name', 'foo-plugin' );
86
+
87
+ /* Translators: This is another comment! */
88
+ __( 'https://example.com', 'foo-plugin' );
89
+ `
90
+
91
+ const filename = 'filename.php'
92
+
93
+ const result = doTree(content, filename)
94
+
95
+ expect(result).toMatchSnapshot()
96
+ })
97
+ })