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.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 LOCALIZABLE_ATTRIBUTES = {
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 getInnerHTML(element) {
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 = LOCALIZABLE_ATTRIBUTES[tagName];
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 = getInnerHTML(element).trim();
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 = getInnerHTML(element).trim();
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, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;");
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 Parser2 = class {
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 Parser2(tokens);
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 parseStringPromise2, Builder } from "xml2js";
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 parseStringPromise2(input2, {
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 Builder({ headless: true });
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 traverse = resolveCjsExport(babelTraverseModule, "@babel/traverse");
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
- traverse(ast, {
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
- traverse(ast, {
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.6",
14104
+ version: "0.117.7",
13836
14105
  description: "Lingo.dev CLI",
13837
14106
  private: false,
13838
14107
  publishConfig: {