@reteps/tree-sitter-htmlmustache 0.7.3 → 0.8.1
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/README.md +68 -22
- package/cli/out/main.js +946 -429
- package/package.json +2 -1
package/cli/out/main.js
CHANGED
|
@@ -542,8 +542,8 @@ function parseDocument(source) {
|
|
|
542
542
|
}
|
|
543
543
|
|
|
544
544
|
// lsp/server/src/configFile.ts
|
|
545
|
-
var fs = __toESM(require("fs"));
|
|
546
|
-
var path2 = __toESM(require("path"));
|
|
545
|
+
var fs = __toESM(require("fs"), 1);
|
|
546
|
+
var path2 = __toESM(require("path"), 1);
|
|
547
547
|
|
|
548
548
|
// lsp/server/src/ruleMetadata.ts
|
|
549
549
|
var RULES = [
|
|
@@ -586,11 +586,16 @@ var RULES = [
|
|
|
586
586
|
name: "unrecognizedHtmlTags",
|
|
587
587
|
defaultSeverity: "error",
|
|
588
588
|
description: "Flags HTML tags that are not standard HTML elements or valid custom elements"
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
name: "elementContentTooLong",
|
|
592
|
+
defaultSeverity: "off",
|
|
593
|
+
description: "Flags configured elements whose inner content exceeds a byte-length threshold (opt-in; requires `elements: [{ tag, maxBytes }]` option)"
|
|
589
594
|
}
|
|
590
595
|
];
|
|
591
|
-
var KNOWN_RULE_NAMES = new Set(RULES.map((
|
|
596
|
+
var KNOWN_RULE_NAMES = new Set(RULES.map((r2) => r2.name));
|
|
592
597
|
var RULE_DEFAULTS = Object.fromEntries(
|
|
593
|
-
RULES.map((
|
|
598
|
+
RULES.map((r2) => [r2.name, r2.defaultSeverity])
|
|
594
599
|
);
|
|
595
600
|
|
|
596
601
|
// lsp/server/src/configFile.ts
|
|
@@ -614,41 +619,70 @@ var VALID_CSS_DISPLAY_VALUES = /* @__PURE__ */ new Set([
|
|
|
614
619
|
"none"
|
|
615
620
|
]);
|
|
616
621
|
var VALID_RULE_SEVERITIES = /* @__PURE__ */ new Set(["error", "warning", "off"]);
|
|
622
|
+
function parseElementContentTooLongOptions(raw) {
|
|
623
|
+
if (!Array.isArray(raw.elements)) return null;
|
|
624
|
+
const elements = [];
|
|
625
|
+
for (const entry of raw.elements) {
|
|
626
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
627
|
+
const e2 = entry;
|
|
628
|
+
if (typeof e2.tag !== "string" || e2.tag.length === 0) continue;
|
|
629
|
+
if (typeof e2.maxBytes !== "number" || !Number.isFinite(e2.maxBytes) || e2.maxBytes < 0) continue;
|
|
630
|
+
elements.push({ tag: e2.tag, maxBytes: e2.maxBytes });
|
|
631
|
+
}
|
|
632
|
+
return { elements };
|
|
633
|
+
}
|
|
634
|
+
var OPTION_PARSERS = {
|
|
635
|
+
elementContentTooLong: parseElementContentTooLongOptions
|
|
636
|
+
};
|
|
637
|
+
function parseRuleEntry(key, value) {
|
|
638
|
+
if (typeof value === "string") {
|
|
639
|
+
return VALID_RULE_SEVERITIES.has(value) ? value : null;
|
|
640
|
+
}
|
|
641
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
642
|
+
const obj = value;
|
|
643
|
+
if (typeof obj.severity !== "string" || !VALID_RULE_SEVERITIES.has(obj.severity)) return null;
|
|
644
|
+
const severity = obj.severity;
|
|
645
|
+
const parser2 = OPTION_PARSERS[key];
|
|
646
|
+
if (!parser2) return { severity };
|
|
647
|
+
const options = parser2(obj);
|
|
648
|
+
if (!options) return { severity };
|
|
649
|
+
return { severity, ...options };
|
|
650
|
+
}
|
|
617
651
|
var CONFIG_FILENAME = ".htmlmustache.jsonc";
|
|
618
652
|
function parseJsonc(text2) {
|
|
619
653
|
let result = "";
|
|
620
|
-
let
|
|
621
|
-
while (
|
|
622
|
-
if (text2[
|
|
654
|
+
let i2 = 0;
|
|
655
|
+
while (i2 < text2.length) {
|
|
656
|
+
if (text2[i2] === '"') {
|
|
623
657
|
result += '"';
|
|
624
|
-
|
|
625
|
-
while (
|
|
626
|
-
if (text2[
|
|
627
|
-
result += text2[
|
|
628
|
-
|
|
658
|
+
i2++;
|
|
659
|
+
while (i2 < text2.length && text2[i2] !== '"') {
|
|
660
|
+
if (text2[i2] === "\\") {
|
|
661
|
+
result += text2[i2] + (text2[i2 + 1] ?? "");
|
|
662
|
+
i2 += 2;
|
|
629
663
|
} else {
|
|
630
|
-
result += text2[
|
|
631
|
-
|
|
664
|
+
result += text2[i2];
|
|
665
|
+
i2++;
|
|
632
666
|
}
|
|
633
667
|
}
|
|
634
|
-
if (
|
|
668
|
+
if (i2 < text2.length) {
|
|
635
669
|
result += '"';
|
|
636
|
-
|
|
670
|
+
i2++;
|
|
637
671
|
}
|
|
638
672
|
continue;
|
|
639
673
|
}
|
|
640
|
-
if (text2[
|
|
641
|
-
while (
|
|
674
|
+
if (text2[i2] === "/" && text2[i2 + 1] === "/") {
|
|
675
|
+
while (i2 < text2.length && text2[i2] !== "\n") i2++;
|
|
642
676
|
continue;
|
|
643
677
|
}
|
|
644
|
-
if (text2[
|
|
645
|
-
|
|
646
|
-
while (
|
|
647
|
-
|
|
678
|
+
if (text2[i2] === "/" && text2[i2 + 1] === "*") {
|
|
679
|
+
i2 += 2;
|
|
680
|
+
while (i2 < text2.length && !(text2[i2] === "*" && text2[i2 + 1] === "/")) i2++;
|
|
681
|
+
i2 += 2;
|
|
648
682
|
continue;
|
|
649
683
|
}
|
|
650
|
-
result += text2[
|
|
651
|
-
|
|
684
|
+
result += text2[i2];
|
|
685
|
+
i2++;
|
|
652
686
|
}
|
|
653
687
|
result = result.replace(/,\s*([}\]])/g, "$1");
|
|
654
688
|
return JSON.parse(result);
|
|
@@ -674,21 +708,21 @@ function parseCustomTagArray(arr) {
|
|
|
674
708
|
const tags = [];
|
|
675
709
|
for (const entry of arr) {
|
|
676
710
|
if (entry && typeof entry === "object" && "name" in entry) {
|
|
677
|
-
const
|
|
678
|
-
if (typeof
|
|
679
|
-
const tag = { name:
|
|
680
|
-
if (typeof
|
|
681
|
-
tag.display =
|
|
711
|
+
const e2 = entry;
|
|
712
|
+
if (typeof e2.name !== "string" || e2.name.length === 0) continue;
|
|
713
|
+
const tag = { name: e2.name };
|
|
714
|
+
if (typeof e2.display === "string" && VALID_CSS_DISPLAY_VALUES.has(e2.display)) {
|
|
715
|
+
tag.display = e2.display;
|
|
682
716
|
}
|
|
683
|
-
if (typeof
|
|
684
|
-
if (
|
|
685
|
-
tag.languageMap =
|
|
717
|
+
if (typeof e2.languageAttribute === "string") tag.languageAttribute = e2.languageAttribute;
|
|
718
|
+
if (e2.languageMap && typeof e2.languageMap === "object" && !Array.isArray(e2.languageMap)) {
|
|
719
|
+
tag.languageMap = e2.languageMap;
|
|
686
720
|
}
|
|
687
|
-
if (typeof
|
|
688
|
-
if (typeof
|
|
689
|
-
tag.indent =
|
|
721
|
+
if (typeof e2.languageDefault === "string") tag.languageDefault = e2.languageDefault;
|
|
722
|
+
if (typeof e2.indent === "string" && VALID_INDENT_MODES.has(e2.indent)) {
|
|
723
|
+
tag.indent = e2.indent;
|
|
690
724
|
}
|
|
691
|
-
if (typeof
|
|
725
|
+
if (typeof e2.indentAttribute === "string") tag.indentAttribute = e2.indentAttribute;
|
|
692
726
|
tags.push(tag);
|
|
693
727
|
}
|
|
694
728
|
}
|
|
@@ -717,11 +751,11 @@ function validateConfig(raw) {
|
|
|
717
751
|
if (items.length > 0) config.noBreakDelimiters = items;
|
|
718
752
|
}
|
|
719
753
|
if (Array.isArray(obj.include)) {
|
|
720
|
-
const items = obj.include.filter((
|
|
754
|
+
const items = obj.include.filter((s2) => typeof s2 === "string" && s2.length > 0);
|
|
721
755
|
if (items.length > 0) config.include = items;
|
|
722
756
|
}
|
|
723
757
|
if (Array.isArray(obj.exclude)) {
|
|
724
|
-
const items = obj.exclude.filter((
|
|
758
|
+
const items = obj.exclude.filter((s2) => typeof s2 === "string" && s2.length > 0);
|
|
725
759
|
if (items.length > 0) config.exclude = items;
|
|
726
760
|
}
|
|
727
761
|
const parsedCodeTags = parseCustomTagArray(obj.customCodeTags);
|
|
@@ -741,10 +775,11 @@ function validateConfig(raw) {
|
|
|
741
775
|
const rules = {};
|
|
742
776
|
let hasRules = false;
|
|
743
777
|
for (const [key, value] of Object.entries(rawRules)) {
|
|
744
|
-
if (KNOWN_RULE_NAMES.has(key)
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
778
|
+
if (!KNOWN_RULE_NAMES.has(key)) continue;
|
|
779
|
+
const entry = parseRuleEntry(key, value);
|
|
780
|
+
if (entry === null) continue;
|
|
781
|
+
rules[key] = entry;
|
|
782
|
+
hasRules = true;
|
|
748
783
|
}
|
|
749
784
|
if (hasRules) config.rules = rules;
|
|
750
785
|
}
|
|
@@ -752,13 +787,13 @@ function validateConfig(raw) {
|
|
|
752
787
|
const rules = [];
|
|
753
788
|
for (const entry of obj.customRules) {
|
|
754
789
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
755
|
-
const
|
|
756
|
-
if (typeof
|
|
757
|
-
if (typeof
|
|
758
|
-
if (typeof
|
|
759
|
-
const rule = { id:
|
|
760
|
-
if (typeof
|
|
761
|
-
rule.severity =
|
|
790
|
+
const e2 = entry;
|
|
791
|
+
if (typeof e2.id !== "string" || e2.id.length === 0) continue;
|
|
792
|
+
if (typeof e2.selector !== "string" || e2.selector.length === 0) continue;
|
|
793
|
+
if (typeof e2.message !== "string" || e2.message.length === 0) continue;
|
|
794
|
+
const rule = { id: e2.id, selector: e2.selector, message: e2.message };
|
|
795
|
+
if (typeof e2.severity === "string" && VALID_RULE_SEVERITIES.has(e2.severity)) {
|
|
796
|
+
rule.severity = e2.severity;
|
|
762
797
|
}
|
|
763
798
|
rules.push(rule);
|
|
764
799
|
}
|
|
@@ -807,7 +842,7 @@ function isHtmlElementType(node) {
|
|
|
807
842
|
function getTagName(node) {
|
|
808
843
|
for (const child of node.children) {
|
|
809
844
|
if (child.type === "html_start_tag" || child.type === "html_self_closing_tag") {
|
|
810
|
-
const tagNameNode = child.children.find((
|
|
845
|
+
const tagNameNode = child.children.find((c2) => c2.type === "html_tag_name");
|
|
811
846
|
if (tagNameNode) return tagNameNode.text;
|
|
812
847
|
}
|
|
813
848
|
}
|
|
@@ -815,16 +850,33 @@ function getTagName(node) {
|
|
|
815
850
|
}
|
|
816
851
|
function getSectionName(node) {
|
|
817
852
|
const beginNode = node.children.find(
|
|
818
|
-
(
|
|
853
|
+
(c2) => c2.type === "mustache_section_begin" || c2.type === "mustache_inverted_section_begin"
|
|
819
854
|
);
|
|
820
855
|
if (!beginNode) return null;
|
|
821
|
-
const tagNameNode = beginNode.children.find((
|
|
856
|
+
const tagNameNode = beginNode.children.find((c2) => c2.type === "mustache_tag_name");
|
|
822
857
|
return tagNameNode?.text ?? null;
|
|
823
858
|
}
|
|
824
859
|
function getErroneousEndTagName(node) {
|
|
825
|
-
const nameNode = node.children.find((
|
|
860
|
+
const nameNode = node.children.find((c2) => c2.type === "html_erroneous_end_tag_name");
|
|
826
861
|
return nameNode?.text?.toLowerCase() ?? null;
|
|
827
862
|
}
|
|
863
|
+
function getInterpolationPath(node) {
|
|
864
|
+
for (const child of node.children) {
|
|
865
|
+
if (child.type === "mustache_path_expression" || child.type === "mustache_identifier") {
|
|
866
|
+
return child.text;
|
|
867
|
+
}
|
|
868
|
+
if (child.type === ".") return ".";
|
|
869
|
+
}
|
|
870
|
+
return null;
|
|
871
|
+
}
|
|
872
|
+
function getCommentContent(node) {
|
|
873
|
+
const child = node.children.find((c2) => c2.type === "mustache_comment_content");
|
|
874
|
+
return child ? child.text.trim() : null;
|
|
875
|
+
}
|
|
876
|
+
function getPartialName(node) {
|
|
877
|
+
const child = node.children.find((c2) => c2.type === "mustache_partial_content");
|
|
878
|
+
return child ? child.text.trim() : null;
|
|
879
|
+
}
|
|
828
880
|
|
|
829
881
|
// lsp/server/src/htmlBalanceChecker.ts
|
|
830
882
|
function getTagNameLower(element) {
|
|
@@ -834,7 +886,7 @@ function getErroneousEndTagNameLower(node) {
|
|
|
834
886
|
return getErroneousEndTagName(node)?.toLowerCase() ?? null;
|
|
835
887
|
}
|
|
836
888
|
function hasForcedEndTag(element) {
|
|
837
|
-
return element.children.some((
|
|
889
|
+
return element.children.some((c2) => c2.type === "html_forced_end_tag");
|
|
838
890
|
}
|
|
839
891
|
function extractFromNodes(nodes) {
|
|
840
892
|
const items = [];
|
|
@@ -846,13 +898,13 @@ function extractFromNodes(nodes) {
|
|
|
846
898
|
function extractFromNode(node) {
|
|
847
899
|
if (node.type === "html_element") {
|
|
848
900
|
const contentChildren = node.children.filter(
|
|
849
|
-
(
|
|
901
|
+
(c2) => c2.type !== "html_start_tag" && c2.type !== "html_end_tag" && c2.type !== "html_forced_end_tag"
|
|
850
902
|
);
|
|
851
903
|
if (hasForcedEndTag(node)) {
|
|
852
904
|
const tagName = getTagNameLower(node);
|
|
853
905
|
const items = [];
|
|
854
906
|
if (tagName) {
|
|
855
|
-
const startTag = node.children.find((
|
|
907
|
+
const startTag = node.children.find((c2) => c2.type === "html_start_tag");
|
|
856
908
|
items.push({ type: "open", tagName, node: startTag ?? node });
|
|
857
909
|
}
|
|
858
910
|
items.push(...extractFromNodes(contentChildren));
|
|
@@ -874,7 +926,7 @@ function extractFromNode(node) {
|
|
|
874
926
|
const sectionName = getSectionName(node);
|
|
875
927
|
if (sectionName) {
|
|
876
928
|
const contentChildren = node.children.filter(
|
|
877
|
-
(
|
|
929
|
+
(c2) => c2.type !== "mustache_section_begin" && c2.type !== "mustache_section_end" && c2.type !== "mustache_erroneous_section_end"
|
|
878
930
|
);
|
|
879
931
|
return [
|
|
880
932
|
{
|
|
@@ -891,7 +943,7 @@ function extractFromNode(node) {
|
|
|
891
943
|
const sectionName = getSectionName(node);
|
|
892
944
|
if (sectionName) {
|
|
893
945
|
const contentChildren = node.children.filter(
|
|
894
|
-
(
|
|
946
|
+
(c2) => c2.type !== "mustache_inverted_section_begin" && c2.type !== "mustache_inverted_section_end" && c2.type !== "mustache_erroneous_inverted_section_end"
|
|
895
947
|
);
|
|
896
948
|
return [
|
|
897
949
|
{
|
|
@@ -909,17 +961,17 @@ function extractFromNode(node) {
|
|
|
909
961
|
function mergeAdjacentForks(items) {
|
|
910
962
|
if (items.length === 0) return items;
|
|
911
963
|
const result = [];
|
|
912
|
-
let
|
|
913
|
-
while (
|
|
914
|
-
const item = items[
|
|
964
|
+
let i2 = 0;
|
|
965
|
+
while (i2 < items.length) {
|
|
966
|
+
const item = items[i2];
|
|
915
967
|
if (item.type !== "fork") {
|
|
916
968
|
result.push(item);
|
|
917
|
-
|
|
969
|
+
i2++;
|
|
918
970
|
continue;
|
|
919
971
|
}
|
|
920
972
|
const truthy = [...item.truthy];
|
|
921
973
|
const falsy = [...item.falsy];
|
|
922
|
-
let j =
|
|
974
|
+
let j = i2 + 1;
|
|
923
975
|
while (j < items.length) {
|
|
924
976
|
const next = items[j];
|
|
925
977
|
if (next.type !== "fork" || next.sectionName !== item.sectionName) break;
|
|
@@ -933,7 +985,7 @@ function mergeAdjacentForks(items) {
|
|
|
933
985
|
truthy: mergeAdjacentForks(truthy),
|
|
934
986
|
falsy: mergeAdjacentForks(falsy)
|
|
935
987
|
});
|
|
936
|
-
|
|
988
|
+
i2 = j;
|
|
937
989
|
}
|
|
938
990
|
return result;
|
|
939
991
|
}
|
|
@@ -1074,12 +1126,12 @@ function checkUnclosedTags(rootNode) {
|
|
|
1074
1126
|
const errors = [];
|
|
1075
1127
|
function visit(node) {
|
|
1076
1128
|
if (node.type === "html_element") {
|
|
1077
|
-
const hasEndTag = node.children.some((
|
|
1078
|
-
const hasForcedEnd = node.children.some((
|
|
1129
|
+
const hasEndTag = node.children.some((c2) => c2.type === "html_end_tag");
|
|
1130
|
+
const hasForcedEnd = node.children.some((c2) => c2.type === "html_forced_end_tag");
|
|
1079
1131
|
if (!hasEndTag && !hasForcedEnd) {
|
|
1080
1132
|
const tagName = getTagNameLower(node);
|
|
1081
1133
|
if (tagName && !VOID_ELEMENTS.has(tagName) && !OPTIONAL_END_TAG_ELEMENTS.has(tagName)) {
|
|
1082
|
-
const startTag = node.children.find((
|
|
1134
|
+
const startTag = node.children.find((c2) => c2.type === "html_start_tag");
|
|
1083
1135
|
errors.push({
|
|
1084
1136
|
node: startTag ?? node,
|
|
1085
1137
|
message: `Unclosed HTML tag: <${tagName}>`
|
|
@@ -1107,8 +1159,8 @@ function checkHtmlBalance(rootNode) {
|
|
|
1107
1159
|
const totalPaths = 1 << sectionNames.length;
|
|
1108
1160
|
for (let mask = 0; mask < totalPaths; mask++) {
|
|
1109
1161
|
const assignment = /* @__PURE__ */ new Map();
|
|
1110
|
-
for (let
|
|
1111
|
-
assignment.set(sectionNames[
|
|
1162
|
+
for (let i2 = 0; i2 < sectionNames.length; i2++) {
|
|
1163
|
+
assignment.set(sectionNames[i2], (mask & 1 << i2) !== 0);
|
|
1112
1164
|
}
|
|
1113
1165
|
const events = flattenPath(items, assignment);
|
|
1114
1166
|
const condition = formatCondition(assignment);
|
|
@@ -1132,7 +1184,7 @@ function checkNestedSameNameSections(rootNode) {
|
|
|
1132
1184
|
if (name) {
|
|
1133
1185
|
if (ancestors.has(name)) {
|
|
1134
1186
|
const beginNode = node.children.find(
|
|
1135
|
-
(
|
|
1187
|
+
(c2) => c2.type === "mustache_section_begin" || c2.type === "mustache_inverted_section_begin"
|
|
1136
1188
|
);
|
|
1137
1189
|
errors.push({
|
|
1138
1190
|
node: beginNode ?? node,
|
|
@@ -1158,7 +1210,7 @@ function checkUnquotedMustacheAttributes(rootNode) {
|
|
|
1158
1210
|
const errors = [];
|
|
1159
1211
|
function visit(node) {
|
|
1160
1212
|
if (node.type === "html_attribute") {
|
|
1161
|
-
const mustacheNode = node.children.find((
|
|
1213
|
+
const mustacheNode = node.children.find((c2) => c2.type === "mustache_interpolation");
|
|
1162
1214
|
if (mustacheNode) {
|
|
1163
1215
|
errors.push({
|
|
1164
1216
|
node: mustacheNode,
|
|
@@ -1184,9 +1236,9 @@ function checkConsecutiveSameNameSections(rootNode, sourceText) {
|
|
|
1184
1236
|
const errors = [];
|
|
1185
1237
|
function visit(node) {
|
|
1186
1238
|
const children = node.children;
|
|
1187
|
-
for (let
|
|
1188
|
-
const current = children[
|
|
1189
|
-
const next = children[
|
|
1239
|
+
for (let i2 = 0; i2 < children.length - 1; i2++) {
|
|
1240
|
+
const current = children[i2];
|
|
1241
|
+
const next = children[i2 + 1];
|
|
1190
1242
|
if (!isMustacheSection(current) || current.type !== next.type) {
|
|
1191
1243
|
continue;
|
|
1192
1244
|
}
|
|
@@ -1197,12 +1249,12 @@ function checkConsecutiveSameNameSections(rootNode, sourceText) {
|
|
|
1197
1249
|
if (gap.length > 0 && !/^\s*$/.test(gap)) continue;
|
|
1198
1250
|
const endTagType = current.type === "mustache_section" ? "mustache_section_end" : "mustache_inverted_section_end";
|
|
1199
1251
|
const beginTagType = next.type === "mustache_section" ? "mustache_section_begin" : "mustache_inverted_section_begin";
|
|
1200
|
-
const currentEndTag = current.children.find((
|
|
1201
|
-
const nextBeginTag = next.children.find((
|
|
1252
|
+
const currentEndTag = current.children.find((c2) => c2.type === endTagType);
|
|
1253
|
+
const nextBeginTag = next.children.find((c2) => c2.type === beginTagType);
|
|
1202
1254
|
if (!currentEndTag || !nextBeginTag) continue;
|
|
1203
1255
|
const sectionTypeStr = current.type === "mustache_section" ? "#" : "^";
|
|
1204
1256
|
const nextBeginNode = next.children.find(
|
|
1205
|
-
(
|
|
1257
|
+
(c2) => c2.type === "mustache_section_begin" || c2.type === "mustache_inverted_section_begin"
|
|
1206
1258
|
);
|
|
1207
1259
|
errors.push({
|
|
1208
1260
|
node: nextBeginNode ?? next,
|
|
@@ -1252,7 +1304,7 @@ function checkSelfClosingNonVoidTags(rootNode) {
|
|
|
1252
1304
|
const errors = [];
|
|
1253
1305
|
function visit(node) {
|
|
1254
1306
|
if (node.type === "html_self_closing_tag") {
|
|
1255
|
-
const tagNameNode = node.children.find((
|
|
1307
|
+
const tagNameNode = node.children.find((c2) => c2.type === "html_tag_name");
|
|
1256
1308
|
const tagName = tagNameNode?.text.toLowerCase();
|
|
1257
1309
|
if (tagName && !VOID_ELEMENTS2.has(tagName)) {
|
|
1258
1310
|
errors.push({
|
|
@@ -1275,8 +1327,8 @@ function checkSelfClosingNonVoidTags(rootNode) {
|
|
|
1275
1327
|
visit(rootNode);
|
|
1276
1328
|
return errors;
|
|
1277
1329
|
}
|
|
1278
|
-
function areMutuallyExclusive(
|
|
1279
|
-
for (const ac of
|
|
1330
|
+
function areMutuallyExclusive(a2, b) {
|
|
1331
|
+
for (const ac of a2) {
|
|
1280
1332
|
for (const bc of b) {
|
|
1281
1333
|
if (ac.name === bc.name && ac.inverted !== bc.inverted) {
|
|
1282
1334
|
return true;
|
|
@@ -1285,11 +1337,11 @@ function areMutuallyExclusive(a, b) {
|
|
|
1285
1337
|
}
|
|
1286
1338
|
return false;
|
|
1287
1339
|
}
|
|
1288
|
-
function formatConditionClause(
|
|
1340
|
+
function formatConditionClause(a2, b) {
|
|
1289
1341
|
const seen = /* @__PURE__ */ new Map();
|
|
1290
|
-
for (const
|
|
1291
|
-
if (!seen.has(
|
|
1292
|
-
seen.set(
|
|
1342
|
+
for (const c2 of [...a2, ...b]) {
|
|
1343
|
+
if (!seen.has(c2.name)) {
|
|
1344
|
+
seen.set(c2.name, c2.inverted);
|
|
1293
1345
|
}
|
|
1294
1346
|
}
|
|
1295
1347
|
if (seen.size === 0) return "";
|
|
@@ -1302,12 +1354,12 @@ function formatConditionClause(a, b) {
|
|
|
1302
1354
|
function collectAttributes(node, conditions, out) {
|
|
1303
1355
|
for (const child of node.children) {
|
|
1304
1356
|
if (child.type === "html_attribute") {
|
|
1305
|
-
const nameNode = child.children.find((
|
|
1357
|
+
const nameNode = child.children.find((c2) => c2.type === "html_attribute_name");
|
|
1306
1358
|
if (nameNode) {
|
|
1307
1359
|
out.push({ nameNode, conditions: [...conditions] });
|
|
1308
1360
|
}
|
|
1309
1361
|
} else if (child.type === "mustache_attribute") {
|
|
1310
|
-
const section = child.children.find((
|
|
1362
|
+
const section = child.children.find((c2) => isMustacheSection(c2));
|
|
1311
1363
|
if (section) {
|
|
1312
1364
|
const name = getSectionName(section);
|
|
1313
1365
|
if (name) {
|
|
@@ -1528,15 +1580,15 @@ var KNOWN_HTML_TAGS = /* @__PURE__ */ new Set([
|
|
|
1528
1580
|
]);
|
|
1529
1581
|
function checkUnrecognizedHtmlTags(rootNode, customTagNames) {
|
|
1530
1582
|
const errors = [];
|
|
1531
|
-
const customSet = customTagNames ? new Set(customTagNames.map((
|
|
1583
|
+
const customSet = customTagNames ? new Set(customTagNames.map((n2) => n2.toLowerCase())) : void 0;
|
|
1532
1584
|
function visit(node) {
|
|
1533
1585
|
if (node.type === "html_element" || node.type === "html_self_closing_tag") {
|
|
1534
|
-
const tagNameNode = node.type === "html_self_closing_tag" ? node.children.find((
|
|
1586
|
+
const tagNameNode = node.type === "html_self_closing_tag" ? node.children.find((c2) => c2.type === "html_tag_name") : node.children.find((c2) => c2.type === "html_start_tag")?.children.find((c2) => c2.type === "html_tag_name");
|
|
1535
1587
|
const tagName = tagNameNode?.text.toLowerCase();
|
|
1536
1588
|
if (tagName === "svg" || tagName === "math") return;
|
|
1537
1589
|
}
|
|
1538
1590
|
if (node.type === "html_start_tag" || node.type === "html_self_closing_tag") {
|
|
1539
|
-
const tagNameNode = node.children.find((
|
|
1591
|
+
const tagNameNode = node.children.find((c2) => c2.type === "html_tag_name");
|
|
1540
1592
|
if (tagNameNode) {
|
|
1541
1593
|
const tagName = tagNameNode.text.toLowerCase();
|
|
1542
1594
|
if (!KNOWN_HTML_TAGS.has(tagName) && !customSet?.has(tagName)) {
|
|
@@ -1573,19 +1625,19 @@ function checkDuplicateAttributes(rootNode) {
|
|
|
1573
1625
|
}
|
|
1574
1626
|
for (const [, group2] of groups) {
|
|
1575
1627
|
if (group2.length < 2) continue;
|
|
1576
|
-
for (let
|
|
1628
|
+
for (let i2 = 1; i2 < group2.length; i2++) {
|
|
1577
1629
|
let conflictIdx = -1;
|
|
1578
|
-
for (let j = 0; j <
|
|
1579
|
-
if (!areMutuallyExclusive(group2[
|
|
1630
|
+
for (let j = 0; j < i2; j++) {
|
|
1631
|
+
if (!areMutuallyExclusive(group2[i2].conditions, group2[j].conditions)) {
|
|
1580
1632
|
conflictIdx = j;
|
|
1581
1633
|
break;
|
|
1582
1634
|
}
|
|
1583
1635
|
}
|
|
1584
1636
|
if (conflictIdx >= 0) {
|
|
1585
|
-
const clause = formatConditionClause(group2[conflictIdx].conditions, group2[
|
|
1637
|
+
const clause = formatConditionClause(group2[conflictIdx].conditions, group2[i2].conditions);
|
|
1586
1638
|
errors.push({
|
|
1587
|
-
node: group2[
|
|
1588
|
-
message: `Duplicate attribute "${group2[
|
|
1639
|
+
node: group2[i2].nameNode,
|
|
1640
|
+
message: `Duplicate attribute "${group2[i2].nameNode.text}"${clause}`
|
|
1589
1641
|
});
|
|
1590
1642
|
}
|
|
1591
1643
|
}
|
|
@@ -1599,272 +1651,721 @@ function checkDuplicateAttributes(rootNode) {
|
|
|
1599
1651
|
visit(rootNode);
|
|
1600
1652
|
return errors;
|
|
1601
1653
|
}
|
|
1654
|
+
function checkElementContentTooLong(rootNode, elements) {
|
|
1655
|
+
const errors = [];
|
|
1656
|
+
if (elements.length === 0) return errors;
|
|
1657
|
+
const thresholds = /* @__PURE__ */ new Map();
|
|
1658
|
+
for (const { tag, maxBytes } of elements) {
|
|
1659
|
+
const key = tag.toLowerCase();
|
|
1660
|
+
const existing = thresholds.get(key);
|
|
1661
|
+
if (existing === void 0 || maxBytes < existing) thresholds.set(key, maxBytes);
|
|
1662
|
+
}
|
|
1663
|
+
function visit(node) {
|
|
1664
|
+
if (node.type === "html_element") {
|
|
1665
|
+
const startTag = node.children.find((c2) => c2.type === "html_start_tag");
|
|
1666
|
+
const endTag = node.children.find((c2) => c2.type === "html_end_tag");
|
|
1667
|
+
const tagNameNode = startTag?.children.find((c2) => c2.type === "html_tag_name");
|
|
1668
|
+
const tagName = tagNameNode?.text.toLowerCase();
|
|
1669
|
+
if (tagName && startTag && endTag) {
|
|
1670
|
+
const maxBytes = thresholds.get(tagName);
|
|
1671
|
+
if (maxBytes !== void 0) {
|
|
1672
|
+
const innerBytes = endTag.startIndex - startTag.endIndex;
|
|
1673
|
+
if (innerBytes > maxBytes) {
|
|
1674
|
+
errors.push({
|
|
1675
|
+
node: startTag,
|
|
1676
|
+
message: `<${tagName}> content is ${innerBytes} bytes, exceeds limit of ${maxBytes}`
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
for (const child of node.children) {
|
|
1683
|
+
visit(child);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
visit(rootNode);
|
|
1687
|
+
return errors;
|
|
1688
|
+
}
|
|
1602
1689
|
|
|
1603
|
-
//
|
|
1604
|
-
|
|
1605
|
-
|
|
1690
|
+
// node_modules/parsel-js/dist/parsel.min.js
|
|
1691
|
+
var e = { attribute: /\[\s*(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?(?<name>[-\w\P{ASCII}]+)\s*(?:(?<operator>\W?=)\s*(?<value>.+?)\s*(\s(?<caseSensitive>[iIsS]))?\s*)?\]/gu, id: /#(?<name>[-\w\P{ASCII}]+)/gu, class: /\.(?<name>[-\w\P{ASCII}]+)/gu, comma: /\s*,\s*/g, combinator: /\s*[\s>+~]\s*/g, "pseudo-element": /::(?<name>[-\w\P{ASCII}]+)(?:\((?<argument>¶*)\))?/gu, "pseudo-class": /:(?<name>[-\w\P{ASCII}]+)(?:\((?<argument>¶*)\))?/gu, universal: /(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?\*/gu, type: /(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?(?<name>[-\w\P{ASCII}]+)/gu };
|
|
1692
|
+
var t = /* @__PURE__ */ new Set(["combinator", "comma"]);
|
|
1693
|
+
var n = /* @__PURE__ */ new Set(["not", "is", "where", "has", "matches", "-moz-any", "-webkit-any", "nth-child", "nth-last-child"]);
|
|
1694
|
+
var s = /(?<index>[\dn+-]+)\s+of\s+(?<subtree>.+)/;
|
|
1695
|
+
var r = { "nth-child": s, "nth-last-child": s };
|
|
1696
|
+
var o = (t2) => {
|
|
1697
|
+
switch (t2) {
|
|
1698
|
+
case "pseudo-element":
|
|
1699
|
+
case "pseudo-class":
|
|
1700
|
+
return new RegExp(e[t2].source.replace("(?<argument>\xB6*)", "(?<argument>.*)"), "gu");
|
|
1701
|
+
default:
|
|
1702
|
+
return e[t2];
|
|
1703
|
+
}
|
|
1704
|
+
};
|
|
1705
|
+
function c(e2, t2) {
|
|
1706
|
+
let n2 = 0, s2 = "";
|
|
1707
|
+
for (; t2 < e2.length; t2++) {
|
|
1708
|
+
const r2 = e2[t2];
|
|
1709
|
+
switch (r2) {
|
|
1710
|
+
case "(":
|
|
1711
|
+
++n2;
|
|
1712
|
+
break;
|
|
1713
|
+
case ")":
|
|
1714
|
+
--n2;
|
|
1715
|
+
}
|
|
1716
|
+
if (s2 += r2, 0 === n2) return s2;
|
|
1717
|
+
}
|
|
1718
|
+
return s2;
|
|
1719
|
+
}
|
|
1720
|
+
function i(n2, s2 = e) {
|
|
1721
|
+
if (!n2) return [];
|
|
1722
|
+
const r2 = [n2];
|
|
1723
|
+
for (const [e2, t2] of Object.entries(s2)) for (let n3 = 0; n3 < r2.length; n3++) {
|
|
1724
|
+
const s3 = r2[n3];
|
|
1725
|
+
if ("string" != typeof s3) continue;
|
|
1726
|
+
t2.lastIndex = 0;
|
|
1727
|
+
const o3 = t2.exec(s3);
|
|
1728
|
+
if (!o3) continue;
|
|
1729
|
+
const c2 = o3.index - 1, i2 = [], a2 = o3[0], l2 = s3.slice(0, c2 + 1);
|
|
1730
|
+
l2 && i2.push(l2), i2.push({ ...o3.groups, type: e2, content: a2 });
|
|
1731
|
+
const u2 = s3.slice(c2 + a2.length + 1);
|
|
1732
|
+
u2 && i2.push(u2), r2.splice(n3, 1, ...i2);
|
|
1733
|
+
}
|
|
1734
|
+
let o2 = 0;
|
|
1735
|
+
for (const e2 of r2) switch (typeof e2) {
|
|
1736
|
+
case "string":
|
|
1737
|
+
throw new Error(`Unexpected sequence ${e2} found at index ${o2}`);
|
|
1738
|
+
case "object":
|
|
1739
|
+
o2 += e2.content.length, e2.pos = [o2 - e2.content.length, o2], t.has(e2.type) && (e2.content = e2.content.trim() || " ");
|
|
1740
|
+
}
|
|
1741
|
+
return r2;
|
|
1742
|
+
}
|
|
1743
|
+
var a = /(['"])([^\\\n]*?)\1/g;
|
|
1744
|
+
var l = /\\./g;
|
|
1745
|
+
function u(t2, n2 = e) {
|
|
1746
|
+
if ("" === (t2 = t2.trim())) return [];
|
|
1747
|
+
const s2 = [];
|
|
1748
|
+
t2 = (t2 = t2.replace(l, ((e2, t3) => (s2.push({ value: e2, offset: t3 }), "\uE000".repeat(e2.length))))).replace(a, ((e2, t3, n3, r3) => (s2.push({ value: e2, offset: r3 }), `${t3}${"\uE001".repeat(n3.length)}${t3}`)));
|
|
1749
|
+
{
|
|
1750
|
+
let e2, n3 = 0;
|
|
1751
|
+
for (; (e2 = t2.indexOf("(", n3)) > -1; ) {
|
|
1752
|
+
const r3 = c(t2, e2);
|
|
1753
|
+
s2.push({ value: r3, offset: e2 }), t2 = `${t2.substring(0, e2)}(${"\xB6".repeat(r3.length - 2)})${t2.substring(e2 + r3.length)}`, n3 = e2 + r3.length;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
const r2 = i(t2, n2), u2 = /* @__PURE__ */ new Set();
|
|
1757
|
+
for (const e2 of s2.reverse()) for (const t3 of r2) {
|
|
1758
|
+
const { offset: n3, value: s3 } = e2;
|
|
1759
|
+
if (!(t3.pos[0] <= n3 && n3 + s3.length <= t3.pos[1])) continue;
|
|
1760
|
+
const { content: r3 } = t3, o2 = n3 - t3.pos[0];
|
|
1761
|
+
t3.content = r3.slice(0, o2) + s3 + r3.slice(o2 + s3.length), t3.content !== r3 && u2.add(t3);
|
|
1762
|
+
}
|
|
1763
|
+
for (const e2 of u2) {
|
|
1764
|
+
const t3 = o(e2.type);
|
|
1765
|
+
if (!t3) throw new Error(`Unknown token type: ${e2.type}`);
|
|
1766
|
+
t3.lastIndex = 0;
|
|
1767
|
+
const n3 = t3.exec(e2.content);
|
|
1768
|
+
if (!n3) throw new Error(`Unable to parse content for ${e2.type}: ${e2.content}`);
|
|
1769
|
+
Object.assign(e2, n3.groups);
|
|
1770
|
+
}
|
|
1771
|
+
return r2;
|
|
1772
|
+
}
|
|
1773
|
+
function f(e2, { list: t2 = true } = {}) {
|
|
1774
|
+
if (t2 && e2.find(((e3) => "comma" === e3.type))) {
|
|
1775
|
+
const t3 = [], n2 = [];
|
|
1776
|
+
for (let s2 = 0; s2 < e2.length; s2++) if ("comma" === e2[s2].type) {
|
|
1777
|
+
if (0 === n2.length) throw new Error("Incorrect comma at " + s2);
|
|
1778
|
+
t3.push(f(n2, { list: false })), n2.length = 0;
|
|
1779
|
+
} else n2.push(e2[s2]);
|
|
1780
|
+
if (0 === n2.length) throw new Error("Trailing comma");
|
|
1781
|
+
return t3.push(f(n2, { list: false })), { type: "list", list: t3 };
|
|
1782
|
+
}
|
|
1783
|
+
for (let t3 = e2.length - 1; t3 >= 0; t3--) {
|
|
1784
|
+
let n2 = e2[t3];
|
|
1785
|
+
if ("combinator" === n2.type) {
|
|
1786
|
+
let s2 = e2.slice(0, t3), r2 = e2.slice(t3 + 1);
|
|
1787
|
+
return 0 === s2.length ? { type: "relative", combinator: n2.content, right: f(r2) } : { type: "complex", combinator: n2.content, left: f(s2), right: f(r2) };
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
switch (e2.length) {
|
|
1791
|
+
case 0:
|
|
1792
|
+
throw new Error("Could not build AST.");
|
|
1793
|
+
case 1:
|
|
1794
|
+
return e2[0];
|
|
1795
|
+
default:
|
|
1796
|
+
return { type: "compound", list: [...e2] };
|
|
1797
|
+
}
|
|
1606
1798
|
}
|
|
1607
|
-
function
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
const attr = parseOneAttribute(raw, pos, false);
|
|
1621
|
-
if (!attr) return attrs;
|
|
1622
|
-
if (raw[pos.i] !== "]") return attrs;
|
|
1623
|
-
pos.i++;
|
|
1624
|
-
attrs.push(attr);
|
|
1625
|
-
} else {
|
|
1799
|
+
function* p(e2, t2) {
|
|
1800
|
+
switch (e2.type) {
|
|
1801
|
+
case "list":
|
|
1802
|
+
for (let t3 of e2.list) yield* p(t3, e2);
|
|
1803
|
+
break;
|
|
1804
|
+
case "complex":
|
|
1805
|
+
yield* p(e2.left, e2), yield* p(e2.right, e2);
|
|
1806
|
+
break;
|
|
1807
|
+
case "relative":
|
|
1808
|
+
yield* p(e2.right, e2);
|
|
1809
|
+
break;
|
|
1810
|
+
case "compound":
|
|
1811
|
+
yield* e2.list.map(((t3) => [t3, e2]));
|
|
1626
1812
|
break;
|
|
1813
|
+
default:
|
|
1814
|
+
yield [e2, t2];
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
function m(e2, { recursive: t2 = true, list: s2 = true } = {}) {
|
|
1818
|
+
const o2 = u(e2);
|
|
1819
|
+
if (!o2) return;
|
|
1820
|
+
const c2 = f(o2, { list: s2 });
|
|
1821
|
+
if (!t2) return c2;
|
|
1822
|
+
for (const [e3] of p(c2)) {
|
|
1823
|
+
if ("pseudo-class" !== e3.type || !e3.argument) continue;
|
|
1824
|
+
if (!n.has(e3.name)) continue;
|
|
1825
|
+
let t3 = e3.argument;
|
|
1826
|
+
const s3 = r[e3.name];
|
|
1827
|
+
if (s3) {
|
|
1828
|
+
const n2 = s3.exec(t3);
|
|
1829
|
+
if (!n2) continue;
|
|
1830
|
+
Object.assign(e3, n2.groups), t3 = n2.groups.subtree;
|
|
1627
1831
|
}
|
|
1832
|
+
t3 && Object.assign(e3, { subtree: m(t3, { recursive: true, list: true }) });
|
|
1628
1833
|
}
|
|
1629
|
-
return
|
|
1834
|
+
return c2;
|
|
1630
1835
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1836
|
+
|
|
1837
|
+
// lsp/server/src/selectorMatcher.ts
|
|
1838
|
+
var MUSTACHE_KIND_PSEUDO = /* @__PURE__ */ new Set([
|
|
1839
|
+
"m-section",
|
|
1840
|
+
"m-inverted",
|
|
1841
|
+
"m-variable",
|
|
1842
|
+
"m-raw",
|
|
1843
|
+
"m-comment",
|
|
1844
|
+
"m-partial"
|
|
1845
|
+
]);
|
|
1846
|
+
function preprocessMustacheLiterals(raw) {
|
|
1847
|
+
let out = "";
|
|
1848
|
+
let i2 = 0;
|
|
1849
|
+
const len = raw.length;
|
|
1850
|
+
while (i2 < len) {
|
|
1851
|
+
const ch = raw[i2];
|
|
1852
|
+
if (ch === '"' || ch === "'") {
|
|
1853
|
+
out += ch;
|
|
1854
|
+
i2++;
|
|
1855
|
+
while (i2 < len && raw[i2] !== ch) {
|
|
1856
|
+
if (raw[i2] === "\\" && i2 + 1 < len) {
|
|
1857
|
+
out += raw[i2] + raw[i2 + 1];
|
|
1858
|
+
i2 += 2;
|
|
1859
|
+
} else {
|
|
1860
|
+
out += raw[i2];
|
|
1861
|
+
i2++;
|
|
1862
|
+
}
|
|
1648
1863
|
}
|
|
1649
|
-
if (
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1864
|
+
if (i2 < len) {
|
|
1865
|
+
out += raw[i2];
|
|
1866
|
+
i2++;
|
|
1867
|
+
}
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
if (ch !== "{" || raw[i2 + 1] !== "{") {
|
|
1871
|
+
out += ch;
|
|
1872
|
+
i2++;
|
|
1873
|
+
continue;
|
|
1874
|
+
}
|
|
1875
|
+
if (raw[i2 + 2] === "{") {
|
|
1876
|
+
const end2 = raw.indexOf("}}}", i2 + 3);
|
|
1877
|
+
if (end2 < 0) return null;
|
|
1878
|
+
const inner = raw.slice(i2 + 3, end2).trim();
|
|
1879
|
+
if (inner.length === 0) return null;
|
|
1880
|
+
out += `:m-raw(${inner})`;
|
|
1881
|
+
i2 = end2 + 3;
|
|
1882
|
+
continue;
|
|
1883
|
+
}
|
|
1884
|
+
const end = raw.indexOf("}}", i2 + 2);
|
|
1885
|
+
if (end < 0) return null;
|
|
1886
|
+
const body = raw.slice(i2 + 2, end);
|
|
1887
|
+
i2 = end + 2;
|
|
1888
|
+
const sigil = body.trimStart()[0];
|
|
1889
|
+
const content = body.replace(/^\s*[#^!>/]\s*/, "").replace(/^\s+|\s+$/g, "");
|
|
1890
|
+
switch (sigil) {
|
|
1891
|
+
case "#":
|
|
1892
|
+
if (content.length === 0) return null;
|
|
1893
|
+
out += `:m-section(${content})`;
|
|
1894
|
+
break;
|
|
1895
|
+
case "^":
|
|
1896
|
+
if (content.length === 0) return null;
|
|
1897
|
+
out += `:m-inverted(${content})`;
|
|
1898
|
+
break;
|
|
1899
|
+
case "!":
|
|
1900
|
+
if (content.length === 0) return null;
|
|
1901
|
+
out += `:m-comment(${content})`;
|
|
1902
|
+
break;
|
|
1903
|
+
case ">":
|
|
1904
|
+
if (content.length === 0) return null;
|
|
1905
|
+
out += `:m-partial(${content})`;
|
|
1906
|
+
break;
|
|
1907
|
+
case "/":
|
|
1908
|
+
return null;
|
|
1909
|
+
case "=":
|
|
1910
|
+
return null;
|
|
1911
|
+
default: {
|
|
1912
|
+
const path5 = body.trim();
|
|
1913
|
+
if (path5.length === 0) return null;
|
|
1914
|
+
out += `:m-variable(${path5})`;
|
|
1915
|
+
break;
|
|
1654
1916
|
}
|
|
1655
1917
|
}
|
|
1656
1918
|
}
|
|
1657
|
-
return
|
|
1919
|
+
return out;
|
|
1658
1920
|
}
|
|
1659
1921
|
function parseSelector(raw) {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
alternatives.push(alt);
|
|
1669
|
-
}
|
|
1670
|
-
return { alternatives };
|
|
1671
|
-
}
|
|
1672
|
-
function parseSingleSelector(raw) {
|
|
1673
|
-
const segments = [];
|
|
1674
|
-
let i = 0;
|
|
1675
|
-
let nextCombinator = "descendant";
|
|
1676
|
-
while (i < raw.length) {
|
|
1677
|
-
while (i < raw.length && raw[i] === " ") i++;
|
|
1678
|
-
if (i >= raw.length) break;
|
|
1679
|
-
if (raw[i] === ">") {
|
|
1680
|
-
if (segments.length === 0) return null;
|
|
1681
|
-
nextCombinator = "child";
|
|
1682
|
-
i++;
|
|
1683
|
-
while (i < raw.length && raw[i] === " ") i++;
|
|
1684
|
-
if (i >= raw.length) return null;
|
|
1685
|
-
continue;
|
|
1686
|
-
}
|
|
1687
|
-
const pos = { i };
|
|
1688
|
-
const segment = parseOneSegment(raw, pos);
|
|
1689
|
-
if (!segment) return null;
|
|
1690
|
-
i = pos.i;
|
|
1691
|
-
segment.combinator = nextCombinator;
|
|
1692
|
-
nextCombinator = "descendant";
|
|
1693
|
-
segments.push(segment);
|
|
1922
|
+
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
1923
|
+
const preprocessed = preprocessMustacheLiterals(raw);
|
|
1924
|
+
if (preprocessed === null) return null;
|
|
1925
|
+
let ast;
|
|
1926
|
+
try {
|
|
1927
|
+
ast = m(preprocessed);
|
|
1928
|
+
} catch {
|
|
1929
|
+
return null;
|
|
1694
1930
|
}
|
|
1695
|
-
if (
|
|
1696
|
-
|
|
1931
|
+
if (!ast) return null;
|
|
1932
|
+
const tops = ast.type === "list" ? ast.list : [ast];
|
|
1933
|
+
const alts = [];
|
|
1934
|
+
for (const top of tops) {
|
|
1935
|
+
const segments = [];
|
|
1936
|
+
if (!collectSegments(top, "descendant", segments)) return null;
|
|
1937
|
+
if (segments.length === 0) return null;
|
|
1938
|
+
alts.push(segments);
|
|
1939
|
+
}
|
|
1940
|
+
return alts.length > 0 ? alts : null;
|
|
1941
|
+
}
|
|
1942
|
+
function collectSegments(ast, combinator, out) {
|
|
1943
|
+
if (ast.type === "complex") {
|
|
1944
|
+
const mapped = mapCombinator(ast.combinator);
|
|
1945
|
+
if (!mapped) return false;
|
|
1946
|
+
return collectSegments(ast.left, "descendant", out) && collectSegments(ast.right, mapped, out);
|
|
1947
|
+
}
|
|
1948
|
+
if (ast.type === "list" || ast.type === "relative") return false;
|
|
1949
|
+
const segment = segmentFromCompound(ast);
|
|
1950
|
+
if (!segment) return false;
|
|
1951
|
+
segment.combinator = combinator;
|
|
1952
|
+
out.push(segment);
|
|
1953
|
+
return true;
|
|
1697
1954
|
}
|
|
1698
|
-
function
|
|
1955
|
+
function mapCombinator(c2) {
|
|
1956
|
+
const trimmed = c2.trim();
|
|
1957
|
+
if (trimmed === "") return "descendant";
|
|
1958
|
+
if (trimmed === ">") return "child";
|
|
1959
|
+
return null;
|
|
1960
|
+
}
|
|
1961
|
+
function segmentFromCompound(ast) {
|
|
1962
|
+
const tokens = ast.type === "compound" ? ast.list : [ast];
|
|
1699
1963
|
let kind;
|
|
1700
|
-
let name;
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1964
|
+
let name = null;
|
|
1965
|
+
let pathRegex;
|
|
1966
|
+
let rootOnly = false;
|
|
1967
|
+
const attributes = [];
|
|
1968
|
+
const descendantChecks = [];
|
|
1969
|
+
const forbidChange = (requested) => {
|
|
1970
|
+
if (kind === void 0) return false;
|
|
1971
|
+
if (kind === requested) return false;
|
|
1972
|
+
return true;
|
|
1973
|
+
};
|
|
1974
|
+
for (const token of tokens) {
|
|
1975
|
+
switch (token.type) {
|
|
1976
|
+
case "type":
|
|
1977
|
+
if (forbidChange("html")) return null;
|
|
1978
|
+
kind = "html";
|
|
1979
|
+
name = token.name.toLowerCase();
|
|
1980
|
+
break;
|
|
1981
|
+
case "universal":
|
|
1982
|
+
if (forbidChange("html")) return null;
|
|
1983
|
+
kind = "html";
|
|
1984
|
+
name = null;
|
|
1985
|
+
break;
|
|
1986
|
+
case "class":
|
|
1987
|
+
if (forbidChange("html")) return null;
|
|
1988
|
+
kind = "html";
|
|
1989
|
+
attributes.push(classConstraint(token, false));
|
|
1990
|
+
break;
|
|
1991
|
+
case "id":
|
|
1992
|
+
if (forbidChange("html")) return null;
|
|
1993
|
+
kind = "html";
|
|
1994
|
+
attributes.push(idConstraint(token, false));
|
|
1995
|
+
break;
|
|
1996
|
+
case "attribute": {
|
|
1997
|
+
if (forbidChange("html")) return null;
|
|
1998
|
+
if (kind === void 0) kind = "html";
|
|
1999
|
+
const c2 = attributeConstraint(token, false);
|
|
2000
|
+
if (!c2) return null;
|
|
2001
|
+
attributes.push(c2);
|
|
2002
|
+
break;
|
|
2003
|
+
}
|
|
2004
|
+
case "pseudo-class": {
|
|
2005
|
+
if (MUSTACHE_KIND_PSEUDO.has(token.name)) {
|
|
2006
|
+
const mustacheKind = mustacheKindFromMarker(token.name);
|
|
2007
|
+
if (mustacheKind === null) return null;
|
|
2008
|
+
if (forbidChange(mustacheKind)) return null;
|
|
2009
|
+
kind = mustacheKind;
|
|
2010
|
+
const glob = parseGlob(token.argument ?? "");
|
|
2011
|
+
name = glob.name;
|
|
2012
|
+
pathRegex = glob.pathRegex;
|
|
2013
|
+
break;
|
|
2014
|
+
}
|
|
2015
|
+
if (token.name === "has") {
|
|
2016
|
+
const sel = subtreeToSelector(token.subtree);
|
|
2017
|
+
if (!sel) return null;
|
|
2018
|
+
descendantChecks.push({ selector: sel, negated: false });
|
|
2019
|
+
break;
|
|
2020
|
+
}
|
|
2021
|
+
if (token.name === "not") {
|
|
2022
|
+
if (!applyNegatedSubtree(token.subtree, attributes, descendantChecks)) return null;
|
|
2023
|
+
break;
|
|
2024
|
+
}
|
|
2025
|
+
if (token.name === "root") {
|
|
2026
|
+
rootOnly = true;
|
|
2027
|
+
if (kind === void 0) kind = "html";
|
|
2028
|
+
break;
|
|
2029
|
+
}
|
|
2030
|
+
return null;
|
|
2031
|
+
}
|
|
2032
|
+
default:
|
|
2033
|
+
return null;
|
|
2034
|
+
}
|
|
1719
2035
|
}
|
|
1720
|
-
if (
|
|
2036
|
+
if (kind === void 0) {
|
|
1721
2037
|
kind = "html";
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
if (
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
kind
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
2038
|
+
}
|
|
2039
|
+
if (rootOnly) {
|
|
2040
|
+
if (name !== null || attributes.length > 0 || kind !== "html") return null;
|
|
2041
|
+
}
|
|
2042
|
+
const isHtml = kind === "html";
|
|
2043
|
+
const finalAttrs = isHtml ? attributes : [];
|
|
2044
|
+
return { kind, rootOnly, name, pathRegex, attributes: finalAttrs, descendantChecks, combinator: "descendant" };
|
|
2045
|
+
}
|
|
2046
|
+
function mustacheKindFromMarker(name) {
|
|
2047
|
+
switch (name) {
|
|
2048
|
+
case "m-section":
|
|
2049
|
+
return "section";
|
|
2050
|
+
case "m-inverted":
|
|
2051
|
+
return "inverted";
|
|
2052
|
+
case "m-variable":
|
|
2053
|
+
return "variable";
|
|
2054
|
+
case "m-raw":
|
|
2055
|
+
return "raw";
|
|
2056
|
+
case "m-comment":
|
|
2057
|
+
return "comment";
|
|
2058
|
+
case "m-partial":
|
|
2059
|
+
return "partial";
|
|
2060
|
+
default:
|
|
2061
|
+
return null;
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
function parseGlob(arg) {
|
|
2065
|
+
const trimmed = arg.trim();
|
|
2066
|
+
if (trimmed === "" || trimmed === "*") {
|
|
2067
|
+
return { name: null };
|
|
2068
|
+
}
|
|
2069
|
+
if (!trimmed.includes("*")) {
|
|
2070
|
+
return { name: trimmed.toLowerCase() };
|
|
2071
|
+
}
|
|
2072
|
+
const escaped = trimmed.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
2073
|
+
const pathRegex = new RegExp(`^${escaped}$`, "i");
|
|
2074
|
+
return { name: trimmed.toLowerCase(), pathRegex };
|
|
2075
|
+
}
|
|
2076
|
+
function attributeConstraint(token, negated) {
|
|
2077
|
+
const name = token.name.toLowerCase();
|
|
2078
|
+
if (token.operator === void 0) {
|
|
2079
|
+
return { name, op: "=", value: void 0, negated };
|
|
2080
|
+
}
|
|
2081
|
+
let op;
|
|
2082
|
+
switch (token.operator) {
|
|
2083
|
+
case "=":
|
|
2084
|
+
op = "=";
|
|
2085
|
+
break;
|
|
2086
|
+
case "^=":
|
|
2087
|
+
op = "^=";
|
|
2088
|
+
break;
|
|
2089
|
+
case "*=":
|
|
2090
|
+
op = "*=";
|
|
2091
|
+
break;
|
|
2092
|
+
case "$=":
|
|
2093
|
+
op = "$=";
|
|
2094
|
+
break;
|
|
2095
|
+
case "~=":
|
|
2096
|
+
op = "~=";
|
|
2097
|
+
break;
|
|
2098
|
+
default:
|
|
2099
|
+
return null;
|
|
2100
|
+
}
|
|
2101
|
+
return { name, op, value: stripQuotes(token.value ?? ""), negated };
|
|
2102
|
+
}
|
|
2103
|
+
function classConstraint(token, negated) {
|
|
2104
|
+
return { name: "class", op: "~=", value: token.name, negated };
|
|
2105
|
+
}
|
|
2106
|
+
function idConstraint(token, negated) {
|
|
2107
|
+
return { name: "id", op: "=", value: token.name, negated };
|
|
2108
|
+
}
|
|
2109
|
+
function applyNegatedSubtree(subtree, attributes, descendantChecks) {
|
|
2110
|
+
if (!subtree) return false;
|
|
2111
|
+
if (subtree.type === "attribute") {
|
|
2112
|
+
const c2 = attributeConstraint(subtree, true);
|
|
2113
|
+
if (!c2) return false;
|
|
2114
|
+
attributes.push(c2);
|
|
2115
|
+
return true;
|
|
2116
|
+
}
|
|
2117
|
+
if (subtree.type === "class") {
|
|
2118
|
+
attributes.push(classConstraint(subtree, true));
|
|
2119
|
+
return true;
|
|
2120
|
+
}
|
|
2121
|
+
if (subtree.type === "id") {
|
|
2122
|
+
attributes.push(idConstraint(subtree, true));
|
|
2123
|
+
return true;
|
|
2124
|
+
}
|
|
2125
|
+
if (subtree.type === "pseudo-class" && subtree.name === "has") {
|
|
2126
|
+
const sel = subtreeToSelector(subtree.subtree);
|
|
2127
|
+
if (!sel) return false;
|
|
2128
|
+
descendantChecks.push({ selector: sel, negated: true });
|
|
2129
|
+
return true;
|
|
2130
|
+
}
|
|
2131
|
+
return false;
|
|
2132
|
+
}
|
|
2133
|
+
function subtreeToSelector(subtree) {
|
|
2134
|
+
if (!subtree) return null;
|
|
2135
|
+
const tops = subtree.type === "list" ? subtree.list : [subtree];
|
|
2136
|
+
const alts = [];
|
|
2137
|
+
for (const top of tops) {
|
|
2138
|
+
const segments = [];
|
|
2139
|
+
if (!collectSegments(top, "descendant", segments)) return null;
|
|
2140
|
+
if (segments.length === 0) return null;
|
|
2141
|
+
alts.push(segments);
|
|
2142
|
+
}
|
|
2143
|
+
return alts.length > 0 ? alts : null;
|
|
2144
|
+
}
|
|
2145
|
+
function stripQuotes(raw) {
|
|
2146
|
+
if (raw.length < 2) return raw;
|
|
2147
|
+
const first = raw[0];
|
|
2148
|
+
const last = raw[raw.length - 1];
|
|
2149
|
+
if ((first === '"' || first === "'") && first === last) {
|
|
2150
|
+
return raw.slice(1, -1);
|
|
2151
|
+
}
|
|
2152
|
+
return raw;
|
|
2153
|
+
}
|
|
2154
|
+
function ancestorKindForNode(node) {
|
|
2155
|
+
if (HTML_ELEMENT_TYPES.has(node.type)) return "html";
|
|
2156
|
+
if (node.type === "mustache_section") return "section";
|
|
2157
|
+
if (node.type === "mustache_inverted_section") return "inverted";
|
|
2158
|
+
return null;
|
|
2159
|
+
}
|
|
2160
|
+
function getHtmlAttributes(node) {
|
|
1739
2161
|
const startTag = node.children.find(
|
|
1740
|
-
(
|
|
2162
|
+
(c2) => c2.type === "html_start_tag" || c2.type === "html_self_closing_tag"
|
|
1741
2163
|
);
|
|
1742
2164
|
if (!startTag) return [];
|
|
1743
2165
|
const attrs = [];
|
|
1744
2166
|
for (const child of startTag.children) {
|
|
1745
|
-
if (child.type
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
}
|
|
2167
|
+
if (child.type !== "html_attribute") continue;
|
|
2168
|
+
let attrName = "";
|
|
2169
|
+
let attrValue;
|
|
2170
|
+
for (const part of child.children) {
|
|
2171
|
+
if (part.type === "html_attribute_name") {
|
|
2172
|
+
attrName = part.text.toLowerCase();
|
|
2173
|
+
} else if (part.type === "html_quoted_attribute_value") {
|
|
2174
|
+
attrValue = part.text.replace(/^["']|["']$/g, "");
|
|
2175
|
+
} else if (part.type === "html_attribute_value") {
|
|
2176
|
+
attrValue = part.text;
|
|
1756
2177
|
}
|
|
1757
|
-
if (attrName) attrs.push({ name: attrName, value: attrValue });
|
|
1758
2178
|
}
|
|
2179
|
+
if (attrName) attrs.push({ name: attrName, value: attrValue });
|
|
1759
2180
|
}
|
|
1760
2181
|
return attrs;
|
|
1761
2182
|
}
|
|
2183
|
+
function matchesAttributeValue(has, c2) {
|
|
2184
|
+
if (has === void 0 || c2.value === void 0) return false;
|
|
2185
|
+
const v = c2.value;
|
|
2186
|
+
if (v === "") return false;
|
|
2187
|
+
switch (c2.op) {
|
|
2188
|
+
case "=":
|
|
2189
|
+
return has === v;
|
|
2190
|
+
case "^=":
|
|
2191
|
+
return has.startsWith(v);
|
|
2192
|
+
case "*=":
|
|
2193
|
+
return has.includes(v);
|
|
2194
|
+
case "$=":
|
|
2195
|
+
return has.endsWith(v);
|
|
2196
|
+
case "~=":
|
|
2197
|
+
return has.split(/\s+/).includes(v);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
1762
2200
|
function checkAttributes(node, constraints) {
|
|
1763
2201
|
if (constraints.length === 0) return true;
|
|
1764
|
-
const nodeAttrs =
|
|
1765
|
-
for (const
|
|
1766
|
-
const found = nodeAttrs.find((
|
|
1767
|
-
if (
|
|
1768
|
-
if (found)
|
|
1769
|
-
|
|
1770
|
-
if (
|
|
1771
|
-
|
|
2202
|
+
const nodeAttrs = getHtmlAttributes(node);
|
|
2203
|
+
for (const c2 of constraints) {
|
|
2204
|
+
const found = nodeAttrs.find((a2) => a2.name === c2.name);
|
|
2205
|
+
if (c2.negated) {
|
|
2206
|
+
if (!found) continue;
|
|
2207
|
+
if (c2.value === void 0) return false;
|
|
2208
|
+
if (matchesAttributeValue(found.value, c2)) return false;
|
|
2209
|
+
continue;
|
|
2210
|
+
}
|
|
2211
|
+
if (c2.value === void 0) {
|
|
1772
2212
|
if (!found) return false;
|
|
2213
|
+
continue;
|
|
1773
2214
|
}
|
|
2215
|
+
if (!found || !matchesAttributeValue(found.value, c2)) return false;
|
|
1774
2216
|
}
|
|
1775
2217
|
return true;
|
|
1776
2218
|
}
|
|
1777
|
-
function
|
|
1778
|
-
if (
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
if (tagName !== segment.name) return false;
|
|
1783
|
-
}
|
|
1784
|
-
return checkAttributes(node, segment.attributes);
|
|
1785
|
-
}
|
|
1786
|
-
if (!MUSTACHE_SECTION_TYPES.has(node.type)) return false;
|
|
1787
|
-
if (segment.name !== null) {
|
|
1788
|
-
const sectionName = getSectionName(node)?.toLowerCase();
|
|
1789
|
-
if (sectionName !== segment.name) return false;
|
|
2219
|
+
function checkDescendants(node, checks) {
|
|
2220
|
+
if (checks.length === 0) return true;
|
|
2221
|
+
for (const check of checks) {
|
|
2222
|
+
const present = hasDescendantMatch(node, check.selector);
|
|
2223
|
+
if (check.negated ? present : !present) return false;
|
|
1790
2224
|
}
|
|
1791
2225
|
return true;
|
|
1792
2226
|
}
|
|
2227
|
+
function hasDescendantMatch(node, selector) {
|
|
2228
|
+
for (const child of node.children) {
|
|
2229
|
+
if (matchSelector(child, selector).length > 0) return true;
|
|
2230
|
+
}
|
|
2231
|
+
return false;
|
|
2232
|
+
}
|
|
2233
|
+
function matchesName(actual, segment) {
|
|
2234
|
+
if (segment.name === null) return true;
|
|
2235
|
+
if (actual === null) return false;
|
|
2236
|
+
if (segment.pathRegex) return segment.pathRegex.test(actual);
|
|
2237
|
+
return actual === segment.name;
|
|
2238
|
+
}
|
|
2239
|
+
function nodeMatchesSegment(node, segment, rootNode) {
|
|
2240
|
+
if (segment.rootOnly) {
|
|
2241
|
+
if (node !== rootNode) return false;
|
|
2242
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2243
|
+
}
|
|
2244
|
+
switch (segment.kind) {
|
|
2245
|
+
case "html": {
|
|
2246
|
+
if (!HTML_ELEMENT_TYPES.has(node.type)) return false;
|
|
2247
|
+
if (segment.name !== null) {
|
|
2248
|
+
const tagName = getTagName(node)?.toLowerCase();
|
|
2249
|
+
if (tagName !== segment.name) return false;
|
|
2250
|
+
}
|
|
2251
|
+
return checkAttributes(node, segment.attributes) && checkDescendants(node, segment.descendantChecks);
|
|
2252
|
+
}
|
|
2253
|
+
case "section":
|
|
2254
|
+
if (node.type !== "mustache_section") return false;
|
|
2255
|
+
if (!matchesName(getSectionName(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2256
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2257
|
+
case "inverted":
|
|
2258
|
+
if (node.type !== "mustache_inverted_section") return false;
|
|
2259
|
+
if (!matchesName(getSectionName(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2260
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2261
|
+
case "variable":
|
|
2262
|
+
if (node.type !== "mustache_interpolation") return false;
|
|
2263
|
+
if (!matchesName(getInterpolationPath(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2264
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2265
|
+
case "raw":
|
|
2266
|
+
if (node.type !== "mustache_triple") return false;
|
|
2267
|
+
if (!matchesName(getInterpolationPath(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2268
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2269
|
+
case "comment":
|
|
2270
|
+
if (node.type !== "mustache_comment") return false;
|
|
2271
|
+
if (!matchesName(getCommentContent(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2272
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2273
|
+
case "partial":
|
|
2274
|
+
if (node.type !== "mustache_partial") return false;
|
|
2275
|
+
if (!matchesName(getPartialName(node)?.toLowerCase() ?? null, segment)) return false;
|
|
2276
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
1793
2279
|
function checkAncestors(ancestors, segments, segIdx, childCombinator) {
|
|
1794
2280
|
if (segIdx < 0) return true;
|
|
1795
2281
|
const segment = segments[segIdx];
|
|
2282
|
+
const ancestorKind = ancestorKindForSegment(segment);
|
|
2283
|
+
if (ancestorKind === null) return false;
|
|
1796
2284
|
if (childCombinator === "child") {
|
|
1797
|
-
for (let
|
|
1798
|
-
const entry = ancestors[
|
|
1799
|
-
if (entry.kind !==
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
if (!checkAttributes(entry.node, segment.attributes)) return false;
|
|
2285
|
+
for (let a2 = ancestors.length - 1; a2 >= 0; a2--) {
|
|
2286
|
+
const entry = ancestors[a2];
|
|
2287
|
+
if (entry.kind !== ancestorKind) {
|
|
2288
|
+
if (ancestorKind === "root" && entry.kind === "html") return false;
|
|
2289
|
+
continue;
|
|
1803
2290
|
}
|
|
1804
|
-
|
|
2291
|
+
if (!matchesName(entry.name, segment)) return false;
|
|
2292
|
+
if (segment.kind === "html" && !checkAttributes(entry.node, segment.attributes)) return false;
|
|
2293
|
+
if (!checkDescendants(entry.node, segment.descendantChecks)) return false;
|
|
2294
|
+
return checkAncestors(ancestors.slice(0, a2), segments, segIdx - 1, segment.combinator);
|
|
1805
2295
|
}
|
|
1806
2296
|
return false;
|
|
1807
2297
|
}
|
|
1808
|
-
for (let
|
|
1809
|
-
const entry = ancestors[
|
|
1810
|
-
if (entry.kind !==
|
|
1811
|
-
if (
|
|
1812
|
-
if (segment.kind === "html" && segment.attributes
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
if (checkAncestors(ancestors.slice(0, a), segments, segIdx - 1, segment.combinator)) {
|
|
2298
|
+
for (let a2 = ancestors.length - 1; a2 >= 0; a2--) {
|
|
2299
|
+
const entry = ancestors[a2];
|
|
2300
|
+
if (entry.kind !== ancestorKind) continue;
|
|
2301
|
+
if (!matchesName(entry.name, segment)) continue;
|
|
2302
|
+
if (segment.kind === "html" && !checkAttributes(entry.node, segment.attributes)) continue;
|
|
2303
|
+
if (!checkDescendants(entry.node, segment.descendantChecks)) continue;
|
|
2304
|
+
if (checkAncestors(ancestors.slice(0, a2), segments, segIdx - 1, segment.combinator)) {
|
|
1816
2305
|
return true;
|
|
1817
2306
|
}
|
|
1818
2307
|
}
|
|
1819
2308
|
return false;
|
|
1820
2309
|
}
|
|
1821
|
-
function
|
|
2310
|
+
function ancestorKindForSegment(segment) {
|
|
2311
|
+
if (segment.rootOnly) return "root";
|
|
2312
|
+
if (segment.kind === "html") return "html";
|
|
2313
|
+
if (segment.kind === "section") return "section";
|
|
2314
|
+
if (segment.kind === "inverted") return "inverted";
|
|
2315
|
+
return null;
|
|
2316
|
+
}
|
|
2317
|
+
function getReportNode(node, rootNode) {
|
|
1822
2318
|
if (HTML_ELEMENT_TYPES.has(node.type)) {
|
|
1823
2319
|
const startTag = node.children.find(
|
|
1824
|
-
(
|
|
2320
|
+
(c2) => c2.type === "html_start_tag" || c2.type === "html_self_closing_tag"
|
|
1825
2321
|
);
|
|
1826
2322
|
return startTag ?? node;
|
|
1827
2323
|
}
|
|
1828
|
-
if (
|
|
2324
|
+
if (node.type === "mustache_section" || node.type === "mustache_inverted_section") {
|
|
1829
2325
|
const begin = node.children.find(
|
|
1830
|
-
(
|
|
2326
|
+
(c2) => c2.type === "mustache_section_begin" || c2.type === "mustache_inverted_section_begin"
|
|
1831
2327
|
);
|
|
1832
2328
|
return begin ?? node;
|
|
1833
2329
|
}
|
|
2330
|
+
if (rootNode && node === rootNode) {
|
|
2331
|
+
return {
|
|
2332
|
+
type: node.type,
|
|
2333
|
+
text: "",
|
|
2334
|
+
startPosition: node.startPosition,
|
|
2335
|
+
endPosition: { row: node.startPosition.row, column: node.startPosition.column + 1 },
|
|
2336
|
+
startIndex: node.startIndex,
|
|
2337
|
+
endIndex: Math.min(node.startIndex + 1, node.endIndex),
|
|
2338
|
+
children: []
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
1834
2341
|
return node;
|
|
1835
2342
|
}
|
|
1836
|
-
function matchAlternative(rootNode,
|
|
2343
|
+
function matchAlternative(rootNode, segments) {
|
|
1837
2344
|
const results = [];
|
|
1838
|
-
const lastSegment =
|
|
2345
|
+
const lastSegment = segments[segments.length - 1];
|
|
1839
2346
|
function walk(node, ancestors) {
|
|
1840
|
-
if (nodeMatchesSegment(node, lastSegment)) {
|
|
1841
|
-
if (
|
|
1842
|
-
results.push(getReportNode(node));
|
|
2347
|
+
if (nodeMatchesSegment(node, lastSegment, rootNode)) {
|
|
2348
|
+
if (segments.length === 1 || checkAncestors(ancestors, segments, segments.length - 2, lastSegment.combinator)) {
|
|
2349
|
+
results.push(getReportNode(node, rootNode));
|
|
1843
2350
|
}
|
|
1844
2351
|
}
|
|
1845
2352
|
let newAncestors = ancestors;
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
} else if (MUSTACHE_SECTION_TYPES.has(node.type)) {
|
|
1852
|
-
const sectionName = getSectionName(node)?.toLowerCase();
|
|
1853
|
-
if (sectionName) {
|
|
1854
|
-
newAncestors = [...ancestors, { kind: "mustache", name: sectionName, node }];
|
|
2353
|
+
const ancestorKind = ancestorKindForNode(node);
|
|
2354
|
+
if (ancestorKind !== null) {
|
|
2355
|
+
const name = ancestorKind === "html" ? getTagName(node)?.toLowerCase() : getSectionName(node)?.toLowerCase();
|
|
2356
|
+
if (name) {
|
|
2357
|
+
newAncestors = [...ancestors, { kind: ancestorKind, name, node }];
|
|
1855
2358
|
}
|
|
1856
2359
|
}
|
|
1857
|
-
for (const child of node.children)
|
|
1858
|
-
walk(child, newAncestors);
|
|
1859
|
-
}
|
|
2360
|
+
for (const child of node.children) walk(child, newAncestors);
|
|
1860
2361
|
}
|
|
1861
|
-
walk(rootNode, []);
|
|
2362
|
+
walk(rootNode, [{ kind: "root", name: "", node: rootNode }]);
|
|
1862
2363
|
return results;
|
|
1863
2364
|
}
|
|
1864
2365
|
function matchSelector(rootNode, selector) {
|
|
1865
2366
|
const allResults = [];
|
|
1866
2367
|
const seen = /* @__PURE__ */ new Set();
|
|
1867
|
-
for (const alt of selector
|
|
2368
|
+
for (const alt of selector) {
|
|
1868
2369
|
for (const node of matchAlternative(rootNode, alt)) {
|
|
1869
2370
|
if (!seen.has(node)) {
|
|
1870
2371
|
seen.add(node);
|
|
@@ -1883,7 +2384,7 @@ var ERROR_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
1883
2384
|
]);
|
|
1884
2385
|
function errorMessageForNode(nodeType, node) {
|
|
1885
2386
|
if (nodeType === "mustache_erroneous_section_end" || nodeType === "mustache_erroneous_inverted_section_end") {
|
|
1886
|
-
const tagNameNode = node.children.find((
|
|
2387
|
+
const tagNameNode = node.children.find((c2) => c2.type === "mustache_erroneous_tag_name");
|
|
1887
2388
|
return `Mismatched mustache section: {{/${tagNameNode?.text || "?"}}}`;
|
|
1888
2389
|
}
|
|
1889
2390
|
if (nodeType === "ERROR") {
|
|
@@ -1891,8 +2392,17 @@ function errorMessageForNode(nodeType, node) {
|
|
|
1891
2392
|
}
|
|
1892
2393
|
return `Missing ${nodeType}`;
|
|
1893
2394
|
}
|
|
1894
|
-
function
|
|
1895
|
-
|
|
2395
|
+
function resolveRuleConfig(rules, ruleName) {
|
|
2396
|
+
const entry = rules?.[ruleName];
|
|
2397
|
+
let severity;
|
|
2398
|
+
if (entry === void 0) {
|
|
2399
|
+
severity = RULE_DEFAULTS[ruleName] ?? "off";
|
|
2400
|
+
} else if (typeof entry === "string") {
|
|
2401
|
+
severity = entry;
|
|
2402
|
+
} else {
|
|
2403
|
+
severity = entry.severity;
|
|
2404
|
+
}
|
|
2405
|
+
return { severity, entry };
|
|
1896
2406
|
}
|
|
1897
2407
|
function parseDisableDirective(node, customRuleIds) {
|
|
1898
2408
|
if (node.type !== "html_comment" && node.type !== "mustache_comment") return null;
|
|
@@ -1954,7 +2464,7 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
1954
2464
|
for (const error of unclosedErrors) {
|
|
1955
2465
|
errors.push({ node: error.node, message: error.message });
|
|
1956
2466
|
}
|
|
1957
|
-
const customRuleIds = customRules ? new Set(customRules.map((
|
|
2467
|
+
const customRuleIds = customRules ? new Set(customRules.map((r2) => r2.id)) : void 0;
|
|
1958
2468
|
const disabledRules = collectDisabledRules(tree.rootNode, customRuleIds);
|
|
1959
2469
|
const effectiveRules = { ...rules };
|
|
1960
2470
|
for (const rule of disabledRules) {
|
|
@@ -1969,12 +2479,19 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
1969
2479
|
{ rule: "duplicateAttributes", errors: () => checkDuplicateAttributes(tree.rootNode) },
|
|
1970
2480
|
{ rule: "unescapedEntities", errors: () => checkUnescapedEntities(tree.rootNode) },
|
|
1971
2481
|
{ rule: "preferMustacheComments", errors: () => checkHtmlComments(tree.rootNode) },
|
|
1972
|
-
{ rule: "unrecognizedHtmlTags", errors: () => checkUnrecognizedHtmlTags(tree.rootNode, customTagNames) }
|
|
2482
|
+
{ rule: "unrecognizedHtmlTags", errors: () => checkUnrecognizedHtmlTags(tree.rootNode, customTagNames) },
|
|
2483
|
+
{
|
|
2484
|
+
rule: "elementContentTooLong",
|
|
2485
|
+
errors: (entry) => {
|
|
2486
|
+
const elements = (entry && typeof entry === "object" ? entry.elements : void 0) ?? [];
|
|
2487
|
+
return checkElementContentTooLong(tree.rootNode, elements);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
1973
2490
|
];
|
|
1974
2491
|
for (const { rule, errors: getErrors } of ruleChecks) {
|
|
1975
|
-
const severity =
|
|
2492
|
+
const { severity, entry } = resolveRuleConfig(effectiveRules, rule);
|
|
1976
2493
|
if (severity === "off") continue;
|
|
1977
|
-
for (const error of getErrors()) {
|
|
2494
|
+
for (const error of getErrors(entry)) {
|
|
1978
2495
|
errors.push({
|
|
1979
2496
|
node: error.node,
|
|
1980
2497
|
message: error.message,
|
|
@@ -1999,7 +2516,7 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
1999
2516
|
}
|
|
2000
2517
|
}
|
|
2001
2518
|
return errors.filter(
|
|
2002
|
-
(
|
|
2519
|
+
(e2) => !(e2.message.includes("HTML comment found") && parseDisableDirective(e2.node, customRuleIds) !== null)
|
|
2003
2520
|
);
|
|
2004
2521
|
}
|
|
2005
2522
|
|
|
@@ -2029,12 +2546,12 @@ function formatError(error, source) {
|
|
|
2029
2546
|
const contextStart = Math.max(0, errorLine - 2);
|
|
2030
2547
|
const contextEnd = Math.min(lines.length - 1, error.endLine - 1);
|
|
2031
2548
|
const gutterWidth = String(contextEnd + 1).length;
|
|
2032
|
-
const pad = (
|
|
2549
|
+
const pad = (n2) => String(n2).padStart(gutterWidth);
|
|
2033
2550
|
const outputLines = [header];
|
|
2034
2551
|
outputLines.push(source_default.dim(" ".repeat(gutterWidth) + " |"));
|
|
2035
|
-
for (let
|
|
2036
|
-
const lineNum =
|
|
2037
|
-
outputLines.push(source_default.dim(`${pad(lineNum)} |`) + " " + lines[
|
|
2552
|
+
for (let i2 = contextStart; i2 <= contextEnd; i2++) {
|
|
2553
|
+
const lineNum = i2 + 1;
|
|
2554
|
+
outputLines.push(source_default.dim(`${pad(lineNum)} |`) + " " + lines[i2]);
|
|
2038
2555
|
}
|
|
2039
2556
|
const lastErrorLineIdx = error.endLine - 1;
|
|
2040
2557
|
const lastLine = lines[lastErrorLineIdx] || "";
|
|
@@ -2108,7 +2625,7 @@ function resolveFiles(cliPatterns) {
|
|
|
2108
2625
|
return { files: [], config };
|
|
2109
2626
|
}
|
|
2110
2627
|
let files = expandGlobs(patterns);
|
|
2111
|
-
files = files.filter((
|
|
2628
|
+
files = files.filter((f2) => !DEFAULT_EXCLUDE_SEGMENTS.some((seg) => f2.includes(seg)));
|
|
2112
2629
|
if (config?.exclude && config.exclude.length > 0) {
|
|
2113
2630
|
const cwd = process.cwd();
|
|
2114
2631
|
const excludeSet = /* @__PURE__ */ new Set();
|
|
@@ -2121,7 +2638,7 @@ function resolveFiles(cliPatterns) {
|
|
|
2121
2638
|
}
|
|
2122
2639
|
}
|
|
2123
2640
|
}
|
|
2124
|
-
files = files.filter((
|
|
2641
|
+
files = files.filter((f2) => !excludeSet.has(f2));
|
|
2125
2642
|
}
|
|
2126
2643
|
return { files, config };
|
|
2127
2644
|
}
|
|
@@ -2133,13 +2650,13 @@ function applyFixes(source, errors) {
|
|
|
2133
2650
|
}
|
|
2134
2651
|
}
|
|
2135
2652
|
if (replacements.length === 0) return source;
|
|
2136
|
-
replacements.sort((
|
|
2653
|
+
replacements.sort((a2, b) => b.startIndex - a2.startIndex);
|
|
2137
2654
|
let result = source;
|
|
2138
2655
|
let minIndex = Infinity;
|
|
2139
|
-
for (const
|
|
2140
|
-
if (
|
|
2141
|
-
result = result.slice(0,
|
|
2142
|
-
minIndex =
|
|
2656
|
+
for (const r2 of replacements) {
|
|
2657
|
+
if (r2.endIndex > minIndex) continue;
|
|
2658
|
+
result = result.slice(0, r2.startIndex) + r2.newText + result.slice(r2.endIndex);
|
|
2659
|
+
minIndex = r2.startIndex;
|
|
2143
2660
|
}
|
|
2144
2661
|
return result;
|
|
2145
2662
|
}
|
|
@@ -2168,7 +2685,7 @@ async function run(args) {
|
|
|
2168
2685
|
return 0;
|
|
2169
2686
|
}
|
|
2170
2687
|
const fixMode = args.includes("--fix");
|
|
2171
|
-
const patterns = args.filter((
|
|
2688
|
+
const patterns = args.filter((a2) => a2 !== "--fix");
|
|
2172
2689
|
const { files, config } = resolveFiles(patterns);
|
|
2173
2690
|
if (files.length === 0) {
|
|
2174
2691
|
if (patterns.length === 0 && (!config?.include || config.include.length === 0)) {
|
|
@@ -2177,8 +2694,8 @@ async function run(args) {
|
|
|
2177
2694
|
}
|
|
2178
2695
|
const displayPatterns = patterns.length > 0 ? patterns : config?.include ?? [];
|
|
2179
2696
|
console.error(source_default.yellow("No files matched the given patterns:"));
|
|
2180
|
-
for (const
|
|
2181
|
-
console.error(source_default.yellow(` ${
|
|
2697
|
+
for (const p2 of displayPatterns) {
|
|
2698
|
+
console.error(source_default.yellow(` ${p2}`));
|
|
2182
2699
|
}
|
|
2183
2700
|
return 1;
|
|
2184
2701
|
}
|
|
@@ -2189,7 +2706,7 @@ async function run(args) {
|
|
|
2189
2706
|
const cwd = process.cwd();
|
|
2190
2707
|
const errorOutput = [];
|
|
2191
2708
|
const rules = config?.rules;
|
|
2192
|
-
const customTagNames = config?.customTags?.map((
|
|
2709
|
+
const customTagNames = config?.customTags?.map((t2) => t2.name);
|
|
2193
2710
|
const customRules = config?.customRules;
|
|
2194
2711
|
for (const file of files) {
|
|
2195
2712
|
const displayPath = import_node_path.default.relative(cwd, file) || file;
|
|
@@ -2205,8 +2722,8 @@ async function run(args) {
|
|
|
2205
2722
|
}
|
|
2206
2723
|
const tree = parseDocument(source);
|
|
2207
2724
|
const errors = collectErrors2(tree, displayPath, rules, customTagNames, customRules);
|
|
2208
|
-
const fileErrors = errors.filter((
|
|
2209
|
-
const fileWarnings = errors.filter((
|
|
2725
|
+
const fileErrors = errors.filter((e2) => e2.severity !== "warning");
|
|
2726
|
+
const fileWarnings = errors.filter((e2) => e2.severity === "warning");
|
|
2210
2727
|
if (errors.length > 0) {
|
|
2211
2728
|
filesWithErrors++;
|
|
2212
2729
|
totalErrors += fileErrors.length;
|
|
@@ -2271,8 +2788,8 @@ var FullTextDocument = class _FullTextDocument {
|
|
|
2271
2788
|
let lineOffsets = this._lineOffsets;
|
|
2272
2789
|
const addedLineOffsets = computeLineOffsets(change.text, false, startOffset);
|
|
2273
2790
|
if (endLine - startLine === addedLineOffsets.length) {
|
|
2274
|
-
for (let
|
|
2275
|
-
lineOffsets[
|
|
2791
|
+
for (let i2 = 0, len = addedLineOffsets.length; i2 < len; i2++) {
|
|
2792
|
+
lineOffsets[i2 + startLine + 1] = addedLineOffsets[i2];
|
|
2276
2793
|
}
|
|
2277
2794
|
} else {
|
|
2278
2795
|
if (addedLineOffsets.length < 1e4) {
|
|
@@ -2283,8 +2800,8 @@ var FullTextDocument = class _FullTextDocument {
|
|
|
2283
2800
|
}
|
|
2284
2801
|
const diff = change.text.length - (endOffset - startOffset);
|
|
2285
2802
|
if (diff !== 0) {
|
|
2286
|
-
for (let
|
|
2287
|
-
lineOffsets[
|
|
2803
|
+
for (let i2 = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i2 < len; i2++) {
|
|
2804
|
+
lineOffsets[i2] = lineOffsets[i2] + diff;
|
|
2288
2805
|
}
|
|
2289
2806
|
}
|
|
2290
2807
|
} else if (_FullTextDocument.isFull(change)) {
|
|
@@ -2371,26 +2888,26 @@ var TextDocument;
|
|
|
2371
2888
|
TextDocument2.update = update;
|
|
2372
2889
|
function applyEdits(document, edits) {
|
|
2373
2890
|
const text2 = document.getText();
|
|
2374
|
-
const sortedEdits = mergeSort(edits.map(getWellformedEdit), (
|
|
2375
|
-
const diff =
|
|
2891
|
+
const sortedEdits = mergeSort(edits.map(getWellformedEdit), (a2, b) => {
|
|
2892
|
+
const diff = a2.range.start.line - b.range.start.line;
|
|
2376
2893
|
if (diff === 0) {
|
|
2377
|
-
return
|
|
2894
|
+
return a2.range.start.character - b.range.start.character;
|
|
2378
2895
|
}
|
|
2379
2896
|
return diff;
|
|
2380
2897
|
});
|
|
2381
2898
|
let lastModifiedOffset = 0;
|
|
2382
2899
|
const spans = [];
|
|
2383
|
-
for (const
|
|
2384
|
-
const startOffset = document.offsetAt(
|
|
2900
|
+
for (const e2 of sortedEdits) {
|
|
2901
|
+
const startOffset = document.offsetAt(e2.range.start);
|
|
2385
2902
|
if (startOffset < lastModifiedOffset) {
|
|
2386
2903
|
throw new Error("Overlapping edit");
|
|
2387
2904
|
} else if (startOffset > lastModifiedOffset) {
|
|
2388
2905
|
spans.push(text2.substring(lastModifiedOffset, startOffset));
|
|
2389
2906
|
}
|
|
2390
|
-
if (
|
|
2391
|
-
spans.push(
|
|
2907
|
+
if (e2.newText.length) {
|
|
2908
|
+
spans.push(e2.newText);
|
|
2392
2909
|
}
|
|
2393
|
-
lastModifiedOffset = document.offsetAt(
|
|
2910
|
+
lastModifiedOffset = document.offsetAt(e2.range.end);
|
|
2394
2911
|
}
|
|
2395
2912
|
spans.push(text2.substr(lastModifiedOffset));
|
|
2396
2913
|
return spans.join("");
|
|
@@ -2401,39 +2918,39 @@ function mergeSort(data, compare) {
|
|
|
2401
2918
|
if (data.length <= 1) {
|
|
2402
2919
|
return data;
|
|
2403
2920
|
}
|
|
2404
|
-
const
|
|
2405
|
-
const left = data.slice(0,
|
|
2406
|
-
const right = data.slice(
|
|
2921
|
+
const p2 = data.length / 2 | 0;
|
|
2922
|
+
const left = data.slice(0, p2);
|
|
2923
|
+
const right = data.slice(p2);
|
|
2407
2924
|
mergeSort(left, compare);
|
|
2408
2925
|
mergeSort(right, compare);
|
|
2409
2926
|
let leftIdx = 0;
|
|
2410
2927
|
let rightIdx = 0;
|
|
2411
|
-
let
|
|
2928
|
+
let i2 = 0;
|
|
2412
2929
|
while (leftIdx < left.length && rightIdx < right.length) {
|
|
2413
2930
|
const ret = compare(left[leftIdx], right[rightIdx]);
|
|
2414
2931
|
if (ret <= 0) {
|
|
2415
|
-
data[
|
|
2932
|
+
data[i2++] = left[leftIdx++];
|
|
2416
2933
|
} else {
|
|
2417
|
-
data[
|
|
2934
|
+
data[i2++] = right[rightIdx++];
|
|
2418
2935
|
}
|
|
2419
2936
|
}
|
|
2420
2937
|
while (leftIdx < left.length) {
|
|
2421
|
-
data[
|
|
2938
|
+
data[i2++] = left[leftIdx++];
|
|
2422
2939
|
}
|
|
2423
2940
|
while (rightIdx < right.length) {
|
|
2424
|
-
data[
|
|
2941
|
+
data[i2++] = right[rightIdx++];
|
|
2425
2942
|
}
|
|
2426
2943
|
return data;
|
|
2427
2944
|
}
|
|
2428
2945
|
function computeLineOffsets(text2, isAtLineStart, textOffset = 0) {
|
|
2429
2946
|
const result = isAtLineStart ? [textOffset] : [];
|
|
2430
|
-
for (let
|
|
2431
|
-
const ch = text2.charCodeAt(
|
|
2947
|
+
for (let i2 = 0; i2 < text2.length; i2++) {
|
|
2948
|
+
const ch = text2.charCodeAt(i2);
|
|
2432
2949
|
if (isEOL(ch)) {
|
|
2433
|
-
if (ch === 13 &&
|
|
2434
|
-
|
|
2950
|
+
if (ch === 13 && i2 + 1 < text2.length && text2.charCodeAt(i2 + 1) === 10) {
|
|
2951
|
+
i2++;
|
|
2435
2952
|
}
|
|
2436
|
-
result.push(textOffset +
|
|
2953
|
+
result.push(textOffset + i2 + 1);
|
|
2437
2954
|
}
|
|
2438
2955
|
}
|
|
2439
2956
|
return result;
|
|
@@ -2466,8 +2983,8 @@ function print(doc, options) {
|
|
|
2466
2983
|
}
|
|
2467
2984
|
function currentColumn(output) {
|
|
2468
2985
|
let col = 0;
|
|
2469
|
-
for (let
|
|
2470
|
-
const chunk = output[
|
|
2986
|
+
for (let i2 = output.length - 1; i2 >= 0; i2--) {
|
|
2987
|
+
const chunk = output[i2];
|
|
2471
2988
|
const nlIndex = chunk.lastIndexOf("\n");
|
|
2472
2989
|
if (nlIndex !== -1) {
|
|
2473
2990
|
col += chunk.length - nlIndex - 1;
|
|
@@ -2577,12 +3094,12 @@ function printDoc(doc, state, output, options) {
|
|
|
2577
3094
|
function printFill(parts, state, output, options) {
|
|
2578
3095
|
if (parts.length === 0) return;
|
|
2579
3096
|
const printWidth = options.printWidth ?? 80;
|
|
2580
|
-
for (let
|
|
2581
|
-
const content = parts[
|
|
2582
|
-
const separator =
|
|
3097
|
+
for (let i2 = 0; i2 < parts.length; i2++) {
|
|
3098
|
+
const content = parts[i2];
|
|
3099
|
+
const separator = i2 + 1 < parts.length ? parts[i2 + 1] : null;
|
|
2583
3100
|
printDoc(content, state, output, options);
|
|
2584
3101
|
if (separator === null) break;
|
|
2585
|
-
const nextContent =
|
|
3102
|
+
const nextContent = i2 + 2 < parts.length ? parts[i2 + 2] : null;
|
|
2586
3103
|
if (nextContent !== null) {
|
|
2587
3104
|
const testOutput = [];
|
|
2588
3105
|
const flatState = { ...state, mode: "flat" };
|
|
@@ -2600,7 +3117,7 @@ function printFill(parts, state, output, options) {
|
|
|
2600
3117
|
} else {
|
|
2601
3118
|
printDoc(separator, state, output, options);
|
|
2602
3119
|
}
|
|
2603
|
-
|
|
3120
|
+
i2++;
|
|
2604
3121
|
}
|
|
2605
3122
|
}
|
|
2606
3123
|
function makeIndent(level, options) {
|
|
@@ -2633,10 +3150,10 @@ function indent(contents) {
|
|
|
2633
3150
|
if (contents === "") return "";
|
|
2634
3151
|
return { type: "indent", contents };
|
|
2635
3152
|
}
|
|
2636
|
-
function indentN(contents,
|
|
2637
|
-
if (
|
|
3153
|
+
function indentN(contents, n2) {
|
|
3154
|
+
if (n2 <= 0 || contents === "") return contents;
|
|
2638
3155
|
let result = contents;
|
|
2639
|
-
for (let
|
|
3156
|
+
for (let i2 = 0; i2 < n2; i2++) {
|
|
2640
3157
|
result = indent(result);
|
|
2641
3158
|
}
|
|
2642
3159
|
return result;
|
|
@@ -2650,7 +3167,7 @@ function ifBreak(breakContents, flatContents, options) {
|
|
|
2650
3167
|
return { type: "ifBreak", breakContents, flatContents, groupId: options?.groupId };
|
|
2651
3168
|
}
|
|
2652
3169
|
function fill(parts) {
|
|
2653
|
-
const filtered = parts.filter((
|
|
3170
|
+
const filtered = parts.filter((p2) => p2 !== "");
|
|
2654
3171
|
if (filtered.length === 0) return "";
|
|
2655
3172
|
if (filtered.length === 1) return filtered[0];
|
|
2656
3173
|
return { type: "fill", parts: filtered };
|
|
@@ -2661,12 +3178,12 @@ function isLine(doc) {
|
|
|
2661
3178
|
|
|
2662
3179
|
// lsp/server/src/formatting/utils.ts
|
|
2663
3180
|
function normalizeText(text2) {
|
|
2664
|
-
return text2.split("\n").map((line2) => line2.replace(/[ \t]+/g, " ").trim()).filter((line2,
|
|
3181
|
+
return text2.split("\n").map((line2) => line2.replace(/[ \t]+/g, " ").trim()).filter((line2, i2, arr) => line2 || i2 > 0 && i2 < arr.length - 1).join("\n");
|
|
2665
3182
|
}
|
|
2666
3183
|
function getVisibleChildren(node) {
|
|
2667
3184
|
const children = [];
|
|
2668
|
-
for (let
|
|
2669
|
-
const child = node.child(
|
|
3185
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3186
|
+
const child = node.child(i2);
|
|
2670
3187
|
if (child && !child.type.startsWith("_")) {
|
|
2671
3188
|
children.push(child);
|
|
2672
3189
|
}
|
|
@@ -2697,8 +3214,8 @@ ${middle.join("\n")}
|
|
|
2697
3214
|
${last} }}`;
|
|
2698
3215
|
}
|
|
2699
3216
|
const trimmed = inner.trim();
|
|
2700
|
-
const
|
|
2701
|
-
return `{{${prefix}${
|
|
3217
|
+
const s2 = prefix === "!" ? " " : space;
|
|
3218
|
+
return `{{${prefix}${s2}${trimmed}${s2}}}`;
|
|
2702
3219
|
}
|
|
2703
3220
|
const plainMatch = raw.match(/^\{\{([\s\S]*)\}\}$/);
|
|
2704
3221
|
if (plainMatch) {
|
|
@@ -2740,8 +3257,8 @@ function isCodeTag(config) {
|
|
|
2740
3257
|
return !!(config.languageAttribute || config.languageDefault);
|
|
2741
3258
|
}
|
|
2742
3259
|
function getAttributeValue(node, attrName) {
|
|
2743
|
-
for (let
|
|
2744
|
-
const child = node.child(
|
|
3260
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3261
|
+
const child = node.child(i2);
|
|
2745
3262
|
if (child?.type === "html_start_tag") {
|
|
2746
3263
|
for (let j = 0; j < child.childCount; j++) {
|
|
2747
3264
|
const attr = child.child(j);
|
|
@@ -2958,8 +3475,8 @@ function getContentNodes(sectionNode) {
|
|
|
2958
3475
|
const beginType = isInverted ? "mustache_inverted_section_begin" : "mustache_section_begin";
|
|
2959
3476
|
const endType = isInverted ? "mustache_inverted_section_end" : "mustache_section_end";
|
|
2960
3477
|
const contentNodes = [];
|
|
2961
|
-
for (let
|
|
2962
|
-
const child = sectionNode.child(
|
|
3478
|
+
for (let i2 = 0; i2 < sectionNode.childCount; i2++) {
|
|
3479
|
+
const child = sectionNode.child(i2);
|
|
2963
3480
|
if (!child) continue;
|
|
2964
3481
|
if (child.type !== beginType && child.type !== endType && child.type !== "mustache_erroneous_section_end" && child.type !== "mustache_erroneous_inverted_section_end" && !child.type.startsWith("_")) {
|
|
2965
3482
|
contentNodes.push(child);
|
|
@@ -2980,8 +3497,8 @@ function hasImplicitEndTagsRecursive(node) {
|
|
|
2980
3497
|
let hasStartTag = false;
|
|
2981
3498
|
let hasEndTag = false;
|
|
2982
3499
|
let hasContentChildren = false;
|
|
2983
|
-
for (let
|
|
2984
|
-
const child = node.child(
|
|
3500
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3501
|
+
const child = node.child(i2);
|
|
2985
3502
|
if (!child) continue;
|
|
2986
3503
|
if (child.type === "html_start_tag") hasStartTag = true;
|
|
2987
3504
|
else if (child.type === "html_end_tag") hasEndTag = true;
|
|
@@ -2990,8 +3507,8 @@ function hasImplicitEndTagsRecursive(node) {
|
|
|
2990
3507
|
}
|
|
2991
3508
|
if (hasStartTag && !hasEndTag && hasContentChildren) return true;
|
|
2992
3509
|
}
|
|
2993
|
-
for (let
|
|
2994
|
-
const child = node.child(
|
|
3510
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3511
|
+
const child = node.child(i2);
|
|
2995
3512
|
if (child && hasImplicitEndTagsRecursive(child)) {
|
|
2996
3513
|
return true;
|
|
2997
3514
|
}
|
|
@@ -3018,16 +3535,16 @@ function isInTextFlow(node, index, nodes) {
|
|
|
3018
3535
|
return false;
|
|
3019
3536
|
}
|
|
3020
3537
|
function hasAdjacentInlineContent(index, nodes) {
|
|
3021
|
-
for (let
|
|
3022
|
-
const
|
|
3023
|
-
if (
|
|
3024
|
-
if (isInlineContentNode(
|
|
3538
|
+
for (let i2 = index - 1; i2 >= 0; i2--) {
|
|
3539
|
+
const n2 = nodes[i2];
|
|
3540
|
+
if (n2.type === "text" && n2.text.trim().length === 0) continue;
|
|
3541
|
+
if (isInlineContentNode(n2)) return true;
|
|
3025
3542
|
break;
|
|
3026
3543
|
}
|
|
3027
|
-
for (let
|
|
3028
|
-
const
|
|
3029
|
-
if (
|
|
3030
|
-
if (isInlineContentNode(
|
|
3544
|
+
for (let i2 = index + 1; i2 < nodes.length; i2++) {
|
|
3545
|
+
const n2 = nodes[i2];
|
|
3546
|
+
if (n2.type === "text" && n2.text.trim().length === 0) continue;
|
|
3547
|
+
if (isInlineContentNode(n2)) return true;
|
|
3031
3548
|
break;
|
|
3032
3549
|
}
|
|
3033
3550
|
return false;
|
|
@@ -3083,15 +3600,15 @@ function dedentContent(rawContent) {
|
|
|
3083
3600
|
}
|
|
3084
3601
|
if (lines.length === 0) return "";
|
|
3085
3602
|
let minIndent = Infinity;
|
|
3086
|
-
for (const
|
|
3087
|
-
if (
|
|
3088
|
-
const match =
|
|
3603
|
+
for (const l2 of lines) {
|
|
3604
|
+
if (l2.trim() === "") continue;
|
|
3605
|
+
const match = l2.match(/^(\s*)/);
|
|
3089
3606
|
if (match && match[1].length < minIndent) {
|
|
3090
3607
|
minIndent = match[1].length;
|
|
3091
3608
|
}
|
|
3092
3609
|
}
|
|
3093
3610
|
if (minIndent === Infinity) minIndent = 0;
|
|
3094
|
-
return lines.map((
|
|
3611
|
+
return lines.map((l2) => l2.trim() === "" ? "" : l2.slice(minIndent)).join("\n");
|
|
3095
3612
|
}
|
|
3096
3613
|
function resolveIndentMode(node, config) {
|
|
3097
3614
|
const mode = config.indent ?? "never";
|
|
@@ -3102,8 +3619,8 @@ function resolveIndentMode(node, config) {
|
|
|
3102
3619
|
return isAttributeTruthy(value);
|
|
3103
3620
|
}
|
|
3104
3621
|
function getTagNameFromStartTag(startTag) {
|
|
3105
|
-
for (let
|
|
3106
|
-
const child = startTag.child(
|
|
3622
|
+
for (let i2 = 0; i2 < startTag.childCount; i2++) {
|
|
3623
|
+
const child = startTag.child(i2);
|
|
3107
3624
|
if (child?.type === "html_tag_name") return child.text.toLowerCase();
|
|
3108
3625
|
}
|
|
3109
3626
|
return null;
|
|
@@ -3172,8 +3689,8 @@ function formatHtmlElement(node, context, forceInline = false) {
|
|
|
3172
3689
|
let endTag = null;
|
|
3173
3690
|
let hasRealEndTag = false;
|
|
3174
3691
|
const contentNodes = [];
|
|
3175
|
-
for (let
|
|
3176
|
-
const child = node.child(
|
|
3692
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3693
|
+
const child = node.child(i2);
|
|
3177
3694
|
if (!child) continue;
|
|
3178
3695
|
if (child.type === "html_start_tag") {
|
|
3179
3696
|
startTag = child;
|
|
@@ -3273,8 +3790,8 @@ function formatHtmlElement(node, context, forceInline = false) {
|
|
|
3273
3790
|
const formattedContent = formatBlockChildren(contentNodes, context);
|
|
3274
3791
|
const hasContent = hasDocContent(formattedContent);
|
|
3275
3792
|
if (hasContent) {
|
|
3276
|
-
const hasBlockChildren = contentNodes.some((child,
|
|
3277
|
-
if (!shouldTreatAsBlock(child,
|
|
3793
|
+
const hasBlockChildren = contentNodes.some((child, i2) => {
|
|
3794
|
+
if (!shouldTreatAsBlock(child, i2, contentNodes, tags)) {
|
|
3278
3795
|
return false;
|
|
3279
3796
|
}
|
|
3280
3797
|
const childDisplay = getCSSDisplay(child, tags);
|
|
@@ -3330,8 +3847,8 @@ function formatHtmlElement(node, context, forceInline = false) {
|
|
|
3330
3847
|
}
|
|
3331
3848
|
function formatScriptStyleElement(node, context) {
|
|
3332
3849
|
const parts = [];
|
|
3333
|
-
for (let
|
|
3334
|
-
const child = node.child(
|
|
3850
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3851
|
+
const child = node.child(i2);
|
|
3335
3852
|
if (!child) continue;
|
|
3336
3853
|
if (child.type === "html_start_tag") {
|
|
3337
3854
|
parts.push(formatStartTag(child, context));
|
|
@@ -3415,8 +3932,8 @@ function formatMustacheSection(node, context) {
|
|
|
3415
3932
|
let beginNode = null;
|
|
3416
3933
|
let endNode = null;
|
|
3417
3934
|
const contentNodes = [];
|
|
3418
|
-
for (let
|
|
3419
|
-
const child = node.child(
|
|
3935
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
3936
|
+
const child = node.child(i2);
|
|
3420
3937
|
if (!child) continue;
|
|
3421
3938
|
if (child.type === beginType) {
|
|
3422
3939
|
beginNode = child;
|
|
@@ -3431,7 +3948,7 @@ function formatMustacheSection(node, context) {
|
|
|
3431
3948
|
parts.push(text(mustacheText(beginNode.text, context)));
|
|
3432
3949
|
}
|
|
3433
3950
|
const hasImplicit = hasImplicitEndTags(contentNodes);
|
|
3434
|
-
const erroneousCount = contentNodes.filter((
|
|
3951
|
+
const erroneousCount = contentNodes.filter((n2) => n2.type === "html_erroneous_end_tag").length;
|
|
3435
3952
|
const hasStaircase = !hasImplicit && erroneousCount > 0;
|
|
3436
3953
|
if (hasStaircase) {
|
|
3437
3954
|
let virtualDepth = erroneousCount - 1;
|
|
@@ -3485,8 +4002,8 @@ function formatMustacheSection(node, context) {
|
|
|
3485
4002
|
parts.push(formattedContent);
|
|
3486
4003
|
parts.push(hardline);
|
|
3487
4004
|
} else {
|
|
3488
|
-
const hasBlockChildren = contentNodes.some((child,
|
|
3489
|
-
if (!shouldTreatAsBlock(child,
|
|
4005
|
+
const hasBlockChildren = contentNodes.some((child, i2) => {
|
|
4006
|
+
if (!shouldTreatAsBlock(child, i2, contentNodes, context.customTags)) {
|
|
3490
4007
|
return false;
|
|
3491
4008
|
}
|
|
3492
4009
|
const childDisplay = getCSSDisplay(child, context.customTags);
|
|
@@ -3508,8 +4025,8 @@ function formatMustacheSection(node, context) {
|
|
|
3508
4025
|
return group(concat(parts));
|
|
3509
4026
|
}
|
|
3510
4027
|
function startTagHasAttributes(startTag) {
|
|
3511
|
-
for (let
|
|
3512
|
-
const child = startTag.child(
|
|
4028
|
+
for (let i2 = 0; i2 < startTag.childCount; i2++) {
|
|
4029
|
+
const child = startTag.child(i2);
|
|
3513
4030
|
if (!child) continue;
|
|
3514
4031
|
if (child.type === "html_attribute" || child.type === "mustache_attribute" || child.type === "mustache_interpolation" || child.type === "mustache_triple") {
|
|
3515
4032
|
return true;
|
|
@@ -3520,8 +4037,8 @@ function startTagHasAttributes(startTag) {
|
|
|
3520
4037
|
function formatStartTag(node, context, bare = false) {
|
|
3521
4038
|
let tagNameText = "";
|
|
3522
4039
|
const attrs = [];
|
|
3523
|
-
for (let
|
|
3524
|
-
const child = node.child(
|
|
4040
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4041
|
+
const child = node.child(i2);
|
|
3525
4042
|
if (!child) continue;
|
|
3526
4043
|
if (child.type === "html_tag_name") {
|
|
3527
4044
|
tagNameText = child.text;
|
|
@@ -3543,11 +4060,11 @@ function formatStartTag(node, context, bare = false) {
|
|
|
3543
4060
|
return text("<" + tagNameText + closingBracket);
|
|
3544
4061
|
}
|
|
3545
4062
|
const attrParts = [];
|
|
3546
|
-
for (let
|
|
3547
|
-
if (
|
|
4063
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
4064
|
+
if (i2 > 0) {
|
|
3548
4065
|
attrParts.push(line);
|
|
3549
4066
|
}
|
|
3550
|
-
attrParts.push(attrs[
|
|
4067
|
+
attrParts.push(attrs[i2]);
|
|
3551
4068
|
}
|
|
3552
4069
|
const breakClosingBracket = isSelfClosing ? "/>" : ">";
|
|
3553
4070
|
const inner = concat([
|
|
@@ -3559,8 +4076,8 @@ function formatStartTag(node, context, bare = false) {
|
|
|
3559
4076
|
return bare ? inner : group(inner);
|
|
3560
4077
|
}
|
|
3561
4078
|
function formatEndTag(node) {
|
|
3562
|
-
for (let
|
|
3563
|
-
const child = node.child(
|
|
4079
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4080
|
+
const child = node.child(i2);
|
|
3564
4081
|
if (child && child.type === "html_tag_name") {
|
|
3565
4082
|
return text("</" + child.text + ">");
|
|
3566
4083
|
}
|
|
@@ -3569,8 +4086,8 @@ function formatEndTag(node) {
|
|
|
3569
4086
|
}
|
|
3570
4087
|
function formatAttribute(node, context) {
|
|
3571
4088
|
const parts = [];
|
|
3572
|
-
for (let
|
|
3573
|
-
const child = node.child(
|
|
4089
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4090
|
+
const child = node.child(i2);
|
|
3574
4091
|
if (!child) continue;
|
|
3575
4092
|
if (child.type === "html_attribute_name") {
|
|
3576
4093
|
parts.push(text(child.text));
|
|
@@ -3595,21 +4112,21 @@ function textWords(str) {
|
|
|
3595
4112
|
const words = str.split(/\s+/).filter((w) => w.length > 0);
|
|
3596
4113
|
if (words.length === 0) return [];
|
|
3597
4114
|
const parts = [words[0]];
|
|
3598
|
-
for (let
|
|
4115
|
+
for (let i2 = 1; i2 < words.length; i2++) {
|
|
3599
4116
|
parts.push(line);
|
|
3600
|
-
parts.push(words[
|
|
4117
|
+
parts.push(words[i2]);
|
|
3601
4118
|
}
|
|
3602
4119
|
return parts;
|
|
3603
4120
|
}
|
|
3604
4121
|
function collapseDelimitedRegions(parts, delimiters) {
|
|
3605
4122
|
if (delimiters.length === 0) return parts;
|
|
3606
4123
|
const sorted = [...delimiters].sort(
|
|
3607
|
-
(
|
|
4124
|
+
(a2, b) => Math.max(b.start.length, b.end.length) - Math.max(a2.start.length, a2.end.length)
|
|
3608
4125
|
);
|
|
3609
4126
|
const result = [...parts];
|
|
3610
4127
|
let activeDelimiter = null;
|
|
3611
|
-
for (let
|
|
3612
|
-
const part = result[
|
|
4128
|
+
for (let i2 = 0; i2 < result.length; i2++) {
|
|
4129
|
+
const part = result[i2];
|
|
3613
4130
|
if (typeof part === "string") {
|
|
3614
4131
|
if (activeDelimiter === null) {
|
|
3615
4132
|
for (const delim of sorted) {
|
|
@@ -3630,7 +4147,7 @@ function collapseDelimitedRegions(parts, delimiters) {
|
|
|
3630
4147
|
}
|
|
3631
4148
|
}
|
|
3632
4149
|
} else if (activeDelimiter !== null && isLine(part)) {
|
|
3633
|
-
result[
|
|
4150
|
+
result[i2] = " ";
|
|
3634
4151
|
}
|
|
3635
4152
|
}
|
|
3636
4153
|
return result;
|
|
@@ -3682,8 +4199,8 @@ function formatBlockChildren(nodes, context) {
|
|
|
3682
4199
|
const parts2 = noBreakDelims ? collapseDelimitedRegions(currentLine, noBreakDelims) : currentLine;
|
|
3683
4200
|
return inlineContentToFill(parts2);
|
|
3684
4201
|
}
|
|
3685
|
-
for (let
|
|
3686
|
-
const node = nodes[
|
|
4202
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
4203
|
+
const node = nodes[i2];
|
|
3687
4204
|
if (lastNodeEnd >= 0 && node.startIndex > lastNodeEnd && !inIgnoreRegion) {
|
|
3688
4205
|
const gap = context.document.getText().slice(lastNodeEnd, node.startIndex);
|
|
3689
4206
|
const newlineCount = (gap.match(/\n/g) || []).length;
|
|
@@ -3756,10 +4273,10 @@ function formatBlockChildren(nodes, context) {
|
|
|
3756
4273
|
lastNodeEnd = node.endIndex;
|
|
3757
4274
|
continue;
|
|
3758
4275
|
}
|
|
3759
|
-
const treatAsBlock = shouldTreatAsBlock(node,
|
|
4276
|
+
const treatAsBlock = shouldTreatAsBlock(node, i2, nodes, context.customTags);
|
|
3760
4277
|
if (lastNodeEnd >= 0 && node.startIndex > lastNodeEnd) {
|
|
3761
|
-
const prevNode = nodes[
|
|
3762
|
-
const prevTreatAsBlock = shouldTreatAsBlock(prevNode,
|
|
4278
|
+
const prevNode = nodes[i2 - 1];
|
|
4279
|
+
const prevTreatAsBlock = shouldTreatAsBlock(prevNode, i2 - 1, nodes, context.customTags);
|
|
3763
4280
|
if (!prevTreatAsBlock && !treatAsBlock) {
|
|
3764
4281
|
const gap = context.document.getText().slice(lastNodeEnd, node.startIndex);
|
|
3765
4282
|
if (/\s/.test(gap)) {
|
|
@@ -3780,7 +4297,7 @@ function formatBlockChildren(nodes, context) {
|
|
|
3780
4297
|
pendingBlankLine = false;
|
|
3781
4298
|
} else if (node.type === "html_comment" || node.type === "mustache_comment") {
|
|
3782
4299
|
const isMultiline = node.startPosition.row !== node.endPosition.row;
|
|
3783
|
-
const isOnOwnLine =
|
|
4300
|
+
const isOnOwnLine = i2 > 0 && node.startPosition.row > nodes[i2 - 1].endPosition.row;
|
|
3784
4301
|
if (isMultiline || isOnOwnLine) {
|
|
3785
4302
|
if (currentLine.length > 0) {
|
|
3786
4303
|
const lineContent = trimDoc(flushCurrentLine());
|
|
@@ -3806,7 +4323,7 @@ function formatBlockChildren(nodes, context) {
|
|
|
3806
4323
|
blankLineBeforeCurrentLine = pendingBlankLine;
|
|
3807
4324
|
pendingBlankLine = false;
|
|
3808
4325
|
}
|
|
3809
|
-
const forceInline = isInTextFlow(node,
|
|
4326
|
+
const forceInline = isInTextFlow(node, i2, nodes);
|
|
3810
4327
|
const formatted = formatNode(node, context, forceInline);
|
|
3811
4328
|
if (typeof formatted === "string" && formatted.includes("\n")) {
|
|
3812
4329
|
const contentLines = formatted.split("\n");
|
|
@@ -3915,18 +4432,18 @@ function formatBlockChildren(nodes, context) {
|
|
|
3915
4432
|
return empty;
|
|
3916
4433
|
}
|
|
3917
4434
|
const parts = [];
|
|
3918
|
-
for (let
|
|
3919
|
-
if (
|
|
3920
|
-
if (lines[
|
|
4435
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
4436
|
+
if (i2 > 0) {
|
|
4437
|
+
if (lines[i2].blankLineBefore) {
|
|
3921
4438
|
parts.push("\n");
|
|
3922
4439
|
}
|
|
3923
|
-
if (lines[
|
|
4440
|
+
if (lines[i2].rawLine) {
|
|
3924
4441
|
parts.push("\n");
|
|
3925
4442
|
} else {
|
|
3926
4443
|
parts.push(hardline);
|
|
3927
4444
|
}
|
|
3928
4445
|
}
|
|
3929
|
-
parts.push(lines[
|
|
4446
|
+
parts.push(lines[i2].doc);
|
|
3930
4447
|
}
|
|
3931
4448
|
return concat(parts);
|
|
3932
4449
|
}
|
|
@@ -4035,8 +4552,8 @@ function getEmbeddedLanguageId(node) {
|
|
|
4035
4552
|
if (node.type === "html_style_element") {
|
|
4036
4553
|
return "css";
|
|
4037
4554
|
}
|
|
4038
|
-
for (let
|
|
4039
|
-
const child = node.child(
|
|
4555
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4556
|
+
const child = node.child(i2);
|
|
4040
4557
|
if (child?.type === "html_start_tag") {
|
|
4041
4558
|
for (let j = 0; j < child.childCount; j++) {
|
|
4042
4559
|
const attr = child.child(j);
|
|
@@ -4062,8 +4579,8 @@ function collectEmbeddedRegions(rootNode) {
|
|
|
4062
4579
|
const regions = [];
|
|
4063
4580
|
const walk = (node) => {
|
|
4064
4581
|
if (node.type === "html_script_element" || node.type === "html_style_element") {
|
|
4065
|
-
for (let
|
|
4066
|
-
const child = node.child(
|
|
4582
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4583
|
+
const child = node.child(i2);
|
|
4067
4584
|
if (child?.type === "html_raw_text") {
|
|
4068
4585
|
regions.push({
|
|
4069
4586
|
startIndex: child.startIndex,
|
|
@@ -4074,8 +4591,8 @@ function collectEmbeddedRegions(rootNode) {
|
|
|
4074
4591
|
}
|
|
4075
4592
|
return;
|
|
4076
4593
|
}
|
|
4077
|
-
for (let
|
|
4078
|
-
const child = node.child(
|
|
4594
|
+
for (let i2 = 0; i2 < node.childCount; i2++) {
|
|
4595
|
+
const child = node.child(i2);
|
|
4079
4596
|
if (child) walk(child);
|
|
4080
4597
|
}
|
|
4081
4598
|
};
|
|
@@ -4115,9 +4632,9 @@ function parseFlags(args) {
|
|
|
4115
4632
|
mustacheSpaces: void 0,
|
|
4116
4633
|
patterns: []
|
|
4117
4634
|
};
|
|
4118
|
-
let
|
|
4119
|
-
while (
|
|
4120
|
-
const arg = args[
|
|
4635
|
+
let i2 = 0;
|
|
4636
|
+
while (i2 < args.length) {
|
|
4637
|
+
const arg = args[i2];
|
|
4121
4638
|
switch (arg) {
|
|
4122
4639
|
case "--write":
|
|
4123
4640
|
flags.write = true;
|
|
@@ -4129,16 +4646,16 @@ function parseFlags(args) {
|
|
|
4129
4646
|
flags.stdin = true;
|
|
4130
4647
|
break;
|
|
4131
4648
|
case "--indent-size":
|
|
4132
|
-
|
|
4133
|
-
flags.indentSize = parseInt(args[
|
|
4649
|
+
i2++;
|
|
4650
|
+
flags.indentSize = parseInt(args[i2], 10);
|
|
4134
4651
|
if (isNaN(flags.indentSize)) {
|
|
4135
4652
|
console.error(source_default.red("Error: --indent-size requires a number"));
|
|
4136
4653
|
process.exit(1);
|
|
4137
4654
|
}
|
|
4138
4655
|
break;
|
|
4139
4656
|
case "--print-width":
|
|
4140
|
-
|
|
4141
|
-
flags.printWidth = parseInt(args[
|
|
4657
|
+
i2++;
|
|
4658
|
+
flags.printWidth = parseInt(args[i2], 10);
|
|
4142
4659
|
if (isNaN(flags.printWidth)) {
|
|
4143
4660
|
console.error(source_default.red("Error: --print-width requires a number"));
|
|
4144
4661
|
process.exit(1);
|
|
@@ -4151,7 +4668,7 @@ function parseFlags(args) {
|
|
|
4151
4668
|
flags.patterns.push(arg);
|
|
4152
4669
|
break;
|
|
4153
4670
|
}
|
|
4154
|
-
|
|
4671
|
+
i2++;
|
|
4155
4672
|
}
|
|
4156
4673
|
return flags;
|
|
4157
4674
|
}
|