@reteps/tree-sitter-htmlmustache 0.5.2 → 0.7.0
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/cli/out/main.js +349 -25
- package/package.json +1 -1
package/cli/out/main.js
CHANGED
|
@@ -708,9 +708,12 @@ function validateConfig(raw) {
|
|
|
708
708
|
config.mustacheSpaces = obj.mustacheSpaces;
|
|
709
709
|
}
|
|
710
710
|
if (Array.isArray(obj.noBreakDelimiters)) {
|
|
711
|
-
const items =
|
|
712
|
-
|
|
713
|
-
|
|
711
|
+
const items = [];
|
|
712
|
+
for (const entry of obj.noBreakDelimiters) {
|
|
713
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.start === "string" && entry.start !== "" && typeof entry.end === "string" && entry.end !== "") {
|
|
714
|
+
items.push({ start: entry.start, end: entry.end });
|
|
715
|
+
}
|
|
716
|
+
}
|
|
714
717
|
if (items.length > 0) config.noBreakDelimiters = items;
|
|
715
718
|
}
|
|
716
719
|
if (Array.isArray(obj.include)) {
|
|
@@ -745,6 +748,22 @@ function validateConfig(raw) {
|
|
|
745
748
|
}
|
|
746
749
|
if (hasRules) config.rules = rules;
|
|
747
750
|
}
|
|
751
|
+
if (Array.isArray(obj.customRules)) {
|
|
752
|
+
const rules = [];
|
|
753
|
+
for (const entry of obj.customRules) {
|
|
754
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
755
|
+
const e = entry;
|
|
756
|
+
if (typeof e.id !== "string" || e.id.length === 0) continue;
|
|
757
|
+
if (typeof e.selector !== "string" || e.selector.length === 0) continue;
|
|
758
|
+
if (typeof e.message !== "string" || e.message.length === 0) continue;
|
|
759
|
+
const rule = { id: e.id, selector: e.selector, message: e.message };
|
|
760
|
+
if (typeof e.severity === "string" && VALID_RULE_SEVERITIES.has(e.severity)) {
|
|
761
|
+
rule.severity = e.severity;
|
|
762
|
+
}
|
|
763
|
+
rules.push(rule);
|
|
764
|
+
}
|
|
765
|
+
if (rules.length > 0) config.customRules = rules;
|
|
766
|
+
}
|
|
748
767
|
return config;
|
|
749
768
|
}
|
|
750
769
|
function loadConfigFileForPath(filePath) {
|
|
@@ -918,18 +937,29 @@ function mergeAdjacentForks(items) {
|
|
|
918
937
|
}
|
|
919
938
|
return result;
|
|
920
939
|
}
|
|
921
|
-
function
|
|
940
|
+
function isBranchBalanced(items) {
|
|
941
|
+
const stack = [];
|
|
922
942
|
for (const item of items) {
|
|
923
|
-
if (item.type
|
|
924
|
-
|
|
943
|
+
if (item.type === "fork") {
|
|
944
|
+
if (!isBranchBalanced(item.truthy) || !isBranchBalanced(item.falsy)) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
} else if (item.type === "open") {
|
|
948
|
+
stack.push(item.tagName);
|
|
949
|
+
} else {
|
|
950
|
+
if (stack.length === 0 || stack[stack.length - 1] !== item.tagName) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
stack.pop();
|
|
954
|
+
}
|
|
925
955
|
}
|
|
926
|
-
return
|
|
956
|
+
return stack.length === 0;
|
|
927
957
|
}
|
|
928
958
|
function collectSectionNames(items) {
|
|
929
959
|
const names = /* @__PURE__ */ new Set();
|
|
930
960
|
for (const item of items) {
|
|
931
961
|
if (item.type === "fork") {
|
|
932
|
-
if (
|
|
962
|
+
if (!isBranchBalanced(item.truthy) || !isBranchBalanced(item.falsy)) {
|
|
933
963
|
names.add(item.sectionName);
|
|
934
964
|
}
|
|
935
965
|
for (const name of collectSectionNames(item.truthy)) names.add(name);
|
|
@@ -1570,6 +1600,281 @@ function checkDuplicateAttributes(rootNode) {
|
|
|
1570
1600
|
return errors;
|
|
1571
1601
|
}
|
|
1572
1602
|
|
|
1603
|
+
// lsp/server/src/selectorMatcher.ts
|
|
1604
|
+
function isNameChar(ch) {
|
|
1605
|
+
return /[a-zA-Z0-9\-_]/.test(ch);
|
|
1606
|
+
}
|
|
1607
|
+
function parseAttributes(raw, pos) {
|
|
1608
|
+
const attrs = [];
|
|
1609
|
+
while (pos.i < raw.length) {
|
|
1610
|
+
if (raw[pos.i] === ":") {
|
|
1611
|
+
if (raw.slice(pos.i, pos.i + 6).toLowerCase() !== ":not([") return attrs;
|
|
1612
|
+
pos.i += 6;
|
|
1613
|
+
const attr = parseOneAttribute(raw, pos, true);
|
|
1614
|
+
if (!attr) return attrs;
|
|
1615
|
+
if (raw[pos.i] !== "]" || raw[pos.i + 1] !== ")") return attrs;
|
|
1616
|
+
pos.i += 2;
|
|
1617
|
+
attrs.push(attr);
|
|
1618
|
+
} else if (raw[pos.i] === "[") {
|
|
1619
|
+
pos.i++;
|
|
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 {
|
|
1626
|
+
break;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
return attrs;
|
|
1630
|
+
}
|
|
1631
|
+
function parseOneAttribute(raw, pos, negated) {
|
|
1632
|
+
let name = "";
|
|
1633
|
+
while (pos.i < raw.length && isNameChar(raw[pos.i])) {
|
|
1634
|
+
name += raw[pos.i];
|
|
1635
|
+
pos.i++;
|
|
1636
|
+
}
|
|
1637
|
+
if (name.length === 0) return null;
|
|
1638
|
+
let value;
|
|
1639
|
+
if (raw[pos.i] === "=") {
|
|
1640
|
+
pos.i++;
|
|
1641
|
+
value = "";
|
|
1642
|
+
if (raw[pos.i] === '"' || raw[pos.i] === "'") {
|
|
1643
|
+
const quote = raw[pos.i];
|
|
1644
|
+
pos.i++;
|
|
1645
|
+
while (pos.i < raw.length && raw[pos.i] !== quote) {
|
|
1646
|
+
value += raw[pos.i];
|
|
1647
|
+
pos.i++;
|
|
1648
|
+
}
|
|
1649
|
+
if (pos.i < raw.length) pos.i++;
|
|
1650
|
+
} else {
|
|
1651
|
+
while (pos.i < raw.length && raw[pos.i] !== "]") {
|
|
1652
|
+
value += raw[pos.i];
|
|
1653
|
+
pos.i++;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
return { name: name.toLowerCase(), value, negated };
|
|
1658
|
+
}
|
|
1659
|
+
function parseSelector(raw) {
|
|
1660
|
+
const trimmed = raw.trim();
|
|
1661
|
+
if (trimmed.length === 0) return null;
|
|
1662
|
+
const parts = trimmed.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1663
|
+
if (parts.length === 0) return null;
|
|
1664
|
+
const alternatives = [];
|
|
1665
|
+
for (const part of parts) {
|
|
1666
|
+
const alt = parseSingleSelector(part);
|
|
1667
|
+
if (!alt) return null;
|
|
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);
|
|
1694
|
+
}
|
|
1695
|
+
if (segments.length === 0) return null;
|
|
1696
|
+
return { segments };
|
|
1697
|
+
}
|
|
1698
|
+
function parseOneSegment(raw, pos) {
|
|
1699
|
+
let kind;
|
|
1700
|
+
let name;
|
|
1701
|
+
if (raw[pos.i] === "#") {
|
|
1702
|
+
kind = "mustache";
|
|
1703
|
+
pos.i++;
|
|
1704
|
+
name = "";
|
|
1705
|
+
while (pos.i < raw.length && isNameChar(raw[pos.i])) {
|
|
1706
|
+
name += raw[pos.i];
|
|
1707
|
+
pos.i++;
|
|
1708
|
+
}
|
|
1709
|
+
if (name.length === 0) name = null;
|
|
1710
|
+
else name = name.toLowerCase();
|
|
1711
|
+
return { kind, name, attributes: [], combinator: "descendant" };
|
|
1712
|
+
}
|
|
1713
|
+
if (raw[pos.i] === "*") {
|
|
1714
|
+
kind = "html";
|
|
1715
|
+
name = null;
|
|
1716
|
+
pos.i++;
|
|
1717
|
+
const attrs2 = parseAttributes(raw, pos);
|
|
1718
|
+
return { kind, name, attributes: attrs2, combinator: "descendant" };
|
|
1719
|
+
}
|
|
1720
|
+
if (raw[pos.i] === "[" || raw[pos.i] === ":") {
|
|
1721
|
+
kind = "html";
|
|
1722
|
+
name = null;
|
|
1723
|
+
const attrs2 = parseAttributes(raw, pos);
|
|
1724
|
+
if (attrs2.length === 0) return null;
|
|
1725
|
+
return { kind, name, attributes: attrs2, combinator: "descendant" };
|
|
1726
|
+
}
|
|
1727
|
+
if (!isNameChar(raw[pos.i])) return null;
|
|
1728
|
+
kind = "html";
|
|
1729
|
+
name = "";
|
|
1730
|
+
while (pos.i < raw.length && isNameChar(raw[pos.i])) {
|
|
1731
|
+
name += raw[pos.i];
|
|
1732
|
+
pos.i++;
|
|
1733
|
+
}
|
|
1734
|
+
name = name.toLowerCase();
|
|
1735
|
+
const attrs = parseAttributes(raw, pos);
|
|
1736
|
+
return { kind, name, attributes: attrs, combinator: "descendant" };
|
|
1737
|
+
}
|
|
1738
|
+
function getNodeAttributes(node) {
|
|
1739
|
+
const startTag = node.children.find(
|
|
1740
|
+
(c) => c.type === "html_start_tag" || c.type === "html_self_closing_tag"
|
|
1741
|
+
);
|
|
1742
|
+
if (!startTag) return [];
|
|
1743
|
+
const attrs = [];
|
|
1744
|
+
for (const child of startTag.children) {
|
|
1745
|
+
if (child.type === "html_attribute") {
|
|
1746
|
+
let attrName = "";
|
|
1747
|
+
let attrValue;
|
|
1748
|
+
for (const part of child.children) {
|
|
1749
|
+
if (part.type === "html_attribute_name") {
|
|
1750
|
+
attrName = part.text.toLowerCase();
|
|
1751
|
+
} else if (part.type === "html_quoted_attribute_value") {
|
|
1752
|
+
attrValue = part.text.replace(/^["']|["']$/g, "");
|
|
1753
|
+
} else if (part.type === "html_attribute_value") {
|
|
1754
|
+
attrValue = part.text;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
if (attrName) attrs.push({ name: attrName, value: attrValue });
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return attrs;
|
|
1761
|
+
}
|
|
1762
|
+
function checkAttributes(node, constraints) {
|
|
1763
|
+
if (constraints.length === 0) return true;
|
|
1764
|
+
const nodeAttrs = getNodeAttributes(node);
|
|
1765
|
+
for (const constraint of constraints) {
|
|
1766
|
+
const found = nodeAttrs.find((a) => a.name === constraint.name);
|
|
1767
|
+
if (constraint.negated) {
|
|
1768
|
+
if (found) return false;
|
|
1769
|
+
} else if (constraint.value !== void 0) {
|
|
1770
|
+
if (!found || found.value !== constraint.value) return false;
|
|
1771
|
+
} else {
|
|
1772
|
+
if (!found) return false;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
return true;
|
|
1776
|
+
}
|
|
1777
|
+
function nodeMatchesSegment(node, segment) {
|
|
1778
|
+
if (segment.kind === "html") {
|
|
1779
|
+
if (!HTML_ELEMENT_TYPES.has(node.type)) return false;
|
|
1780
|
+
if (segment.name !== null) {
|
|
1781
|
+
const tagName = getTagName(node)?.toLowerCase();
|
|
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;
|
|
1790
|
+
}
|
|
1791
|
+
return true;
|
|
1792
|
+
}
|
|
1793
|
+
function checkAncestors(ancestors, segments, segIdx, childCombinator) {
|
|
1794
|
+
if (segIdx < 0) return true;
|
|
1795
|
+
const segment = segments[segIdx];
|
|
1796
|
+
if (childCombinator === "child") {
|
|
1797
|
+
for (let a = ancestors.length - 1; a >= 0; a--) {
|
|
1798
|
+
const entry = ancestors[a];
|
|
1799
|
+
if (entry.kind !== segment.kind) continue;
|
|
1800
|
+
if (segment.name !== null && entry.name !== segment.name) return false;
|
|
1801
|
+
if (segment.kind === "html" && segment.attributes.length > 0) {
|
|
1802
|
+
if (!checkAttributes(entry.node, segment.attributes)) return false;
|
|
1803
|
+
}
|
|
1804
|
+
return checkAncestors(ancestors.slice(0, a), segments, segIdx - 1, segment.combinator);
|
|
1805
|
+
}
|
|
1806
|
+
return false;
|
|
1807
|
+
}
|
|
1808
|
+
for (let a = ancestors.length - 1; a >= 0; a--) {
|
|
1809
|
+
const entry = ancestors[a];
|
|
1810
|
+
if (entry.kind !== segment.kind) continue;
|
|
1811
|
+
if (segment.name !== null && entry.name !== segment.name) continue;
|
|
1812
|
+
if (segment.kind === "html" && segment.attributes.length > 0) {
|
|
1813
|
+
if (!checkAttributes(entry.node, segment.attributes)) continue;
|
|
1814
|
+
}
|
|
1815
|
+
if (checkAncestors(ancestors.slice(0, a), segments, segIdx - 1, segment.combinator)) {
|
|
1816
|
+
return true;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
return false;
|
|
1820
|
+
}
|
|
1821
|
+
function getReportNode(node) {
|
|
1822
|
+
if (HTML_ELEMENT_TYPES.has(node.type)) {
|
|
1823
|
+
const startTag = node.children.find(
|
|
1824
|
+
(c) => c.type === "html_start_tag" || c.type === "html_self_closing_tag"
|
|
1825
|
+
);
|
|
1826
|
+
return startTag ?? node;
|
|
1827
|
+
}
|
|
1828
|
+
if (MUSTACHE_SECTION_TYPES.has(node.type)) {
|
|
1829
|
+
const begin = node.children.find(
|
|
1830
|
+
(c) => c.type === "mustache_section_begin" || c.type === "mustache_inverted_section_begin"
|
|
1831
|
+
);
|
|
1832
|
+
return begin ?? node;
|
|
1833
|
+
}
|
|
1834
|
+
return node;
|
|
1835
|
+
}
|
|
1836
|
+
function matchAlternative(rootNode, alt) {
|
|
1837
|
+
const results = [];
|
|
1838
|
+
const lastSegment = alt.segments[alt.segments.length - 1];
|
|
1839
|
+
function walk(node, ancestors) {
|
|
1840
|
+
if (nodeMatchesSegment(node, lastSegment)) {
|
|
1841
|
+
if (alt.segments.length === 1 || checkAncestors(ancestors, alt.segments, alt.segments.length - 2, lastSegment.combinator)) {
|
|
1842
|
+
results.push(getReportNode(node));
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
let newAncestors = ancestors;
|
|
1846
|
+
if (HTML_ELEMENT_TYPES.has(node.type)) {
|
|
1847
|
+
const tagName = getTagName(node)?.toLowerCase();
|
|
1848
|
+
if (tagName) {
|
|
1849
|
+
newAncestors = [...ancestors, { kind: "html", name: tagName, node }];
|
|
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 }];
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
for (const child of node.children) {
|
|
1858
|
+
walk(child, newAncestors);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
walk(rootNode, []);
|
|
1862
|
+
return results;
|
|
1863
|
+
}
|
|
1864
|
+
function matchSelector(rootNode, selector) {
|
|
1865
|
+
const allResults = [];
|
|
1866
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1867
|
+
for (const alt of selector.alternatives) {
|
|
1868
|
+
for (const node of matchAlternative(rootNode, alt)) {
|
|
1869
|
+
if (!seen.has(node)) {
|
|
1870
|
+
seen.add(node);
|
|
1871
|
+
allResults.push(node);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return allResults;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1573
1878
|
// lsp/server/src/collectErrors.ts
|
|
1574
1879
|
var ERROR_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
1575
1880
|
"ERROR",
|
|
@@ -1589,7 +1894,7 @@ function errorMessageForNode(nodeType, node) {
|
|
|
1589
1894
|
function resolveRuleSeverity(rules, ruleName) {
|
|
1590
1895
|
return rules?.[ruleName] ?? RULE_DEFAULTS[ruleName] ?? "off";
|
|
1591
1896
|
}
|
|
1592
|
-
function parseDisableDirective(node) {
|
|
1897
|
+
function parseDisableDirective(node, customRuleIds) {
|
|
1593
1898
|
if (node.type !== "html_comment" && node.type !== "mustache_comment") return null;
|
|
1594
1899
|
let inner = null;
|
|
1595
1900
|
if (node.type === "html_comment") {
|
|
@@ -1603,12 +1908,14 @@ function parseDisableDirective(node) {
|
|
|
1603
1908
|
const prefix = "htmlmustache-disable ";
|
|
1604
1909
|
if (!inner.startsWith(prefix)) return null;
|
|
1605
1910
|
const ruleName = inner.slice(prefix.length).trim();
|
|
1606
|
-
|
|
1911
|
+
if (KNOWN_RULE_NAMES.has(ruleName)) return ruleName;
|
|
1912
|
+
if (customRuleIds?.has(ruleName)) return ruleName;
|
|
1913
|
+
return null;
|
|
1607
1914
|
}
|
|
1608
|
-
function collectDisabledRules(rootNode) {
|
|
1915
|
+
function collectDisabledRules(rootNode, customRuleIds) {
|
|
1609
1916
|
const disabled = /* @__PURE__ */ new Set();
|
|
1610
1917
|
function walk(node) {
|
|
1611
|
-
const rule = parseDisableDirective(node);
|
|
1918
|
+
const rule = parseDisableDirective(node, customRuleIds);
|
|
1612
1919
|
if (rule) {
|
|
1613
1920
|
disabled.add(rule);
|
|
1614
1921
|
return;
|
|
@@ -1618,7 +1925,7 @@ function collectDisabledRules(rootNode) {
|
|
|
1618
1925
|
walk(rootNode);
|
|
1619
1926
|
return disabled;
|
|
1620
1927
|
}
|
|
1621
|
-
function collectErrors(tree, rules, customTagNames) {
|
|
1928
|
+
function collectErrors(tree, rules, customTagNames, customRules) {
|
|
1622
1929
|
const errors = [];
|
|
1623
1930
|
const cursor = tree.walk();
|
|
1624
1931
|
function visit() {
|
|
@@ -1647,7 +1954,8 @@ function collectErrors(tree, rules, customTagNames) {
|
|
|
1647
1954
|
for (const error of unclosedErrors) {
|
|
1648
1955
|
errors.push({ node: error.node, message: error.message });
|
|
1649
1956
|
}
|
|
1650
|
-
const
|
|
1957
|
+
const customRuleIds = customRules ? new Set(customRules.map((r) => r.id)) : void 0;
|
|
1958
|
+
const disabledRules = collectDisabledRules(tree.rootNode, customRuleIds);
|
|
1651
1959
|
const effectiveRules = { ...rules };
|
|
1652
1960
|
for (const rule of disabledRules) {
|
|
1653
1961
|
effectiveRules[rule] = "off";
|
|
@@ -1676,14 +1984,27 @@ function collectErrors(tree, rules, customTagNames) {
|
|
|
1676
1984
|
});
|
|
1677
1985
|
}
|
|
1678
1986
|
}
|
|
1987
|
+
if (customRules) {
|
|
1988
|
+
for (const rule of customRules) {
|
|
1989
|
+
if (disabledRules.has(rule.id)) continue;
|
|
1990
|
+
const severity = rule.severity ?? "error";
|
|
1991
|
+
if (severity === "off") continue;
|
|
1992
|
+
const parsed = parseSelector(rule.selector);
|
|
1993
|
+
if (!parsed) continue;
|
|
1994
|
+
const matches = matchSelector(tree.rootNode, parsed);
|
|
1995
|
+
for (const node of matches) {
|
|
1996
|
+
errors.push({ node, message: rule.message, severity });
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
1679
2000
|
return errors.filter(
|
|
1680
|
-
(e) => !(e.message.includes("HTML comment found") && parseDisableDirective(e.node) !== null)
|
|
2001
|
+
(e) => !(e.message.includes("HTML comment found") && parseDisableDirective(e.node, customRuleIds) !== null)
|
|
1681
2002
|
);
|
|
1682
2003
|
}
|
|
1683
2004
|
|
|
1684
2005
|
// cli/src/check.ts
|
|
1685
|
-
function collectErrors2(tree, file, rules, customTagNames) {
|
|
1686
|
-
const errors = collectErrors(tree, rules, customTagNames);
|
|
2006
|
+
function collectErrors2(tree, file, rules, customTagNames, customRules) {
|
|
2007
|
+
const errors = collectErrors(tree, rules, customTagNames, customRules);
|
|
1687
2008
|
return errors.map((error) => ({
|
|
1688
2009
|
file,
|
|
1689
2010
|
line: error.node.startPosition.row + 1,
|
|
@@ -1868,12 +2189,13 @@ async function run(args) {
|
|
|
1868
2189
|
const errorOutput = [];
|
|
1869
2190
|
const rules = config?.rules;
|
|
1870
2191
|
const customTagNames = config?.customTags?.map((t) => t.name);
|
|
2192
|
+
const customRules = config?.customRules;
|
|
1871
2193
|
for (const file of files) {
|
|
1872
2194
|
const displayPath = import_node_path.default.relative(cwd, file) || file;
|
|
1873
2195
|
let source = import_node_fs.default.readFileSync(file, "utf-8");
|
|
1874
2196
|
if (fixMode) {
|
|
1875
2197
|
const tree2 = parseDocument(source);
|
|
1876
|
-
const errors2 = collectErrors2(tree2, displayPath, rules, customTagNames);
|
|
2198
|
+
const errors2 = collectErrors2(tree2, displayPath, rules, customTagNames, customRules);
|
|
1877
2199
|
const fixed = applyFixes(source, errors2);
|
|
1878
2200
|
if (fixed !== source) {
|
|
1879
2201
|
import_node_fs.default.writeFileSync(file, fixed, "utf-8");
|
|
@@ -1881,7 +2203,7 @@ async function run(args) {
|
|
|
1881
2203
|
}
|
|
1882
2204
|
}
|
|
1883
2205
|
const tree = parseDocument(source);
|
|
1884
|
-
const errors = collectErrors2(tree, displayPath, rules, customTagNames);
|
|
2206
|
+
const errors = collectErrors2(tree, displayPath, rules, customTagNames, customRules);
|
|
1885
2207
|
const fileErrors = errors.filter((e) => e.severity !== "warning");
|
|
1886
2208
|
const fileWarnings = errors.filter((e) => e.severity === "warning");
|
|
1887
2209
|
if (errors.length > 0) {
|
|
@@ -3280,7 +3602,9 @@ function textWords(str) {
|
|
|
3280
3602
|
}
|
|
3281
3603
|
function collapseDelimitedRegions(parts, delimiters) {
|
|
3282
3604
|
if (delimiters.length === 0) return parts;
|
|
3283
|
-
const sorted = [...delimiters].sort(
|
|
3605
|
+
const sorted = [...delimiters].sort(
|
|
3606
|
+
(a, b) => Math.max(b.start.length, b.end.length) - Math.max(a.start.length, a.end.length)
|
|
3607
|
+
);
|
|
3284
3608
|
const result = [...parts];
|
|
3285
3609
|
let activeDelimiter = null;
|
|
3286
3610
|
for (let i = 0; i < result.length; i++) {
|
|
@@ -3288,10 +3612,10 @@ function collapseDelimitedRegions(parts, delimiters) {
|
|
|
3288
3612
|
if (typeof part === "string") {
|
|
3289
3613
|
if (activeDelimiter === null) {
|
|
3290
3614
|
for (const delim of sorted) {
|
|
3291
|
-
const
|
|
3292
|
-
if (
|
|
3293
|
-
const afterOpen =
|
|
3294
|
-
const closeIdx = part.indexOf(delim, afterOpen);
|
|
3615
|
+
const startIdx = part.indexOf(delim.start);
|
|
3616
|
+
if (startIdx >= 0) {
|
|
3617
|
+
const afterOpen = startIdx + delim.start.length;
|
|
3618
|
+
const closeIdx = part.indexOf(delim.end, afterOpen);
|
|
3295
3619
|
if (closeIdx >= 0) {
|
|
3296
3620
|
continue;
|
|
3297
3621
|
}
|
|
@@ -3300,7 +3624,7 @@ function collapseDelimitedRegions(parts, delimiters) {
|
|
|
3300
3624
|
}
|
|
3301
3625
|
}
|
|
3302
3626
|
} else {
|
|
3303
|
-
if (part.includes(activeDelimiter)) {
|
|
3627
|
+
if (part.includes(activeDelimiter.end)) {
|
|
3304
3628
|
activeDelimiter = null;
|
|
3305
3629
|
}
|
|
3306
3630
|
}
|