lingo.dev 0.117.6 → 0.117.7
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/build/cli.cjs +281 -12
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +283 -14
- package/build/cli.mjs.map +1 -1
- package/package.json +5 -5
package/build/cli.mjs
CHANGED
|
@@ -3598,7 +3598,7 @@ function createHtmlLoader() {
|
|
|
3598
3598
|
// <title> should be treated as a block element for translation
|
|
3599
3599
|
]);
|
|
3600
3600
|
const UNLOCALIZABLE_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
3601
|
-
const
|
|
3601
|
+
const LOCALIZABLE_ATTRIBUTES2 = {
|
|
3602
3602
|
meta: ["content"],
|
|
3603
3603
|
img: ["alt", "title"],
|
|
3604
3604
|
input: ["placeholder", "title"],
|
|
@@ -3644,12 +3644,12 @@ function createHtmlLoader() {
|
|
|
3644
3644
|
}
|
|
3645
3645
|
return hasTranslatableContent(element);
|
|
3646
3646
|
}
|
|
3647
|
-
function
|
|
3647
|
+
function getInnerHTML2(element) {
|
|
3648
3648
|
return element.children.map((child) => DomSerializer.default(child, { encodeEntities: false })).join("");
|
|
3649
3649
|
}
|
|
3650
3650
|
function extractAttributes(element, path19) {
|
|
3651
3651
|
const tagName = element.name.toLowerCase();
|
|
3652
|
-
const attrs =
|
|
3652
|
+
const attrs = LOCALIZABLE_ATTRIBUTES2[tagName];
|
|
3653
3653
|
if (!attrs) return;
|
|
3654
3654
|
for (const attr of attrs) {
|
|
3655
3655
|
const value = element.attribs?.[attr];
|
|
@@ -3666,14 +3666,14 @@ function createHtmlLoader() {
|
|
|
3666
3666
|
extractAttributes(element, path19);
|
|
3667
3667
|
const tagName = element.name.toLowerCase();
|
|
3668
3668
|
if (BLOCK_ELEMENTS.has(tagName) && isLeafBlock(element)) {
|
|
3669
|
-
const content =
|
|
3669
|
+
const content = getInnerHTML2(element).trim();
|
|
3670
3670
|
if (content) {
|
|
3671
3671
|
result[path19] = content;
|
|
3672
3672
|
}
|
|
3673
3673
|
return;
|
|
3674
3674
|
}
|
|
3675
3675
|
if (PHRASING_ELEMENTS.has(tagName) && hasTranslatableContent(element)) {
|
|
3676
|
-
const content =
|
|
3676
|
+
const content = getInnerHTML2(element).trim();
|
|
3677
3677
|
if (content) {
|
|
3678
3678
|
result[path19] = content;
|
|
3679
3679
|
}
|
|
@@ -4004,6 +4004,264 @@ function applyTranslations(node, path19, data, pathMap) {
|
|
|
4004
4004
|
}
|
|
4005
4005
|
}
|
|
4006
4006
|
|
|
4007
|
+
// src/cli/loaders/mjml.ts
|
|
4008
|
+
import { parseStringPromise as parseStringPromise2 } from "xml2js";
|
|
4009
|
+
import * as htmlparser22 from "htmlparser2";
|
|
4010
|
+
import { DomHandler as DomHandler2 } from "domhandler";
|
|
4011
|
+
var LOCALIZABLE_COMPONENTS = [
|
|
4012
|
+
"mj-text",
|
|
4013
|
+
"mj-button",
|
|
4014
|
+
"mj-title",
|
|
4015
|
+
"mj-preview",
|
|
4016
|
+
"mj-navbar-link",
|
|
4017
|
+
"mj-accordion-title",
|
|
4018
|
+
"mj-accordion-text",
|
|
4019
|
+
"p",
|
|
4020
|
+
"h1",
|
|
4021
|
+
"h2",
|
|
4022
|
+
"h3",
|
|
4023
|
+
"h4",
|
|
4024
|
+
"h5",
|
|
4025
|
+
"h6",
|
|
4026
|
+
"li"
|
|
4027
|
+
];
|
|
4028
|
+
var LOCALIZABLE_ATTRIBUTES = {
|
|
4029
|
+
"mj-image": ["alt", "title"],
|
|
4030
|
+
"mj-button": ["title", "aria-label"],
|
|
4031
|
+
"mj-social-element": ["title", "alt"],
|
|
4032
|
+
"img": ["alt", "title"],
|
|
4033
|
+
"a": ["title", "aria-label"]
|
|
4034
|
+
};
|
|
4035
|
+
function createMjmlLoader() {
|
|
4036
|
+
return createLoader({
|
|
4037
|
+
async pull(locale, input2) {
|
|
4038
|
+
const result = {};
|
|
4039
|
+
try {
|
|
4040
|
+
const parsed = await parseStringPromise2(input2, {
|
|
4041
|
+
explicitArray: true,
|
|
4042
|
+
explicitChildren: true,
|
|
4043
|
+
preserveChildrenOrder: true,
|
|
4044
|
+
charsAsChildren: true,
|
|
4045
|
+
includeWhiteChars: true,
|
|
4046
|
+
mergeAttrs: false,
|
|
4047
|
+
trim: false,
|
|
4048
|
+
attrkey: "$",
|
|
4049
|
+
charkey: "_",
|
|
4050
|
+
childkey: "$$"
|
|
4051
|
+
});
|
|
4052
|
+
if (!parsed || typeof parsed !== "object") {
|
|
4053
|
+
console.error("Failed to parse MJML: invalid parsed structure");
|
|
4054
|
+
return result;
|
|
4055
|
+
}
|
|
4056
|
+
const rootKey = Object.keys(parsed).find((key) => !key.startsWith("_") && !key.startsWith("$"));
|
|
4057
|
+
const rootNode = rootKey ? parsed[rootKey] : parsed;
|
|
4058
|
+
const rootPath = rootNode["#name"] || rootKey || "";
|
|
4059
|
+
traverse(rootNode, (node, path19, componentName) => {
|
|
4060
|
+
if (typeof node !== "object") return;
|
|
4061
|
+
const localizableAttrs = LOCALIZABLE_ATTRIBUTES[componentName];
|
|
4062
|
+
if (localizableAttrs && node.$) {
|
|
4063
|
+
localizableAttrs.forEach((attr) => {
|
|
4064
|
+
const attrValue = node.$[attr];
|
|
4065
|
+
if (attrValue) {
|
|
4066
|
+
result[`${path19}#${attr}`] = attrValue;
|
|
4067
|
+
}
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4070
|
+
if (LOCALIZABLE_COMPONENTS.includes(componentName)) {
|
|
4071
|
+
const innerHTML = getInnerHTML(node);
|
|
4072
|
+
if (innerHTML) {
|
|
4073
|
+
result[path19] = innerHTML;
|
|
4074
|
+
return "SKIP_CHILDREN";
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
return void 0;
|
|
4078
|
+
}, rootPath);
|
|
4079
|
+
} catch (error) {
|
|
4080
|
+
console.error("Failed to parse MJML:", error);
|
|
4081
|
+
}
|
|
4082
|
+
return result;
|
|
4083
|
+
},
|
|
4084
|
+
async push(locale, data, originalInput) {
|
|
4085
|
+
try {
|
|
4086
|
+
const parsed = await parseStringPromise2(originalInput || "", {
|
|
4087
|
+
explicitArray: true,
|
|
4088
|
+
explicitChildren: true,
|
|
4089
|
+
preserveChildrenOrder: true,
|
|
4090
|
+
charsAsChildren: true,
|
|
4091
|
+
includeWhiteChars: true,
|
|
4092
|
+
mergeAttrs: false,
|
|
4093
|
+
trim: false,
|
|
4094
|
+
attrkey: "$",
|
|
4095
|
+
charkey: "_",
|
|
4096
|
+
childkey: "$$"
|
|
4097
|
+
});
|
|
4098
|
+
if (!parsed || typeof parsed !== "object") {
|
|
4099
|
+
console.error("Failed to parse MJML for push: invalid parsed structure");
|
|
4100
|
+
return originalInput || "";
|
|
4101
|
+
}
|
|
4102
|
+
const rootKey = Object.keys(parsed).find((key) => !key.startsWith("_") && !key.startsWith("$"));
|
|
4103
|
+
const rootNode = rootKey ? parsed[rootKey] : parsed;
|
|
4104
|
+
const rootPath = rootNode["#name"] || rootKey || "";
|
|
4105
|
+
traverse(rootNode, (node, path19, componentName) => {
|
|
4106
|
+
if (typeof node !== "object") return;
|
|
4107
|
+
const localizableAttrs = LOCALIZABLE_ATTRIBUTES[componentName];
|
|
4108
|
+
if (localizableAttrs && node.$) {
|
|
4109
|
+
localizableAttrs.forEach((attr) => {
|
|
4110
|
+
const attrKey = `${path19}#${attr}`;
|
|
4111
|
+
if (data[attrKey] !== void 0) {
|
|
4112
|
+
node.$[attr] = data[attrKey];
|
|
4113
|
+
}
|
|
4114
|
+
});
|
|
4115
|
+
}
|
|
4116
|
+
if (LOCALIZABLE_COMPONENTS.includes(componentName) && data[path19]) {
|
|
4117
|
+
setInnerHTML(node, data[path19]);
|
|
4118
|
+
return "SKIP_CHILDREN";
|
|
4119
|
+
}
|
|
4120
|
+
return void 0;
|
|
4121
|
+
}, rootPath);
|
|
4122
|
+
return serializeMjml(parsed);
|
|
4123
|
+
} catch (error) {
|
|
4124
|
+
console.error("Failed to build MJML:", error);
|
|
4125
|
+
return "";
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
});
|
|
4129
|
+
}
|
|
4130
|
+
function traverse(node, visitor, path19 = "") {
|
|
4131
|
+
if (!node || typeof node !== "object") {
|
|
4132
|
+
return;
|
|
4133
|
+
}
|
|
4134
|
+
const children = node.$$;
|
|
4135
|
+
if (!Array.isArray(children)) {
|
|
4136
|
+
return;
|
|
4137
|
+
}
|
|
4138
|
+
const elementCounts = /* @__PURE__ */ new Map();
|
|
4139
|
+
children.forEach((child) => {
|
|
4140
|
+
const elementName = child["#name"];
|
|
4141
|
+
if (!elementName || elementName.startsWith("__")) {
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
const currentIndex = elementCounts.get(elementName) || 0;
|
|
4145
|
+
elementCounts.set(elementName, currentIndex + 1);
|
|
4146
|
+
const currentPath = path19 ? `${path19}/${elementName}/${currentIndex}` : `${elementName}/${currentIndex}`;
|
|
4147
|
+
const result = visitor(child, currentPath, elementName);
|
|
4148
|
+
if (result !== "SKIP_CHILDREN") {
|
|
4149
|
+
traverse(child, visitor, currentPath);
|
|
4150
|
+
}
|
|
4151
|
+
});
|
|
4152
|
+
}
|
|
4153
|
+
function getInnerHTML(node) {
|
|
4154
|
+
if (!node.$$ || !Array.isArray(node.$$)) {
|
|
4155
|
+
return null;
|
|
4156
|
+
}
|
|
4157
|
+
let html = "";
|
|
4158
|
+
node.$$.forEach((child) => {
|
|
4159
|
+
html += serializeXmlNode(child);
|
|
4160
|
+
});
|
|
4161
|
+
return html.trim() || null;
|
|
4162
|
+
}
|
|
4163
|
+
function setInnerHTML(node, htmlContent) {
|
|
4164
|
+
const handler = new DomHandler2();
|
|
4165
|
+
const parser = new htmlparser22.Parser(handler);
|
|
4166
|
+
parser.write(htmlContent);
|
|
4167
|
+
parser.end();
|
|
4168
|
+
const newChildren = [];
|
|
4169
|
+
for (const domNode of handler.dom) {
|
|
4170
|
+
const xmlNode = convertDomToXmlNode(domNode);
|
|
4171
|
+
if (xmlNode) {
|
|
4172
|
+
newChildren.push(xmlNode);
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
node.$$ = newChildren;
|
|
4176
|
+
node._ = htmlContent;
|
|
4177
|
+
}
|
|
4178
|
+
function serializeXmlNode(node) {
|
|
4179
|
+
const name = node["#name"];
|
|
4180
|
+
if (name === "__text__") {
|
|
4181
|
+
return node._ || "";
|
|
4182
|
+
}
|
|
4183
|
+
if (name === "__cdata") {
|
|
4184
|
+
return `<![CDATA[${node._ || ""}]]>`;
|
|
4185
|
+
}
|
|
4186
|
+
if (!name || name.startsWith("__")) {
|
|
4187
|
+
return "";
|
|
4188
|
+
}
|
|
4189
|
+
const attrs = node.$ || {};
|
|
4190
|
+
const attrString = Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttributeValue2(String(value))}"`).join("");
|
|
4191
|
+
const children = node.$$ || [];
|
|
4192
|
+
if (children.length === 0) {
|
|
4193
|
+
const textContent2 = node._ || "";
|
|
4194
|
+
if (textContent2) {
|
|
4195
|
+
return `<${name}${attrString}>${textContent2}</${name}>`;
|
|
4196
|
+
}
|
|
4197
|
+
return `<${name}${attrString} />`;
|
|
4198
|
+
}
|
|
4199
|
+
const childContent = children.map(serializeXmlNode).join("");
|
|
4200
|
+
return `<${name}${attrString}>${childContent}</${name}>`;
|
|
4201
|
+
}
|
|
4202
|
+
function convertDomToXmlNode(domNode) {
|
|
4203
|
+
if (domNode.type === "text") {
|
|
4204
|
+
return {
|
|
4205
|
+
"#name": "__text__",
|
|
4206
|
+
"_": domNode.data
|
|
4207
|
+
};
|
|
4208
|
+
}
|
|
4209
|
+
if (domNode.type === "tag") {
|
|
4210
|
+
const xmlNode = {
|
|
4211
|
+
"#name": domNode.name,
|
|
4212
|
+
"$": domNode.attribs || {},
|
|
4213
|
+
"$$": []
|
|
4214
|
+
};
|
|
4215
|
+
if (domNode.children && domNode.children.length > 0) {
|
|
4216
|
+
for (const child of domNode.children) {
|
|
4217
|
+
const xmlChild = convertDomToXmlNode(child);
|
|
4218
|
+
if (xmlChild) {
|
|
4219
|
+
xmlNode.$$.push(xmlChild);
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
return xmlNode;
|
|
4224
|
+
}
|
|
4225
|
+
return null;
|
|
4226
|
+
}
|
|
4227
|
+
function serializeMjml(parsed) {
|
|
4228
|
+
const xmlDec = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
4229
|
+
const rootKey = Object.keys(parsed).find((key) => !key.startsWith("_") && !key.startsWith("$"));
|
|
4230
|
+
const rootNode = rootKey ? parsed[rootKey] : parsed;
|
|
4231
|
+
const body = serializeElement2(rootNode);
|
|
4232
|
+
return xmlDec + body;
|
|
4233
|
+
}
|
|
4234
|
+
function serializeElement2(node, indent2 = "") {
|
|
4235
|
+
if (!node) {
|
|
4236
|
+
return "";
|
|
4237
|
+
}
|
|
4238
|
+
const name = node["#name"] ?? "mjml";
|
|
4239
|
+
if (name === "__text__") {
|
|
4240
|
+
return node._ ?? "";
|
|
4241
|
+
}
|
|
4242
|
+
if (name === "__cdata") {
|
|
4243
|
+
return `<![CDATA[${node._ ?? ""}]]>`;
|
|
4244
|
+
}
|
|
4245
|
+
if (name === "__comment__") {
|
|
4246
|
+
return `<!--${node._ ?? ""}-->`;
|
|
4247
|
+
}
|
|
4248
|
+
const attributes = node.$ ?? {};
|
|
4249
|
+
const attrString = Object.entries(attributes).map(([key, value]) => ` ${key}="${escapeAttributeValue2(String(value))}"`).join("");
|
|
4250
|
+
const children = Array.isArray(node.$$) ? node.$$ : [];
|
|
4251
|
+
if (children.length === 0) {
|
|
4252
|
+
const textContent2 = node._ ?? "";
|
|
4253
|
+
if (textContent2) {
|
|
4254
|
+
return `${indent2}<${name}${attrString}>${textContent2}</${name}>`;
|
|
4255
|
+
}
|
|
4256
|
+
return `${indent2}<${name}${attrString} />`;
|
|
4257
|
+
}
|
|
4258
|
+
const childContent = children.map((child) => serializeElement2(child, indent2)).join("");
|
|
4259
|
+
return `${indent2}<${name}${attrString}>${childContent}</${name}>`;
|
|
4260
|
+
}
|
|
4261
|
+
function escapeAttributeValue2(value) {
|
|
4262
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'");
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4007
4265
|
// src/cli/loaders/properties.ts
|
|
4008
4266
|
function createPropertiesLoader() {
|
|
4009
4267
|
return createLoader({
|
|
@@ -4267,7 +4525,7 @@ function escapeString(str) {
|
|
|
4267
4525
|
}
|
|
4268
4526
|
|
|
4269
4527
|
// src/cli/loaders/xcode-strings/parser.ts
|
|
4270
|
-
var
|
|
4528
|
+
var Parser3 = class {
|
|
4271
4529
|
tokens;
|
|
4272
4530
|
pos;
|
|
4273
4531
|
constructor(tokens) {
|
|
@@ -4340,7 +4598,7 @@ function createXcodeStringsLoader() {
|
|
|
4340
4598
|
async pull(locale, input2) {
|
|
4341
4599
|
const tokenizer = new Tokenizer(input2);
|
|
4342
4600
|
const tokens = tokenizer.tokenize();
|
|
4343
|
-
const parser = new
|
|
4601
|
+
const parser = new Parser3(tokens);
|
|
4344
4602
|
const result = parser.parse();
|
|
4345
4603
|
return result;
|
|
4346
4604
|
},
|
|
@@ -5607,7 +5865,7 @@ function pushNewFile(locale, translations, originalLocale) {
|
|
|
5607
5865
|
}
|
|
5608
5866
|
|
|
5609
5867
|
// src/cli/loaders/xml.ts
|
|
5610
|
-
import { parseStringPromise as
|
|
5868
|
+
import { parseStringPromise as parseStringPromise3, Builder as Builder2 } from "xml2js";
|
|
5611
5869
|
function normalizeXMLString(xmlString) {
|
|
5612
5870
|
return xmlString.replace(/\s+/g, " ").replace(/>\s+</g, "><").replace("\n", "").trim();
|
|
5613
5871
|
}
|
|
@@ -5616,7 +5874,7 @@ function createXmlLoader() {
|
|
|
5616
5874
|
async pull(locale, input2) {
|
|
5617
5875
|
let result = {};
|
|
5618
5876
|
try {
|
|
5619
|
-
const parsed = await
|
|
5877
|
+
const parsed = await parseStringPromise3(input2, {
|
|
5620
5878
|
explicitArray: false,
|
|
5621
5879
|
mergeAttrs: false,
|
|
5622
5880
|
normalize: true,
|
|
@@ -5634,7 +5892,7 @@ function createXmlLoader() {
|
|
|
5634
5892
|
},
|
|
5635
5893
|
async push(locale, data) {
|
|
5636
5894
|
try {
|
|
5637
|
-
const builder = new
|
|
5895
|
+
const builder = new Builder2({ headless: true });
|
|
5638
5896
|
const xmlOutput = builder.buildObject(data);
|
|
5639
5897
|
const expectedOutput = normalizeXMLString(xmlOutput);
|
|
5640
5898
|
return expectedOutput;
|
|
@@ -6727,7 +6985,7 @@ function resolveCjsExport(mod, name = "module") {
|
|
|
6727
6985
|
}
|
|
6728
6986
|
|
|
6729
6987
|
// src/cli/loaders/typescript/index.ts
|
|
6730
|
-
var
|
|
6988
|
+
var traverse2 = resolveCjsExport(babelTraverseModule, "@babel/traverse");
|
|
6731
6989
|
var generate = resolveCjsExport(babelGenerateModule, "@babel/generator");
|
|
6732
6990
|
function createTypescriptLoader() {
|
|
6733
6991
|
return createLoader({
|
|
@@ -6760,7 +7018,7 @@ function parseTypeScript(input2) {
|
|
|
6760
7018
|
}
|
|
6761
7019
|
function extractStringsFromDefaultExport(ast) {
|
|
6762
7020
|
let extracted = {};
|
|
6763
|
-
|
|
7021
|
+
traverse2(ast, {
|
|
6764
7022
|
ExportDefaultDeclaration(path19) {
|
|
6765
7023
|
const { declaration } = path19.node;
|
|
6766
7024
|
const decl = unwrapTSAsExpression(declaration);
|
|
@@ -6833,7 +7091,7 @@ function arrayExpressionToArray(arrayExpression) {
|
|
|
6833
7091
|
}
|
|
6834
7092
|
function updateStringsInDefaultExport(ast, data) {
|
|
6835
7093
|
let modified = false;
|
|
6836
|
-
|
|
7094
|
+
traverse2(ast, {
|
|
6837
7095
|
ExportDefaultDeclaration(path19) {
|
|
6838
7096
|
const { declaration } = path19.node;
|
|
6839
7097
|
const decl = unwrapTSAsExpression(declaration);
|
|
@@ -9250,6 +9508,17 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
|
|
|
9250
9508
|
createSyncLoader(),
|
|
9251
9509
|
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
9252
9510
|
);
|
|
9511
|
+
case "mjml":
|
|
9512
|
+
return composeLoaders(
|
|
9513
|
+
createTextFileLoader(bucketPathPattern),
|
|
9514
|
+
createFormatterLoader(options.formatter, "html", bucketPathPattern),
|
|
9515
|
+
createLockedPatternsLoader(lockedPatterns),
|
|
9516
|
+
createMjmlLoader(),
|
|
9517
|
+
createLockedKeysLoader(lockedKeys || []),
|
|
9518
|
+
createIgnoredKeysLoader(ignoredKeys || []),
|
|
9519
|
+
createSyncLoader(),
|
|
9520
|
+
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
9521
|
+
);
|
|
9253
9522
|
case "po":
|
|
9254
9523
|
return composeLoaders(
|
|
9255
9524
|
createTextFileLoader(bucketPathPattern),
|
|
@@ -13832,7 +14101,7 @@ async function renderHero2() {
|
|
|
13832
14101
|
// package.json
|
|
13833
14102
|
var package_default = {
|
|
13834
14103
|
name: "lingo.dev",
|
|
13835
|
-
version: "0.117.
|
|
14104
|
+
version: "0.117.7",
|
|
13836
14105
|
description: "Lingo.dev CLI",
|
|
13837
14106
|
private: false,
|
|
13838
14107
|
publishConfig: {
|