@wp-blocks/make-pot 1.6.3 → 1.6.4

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/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.3.14/schema.json",
3
3
  "formatter": {
4
4
  "enabled": false
5
5
  },
@@ -1 +1 @@
1
- "use strict";var w=Object.create;var m=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var j=(t,n)=>{for(var e in n)m(t,e,{get:n[e],enumerable:!0})},g=(t,n,e,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of S(n))!T.call(t,s)&&s!==e&&m(t,s,{get:()=>n[s],enumerable:!(o=_(n,s))||o.enumerable});return t};var u=(t,n,e)=>(e=t!=null?w(J(t)):{},g(n||!t||!t.__esModule?m(e,"default",{value:t,enumerable:!0}):e,t)),v=t=>g(m({},"__esModule",{value:!0}),t);var $={};j($,{parseCliArgs:()=>C,parseJsonArgs:()=>N});module.exports=v($);var a=u(require("node:fs")),i=u(require("node:path")),f=u(require("node:process")),y=require("../const.js"),k=require("../fs/fs"),c=require("../utils/common.js");function O(t="/",n="default"){const e=t;try{return(0,a.accessSync)(i.join(e,`${n}.php`),a.default.constants.R_OK),"plugin"}catch{console.log(`the current working directory ${e} does not contain a ${n}.php file`)}try{return(0,a.accessSync)(i.join(e,"style.css"),a.default.constants.R_OK),"theme"}catch{console.log(`the current working directory ${e} does not contain a style.css file`)}return"generic"}function C(t){const n=t._[0]?.toString(),e=t._[1]?.toString()||"languages",o=n??".",s=e.startsWith("/")?e.slice(1):e,r=f.cwd(),p=t.slug&&typeof t.slug=="string"?t.slug:i.basename(i.resolve(r,o)),l=i.relative(r,o),b=i.relative(r,s);if(!t?.domain)t.domain=O(i.resolve(l),p);else switch(t.domain){case"plugin":case"theme":case"block":case"theme-block":break;default:console.error(`Invalid domain: ${t.domain}. Valid domains are: plugin, theme, block, theme-block, generic`),t.domain="generic"}const d={};for(const D of t.headers){const[P,A]=D.split(":");d[P.trim()]=A.trim()}const h={slug:p,debug:!!t.debug,domain:t.domain,paths:{cwd:l,out:b},options:{ignoreDomain:!!t?.ignoreDomain,packageName:String(t.packageName),silent:t.silent===!0,json:!!t.json,location:!!t?.location,headers:d,theme:!!t?.theme,output:!!t?.output,fileComment:t.fileComment?String(t.fileComment):void 0,charset:(0,k.getEncodingCharset)(t?.charset),skip:{js:!!t.skipJs,php:!!t.skipPhp,blade:!!t.skipBlade,blockJson:!!t.skipBlockJson,themeJson:!!t.skipThemeJson,audit:!!t.skipAudit},translationDomains:t.translationDomains?Array.isArray(t.translationDomains)?t.translationDomains.map(String):[String(t.translationDomains)]:void 0},patterns:{mergePaths:(0,c.stringstring)(t.mergePaths),subtractPaths:(0,c.stringstring)(t.subtractPaths),subtractAndMerge:!!t.subtractAndMerge,include:(0,c.stringstring)(t.include),exclude:[...(0,c.stringstring)(t.exclude),...y.DEFAULT_EXCLUDED_PATH]}};return h.paths.root=t.root?String(t.root):void 0,h}function N(t){const n=t._[0]||"build",e=t._[1]||"languages",o=f.cwd(),s=i.basename(i.resolve(o));let r;return t.scriptName&&(r=t.scriptName.split(",").map(p=>p.trim()),r.length===1&&(r=r[0])),{timeStart:Date.now(),slug:s,source:n,destination:e,scriptName:r,allowedFormats:t.allowedFormats,purge:!!t.purge,stripUnused:!!t.stripUnused,prettyPrint:!!t.prettyPrint,debug:!!t.debug,paths:{cwd:o,out:i.join(o,e)}}}0&&(module.exports={parseCliArgs,parseJsonArgs});
1
+ "use strict";var w=Object.create;var u=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var j=(t,n)=>{for(var e in n)u(t,e,{get:n[e],enumerable:!0})},k=(t,n,e,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of _(n))!T.call(t,s)&&s!==e&&u(t,s,{get:()=>n[s],enumerable:!(o=S(n,s))||o.enumerable});return t};var d=(t,n,e)=>(e=t!=null?w(J(t)):{},k(n||!t||!t.__esModule?u(e,"default",{value:t,enumerable:!0}):e,t)),v=t=>k(u({},"__esModule",{value:!0}),t);var $={};j($,{parseCliArgs:()=>C,parseJsonArgs:()=>N});module.exports=v($);var a=d(require("node:fs")),i=d(require("node:path")),A=d(require("node:process")),b=require("../const.js"),D=require("../fs/fs"),p=require("../utils/common.js");function O(t="/",n="default"){const e=t;try{return(0,a.accessSync)(i.join(e,`${n}.php`),a.default.constants.R_OK),"plugin"}catch{console.log(`the current working directory ${e} does not contain a ${n}.php file`)}try{return(0,a.accessSync)(i.join(e,"style.css"),a.default.constants.R_OK),"theme"}catch{console.log(`the current working directory ${e} does not contain a style.css file`)}return"generic"}function C(t){const n=t._[0]?.toString(),e=t._[1]?.toString()||"languages",o=n??".",s=e.startsWith("/")?e.slice(1):e,r=A.cwd(),c=t.slug&&typeof t.slug=="string"?t.slug:i.basename(i.resolve(r,o)),m=i.relative(r,o),P=i.relative(r,s);if(!t?.domain)t.domain=O(i.resolve(m),c);else switch(t.domain){case"plugin":case"theme":case"block":case"theme-block":break;default:console.error(`Invalid domain: ${t.domain}. Valid domains are: plugin, theme, block, theme-block, generic`),t.domain="generic"}const l={};if(t.headers&&Array.isArray(t.headers)){for(const g of t.headers)if(typeof g=="string"){const[f,y]=g.split(":");f&&y&&(l[f.trim()]=y.trim())}}const h={slug:c,debug:!!t.debug,domain:t.domain,paths:{cwd:m,out:P},options:{ignoreDomain:!!t?.ignoreDomain,packageName:String(t.packageName),silent:t.silent===!0,json:!!t.json,location:!!t?.location,headers:l,theme:!!t?.theme,output:!!t?.output,fileComment:t.fileComment?String(t.fileComment):void 0,charset:(0,D.getEncodingCharset)(t?.charset),skip:{js:!!t.skipJs,php:!!t.skipPhp,blade:!!t.skipBlade,blockJson:!!t.skipBlockJson,themeJson:!!t.skipThemeJson,audit:!!t.skipAudit},translationDomains:t.translationDomains?Array.isArray(t.translationDomains)?t.translationDomains.map(String):[String(t.translationDomains)]:void 0},patterns:{mergePaths:(0,p.stringstring)(t.mergePaths),subtractPaths:(0,p.stringstring)(t.subtractPaths),subtractAndMerge:!!t.subtractAndMerge,include:(0,p.stringstring)(t.include),exclude:[...(0,p.stringstring)(t.exclude),...b.DEFAULT_EXCLUDED_PATH]}};return h.paths.root=t.root?String(t.root):void 0,h}function N(t){const n=t._[0]||"build",e=t._[1]||"languages",o=A.cwd(),s=i.basename(i.resolve(o));let r;if(t.scriptName){const c=t.scriptName.toString().split(",").map(m=>m.trim());c.length===1&&(r=c[0])}return{timeStart:Date.now(),slug:s,source:n,destination:e,scriptName:r,allowedFormats:t.allowedFormats,purge:!!t.purge,stripUnused:!!t.stripUnused,prettyPrint:!!t.prettyPrint,debug:!!t.debug,paths:{cwd:o,out:i.join(o,e)}}}0&&(module.exports={parseCliArgs,parseJsonArgs});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/parseCli.ts"],
4
- "sourcesContent": ["import fs, { accessSync } from \"node:fs\";\r\nimport * as path from \"node:path\";\r\nimport * as process from \"node:process\";\r\nimport type * as yargs from \"yargs\";\r\nimport { DEFAULT_EXCLUDED_PATH } from \"../const.js\";\r\nimport { getEncodingCharset } from \"../fs/fs\";\r\nimport type { Args, DomainType, MakeJsonArgs, PotHeaders } from \"../types.js\";\r\nimport { stringstring } from \"../utils/common.js\";\r\n\r\n/**\r\n * This function checks if the current working directory is a theme or plugin\r\n * @param currentPath The current working directory\r\n * @param slug The slug of the theme or plugin\r\n */\r\nfunction isThemeOrPlugin(currentPath = \"/\", slug = \"default\"): DomainType {\r\n\tconst currentWorkingDirectory = currentPath;\r\n\r\n\t/**\r\n\t * Checks if the current working directory contains a plugin file\r\n\t */\r\n\ttry {\r\n\t\taccessSync(\r\n\t\t\tpath.join(currentWorkingDirectory, `${slug}.php`),\r\n\t\t\tfs.constants.R_OK,\r\n\t\t);\r\n\t\treturn \"plugin\";\r\n\t} catch (_err) {\r\n\t\t// do nothing\r\n\t\tconsole.log(\r\n\t\t\t`the current working directory ${currentWorkingDirectory} does not contain a ${slug}.php file`,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the current working directory contains a style.css file and is a theme\r\n\t */\r\n\ttry {\r\n\t\taccessSync(\r\n\t\t\tpath.join(currentWorkingDirectory, \"style.css\"),\r\n\t\t\tfs.constants.R_OK,\r\n\t\t);\r\n\t\treturn \"theme\";\r\n\t} catch (_err) {\r\n\t\t// do nothing\r\n\t\tconsole.log(\r\n\t\t\t`the current working directory ${currentWorkingDirectory} does not contain a style.css file`,\r\n\t\t);\r\n\t}\r\n\r\n\t// If none of the above conditions are met, return \"generic\"\r\n\treturn \"generic\";\r\n}\r\n\r\n/**\r\n * Parses the command line arguments and returns an object with the parsed values.\r\n *\r\n * @param {{_: string[]}} args - The command line arguments to be parsed.\r\n * @return {object} - An object with the parsed values from the command line arguments.\r\n */\r\nexport function parseCliArgs(\r\n\targs: yargs.PositionalOptions & yargs.Options & yargs.Arguments,\r\n): Args {\r\n\t// Get the input and output paths\r\n\tconst pos1: string | undefined = args._[0]?.toString();\r\n\tconst pos2: string = args._[1]?.toString() || \"languages\";\r\n\r\n\tconst inputPath: string | undefined = pos1 ?? \".\";\r\n\t// remove \"/\" if the output path starts with it\r\n\tconst outputPath: string = pos2.startsWith(\"/\") ? pos2.slice(1) : pos2;\r\n\r\n\t// Store the current working directory\r\n\tconst currentWorkingDirectory = process.cwd();\r\n\r\n\t// Get the slug or use the basename of the current working directory\r\n\t// the slug is the plugin or theme slug. Defaults to the source directory\u2019s basename\r\n\tconst slug =\r\n\t\targs.slug && typeof args.slug === \"string\"\r\n\t\t\t? args.slug\r\n\t\t\t: path.basename(path.resolve(currentWorkingDirectory, inputPath));\r\n\r\n\t// Get the relative paths\r\n\tconst cwd = path.relative(currentWorkingDirectory, inputPath);\r\n\tconst out = path.relative(currentWorkingDirectory, outputPath);\r\n\r\n\t/** get the domain to look for (plugin, theme, etc) */\r\n\tif (!(args?.domain as DomainType)) {\r\n\t\targs.domain = isThemeOrPlugin(path.resolve(cwd), slug);\r\n\t} else {\r\n\t\tswitch (args.domain) {\r\n\t\t\tcase \"plugin\":\r\n\t\t\tcase \"theme\":\r\n\t\t\tcase \"block\":\r\n\t\t\tcase \"theme-block\":\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t`Invalid domain: ${args.domain}. Valid domains are: plugin, theme, block, theme-block, generic`,\r\n\t\t\t\t);\r\n\t\t\t\t// fallback to generic if the domain is invalid\r\n\t\t\t\targs.domain = \"generic\";\r\n\t\t}\r\n\t}\r\n\r\n\t// Collect the headers passed via cli\r\n\tconst headers = {};\r\n\tfor (const header of args.headers) {\r\n\t\tconst [key, value] = header.split(\":\") as Record<PotHeaders, string>;\r\n\t\theaders[key.trim()] = value.trim();\r\n\t}\r\n\r\n\tconst parsedArgs: Args = {\r\n\t\tslug: slug,\r\n\t\tdebug: !!args.debug,\r\n\t\tdomain: args.domain as DomainType,\r\n\t\tpaths: { cwd: cwd, out: out },\r\n\t\toptions: {\r\n\t\t\tignoreDomain: !!args?.ignoreDomain,\r\n\t\t\tpackageName: String(args.packageName),\r\n\t\t\tsilent: args.silent === true, // default is false\r\n\t\t\tjson: !!args.json,\r\n\t\t\tlocation: !!args?.location,\r\n\t\t\theaders: headers as Record<PotHeaders, string>,\r\n\t\t\ttheme: !!args?.theme,\r\n\t\t\toutput: !!args?.output,\r\n\t\t\tfileComment: args.fileComment ? String(args.fileComment) : undefined,\r\n\t\t\tcharset: getEncodingCharset(args?.charset as string | undefined),\r\n\t\t\tskip: {\r\n\t\t\t\tjs: !!args.skipJs,\r\n\t\t\t\tphp: !!args.skipPhp,\r\n\t\t\t\tblade: !!args.skipBlade,\r\n\t\t\t\tblockJson: !!args.skipBlockJson,\r\n\t\t\t\tthemeJson: !!args.skipThemeJson,\r\n\t\t\t\taudit: !!args.skipAudit,\r\n\t\t\t},\r\n\t\t\ttranslationDomains: args.translationDomains\r\n\t\t\t\t? Array.isArray(args.translationDomains)\r\n\t\t\t\t\t? args.translationDomains.map(String)\r\n\t\t\t\t\t: [String(args.translationDomains)]\r\n\t\t\t\t: undefined,\r\n\t\t},\r\n\t\t// Patterns\r\n\t\tpatterns: {\r\n\t\t\tmergePaths: stringstring(args.mergePaths as string),\r\n\t\t\tsubtractPaths: stringstring(args.subtractPaths as string),\r\n\t\t\tsubtractAndMerge: !!args.subtractAndMerge,\r\n\t\t\tinclude: stringstring(args.include as string),\r\n\t\t\texclude: [\r\n\t\t\t\t...stringstring(args.exclude as string),\r\n\t\t\t\t...DEFAULT_EXCLUDED_PATH,\r\n\t\t\t],\r\n\t\t},\r\n\t};\r\n\r\n\tparsedArgs.paths.root = args.root ? String(args.root) : undefined;\r\n\r\n\treturn parsedArgs;\r\n}\r\n\r\n/**\r\n * Parses the command line arguments for the JSON command.\r\n * @param args - The command line arguments to be parsed.\r\n */\r\nexport function parseJsonArgs(\r\n\targs: yargs.PositionalOptions & yargs.Options & yargs.Arguments,\r\n): MakeJsonArgs {\r\n\t// Get the input and output paths\r\n\tconst inputPath: string = (args._[0] as string) || \"build\";\r\n\tconst outputPath: string = (args._[1] as string) || \"languages\";\r\n\tconst currentWorkingDirectory = process.cwd();\r\n\tconst slug = path.basename(path.resolve(currentWorkingDirectory));\r\n\r\n\tlet scriptName: string;\r\n\tif (args.scriptName) {\r\n\t\tscriptName = args.scriptName.split(\",\").map((s) => s.trim());\r\n\t\tif (scriptName.length === 1) {\r\n\t\t\tscriptName = scriptName[0];\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\ttimeStart: Date.now(),\r\n\t\tslug,\r\n\t\tsource: inputPath,\r\n\t\tdestination: outputPath,\r\n\t\tscriptName,\r\n\t\tallowedFormats: args.allowedFormats as string[],\r\n\t\tpurge: !!args.purge,\r\n\t\tstripUnused: !!args.stripUnused,\r\n\t\tprettyPrint: !!args.prettyPrint,\r\n\t\tdebug: !!args.debug,\r\n\t\tpaths: {\r\n\t\t\tcwd: currentWorkingDirectory,\r\n\t\t\tout: path.join(currentWorkingDirectory, outputPath),\r\n\t\t},\r\n\t};\r\n}\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs, { accessSync } from \"node:fs\";\r\nimport * as path from \"node:path\";\r\nimport * as process from \"node:process\";\r\nimport type * as yargs from \"yargs\";\r\nimport { DEFAULT_EXCLUDED_PATH } from \"../const.js\";\r\nimport { getEncodingCharset } from \"../fs/fs\";\r\nimport type { Args, DomainType, MakeJsonArgs, PotHeaders } from \"../types.js\";\r\nimport { stringstring } from \"../utils/common.js\";\r\n\r\n/**\r\n * This function checks if the current working directory is a theme or plugin\r\n * @param currentPath The current working directory\r\n * @param slug The slug of the theme or plugin\r\n */\r\nfunction isThemeOrPlugin(currentPath = \"/\", slug = \"default\"): DomainType {\r\n\tconst currentWorkingDirectory = currentPath;\r\n\r\n\t/**\r\n\t * Checks if the current working directory contains a plugin file\r\n\t */\r\n\ttry {\r\n\t\taccessSync(\r\n\t\t\tpath.join(currentWorkingDirectory, `${slug}.php`),\r\n\t\t\tfs.constants.R_OK,\r\n\t\t);\r\n\t\treturn \"plugin\";\r\n\t} catch (_err) {\r\n\t\t// do nothing\r\n\t\tconsole.log(\r\n\t\t\t`the current working directory ${currentWorkingDirectory} does not contain a ${slug}.php file`,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the current working directory contains a style.css file and is a theme\r\n\t */\r\n\ttry {\r\n\t\taccessSync(\r\n\t\t\tpath.join(currentWorkingDirectory, \"style.css\"),\r\n\t\t\tfs.constants.R_OK,\r\n\t\t);\r\n\t\treturn \"theme\";\r\n\t} catch (_err) {\r\n\t\t// do nothing\r\n\t\tconsole.log(\r\n\t\t\t`the current working directory ${currentWorkingDirectory} does not contain a style.css file`,\r\n\t\t);\r\n\t}\r\n\r\n\t// If none of the above conditions are met, return \"generic\"\r\n\treturn \"generic\";\r\n}\r\n\r\n/**\r\n * Parses the command line arguments and returns an object with the parsed values.\r\n *\r\n * @param {{_: string[]}} args - The command line arguments to be parsed.\r\n * @return {object} - An object with the parsed values from the command line arguments.\r\n */\r\nexport function parseCliArgs(\r\n\targs: yargs.PositionalOptions & yargs.Options & yargs.Arguments,\r\n): Args {\r\n\t// Get the input and output paths\r\n\tconst pos1: string | undefined = args._[0]?.toString();\r\n\tconst pos2: string = args._[1]?.toString() || \"languages\";\r\n\r\n\tconst inputPath: string | undefined = pos1 ?? \".\";\r\n\t// remove \"/\" if the output path starts with it\r\n\tconst outputPath: string = pos2.startsWith(\"/\") ? pos2.slice(1) : pos2;\r\n\r\n\t// Store the current working directory\r\n\tconst currentWorkingDirectory = process.cwd();\r\n\r\n\t// Get the slug or use the basename of the current working directory\r\n\t// the slug is the plugin or theme slug. Defaults to the source directory\u2019s basename\r\n\tconst slug =\r\n\t\targs.slug && typeof args.slug === \"string\"\r\n\t\t\t? args.slug\r\n\t\t\t: path.basename(path.resolve(currentWorkingDirectory, inputPath));\r\n\r\n\t// Get the relative paths\r\n\tconst cwd = path.relative(currentWorkingDirectory, inputPath);\r\n\tconst out = path.relative(currentWorkingDirectory, outputPath);\r\n\r\n\t/** get the domain to look for (plugin, theme, etc) */\r\n\tif (!(args?.domain as DomainType)) {\r\n\t\targs.domain = isThemeOrPlugin(path.resolve(cwd), slug);\r\n\t} else {\r\n\t\tswitch (args.domain) {\r\n\t\t\tcase \"plugin\":\r\n\t\t\tcase \"theme\":\r\n\t\t\tcase \"block\":\r\n\t\t\tcase \"theme-block\":\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t`Invalid domain: ${args.domain}. Valid domains are: plugin, theme, block, theme-block, generic`,\r\n\t\t\t\t);\r\n\t\t\t\t// fallback to generic if the domain is invalid\r\n\t\t\t\targs.domain = \"generic\";\r\n\t\t}\r\n\t}\r\n\r\n\t// Collect the headers passed via cli\r\n\tconst headers: Record<string, string> = {};\r\n\tif (args.headers && Array.isArray(args.headers)) {\r\n\t\tfor (const header of args.headers) {\r\n\t\t\tif (typeof header === \"string\") {\r\n\t\t\t\tconst [key, value] = header.split(\":\") as [PotHeaders, string];\r\n\t\t\t\tif (key && value) {\r\n\t\t\t\t\theaders[key.trim()] = value.trim();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst parsedArgs: Args = {\r\n\t\tslug: slug,\r\n\t\tdebug: !!args.debug,\r\n\t\tdomain: args.domain as DomainType,\r\n\t\tpaths: { cwd: cwd, out: out },\r\n\t\toptions: {\r\n\t\t\tignoreDomain: !!args?.ignoreDomain,\r\n\t\t\tpackageName: String(args.packageName),\r\n\t\t\tsilent: args.silent === true, // default is false\r\n\t\t\tjson: !!args.json,\r\n\t\t\tlocation: !!args?.location,\r\n\t\t\theaders: headers as Record<PotHeaders, string>,\r\n\t\t\ttheme: !!args?.theme,\r\n\t\t\toutput: !!args?.output,\r\n\t\t\tfileComment: args.fileComment ? String(args.fileComment) : undefined,\r\n\t\t\tcharset: getEncodingCharset(args?.charset as string | undefined),\r\n\t\t\tskip: {\r\n\t\t\t\tjs: !!args.skipJs,\r\n\t\t\t\tphp: !!args.skipPhp,\r\n\t\t\t\tblade: !!args.skipBlade,\r\n\t\t\t\tblockJson: !!args.skipBlockJson,\r\n\t\t\t\tthemeJson: !!args.skipThemeJson,\r\n\t\t\t\taudit: !!args.skipAudit,\r\n\t\t\t},\r\n\t\t\ttranslationDomains: args.translationDomains\r\n\t\t\t\t? Array.isArray(args.translationDomains)\r\n\t\t\t\t\t? args.translationDomains.map(String)\r\n\t\t\t\t\t: [String(args.translationDomains)]\r\n\t\t\t\t: undefined,\r\n\t\t},\r\n\t\t// Patterns\r\n\t\tpatterns: {\r\n\t\t\tmergePaths: stringstring(args.mergePaths as string),\r\n\t\t\tsubtractPaths: stringstring(args.subtractPaths as string),\r\n\t\t\tsubtractAndMerge: !!args.subtractAndMerge,\r\n\t\t\tinclude: stringstring(args.include as string),\r\n\t\t\texclude: [\r\n\t\t\t\t...stringstring(args.exclude as string),\r\n\t\t\t\t...DEFAULT_EXCLUDED_PATH,\r\n\t\t\t],\r\n\t\t},\r\n\t};\r\n\r\n\tparsedArgs.paths.root = args.root ? String(args.root) : undefined;\r\n\r\n\treturn parsedArgs;\r\n}\r\n\r\n/**\r\n * Parses the command line arguments for the JSON command.\r\n * @param args - The command line arguments to be parsed.\r\n */\r\nexport function parseJsonArgs(\r\n\targs: yargs.PositionalOptions & yargs.Options & yargs.Arguments,\r\n): MakeJsonArgs {\r\n\t// Get the input and output paths\r\n\tconst inputPath: string = (args._[0] as string) || \"build\";\r\n\tconst outputPath: string = (args._[1] as string) || \"languages\";\r\n\tconst currentWorkingDirectory = process.cwd();\r\n\tconst slug = path.basename(path.resolve(currentWorkingDirectory));\r\n\r\n\tlet scriptName: string | undefined;\r\n\tif (args.scriptName) {\r\n\t\tconst scripts = args.scriptName.toString().split(\",\").map((s) => s.trim());\r\n\t\tif (scripts.length === 1) {\r\n\t\t\tscriptName = scripts[0];\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\ttimeStart: Date.now(),\r\n\t\tslug,\r\n\t\tsource: inputPath,\r\n\t\tdestination: outputPath,\r\n\t\tscriptName,\r\n\t\tallowedFormats: args.allowedFormats as string[],\r\n\t\tpurge: !!args.purge,\r\n\t\tstripUnused: !!args.stripUnused,\r\n\t\tprettyPrint: !!args.prettyPrint,\r\n\t\tdebug: !!args.debug,\r\n\t\tpaths: {\r\n\t\t\tcwd: currentWorkingDirectory,\r\n\t\t\tout: path.join(currentWorkingDirectory, outputPath),\r\n\t\t},\r\n\t};\r\n}\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["fs"]
7
7
  }
@@ -1,5 +1,6 @@
1
- "use strict";var p=Object.create;var c=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var S=(t,s)=>{for(var e in s)c(t,e,{get:s[e],enumerable:!0})},g=(t,s,e,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of R(s))!P.call(t,r)&&r!==e&&c(t,r,{get:()=>s[r],enumerable:!(o=f(s,r))||o.enumerable});return t};var _=(t,s,e)=>(e=t!=null?p(E(t)):{},g(s||!t||!t.__esModule?c(e,"default",{value:t,enumerable:!0}):e,t)),D=t=>g(c({},"__esModule",{value:!0}),t);var $={};S($,{audit:()=>T,default:()=>L});module.exports=D($);var u=require("node:fs"),d=_(require("node:path"));function T(t,s){const e=new m(t.domain);if(e.auditStrings(s.blocks),console.log(`
2
- Audit Complete!`),e.getResults().length===0){console.log("No issues found! \u{1F389}");try{(0,u.unlinkSync)(d.default.join(t.paths.cwd,"audit.log"))}catch{}}else{console.log(`Found ${e.getResults().length} issues!`);const o=e.getResults().join(`
3
- `);console.log(o),(0,u.writeFileSync)(d.default.join(t.paths.cwd,"audit.log"),o)}}class m{SPRINTF_PLACEHOLDER_REGEX=/%(?:\d+\$)?[+-]?(?:[ 0]|'.)?-?\d*(?:\.\d+)?[bcdeEfFgGhHosuxX]/g;UNORDERED_SPRINTF_PLACEHOLDER_REGEX=/%(?!(\d+)\$)[+-]?(?:[ 0]|'.)?-?\d*(?:\.\d+)?[bcdeEfFgGhHosuxX]/g;projectType;results=[];constructor(s){this.projectType=s}getFileHeaders(s){return{plugin:["Plugin Name:","Plugin URI:","Description:","Author:","Author URI:","Version:","Text Domain:","Domain Path:","Network:","Requires at least:","Requires PHP:"],theme:["Theme Name:","Theme URI:","Author:","Author URI:","Description:","Version:","License:","License URI:","Text Domain:","Domain Path:","Tags:","Requires at least:","Requires PHP:"]}[s]||[]}auditStrings(s){for(const e of s){const o=e.comments?.reference||[],r=o.length>0?`(${o[0]})`:"";if(!e.msgid)continue;if((!e.comments?.extracted||e.comments.extracted.length===0)&&(e.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX)||[]).length>=1){const n=`The string "${e.msgid}" contains placeholders but has no "translators:" comment to clarify their meaning. ${r}`;this.results.push(n)}if(e.comments?.extracted&&e.comments.extracted.length>0){let n=e.comments.extracted;n=n.filter(i=>{for(const h of this.getFileHeaders(this.projectType))if(i.startsWith(h))return!1;return!0});const a=[];n=n.filter(i=>a.includes(i)?!1:(a.push(i),!0));const l=n.length;if(l>1){const i=`The string "${e.msgid}" has ${l} different translator comments. ${r}
1
+ "use strict";var p=Object.create;var c=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var _=(t,s)=>{for(var e in s)c(t,e,{get:s[e],enumerable:!0})},g=(t,s,e,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of R(s))!P.call(t,r)&&r!==e&&c(t,r,{get:()=>s[r],enumerable:!(o=f(s,r))||o.enumerable});return t};var S=(t,s,e)=>(e=t!=null?p(E(t)):{},g(s||!t||!t.__esModule?c(e,"default",{value:t,enumerable:!0}):e,t)),D=t=>g(c({},"__esModule",{value:!0}),t);var $={};_($,{audit:()=>T,default:()=>L});module.exports=D($);var u=require("node:fs"),d=S(require("node:path"));function T(t,s){const e=new m(t.domain);if(e.auditStrings(s.blocks),console.log(`
2
+ Audit Complete!`),e.getResults().length===0){console.log("No issues found! \u{1F389}");try{(0,u.unlinkSync)(d.default.join(t.paths.cwd,"audit.log"))}catch{}}else{if(console.log(`Found ${e.getResults().length} issues!`),t.options?.silent!==!0){const o=e.getResults().join(`
3
+ `);console.log(o)}(0,u.writeFileSync)(d.default.join(t.paths.cwd,"audit.log"),e.getResults().join(`
4
+ `))}}class m{SPRINTF_PLACEHOLDER_REGEX=/%(?:\d+\$)?[+-]?(?:[ 0]|'.)?-?\d*(?:\.\d+)?[bcdeEfFgGhHosuxX]/g;UNORDERED_SPRINTF_PLACEHOLDER_REGEX=/%(?!(\d+)\$)[+-]?(?:[ 0]|'.)?-?\d*(?:\.\d+)?[bcdeEfFgGhHosuxX]/g;projectType;results=[];constructor(s){this.projectType=s}getFileHeaders(s){return{plugin:["Plugin Name:","Plugin URI:","Description:","Author:","Author URI:","Version:","Text Domain:","Domain Path:","Network:","Requires at least:","Requires PHP:"],theme:["Theme Name:","Theme URI:","Author:","Author URI:","Description:","Version:","License:","License URI:","Text Domain:","Domain Path:","Tags:","Requires at least:","Requires PHP:"]}[s]||[]}auditStrings(s){for(const e of s){const o=e.comments?.reference||[],r=o.length>0?`(${o[0]})`:"";if(!e.msgid)continue;if((!e.comments?.extracted||e.comments.extracted.length===0)&&(e.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX)||[]).length>=1){const n=`The string "${e.msgid}" contains placeholders but has no "translators:" comment to clarify their meaning. ${r}`;this.results.push(n)}if(e.comments?.extracted&&e.comments.extracted.length>0){let n=e.comments.extracted;n=n.filter(i=>{for(const h of this.getFileHeaders(this.projectType))if(i.startsWith(h))return!1;return!0});const a=[];n=n.filter(i=>a.includes(i)?!1:(a.push(i),!0));const l=n.length;if(l>1){const i=`The string "${e.msgid}" has ${l} different translator comments. ${r}
4
5
  ${n.join(`
5
6
  `)}`;this.results.push(i)}}if(e.msgid.trim().replace(/^(['"])(.*)\1$/s,"$2").replace(this.SPRINTF_PLACEHOLDER_REGEX,"")===""){const n=`Found string without translatable content. ${r}`;this.results.push(n)}if((e.msgid.match(this.UNORDERED_SPRINTF_PLACEHOLDER_REGEX)||[]).length>=2){const n=`Multiple placeholders should be ordered. ${r}`;this.results.push(n)}if(e.msgid_plural){const n=e.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX)||[],a=e.msgid_plural.match(this.SPRINTF_PLACEHOLDER_REGEX)||[];if(n.length<a.length){const l=`Missing singular placeholder, needed for some languages. See https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#plurals ${r}`;this.results.push(l)}else{const l=[...n].sort(),i=[...a].sort();if(JSON.stringify(l)!==JSON.stringify(i)){const h=`Mismatched placeholders for singular and plural string. ${r}`;this.results.push(h)}}}}}getResults(){return this.results}}var L=m;0&&(module.exports={audit});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/extractors/auditStrings.ts"],
4
- "sourcesContent": ["import { unlinkSync, writeFileSync } from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport type { Block, SetOfBlocks } from \"gettext-merger\";\r\nimport type { Args } from \"../types.js\";\r\n\r\nexport function audit(args: Args, translationsUnion: SetOfBlocks) {\r\n\t/** Run the audit process */\r\n\tconst auditor = new StringAuditor(args.domain);\r\n\tauditor.auditStrings(translationsUnion.blocks);\r\n\r\n\t/** Get and print the results of the audit process */\r\n\tconsole.log(\"\\nAudit Complete!\");\r\n\tif (auditor.getResults().length === 0) {\r\n\t\tconsole.log(\"No issues found! \uD83C\uDF89\");\r\n\t\t//if there are no errors, we can remove the audit.log file\r\n\t\ttry {\r\n\t\t\tunlinkSync(path.join(args.paths.cwd, \"audit.log\"));\r\n\t\t} catch (error) {\r\n\t\t\t//ignore\r\n\t\t}\r\n\t} else {\r\n\t\tconsole.log(`Found ${auditor.getResults().length} issues!`);\r\n\t\tconst results = auditor.getResults().join(\"\\n\");\r\n\t\tconsole.log(results);\r\n\t\t/** Write the audit results to a file */\r\n\t\twriteFileSync(path.join(args.paths.cwd, \"audit.log\"), results);\r\n\t}\r\n}\r\n\r\n/**\r\n * Class to audit gettext strings\r\n *\r\n * Example usage:\r\n * const auditor = new StringAuditor('plugin');\r\n * auditor.auditStrings(translationBlocks);\r\n */\r\nclass StringAuditor {\r\n\tprivate readonly SPRINTF_PLACEHOLDER_REGEX =\r\n\t\t/%(?:\\d+\\$)?[+-]?(?:[ 0]|'.)?-?\\d*(?:\\.\\d+)?[bcdeEfFgGhHosuxX]/g;\r\n\tprivate readonly UNORDERED_SPRINTF_PLACEHOLDER_REGEX =\r\n\t\t/%(?!(\\d+)\\$)[+-]?(?:[ 0]|'.)?-?\\d*(?:\\.\\d+)?[bcdeEfFgGhHosuxX]/g;\r\n\tprivate projectType: string;\r\n\r\n\t/**\r\n\t * The results of the audit process\r\n\t */\r\n\tpublic results: string[] = [];\r\n\r\n\tconstructor(projectType: string) {\r\n\t\tthis.projectType = projectType;\r\n\t}\r\n\r\n\tprivate getFileHeaders(projectType: string): string[] {\r\n\t\t// Implement based on your requirements\r\n\t\t// This would be the equivalent of the PHP get_file_headers method\r\n\t\tconst headers: Record<string, string[]> = {\r\n\t\t\tplugin: [\r\n\t\t\t\t\"Plugin Name:\",\r\n\t\t\t\t\"Plugin URI:\",\r\n\t\t\t\t\"Description:\",\r\n\t\t\t\t\"Author:\",\r\n\t\t\t\t\"Author URI:\",\r\n\t\t\t\t\"Version:\",\r\n\t\t\t\t\"Text Domain:\",\r\n\t\t\t\t\"Domain Path:\",\r\n\t\t\t\t\"Network:\",\r\n\t\t\t\t\"Requires at least:\",\r\n\t\t\t\t\"Requires PHP:\",\r\n\t\t\t],\r\n\t\t\ttheme: [\r\n\t\t\t\t\"Theme Name:\",\r\n\t\t\t\t\"Theme URI:\",\r\n\t\t\t\t\"Author:\",\r\n\t\t\t\t\"Author URI:\",\r\n\t\t\t\t\"Description:\",\r\n\t\t\t\t\"Version:\",\r\n\t\t\t\t\"License:\",\r\n\t\t\t\t\"License URI:\",\r\n\t\t\t\t\"Text Domain:\",\r\n\t\t\t\t\"Domain Path:\",\r\n\t\t\t\t\"Tags:\",\r\n\t\t\t\t\"Requires at least:\",\r\n\t\t\t\t\"Requires PHP:\",\r\n\t\t\t],\r\n\t\t};\r\n\r\n\t\treturn headers[projectType] || [];\r\n\t}\r\n\r\n\tauditStrings(translations: Block[]): void {\r\n\t\tfor (const translation of translations) {\r\n\t\t\tconst references = translation.comments?.reference || [];\r\n\r\n\t\t\t// File headers don't have any file references\r\n\t\t\tconst location = references.length > 0 ? `(${references[0]})` : \"\";\r\n\r\n\t\t\t// Check 0: Flag strings without msgid is the header so it's not a translation and should be ignored\r\n\t\t\tif (!translation.msgid) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Check 1: Flag strings with placeholders that should have translator comments\r\n\t\t\tif (\r\n\t\t\t\t(!translation.comments?.extracted ||\r\n\t\t\t\t\ttranslation.comments.extracted.length === 0) &&\r\n\t\t\t\t(translation.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX) || [])\r\n\t\t\t\t\t.length >= 1\r\n\t\t\t) {\r\n\t\t\t\tconst message = `The string \"${translation.msgid}\" contains placeholders but has no \"translators:\" comment to clarify their meaning. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\t// Check 2: Flag strings with different translator comments\r\n\t\t\tif (\r\n\t\t\t\ttranslation.comments?.extracted &&\r\n\t\t\t\ttranslation.comments.extracted.length > 0\r\n\t\t\t) {\r\n\t\t\t\tlet comments = translation.comments.extracted;\r\n\r\n\t\t\t\t// Remove plugin header information from comments\r\n\t\t\t\tcomments = comments.filter((comment) => {\r\n\t\t\t\t\tfor (const fileHeader of this.getFileHeaders(this.projectType)) {\r\n\t\t\t\t\t\tif (comment.startsWith(fileHeader)) {\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst uniqueComments: string[] = [];\r\n\r\n\t\t\t\t// Remove duplicate comments\r\n\t\t\t\tcomments = comments.filter((comment) => {\r\n\t\t\t\t\tif (uniqueComments.includes(comment)) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tuniqueComments.push(comment);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst commentsCount = comments.length;\r\n\r\n\t\t\t\tif (commentsCount > 1) {\r\n\t\t\t\t\tconst message = `The string \"${translation.msgid}\" has ${commentsCount} different translator comments. ${location}\\n${comments.join(\"\\n\")}`;\r\n\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Extract non-placeholder content from the string\r\n\t\t\tconst nonPlaceholderContent = translation.msgid\r\n\t\t\t\t.trim()\r\n\t\t\t\t.replace(/^(['\"])(.*)\\1$/s, \"$2\")\r\n\t\t\t\t.replace(this.SPRINTF_PLACEHOLDER_REGEX, \"\");\r\n\r\n\t\t\t// Check 3: Flag empty strings without any translatable content\r\n\t\t\tif (nonPlaceholderContent === \"\") {\r\n\t\t\t\tconst message = `Found string without translatable content. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\t// Check 4: Flag strings with multiple unordered placeholders (%s %s %s vs. %1$s %2$s %3$s)\r\n\t\t\tconst unorderedMatches =\r\n\t\t\t\ttranslation.msgid.match(this.UNORDERED_SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\t\t\tconst unorderedMatchesCount = unorderedMatches.length;\r\n\r\n\t\t\tif (unorderedMatchesCount >= 2) {\r\n\t\t\t\tconst message = `Multiple placeholders should be ordered. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\tif (translation.msgid_plural) {\r\n\t\t\t\tconst singlePlaceholders =\r\n\t\t\t\t\ttranslation.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\t\t\t\tconst pluralPlaceholders =\r\n\t\t\t\t\ttranslation.msgid_plural.match(this.SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\r\n\t\t\t\t// See https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#plurals\r\n\t\t\t\tif (singlePlaceholders.length < pluralPlaceholders.length) {\r\n\t\t\t\t\t// Check 5: Flag things like _n('One comment', '%s Comments')\r\n\t\t\t\t\tconst message = `Missing singular placeholder, needed for some languages. See https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#plurals ${location}`;\r\n\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Reordering is fine, but mismatched placeholders is probably wrong\r\n\t\t\t\t\tconst sortedSinglePlaceholders = [...singlePlaceholders].sort();\r\n\t\t\t\t\tconst sortedPluralPlaceholders = [...pluralPlaceholders].sort();\r\n\r\n\t\t\t\t\t// Check 6: Flag things like _n('%s Comment (%d)', '%s Comments (%s)')\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tJSON.stringify(sortedSinglePlaceholders) !==\r\n\t\t\t\t\t\tJSON.stringify(sortedPluralPlaceholders)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tconst message = `Mismatched placeholders for singular and plural string. ${location}`;\r\n\t\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Get the results of the audit process\r\n\t * @returns An array of messages\r\n\t */\r\n\tpublic getResults(): string[] {\r\n\t\treturn this.results;\r\n\t}\r\n}\r\n\r\nexport default StringAuditor;\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { unlinkSync, writeFileSync } from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport type { Block, SetOfBlocks } from \"gettext-merger\";\r\nimport type { Args } from \"../types.js\";\r\n\r\nexport function audit(args: Args, translationsUnion: SetOfBlocks) {\r\n\t/** Run the audit process */\r\n\tconst auditor = new StringAuditor(args.domain);\r\n\tauditor.auditStrings(translationsUnion.blocks);\r\n\r\n\t/** Get and print the results of the audit process */\r\n\tconsole.log(\"\\nAudit Complete!\");\r\n\tif (auditor.getResults().length === 0) {\r\n\t\tconsole.log(\"No issues found! \uD83C\uDF89\");\r\n\t\t// if there are no errors, we can remove the audit.log file\r\n\t\ttry {\r\n\t\t\tunlinkSync(path.join(args.paths.cwd, \"audit.log\"));\r\n\t\t} catch (_error) {\r\n\t\t\t//ignore\r\n\t\t}\r\n\t} else {\r\n\t\tconsole.log(`Found ${auditor.getResults().length} issues!`);\r\n\t\t// Print the results if not in silent mode\r\n\t\tif (args.options?.silent !== true) {\r\n\t\t\tconst results = auditor.getResults().join(\"\\n\");\r\n\t\t\tconsole.log(results);\r\n\t\t}\r\n\t\t/** Write the audit results to a file */\r\n\t\twriteFileSync(path.join(args.paths.cwd, \"audit.log\"), auditor.getResults().join(\"\\n\"));\r\n\t}\r\n}\r\n\r\n/**\r\n * Class to audit gettext strings\r\n *\r\n * Example usage:\r\n * const auditor = new StringAuditor('plugin');\r\n * auditor.auditStrings(translationBlocks);\r\n */\r\nclass StringAuditor {\r\n\tprivate readonly SPRINTF_PLACEHOLDER_REGEX =\r\n\t\t/%(?:\\d+\\$)?[+-]?(?:[ 0]|'.)?-?\\d*(?:\\.\\d+)?[bcdeEfFgGhHosuxX]/g;\r\n\tprivate readonly UNORDERED_SPRINTF_PLACEHOLDER_REGEX =\r\n\t\t/%(?!(\\d+)\\$)[+-]?(?:[ 0]|'.)?-?\\d*(?:\\.\\d+)?[bcdeEfFgGhHosuxX]/g;\r\n\tprivate projectType: string;\r\n\r\n\t/**\r\n\t * The results of the audit process\r\n\t */\r\n\tpublic results: string[] = [];\r\n\r\n\tconstructor(projectType: string) {\r\n\t\tthis.projectType = projectType;\r\n\t}\r\n\r\n\tprivate getFileHeaders(projectType: string): string[] {\r\n\t\t// Implement based on your requirements\r\n\t\t// This would be the equivalent of the PHP get_file_headers method\r\n\t\tconst headers: Record<string, string[]> = {\r\n\t\t\tplugin: [\r\n\t\t\t\t\"Plugin Name:\",\r\n\t\t\t\t\"Plugin URI:\",\r\n\t\t\t\t\"Description:\",\r\n\t\t\t\t\"Author:\",\r\n\t\t\t\t\"Author URI:\",\r\n\t\t\t\t\"Version:\",\r\n\t\t\t\t\"Text Domain:\",\r\n\t\t\t\t\"Domain Path:\",\r\n\t\t\t\t\"Network:\",\r\n\t\t\t\t\"Requires at least:\",\r\n\t\t\t\t\"Requires PHP:\",\r\n\t\t\t],\r\n\t\t\ttheme: [\r\n\t\t\t\t\"Theme Name:\",\r\n\t\t\t\t\"Theme URI:\",\r\n\t\t\t\t\"Author:\",\r\n\t\t\t\t\"Author URI:\",\r\n\t\t\t\t\"Description:\",\r\n\t\t\t\t\"Version:\",\r\n\t\t\t\t\"License:\",\r\n\t\t\t\t\"License URI:\",\r\n\t\t\t\t\"Text Domain:\",\r\n\t\t\t\t\"Domain Path:\",\r\n\t\t\t\t\"Tags:\",\r\n\t\t\t\t\"Requires at least:\",\r\n\t\t\t\t\"Requires PHP:\",\r\n\t\t\t],\r\n\t\t};\r\n\r\n\t\treturn headers[projectType] || [];\r\n\t}\r\n\r\n\tauditStrings(translations: Block[]): void {\r\n\t\tfor (const translation of translations) {\r\n\t\t\tconst references = translation.comments?.reference || [];\r\n\r\n\t\t\t// File headers don't have any file references\r\n\t\t\tconst location = references.length > 0 ? `(${references[0]})` : \"\";\r\n\r\n\t\t\t// Check 0: Flag strings without msgid is the header so it's not a translation and should be ignored\r\n\t\t\tif (!translation.msgid) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Check 1: Flag strings with placeholders that should have translator comments\r\n\t\t\tif (\r\n\t\t\t\t(!translation.comments?.extracted ||\r\n\t\t\t\t\ttranslation.comments.extracted.length === 0) &&\r\n\t\t\t\t(translation.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX) || [])\r\n\t\t\t\t\t.length >= 1\r\n\t\t\t) {\r\n\t\t\t\tconst message = `The string \"${translation.msgid}\" contains placeholders but has no \"translators:\" comment to clarify their meaning. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\t// Check 2: Flag strings with different translator comments\r\n\t\t\tif (\r\n\t\t\t\ttranslation.comments?.extracted &&\r\n\t\t\t\ttranslation.comments.extracted.length > 0\r\n\t\t\t) {\r\n\t\t\t\tlet comments = translation.comments.extracted;\r\n\r\n\t\t\t\t// Remove plugin header information from comments\r\n\t\t\t\tcomments = comments.filter((comment) => {\r\n\t\t\t\t\tfor (const fileHeader of this.getFileHeaders(this.projectType)) {\r\n\t\t\t\t\t\tif (comment.startsWith(fileHeader)) {\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst uniqueComments: string[] = [];\r\n\r\n\t\t\t\t// Remove duplicate comments\r\n\t\t\t\tcomments = comments.filter((comment) => {\r\n\t\t\t\t\tif (uniqueComments.includes(comment)) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tuniqueComments.push(comment);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst commentsCount = comments.length;\r\n\r\n\t\t\t\tif (commentsCount > 1) {\r\n\t\t\t\t\tconst message = `The string \"${translation.msgid}\" has ${commentsCount} different translator comments. ${location}\\n${comments.join(\"\\n\")}`;\r\n\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Extract non-placeholder content from the string\r\n\t\t\tconst nonPlaceholderContent = translation.msgid\r\n\t\t\t\t.trim()\r\n\t\t\t\t.replace(/^(['\"])(.*)\\1$/s, \"$2\")\r\n\t\t\t\t.replace(this.SPRINTF_PLACEHOLDER_REGEX, \"\");\r\n\r\n\t\t\t// Check 3: Flag empty strings without any translatable content\r\n\t\t\tif (nonPlaceholderContent === \"\") {\r\n\t\t\t\tconst message = `Found string without translatable content. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\t// Check 4: Flag strings with multiple unordered placeholders (%s %s %s vs. %1$s %2$s %3$s)\r\n\t\t\tconst unorderedMatches =\r\n\t\t\t\ttranslation.msgid.match(this.UNORDERED_SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\t\t\tconst unorderedMatchesCount = unorderedMatches.length;\r\n\r\n\t\t\tif (unorderedMatchesCount >= 2) {\r\n\t\t\t\tconst message = `Multiple placeholders should be ordered. ${location}`;\r\n\t\t\t\tthis.results.push(message);\r\n\t\t\t}\r\n\r\n\t\t\tif (translation.msgid_plural) {\r\n\t\t\t\tconst singlePlaceholders =\r\n\t\t\t\t\ttranslation.msgid.match(this.SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\t\t\t\tconst pluralPlaceholders =\r\n\t\t\t\t\ttranslation.msgid_plural.match(this.SPRINTF_PLACEHOLDER_REGEX) || [];\r\n\r\n\t\t\t\t// See https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#plurals\r\n\t\t\t\tif (singlePlaceholders.length < pluralPlaceholders.length) {\r\n\t\t\t\t\t// Check 5: Flag things like _n('One comment', '%s Comments')\r\n\t\t\t\t\tconst message = `Missing singular placeholder, needed for some languages. See https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#plurals ${location}`;\r\n\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Reordering is fine, but mismatched placeholders is probably wrong\r\n\t\t\t\t\tconst sortedSinglePlaceholders = [...singlePlaceholders].sort();\r\n\t\t\t\t\tconst sortedPluralPlaceholders = [...pluralPlaceholders].sort();\r\n\r\n\t\t\t\t\t// Check 6: Flag things like _n('%s Comment (%d)', '%s Comments (%s)')\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tJSON.stringify(sortedSinglePlaceholders) !==\r\n\t\t\t\t\t\tJSON.stringify(sortedPluralPlaceholders)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tconst message = `Mismatched placeholders for singular and plural string. ${location}`;\r\n\t\t\t\t\t\tthis.results.push(message);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Get the results of the audit process\r\n\t * @returns An array of messages\r\n\t */\r\n\tpublic getResults(): string[] {\r\n\t\treturn this.results;\r\n\t}\r\n}\r\n\r\nexport default StringAuditor;\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["path"]
7
7
  }
@@ -1,14 +1,15 @@
1
- "use strict";var y=Object.create;var c=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var O=(e,t)=>{for(var o in t)c(e,o,{get:t[o],enumerable:!0})},d=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of H(t))!M.call(e,n)&&n!==o&&c(e,n,{get:()=>t[n],enumerable:!(r=T(t,n))||r.enumerable});return e};var $=(e,t,o)=>(o=e!=null?y(I(e)):{},d(t||!e||!e.__esModule?c(o,"default",{value:e,enumerable:!0}):o,e)),w=e=>d(c({},"__esModule",{value:!0}),e);var L={};O(L,{extractMainFileData:()=>v,generateHeader:()=>U,getAuthorFromPackage:()=>P,translationsHeaders:()=>E});module.exports=w(L);var f=$(require("node:path")),g=require("gettext-merger"),p=require("../const.js"),k=require("../fs/fs.js"),u=require("../utils/common.js"),m=require("../utils/extractors.js"),b=require("./css.js"),A=require("./php.js");function R(e,t){const r=[{key:"slug",name:"Plugin/Theme slug",placeholder:"PLUGIN NAME"},{key:"author",name:"Author name",placeholder:"AUTHOR"},{key:"version",name:"Version",placeholder:""},{key:"email",name:"Author email",placeholder:"AUTHOR EMAIL"},{key:"xDomain",name:"Text domain",placeholder:"PLUGIN TEXTDOMAIN"}].filter(n=>!e[n.key]||e[n.key]===n.placeholder||n.key==="version"&&e[n.key]==="0.0.1");if(r.length>0){console.error(`
1
+ "use strict";var D=Object.create;var u=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var O=(e,t)=>{for(var r in t)u(e,r,{get:t[r],enumerable:!0})},p=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of M(t))!I.call(e,o)&&o!==r&&u(e,o,{get:()=>t[o],enumerable:!(i=H(t,o))||i.enumerable});return e};var d=(e,t,r)=>(r=e!=null?D(T(e)):{},p(t||!e||!e.__esModule?u(r,"default",{value:e,enumerable:!0}):r,e)),$=e=>p(u({},"__esModule",{value:!0}),e);var N={};O(N,{extractMainFileData:()=>E,generateHeader:()=>x,getAuthorFromPackage:()=>w,translationsHeaders:()=>L});module.exports=$(N);var g=d(require("node:path")),m=d(require("node:process")),R=d(require("node:readline")),A=require("gettext-merger"),k=require("../const.js"),y=require("../fs/fs.js"),h=require("../utils/common.js"),c=require("../utils/extractors.js"),b=require("./css.js"),P=require("./php.js");function v(e,t,r=!1){const o=[{key:"slug",name:"Plugin/Theme slug",placeholder:"PLUGIN NAME"},{key:"author",name:"Author name",placeholder:"AUTHOR"},{key:"version",name:"Version",placeholder:""},{key:"email",name:"Author email",placeholder:"AUTHOR EMAIL"},{key:"xDomain",name:"Text domain",placeholder:"PLUGIN TEXTDOMAIN"}].filter(n=>!e[n.key]||e[n.key]===n.placeholder||n.key==="version"&&e[n.key]==="0.0.1");if(o.length>0){if(!r){console.error(`
2
2
  ! Missing required information for POT file header:
3
- `);for(const n of r)console.error(` - ${n.name} is missing or has a default value (eg. version: 0.0.1")`);return console.error(`
3
+ `);for(const n of o)console.error(` - ${n.name} is missing or has a default value (eg. version: 0.0.1")`);console.error(`
4
4
  Please provide this information adding the missing fields inside the headers object of the plugin/theme declaration or to the package.json file.`,`
5
- For more information check the documentation at https://github.com/wp-blocks/makePot`),r.some(n=>n.key==="email")&&console.error(`
5
+ For more information check the documentation at https://github.com/wp-blocks/makePot`),o.some(n=>n.key==="email")&&console.error(`
6
6
 
7
7
  Wordpress didn't require an email field in the headers object but it's required in order to generate a valid pot file.`,`
8
8
  Please add the email field to the package.json file (author field eg. author: "AUTHOR <EMAIL>")`,`
9
9
  or inject those information using the --headers flag to the "makePot" command (eg. --headers=email:erik@ck.it).`,`
10
- For more information check the documentation at https://github.com/wp-blocks/makePot`),r&&t&&console.error(`
10
+ For more information check the documentation at https://github.com/wp-blocks/makePot`),o&&t&&console.error(`
11
11
  Debug information:`,`
12
- Missing fields:`,r,`
12
+ Missing fields:`,o,`
13
13
  Header data:`,e),console.error(`
14
- `),!1}return!0}function h(e){const t={name:"AUTHOR",email:"AUTHOR EMAIL"};if(!e)return t;if(typeof e=="string"){const o=e.match(/<([^>]+)>/),r=o?o[1].trim():void 0,n=e.match(/\(([^)]+)\)/),s=n?n[1].trim():void 0;let i=e.trim();return o&&(i=i.replace(o[0],"").trim()),n&&(i=i.replace(n[0],"").trim()),{name:i,email:r,website:s}}if(typeof e=="object")return{name:e.name,email:e.email,website:e.website}}function P(e){const t=["author","authors","contributors","maintainers"];for(const o of t)if(e[o]){let r;if(typeof e[o]=="string")r=h(e[o]);else if(typeof e[o]=="object"){for(const n of e[o])if(n&&(r=h(n),r))break}if(r?.name!=="AUTHOR"||r?.email!=="AUTHOR EMAIL")return r}return{name:"AUTHOR",email:"AUTHOR EMAIL"}}function x(e){const t=(0,u.getPkgJsonData)(e.paths?.cwd,"name","version","author","authors","contributors","maintainers"),o=P(t),r=f.default.basename(e.paths?.cwd||process.cwd())?.toLowerCase().replace(" ","-"),n=e?.headers?.author||o?.name,s=e?.headers?.email||o?.email,i=`${n} <${s}>`,l=e.slug||r||e.headers?.name?.toString().replace(/ /g,"-")||(e.domain==="theme"?"THEME NAME":"PLUGIN NAME"),a=`https://wordpress.org/support/${e.domain==="theme"?"themes":"plugins"}/${l}`;return{...e.headers,name:e.headers?.name||l,author:n,authorString:i,slug:l,email:s,bugs:a,license:e.headers?.license||"gpl-2.0 or later",version:e.headers?.version||t.version||"0.0.1",language:"en",xDomain:e.headers?.textDomain||l}}async function U(e){const t=x(e),{name:o,version:r}=(0,u.getPkgJsonData)(p.modulePath,"name","version");return R(t,e.debug)?{"Project-Id-Version":`${t.name} ${t.version}`,"Report-Msgid-Bugs-To":t.bugs,"MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","content-type":`text/plain; charset=${(0,k.getEncodingCharset)(e.options?.charset)}`,"plural-forms":"nplurals=2; plural=(n!=1);","POT-Creation-Date":`${new Date().toISOString()}`,"PO-Revision-Date":`${new Date().getFullYear()}-MO-DA HO:MI+ZONE`,"Last-Translator":t.authorString,"Language-Team":t.authorString,"X-Generator":`${o} ${r}`,Language:`${t.language}`,"X-Domain":t.xDomain}:(process.exit(1),null)}function v(e){let t={};return["plugin","block","generic"].includes(e.domain)?t=(0,A.extractPhpPluginData)(e):["theme","theme-block"].includes(e.domain)?t=(0,b.extractCssThemeData)(e):console.log("No main file detected."),t}function E(e){const{domain:t,headers:o}=e,{name:r,description:n,author:s,authorUri:i,url:l}=o,a=t==="plugin"?`${e.slug}.php`:"style.css";return new g.SetOfBlocks([(0,m.buildBlock)(`Name of the ${t}`,r,[a]),(0,m.buildBlock)(`Url of the ${t}`,l,[a]),(0,m.buildBlock)(`Description of the ${t}`,n,[a]),(0,m.buildBlock)(`Author of the ${t}`,s,[a]),(0,m.buildBlock)(`Author URI of the ${t}`,i,[a])])}0&&(module.exports={extractMainFileData,generateHeader,getAuthorFromPackage,translationsHeaders});
14
+ `)}return!1}return!0}function f(e){const t={name:"AUTHOR",email:"AUTHOR EMAIL"};if(!e)return t;if(typeof e=="string"){const r=e.match(/<([^>]+)>/),i=r?r[1].trim():void 0,o=e.match(/\(([^)]+)\)/),n=o?o[1].trim():void 0;let a=e.trim();return r&&(a=a.replace(r[0],"").trim()),o&&(a=a.replace(o[0],"").trim()),{name:a,email:i,website:n}}if(typeof e=="object")return{name:e.name,email:e.email,website:e.website}}function w(e){const t=["author","authors","contributors","maintainers"];for(const r of t){const i=e[r];if(i){let o;if(typeof i=="string")o=f(i);else if(Array.isArray(i)){for(const n of i)if(n&&(typeof n=="string"||typeof n=="object")&&(o=f(n),o))break}else typeof i=="object"&&(o=f(i));if(o?.name!=="AUTHOR"||o?.email!=="AUTHOR EMAIL")return o}}return{name:"AUTHOR",email:"AUTHOR EMAIL"}}function U(e){const t=(0,h.getPkgJsonData)(e.paths?.cwd,"name","version","author","authors","contributors","maintainers"),r=w(t),i=g.default.basename(e.paths?.cwd||m.default.cwd())?.toLowerCase().replace(" ","-"),o=e?.headers?.author||r?.name,n=e?.headers?.email||r?.email,a=`${o} <${n}>`,l=e.slug||i||e.headers?.name?.toString().replace(/ /g,"-")||(e.domain==="theme"?"THEME NAME":"PLUGIN NAME"),s=`https://wordpress.org/support/${e.domain==="theme"?"themes":"plugins"}/${l}`;return{...e.headers,name:e.headers?.name?.toString()||l,author:o,authorString:a,slug:l,email:n,bugs:s,license:e.headers?.license||"gpl-2.0 or later",version:e.headers?.version||t.version||"0.0.1",language:"en",xDomain:e.headers?.textDomain?.toString()||l}}async function x(e){const t=U(e),{name:r,version:i}=(0,h.getPkgJsonData)(k.modulePath,"name","version");if(!v(t,e.debug,e.options?.silent)&&!e.options?.silent){const o=R.createInterface({input:m.default.stdin,output:m.default.stdout}),n=await new Promise(a=>{o.question(`
15
+ Missing required fields. Use default values? (y/N) `,a)});o.close(),typeof n=="string"&&n.toLowerCase()!=="y"&&n.toLowerCase()!=="yes"&&m.default.exit(1)}return{"Project-Id-Version":`${t.name} ${t.version}`,"Report-Msgid-Bugs-To":t.bugs,"MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","content-type":`text/plain; charset=${(0,y.getEncodingCharset)(e.options?.charset)}`,"plural-forms":"nplurals=2; plural=(n!=1);","POT-Creation-Date":`${new Date().toISOString()}`,"PO-Revision-Date":`${new Date().getFullYear()}-MO-DA HO:MI+ZONE`,"Last-Translator":t.authorString,"Language-Team":t.authorString,"X-Generator":`${r} ${i}`,Language:`${t.language}`,"X-Domain":t.xDomain}}function E(e){let t={};return["plugin","block","generic"].includes(e.domain)?t=(0,P.extractPhpPluginData)(e):["theme","theme-block"].includes(e.domain)?t=(0,b.extractCssThemeData)(e):console.log("No main file detected."),t}function L(e){const{domain:t,headers:r}=e,{name:i,description:o,author:n,authorUri:a,url:l}=r,s=t==="plugin"?`${e.slug}.php`:"style.css";return new A.SetOfBlocks([(0,c.buildBlock)(`Name of the ${t}`,i,[s]),(0,c.buildBlock)(`Url of the ${t}`,l,[s]),(0,c.buildBlock)(`Description of the ${t}`,o,[s]),(0,c.buildBlock)(`Author of the ${t}`,n,[s]),(0,c.buildBlock)(`Author URI of the ${t}`,a,[s])])}0&&(module.exports={extractMainFileData,generateHeader,getAuthorFromPackage,translationsHeaders});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/extractors/headers.ts"],
4
- "sourcesContent": ["import path from \"node:path\";\r\nimport { SetOfBlocks } from \"gettext-merger\";\r\nimport { boolean } from \"yargs\";\r\nimport type PackageI18n from \"../assets/package-i18n.js\";\r\nimport { modulePath } from \"../const.js\";\r\nimport { getEncodingCharset } from \"../fs/fs.js\";\r\nimport type { Args, I18nHeaders, PotHeaders } from \"../types.js\";\r\nimport { getPkgJsonData } from \"../utils/common.js\";\r\nimport { buildBlock } from \"../utils/extractors.js\";\r\nimport { extractCssThemeData } from \"./css.js\";\r\nimport { extractPhpPluginData } from \"./php.js\";\r\n\r\n/**\r\n * Checks if required fields are missing and logs a clear error message\r\n * @param {object} headerData - The header data to validate\r\n * @param {boolean} debug - Debug mode flag\r\n * @returns {boolean} - true if all required fields are present, false otherwise\r\n */\r\nfunction validateRequiredFields(\r\n\theaderData: I18nHeaders,\r\n\tdebug: boolean,\r\n): boolean {\r\n\tconst requiredFields = [\r\n\t\t{ key: \"slug\", name: \"Plugin/Theme slug\", placeholder: \"PLUGIN NAME\" },\r\n\t\t{ key: \"author\", name: \"Author name\", placeholder: \"AUTHOR\" },\r\n\t\t{ key: \"version\", name: \"Version\", placeholder: \"\" },\r\n\t\t{ key: \"email\", name: \"Author email\", placeholder: \"AUTHOR EMAIL\" },\r\n\t\t{ key: \"xDomain\", name: \"Text domain\", placeholder: \"PLUGIN TEXTDOMAIN\" },\r\n\t];\r\n\r\n\tconst missingFields = requiredFields.filter(\r\n\t\t(field) =>\r\n\t\t\t!headerData[field.key] ||\r\n\t\t\theaderData[field.key] === field.placeholder ||\r\n\t\t\t(field.key === \"version\" && headerData[field.key] === \"0.0.1\"),\r\n\t);\r\n\r\n\tif (missingFields.length > 0) {\r\n\t\tconsole.error(\"\\n! Missing required information for POT file header:\\n\");\r\n\r\n\t\tfor (const field of missingFields) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t` - ${field.name} is missing or has a default value (eg. version: 0.0.1\")`,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tconsole.error(\r\n\t\t\t\"\\nPlease provide this information adding the missing fields inside the headers object of the plugin/theme declaration or to the package.json file.\",\r\n\t\t\t\"\\nFor more information check the documentation at https://github.com/wp-blocks/makePot\",\r\n\t\t);\r\n\r\n\t\tif (missingFields.some((field) => field.key === \"email\")) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"\\n\\nWordpress didn't require an email field in the headers object but it's required in order to generate a valid pot file.\",\r\n\t\t\t\t'\\nPlease add the email field to the package.json file (author field eg. author: \"AUTHOR <EMAIL>\")',\r\n\t\t\t\t'\\nor inject those information using the --headers flag to the \"makePot\" command (eg. --headers=email:erik@ck.it).',\r\n\t\t\t\t\"\\nFor more information check the documentation at https://github.com/wp-blocks/makePot\",\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (missingFields && debug) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"\\nDebug information:\",\r\n\t\t\t\t\"\\nMissing fields:\",\r\n\t\t\t\tmissingFields,\r\n\t\t\t\t\"\\nHeader data:\",\r\n\t\t\t\theaderData,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tconsole.error(\"\\n\");\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * Extract author data from package.json author field and return an array of strings\r\n * the original field is a string and it's longer form is \"Your Name <email@example.com> (https://example.com)\"\r\n *\r\n * @returns an object with name, email, and website\r\n * @param authorData\r\n */\r\nfunction extractAuthorData(authorData: string | object): {\r\n\tname: string;\r\n\temail?: string;\r\n\twebsite?: string;\r\n} {\r\n\t// Default result with placeholder values\r\n\tconst defaultResult = { name: \"AUTHOR\", email: \"AUTHOR EMAIL\" };\r\n\r\n\t// Return default if no author data\r\n\tif (!authorData) {\r\n\t\treturn defaultResult;\r\n\t}\r\n\r\n\t// Handle string format: \"Barney Rubble <barney@npmjs.com> (http://barnyrubble.npmjs.com/)\"\r\n\tif (typeof authorData === \"string\") {\r\n\t\t// Try to extract email with regex\r\n\t\tconst emailMatch = authorData.match(/<([^>]+)>/);\r\n\t\tconst email = emailMatch ? emailMatch[1].trim() : undefined;\r\n\r\n\t\t// Try to extract website with regex\r\n\t\tconst websiteMatch = authorData.match(/\\(([^)]+)\\)/);\r\n\t\tconst website = websiteMatch ? websiteMatch[1].trim() : undefined;\r\n\r\n\t\t// Extract name by removing email and website parts if present\r\n\t\tlet name = authorData.trim();\r\n\t\tif (emailMatch) name = name.replace(emailMatch[0], \"\").trim();\r\n\t\tif (websiteMatch) name = name.replace(websiteMatch[0], \"\").trim();\r\n\r\n\t\treturn { name, email, website };\r\n\t}\r\n\tif (typeof authorData === \"object\") {\r\n\t\t// Handle object format: { name: \"Barney Rubble\", email: \"barney@npmjs.com\", website: \"http://barnyrubble.npmjs.com/\" }\r\n\t\treturn {\r\n\t\t\tname: authorData.name,\r\n\t\t\temail: authorData.email,\r\n\t\t\twebsite: authorData.website,\r\n\t\t};\r\n\t}\r\n}\r\n\r\n/**\r\n * Gets author data by checking multiple possible locations in package.json\r\n *\r\n * @param pkgJsonData The package.json data object\r\n * @returns Author data with name, email and website\r\n */\r\nexport function getAuthorFromPackage(pkgJsonData: PackageI18n): {\r\n\tname: string;\r\n\temail?: string;\r\n\twebsite?: string;\r\n} {\r\n\t// Check multiple possible locations for author information\r\n\tconst locations = [\r\n\t\t\"author\", // Standard author field\r\n\t\t\"authors\", // Some packages use authors (plural)\r\n\t\t\"contributors\", // Try contributors if no author\r\n\t\t\"maintainers\", // Try maintainers as last resort\r\n\t];\r\n\r\n\t// Try each location in order\r\n\tfor (const location of locations) {\r\n\t\tif (pkgJsonData[location]) {\r\n\t\t\tlet authorData: {\r\n\t\t\t\tname: string;\r\n\t\t\t\temail?: string;\r\n\t\t\t\twebsite?: string;\r\n\t\t\t};\r\n\t\t\tif (typeof pkgJsonData[location] === \"string\") {\r\n\t\t\t\tauthorData = extractAuthorData(pkgJsonData[location]);\r\n\t\t\t} else if (typeof pkgJsonData[location] === \"object\") {\r\n\t\t\t\tfor (const author of pkgJsonData[location]) {\r\n\t\t\t\t\tif (!author) continue;\r\n\t\t\t\t\tauthorData = extractAuthorData(author);\r\n\t\t\t\t\tif (authorData) break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (\r\n\t\t\t\tauthorData?.name !== \"AUTHOR\" ||\r\n\t\t\t\tauthorData?.email !== \"AUTHOR EMAIL\"\r\n\t\t\t) {\r\n\t\t\t\treturn authorData;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If no valid author data found in any location\r\n\treturn { name: \"AUTHOR\", email: \"AUTHOR EMAIL\" };\r\n}\r\n\r\n/**\r\n * This function consolidates the user headers data into a single object\r\n *\r\n * @param args the command line arguments\r\n * @return {Record<string, string>} the consolidated headers data object\r\n */\r\nfunction consolidateUserHeaderData(args: Args): I18nHeaders {\r\n\tconst pkgJsonData = getPkgJsonData(\r\n\t\targs.paths?.cwd,\r\n\t\t\"name\",\r\n\t\t\"version\",\r\n\t\t\"author\",\r\n\t\t\"authors\",\r\n\t\t\"contributors\",\r\n\t\t\"maintainers\",\r\n\t) as Record<[keyof PackageI18n], string>;\r\n\t// get author data from package.json\r\n\tconst pkgAuthor = getAuthorFromPackage(pkgJsonData);\r\n\r\n\t// get the current directory name as slug\r\n\tconst currentDir = path\r\n\t\t.basename(args.paths?.cwd || process.cwd())\r\n\t\t?.toLowerCase()\r\n\t\t.replace(\" \", \"-\");\r\n\r\n\t// Use command line author name if provided, fallback to package.json\r\n\tconst authorName = args?.headers?.author || pkgAuthor?.name;\r\n\tconst email = args?.headers?.email || pkgAuthor?.email;\r\n\t// this is the author with email address in this format: author <email>\r\n\tconst authorString = `${authorName} <${email}>`;\r\n\tconst slug =\r\n\t\targs.slug ||\r\n\t\tcurrentDir ||\r\n\t\targs.headers?.name?.toString().replace(/ /g, \"-\") ||\r\n\t\t(args.domain === \"theme\" ? \"THEME NAME\" : \"PLUGIN NAME\");\r\n\r\n\tconst bugs = `https://wordpress.org/support/${args.domain === \"theme\" ? \"themes\" : \"plugins\"}/${slug}`;\r\n\r\n\treturn {\r\n\t\t...args.headers,\r\n\t\tname: args.headers?.name || slug,\r\n\t\tauthor: authorName,\r\n\t\tauthorString: authorString, // this is the author with email address in this format: author <email>\r\n\t\tslug,\r\n\t\temail,\r\n\t\tbugs,\r\n\t\tlicense: args.headers?.license || \"gpl-2.0 or later\",\r\n\t\tversion: args.headers?.version || pkgJsonData.version || \"0.0.1\",\r\n\t\tlanguage: \"en\",\r\n\t\txDomain: args.headers?.textDomain || slug,\r\n\t};\r\n}\r\n\r\n/**\r\n * Generates a POT header for a given set of arguments.\r\n * https://developer.wordpress.org/cli/commands/i18n/make-pot/\r\n * String that should be added as a comment to the top of the resulting POT file.\r\n * By default, a copyright comment is added for WordPress plugins and themes in the following manner:\r\n * `\r\n * Copyright (C) 2018 Example Plugin Author\r\n * This file is distributed under the same license as the Example Plugin package.\r\n * `\r\n * If a plugin or theme specifies a license in their main plugin file or stylesheet,\r\n * the comment looks like this: Copyright (C) 2018 Example Plugin Author This file is distributed under the GPLv2.\r\n *\r\n * @param args - The argument object containing the headers and their values.\r\n * @return The generated POT header.\r\n */\r\nexport async function generateHeader(\r\n\targs: Args,\r\n): Promise<Record<string, string> | null> {\r\n\t// Consolidate the user headers data into a single object\r\n\tconst headerData = consolidateUserHeaderData(args);\r\n\r\n\t// the makepot module name and version\r\n\tconst { name, version } = getPkgJsonData(modulePath, \"name\", \"version\");\r\n\r\n\t// Validate required fields - exit early if validation fails\r\n\tif (!validateRequiredFields(headerData, args.debug)) {\r\n\t\tprocess.exit(1); // Exit with error code\r\n\t\treturn null; // This is never reached but helps with TypeScript\r\n\t}\r\n\r\n\treturn {\r\n\t\t\"Project-Id-Version\": `${headerData.name} ${headerData.version}`,\r\n\t\t\"Report-Msgid-Bugs-To\": headerData.bugs,\r\n\t\t\"MIME-Version\": \"1.0\",\r\n\t\t\"Content-Transfer-Encoding\": \"8bit\",\r\n\t\t\"content-type\": `text/plain; charset=${getEncodingCharset(args.options?.charset)}`,\r\n\t\t\"plural-forms\": \"nplurals=2; plural=(n!=1);\",\r\n\t\t\"POT-Creation-Date\": `${new Date().toISOString()}`,\r\n\t\t\"PO-Revision-Date\": `${new Date().getFullYear()}-MO-DA HO:MI+ZONE`,\r\n\t\t\"Last-Translator\": headerData.authorString,\r\n\t\t\"Language-Team\": headerData.authorString,\r\n\t\t\"X-Generator\": `${name} ${version}`,\r\n\t\tLanguage: `${headerData.language}`,\r\n\t\t\"X-Domain\": headerData.xDomain,\r\n\t};\r\n}\r\n\r\n/**\r\n * Extracts main file data based on the given arguments.\r\n *\r\n * @param {Args} args - The arguments for extracting the main file data.\r\n * @return {Record<string, string>} The extracted main file data.\r\n */\r\nexport function extractMainFileData(args: Args): Record<string, string> {\r\n\tlet extractedData = {};\r\n\tif ([\"plugin\", \"block\", \"generic\"].includes(args.domain)) {\r\n\t\textractedData = extractPhpPluginData(args);\r\n\t} else if ([\"theme\", \"theme-block\"].includes(args.domain)) {\r\n\t\textractedData = extractCssThemeData(args);\r\n\t} else {\r\n\t\tconsole.log(\"No main file detected.\");\r\n\t}\r\n\r\n\treturn extractedData;\r\n}\r\n\r\n/**\r\n * Generate translation strings based on the given type and headers.\r\n *\r\n * @return {Record<string, string>} the generated translation strings\r\n * @param args\r\n */\r\nexport function translationsHeaders(args: Args): SetOfBlocks {\r\n\tconst { domain, headers } = args as Args;\r\n\tconst { name, description, author, authorUri, url } = headers as {\r\n\t\t[key in PotHeaders]: string;\r\n\t};\r\n\r\n\t// the main file is the plugin main php file or the css file\r\n\tconst fakePath = domain === \"plugin\" ? `${args.slug}.php` : \"style.css\";\r\n\r\n\treturn new SetOfBlocks([\r\n\t\tbuildBlock(`Name of the ${domain}`, name, [fakePath]),\r\n\t\tbuildBlock(`Url of the ${domain}`, url, [fakePath]),\r\n\t\tbuildBlock(`Description of the ${domain}`, description, [fakePath]),\r\n\t\tbuildBlock(`Author of the ${domain}`, author, [fakePath]),\r\n\t\tbuildBlock(`Author URI of the ${domain}`, authorUri, [fakePath]),\r\n\t]);\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["path"]
4
+ "sourcesContent": ["import path from 'node:path'\r\nimport process from 'node:process'\r\nimport * as readline from 'node:readline'\r\nimport { SetOfBlocks } from 'gettext-merger'\r\nimport { modulePath } from '../const.js'\r\nimport { getEncodingCharset } from '../fs/fs.js'\r\nimport type { Args, AuthorData, I18nHeaders, PotHeaders } from '../types.js'\r\nimport { getPkgJsonData } from '../utils/common.js'\r\nimport { buildBlock } from '../utils/extractors.js'\r\nimport { extractCssThemeData } from './css.js'\r\nimport { extractPhpPluginData } from './php.js'\r\n\r\n/**\r\n * Checks if required fields are missing and logs a clear error message\r\n * @param {object} headerData - The header data to validate\r\n * @param {boolean} debug - Debug mode flag\r\n * @param {boolean} silent - Silent mode flag\r\n * @returns {boolean} - true if all required fields are present, false otherwise\r\n */\r\nfunction validateRequiredFields(\r\n\theaderData: I18nHeaders,\r\n\tdebug: boolean,\r\n\tsilent = false,\r\n): boolean {\r\n\t// Define the required fields with strict key types\r\n\tconst requiredFields: {\r\n\t\tkey: keyof I18nHeaders;\r\n\t\tname: string;\r\n\t\tplaceholder: string;\r\n\t}[] = [\r\n\t\t\t{ key: \"slug\", name: \"Plugin/Theme slug\", placeholder: \"PLUGIN NAME\" },\r\n\t\t\t{ key: \"author\", name: \"Author name\", placeholder: \"AUTHOR\" },\r\n\t\t\t{ key: \"version\", name: \"Version\", placeholder: \"\" },\r\n\t\t\t{ key: \"email\", name: \"Author email\", placeholder: \"AUTHOR EMAIL\" },\r\n\t\t\t{ key: \"xDomain\", name: \"Text domain\", placeholder: \"PLUGIN TEXTDOMAIN\" },\r\n\t\t];\r\n\r\n\t// Filter out the missing or default fields\r\n\tconst missingFields = requiredFields.filter(\r\n\t\t(field) =>\r\n\t\t\t!headerData[field.key] ||\r\n\t\t\theaderData[field.key] === field.placeholder ||\r\n\t\t\t(field.key === \"version\" && headerData[field.key] === \"0.0.1\"),\r\n\t);\r\n\r\n\tif (missingFields.length > 0) {\r\n\t\tif (!silent) {\r\n\t\t\tconsole.error(\"\\n! Missing required information for POT file header:\\n\");\r\n\r\n\t\t\tfor (const field of missingFields) {\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t` - ${field.name} is missing or has a default value (eg. version: 0.0.1\")`,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"\\nPlease provide this information adding the missing fields inside the headers object of the plugin/theme declaration or to the package.json file.\",\r\n\t\t\t\t\"\\nFor more information check the documentation at https://github.com/wp-blocks/makePot\",\r\n\t\t\t);\r\n\r\n\t\t\tif (missingFields.some((field) => field.key === \"email\")) {\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t\"\\n\\nWordpress didn't require an email field in the headers object but it's required in order to generate a valid pot file.\",\r\n\t\t\t\t\t'\\nPlease add the email field to the package.json file (author field eg. author: \"AUTHOR <EMAIL>\")',\r\n\t\t\t\t\t'\\nor inject those information using the --headers flag to the \"makePot\" command (eg. --headers=email:erik@ck.it).',\r\n\t\t\t\t\t\"\\nFor more information check the documentation at https://github.com/wp-blocks/makePot\",\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tif (missingFields && debug) {\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t\"\\nDebug information:\",\r\n\t\t\t\t\t\"\\nMissing fields:\",\r\n\t\t\t\t\tmissingFields,\r\n\t\t\t\t\t\"\\nHeader data:\",\r\n\t\t\t\t\theaderData,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconsole.error(\"\\n\");\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * Extract author data from package.json author field and return an array of strings\r\n * the original field is a string and it's longer form is \"Your Name <email@example.com> (https://example.com)\"\r\n *\r\n * @returns an object with name, email, and website\r\n * @param authorData\r\n */\r\nfunction extractAuthorData(\r\n\tauthorData: string | AuthorData,\r\n): AuthorData | undefined {\r\n\t// Default result with placeholder values\r\n\tconst defaultResult = { name: \"AUTHOR\", email: \"AUTHOR EMAIL\" };\r\n\r\n\t// Return default if no author data\r\n\tif (!authorData) {\r\n\t\treturn defaultResult;\r\n\t}\r\n\r\n\t// Handle string format: \"Barney Rubble <barney@npmjs.com> (http://barnyrubble.npmjs.com/)\"\r\n\tif (typeof authorData === \"string\") {\r\n\t\t// Try to extract email with regex\r\n\t\tconst emailMatch = authorData.match(/<([^>]+)>/);\r\n\t\tconst email = emailMatch ? emailMatch[1].trim() : undefined;\r\n\r\n\t\t// Try to extract website with regex\r\n\t\tconst websiteMatch = authorData.match(/\\(([^)]+)\\)/);\r\n\t\tconst website = websiteMatch ? websiteMatch[1].trim() : undefined;\r\n\r\n\t\t// Extract name by removing email and website parts if present\r\n\t\tlet name = authorData.trim();\r\n\t\tif (emailMatch) name = name.replace(emailMatch[0], \"\").trim();\r\n\t\tif (websiteMatch) name = name.replace(websiteMatch[0], \"\").trim();\r\n\r\n\t\treturn { name, email, website };\r\n\t}\r\n\tif (typeof authorData === \"object\") {\r\n\t\t// Handle object format: { name: \"Barney Rubble\", email: \"barney@npmjs.com\", website: \"http://barnyrubble.npmjs.com/\" }\r\n\t\treturn {\r\n\t\t\tname: authorData.name,\r\n\t\t\temail: authorData.email,\r\n\t\t\twebsite: authorData.website,\r\n\t\t};\r\n\t}\r\n}\r\n\r\n/**\r\n * Gets author data by checking multiple possible locations in package.json\r\n *\r\n * @param pkgJsonData The package.json data object\r\n * @returns Author data with name, email and website\r\n */\r\nexport function getAuthorFromPackage(\r\n\tpkgJsonData: Record<string, unknown>,\r\n): AuthorData {\r\n\t// Check multiple possible locations for author information\r\n\tconst fields = [\r\n\t\t\"author\", // Standard author field\r\n\t\t\"authors\", // Some packages use authors (plural)\r\n\t\t\"contributors\", // Try contributors if no author\r\n\t\t\"maintainers\", // Try maintainers as a last resort\r\n\t] as string[];\r\n\r\n\t// Try each location in order\r\n\tfor (const field of fields) {\r\n\t\tconst value = pkgJsonData[field];\r\n\t\tif (value) {\r\n\t\t\tlet authorData: AuthorData | undefined;\r\n\r\n\t\t\tif (typeof value === \"string\") {\r\n\t\t\t\tauthorData = extractAuthorData(value);\r\n\t\t\t} else if (Array.isArray(value)) {\r\n\t\t\t\tfor (const author of value) {\r\n\t\t\t\t\tif (!author) continue;\r\n\t\t\t\t\tif (typeof author === \"string\" || typeof author === \"object\") {\r\n\t\t\t\t\t\tauthorData = extractAuthorData(author as string | AuthorData);\r\n\t\t\t\t\t\tif (authorData) break;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else if (typeof value === \"object\") {\r\n\t\t\t\t// Handle single object author field\r\n\t\t\t\tauthorData = extractAuthorData(value as AuthorData);\r\n\t\t\t}\r\n\r\n\t\t\tif (\r\n\t\t\t\tauthorData?.name !== \"AUTHOR\" ||\r\n\t\t\t\tauthorData?.email !== \"AUTHOR EMAIL\"\r\n\t\t\t) {\r\n\t\t\t\treturn authorData as AuthorData; // Returns the valid author data found\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If no valid author data found in any location\r\n\treturn { name: \"AUTHOR\", email: \"AUTHOR EMAIL\" };\r\n}\r\n\r\n/**\r\n * This function consolidates the user headers data into a single object\r\n *\r\n * @param args the command line arguments\r\n * @return {Record<string, string>} the consolidated headers data object\r\n */\r\nfunction consolidateUserHeaderData(args: Args): I18nHeaders {\r\n\tconst pkgJsonData = getPkgJsonData(\r\n\t\targs.paths?.cwd,\r\n\t\t\"name\",\r\n\t\t\"version\",\r\n\t\t\"author\",\r\n\t\t\"authors\",\r\n\t\t\"contributors\",\r\n\t\t\"maintainers\",\r\n\t);\r\n\t// get author data from package.json\r\n\tconst pkgAuthor = getAuthorFromPackage(\r\n\t\tpkgJsonData as unknown as Record<string, unknown>,\r\n\t);\r\n\r\n\t// get the current directory name as slug\r\n\tconst currentDir = path\r\n\t\t.basename(args.paths?.cwd || process.cwd())\r\n\t\t?.toLowerCase()\r\n\t\t.replace(\" \", \"-\");\r\n\r\n\t// Use command line author name if provided, fallback to package.json\r\n\tconst authorName = args?.headers?.author || pkgAuthor?.name;\r\n\tconst email = args?.headers?.email || pkgAuthor?.email;\r\n\t// this is the author with email address in this format: author <email>\r\n\tconst authorString = `${authorName} <${email}>`;\r\n\tconst slug =\r\n\t\targs.slug ||\r\n\t\tcurrentDir ||\r\n\t\targs.headers?.name?.toString().replace(/ /g, \"-\") ||\r\n\t\t(args.domain === \"theme\" ? \"THEME NAME\" : \"PLUGIN NAME\");\r\n\r\n\tconst bugs = `https://wordpress.org/support/${args.domain === \"theme\" ? \"themes\" : \"plugins\"\r\n\t\t}/${slug}`;\r\n\r\n\treturn {\r\n\t\t...args.headers,\r\n\t\tname: args.headers?.name?.toString() || slug,\r\n\t\tauthor: authorName,\r\n\t\tauthorString: authorString, // this is the author + email address in this format: author <email>\r\n\t\tslug,\r\n\t\temail,\r\n\t\tbugs,\r\n\t\tlicense: args.headers?.license || \"gpl-2.0 or later\",\r\n\t\tversion:\r\n\t\t\targs.headers?.version || (pkgJsonData.version as string) || \"0.0.1\",\r\n\t\tlanguage: \"en\",\r\n\t\txDomain: args.headers?.textDomain?.toString() || slug,\r\n\t};\r\n}\r\n\r\n/**\r\n * Generates a POT header for a given set of arguments.\r\n * https://developer.wordpress.org/cli/commands/i18n/make-pot/\r\n * String that should be added as a comment to the top of the resulting POT file.\r\n * By default, a copyright comment is added for WordPress plugins and themes in the following manner:\r\n * `\r\n * Copyright (C) 2018 Example Plugin Author\r\n * This file is distributed under the same license as the Example Plugin package.\r\n * `\r\n * If a plugin or theme specifies a license in their main plugin file or stylesheet,\r\n * the comment looks like this: Copyright (C) 2018 Example Plugin Author This file is distributed under the GPLv2.\r\n *\r\n * @param args - The argument object containing the headers and their values.\r\n * @return The generated POT header.\r\n */\r\nexport async function generateHeader(\r\n\targs: Args,\r\n): Promise<Record<string, string> | null> {\r\n\t// Consolidate the user headers data into a single object\r\n\tconst headerData = consolidateUserHeaderData(args);\r\n\r\n\t// the makepot module name and version\r\n\tconst { name, version } = getPkgJsonData(modulePath, \"name\", \"version\");\r\n\r\n\t// Validate required fields - exit early if validation fails\r\n\tif (!validateRequiredFields(headerData, args.debug, args.options?.silent)) {\r\n\t\tif (args.options?.silent) {\r\n\t\t\t// In silent mode, we use defaults without asking\r\n\t\t} else {\r\n\t\t\t// Ask the user if default values should be used\r\n\t\t\tconst rl = readline.createInterface({\r\n\t\t\t\tinput: process.stdin,\r\n\t\t\t\toutput: process.stdout,\r\n\t\t\t});\r\n\r\n\t\t\tconst answer = await new Promise((resolve) => {\r\n\t\t\t\trl.question(\r\n\t\t\t\t\t\"\\nMissing required fields. Use default values? (y/N) \",\r\n\t\t\t\t\tresolve,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t\t\trl.close();\r\n\r\n\t\t\tif (\r\n\t\t\t\ttypeof answer === \"string\" &&\r\n\t\t\t\tanswer.toLowerCase() !== \"y\" &&\r\n\t\t\t\tanswer.toLowerCase() !== \"yes\"\r\n\t\t\t) {\r\n\t\t\t\tprocess.exit(1); // Exit with error code\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\t\"Project-Id-Version\": `${headerData.name} ${headerData.version}`,\r\n\t\t\"Report-Msgid-Bugs-To\": headerData.bugs,\r\n\t\t\"MIME-Version\": \"1.0\",\r\n\t\t\"Content-Transfer-Encoding\": \"8bit\",\r\n\t\t\"content-type\": `text/plain; charset=${getEncodingCharset(args.options?.charset)}`,\r\n\t\t\"plural-forms\": \"nplurals=2; plural=(n!=1);\",\r\n\t\t\"POT-Creation-Date\": `${new Date().toISOString()}`,\r\n\t\t\"PO-Revision-Date\": `${new Date().getFullYear()}-MO-DA HO:MI+ZONE`,\r\n\t\t\"Last-Translator\": headerData.authorString,\r\n\t\t\"Language-Team\": headerData.authorString,\r\n\t\t\"X-Generator\": `${name} ${version}`,\r\n\t\tLanguage: `${headerData.language}`,\r\n\t\t\"X-Domain\": headerData.xDomain,\r\n\t};\r\n}\r\n\r\n/**\r\n * Extracts main file data based on the given arguments.\r\n *\r\n * @param {Args} args - The arguments for extracting the main file data.\r\n * @return {Record<string, string>} The extracted main file data.\r\n */\r\nexport function extractMainFileData(args: Args): Record<string, string> {\r\n\tlet extractedData = {};\r\n\tif ([\"plugin\", \"block\", \"generic\"].includes(args.domain)) {\r\n\t\textractedData = extractPhpPluginData(args);\r\n\t} else if ([\"theme\", \"theme-block\"].includes(args.domain)) {\r\n\t\textractedData = extractCssThemeData(args);\r\n\t} else {\r\n\t\tconsole.log(\"No main file detected.\");\r\n\t}\r\n\r\n\treturn extractedData;\r\n}\r\n\r\n/**\r\n * Generate translation strings based on the given type and headers.\r\n *\r\n * @return {Record<string, string>} the generated translation strings\r\n * @param args\r\n */\r\nexport function translationsHeaders(args: Args): SetOfBlocks {\r\n\tconst { domain, headers } = args as Args;\r\n\tconst { name, description, author, authorUri, url } = headers as {\r\n\t\t[key in PotHeaders]: string;\r\n\t};\r\n\r\n\t// the main file is the plugin main php file or the css file\r\n\tconst fakePath = domain === \"plugin\" ? `${args.slug}.php` : \"style.css\";\r\n\r\n\treturn new SetOfBlocks([\r\n\t\tbuildBlock(`Name of the ${domain}`, name, [fakePath]),\r\n\t\tbuildBlock(`Url of the ${domain}`, url, [fakePath]),\r\n\t\tbuildBlock(`Description of the ${domain}`, description, [fakePath]),\r\n\t\tbuildBlock(`Author of the ${domain}`, author, [fakePath]),\r\n\t\tbuildBlock(`Author URI of the ${domain}`, authorUri, [fakePath]),\r\n\t]);\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["path", "process"]
7
7
  }
@@ -1 +1 @@
1
- "use strict";var f=Object.create;var s=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var p=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var u=(e,o)=>{for(var n in o)s(e,n,{get:o[n],enumerable:!0})},l=(e,o,n,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of h(o))!b.call(e,r)&&r!==n&&s(e,r,{get:()=>o[r],enumerable:!(a=k(o,r))||a.enumerable});return e};var S=(e,o,n)=>(n=e!=null?f(p(e)):{},l(o||!e||!e.__esModule?s(n,"default",{value:e,enumerable:!0}):n,e)),j=e=>l(s({},"__esModule",{value:!0}),e);var J={};u(J,{parseJsonCallback:()=>d,parseJsonFile:()=>m});module.exports=j(J);var c=S(require("node:path")),i=require("../utils/extractors.js"),t=require("./schema.js");async function m(e){const o=e.filename==="theme.json",n={url:o?t.JsonSchemaExtractor.themeJsonSource:t.JsonSchemaExtractor.blockJsonSource,fallback:o?t.JsonSchemaExtractor.themeJsonFallback:t.JsonSchemaExtractor.blockJsonFallback};if(!n.url||!n.fallback){console.error("Schema URL or fallback not provided");return}return await t.JsonSchemaExtractor.parse(e.fileContent,n,{file:e.filename,addReferences:!0})??[]}async function d(e,o,n){const a=await m({fileContent:e,filename:n});return(0,i.yieldParsedData)(a,n,c.default.join(o,n))}0&&(module.exports={parseJsonCallback,parseJsonFile});
1
+ "use strict";var f=Object.create;var s=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var p=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var b=(e,o)=>{for(var n in o)s(e,n,{get:o[n],enumerable:!0})},l=(e,o,n,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of h(o))!u.call(e,r)&&r!==n&&s(e,r,{get:()=>o[r],enumerable:!(a=k(o,r))||a.enumerable});return e};var S=(e,o,n)=>(n=e!=null?f(p(e)):{},l(o||!e||!e.__esModule?s(n,"default",{value:e,enumerable:!0}):n,e)),d=e=>l(s({},"__esModule",{value:!0}),e);var J={};b(J,{parseJsonCallback:()=>j,parseJsonFile:()=>m});module.exports=d(J);var c=S(require("node:path")),i=require("../utils/extractors.js"),t=require("./schema.js");async function m(e){const o=e.filename==="theme.json",n={url:o?t.JsonSchemaExtractor.themeJsonSource:t.JsonSchemaExtractor.blockJsonSource,fallback:o?t.JsonSchemaExtractor.themeJsonFallback:t.JsonSchemaExtractor.blockJsonFallback};if(!n.url||!n.fallback){console.error("Schema URL or fallback not provided");return}return await t.JsonSchemaExtractor.parse(e.fileContent,n,{file:e.filename,addReferences:!0})??[]}async function j(e,o,n){const a=await m({fileContent:e,filename:n});return(0,i.yieldParsedData)(a,n,c.default.join(o,n))}0&&(module.exports={parseJsonCallback,parseJsonFile});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/extractors/json.ts"],
4
- "sourcesContent": ["import path from \"node:path\";\nimport type { Block, SetOfBlocks } from \"gettext-merger\";\nimport type { I18nSchema } from \"../types.js\";\nimport { yieldParsedData } from \"../utils/extractors.js\";\nimport { JsonSchemaExtractor } from \"./schema.js\";\n\n/**\n * Parses a JSON file and returns an array of parsed data.\n *\n * @param {Object} opts - The arguments for parsing the JSON file.\n * @param {string} opts.filepath - The filepath of the JSON file to parse.\n * @param {Object} [opts.stats] - Optional statistics object.\n * @param {number} opts.stats.index - The index of the progress bar.\n * @return {Promise<TranslationStrings>} A promise that resolves to an object containing the parsed data.\n */\nexport async function parseJsonFile(opts: {\n\tfileContent: string;\n\tfilename: \"block.json\" | \"theme.json\";\n}): Promise<Block[]> {\n\tconst isTheme = opts.filename === \"theme.json\";\n\tconst schema: { url: string; fallback: I18nSchema } = {\n\t\turl: isTheme\n\t\t\t? JsonSchemaExtractor.themeJsonSource\n\t\t\t: JsonSchemaExtractor.blockJsonSource,\n\t\tfallback: isTheme\n\t\t\t? (JsonSchemaExtractor.themeJsonFallback as I18nSchema)\n\t\t\t: (JsonSchemaExtractor.blockJsonFallback as I18nSchema),\n\t};\n\n\tif (!schema.url || !schema.fallback) {\n\t\tconsole.error(\"Schema URL or fallback not provided\");\n\t\treturn;\n\t}\n\n\t// Get the JSON translations from the schema\n\tconst jsonTranslations = await JsonSchemaExtractor.parse(\n\t\topts.fileContent,\n\t\tschema,\n\t\t{\n\t\t\tfile: opts.filename,\n\t\t\taddReferences: true,\n\t\t},\n\t);\n\n\treturn jsonTranslations ?? [];\n}\n\n/**\n * Parses the JSON content of a file based on the filename and file content.\n *\n * @param {string} fileContent - The content of the file to parse.\n * @param {string} filePath - The path of the file being parsed.\n * @param {'block.json' | 'theme.json'} filename - The type of JSON file being parsed.\n * @return {Promise<TranslationStrings>} The parsed translation strings.\n */\nexport async function parseJsonCallback(\n\tfileContent: string,\n\tfilePath: string,\n\tfilename: \"block.json\" | \"theme.json\",\n): Promise<SetOfBlocks> {\n\tconst data = await parseJsonFile({\n\t\tfileContent: fileContent,\n\t\tfilename: filename,\n\t});\n\n\treturn yieldParsedData(data, filename, path.join(filePath, filename));\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAiB;AAGjB,wBAAgC;AAChC,oBAAoC;AAWpC,eAAsB,cAAc,MAGf;AACpB,QAAM,UAAU,KAAK,aAAa;AAClC,QAAM,SAAgD;AAAA,IACrD,KAAK,UACF,kCAAoB,kBACpB,kCAAoB;AAAA,IACvB,UAAU,UACN,kCAAoB,oBACpB,kCAAoB;AAAA,EACzB;AAEA,MAAI,CAAC,OAAO,OAAO,CAAC,OAAO,UAAU;AACpC,YAAQ,MAAM,qCAAqC;AACnD;AAAA,EACD;AAGA,QAAM,mBAAmB,MAAM,kCAAoB;AAAA,IAClD,KAAK;AAAA,IACL;AAAA,IACA;AAAA,MACC,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAO,oBAAoB,CAAC;AAC7B;AAUA,eAAsB,kBACrB,aACA,UACA,UACuB;AACvB,QAAM,OAAO,MAAM,cAAc;AAAA,IAChC;AAAA,IACA;AAAA,EACD,CAAC;AAED,aAAO,mCAAgB,MAAM,UAAU,iBAAAA,QAAK,KAAK,UAAU,QAAQ,CAAC;AACrE;",
4
+ "sourcesContent": ["import path from \"node:path\";\nimport type { Block, SetOfBlocks } from \"gettext-merger\";\nimport type { I18nSchema } from \"../types.js\";\nimport { yieldParsedData } from \"../utils/extractors.js\";\nimport { JsonSchemaExtractor } from \"./schema.js\";\n\n/**\n * Parses a JSON file and returns an array of parsed data.\n *\n * @param {Object} opts - The arguments for parsing the JSON file.\n * @param {string} opts.filepath - The filepath of the JSON file to parse.\n * @param {Object} [opts.stats] - Optional statistics object.\n * @param {number} opts.stats.index - The index of the progress bar.\n * @return {Promise<TranslationStrings>} A promise that resolves to an object containing the parsed data.\n */\nexport async function parseJsonFile(opts: {\n\tfileContent: string;\n\tfilename: \"block.json\" | \"theme.json\";\n}): Promise<Block[] | undefined> {\n\tconst isTheme = opts.filename === \"theme.json\";\n\tconst schema: { url: string; fallback: I18nSchema } = {\n\t\turl: isTheme\n\t\t\t? JsonSchemaExtractor.themeJsonSource\n\t\t\t: JsonSchemaExtractor.blockJsonSource,\n\t\tfallback: isTheme\n\t\t\t? (JsonSchemaExtractor.themeJsonFallback as I18nSchema)\n\t\t\t: (JsonSchemaExtractor.blockJsonFallback as I18nSchema),\n\t};\n\n\tif (!schema.url || !schema.fallback) {\n\t\tconsole.error(\"Schema URL or fallback not provided\");\n\t\treturn;\n\t}\n\n\t// Get the JSON translations from the schema\n\tconst jsonTranslations = await JsonSchemaExtractor.parse(\n\t\topts.fileContent,\n\t\tschema,\n\t\t{\n\t\t\tfile: opts.filename,\n\t\t\taddReferences: true,\n\t\t},\n\t);\n\n\treturn jsonTranslations ?? [];\n}\n\n/**\n * Parses the JSON content of a file based on the filename and file content.\n *\n * @param {string} fileContent - The content of the file to parse.\n * @param {string} filePath - The path of the file being parsed.\n * @param {'block.json' | 'theme.json'} filename - The type of JSON file being parsed.\n * @return {Promise<TranslationStrings>} The parsed translation strings.\n */\nexport async function parseJsonCallback(\n\tfileContent: string,\n\tfilePath: string,\n\tfilename: \"block.json\" | \"theme.json\",\n): Promise<SetOfBlocks> {\n\tconst data = await parseJsonFile({\n\t\tfileContent: fileContent,\n\t\tfilename: filename,\n\t});\n\n\treturn yieldParsedData(data, filename, path.join(filePath, filename));\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAiB;AAGjB,wBAAgC;AAChC,oBAAoC;AAWpC,eAAsB,cAAc,MAGH;AAChC,QAAM,UAAU,KAAK,aAAa;AAClC,QAAM,SAAgD;AAAA,IACrD,KAAK,UACF,kCAAoB,kBACpB,kCAAoB;AAAA,IACvB,UAAU,UACN,kCAAoB,oBACpB,kCAAoB;AAAA,EACzB;AAEA,MAAI,CAAC,OAAO,OAAO,CAAC,OAAO,UAAU;AACpC,YAAQ,MAAM,qCAAqC;AACnD;AAAA,EACD;AAGA,QAAM,mBAAmB,MAAM,kCAAoB;AAAA,IAClD,KAAK;AAAA,IACL;AAAA,IACA;AAAA,MACC,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAO,oBAAoB,CAAC;AAC7B;AAUA,eAAsB,kBACrB,aACA,UACA,UACuB;AACvB,QAAM,OAAO,MAAM,cAAc;AAAA,IAChC;AAAA,IACA;AAAA,EACD,CAAC;AAED,aAAO,mCAAgB,MAAM,UAAU,iBAAAA,QAAK,KAAK,UAAU,QAAQ,CAAC;AACrE;",
6
6
  "names": ["path"]
7
7
  }
@@ -1,4 +1,3 @@
1
- "use strict";var A=Object.create;var y=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var C=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var F=(n,e)=>{for(var s in e)y(n,s,{get:e[s],enumerable:!0})},j=(n,e,s,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of v(e))!B.call(n,r)&&r!==s&&y(n,r,{get:()=>e[r],enumerable:!(i=u(e,r))||i.enumerable});return n};var w=(n,e,s)=>(s=n!=null?A(C(n)):{},j(e||!n||!n.__esModule?y(s,"default",{value:n,enumerable:!0}):s,n)),O=n=>j(y({},"__esModule",{value:!0}),n);var T={};F(T,{JsonSchemaExtractor:()=>c});module.exports=O(T);var $=w(require("../assets/block-i18n.js")),R=w(require("../assets/theme-i18n.js"));class c{static schemaCache={};static themeJsonSource="http://develop.svn.wordpress.org/trunk/src/wp-includes/theme-i18n.json";static themeJsonFallback=R;static blockJsonSource="http://develop.svn.wordpress.org/trunk/src/wp-includes/block-i18n.json";static blockJsonFallback=$;static async loadSchema(e,s){if(c.schemaCache[e])return c.schemaCache[e];try{console.log(`
2
- [i] Loading schema from ${e}`);const i=await fetch(e,{responseType:"json",accept:"application/json",headers:{"Access-Control-Allow-Origin":"*"}}).then(r=>r.json()).catch(r=>{throw new Error(`
3
- Failed to load schema from ${e}. Error: ${r.message}`)});return i?(console.log("Schema loaded successfully"),c.schemaCache[e]=i,i):s}catch(i){return console.error(`
4
- Failed to load schema from ${e}. Using fallback. Error: ${i.message}`),c.schemaCache[e]=s,s}}static async parse(e,s,i){const r=await c.loadSchema(s.url,s.fallback);try{const l=JSON.parse(e);if(!l){console.error("Could not parse JSON.");return}return c.extractFromJsonSchema(l,r,i)}catch(l){console.error(`Error parsing JSON: ${l.message}`);return}}static extractFromJsonSchema(e,s,i={filename:void 0,addReferences:!1}){const{filename:r="block.json",addReferences:l=!1}=i,g=[];function h(t,a,p=[]){if(!(!t||!a)&&typeof t=="object"&&!Array.isArray(t)&&typeof a=="object"&&!Array.isArray(a))for(const o of Object.keys(a))o in t&&(typeof t[o]=="string"?k(t[o],a[o],r,l):Array.isArray(t[o])&&Array.isArray(a[o])?I(t[o],a[o],[...p,o],r,l):typeof t[o]=="object"&&typeof a[o]=="object"&&h(t[o],a[o],[...p,o]))}function I(t,a,p,o,m){if(a.length>0){const d=a[0];for(const f of t)if(typeof f=="string")k(f,d,o,m);else if(typeof f=="object")if(typeof d=="object")h(f,d,p);else for(const b of Object.keys(f))typeof f[b]=="string"&&k(f[b],d,o,m)}}function k(t,a,p,o){if(!t)return;const m={msgid:a,msgctxt:t};o&&(m.comments={reference:[p]}),g.push(m)}return h(e,s),g}}0&&(module.exports={JsonSchemaExtractor});
1
+ "use strict";var A=Object.create;var g=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var C=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var F=(r,e)=>{for(var o in e)g(r,o,{get:e[o],enumerable:!0})},j=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of v(e))!S.call(r,t)&&t!==o&&g(r,t,{get:()=>e[t],enumerable:!(i=R(e,t))||i.enumerable});return r};var w=(r,e,o)=>(o=r!=null?A(C(r)):{},j(e||!r||!r.__esModule?g(o,"default",{value:r,enumerable:!0}):o,r)),O=r=>j(g({},"__esModule",{value:!0}),r);var N={};F(N,{JsonSchemaExtractor:()=>c});module.exports=O(N);var B=w(require("../assets/block-i18n.js")),$=w(require("../assets/theme-i18n.js"));class c{static schemaCache={};static themeJsonSource="http://develop.svn.wordpress.org/trunk/src/wp-includes/theme-i18n.json";static themeJsonFallback=$;static blockJsonSource="http://develop.svn.wordpress.org/trunk/src/wp-includes/block-i18n.json";static blockJsonFallback=B;static async loadSchema(e,o){if(c.schemaCache[e])return c.schemaCache[e];try{const i=await fetch(e,{headers:{"Access-Control-Allow-Origin":"*"}}).then(t=>t.json()).catch(t=>{throw new Error(`
2
+ Failed to load schema from ${e}. Error: ${t.message}`)});return i?(c.schemaCache[e]=i,i):o}catch(i){return console.error(`
3
+ Failed to load schema from ${e}. Using fallback. Error: ${i.message}`),c.schemaCache[e]=o,o}}static async parse(e,o,i){const t=await c.loadSchema(o.url,o.fallback);try{const l=JSON.parse(e);if(!l){console.error("Could not parse JSON.");return}return c.extractFromJsonSchema(l,t,i)}catch(l){console.error(`Error parsing JSON: ${l.message}`);return}}static extractFromJsonSchema(e,o,i={filename:void 0,addReferences:!1}){const{filename:t="block.json",addReferences:l=!1}=i,k=[];function h(n,a,d=[]){if(!(!n||!a)&&typeof n=="object"&&!Array.isArray(n)&&typeof a=="object"&&!Array.isArray(a))for(const s of Object.keys(a))s in n&&(typeof n[s]=="string"?y(n[s],a[s],t,l):Array.isArray(n[s])&&Array.isArray(a[s])?u(n[s],a[s],[...d,s],t,l):typeof n[s]=="object"&&n[s]!==null&&typeof a[s]=="object"&&h(n[s],a[s],[...d,s]))}function u(n,a,d,s,m){if(a.length>0){const p=a[0];for(const f of n)if(typeof f=="string")y(f,p,s,m);else if(typeof f=="object"&&f!==null)if(typeof p=="object")h(f,p,d);else for(const I of Object.keys(f)){const b=f[I];typeof b=="string"&&y(b,p,s,m)}}}function y(n,a,d,s){if(!n)return;const m={msgid:a,msgctxt:n};s&&(m.comments={reference:[d]}),k.push(m)}return h(e,o),k}}0&&(module.exports={JsonSchemaExtractor});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/extractors/schema.ts"],
4
- "sourcesContent": ["import type { Block } from \"gettext-merger\";\r\nimport type BlockI18n from \"../assets/block-i18n.js\";\r\nimport * as blocki18n from \"../assets/block-i18n.js\";\r\nimport type ThemeI18n from \"../assets/theme-i18n.js\";\r\nimport * as themei18n from \"../assets/theme-i18n.js\";\r\nimport type { I18nSchema } from \"../types.js\";\r\n\r\n/**\r\n * Extracts strings from JSON files using the I18n schema.\r\n */\r\nexport class JsonSchemaExtractor {\r\n\tprivate static schemaCache: { [url: string]: I18nSchema } = {};\r\n\r\n\t/** Theme */\r\n\tstatic themeJsonSource =\r\n\t\t\"http://develop.svn.wordpress.org/trunk/src/wp-includes/theme-i18n.json\";\r\n\tstatic themeJsonFallback = themei18n as ThemeI18n;\r\n\t/** Block */\r\n\tstatic blockJsonSource =\r\n\t\t\"http://develop.svn.wordpress.org/trunk/src/wp-includes/block-i18n.json\";\r\n\tstatic blockJsonFallback = blocki18n as BlockI18n;\r\n\r\n\t/**\r\n\t * Load the schema from the specified URL, with a fallback URL if needed.\r\n\t *\r\n\t * @param {string} url - The URL to load the schema from.\r\n\t * @param {I18nSchema} fallback - The fallback schema to use if the main URL fails.\r\n\t * @return {Promise<I18nSchema>} The loaded schema.\r\n\t */\r\n\tprivate static async loadSchema(\r\n\t\turl: string,\r\n\t\tfallback: I18nSchema,\r\n\t): Promise<I18nSchema> {\r\n\t\tif (JsonSchemaExtractor.schemaCache[url]) {\r\n\t\t\treturn JsonSchemaExtractor.schemaCache[url];\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconsole.log(`\\n[i] Loading schema from ${url}`);\r\n\t\t\tconst response = await fetch(url, {\r\n\t\t\t\tresponseType: \"json\",\r\n\t\t\t\taccept: \"application/json\",\r\n\t\t\t\theaders: {\r\n\t\t\t\t\t\"Access-Control-Allow-Origin\": \"*\",\r\n\t\t\t\t},\r\n\t\t\t})\r\n\t\t\t\t.then((response) => response.json())\r\n\t\t\t\t.catch((error: Error) => {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t`\\nFailed to load schema from ${url}. Error: ${error.message}`,\r\n\t\t\t\t\t);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Verify if the response is valid\r\n\t\t\tif (!response) {\r\n\t\t\t\treturn fallback;\r\n\t\t\t}\r\n\r\n\t\t\tconsole.log(\"Schema loaded successfully\");\r\n\t\t\tJsonSchemaExtractor.schemaCache[url] = response;\r\n\t\t\treturn response;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t`\\nFailed to load schema from ${url}. Using fallback. Error: ${error.message}`,\r\n\t\t\t);\r\n\t\t\tJsonSchemaExtractor.schemaCache[url] = fallback;\r\n\t\t\treturn fallback;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Parses a string and extracts translations using the specified schema.\r\n\t *\r\n\t * @param {string} text - the input string to be parsed\r\n\t * @param {object} schema - the schema to use for parsing the input string\r\n\t * @param {string} schema.url - the URL of the schema to use for parsing the input string\r\n\t * @param {object} schema.schemaFallback - the fallback schema to use if the main schema fails\r\n\t * @param {object} options - the options for parsing the input string\r\n\t * @param {string} options.file - the name of the file being parsed\r\n\t * @param {boolean} options.addReferences - whether to add references to the extracted strings\r\n\t *\r\n\t * @return {Promise<I18nSchema | undefined>} a promise that resolves with the extracted schema\r\n\t */\r\n\tpublic static async parse(\r\n\t\ttext: string,\r\n\t\tschema: {\r\n\t\t\turl: string;\r\n\t\t\tfallback: I18nSchema;\r\n\t\t},\r\n\t\toptions: {\r\n\t\t\tfile: \"block.json\" | \"theme.json\";\r\n\t\t\taddReferences: boolean;\r\n\t\t},\r\n\t): Promise<Block[] | undefined> {\r\n\t\tconst parsedSchema = await JsonSchemaExtractor.loadSchema(\r\n\t\t\tschema.url,\r\n\t\t\tschema.fallback,\r\n\t\t);\r\n\r\n\t\ttry {\r\n\t\t\tconst json = JSON.parse(text) as Record<string, unknown>;\r\n\t\t\tif (!json) {\r\n\t\t\t\tconsole.error(\"Could not parse JSON.\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\treturn JsonSchemaExtractor.extractFromJsonSchema(\r\n\t\t\t\tjson,\r\n\t\t\t\tparsedSchema,\r\n\t\t\t\toptions,\r\n\t\t\t);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(`Error parsing JSON: ${error.message}`);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Extracts translatable strings from a JSON file by comparing it with a schema\r\n\t *\r\n\t * @param {Object} json - The JSON object to extract strings from\r\n\t * @param {Object} schema - The schema that defines which fields contain translatable strings\r\n\t * @param {Object} options - Options for extraction\r\n\t * @param {string} options.filename - The name of the file being extracted (for references)\r\n\t * @param {boolean} options.addReferences - Whether to add file references in comments\r\n\t * @return {Array} - An array of objects with translatable strings in gettext format\r\n\t */\r\n\tprivate static extractFromJsonSchema(\r\n\t\tjson: Record<string, unknown>,\r\n\t\tschema: I18nSchema,\r\n\t\toptions: { filename?: string; addReferences?: boolean } = {\r\n\t\t\tfilename: undefined,\r\n\t\t\taddReferences: false,\r\n\t\t},\r\n\t): Block[] | undefined {\r\n\t\tconst { filename = \"block.json\", addReferences = false } = options;\r\n\t\tconst translations = [];\r\n\r\n\t\t/**\r\n\t\t * Recursive function to extract translatable strings\r\n\t\t * @param {*} currentJson - The current node in the JSON\r\n\t\t * @param {*} currentSchema - The current node in the schema\r\n\t\t * @param {Array} path - The current path in the JSON\r\n\t\t */\r\n\t\tfunction extract(currentJson, currentSchema, path = []) {\r\n\t\t\t// If either is null or undefined, there's nothing to do\r\n\t\t\tif (!currentJson || !currentSchema) return;\r\n\r\n\t\t\t// Handles the case where both are objects\r\n\t\t\tif (\r\n\t\t\t\ttypeof currentJson === \"object\" &&\r\n\t\t\t\t!Array.isArray(currentJson) &&\r\n\t\t\t\ttypeof currentSchema === \"object\" &&\r\n\t\t\t\t!Array.isArray(currentSchema)\r\n\t\t\t) {\r\n\t\t\t\t// Iterate over the schema keys\r\n\t\t\t\tfor (const key of Object.keys(currentSchema)) {\r\n\t\t\t\t\tif (key in currentJson) {\r\n\t\t\t\t\t\t// If the key exists in the JSON, check the type\r\n\t\t\t\t\t\tif (typeof currentJson[key] === \"string\") {\r\n\t\t\t\t\t\t\t// It's a string - add it to translations\r\n\t\t\t\t\t\t\taddTranslation(\r\n\t\t\t\t\t\t\t\tcurrentJson[key],\r\n\t\t\t\t\t\t\t\tcurrentSchema[key],\r\n\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} else if (\r\n\t\t\t\t\t\t\tArray.isArray(currentJson[key]) &&\r\n\t\t\t\t\t\t\tArray.isArray(currentSchema[key])\r\n\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t// It's an array - handle each element\r\n\t\t\t\t\t\t\thandleArrays(\r\n\t\t\t\t\t\t\t\tcurrentJson[key],\r\n\t\t\t\t\t\t\t\tcurrentSchema[key],\r\n\t\t\t\t\t\t\t\t[...path, key],\r\n\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} else if (\r\n\t\t\t\t\t\t\ttypeof currentJson[key] === \"object\" &&\r\n\t\t\t\t\t\t\ttypeof currentSchema[key] === \"object\"\r\n\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t// It's an object - recurse\r\n\t\t\t\t\t\t\textract(currentJson[key], currentSchema[key], [...path, key]);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Handles arrays in JSON and schema\r\n\t\t * @param {Array} jsonArray - The JSON array\r\n\t\t * @param {Array} schemaArray - The schema array\r\n\t\t * @param {Array} path - The current path\r\n\t\t * @param {string} filename - The name of the file\r\n\t\t * @param {boolean} addReferences - whenever to add references\r\n\t\t */\r\n\t\tfunction handleArrays(\r\n\t\t\tjsonArray,\r\n\t\t\tschemaArray,\r\n\t\t\tpath,\r\n\t\t\tfilename,\r\n\t\t\taddReferences,\r\n\t\t) {\r\n\t\t\t// If the schema has at least one element, use it as a template\r\n\t\t\tif (schemaArray.length > 0) {\r\n\t\t\t\tconst schemaTemplate = schemaArray[0];\r\n\r\n\t\t\t\t// For each element in the JSON array\r\n\t\t\t\tfor (const jsonItem of jsonArray) {\r\n\t\t\t\t\tif (typeof jsonItem === \"string\") {\r\n\t\t\t\t\t\t// If the JSON element is a string, add it directly\r\n\t\t\t\t\t\taddTranslation(jsonItem, schemaTemplate, filename, addReferences);\r\n\t\t\t\t\t} else if (typeof jsonItem === \"object\") {\r\n\t\t\t\t\t\t// If it's an object, recurse\r\n\t\t\t\t\t\tif (typeof schemaTemplate === \"object\") {\r\n\t\t\t\t\t\t\textract(jsonItem, schemaTemplate, path);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t// Edge case: handles cases like keywords: [\"string1\", \"string2\"]\r\n\t\t\t\t\t\t\t// when the schema has keywords: [\"keyword context\"]\r\n\t\t\t\t\t\t\tfor (const key of Object.keys(jsonItem)) {\r\n\t\t\t\t\t\t\t\tif (typeof jsonItem[key] === \"string\") {\r\n\t\t\t\t\t\t\t\t\taddTranslation(\r\n\t\t\t\t\t\t\t\t\t\tjsonItem[key],\r\n\t\t\t\t\t\t\t\t\t\tschemaTemplate,\r\n\t\t\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Adds a translation to the translations array\r\n\t\t * @param {string} msgctxt - The context of the text to be translated\r\n\t\t * @param {string} msgid - The text to be translated\r\n\t\t * @param {string} filename - The name of the file for references\r\n\t\t * @param {boolean} addReferences - Whether to add references\r\n\t\t */\r\n\t\tfunction addTranslation(msgctxt, msgid, filename, addReferences) {\r\n\t\t\tif (!msgctxt) return; // Do not add empty strings\r\n\r\n\t\t\tconst translation = {\r\n\t\t\t\tmsgid,\r\n\t\t\t\tmsgctxt,\r\n\t\t\t} as Block;\r\n\r\n\t\t\tif (addReferences) {\r\n\t\t\t\ttranslation.comments = {\r\n\t\t\t\t\treference: [filename],\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\ttranslations.push(translation);\r\n\t\t}\r\n\r\n\t\t// Start extraction from the root\r\n\t\textract(json, schema);\r\n\r\n\t\treturn translations;\r\n\t}\r\n}\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,gBAA2B;AAE3B,gBAA2B;AAMpB,MAAM,oBAAoB;AAAA,EAChC,OAAe,cAA6C,CAAC;AAAA;AAAA,EAG7D,OAAO,kBACN;AAAA,EACD,OAAO,oBAAoB;AAAA;AAAA,EAE3B,OAAO,kBACN;AAAA,EACD,OAAO,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3B,aAAqB,WACpB,KACA,UACsB;AACtB,QAAI,oBAAoB,YAAY,GAAG,GAAG;AACzC,aAAO,oBAAoB,YAAY,GAAG;AAAA,IAC3C;AAEA,QAAI;AACH,cAAQ,IAAI;AAAA,0BAA6B,GAAG,EAAE;AAC9C,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QACjC,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,SAAS;AAAA,UACR,+BAA+B;AAAA,QAChC;AAAA,MACD,CAAC,EACC,KAAK,CAACA,cAAaA,UAAS,KAAK,CAAC,EAClC,MAAM,CAAC,UAAiB;AACxB,cAAM,IAAI;AAAA,UACT;AAAA,6BAAgC,GAAG,YAAY,MAAM,OAAO;AAAA,QAC7D;AAAA,MACD,CAAC;AAGF,UAAI,CAAC,UAAU;AACd,eAAO;AAAA,MACR;AAEA,cAAQ,IAAI,4BAA4B;AACxC,0BAAoB,YAAY,GAAG,IAAI;AACvC,aAAO;AAAA,IACR,SAAS,OAAO;AACf,cAAQ;AAAA,QACP;AAAA,6BAAgC,GAAG,4BAA4B,MAAM,OAAO;AAAA,MAC7E;AACA,0BAAoB,YAAY,GAAG,IAAI;AACvC,aAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,aAAoB,MACnB,MACA,QAIA,SAI+B;AAC/B,UAAM,eAAe,MAAM,oBAAoB;AAAA,MAC9C,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAEA,QAAI;AACH,YAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,UAAI,CAAC,MAAM;AACV,gBAAQ,MAAM,uBAAuB;AACrC;AAAA,MACD;AAEA,aAAO,oBAAoB;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,SAAS,OAAO;AACf,cAAQ,MAAM,uBAAuB,MAAM,OAAO,EAAE;AACpD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAe,sBACd,MACA,QACA,UAA0D;AAAA,IACzD,UAAU;AAAA,IACV,eAAe;AAAA,EAChB,GACsB;AACtB,UAAM,EAAE,WAAW,cAAc,gBAAgB,MAAM,IAAI;AAC3D,UAAM,eAAe,CAAC;AAQtB,aAAS,QAAQ,aAAa,eAAe,OAAO,CAAC,GAAG;AAEvD,UAAI,CAAC,eAAe,CAAC,cAAe;AAGpC,UACC,OAAO,gBAAgB,YACvB,CAAC,MAAM,QAAQ,WAAW,KAC1B,OAAO,kBAAkB,YACzB,CAAC,MAAM,QAAQ,aAAa,GAC3B;AAED,mBAAW,OAAO,OAAO,KAAK,aAAa,GAAG;AAC7C,cAAI,OAAO,aAAa;AAEvB,gBAAI,OAAO,YAAY,GAAG,MAAM,UAAU;AAEzC;AAAA,gBACC,YAAY,GAAG;AAAA,gBACf,cAAc,GAAG;AAAA,gBACjB;AAAA,gBACA;AAAA,cACD;AAAA,YACD,WACC,MAAM,QAAQ,YAAY,GAAG,CAAC,KAC9B,MAAM,QAAQ,cAAc,GAAG,CAAC,GAC/B;AAED;AAAA,gBACC,YAAY,GAAG;AAAA,gBACf,cAAc,GAAG;AAAA,gBACjB,CAAC,GAAG,MAAM,GAAG;AAAA,gBACb;AAAA,gBACA;AAAA,cACD;AAAA,YACD,WACC,OAAO,YAAY,GAAG,MAAM,YAC5B,OAAO,cAAc,GAAG,MAAM,UAC7B;AAED,sBAAQ,YAAY,GAAG,GAAG,cAAc,GAAG,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,YAC7D;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAUA,aAAS,aACR,WACA,aACA,MACAC,WACAC,gBACC;AAED,UAAI,YAAY,SAAS,GAAG;AAC3B,cAAM,iBAAiB,YAAY,CAAC;AAGpC,mBAAW,YAAY,WAAW;AACjC,cAAI,OAAO,aAAa,UAAU;AAEjC,2BAAe,UAAU,gBAAgBD,WAAUC,cAAa;AAAA,UACjE,WAAW,OAAO,aAAa,UAAU;AAExC,gBAAI,OAAO,mBAAmB,UAAU;AACvC,sBAAQ,UAAU,gBAAgB,IAAI;AAAA,YACvC,OAAO;AAGN,yBAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACxC,oBAAI,OAAO,SAAS,GAAG,MAAM,UAAU;AACtC;AAAA,oBACC,SAAS,GAAG;AAAA,oBACZ;AAAA,oBACAD;AAAA,oBACAC;AAAA,kBACD;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AASA,aAAS,eAAe,SAAS,OAAOD,WAAUC,gBAAe;AAChE,UAAI,CAAC,QAAS;AAEd,YAAM,cAAc;AAAA,QACnB;AAAA,QACA;AAAA,MACD;AAEA,UAAIA,gBAAe;AAClB,oBAAY,WAAW;AAAA,UACtB,WAAW,CAACD,SAAQ;AAAA,QACrB;AAAA,MACD;AAEA,mBAAa,KAAK,WAAW;AAAA,IAC9B;AAGA,YAAQ,MAAM,MAAM;AAEpB,WAAO;AAAA,EACR;AACD;",
4
+ "sourcesContent": ["import type { Block } from \"gettext-merger\";\r\nimport * as blocki18n from \"../assets/block-i18n.js\";\r\nimport * as themei18n from \"../assets/theme-i18n.js\";\r\nimport type { I18nSchema } from \"../types.js\";\r\n\r\n/**\r\n * Extracts strings from JSON files using the I18n schema.\r\n */\r\n// biome-ignore lint/complexity/noStaticOnlyClass: <ATM it's fine in that way>\r\nexport class JsonSchemaExtractor {\r\n\tprivate static schemaCache: { [url: string]: I18nSchema } = {};\r\n\r\n\t/** Theme */\r\n\tstatic themeJsonSource =\r\n\t\t\"http://develop.svn.wordpress.org/trunk/src/wp-includes/theme-i18n.json\";\r\n\tstatic themeJsonFallback = themei18n;\r\n\t/** Block */\r\n\tstatic blockJsonSource =\r\n\t\t\"http://develop.svn.wordpress.org/trunk/src/wp-includes/block-i18n.json\";\r\n\tstatic blockJsonFallback = blocki18n;\r\n\r\n\t/**\r\n\t * Load the schema from the specified URL, with a fallback URL if needed.\r\n\t *\r\n\t * @param {string} url - The URL to load the schema from.\r\n\t * @param {I18nSchema} fallback - The fallback schema to use if the main URL fails.\r\n\t * @return {Promise<I18nSchema>} The loaded schema.\r\n\t */\r\n\tprivate static async loadSchema(\r\n\t\turl: string,\r\n\t\tfallback: I18nSchema,\r\n\t): Promise<I18nSchema> {\r\n\t\tif (JsonSchemaExtractor.schemaCache[url]) {\r\n\t\t\treturn JsonSchemaExtractor.schemaCache[url];\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst response = await fetch(url, {\r\n\t\t\t\theaders: {\r\n\t\t\t\t\t\"Access-Control-Allow-Origin\": \"*\",\r\n\t\t\t\t},\r\n\t\t\t})\r\n\t\t\t\t.then((response) => response.json())\r\n\t\t\t\t.catch((error: Error) => {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t`\\nFailed to load schema from ${url}. Error: ${error.message}`,\r\n\t\t\t\t\t);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Verify if the response is valid\r\n\t\t\tif (!response) {\r\n\t\t\t\treturn fallback;\r\n\t\t\t}\r\n\r\n\t\t\tJsonSchemaExtractor.schemaCache[url] = response;\r\n\t\t\treturn response;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t`\\nFailed to load schema from ${url}. Using fallback. Error: ${(error as Error).message}`,\r\n\t\t\t);\r\n\t\t\tJsonSchemaExtractor.schemaCache[url] = fallback;\r\n\t\t\treturn fallback;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Parses a string and extracts translations using the specified schema.\r\n\t *\r\n\t * @param {string} text - the input string to be parsed\r\n\t * @param {object} schema - the schema to use for parsing the input string\r\n\t * @param {string} schema.url - the URL of the schema to use for parsing the input string\r\n\t * @param {object} schema.schemaFallback - the fallback schema to use if the main schema fails\r\n\t * @param {object} options - the options for parsing the input string\r\n\t * @param {string} options.file - the name of the file being parsed\r\n\t * @param {boolean} options.addReferences - whether to add references to the extracted strings\r\n\t *\r\n\t * @return {Promise<I18nSchema | undefined>} a promise that resolves with the extracted schema\r\n\t */\r\n\tpublic static async parse(\r\n\t\ttext: string,\r\n\t\tschema: {\r\n\t\t\turl: string;\r\n\t\t\tfallback: I18nSchema;\r\n\t\t},\r\n\t\toptions: {\r\n\t\t\tfile: \"block.json\" | \"theme.json\";\r\n\t\t\taddReferences: boolean;\r\n\t\t},\r\n\t): Promise<Block[] | undefined> {\r\n\t\tconst parsedSchema = await JsonSchemaExtractor.loadSchema(\r\n\t\t\tschema.url,\r\n\t\t\tschema.fallback,\r\n\t\t);\r\n\r\n\t\ttry {\r\n\t\t\tconst json = JSON.parse(text) as Record<string, unknown>;\r\n\t\t\tif (!json) {\r\n\t\t\t\tconsole.error(\"Could not parse JSON.\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\treturn JsonSchemaExtractor.extractFromJsonSchema(\r\n\t\t\t\tjson,\r\n\t\t\t\tparsedSchema,\r\n\t\t\t\toptions,\r\n\t\t\t);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(`Error parsing JSON: ${(error as Error).message}`);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Extracts translatable strings from a JSON file by comparing it with a schema\r\n\t *\r\n\t * @param {Object} json - The JSON object to extract strings from\r\n\t * @param {Object} schema - The schema that defines which fields contain translatable strings\r\n\t * @param {Object} options - Options for extraction\r\n\t * @param {string} options.filename - The name of the file being extracted (for references)\r\n\t * @param {boolean} options.addReferences - Whether to add file references in comments\r\n\t * @return {Array} - An array of objects with translatable strings in gettext format\r\n\t */\r\n\tprivate static extractFromJsonSchema(\r\n\t\tjson: Record<string, unknown>,\r\n\t\tschema: I18nSchema,\r\n\t\toptions: { filename?: string; addReferences?: boolean } = {\r\n\t\t\tfilename: undefined,\r\n\t\t\taddReferences: false,\r\n\t\t},\r\n\t): Block[] | undefined {\r\n\t\tconst { filename = \"block.json\", addReferences = false } = options;\r\n\t\tconst translations: Block[] = [];\r\n\r\n\t\t/**\r\n\t\t * Recursive function to extract translatable strings\r\n\t\t * @param {*} currentJson - The current node in the JSON\r\n\t\t * @param {*} currentSchema - The current node in the schema\r\n\t\t * @param {Array} path - The current path in the JSON\r\n\t\t */\r\n\t\tfunction extract(\r\n\t\t\tcurrentJson: Record<string, unknown>,\r\n\t\t\tcurrentSchema: I18nSchema,\r\n\t\t\tpath: string[] = [],\r\n\t\t) {\r\n\t\t\t// If either is null or undefined, there's nothing to do\r\n\t\t\tif (!currentJson || !currentSchema) return;\r\n\r\n\t\t\t// Handles the case where both are objects\r\n\t\t\tif (\r\n\t\t\t\ttypeof currentJson === \"object\" &&\r\n\t\t\t\t!Array.isArray(currentJson) &&\r\n\t\t\t\ttypeof currentSchema === \"object\" &&\r\n\t\t\t\t!Array.isArray(currentSchema)\r\n\t\t\t) {\r\n\t\t\t\t// Iterate over the schema keys\r\n\t\t\t\tfor (const key of Object.keys(currentSchema)) {\r\n\t\t\t\t\tif (key in currentJson) {\r\n\t\t\t\t\t\t// If the key exists in the JSON, check the type\r\n\t\t\t\t\t\tif (typeof currentJson[key] === \"string\") {\r\n\t\t\t\t\t\t\t// It's a string - add it to translations\r\n\t\t\t\t\t\t\taddTranslation(\r\n\t\t\t\t\t\t\t\tcurrentJson[key],\r\n\t\t\t\t\t\t\t\tcurrentSchema[key] as string,\r\n\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} else if (\r\n\t\t\t\t\t\t\tArray.isArray(currentJson[key]) &&\r\n\t\t\t\t\t\t\tArray.isArray(currentSchema[key])\r\n\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t// It's an array - handle each element\r\n\t\t\t\t\t\t\thandleArrays(\r\n\t\t\t\t\t\t\t\tcurrentJson[key],\r\n\t\t\t\t\t\t\t\tcurrentSchema[key],\r\n\t\t\t\t\t\t\t\t[...path, key],\r\n\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} else if (\r\n\t\t\t\t\t\t\ttypeof currentJson[key] === \"object\" &&\r\n\t\t\t\t\t\t\tcurrentJson[key] !== null &&\r\n\t\t\t\t\t\t\ttypeof currentSchema[key] === \"object\"\r\n\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t// It's an object - recurse\r\n\t\t\t\t\t\t\textract(\r\n\t\t\t\t\t\t\t\tcurrentJson[key] as Record<string, unknown>,\r\n\t\t\t\t\t\t\t\tcurrentSchema[key] as I18nSchema,\r\n\t\t\t\t\t\t\t\t[...path, key],\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Handles arrays in JSON and schema\r\n\t\t * @param {unknown[]} jsonArray - The JSON array\r\n\t\t * @param {string[] | I18nSchema[]} schemaArray - The schema array\r\n\t\t * @param {string[]} path - The current path\r\n\t\t * @param {string} filename - The name of the file\r\n\t\t * @param {boolean} addReferences - whenever to add references\r\n\t\t */\r\n\t\tfunction handleArrays(\r\n\t\t\tjsonArray: unknown[],\r\n\t\t\tschemaArray: string[] | I18nSchema[],\r\n\t\t\tpath: string[],\r\n\t\t\tfilename: string,\r\n\t\t\taddReferences: boolean,\r\n\t\t) {\r\n\t\t\t// If the schema has at least one element, use it as a template\r\n\t\t\tif (schemaArray.length > 0) {\r\n\t\t\t\tconst schemaTemplate = schemaArray[0];\r\n\r\n\t\t\t\t// For each element in the JSON array\r\n\t\t\t\tfor (const jsonItem of jsonArray) {\r\n\t\t\t\t\tif (typeof jsonItem === \"string\") {\r\n\t\t\t\t\t\t// If the JSON element is a string, add it directly\r\n\t\t\t\t\t\taddTranslation(\r\n\t\t\t\t\t\t\tjsonItem,\r\n\t\t\t\t\t\t\tschemaTemplate as string,\r\n\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else if (typeof jsonItem === \"object\" && jsonItem !== null) {\r\n\t\t\t\t\t\t// If it's an object, recurse\r\n\t\t\t\t\t\tif (typeof schemaTemplate === \"object\") {\r\n\t\t\t\t\t\t\textract(\r\n\t\t\t\t\t\t\t\tjsonItem as Record<string, unknown>,\r\n\t\t\t\t\t\t\t\tschemaTemplate as I18nSchema,\r\n\t\t\t\t\t\t\t\tpath,\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t// Edge case: handles cases like keywords: [\"string1\", \"string2\"]\r\n\t\t\t\t\t\t\t// when the schema has keywords: [\"keyword context\"]\r\n\t\t\t\t\t\t\tfor (const key of Object.keys(jsonItem)) {\r\n\t\t\t\t\t\t\t\t// Type guard to ensure we are accessing a string\r\n\t\t\t\t\t\t\t\tconst value = (jsonItem as Record<string, unknown>)[key];\r\n\t\t\t\t\t\t\t\tif (typeof value === \"string\") {\r\n\t\t\t\t\t\t\t\t\taddTranslation(\r\n\t\t\t\t\t\t\t\t\t\tvalue,\r\n\t\t\t\t\t\t\t\t\t\tschemaTemplate as string,\r\n\t\t\t\t\t\t\t\t\t\tfilename,\r\n\t\t\t\t\t\t\t\t\t\taddReferences,\r\n\t\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Adds a translation to the translations array\r\n\t\t * @param {string} msgctxt - The context of the text to be translated\r\n\t\t * @param {string} msgid - The text to be translated\r\n\t\t * @param {string} filename - The name of the file for references\r\n\t\t * @param {boolean} addReferences - Whether to add references\r\n\t\t */\r\n\t\tfunction addTranslation(msgctxt: string, msgid: string, filename: string, addReferences: boolean) {\r\n\t\t\tif (!msgctxt) return; // Do not add empty strings\r\n\r\n\t\t\tconst translation = {\r\n\t\t\t\tmsgid,\r\n\t\t\t\tmsgctxt,\r\n\t\t\t} as Block;\r\n\r\n\t\t\tif (addReferences) {\r\n\t\t\t\ttranslation.comments = {\r\n\t\t\t\t\treference: [filename],\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\ttranslations.push(translation);\r\n\t\t}\r\n\r\n\t\t// Start extraction from the root\r\n\t\textract(json, schema);\r\n\r\n\t\treturn translations;\r\n\t}\r\n}\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["response", "filename", "addReferences"]
7
7
  }
package/lib/fs/fs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var l=Object.create;var i=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var y=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of m(t))!x.call(e,r)&&r!==n&&i(e,r,{get:()=>t[r],enumerable:!(o=p(t,r))||o.enumerable});return e};var f=(e,t,n)=>(n=e!=null?l(F(e)):{},u(t||!e||!e.__esModule?i(n,"default",{value:e,enumerable:!0}):n,e)),w=e=>u(i({},"__esModule",{value:!0}),e);var j={};y(j,{getCharset:()=>d,getEncodingCharset:()=>$,readFileAsync:()=>S,writeFile:()=>C});module.exports=w(j);var s=f(require("node:fs")),a=require("node:fs/promises"),c=f(require("node:path"));function E(e){if(e===void 0)return".";try{s.default.accessSync(c.default.resolve(e),s.default.constants.R_OK|s.default.constants.W_OK)}catch(t){if(t.code==="ENOENT")return s.default.mkdirSync(e,{recursive:!0}),console.log(`Folder created: ${e}`),e}return e}function d(e){if(!e)return"latin1";switch(e.toLowerCase()){case"utf-8":case"utf8":return"utf-8";default:return"latin1"}}function $(e){if(!e)return"iso-8859-1";switch(e.toLowerCase()){case"utf-8":case"utf8":return"utf-8";default:return"iso-8859-1"}}function h(e){const{out:t,headers:n,options:o}=e.paths;let r=t??n?.domainPath??"languages";r=r.replace(/^\/+|\/+$/g,"");const g=o?.json?"json":"pot";return c.default.join(process.cwd(),r,`${e.slug}.${g}`)}function C(e,t){const n=h(t);if(E(c.default.dirname(n))){const o=d(t.options?.charset);console.log(`
2
- Pot File created at ${n}`);const r=Buffer.from(e);(0,s.writeFileSync)(n,r.toString(o),{encoding:o})}else console.log(`Folder ${n} does not exist and cannot be created`)}async function S(e){return(0,a.readFile)(e,"utf-8")}0&&(module.exports={getCharset,getEncodingCharset,readFileAsync,writeFile});
1
+ "use strict";var p=Object.create;var i=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,y=Object.prototype.hasOwnProperty;var w=(t,e)=>{for(var n in e)i(t,n,{get:e[n],enumerable:!0})},f=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of F(e))!y.call(t,r)&&r!==n&&i(t,r,{get:()=>e[r],enumerable:!(o=m(e,r))||o.enumerable});return t};var a=(t,e,n)=>(n=t!=null?p(x(t)):{},f(e||!t||!t.__esModule?i(n,"default",{value:t,enumerable:!0}):n,t)),E=t=>f(i({},"__esModule",{value:!0}),t);var A={};w(A,{getCharset:()=>g,getEncodingCharset:()=>h,readFileAsync:()=>j,writeFile:()=>S});module.exports=E(A);var s=a(require("node:fs")),d=require("node:fs/promises"),c=a(require("node:path"));function $(t){if(t===void 0)return".";try{s.default.accessSync(c.default.resolve(t),s.default.constants.R_OK|s.default.constants.W_OK)}catch(e){if(e.code==="ENOENT")return s.default.mkdirSync(t,{recursive:!0}),console.log(`Folder created: ${t}`),t}return t}function g(t){if(!t)return"latin1";switch(t.toLowerCase()){case"utf-8":case"utf8":return"utf-8";default:return"latin1"}}function h(t){if(!t)return"iso-8859-1";switch(t.toLowerCase()){case"utf-8":case"utf8":return"utf-8";default:return"iso-8859-1"}}function C(t){const{paths:e,headers:n,options:o}=t;let u=e.out??n?.domainPath??"languages";u=u.replace(/^\/+|\/+$/g,"");const l=o?.json?"json":"pot";return c.default.join(process.cwd(),u,`${t.slug}.${l}`)}function S(t,e){const n=C(e);if($(c.default.dirname(n))){const o=g(e.options?.charset);console.log(`
2
+ Pot File created at ${n}`);const r=Buffer.from(t);(0,s.writeFileSync)(n,r.toString(o),{encoding:o})}else console.log(`Folder ${n} does not exist and cannot be created`)}async function j(t){return(0,d.readFile)(t,"utf-8")}0&&(module.exports={getCharset,getEncodingCharset,readFileAsync,writeFile});
package/lib/fs/fs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/fs/fs.ts"],
4
- "sourcesContent": ["import fs, { writeFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Args } from \"../types.js\";\n\n/**\n * Ensures that a folder exists at the specified path.\n *\n * @param {string | undefined} folderPath - The path of the folder to ensure existence for.\n * @return {string} - The path of the folder, or '.' if folderPath is undefined.\n */\nfunction ensureFolderExists(folderPath: string | undefined): string {\n\tif (folderPath === undefined) {\n\t\treturn \".\";\n\t}\n\ttry {\n\t\t// Check if the folder exists\n\t\tfs.accessSync(\n\t\t\tpath.resolve(folderPath),\n\t\t\tfs.constants.R_OK | fs.constants.W_OK,\n\t\t);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\t// The Folder does not exist, so create it\n\t\t\tfs.mkdirSync(folderPath, { recursive: true });\n\t\t\tconsole.log(`Folder created: ${folderPath}`);\n\t\t\treturn folderPath;\n\t\t}\n\t}\n\treturn folderPath;\n}\n\n/**\n * Gets the charset of the .pot file\n *\n * @param charset the charset of the .pot file\n * @return the charset of the .pot file\n */\nexport function getCharset(charset: string | undefined): BufferEncoding {\n\tif (!charset) {\n\t\treturn \"latin1\";\n\t}\n\t// we need to check if the charset is valid otherwise we return latin1 that is a common alias for ISO-8859-1 and the default charset for pot files\n\tswitch (charset.toLowerCase()) {\n\t\tcase \"utf-8\":\n\t\tcase \"utf8\":\n\t\t\treturn \"utf-8\";\n\t\tdefault:\n\t\t\treturn \"latin1\";\n\t}\n}\n\nexport function getEncodingCharset(charset: string | undefined): string {\n\tif (!charset) {\n\t\treturn \"iso-8859-1\";\n\t}\n\t// we need to check if the charset is valid otherwise we return utf-8 that is a common alias for ISO-8859-1 and the default charset for pot files\n\tswitch (charset.toLowerCase()) {\n\t\tcase \"utf-8\":\n\t\tcase \"utf8\":\n\t\t\treturn \"utf-8\";\n\t\tdefault:\n\t\t\treturn \"iso-8859-1\";\n\t}\n}\n\n/**\n * The output path for the pot file.\n * @param args - the command line arguments\n */\nfunction getOutputFilePath(args: Args): string {\n\tconst { out, headers, options } = args.paths;\n\tlet i18nFolder = out ?? headers?.domainPath ?? \"languages\";\n\n\t// Remove leading and trailing slashes\n\ti18nFolder = i18nFolder.replace(/^\\/+|\\/+$/g, \"\");\n\n\tconst extension = options?.json ? \"json\" : \"pot\";\n\n\treturn path.join(process.cwd(), i18nFolder, `${args.slug}.${extension}`);\n}\n\n/**\n * Writes the .pot file to disk\n *\n * @param fileContent the content of the .pot file\n * @param args the command line arguments passed to the program\n */\nexport function writeFile(fileContent: string, args: Args): void {\n\tconst dest = getOutputFilePath(args);\n\n\tif (ensureFolderExists(path.dirname(dest))) {\n\t\t// get the encoding charset\n\t\tconst encodingCharset = getCharset(args.options?.charset);\n\t\tconsole.log(`\\nPot File created at ${dest}`);\n\n\t\t// write the file\n\t\tconst potBuffer = Buffer.from(fileContent);\n\t\twriteFileSync(dest, potBuffer.toString(encodingCharset), {\n\t\t\tencoding: encodingCharset,\n\t\t});\n\t} else {\n\t\tconsole.log(`Folder ${dest} does not exist and cannot be created`);\n\t}\n}\n\n/**\n * The async version of fs.readFile method\n * @param path the path of the file to read\n * @return the content of the file as a string\n */\nexport async function readFileAsync(path: string): Promise<string> {\n\treturn readFile(path, \"utf-8\");\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAkC;AAClC,sBAAyB;AACzB,uBAAiB;AASjB,SAAS,mBAAmB,YAAwC;AACnE,MAAI,eAAe,QAAW;AAC7B,WAAO;AAAA,EACR;AACA,MAAI;AAEH,mBAAAA,QAAG;AAAA,MACF,iBAAAC,QAAK,QAAQ,UAAU;AAAA,MACvB,eAAAD,QAAG,UAAU,OAAO,eAAAA,QAAG,UAAU;AAAA,IAClC;AAAA,EACD,SAAS,OAAO;AACf,QAAK,MAAgC,SAAS,UAAU;AAEvD,qBAAAA,QAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,cAAQ,IAAI,mBAAmB,UAAU,EAAE;AAC3C,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;AAQO,SAAS,WAAW,SAA6C;AACvE,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,EACR;AAEA,UAAQ,QAAQ,YAAY,GAAG;AAAA,IAC9B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAEO,SAAS,mBAAmB,SAAqC;AACvE,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,EACR;AAEA,UAAQ,QAAQ,YAAY,GAAG;AAAA,IAC9B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAMA,SAAS,kBAAkB,MAAoB;AAC9C,QAAM,EAAE,KAAK,SAAS,QAAQ,IAAI,KAAK;AACvC,MAAI,aAAa,OAAO,SAAS,cAAc;AAG/C,eAAa,WAAW,QAAQ,cAAc,EAAE;AAEhD,QAAM,YAAY,SAAS,OAAO,SAAS;AAE3C,SAAO,iBAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,GAAG,KAAK,IAAI,IAAI,SAAS,EAAE;AACxE;AAQO,SAAS,UAAU,aAAqB,MAAkB;AAChE,QAAM,OAAO,kBAAkB,IAAI;AAEnC,MAAI,mBAAmB,iBAAAA,QAAK,QAAQ,IAAI,CAAC,GAAG;AAE3C,UAAM,kBAAkB,WAAW,KAAK,SAAS,OAAO;AACxD,YAAQ,IAAI;AAAA,sBAAyB,IAAI,EAAE;AAG3C,UAAM,YAAY,OAAO,KAAK,WAAW;AACzC,sCAAc,MAAM,UAAU,SAAS,eAAe,GAAG;AAAA,MACxD,UAAU;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AACN,YAAQ,IAAI,UAAU,IAAI,uCAAuC;AAAA,EAClE;AACD;AAOA,eAAsB,cAAcA,OAA+B;AAClE,aAAO,0BAASA,OAAM,OAAO;AAC9B;",
4
+ "sourcesContent": ["import fs, { writeFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Args } from \"../types.js\";\n\n/**\n * Ensures that a folder exists at the specified path.\n *\n * @param {string | undefined} folderPath - The path of the folder to ensure existence for.\n * @return {string} - The path of the folder, or '.' if folderPath is undefined.\n */\nfunction ensureFolderExists(folderPath: string | undefined): string {\n\tif (folderPath === undefined) {\n\t\treturn \".\";\n\t}\n\ttry {\n\t\t// Check if the folder exists\n\t\tfs.accessSync(\n\t\t\tpath.resolve(folderPath),\n\t\t\tfs.constants.R_OK | fs.constants.W_OK,\n\t\t);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\t// The Folder does not exist, so create it\n\t\t\tfs.mkdirSync(folderPath, { recursive: true });\n\t\t\tconsole.log(`Folder created: ${folderPath}`);\n\t\t\treturn folderPath;\n\t\t}\n\t}\n\treturn folderPath;\n}\n\n/**\n * Gets the charset of the .pot file\n *\n * @param charset the charset of the .pot file\n * @return the charset of the .pot file\n */\nexport function getCharset(charset: string | undefined): BufferEncoding {\n\tif (!charset) {\n\t\treturn \"latin1\";\n\t}\n\t// we need to check if the charset is valid otherwise we return latin1 that is a common alias for ISO-8859-1 and the default charset for pot files\n\tswitch (charset.toLowerCase()) {\n\t\tcase \"utf-8\":\n\t\tcase \"utf8\":\n\t\t\treturn \"utf-8\";\n\t\tdefault:\n\t\t\treturn \"latin1\";\n\t}\n}\n\nexport function getEncodingCharset(charset: string | undefined): string {\n\tif (!charset) {\n\t\treturn \"iso-8859-1\";\n\t}\n\t// we need to check if the charset is valid otherwise we return utf-8 that is a common alias for ISO-8859-1 and the default charset for pot files\n\tswitch (charset.toLowerCase()) {\n\t\tcase \"utf-8\":\n\t\tcase \"utf8\":\n\t\t\treturn \"utf-8\";\n\t\tdefault:\n\t\t\treturn \"iso-8859-1\";\n\t}\n}\n\n/**\n * The output path for the pot file.\n * @param args - the command line arguments\n */\nfunction getOutputFilePath(args: Args): string {\n\tconst { paths, headers, options } = args;\n\tconst out = paths.out\n\tlet i18nFolder = out ?? headers?.domainPath ?? \"languages\";\n\n\t// Remove leading and trailing slashes\n\ti18nFolder = i18nFolder.replace(/^\\/+|\\/+$/g, \"\");\n\n\tconst extension = options?.json ? \"json\" : \"pot\";\n\n\treturn path.join(process.cwd(), i18nFolder, `${args.slug}.${extension}`);\n}\n\n/**\n * Writes the .pot file to disk\n *\n * @param fileContent the content of the .pot file\n * @param args the command line arguments passed to the program\n */\nexport function writeFile(fileContent: string, args: Args): void {\n\tconst dest = getOutputFilePath(args);\n\n\tif (ensureFolderExists(path.dirname(dest))) {\n\t\t// get the encoding charset\n\t\tconst encodingCharset = getCharset(args.options?.charset);\n\t\tconsole.log(`\\nPot File created at ${dest}`);\n\n\t\t// write the file\n\t\tconst potBuffer = Buffer.from(fileContent);\n\t\twriteFileSync(dest, potBuffer.toString(encodingCharset), {\n\t\t\tencoding: encodingCharset,\n\t\t});\n\t} else {\n\t\tconsole.log(`Folder ${dest} does not exist and cannot be created`);\n\t}\n}\n\n/**\n * The async version of fs.readFile method\n * @param path the path of the file to read\n * @return the content of the file as a string\n */\nexport async function readFileAsync(path: string): Promise<string> {\n\treturn readFile(path, \"utf-8\");\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAkC;AAClC,sBAAyB;AACzB,uBAAiB;AASjB,SAAS,mBAAmB,YAAwC;AACnE,MAAI,eAAe,QAAW;AAC7B,WAAO;AAAA,EACR;AACA,MAAI;AAEH,mBAAAA,QAAG;AAAA,MACF,iBAAAC,QAAK,QAAQ,UAAU;AAAA,MACvB,eAAAD,QAAG,UAAU,OAAO,eAAAA,QAAG,UAAU;AAAA,IAClC;AAAA,EACD,SAAS,OAAO;AACf,QAAK,MAAgC,SAAS,UAAU;AAEvD,qBAAAA,QAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,cAAQ,IAAI,mBAAmB,UAAU,EAAE;AAC3C,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;AAQO,SAAS,WAAW,SAA6C;AACvE,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,EACR;AAEA,UAAQ,QAAQ,YAAY,GAAG;AAAA,IAC9B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAEO,SAAS,mBAAmB,SAAqC;AACvE,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,EACR;AAEA,UAAQ,QAAQ,YAAY,GAAG;AAAA,IAC9B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAMA,SAAS,kBAAkB,MAAoB;AAC9C,QAAM,EAAE,OAAO,SAAS,QAAQ,IAAI;AACpC,QAAM,MAAM,MAAM;AAClB,MAAI,aAAa,OAAO,SAAS,cAAc;AAG/C,eAAa,WAAW,QAAQ,cAAc,EAAE;AAEhD,QAAM,YAAY,SAAS,OAAO,SAAS;AAE3C,SAAO,iBAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,GAAG,KAAK,IAAI,IAAI,SAAS,EAAE;AACxE;AAQO,SAAS,UAAU,aAAqB,MAAkB;AAChE,QAAM,OAAO,kBAAkB,IAAI;AAEnC,MAAI,mBAAmB,iBAAAA,QAAK,QAAQ,IAAI,CAAC,GAAG;AAE3C,UAAM,kBAAkB,WAAW,KAAK,SAAS,OAAO;AACxD,YAAQ,IAAI;AAAA,sBAAyB,IAAI,EAAE;AAG3C,UAAM,YAAY,OAAO,KAAK,WAAW;AACzC,sCAAc,MAAM,UAAU,SAAS,eAAe,GAAG;AAAA,MACxD,UAAU;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AACN,YAAQ,IAAI,UAAU,IAAI,uCAAuC;AAAA,EAClE;AACD;AAOA,eAAsB,cAAcA,OAA+B;AAClE,aAAO,0BAASA,OAAM,OAAO;AAC9B;",
6
6
  "names": ["fs", "path"]
7
7
  }
package/lib/fs/glob.js CHANGED
@@ -1 +1 @@
1
- "use strict";var f=Object.create;var s=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,j=Object.prototype.hasOwnProperty;var w=(t,e)=>{for(var r in e)s(t,r,{get:e[r],enumerable:!0})},p=(t,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of y(e))!j.call(t,n)&&n!==r&&s(t,n,{get:()=>e[n],enumerable:!(i=g(e,n))||i.enumerable});return t};var o=(t,e,r)=>(r=t!=null?f(x(t)):{},p(e||!t||!t.__esModule?s(r,"default",{value:t,enumerable:!0}):r,t)),P=t=>p(s({},"__esModule",{value:!0}),t);var A={};w(A,{getFiles:()=>F,getParser:()=>v,ignoreFunc:()=>d});module.exports=P(A);var u=o(require("node:path")),l=require("glob"),h=require("minimatch"),b=o(require("tree-sitter-javascript")),c=o(require("tree-sitter-php")),m=o(require("tree-sitter-typescript")),a=require("../utils/common.js");function v(t){switch((0,a.getFileExtension)(t)){case"ts":return m.typescript;case"tsx":return m.tsx;case"js":case"jsx":case"mjs":case"cjs":return b;case"php":return c.php;case"blade.php":return c.php_only;default:return null}}const d=(t,e)=>e.some(r=>{switch((0,a.detectPatternType)(r)){case"file":return t.isNamed(r);case"directory":return t.relative().includes(r);default:return(0,h.minimatch)(t.relative(),r)}});function F(t,e){return new l.Glob(e.include,{ignore:{ignored:r=>d(r,e.exclude)},nodir:!0,cwd:t.paths.cwd,root:t.paths.root?u.default.resolve(t.paths.root):void 0})}0&&(module.exports={getFiles,getParser,ignoreFunc});
1
+ "use strict";var d=Object.create;var o=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var w=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var j=(t,r)=>{for(var e in r)o(t,e,{get:r[e],enumerable:!0})},p=(t,r,e,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of y(r))!x.call(t,n)&&n!==e&&o(t,n,{get:()=>r[n],enumerable:!(s=f(r,n))||s.enumerable});return t};var a=(t,r,e)=>(e=t!=null?d(w(t)):{},p(r||!t||!t.__esModule?o(e,"default",{value:t,enumerable:!0}):e,t)),P=t=>p(o({},"__esModule",{value:!0}),t);var k={};j(k,{getFiles:()=>F,getParser:()=>v,ignoreFunc:()=>h});module.exports=P(k);var u=a(require("node:path")),l=require("glob"),g=require("minimatch"),b=a(require("tree-sitter-javascript")),c=a(require("tree-sitter-php")),m=a(require("tree-sitter-typescript")),i=require("../utils/common.js");function v(t){switch((0,i.getFileExtension)(t)){case"ts":return m.typescript;case"tsx":return m.tsx;case"js":case"jsx":case"mjs":case"cjs":return b;case"php":return c.php;case"blade.php":return c.php_only;default:return null}}const h=(t,r)=>r.some(e=>{switch((0,i.detectPatternType)(e)){case"file":return t.isNamed(e);case"directory":return t.relative().includes(e);default:return(0,g.minimatch)(t.relative(),e)}});async function F(t,r){return new l.Glob(r.include,{ignore:{ignored:s=>h(s,r.exclude)},nodir:!0,cwd:t.paths.cwd,root:t.paths.root?u.default.resolve(t.paths.root):void 0}).walk()}0&&(module.exports={getFiles,getParser,ignoreFunc});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/fs/glob.ts"],
4
- "sourcesContent": ["import path from \"node:path\";\r\nimport { Glob, type Path } from \"glob\";\r\nimport { minimatch } from \"minimatch\";\r\n// @ts-expect-error\r\nimport * as javascript from \"tree-sitter-javascript\";\r\n// @ts-expect-error\r\nimport * as php from \"tree-sitter-php\";\r\n// @ts-expect-error\r\nimport * as ts from \"tree-sitter-typescript\";\r\nimport type { Args, Patterns } from \"../types.js\";\r\nimport { detectPatternType, getFileExtension } from \"../utils/common.js\";\r\n\r\n/**\r\n * Return the parser based on the file extension\r\n *\r\n * @param file - Path to the file\r\n * @return {Parser|null} - the parser to be used with the file or null if no parser is found\r\n */\r\nexport function getParser(\r\n\tfile: string,\r\n): string | { name: string; language: unknown } | null {\r\n\tconst ext = getFileExtension(file);\r\n\tswitch (ext) {\r\n\t\tcase \"ts\":\r\n\t\t\treturn ts.typescript;\r\n\t\tcase \"tsx\":\r\n\t\t\treturn ts.tsx;\r\n\t\tcase \"js\":\r\n\t\tcase \"jsx\":\r\n\t\tcase \"mjs\":\r\n\t\tcase \"cjs\":\r\n\t\t\treturn javascript;\r\n\t\tcase \"php\":\r\n\t\t\treturn php.php;\r\n\t\tcase \"blade.php\":\r\n\t\t\treturn php.php_only;\r\n\t\tdefault:\r\n\t\t\treturn null;\r\n\t}\r\n}\r\n\r\n// Build the ignore function for Glob\r\nexport const ignoreFunc = (\r\n\tfilePath: Path,\r\n\texcludedPatterns: string[],\r\n): boolean => {\r\n\treturn excludedPatterns.some((exclude) => {\r\n\t\tconst type = detectPatternType(exclude);\r\n\t\t// return true to ignore\r\n\t\tswitch (type) {\r\n\t\t\tcase \"file\":\r\n\t\t\t\treturn filePath.isNamed(exclude);\r\n\t\t\tcase \"directory\":\r\n\t\t\t\treturn filePath.relative().includes(exclude);\r\n\t\t\tdefault:\r\n\t\t\t\t// Handle glob patterns using minimatch\r\n\t\t\t\treturn minimatch(filePath.relative(), exclude);\r\n\t\t}\r\n\t}) as boolean;\r\n};\r\n\r\n/**\r\n * Retrieves a list of files based on the provided arguments and patterns.\r\n *\r\n * @param {Args} args - The argument object containing the source directory and other options.\r\n * @param {Patterns} pattern - The pattern object containing the included and excluded file patterns.\r\n * @return A promise that resolves to an array of file paths.\r\n */\r\nexport function getFiles(args: Args, pattern: Patterns) {\r\n\t// Execute the glob search with the built patterns\r\n\treturn new Glob(pattern.include, {\r\n\t\tignore: {\r\n\t\t\tignored: (p: Path) => ignoreFunc(p, pattern.exclude),\r\n\t\t},\r\n\t\tnodir: true,\r\n\t\tcwd: args.paths.cwd,\r\n\t\troot: args.paths.root ? path.resolve(args.paths.root) : undefined,\r\n\t});\r\n}\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAiB;AACjB,kBAAgC;AAChC,uBAA0B;AAE1B,iBAA4B;AAE5B,UAAqB;AAErB,SAAoB;AAEpB,oBAAoD;AAQ7C,SAAS,UACf,MACsD;AACtD,QAAM,UAAM,gCAAiB,IAAI;AACjC,UAAQ,KAAK;AAAA,IACZ,KAAK;AACJ,aAAO,GAAG;AAAA,IACX,KAAK;AACJ,aAAO,GAAG;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,IAAI;AAAA,IACZ,KAAK;AACJ,aAAO,IAAI;AAAA,IACZ;AACC,aAAO;AAAA,EACT;AACD;AAGO,MAAM,aAAa,CACzB,UACA,qBACa;AACb,SAAO,iBAAiB,KAAK,CAAC,YAAY;AACzC,UAAM,WAAO,iCAAkB,OAAO;AAEtC,YAAQ,MAAM;AAAA,MACb,KAAK;AACJ,eAAO,SAAS,QAAQ,OAAO;AAAA,MAChC,KAAK;AACJ,eAAO,SAAS,SAAS,EAAE,SAAS,OAAO;AAAA,MAC5C;AAEC,mBAAO,4BAAU,SAAS,SAAS,GAAG,OAAO;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;AASO,SAAS,SAAS,MAAY,SAAmB;AAEvD,SAAO,IAAI,iBAAK,QAAQ,SAAS;AAAA,IAChC,QAAQ;AAAA,MACP,SAAS,CAAC,MAAY,WAAW,GAAG,QAAQ,OAAO;AAAA,IACpD;AAAA,IACA,OAAO;AAAA,IACP,KAAK,KAAK,MAAM;AAAA,IAChB,MAAM,KAAK,MAAM,OAAO,iBAAAA,QAAK,QAAQ,KAAK,MAAM,IAAI,IAAI;AAAA,EACzD,CAAC;AACF;",
4
+ "sourcesContent": ["import path from 'node:path'\r\nimport { Glob, type Path } from 'glob'\r\nimport { minimatch } from 'minimatch'\r\nimport * as javascript from 'tree-sitter-javascript'\r\n// @ts-expect-error\r\nimport * as php from 'tree-sitter-php'\r\n// @ts-expect-error\r\nimport * as ts from 'tree-sitter-typescript'\r\nimport type { Args, Patterns } from '../types.js'\r\nimport { detectPatternType, getFileExtension } from '../utils/common.js'\r\n\r\n/**\r\n * Return the parser based on the file extension\r\n *\r\n * @param file - Path to the file\r\n * @return {Parser|null} - the parser to be used with the file or null if no parser is found\r\n */\r\nexport function getParser(\r\n\tfile: string,\r\n): string | { name: string; language: unknown } | null {\r\n\tconst ext = getFileExtension(file);\r\n\tswitch (ext) {\r\n\t\tcase \"ts\":\r\n\t\t\treturn ts.typescript;\r\n\t\tcase \"tsx\":\r\n\t\t\treturn ts.tsx;\r\n\t\tcase \"js\":\r\n\t\tcase \"jsx\":\r\n\t\tcase \"mjs\":\r\n\t\tcase \"cjs\":\r\n\t\t\treturn javascript;\r\n\t\tcase \"php\":\r\n\t\t\treturn php.php;\r\n\t\tcase \"blade.php\":\r\n\t\t\treturn php.php_only;\r\n\t\tdefault:\r\n\t\t\treturn null;\r\n\t}\r\n}\r\n\r\n// Build the ignore function for Glob\r\nexport const ignoreFunc = (\r\n\tfilePath: Path,\r\n\texcludedPatterns: string[],\r\n): boolean => {\r\n\treturn excludedPatterns.some((exclude) => {\r\n\t\tconst type = detectPatternType(exclude);\r\n\t\t// return true to ignore\r\n\t\tswitch (type) {\r\n\t\t\tcase \"file\":\r\n\t\t\t\treturn filePath.isNamed(exclude);\r\n\t\t\tcase \"directory\":\r\n\t\t\t\treturn filePath.relative().includes(exclude);\r\n\t\t\tdefault:\r\n\t\t\t\t// Handle glob patterns using minimatch\r\n\t\t\t\treturn minimatch(filePath.relative(), exclude);\r\n\t\t}\r\n\t}) as boolean;\r\n};\r\n\r\n/**\r\n * Retrieves a list of files based on the provided arguments and patterns.\r\n *\r\n * @param {Args} args - The argument object containing the source directory and other options.\r\n * @param {Patterns} pattern - The pattern object containing the included and excluded file patterns.\r\n * @return A promise that resolves to an array of file paths.\r\n */\r\nexport async function getFiles(args: Args, pattern: Patterns): Promise<string[]> {\r\n\t// 1. Create the Glob instance\r\n\tconst g = new Glob(pattern.include, {\r\n\t\tignore: {\r\n\t\t\tignored: (p: Path) => ignoreFunc(p, pattern.exclude),\r\n\t\t},\r\n\t\tnodir: true,\r\n\t\tcwd: args.paths.cwd,\r\n\t\troot: args.paths.root ? path.resolve(args.paths.root) : undefined,\r\n\t});\r\n\r\n\t// 2. Return the walk() promise, which resolves to an array of all file paths\r\n\treturn g.walk();\r\n}\r\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAiB;AACjB,kBAAgC;AAChC,uBAA0B;AAC1B,iBAA4B;AAE5B,UAAqB;AAErB,SAAoB;AAEpB,oBAAoD;AAQ7C,SAAS,UACf,MACsD;AACtD,QAAM,UAAM,gCAAiB,IAAI;AACjC,UAAQ,KAAK;AAAA,IACZ,KAAK;AACJ,aAAO,GAAG;AAAA,IACX,KAAK;AACJ,aAAO,GAAG;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,IAAI;AAAA,IACZ,KAAK;AACJ,aAAO,IAAI;AAAA,IACZ;AACC,aAAO;AAAA,EACT;AACD;AAGO,MAAM,aAAa,CACzB,UACA,qBACa;AACb,SAAO,iBAAiB,KAAK,CAAC,YAAY;AACzC,UAAM,WAAO,iCAAkB,OAAO;AAEtC,YAAQ,MAAM;AAAA,MACb,KAAK;AACJ,eAAO,SAAS,QAAQ,OAAO;AAAA,MAChC,KAAK;AACJ,eAAO,SAAS,SAAS,EAAE,SAAS,OAAO;AAAA,MAC5C;AAEC,mBAAO,4BAAU,SAAS,SAAS,GAAG,OAAO;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;AASA,eAAsB,SAAS,MAAY,SAAsC;AAEhF,QAAM,IAAI,IAAI,iBAAK,QAAQ,SAAS;AAAA,IACnC,QAAQ;AAAA,MACP,SAAS,CAAC,MAAY,WAAW,GAAG,QAAQ,OAAO;AAAA,IACpD;AAAA,IACA,OAAO;AAAA,IACP,KAAK,KAAK,MAAM;AAAA,IAChB,MAAM,KAAK,MAAM,OAAO,iBAAAA,QAAK,QAAQ,KAAK,MAAM,IAAI,IAAI;AAAA,EACzD,CAAC;AAGD,SAAO,EAAE,KAAK;AACf;",
6
6
  "names": ["path"]
7
7
  }