lingo.dev 0.125.2 → 0.125.3

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