lingo.dev 0.125.2 → 0.125.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/build/cli.mjs CHANGED
@@ -3639,8 +3639,8 @@ function serializeElement(node) {
3639
3639
  const attrString = Object.entries(attributes).map(([key, value]) => ` ${key}="${escapeAttributeValue(String(value))}"`).join("");
3640
3640
  const children = Array.isArray(node.$$) ? node.$$ : [];
3641
3641
  if (children.length === 0) {
3642
- const textContent3 = node._ ?? "";
3643
- return `<${name}${attrString}>${textContent3}</${name}>`;
3642
+ const textContent2 = node._ ?? "";
3643
+ return `<${name}${attrString}>${textContent2}</${name}>`;
3644
3644
  }
3645
3645
  const childContent = children.map(serializeElement).join("");
3646
3646
  return `<${name}${attrString}>${childContent}</${name}>`;
@@ -3731,119 +3731,241 @@ function createPullOutputCleaner() {
3731
3731
  // src/cli/loaders/html.ts
3732
3732
  import * as htmlparser2 from "htmlparser2";
3733
3733
  import { DomHandler } from "domhandler";
3734
- import * as domutils from "domutils";
3734
+ import * as domutils2 from "domutils";
3735
3735
  import * as DomSerializer from "dom-serializer";
3736
+
3737
+ // src/cli/utils/element-extraction.ts
3738
+ import * as domutils from "domutils";
3739
+ var SVG_TRANSLATABLE_TAGS = /* @__PURE__ */ new Set([
3740
+ "title",
3741
+ "text",
3742
+ "desc"
3743
+ ]);
3744
+ var PHRASING_ELEMENTS = /* @__PURE__ */ new Set([
3745
+ // Text-level semantics
3746
+ "a",
3747
+ "abbr",
3748
+ "b",
3749
+ "bdi",
3750
+ "bdo",
3751
+ "br",
3752
+ "cite",
3753
+ "code",
3754
+ "data",
3755
+ "dfn",
3756
+ "em",
3757
+ "i",
3758
+ "kbd",
3759
+ "mark",
3760
+ "q",
3761
+ "ruby",
3762
+ "s",
3763
+ "samp",
3764
+ "small",
3765
+ "span",
3766
+ "strong",
3767
+ "sub",
3768
+ "sup",
3769
+ "time",
3770
+ "u",
3771
+ "var",
3772
+ "wbr",
3773
+ // Media
3774
+ "audio",
3775
+ "img",
3776
+ "video",
3777
+ "picture",
3778
+ // Interactive
3779
+ "button",
3780
+ "input",
3781
+ "label",
3782
+ "select",
3783
+ "textarea",
3784
+ // Embedded
3785
+ "canvas",
3786
+ "iframe",
3787
+ "object",
3788
+ "svg",
3789
+ "math",
3790
+ // Other
3791
+ "del",
3792
+ "ins",
3793
+ "map",
3794
+ "area"
3795
+ ]);
3796
+ var BLOCK_ELEMENTS = /* @__PURE__ */ new Set([
3797
+ "div",
3798
+ "p",
3799
+ "h1",
3800
+ "h2",
3801
+ "h3",
3802
+ "h4",
3803
+ "h5",
3804
+ "h6",
3805
+ "ul",
3806
+ "ol",
3807
+ "li",
3808
+ "dl",
3809
+ "dt",
3810
+ "dd",
3811
+ "blockquote",
3812
+ "pre",
3813
+ "article",
3814
+ "aside",
3815
+ "nav",
3816
+ "section",
3817
+ "header",
3818
+ "footer",
3819
+ "main",
3820
+ "figure",
3821
+ "figcaption",
3822
+ "table",
3823
+ "thead",
3824
+ "tbody",
3825
+ "tfoot",
3826
+ "tr",
3827
+ "td",
3828
+ "th",
3829
+ "caption",
3830
+ "form",
3831
+ "fieldset",
3832
+ "legend",
3833
+ "details",
3834
+ "summary",
3835
+ "address",
3836
+ "hr",
3837
+ "search",
3838
+ "dialog",
3839
+ "noscript",
3840
+ "title"
3841
+ ]);
3842
+ var UNLOCALIZABLE_TAGS = /* @__PURE__ */ new Set([
3843
+ "script",
3844
+ "style"
3845
+ ]);
3846
+ var BASE_LOCALIZABLE_ATTRIBUTES = {
3847
+ meta: ["content"],
3848
+ img: ["alt", "title"],
3849
+ input: ["placeholder", "title"],
3850
+ textarea: ["placeholder", "title"],
3851
+ a: ["title"],
3852
+ abbr: ["title"],
3853
+ button: ["title"],
3854
+ link: ["title"]
3855
+ };
3856
+ function isInsideUnlocalizableTag(element, unlocalizableTags = UNLOCALIZABLE_TAGS) {
3857
+ let current = element.parent;
3858
+ while (current && current.type === "tag") {
3859
+ if (unlocalizableTags.has(current.name.toLowerCase())) {
3860
+ return true;
3861
+ }
3862
+ current = current.parent;
3863
+ }
3864
+ return false;
3865
+ }
3866
+ function hasTranslatableContent(element) {
3867
+ const text = domutils.textContent(element);
3868
+ return text.trim().length > 0;
3869
+ }
3870
+ function isLeafBlock(element, blockElements = BLOCK_ELEMENTS) {
3871
+ const childElements = element.children.filter(
3872
+ (child) => child.type === "tag"
3873
+ );
3874
+ for (const child of childElements) {
3875
+ if (blockElements.has(child.name.toLowerCase())) {
3876
+ return false;
3877
+ }
3878
+ }
3879
+ return hasTranslatableContent(element);
3880
+ }
3881
+ function isInsideSvg(element) {
3882
+ let current = element.parent;
3883
+ while (current && current.type === "tag") {
3884
+ if (current.name.toLowerCase() === "svg") {
3885
+ return true;
3886
+ }
3887
+ current = current.parent;
3888
+ }
3889
+ return false;
3890
+ }
3891
+ function containsSvgDescendant(element) {
3892
+ const childElements = element.children.filter(
3893
+ (child) => child.type === "tag"
3894
+ );
3895
+ for (const child of childElements) {
3896
+ if (child.name.toLowerCase() === "svg") {
3897
+ return true;
3898
+ }
3899
+ if (containsSvgDescendant(child)) {
3900
+ return true;
3901
+ }
3902
+ }
3903
+ return false;
3904
+ }
3905
+ function getSvgExtractionStrategy(element) {
3906
+ const tagName = element.name.toLowerCase();
3907
+ if (tagName === "svg") {
3908
+ return "skip-recurse";
3909
+ }
3910
+ const inSvg = isInsideSvg(element);
3911
+ if (!inSvg) {
3912
+ return "process-normal";
3913
+ }
3914
+ return SVG_TRANSLATABLE_TAGS.has(tagName) ? "extract" : "skip-recurse";
3915
+ }
3916
+ function createElementExtractor(context, result) {
3917
+ function extractFromElement(element, pathParts) {
3918
+ const path20 = pathParts.join("/");
3919
+ const tagName = element.name.toLowerCase();
3920
+ if (isInsideUnlocalizableTag(element)) {
3921
+ return;
3922
+ }
3923
+ context.extractAttributes(element, path20);
3924
+ const svgStrategy = getSvgExtractionStrategy(element);
3925
+ if (svgStrategy === "extract") {
3926
+ const content = context.getInnerHTML(element).trim();
3927
+ if (content) {
3928
+ result[path20] = content;
3929
+ }
3930
+ return;
3931
+ }
3932
+ if (svgStrategy === "skip-recurse") {
3933
+ let childIndex2 = 0;
3934
+ const childElements2 = element.children.filter(
3935
+ (child) => child.type === "tag"
3936
+ );
3937
+ for (const child of childElements2) {
3938
+ extractFromElement(child, [...pathParts, childIndex2++]);
3939
+ }
3940
+ return;
3941
+ }
3942
+ if (BLOCK_ELEMENTS.has(tagName) && isLeafBlock(element) && !containsSvgDescendant(element)) {
3943
+ const content = context.getInnerHTML(element).trim();
3944
+ if (content) {
3945
+ result[path20] = content;
3946
+ }
3947
+ return;
3948
+ }
3949
+ if (PHRASING_ELEMENTS.has(tagName) && hasTranslatableContent(element) && !containsSvgDescendant(element)) {
3950
+ const content = context.getInnerHTML(element).trim();
3951
+ if (content) {
3952
+ result[path20] = content;
3953
+ }
3954
+ return;
3955
+ }
3956
+ let childIndex = 0;
3957
+ const childElements = element.children.filter(
3958
+ (child) => child.type === "tag"
3959
+ );
3960
+ for (const child of childElements) {
3961
+ extractFromElement(child, [...pathParts, childIndex++]);
3962
+ }
3963
+ }
3964
+ return extractFromElement;
3965
+ }
3966
+
3967
+ // src/cli/loaders/html.ts
3736
3968
  function createHtmlLoader() {
3737
- const PHRASING_ELEMENTS = /* @__PURE__ */ new Set([
3738
- // Text-level semantics
3739
- "a",
3740
- "abbr",
3741
- "b",
3742
- "bdi",
3743
- "bdo",
3744
- "br",
3745
- "cite",
3746
- "code",
3747
- "data",
3748
- "dfn",
3749
- "em",
3750
- "i",
3751
- "kbd",
3752
- "mark",
3753
- "q",
3754
- "ruby",
3755
- "s",
3756
- "samp",
3757
- "small",
3758
- "span",
3759
- "strong",
3760
- "sub",
3761
- "sup",
3762
- "time",
3763
- "u",
3764
- "var",
3765
- "wbr",
3766
- // Media
3767
- "audio",
3768
- "img",
3769
- "video",
3770
- "picture",
3771
- // Interactive
3772
- "button",
3773
- "input",
3774
- "label",
3775
- "select",
3776
- "textarea",
3777
- // Embedded
3778
- "canvas",
3779
- "iframe",
3780
- "object",
3781
- "svg",
3782
- "math",
3783
- // Other
3784
- "del",
3785
- "ins",
3786
- "map",
3787
- "area"
3788
- ]);
3789
- const BLOCK_ELEMENTS = /* @__PURE__ */ new Set([
3790
- "div",
3791
- "p",
3792
- "h1",
3793
- "h2",
3794
- "h3",
3795
- "h4",
3796
- "h5",
3797
- "h6",
3798
- "ul",
3799
- "ol",
3800
- "li",
3801
- "dl",
3802
- "dt",
3803
- "dd",
3804
- "blockquote",
3805
- "pre",
3806
- "article",
3807
- "aside",
3808
- "nav",
3809
- "section",
3810
- "header",
3811
- "footer",
3812
- "main",
3813
- "figure",
3814
- "figcaption",
3815
- "table",
3816
- "thead",
3817
- "tbody",
3818
- "tfoot",
3819
- "tr",
3820
- "td",
3821
- "th",
3822
- "caption",
3823
- "form",
3824
- "fieldset",
3825
- "legend",
3826
- "details",
3827
- "summary",
3828
- "address",
3829
- "hr",
3830
- "search",
3831
- "dialog",
3832
- "noscript",
3833
- "title"
3834
- // <title> should be treated as a block element for translation
3835
- ]);
3836
- const UNLOCALIZABLE_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
3837
- const LOCALIZABLE_ATTRIBUTES2 = {
3838
- meta: ["content"],
3839
- img: ["alt", "title"],
3840
- input: ["placeholder", "title"],
3841
- textarea: ["placeholder", "title"],
3842
- a: ["title"],
3843
- abbr: ["title"],
3844
- button: ["title"],
3845
- link: ["title"]
3846
- };
3847
3969
  return createLoader({
3848
3970
  async pull(locale, input2) {
3849
3971
  const result = {};
@@ -3855,37 +3977,14 @@ function createHtmlLoader() {
3855
3977
  parser.write(input2);
3856
3978
  parser.end();
3857
3979
  const dom = handler.dom;
3858
- function isInsideUnlocalizableTag(element) {
3859
- let current = element.parent;
3860
- while (current && current.type === "tag") {
3861
- if (UNLOCALIZABLE_TAGS.has(current.name.toLowerCase())) {
3862
- return true;
3863
- }
3864
- current = current.parent;
3865
- }
3866
- return false;
3867
- }
3868
- function hasTranslatableContent(element) {
3869
- const text = domutils.textContent(element);
3870
- return text.trim().length > 0;
3871
- }
3872
- function isLeafBlock(element) {
3873
- const childElements = element.children.filter(
3874
- (child) => child.type === "tag"
3875
- );
3876
- for (const child of childElements) {
3877
- if (BLOCK_ELEMENTS.has(child.name.toLowerCase())) {
3878
- return false;
3879
- }
3880
- }
3881
- return hasTranslatableContent(element);
3882
- }
3883
3980
  function getInnerHTML2(element) {
3884
- return element.children.map((child) => DomSerializer.default(child, { encodeEntities: false })).join("");
3981
+ return element.children.map(
3982
+ (child) => DomSerializer.default(child, { encodeEntities: false })
3983
+ ).join("");
3885
3984
  }
3886
3985
  function extractAttributes(element, path20) {
3887
3986
  const tagName = element.name.toLowerCase();
3888
- const attrs = LOCALIZABLE_ATTRIBUTES2[tagName];
3987
+ const attrs = BASE_LOCALIZABLE_ATTRIBUTES[tagName];
3889
3988
  if (!attrs) return;
3890
3989
  for (const attr of attrs) {
3891
3990
  const value = element.attribs?.[attr];
@@ -3894,47 +3993,22 @@ function createHtmlLoader() {
3894
3993
  }
3895
3994
  }
3896
3995
  }
3897
- function extractFromElement(element, pathParts) {
3898
- const path20 = pathParts.join("/");
3899
- if (isInsideUnlocalizableTag(element)) {
3900
- return;
3901
- }
3902
- extractAttributes(element, path20);
3903
- const tagName = element.name.toLowerCase();
3904
- if (BLOCK_ELEMENTS.has(tagName) && isLeafBlock(element)) {
3905
- const content = getInnerHTML2(element).trim();
3906
- if (content) {
3907
- result[path20] = content;
3908
- }
3909
- return;
3910
- }
3911
- if (PHRASING_ELEMENTS.has(tagName) && hasTranslatableContent(element)) {
3912
- const content = getInnerHTML2(element).trim();
3913
- if (content) {
3914
- result[path20] = content;
3915
- }
3916
- return;
3917
- }
3918
- let childIndex = 0;
3919
- const childElements = element.children.filter(
3920
- (child) => child.type === "tag"
3921
- );
3922
- for (const child of childElements) {
3923
- extractFromElement(child, [...pathParts, childIndex++]);
3924
- }
3925
- }
3926
- const html = domutils.findOne(
3996
+ const extractFromElement = createElementExtractor(
3997
+ { getInnerHTML: getInnerHTML2, extractAttributes },
3998
+ result
3999
+ );
4000
+ const html = domutils2.findOne(
3927
4001
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "html",
3928
4002
  dom,
3929
4003
  true
3930
4004
  );
3931
4005
  if (html) {
3932
- const head = domutils.findOne(
4006
+ const head = domutils2.findOne(
3933
4007
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "head",
3934
4008
  html.children,
3935
4009
  true
3936
4010
  );
3937
- const body = domutils.findOne(
4011
+ const body = domutils2.findOne(
3938
4012
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "body",
3939
4013
  html.children,
3940
4014
  true
@@ -3979,7 +4053,7 @@ function createHtmlLoader() {
3979
4053
  );
3980
4054
  parser.end();
3981
4055
  const dom = handler.dom;
3982
- const html = domutils.findOne(
4056
+ const html = domutils2.findOne(
3983
4057
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "html",
3984
4058
  dom,
3985
4059
  true
@@ -4009,13 +4083,13 @@ function createHtmlLoader() {
4009
4083
  let current = null;
4010
4084
  if (html) {
4011
4085
  if (rootTag === "head") {
4012
- current = domutils.findOne(
4086
+ current = domutils2.findOne(
4013
4087
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "head",
4014
4088
  html.children,
4015
4089
  true
4016
4090
  );
4017
4091
  } else if (rootTag === "body") {
4018
- current = domutils.findOne(
4092
+ current = domutils2.findOne(
4019
4093
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "body",
4020
4094
  html.children,
4021
4095
  true
@@ -4432,9 +4506,9 @@ function serializeXmlNode(node) {
4432
4506
  const attrString = Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttributeValue2(String(value))}"`).join("");
4433
4507
  const children = node.$$ || [];
4434
4508
  if (children.length === 0) {
4435
- const textContent3 = node._ || "";
4436
- if (textContent3) {
4437
- return `<${name}${attrString}>${textContent3}</${name}>`;
4509
+ const textContent2 = node._ || "";
4510
+ if (textContent2) {
4511
+ return `<${name}${attrString}>${textContent2}</${name}>`;
4438
4512
  }
4439
4513
  return `<${name}${attrString} />`;
4440
4514
  }
@@ -4490,9 +4564,9 @@ function serializeElement2(node, indent2 = "") {
4490
4564
  const attrString = Object.entries(attributes).map(([key, value]) => ` ${key}="${escapeAttributeValue2(String(value))}"`).join("");
4491
4565
  const children = Array.isArray(node.$$) ? node.$$ : [];
4492
4566
  if (children.length === 0) {
4493
- const textContent3 = node._ ?? "";
4494
- if (textContent3) {
4495
- return `${indent2}<${name}${attrString}>${textContent3}</${name}>`;
4567
+ const textContent2 = node._ ?? "";
4568
+ if (textContent2) {
4569
+ return `${indent2}<${name}${attrString}>${textContent2}</${name}>`;
4496
4570
  }
4497
4571
  return `${indent2}<${name}${attrString} />`;
4498
4572
  }
@@ -6053,10 +6127,10 @@ function formatXml(xml) {
6053
6127
  if (cdataNode) {
6054
6128
  return `${indent2}${openTag}<![CDATA[${cdataNode.nodeValue}]]></${tagName}>`;
6055
6129
  }
6056
- const textContent3 = element.textContent?.trim() || "";
6130
+ const textContent2 = element.textContent?.trim() || "";
6057
6131
  const hasOnlyText = element.childNodes.length === 1 && element.childNodes[0].nodeType === 3;
6058
- if (hasOnlyText && textContent3) {
6059
- return `${indent2}${openTag}${textContent3}</${tagName}>`;
6132
+ if (hasOnlyText && textContent2) {
6133
+ return `${indent2}${openTag}${textContent2}</${tagName}>`;
6060
6134
  }
6061
6135
  const children = Array.from(element.children);
6062
6136
  if (children.length === 0) {
@@ -9376,14 +9450,14 @@ function parseEjsForTranslation(input2) {
9376
9450
  if (part.type === "ejs") {
9377
9451
  template += part.content;
9378
9452
  } else {
9379
- const textContent3 = part.content;
9453
+ const textContent2 = part.content;
9380
9454
  const htmlTagRegex = /<[^>]+>/g;
9381
9455
  const textParts = [];
9382
9456
  let lastTextIndex = 0;
9383
9457
  let htmlMatch;
9384
- while ((htmlMatch = htmlTagRegex.exec(textContent3)) !== null) {
9458
+ while ((htmlMatch = htmlTagRegex.exec(textContent2)) !== null) {
9385
9459
  if (htmlMatch.index > lastTextIndex) {
9386
- const textBefore = textContent3.slice(lastTextIndex, htmlMatch.index);
9460
+ const textBefore = textContent2.slice(lastTextIndex, htmlMatch.index);
9387
9461
  if (textBefore.trim()) {
9388
9462
  textParts.push({ type: "text", content: textBefore });
9389
9463
  } else {
@@ -9393,8 +9467,8 @@ function parseEjsForTranslation(input2) {
9393
9467
  textParts.push({ type: "html", content: htmlMatch[0] });
9394
9468
  lastTextIndex = htmlMatch.index + htmlMatch[0].length;
9395
9469
  }
9396
- if (lastTextIndex < textContent3.length) {
9397
- const remainingText = textContent3.slice(lastTextIndex);
9470
+ if (lastTextIndex < textContent2.length) {
9471
+ const remainingText = textContent2.slice(lastTextIndex);
9398
9472
  if (remainingText.trim()) {
9399
9473
  textParts.push({ type: "text", content: remainingText });
9400
9474
  } else {
@@ -9402,11 +9476,11 @@ function parseEjsForTranslation(input2) {
9402
9476
  }
9403
9477
  }
9404
9478
  if (textParts.length === 0) {
9405
- const trimmedContent = textContent3.trim();
9479
+ const trimmedContent = textContent2.trim();
9406
9480
  if (trimmedContent) {
9407
- textParts.push({ type: "text", content: textContent3 });
9481
+ textParts.push({ type: "text", content: textContent2 });
9408
9482
  } else {
9409
- textParts.push({ type: "html", content: textContent3 });
9483
+ textParts.push({ type: "html", content: textContent2 });
9410
9484
  }
9411
9485
  }
9412
9486
  for (const textPart of textParts) {
@@ -9478,117 +9552,15 @@ function createEjsLoader() {
9478
9552
  // src/cli/loaders/twig.ts
9479
9553
  import * as htmlparser23 from "htmlparser2";
9480
9554
  import { DomHandler as DomHandler3 } from "domhandler";
9481
- import * as domutils2 from "domutils";
9555
+ import * as domutils3 from "domutils";
9482
9556
  import * as DomSerializer2 from "dom-serializer";
9483
9557
  function createTwigLoader() {
9484
- const PHRASING_ELEMENTS = /* @__PURE__ */ new Set([
9485
- // Text-level semantics
9486
- "a",
9487
- "abbr",
9488
- "b",
9489
- "bdi",
9490
- "bdo",
9491
- "br",
9492
- "cite",
9493
- "code",
9494
- "data",
9495
- "dfn",
9496
- "em",
9497
- "i",
9498
- "kbd",
9499
- "mark",
9500
- "q",
9501
- "ruby",
9502
- "s",
9503
- "samp",
9504
- "small",
9505
- "span",
9506
- "strong",
9507
- "sub",
9508
- "sup",
9509
- "time",
9510
- "u",
9511
- "var",
9512
- "wbr",
9513
- // Media
9514
- "audio",
9515
- "img",
9516
- "video",
9517
- "picture",
9518
- // Interactive
9519
- "button",
9520
- "input",
9521
- "label",
9522
- "select",
9523
- "textarea",
9524
- // Embedded
9525
- "canvas",
9526
- "iframe",
9527
- "object",
9528
- "svg",
9529
- "math",
9530
- // Other
9531
- "del",
9532
- "ins",
9533
- "map",
9534
- "area"
9535
- ]);
9536
- const BLOCK_ELEMENTS = /* @__PURE__ */ new Set([
9537
- "div",
9538
- "p",
9539
- "h1",
9540
- "h2",
9541
- "h3",
9542
- "h4",
9543
- "h5",
9544
- "h6",
9545
- "ul",
9546
- "ol",
9547
- "li",
9548
- "dl",
9549
- "dt",
9550
- "dd",
9551
- "blockquote",
9552
- "pre",
9553
- "article",
9554
- "aside",
9555
- "nav",
9556
- "section",
9557
- "header",
9558
- "footer",
9559
- "main",
9560
- "figure",
9561
- "figcaption",
9562
- "table",
9563
- "thead",
9564
- "tbody",
9565
- "tfoot",
9566
- "tr",
9567
- "td",
9568
- "th",
9569
- "caption",
9570
- "form",
9571
- "fieldset",
9572
- "legend",
9573
- "details",
9574
- "summary",
9575
- "address",
9576
- "hr",
9577
- "search",
9578
- "dialog",
9579
- "noscript",
9580
- "title"
9581
- ]);
9582
- const UNLOCALIZABLE_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
9583
9558
  const LOCALIZABLE_ATTRIBUTES2 = {
9584
- meta: ["content"],
9585
- img: ["alt", "title"],
9559
+ ...BASE_LOCALIZABLE_ATTRIBUTES,
9586
9560
  input: ["placeholder", "title", "aria-label"],
9587
9561
  textarea: ["placeholder", "title", "aria-label"],
9588
9562
  button: ["title", "aria-label"],
9589
- a: ["title", "aria-label"],
9590
- abbr: ["title"],
9591
- link: ["title"]
9563
+ a: ["title", "aria-label"]
9592
9564
  };
9593
9565
  function preprocessTwig(input2) {
9594
9566
  const twigBlocks = [];
@@ -9622,33 +9594,10 @@ function createTwigLoader() {
9622
9594
  parser.write(processed);
9623
9595
  parser.end();
9624
9596
  const dom = handler.dom;
9625
- function isInsideUnlocalizableTag(element) {
9626
- let current = element.parent;
9627
- while (current && current.type === "tag") {
9628
- if (UNLOCALIZABLE_TAGS.has(current.name.toLowerCase())) {
9629
- return true;
9630
- }
9631
- current = current.parent;
9632
- }
9633
- return false;
9634
- }
9635
- function hasTranslatableContent(element) {
9636
- const text = domutils2.textContent(element);
9637
- return text.trim().length > 0;
9638
- }
9639
- function isLeafBlock(element) {
9640
- const childElements = element.children.filter(
9641
- (child) => child.type === "tag"
9642
- );
9643
- for (const child of childElements) {
9644
- if (BLOCK_ELEMENTS.has(child.name.toLowerCase())) {
9645
- return false;
9646
- }
9647
- }
9648
- return hasTranslatableContent(element);
9649
- }
9650
9597
  function getInnerHTML2(element) {
9651
- const html2 = element.children.map((child) => DomSerializer2.default(child, { encodeEntities: false })).join("");
9598
+ const html2 = element.children.map(
9599
+ (child) => DomSerializer2.default(child, { encodeEntities: false })
9600
+ ).join("");
9652
9601
  return postprocessTwig(html2, twigBlocks);
9653
9602
  }
9654
9603
  function extractAttributes(element, path20) {
@@ -9663,47 +9612,22 @@ function createTwigLoader() {
9663
9612
  }
9664
9613
  }
9665
9614
  }
9666
- function extractFromElement(element, pathParts) {
9667
- const path20 = pathParts.join("/");
9668
- if (isInsideUnlocalizableTag(element)) {
9669
- return;
9670
- }
9671
- extractAttributes(element, path20);
9672
- const tagName = element.name.toLowerCase();
9673
- if (BLOCK_ELEMENTS.has(tagName) && isLeafBlock(element)) {
9674
- const content = getInnerHTML2(element).trim();
9675
- if (content) {
9676
- result[path20] = content;
9677
- }
9678
- return;
9679
- }
9680
- if (PHRASING_ELEMENTS.has(tagName) && hasTranslatableContent(element)) {
9681
- const content = getInnerHTML2(element).trim();
9682
- if (content) {
9683
- result[path20] = content;
9684
- }
9685
- return;
9686
- }
9687
- let childIndex = 0;
9688
- const childElements = element.children.filter(
9689
- (child) => child.type === "tag"
9690
- );
9691
- for (const child of childElements) {
9692
- extractFromElement(child, [...pathParts, childIndex++]);
9693
- }
9694
- }
9695
- const html = domutils2.findOne(
9615
+ const extractFromElement = createElementExtractor(
9616
+ { getInnerHTML: getInnerHTML2, extractAttributes },
9617
+ result
9618
+ );
9619
+ const html = domutils3.findOne(
9696
9620
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "html",
9697
9621
  dom,
9698
9622
  true
9699
9623
  );
9700
9624
  if (html) {
9701
- const head = domutils2.findOne(
9625
+ const head = domutils3.findOne(
9702
9626
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "head",
9703
9627
  html.children,
9704
9628
  true
9705
9629
  );
9706
- const body = domutils2.findOne(
9630
+ const body = domutils3.findOne(
9707
9631
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "body",
9708
9632
  html.children,
9709
9633
  true
@@ -9744,10 +9668,12 @@ function createTwigLoader() {
9744
9668
  lowerCaseTags: false,
9745
9669
  lowerCaseAttributeNames: false
9746
9670
  });
9747
- parser.write(processed || "<!DOCTYPE html><html><head></head><body></body></html>");
9671
+ parser.write(
9672
+ processed || "<!DOCTYPE html><html><head></head><body></body></html>"
9673
+ );
9748
9674
  parser.end();
9749
9675
  const dom = handler.dom;
9750
- const html = domutils2.findOne(
9676
+ const html = domutils3.findOne(
9751
9677
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "html",
9752
9678
  dom,
9753
9679
  true
@@ -9777,13 +9703,13 @@ function createTwigLoader() {
9777
9703
  let current = null;
9778
9704
  if (html) {
9779
9705
  if (rootTag === "head") {
9780
- current = domutils2.findOne(
9706
+ current = domutils3.findOne(
9781
9707
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "head",
9782
9708
  html.children,
9783
9709
  true
9784
9710
  );
9785
9711
  } else if (rootTag === "body") {
9786
- current = domutils2.findOne(
9712
+ current = domutils3.findOne(
9787
9713
  (elem) => elem.type === "tag" && elem.name.toLowerCase() === "body",
9788
9714
  html.children,
9789
9715
  true
@@ -9831,7 +9757,9 @@ function createTwigLoader() {
9831
9757
  }
9832
9758
  }
9833
9759
  }
9834
- const serialized = DomSerializer2.default(dom, { encodeEntities: false });
9760
+ const serialized = DomSerializer2.default(dom, {
9761
+ encodeEntities: false
9762
+ });
9835
9763
  return postprocessTwig(serialized, twigBlocks);
9836
9764
  }
9837
9765
  });
@@ -15246,7 +15174,7 @@ async function renderHero2() {
15246
15174
  // package.json
15247
15175
  var package_default = {
15248
15176
  name: "lingo.dev",
15249
- version: "0.125.2",
15177
+ version: "0.125.4",
15250
15178
  description: "Lingo.dev CLI",
15251
15179
  private: false,
15252
15180
  repository: {