lingo.dev 0.117.5 → 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.mjs CHANGED
@@ -2728,16 +2728,9 @@ function appendResourceNode(document, resourceNode) {
2728
2728
  function setTextualNodeContent(node, value, useCdata) {
2729
2729
  const escapedValue = useCdata ? escapeApostrophesOnly(value) : escapeAndroidString(value);
2730
2730
  node._ = escapedValue;
2731
- node.$$ = node.$$ ?? [];
2732
- let textNode = node.$$.find(
2733
- (child) => child["#name"] === "__text__" || child["#name"] === "__cdata"
2734
- );
2735
- if (!textNode) {
2736
- textNode = {};
2737
- node.$$.push(textNode);
2738
- }
2739
- textNode["#name"] = useCdata ? "__cdata" : "__text__";
2740
- textNode._ = escapedValue;
2731
+ node.$$ = [
2732
+ { "#name": useCdata ? "__cdata" : "__text__", _: escapedValue }
2733
+ ];
2741
2734
  }
2742
2735
  function buildResourceNameMap(document) {
2743
2736
  const map = /* @__PURE__ */ new Map();
@@ -3605,7 +3598,7 @@ function createHtmlLoader() {
3605
3598
  // <title> should be treated as a block element for translation
3606
3599
  ]);
3607
3600
  const UNLOCALIZABLE_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
3608
- const LOCALIZABLE_ATTRIBUTES = {
3601
+ const LOCALIZABLE_ATTRIBUTES2 = {
3609
3602
  meta: ["content"],
3610
3603
  img: ["alt", "title"],
3611
3604
  input: ["placeholder", "title"],
@@ -3651,12 +3644,12 @@ function createHtmlLoader() {
3651
3644
  }
3652
3645
  return hasTranslatableContent(element);
3653
3646
  }
3654
- function getInnerHTML(element) {
3647
+ function getInnerHTML2(element) {
3655
3648
  return element.children.map((child) => DomSerializer.default(child, { encodeEntities: false })).join("");
3656
3649
  }
3657
3650
  function extractAttributes(element, path19) {
3658
3651
  const tagName = element.name.toLowerCase();
3659
- const attrs = LOCALIZABLE_ATTRIBUTES[tagName];
3652
+ const attrs = LOCALIZABLE_ATTRIBUTES2[tagName];
3660
3653
  if (!attrs) return;
3661
3654
  for (const attr of attrs) {
3662
3655
  const value = element.attribs?.[attr];
@@ -3673,14 +3666,14 @@ function createHtmlLoader() {
3673
3666
  extractAttributes(element, path19);
3674
3667
  const tagName = element.name.toLowerCase();
3675
3668
  if (BLOCK_ELEMENTS.has(tagName) && isLeafBlock(element)) {
3676
- const content = getInnerHTML(element).trim();
3669
+ const content = getInnerHTML2(element).trim();
3677
3670
  if (content) {
3678
3671
  result[path19] = content;
3679
3672
  }
3680
3673
  return;
3681
3674
  }
3682
3675
  if (PHRASING_ELEMENTS.has(tagName) && hasTranslatableContent(element)) {
3683
- const content = getInnerHTML(element).trim();
3676
+ const content = getInnerHTML2(element).trim();
3684
3677
  if (content) {
3685
3678
  result[path19] = content;
3686
3679
  }
@@ -4011,6 +4004,264 @@ function applyTranslations(node, path19, data, pathMap) {
4011
4004
  }
4012
4005
  }
4013
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, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;");
4263
+ }
4264
+
4014
4265
  // src/cli/loaders/properties.ts
4015
4266
  function createPropertiesLoader() {
4016
4267
  return createLoader({
@@ -4274,7 +4525,7 @@ function escapeString(str) {
4274
4525
  }
4275
4526
 
4276
4527
  // src/cli/loaders/xcode-strings/parser.ts
4277
- var Parser2 = class {
4528
+ var Parser3 = class {
4278
4529
  tokens;
4279
4530
  pos;
4280
4531
  constructor(tokens) {
@@ -4347,7 +4598,7 @@ function createXcodeStringsLoader() {
4347
4598
  async pull(locale, input2) {
4348
4599
  const tokenizer = new Tokenizer(input2);
4349
4600
  const tokens = tokenizer.tokenize();
4350
- const parser = new Parser2(tokens);
4601
+ const parser = new Parser3(tokens);
4351
4602
  const result = parser.parse();
4352
4603
  return result;
4353
4604
  },
@@ -5614,7 +5865,7 @@ function pushNewFile(locale, translations, originalLocale) {
5614
5865
  }
5615
5866
 
5616
5867
  // src/cli/loaders/xml.ts
5617
- import { parseStringPromise as parseStringPromise2, Builder } from "xml2js";
5868
+ import { parseStringPromise as parseStringPromise3, Builder as Builder2 } from "xml2js";
5618
5869
  function normalizeXMLString(xmlString) {
5619
5870
  return xmlString.replace(/\s+/g, " ").replace(/>\s+</g, "><").replace("\n", "").trim();
5620
5871
  }
@@ -5623,7 +5874,7 @@ function createXmlLoader() {
5623
5874
  async pull(locale, input2) {
5624
5875
  let result = {};
5625
5876
  try {
5626
- const parsed = await parseStringPromise2(input2, {
5877
+ const parsed = await parseStringPromise3(input2, {
5627
5878
  explicitArray: false,
5628
5879
  mergeAttrs: false,
5629
5880
  normalize: true,
@@ -5641,7 +5892,7 @@ function createXmlLoader() {
5641
5892
  },
5642
5893
  async push(locale, data) {
5643
5894
  try {
5644
- const builder = new Builder({ headless: true });
5895
+ const builder = new Builder2({ headless: true });
5645
5896
  const xmlOutput = builder.buildObject(data);
5646
5897
  const expectedOutput = normalizeXMLString(xmlOutput);
5647
5898
  return expectedOutput;
@@ -6734,7 +6985,7 @@ function resolveCjsExport(mod, name = "module") {
6734
6985
  }
6735
6986
 
6736
6987
  // src/cli/loaders/typescript/index.ts
6737
- var traverse = resolveCjsExport(babelTraverseModule, "@babel/traverse");
6988
+ var traverse2 = resolveCjsExport(babelTraverseModule, "@babel/traverse");
6738
6989
  var generate = resolveCjsExport(babelGenerateModule, "@babel/generator");
6739
6990
  function createTypescriptLoader() {
6740
6991
  return createLoader({
@@ -6767,7 +7018,7 @@ function parseTypeScript(input2) {
6767
7018
  }
6768
7019
  function extractStringsFromDefaultExport(ast) {
6769
7020
  let extracted = {};
6770
- traverse(ast, {
7021
+ traverse2(ast, {
6771
7022
  ExportDefaultDeclaration(path19) {
6772
7023
  const { declaration } = path19.node;
6773
7024
  const decl = unwrapTSAsExpression(declaration);
@@ -6840,7 +7091,7 @@ function arrayExpressionToArray(arrayExpression) {
6840
7091
  }
6841
7092
  function updateStringsInDefaultExport(ast, data) {
6842
7093
  let modified = false;
6843
- traverse(ast, {
7094
+ traverse2(ast, {
6844
7095
  ExportDefaultDeclaration(path19) {
6845
7096
  const { declaration } = path19.node;
6846
7097
  const decl = unwrapTSAsExpression(declaration);
@@ -9257,6 +9508,17 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
9257
9508
  createSyncLoader(),
9258
9509
  createUnlocalizableLoader(options.returnUnlocalizedKeys)
9259
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
+ );
9260
9522
  case "po":
9261
9523
  return composeLoaders(
9262
9524
  createTextFileLoader(bucketPathPattern),
@@ -13839,7 +14101,7 @@ async function renderHero2() {
13839
14101
  // package.json
13840
14102
  var package_default = {
13841
14103
  name: "lingo.dev",
13842
- version: "0.117.5",
14104
+ version: "0.117.7",
13843
14105
  description: "Lingo.dev CLI",
13844
14106
  private: false,
13845
14107
  publishConfig: {