From d9a999751b0ed1d9da399d4f32e1c7a6d7916088 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:13:49 +0100 Subject: [PATCH 1/9] Fix: correct `help` alias to properly map `-h` flag --- src/cli/getArgs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/getArgs.ts b/src/cli/getArgs.ts index 74b2901..15d1519 100644 --- a/src/cli/getArgs.ts +++ b/src/cli/getArgs.ts @@ -12,8 +12,8 @@ import { parseCliArgs } from "./parseCli.js"; export function getArgs(userArgs = {}): Args | MakeJsonArgs { const args = yargs .default(hideBin(process.argv)) - .help("h") - .alias("help", "help") + .help("help") + .alias("h", "help") .usage("Usage: $0 [destination] [options]") .positional("sourceDirectory", { describe: "Source directory", From c0f49445780543bc7c6a29f02a869763b8133d93 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:14:11 +0100 Subject: [PATCH 2/9] Enhance: pass `timeStart` as an argument to improve time tracking reliability in `potCommand` --- src/potCommand.ts | 4 +--- src/types.ts | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/potCommand.ts b/src/potCommand.ts index 20234fa..41c657e 100644 --- a/src/potCommand.ts +++ b/src/potCommand.ts @@ -6,13 +6,11 @@ import { printModuleInfo, printTimeElapsed } from "./utils/common.js"; export default function potCommand(args: Args) { if (Object.keys(args).length > 0) { printModuleInfo(); - /* capture the start time */ - const timeStart = new Date(); /** make the pot file */ makePot(args) .then(() => { /* output the end time */ - printTimeElapsed("Make-Pot", timeStart); + printTimeElapsed("Make-Pot", args.timeStart); }) .catch((error) => { console.error(`🫤 Make-pot - ${error}`); diff --git a/src/types.ts b/src/types.ts index e3fc3a1..d094f89 100644 --- a/src/types.ts +++ b/src/types.ts @@ -118,6 +118,7 @@ export interface Args { }; headers?: { [key in PotHeaders]: string }; patterns: Patterns; + timeStart?: Date; } /** From 52bc26ddec009ec08f206ab0b94f26e744d0e2f5 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:14:40 +0100 Subject: [PATCH 3/9] Handle optional `timeStart` in `printTimeElapsed` and improve console formatting --- src/utils/common.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utils/common.ts b/src/utils/common.ts index ef52ed6..1797882 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -148,7 +148,7 @@ export function getPkgJsonData( export function printModuleInfo() { const { version, name } = getPkgJsonData(modulePath, "name", "version"); /* print the version */ - console.log(`${name} version: ${version}`); + console.log(`\n${name} version: ${version}`); } /** @@ -159,11 +159,14 @@ export function printModuleInfo() { */ export function printTimeElapsed( scriptName: "Make-Pot" | "Make-Json", - timeStart: Date, + timeStart?: Date, timeEnd: Date = new Date(), ) { + if (!timeStart) { + return; + } console.log( - `\nšŸš€ ${scriptName}: Task completed! ${scriptName.split("-")[1]} file created in ${timeEnd.getTime() - timeStart.getTime() + `\nšŸš€ ${scriptName}: Task completed! ${scriptName.split("-")[1]} file created in ${timeEnd.getTime() - timeStart.getTime() }ms`, ); } From b3bc7191b65faf321ee052f4c3592ba336a856cc Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:15:33 +0100 Subject: [PATCH 4/9] Add `timeStart` initialization --- src/parser/exec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser/exec.ts b/src/parser/exec.ts index 54a0bd4..937ba64 100644 --- a/src/parser/exec.ts +++ b/src/parser/exec.ts @@ -27,6 +27,9 @@ export async function exec(args: Args): Promise { /** The pot file header contains the data about the plugin or theme */ const potHeader = await generateHeader(args); + /** Capture the start time */ + args.timeStart = new Date(); + /** We need to find the main file data so that the definitions are extracted from the plugin or theme files */ let translationsUnion = translationsHeaders(args); From 241f49d7fe51f1585820fbe0477acf207d899dd5 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:15:55 +0100 Subject: [PATCH 5/9] Refactor: improve PHP comment parsing, header logging, and block creation logic --- src/extractors/headers.ts | 18 ++++++++++-------- src/extractors/php.ts | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/extractors/headers.ts b/src/extractors/headers.ts index b0ad037..5a2f805 100644 --- a/src/extractors/headers.ts +++ b/src/extractors/headers.ts @@ -45,7 +45,7 @@ function validateRequiredFields( if (missingFields.length > 0) { if (!silent) { - console.error("\n! Missing required information for POT file header:\n"); + console.error("\nāš ļø Missing required information for POT file header:\n"); for (const field of missingFields) { console.error( @@ -343,11 +343,13 @@ export function translationsHeaders(args: Args): SetOfBlocks { // the main file is the plugin main php file or the css file const fakePath = domain === "plugin" ? `${args.slug}.php` : "style.css"; - return new SetOfBlocks([ - buildBlock(`Name of the ${domain}`, name, [fakePath]), - buildBlock(`Url of the ${domain}`, url, [fakePath]), - buildBlock(`Description of the ${domain}`, description, [fakePath]), - buildBlock(`Author of the ${domain}`, author, [fakePath]), - buildBlock(`Author URI of the ${domain}`, authorUri, [fakePath]), - ]); + const blocks = []; + + if (name) blocks.push(buildBlock(`Name of the ${domain}`, name, [fakePath])); + if (url) blocks.push(buildBlock(`Url of the ${domain}`, url, [fakePath])); + if (description) blocks.push(buildBlock(`Description of the ${domain}`, description, [fakePath])); + if (author) blocks.push(buildBlock(`Author of the ${domain}`, author, [fakePath])); + if (authorUri) blocks.push(buildBlock(`Author URI of the ${domain}`, authorUri, [fakePath])); + + return new SetOfBlocks(blocks); } diff --git a/src/extractors/php.ts b/src/extractors/php.ts index ff78a8a..be1bfee 100644 --- a/src/extractors/php.ts +++ b/src/extractors/php.ts @@ -33,7 +33,7 @@ export function extractPhpPluginData(args: Args): Record { * @return {Record} - A record containing the plugin information. */ export function parsePHPFile(phpContent: string): Record { - const match = phpContent.match(/\/\*\*([\s\S]*?)\*\//); + const match = phpContent.match(/\/\*\*?([\s\S]*?)\*\//); if (match?.[1] && match) { const commentBlock = match[1]; @@ -42,7 +42,7 @@ export function parsePHPFile(phpContent: string): Record { const pluginInfo: Record = {}; for (const line of lines) { - const keyValueMatch = line.match(/^\s*\*\s*([^:]+):\s*(.*)/); + const keyValueMatch = line.match(/^\s*(?:\*\s*)?([^:]+):\s*(.*)/); if (!keyValueMatch) { continue; From 310567ba6034ba9da22cc29e92b9ad0a3397ba73 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:17:28 +0100 Subject: [PATCH 6/9] Refactor: remove redundant logging and unused variables in `taskRunner`, simplify audit completion message --- src/extractors/auditStrings.ts | 2 +- src/parser/taskRunner.ts | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/extractors/auditStrings.ts b/src/extractors/auditStrings.ts index 1c32176..f2bd079 100644 --- a/src/extractors/auditStrings.ts +++ b/src/extractors/auditStrings.ts @@ -9,7 +9,7 @@ export function audit(args: Args, translationsUnion: SetOfBlocks) { auditor.auditStrings(translationsUnion.blocks); /** Get and print the results of the audit process */ - console.log("\nAudit Complete!"); + console.log("Audit Complete!"); if (auditor.getResults().length === 0) { console.log("No issues found! šŸŽ‰"); // if there are no errors, we can remove the audit.log file diff --git a/src/parser/taskRunner.ts b/src/parser/taskRunner.ts index cfe46e1..a6d584a 100644 --- a/src/parser/taskRunner.ts +++ b/src/parser/taskRunner.ts @@ -18,7 +18,6 @@ export async function taskRunner( args: Args, progressBar: SingleBar, ) { - const messages: string[] = []; // Create a new array of promises that update the bar when they finish. const tasksWithProgress = tasks.map((task) => task.then((result) => { @@ -48,16 +47,6 @@ export async function taskRunner( * Add the strings to the destination set */ destination.addArray(result.blocks); - const strings = result.blocks.map((b) => b.msgid); - - /* Log the results */ - if (args.options?.silent !== true) { - messages.push( - `āœ… ${result.path} - ${strings.length} strings found [${strings.join(", ")}]`, - ); - } - } else if (args.options?.silent !== true) { - messages.push(`āŒ ${result.path} - has no strings`); } } }) @@ -67,12 +56,5 @@ export async function taskRunner( progressBar.stop(); - console.log("\nšŸŽ‰ Done!"); - console.log( - `šŸ“ Found ${Object.values(destination.blocks).length} translation strings in ${path.resolve(args.paths.cwd)}.`, - ); - - console.log(messages.join(os.EOL)); - return destination; } From e4cc653751130bad43fd2f96f1145bc0ba8fb596 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:31:09 +0100 Subject: [PATCH 7/9] FIX: json output in `generateOutput` --- src/utils/output.ts | 57 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/utils/output.ts b/src/utils/output.ts index 826bacc..c921367 100644 --- a/src/utils/output.ts +++ b/src/utils/output.ts @@ -1,6 +1,5 @@ import type { SetOfBlocks } from "gettext-merger"; -import Tannin from "tannin"; -import type { Args } from "../types.js"; +import type { Args, JedData, MakeJson } from "../types.js"; import type { GetTextTranslation } from 'gettext-parser' /** @@ -16,17 +15,51 @@ export function outputJson( potHeader: Record | null, translationsUnion: SetOfBlocks, ): string { - const jedData = { - [args.slug]: { - "": potHeader ?? {}, - ...(translationsUnion.toJson() as{ - [key: string]: { - [key: string]: GetTextTranslation; - }; - }), + const domain = args.slug; + const gettextTranslations = translationsUnion.toJson() as { + [key: string]: { + [key: string]: GetTextTranslation; + }; + }; + + const jedData: JedData = { + [domain]: { + "": { + domain, + lang: potHeader?.Language || "en", + plural_forms: + potHeader?.["Plural-Forms"] || "nplurals=2; plural=(n != 1);", + ...potHeader, + }, }, }; - const i18n = new Tannin(jedData); - return i18n.toString(); + // Process all translations + for (const msgctxt of Object.keys(gettextTranslations)) { + const contextTranslations = gettextTranslations[msgctxt]; + + for (const msgid of Object.keys(contextTranslations)) { + const translation = contextTranslations[msgid]; + + // Skip empty msgid (header) as we've already handled it + if (msgid === "") continue; + + // Construct the key using context if available + const key = + msgctxt && msgctxt !== "" ? `${msgctxt}\u0004${msgid}` : msgid; + + // Add the translation to the Jed data structure + jedData[domain][key] = translation.msgstr; + } + } + + const makeJson: MakeJson = { + domain, + "translation-revision-date": new Date().toISOString(), + generator: "makePot", + source: "", + locale_data: jedData, + }; + + return JSON.stringify(makeJson, null, 2); } From f499633a6274164883ebb71c91f12c760b4b6b64 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:33:44 +0100 Subject: [PATCH 8/9] Bump to v1.6.6 and update README formatting with minor fixes. --- README.md | 4 ++-- package-lock.json | 45 ++------------------------------------------- package.json | 3 +-- 3 files changed, 5 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 5cf9b92..3d7740f 100644 --- a/README.md +++ b/README.md @@ -70,15 +70,15 @@ npx @wp-blocks/make-pot src languages --charset='utf-8' --include="src/**/*.{ts, - `--package-name `: Specifies the package name. - `--location`: Includes location information in the `.pot` file. - `--ignore-domain`: Ignores text domain in the processing. +- `--translation-domains`: Restrict to specific translation domains. - `--mergePaths `: Merges with existing POT file(s). - `--subtractPaths `: Subtracts strings from existing POT file(s). - `--subtractAndMerge`: Subtracts and merges strings from existing POT file(s). - `--include `: Includes specific files for processing. - `--exclude `: Excludes specific files from processing. -- `--silent`: Suppresses output to stdout. +- `--silent`: Suppresses verbose output to stdout. - `--json`: Outputs the JSON gettext data. - `--charset`: Defines the encoding charset of the pot file, you can choose "iso-8859-1" and "uft-8" (defaults to iso-8859-1) -- `--translation-domains`: Restrict to specific translation domains. - `--output`: Outputs the gettext data. ### Example usage diff --git a/package-lock.json b/package-lock.json index 4b0cf8c..3dcde9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wp-blocks/make-pot", - "version": "1.6.5", + "version": "1.6.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wp-blocks/make-pot", - "version": "1.6.5", + "version": "1.6.6", "hasInstallScript": true, "license": "GPL-3.0-or-later", "dependencies": { @@ -16,7 +16,6 @@ "gettext-merger": "^1.2.1", "gettext-parser": "^4.2.0", "glob": "^11.1.0", - "tannin": "^1.2.0", "tree-sitter": "^0.21.1", "tree-sitter-javascript": "^0.23.1", "tree-sitter-php": "^0.23.12", @@ -2150,37 +2149,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@tannin/compile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", - "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", - "license": "MIT", - "dependencies": { - "@tannin/evaluate": "^1.2.0", - "@tannin/postfix": "^1.1.0" - } - }, - "node_modules/@tannin/evaluate": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", - "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==", - "license": "MIT" - }, - "node_modules/@tannin/plural-forms": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", - "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", - "license": "MIT", - "dependencies": { - "@tannin/compile": "^1.1.0" - } - }, - "node_modules/@tannin/postfix": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", - "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==", - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -3124,15 +3092,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tannin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", - "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", - "license": "MIT", - "dependencies": { - "@tannin/plural-forms": "^1.1.0" - } - }, "node_modules/tree-sitter": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", diff --git a/package.json b/package.json index c1370bc..28aab7c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wp-blocks/make-pot", - "version": "1.6.5", + "version": "1.6.6", "license": "GPL-3.0-or-later", "homepage": "https://wp-blocks.github.io/make-pot/", "description": "A Node.js script for generating a POT file from source code", @@ -68,7 +68,6 @@ "gettext-merger": "^1.2.1", "gettext-parser": "^4.2.0", "glob": "^11.1.0", - "tannin": "^1.2.0", "tree-sitter": "^0.21.1", "tree-sitter-javascript": "^0.23.1", "tree-sitter-php": "^0.23.12", From 4c7e7c8dfc9679588309c37adb4865d6d73a8b22 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Sat, 21 Feb 2026 06:33:53 +0100 Subject: [PATCH 9/9] Add unit tests for PHP comment parsing in `parsePHPFile` --- tests/parse-php.test.js | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/parse-php.test.js diff --git a/tests/parse-php.test.js b/tests/parse-php.test.js new file mode 100644 index 0000000..026ddc4 --- /dev/null +++ b/tests/parse-php.test.js @@ -0,0 +1,47 @@ +const { describe, it } = require("node:test"); +const assert = require("node:assert"); +const { parsePHPFile } = require("../lib/extractors/php.js"); + +describe("parsePHPFile", () => { + it("correctly extracts headers from standard docblock (/** ... */)", () => { + const phpContent = ` { + const phpContent = `