@reteps/tree-sitter-htmlmustache 0.2.1 → 0.3.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 +183 -126
- package/package.json +1 -1
- package/src/scanner.c +1 -40
- package/tree-sitter-htmlmustache.wasm +0 -0
package/cli/out/main.js
CHANGED
|
@@ -1715,16 +1715,39 @@ function loadConfigFileForPath(filePath) {
|
|
|
1715
1715
|
}
|
|
1716
1716
|
}
|
|
1717
1717
|
|
|
1718
|
-
// lsp/server/src/
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1718
|
+
// lsp/server/src/nodeHelpers.ts
|
|
1719
|
+
var MUSTACHE_SECTION_TYPES = /* @__PURE__ */ new Set([
|
|
1720
|
+
"mustache_section",
|
|
1721
|
+
"mustache_inverted_section"
|
|
1722
|
+
]);
|
|
1723
|
+
var RAW_CONTENT_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
1724
|
+
"html_script_element",
|
|
1725
|
+
"html_style_element",
|
|
1726
|
+
"html_raw_element"
|
|
1727
|
+
]);
|
|
1728
|
+
var HTML_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
1729
|
+
"html_element",
|
|
1730
|
+
"html_script_element",
|
|
1731
|
+
"html_style_element",
|
|
1732
|
+
"html_raw_element"
|
|
1733
|
+
]);
|
|
1734
|
+
function isMustacheSection(node) {
|
|
1735
|
+
return MUSTACHE_SECTION_TYPES.has(node.type);
|
|
1724
1736
|
}
|
|
1725
|
-
function
|
|
1726
|
-
|
|
1727
|
-
|
|
1737
|
+
function isRawContentElement(node) {
|
|
1738
|
+
return RAW_CONTENT_ELEMENT_TYPES.has(node.type);
|
|
1739
|
+
}
|
|
1740
|
+
function isHtmlElementType(node) {
|
|
1741
|
+
return HTML_ELEMENT_TYPES.has(node.type);
|
|
1742
|
+
}
|
|
1743
|
+
function getTagName(node) {
|
|
1744
|
+
for (const child of node.children) {
|
|
1745
|
+
if (child.type === "html_start_tag" || child.type === "html_self_closing_tag") {
|
|
1746
|
+
const tagNameNode = child.children.find((c) => c.type === "html_tag_name");
|
|
1747
|
+
if (tagNameNode) return tagNameNode.text;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
return null;
|
|
1728
1751
|
}
|
|
1729
1752
|
function getSectionName(node) {
|
|
1730
1753
|
const beginNode = node.children.find(
|
|
@@ -1734,6 +1757,18 @@ function getSectionName(node) {
|
|
|
1734
1757
|
const tagNameNode = beginNode.children.find((c) => c.type === "mustache_tag_name");
|
|
1735
1758
|
return tagNameNode?.text ?? null;
|
|
1736
1759
|
}
|
|
1760
|
+
function getErroneousEndTagName(node) {
|
|
1761
|
+
const nameNode = node.children.find((c) => c.type === "html_erroneous_end_tag_name");
|
|
1762
|
+
return nameNode?.text?.toLowerCase() ?? null;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
// lsp/server/src/htmlBalanceChecker.ts
|
|
1766
|
+
function getTagNameLower(element) {
|
|
1767
|
+
return getTagName(element)?.toLowerCase() ?? null;
|
|
1768
|
+
}
|
|
1769
|
+
function getErroneousEndTagNameLower(node) {
|
|
1770
|
+
return getErroneousEndTagName(node)?.toLowerCase() ?? null;
|
|
1771
|
+
}
|
|
1737
1772
|
function hasForcedEndTag(element) {
|
|
1738
1773
|
return element.children.some((c) => c.type === "html_forced_end_tag");
|
|
1739
1774
|
}
|
|
@@ -1750,7 +1785,7 @@ function extractFromNode(node) {
|
|
|
1750
1785
|
(c) => c.type !== "html_start_tag" && c.type !== "html_end_tag" && c.type !== "html_forced_end_tag"
|
|
1751
1786
|
);
|
|
1752
1787
|
if (hasForcedEndTag(node)) {
|
|
1753
|
-
const tagName =
|
|
1788
|
+
const tagName = getTagNameLower(node);
|
|
1754
1789
|
const items = [];
|
|
1755
1790
|
if (tagName) {
|
|
1756
1791
|
const startTag = node.children.find((c) => c.type === "html_start_tag");
|
|
@@ -1765,7 +1800,7 @@ function extractFromNode(node) {
|
|
|
1765
1800
|
return [];
|
|
1766
1801
|
}
|
|
1767
1802
|
if (node.type === "html_erroneous_end_tag") {
|
|
1768
|
-
const tagName =
|
|
1803
|
+
const tagName = getErroneousEndTagNameLower(node);
|
|
1769
1804
|
if (tagName) {
|
|
1770
1805
|
return [{ type: "close", tagName, node }];
|
|
1771
1806
|
}
|
|
@@ -1967,7 +2002,7 @@ function checkUnclosedTags(rootNode) {
|
|
|
1967
2002
|
const hasEndTag = node.children.some((c) => c.type === "html_end_tag");
|
|
1968
2003
|
const hasForcedEnd = node.children.some((c) => c.type === "html_forced_end_tag");
|
|
1969
2004
|
if (!hasEndTag && !hasForcedEnd) {
|
|
1970
|
-
const tagName =
|
|
2005
|
+
const tagName = getTagNameLower(node);
|
|
1971
2006
|
if (tagName && !VOID_ELEMENTS.has(tagName) && !OPTIONAL_END_TAG_ELEMENTS.has(tagName)) {
|
|
1972
2007
|
const startTag = node.children.find((c) => c.type === "html_start_tag");
|
|
1973
2008
|
errors.push({
|
|
@@ -2017,7 +2052,7 @@ function checkHtmlBalance(rootNode) {
|
|
|
2017
2052
|
function checkNestedSameNameSections(rootNode) {
|
|
2018
2053
|
const errors = [];
|
|
2019
2054
|
function visit(node, ancestors) {
|
|
2020
|
-
if (node
|
|
2055
|
+
if (isMustacheSection(node)) {
|
|
2021
2056
|
const name = getSectionName(node);
|
|
2022
2057
|
if (name) {
|
|
2023
2058
|
if (ancestors.has(name)) {
|
|
@@ -2077,7 +2112,7 @@ function checkConsecutiveSameNameSections(rootNode, sourceText) {
|
|
|
2077
2112
|
for (let i = 0; i < children.length - 1; i++) {
|
|
2078
2113
|
const current = children[i];
|
|
2079
2114
|
const next = children[i + 1];
|
|
2080
|
-
if (current
|
|
2115
|
+
if (!isMustacheSection(current) || current.type !== next.type) {
|
|
2081
2116
|
continue;
|
|
2082
2117
|
}
|
|
2083
2118
|
const currentName = getSectionName(current);
|
|
@@ -2113,6 +2148,58 @@ function checkConsecutiveSameNameSections(rootNode, sourceText) {
|
|
|
2113
2148
|
visit(rootNode);
|
|
2114
2149
|
return errors;
|
|
2115
2150
|
}
|
|
2151
|
+
var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
|
|
2152
|
+
"area",
|
|
2153
|
+
"base",
|
|
2154
|
+
"basefont",
|
|
2155
|
+
"bgsound",
|
|
2156
|
+
"br",
|
|
2157
|
+
"col",
|
|
2158
|
+
"command",
|
|
2159
|
+
"embed",
|
|
2160
|
+
"frame",
|
|
2161
|
+
"hr",
|
|
2162
|
+
"image",
|
|
2163
|
+
"img",
|
|
2164
|
+
"input",
|
|
2165
|
+
"isindex",
|
|
2166
|
+
"keygen",
|
|
2167
|
+
"link",
|
|
2168
|
+
"menuitem",
|
|
2169
|
+
"meta",
|
|
2170
|
+
"nextid",
|
|
2171
|
+
"param",
|
|
2172
|
+
"source",
|
|
2173
|
+
"track",
|
|
2174
|
+
"wbr"
|
|
2175
|
+
]);
|
|
2176
|
+
function checkSelfClosingNonVoidTags(rootNode) {
|
|
2177
|
+
const errors = [];
|
|
2178
|
+
function visit(node) {
|
|
2179
|
+
if (node.type === "html_self_closing_tag") {
|
|
2180
|
+
const tagNameNode = node.children.find((c) => c.type === "html_tag_name");
|
|
2181
|
+
const tagName = tagNameNode?.text.toLowerCase();
|
|
2182
|
+
if (tagName && !VOID_ELEMENTS2.has(tagName)) {
|
|
2183
|
+
errors.push({
|
|
2184
|
+
node,
|
|
2185
|
+
message: `Self-closing non-void element: <${tagNameNode.text}/>`,
|
|
2186
|
+
fix: [{
|
|
2187
|
+
startIndex: node.startIndex,
|
|
2188
|
+
endIndex: node.endIndex,
|
|
2189
|
+
newText: node.text.replace(/\s*\/>$/, ">") + `</${tagNameNode.text}>`
|
|
2190
|
+
}],
|
|
2191
|
+
fixDescription: "Replace self-closing syntax with explicit close tag"
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
for (const child of node.children) {
|
|
2197
|
+
visit(child);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
visit(rootNode);
|
|
2201
|
+
return errors;
|
|
2202
|
+
}
|
|
2116
2203
|
function areMutuallyExclusive(a, b) {
|
|
2117
2204
|
for (const ac of a) {
|
|
2118
2205
|
for (const bc of b) {
|
|
@@ -2145,9 +2232,7 @@ function collectAttributes(node, conditions, out) {
|
|
|
2145
2232
|
out.push({ nameNode, conditions: [...conditions] });
|
|
2146
2233
|
}
|
|
2147
2234
|
} else if (child.type === "mustache_attribute") {
|
|
2148
|
-
const section = child.children.find(
|
|
2149
|
-
(c) => c.type === "mustache_section" || c.type === "mustache_inverted_section"
|
|
2150
|
-
);
|
|
2235
|
+
const section = child.children.find((c) => isMustacheSection(c));
|
|
2151
2236
|
if (section) {
|
|
2152
2237
|
const name = getSectionName(section);
|
|
2153
2238
|
if (name) {
|
|
@@ -2203,7 +2288,12 @@ function checkDuplicateAttributes(rootNode) {
|
|
|
2203
2288
|
return errors;
|
|
2204
2289
|
}
|
|
2205
2290
|
|
|
2206
|
-
//
|
|
2291
|
+
// lsp/server/src/collectErrors.ts
|
|
2292
|
+
var ERROR_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
2293
|
+
"ERROR",
|
|
2294
|
+
"mustache_erroneous_section_end",
|
|
2295
|
+
"mustache_erroneous_inverted_section_end"
|
|
2296
|
+
]);
|
|
2207
2297
|
function errorMessageForNode(nodeType, node) {
|
|
2208
2298
|
if (nodeType === "mustache_erroneous_section_end" || nodeType === "mustache_erroneous_inverted_section_end") {
|
|
2209
2299
|
const tagNameNode = node.children.find((c) => c.type === "mustache_erroneous_tag_name");
|
|
@@ -2214,12 +2304,7 @@ function errorMessageForNode(nodeType, node) {
|
|
|
2214
2304
|
}
|
|
2215
2305
|
return `Missing ${nodeType}`;
|
|
2216
2306
|
}
|
|
2217
|
-
|
|
2218
|
-
"ERROR",
|
|
2219
|
-
"mustache_erroneous_section_end",
|
|
2220
|
-
"mustache_erroneous_inverted_section_end"
|
|
2221
|
-
]);
|
|
2222
|
-
function collectErrors(tree, file) {
|
|
2307
|
+
function collectErrors(tree) {
|
|
2223
2308
|
const errors = [];
|
|
2224
2309
|
const cursor = tree.walk();
|
|
2225
2310
|
function visit() {
|
|
@@ -2227,13 +2312,8 @@ function collectErrors(tree, file) {
|
|
|
2227
2312
|
const nodeType = cursor.nodeType;
|
|
2228
2313
|
if (ERROR_NODE_TYPES.has(nodeType) || cursor.nodeIsMissing) {
|
|
2229
2314
|
errors.push({
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
column: node.startPosition.column + 1,
|
|
2233
|
-
endLine: node.endPosition.row + 1,
|
|
2234
|
-
endColumn: node.endPosition.column + 1,
|
|
2235
|
-
message: errorMessageForNode(nodeType, node),
|
|
2236
|
-
nodeText: node.text
|
|
2315
|
+
node,
|
|
2316
|
+
message: errorMessageForNode(nodeType, node)
|
|
2237
2317
|
});
|
|
2238
2318
|
if (nodeType === "ERROR") return;
|
|
2239
2319
|
}
|
|
@@ -2245,47 +2325,26 @@ function collectErrors(tree, file) {
|
|
|
2245
2325
|
}
|
|
2246
2326
|
}
|
|
2247
2327
|
visit();
|
|
2248
|
-
const
|
|
2249
|
-
const balanceErrors = checkHtmlBalance(rootNode);
|
|
2328
|
+
const balanceErrors = checkHtmlBalance(tree.rootNode);
|
|
2250
2329
|
for (const error of balanceErrors) {
|
|
2251
|
-
errors.push({
|
|
2252
|
-
file,
|
|
2253
|
-
line: error.node.startPosition.row + 1,
|
|
2254
|
-
column: error.node.startPosition.column + 1,
|
|
2255
|
-
endLine: error.node.endPosition.row + 1,
|
|
2256
|
-
endColumn: error.node.endPosition.column + 1,
|
|
2257
|
-
message: error.message,
|
|
2258
|
-
nodeText: error.node.text
|
|
2259
|
-
});
|
|
2330
|
+
errors.push({ node: error.node, message: error.message });
|
|
2260
2331
|
}
|
|
2261
|
-
const unclosedErrors = checkUnclosedTags(rootNode);
|
|
2332
|
+
const unclosedErrors = checkUnclosedTags(tree.rootNode);
|
|
2262
2333
|
for (const error of unclosedErrors) {
|
|
2263
|
-
errors.push({
|
|
2264
|
-
file,
|
|
2265
|
-
line: error.node.startPosition.row + 1,
|
|
2266
|
-
column: error.node.startPosition.column + 1,
|
|
2267
|
-
endLine: error.node.endPosition.row + 1,
|
|
2268
|
-
endColumn: error.node.endPosition.column + 1,
|
|
2269
|
-
message: error.message,
|
|
2270
|
-
nodeText: error.node.text
|
|
2271
|
-
});
|
|
2334
|
+
errors.push({ node: error.node, message: error.message });
|
|
2272
2335
|
}
|
|
2273
|
-
const sourceText = rootNode.text;
|
|
2336
|
+
const sourceText = tree.rootNode.text;
|
|
2274
2337
|
const mustacheChecks = [
|
|
2275
|
-
...checkNestedSameNameSections(rootNode),
|
|
2276
|
-
...checkUnquotedMustacheAttributes(rootNode),
|
|
2277
|
-
...checkConsecutiveSameNameSections(rootNode, sourceText),
|
|
2278
|
-
...
|
|
2338
|
+
...checkNestedSameNameSections(tree.rootNode),
|
|
2339
|
+
...checkUnquotedMustacheAttributes(tree.rootNode),
|
|
2340
|
+
...checkConsecutiveSameNameSections(tree.rootNode, sourceText),
|
|
2341
|
+
...checkSelfClosingNonVoidTags(tree.rootNode),
|
|
2342
|
+
...checkDuplicateAttributes(tree.rootNode)
|
|
2279
2343
|
];
|
|
2280
2344
|
for (const error of mustacheChecks) {
|
|
2281
2345
|
errors.push({
|
|
2282
|
-
|
|
2283
|
-
line: error.node.startPosition.row + 1,
|
|
2284
|
-
column: error.node.startPosition.column + 1,
|
|
2285
|
-
endLine: error.node.endPosition.row + 1,
|
|
2286
|
-
endColumn: error.node.endPosition.column + 1,
|
|
2346
|
+
node: error.node,
|
|
2287
2347
|
message: error.message,
|
|
2288
|
-
nodeText: error.node.text,
|
|
2289
2348
|
severity: error.severity,
|
|
2290
2349
|
fix: error.fix,
|
|
2291
2350
|
fixDescription: error.fixDescription
|
|
@@ -2293,6 +2352,23 @@ function collectErrors(tree, file) {
|
|
|
2293
2352
|
}
|
|
2294
2353
|
return errors;
|
|
2295
2354
|
}
|
|
2355
|
+
|
|
2356
|
+
// cli/src/check.ts
|
|
2357
|
+
function collectErrors2(tree, file) {
|
|
2358
|
+
const errors = collectErrors(tree);
|
|
2359
|
+
return errors.map((error) => ({
|
|
2360
|
+
file,
|
|
2361
|
+
line: error.node.startPosition.row + 1,
|
|
2362
|
+
column: error.node.startPosition.column + 1,
|
|
2363
|
+
endLine: error.node.endPosition.row + 1,
|
|
2364
|
+
endColumn: error.node.endPosition.column + 1,
|
|
2365
|
+
message: error.message,
|
|
2366
|
+
nodeText: error.node.text,
|
|
2367
|
+
severity: error.severity,
|
|
2368
|
+
fix: error.fix,
|
|
2369
|
+
fixDescription: error.fixDescription
|
|
2370
|
+
}));
|
|
2371
|
+
}
|
|
2296
2372
|
function formatError(error, source) {
|
|
2297
2373
|
const lines = source.split("\n");
|
|
2298
2374
|
const errorLine = error.line - 1;
|
|
@@ -2467,7 +2543,7 @@ async function run(args) {
|
|
|
2467
2543
|
let source = import_node_fs.default.readFileSync(file, "utf-8");
|
|
2468
2544
|
if (fixMode) {
|
|
2469
2545
|
const tree2 = parseDocument(source);
|
|
2470
|
-
const errors2 =
|
|
2546
|
+
const errors2 = collectErrors2(tree2, displayPath);
|
|
2471
2547
|
const fixed = applyFixes(source, errors2);
|
|
2472
2548
|
if (fixed !== source) {
|
|
2473
2549
|
import_node_fs.default.writeFileSync(file, fixed, "utf-8");
|
|
@@ -2475,7 +2551,7 @@ async function run(args) {
|
|
|
2475
2551
|
}
|
|
2476
2552
|
}
|
|
2477
2553
|
const tree = parseDocument(source);
|
|
2478
|
-
const errors =
|
|
2554
|
+
const errors = collectErrors2(tree, displayPath);
|
|
2479
2555
|
const fileErrors = errors.filter((e) => e.severity !== "warning");
|
|
2480
2556
|
const fileWarnings = errors.filter((e) => e.severity === "warning");
|
|
2481
2557
|
if (errors.length > 0) {
|
|
@@ -2918,21 +2994,6 @@ function isLine(doc) {
|
|
|
2918
2994
|
}
|
|
2919
2995
|
|
|
2920
2996
|
// lsp/server/src/formatting/utils.ts
|
|
2921
|
-
function getTagName2(node) {
|
|
2922
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
2923
|
-
const child = node.child(i);
|
|
2924
|
-
if (!child) continue;
|
|
2925
|
-
if (child.type === "html_start_tag" || child.type === "html_self_closing_tag") {
|
|
2926
|
-
for (let j = 0; j < child.childCount; j++) {
|
|
2927
|
-
const tagChild = child.child(j);
|
|
2928
|
-
if (tagChild && tagChild.type === "html_tag_name") {
|
|
2929
|
-
return tagChild.text;
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
}
|
|
2933
|
-
}
|
|
2934
|
-
return null;
|
|
2935
|
-
}
|
|
2936
2997
|
function normalizeText(text2) {
|
|
2937
2998
|
return text2.split("\n").map((line2) => line2.replace(/[ \t]+/g, " ").trim()).filter((line2, i, arr) => line2 || i > 0 && i < arr.length - 1).join("\n");
|
|
2938
2999
|
}
|
|
@@ -3009,10 +3070,7 @@ function getIgnoreDirective(node) {
|
|
|
3009
3070
|
}
|
|
3010
3071
|
|
|
3011
3072
|
// lsp/server/src/formatting/classifier.ts
|
|
3012
|
-
var
|
|
3013
|
-
function setCustomCodeTags(tags) {
|
|
3014
|
-
customCodeTags = new Set(tags.map((t) => t.toLowerCase()));
|
|
3015
|
-
}
|
|
3073
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
3016
3074
|
var CSS_DISPLAY_MAP = {
|
|
3017
3075
|
// Block elements
|
|
3018
3076
|
address: "block",
|
|
@@ -3103,10 +3161,10 @@ var PRESERVE_CONTENT_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
3103
3161
|
"script",
|
|
3104
3162
|
"style"
|
|
3105
3163
|
]);
|
|
3106
|
-
function getCSSDisplay(node) {
|
|
3164
|
+
function getCSSDisplay(node, customCodeTags = EMPTY_SET) {
|
|
3107
3165
|
const type = node.type;
|
|
3108
3166
|
if (type === "html_element") {
|
|
3109
|
-
const tagName =
|
|
3167
|
+
const tagName = getTagName(node);
|
|
3110
3168
|
if (tagName) {
|
|
3111
3169
|
if (customCodeTags.has(tagName.toLowerCase())) {
|
|
3112
3170
|
return "block";
|
|
@@ -3115,11 +3173,11 @@ function getCSSDisplay(node) {
|
|
|
3115
3173
|
}
|
|
3116
3174
|
return "block";
|
|
3117
3175
|
}
|
|
3118
|
-
if (
|
|
3176
|
+
if (isRawContentElement(node)) {
|
|
3119
3177
|
return "block";
|
|
3120
3178
|
}
|
|
3121
|
-
if (
|
|
3122
|
-
return hasBlockContent(node) ? "block" : "inline";
|
|
3179
|
+
if (isMustacheSection(node)) {
|
|
3180
|
+
return hasBlockContent(node, customCodeTags) ? "block" : "inline";
|
|
3123
3181
|
}
|
|
3124
3182
|
return "inline";
|
|
3125
3183
|
}
|
|
@@ -3142,55 +3200,55 @@ function isWhitespaceInsensitive(display) {
|
|
|
3142
3200
|
return false;
|
|
3143
3201
|
}
|
|
3144
3202
|
}
|
|
3145
|
-
function isBlockLevel(node) {
|
|
3203
|
+
function isBlockLevel(node, customCodeTags = EMPTY_SET) {
|
|
3146
3204
|
const type = node.type;
|
|
3147
|
-
if (
|
|
3148
|
-
return hasBlockContent(node);
|
|
3205
|
+
if (isMustacheSection(node)) {
|
|
3206
|
+
return hasBlockContent(node, customCodeTags);
|
|
3149
3207
|
}
|
|
3150
3208
|
if (type === "html_element") {
|
|
3151
|
-
const display = getCSSDisplay(node);
|
|
3209
|
+
const display = getCSSDisplay(node, customCodeTags);
|
|
3152
3210
|
return isWhitespaceInsensitive(display);
|
|
3153
3211
|
}
|
|
3154
|
-
if (
|
|
3212
|
+
if (isRawContentElement(node)) {
|
|
3155
3213
|
return true;
|
|
3156
3214
|
}
|
|
3157
3215
|
return false;
|
|
3158
3216
|
}
|
|
3159
|
-
function shouldPreserveContent(node) {
|
|
3217
|
+
function shouldPreserveContent(node, customCodeTags = EMPTY_SET) {
|
|
3160
3218
|
const type = node.type;
|
|
3161
|
-
if (
|
|
3219
|
+
if (isRawContentElement(node)) {
|
|
3162
3220
|
return true;
|
|
3163
3221
|
}
|
|
3164
3222
|
if (type === "html_element") {
|
|
3165
|
-
const tagName =
|
|
3223
|
+
const tagName = getTagName(node);
|
|
3166
3224
|
if (!tagName) return false;
|
|
3167
3225
|
const lower = tagName.toLowerCase();
|
|
3168
3226
|
return PRESERVE_CONTENT_ELEMENTS.has(lower) || customCodeTags.has(lower);
|
|
3169
3227
|
}
|
|
3170
3228
|
return false;
|
|
3171
3229
|
}
|
|
3172
|
-
function hasBlockContent(sectionNode) {
|
|
3230
|
+
function hasBlockContent(sectionNode, customCodeTags = EMPTY_SET) {
|
|
3173
3231
|
const contentNodes = getContentNodes(sectionNode);
|
|
3174
3232
|
if (hasImplicitEndTags(contentNodes)) {
|
|
3175
3233
|
return true;
|
|
3176
3234
|
}
|
|
3177
3235
|
for (const node of contentNodes) {
|
|
3178
|
-
if (isBlockLevelContent(node)) {
|
|
3236
|
+
if (isBlockLevelContent(node, customCodeTags)) {
|
|
3179
3237
|
return true;
|
|
3180
3238
|
}
|
|
3181
3239
|
}
|
|
3182
3240
|
return false;
|
|
3183
3241
|
}
|
|
3184
|
-
function isBlockLevelContent(node) {
|
|
3242
|
+
function isBlockLevelContent(node, customCodeTags = EMPTY_SET) {
|
|
3185
3243
|
const type = node.type;
|
|
3186
3244
|
if (type === "html_element") {
|
|
3187
3245
|
return true;
|
|
3188
3246
|
}
|
|
3189
|
-
if (
|
|
3247
|
+
if (isRawContentElement(node)) {
|
|
3190
3248
|
return true;
|
|
3191
3249
|
}
|
|
3192
|
-
if (
|
|
3193
|
-
return hasBlockContent(node);
|
|
3250
|
+
if (isMustacheSection(node)) {
|
|
3251
|
+
return hasBlockContent(node, customCodeTags);
|
|
3194
3252
|
}
|
|
3195
3253
|
return false;
|
|
3196
3254
|
}
|
|
@@ -3297,10 +3355,10 @@ function shouldHtmlElementStayInline(node, index, nodes) {
|
|
|
3297
3355
|
}
|
|
3298
3356
|
return false;
|
|
3299
3357
|
}
|
|
3300
|
-
function shouldTreatAsBlock(node, index, nodes) {
|
|
3301
|
-
const
|
|
3302
|
-
const
|
|
3303
|
-
return
|
|
3358
|
+
function shouldTreatAsBlock(node, index, nodes, customCodeTags = EMPTY_SET) {
|
|
3359
|
+
const isHtmlEl = isHtmlElementType(node);
|
|
3360
|
+
const isMustacheSec = isMustacheSection(node);
|
|
3361
|
+
return isHtmlEl && !shouldHtmlElementStayInline(node, index, nodes) || isMustacheSec && !isInTextFlow(node, index, nodes) || isBlockLevel(node, customCodeTags) && !isInTextFlow(node, index, nodes);
|
|
3304
3362
|
}
|
|
3305
3363
|
|
|
3306
3364
|
// lsp/server/src/customCodeTags.ts
|
|
@@ -3443,9 +3501,10 @@ function formatText(node) {
|
|
|
3443
3501
|
return text(normalizeText(node.text));
|
|
3444
3502
|
}
|
|
3445
3503
|
function formatHtmlElement(node, context) {
|
|
3446
|
-
const
|
|
3504
|
+
const tags = context.customCodeTags;
|
|
3505
|
+
const display = getCSSDisplay(node, tags);
|
|
3447
3506
|
const isBlock = isWhitespaceInsensitive(display);
|
|
3448
|
-
const preserveContent = shouldPreserveContent(node);
|
|
3507
|
+
const preserveContent = shouldPreserveContent(node, tags);
|
|
3449
3508
|
const selfClosing = node.childCount === 1 && node.child(0)?.type === "html_self_closing_tag";
|
|
3450
3509
|
if (selfClosing) {
|
|
3451
3510
|
const tag = node.child(0);
|
|
@@ -3474,7 +3533,7 @@ function formatHtmlElement(node, context) {
|
|
|
3474
3533
|
parts.push(formatStartTag(startTag, context));
|
|
3475
3534
|
}
|
|
3476
3535
|
const hasHtmlElementChildren = contentNodes.some(
|
|
3477
|
-
(child) => child.type === "html_element" || child
|
|
3536
|
+
(child) => child.type === "html_element" || isRawContentElement(child) || isBlockLevel(child, tags)
|
|
3478
3537
|
);
|
|
3479
3538
|
if (preserveContent) {
|
|
3480
3539
|
const tagNameLower = startTag ? getTagNameFromStartTag(startTag) : null;
|
|
@@ -3538,11 +3597,11 @@ function formatHtmlElement(node, context) {
|
|
|
3538
3597
|
const hasContent = hasDocContent(formattedContent);
|
|
3539
3598
|
if (hasContent) {
|
|
3540
3599
|
const hasBlockChildren = contentNodes.some((child, i) => {
|
|
3541
|
-
if (!shouldTreatAsBlock(child, i, contentNodes)) {
|
|
3600
|
+
if (!shouldTreatAsBlock(child, i, contentNodes, tags)) {
|
|
3542
3601
|
return false;
|
|
3543
3602
|
}
|
|
3544
|
-
const childDisplay = getCSSDisplay(child);
|
|
3545
|
-
return isWhitespaceInsensitive(childDisplay) || child
|
|
3603
|
+
const childDisplay = getCSSDisplay(child, tags);
|
|
3604
|
+
return isWhitespaceInsensitive(childDisplay) || isRawContentElement(child);
|
|
3546
3605
|
});
|
|
3547
3606
|
if (isBlock && !hasBlockChildren) {
|
|
3548
3607
|
const doc = group(
|
|
@@ -3693,11 +3752,11 @@ function formatMustacheSection(node, context) {
|
|
|
3693
3752
|
parts.push(hardline);
|
|
3694
3753
|
} else {
|
|
3695
3754
|
const hasBlockChildren = contentNodes.some((child, i) => {
|
|
3696
|
-
if (!shouldTreatAsBlock(child, i, contentNodes)) {
|
|
3755
|
+
if (!shouldTreatAsBlock(child, i, contentNodes, context.customCodeTags)) {
|
|
3697
3756
|
return false;
|
|
3698
3757
|
}
|
|
3699
|
-
const childDisplay = getCSSDisplay(child);
|
|
3700
|
-
return isWhitespaceInsensitive(childDisplay) || child
|
|
3758
|
+
const childDisplay = getCSSDisplay(child, context.customCodeTags);
|
|
3759
|
+
return isWhitespaceInsensitive(childDisplay) || isRawContentElement(child);
|
|
3701
3760
|
});
|
|
3702
3761
|
if (!hasBlockChildren) {
|
|
3703
3762
|
parts.push(indent(concat([softline, formattedContent])));
|
|
@@ -3914,10 +3973,10 @@ function formatBlockChildren(nodes, context) {
|
|
|
3914
3973
|
lastNodeEnd = node.endIndex;
|
|
3915
3974
|
continue;
|
|
3916
3975
|
}
|
|
3917
|
-
const treatAsBlock = shouldTreatAsBlock(node, i, nodes);
|
|
3976
|
+
const treatAsBlock = shouldTreatAsBlock(node, i, nodes, context.customCodeTags);
|
|
3918
3977
|
if (lastNodeEnd >= 0 && node.startIndex > lastNodeEnd) {
|
|
3919
3978
|
const prevNode = nodes[i - 1];
|
|
3920
|
-
const prevTreatAsBlock = shouldTreatAsBlock(prevNode, i - 1, nodes);
|
|
3979
|
+
const prevTreatAsBlock = shouldTreatAsBlock(prevNode, i - 1, nodes, context.customCodeTags);
|
|
3921
3980
|
if (!prevTreatAsBlock && !treatAsBlock) {
|
|
3922
3981
|
const gap = context.document.getText().slice(lastNodeEnd, node.startIndex);
|
|
3923
3982
|
if (/\s/.test(gap)) {
|
|
@@ -4145,19 +4204,17 @@ function createIndentUnit(options) {
|
|
|
4145
4204
|
|
|
4146
4205
|
// lsp/server/src/formatting/index.ts
|
|
4147
4206
|
function formatDocument2(tree, document, options, params = {}) {
|
|
4148
|
-
const { customCodeTags
|
|
4207
|
+
const { customCodeTags, printWidth = 80, embeddedFormatted, mustacheSpaces, customCodeTagConfigs, configFile } = params;
|
|
4149
4208
|
const mergedOptions = mergeOptions(options, document.uri, configFile);
|
|
4150
4209
|
const indentUnit = createIndentUnit(mergedOptions);
|
|
4151
|
-
if (customCodeTags2) {
|
|
4152
|
-
setCustomCodeTags(customCodeTags2);
|
|
4153
|
-
}
|
|
4154
4210
|
if (tree.rootNode.hasError) {
|
|
4155
4211
|
return [];
|
|
4156
4212
|
}
|
|
4157
4213
|
const configMap = buildConfigMap(customCodeTagConfigs);
|
|
4214
|
+
const customCodeTagSet = customCodeTags ? new Set(customCodeTags.map((t) => t.toLowerCase())) : void 0;
|
|
4158
4215
|
const context = {
|
|
4159
4216
|
document,
|
|
4160
|
-
customCodeTags:
|
|
4217
|
+
customCodeTags: customCodeTagSet,
|
|
4161
4218
|
customCodeTagConfigs: configMap,
|
|
4162
4219
|
embeddedFormatted,
|
|
4163
4220
|
mustacheSpaces
|
|
@@ -4256,7 +4313,7 @@ function resolveSettings(flags, filePath) {
|
|
|
4256
4313
|
let insertSpaces = true;
|
|
4257
4314
|
let printWidth = 80;
|
|
4258
4315
|
let mustacheSpaces = false;
|
|
4259
|
-
let
|
|
4316
|
+
let customCodeTags;
|
|
4260
4317
|
let customCodeTagConfigs;
|
|
4261
4318
|
const configFile = filePath ? loadConfigFileForPath(filePath) : null;
|
|
4262
4319
|
if (configFile) {
|
|
@@ -4265,7 +4322,7 @@ function resolveSettings(flags, filePath) {
|
|
|
4265
4322
|
if (configFile.mustacheSpaces !== void 0) mustacheSpaces = configFile.mustacheSpaces;
|
|
4266
4323
|
if (configFile.customCodeTags && configFile.customCodeTags.length > 0) {
|
|
4267
4324
|
const parsed = parseCustomCodeTagSettings(configFile.customCodeTags);
|
|
4268
|
-
|
|
4325
|
+
customCodeTags = parsed.tagNames;
|
|
4269
4326
|
customCodeTagConfigs = parsed.configs;
|
|
4270
4327
|
}
|
|
4271
4328
|
}
|
|
@@ -4282,7 +4339,7 @@ function resolveSettings(flags, filePath) {
|
|
|
4282
4339
|
options: { tabSize, insertSpaces },
|
|
4283
4340
|
printWidth,
|
|
4284
4341
|
mustacheSpaces,
|
|
4285
|
-
customCodeTags
|
|
4342
|
+
customCodeTags,
|
|
4286
4343
|
customCodeTagConfigs,
|
|
4287
4344
|
configFile
|
|
4288
4345
|
};
|
package/package.json
CHANGED
package/src/scanner.c
CHANGED
|
@@ -83,7 +83,7 @@ static unsigned serialize(Scanner *scanner, char *buffer) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
memcpy(&buffer[0], &serialized_tag_count, sizeof(serialized_tag_count));
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
// Mustache tags
|
|
88
88
|
uint16_t m_tag_count =
|
|
89
89
|
scanner->mustache_tags.size > UINT16_MAX ? UINT16_MAX : scanner->mustache_tags.size;
|
|
@@ -93,7 +93,6 @@ static unsigned serialize(Scanner *scanner, char *buffer) {
|
|
|
93
93
|
size += sizeof(m_serialized_tag_count);
|
|
94
94
|
memcpy(&buffer[size], &m_tag_count, sizeof(m_tag_count));
|
|
95
95
|
size += sizeof(m_tag_count);
|
|
96
|
-
// printf("[S] m_tag_count: %d\n", m_tag_count);
|
|
97
96
|
|
|
98
97
|
for (; m_serialized_tag_count < m_tag_count; m_serialized_tag_count++) {
|
|
99
98
|
MustacheTag tag = scanner->mustache_tags.contents[m_serialized_tag_count];
|
|
@@ -113,12 +112,10 @@ static unsigned serialize(Scanner *scanner, char *buffer) {
|
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
memcpy(&buffer[mustache_start_offset], &m_serialized_tag_count, sizeof(m_serialized_tag_count));
|
|
116
|
-
// printf("[S] m_serialized_tag_count: %d\n", m_serialized_tag_count);
|
|
117
115
|
return size;
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
static void deserialize(Scanner *scanner, const char *buffer, unsigned length) {
|
|
121
|
-
// printf("deserialize\n");
|
|
122
119
|
for (unsigned i = 0; i < scanner->tags.size; i++) {
|
|
123
120
|
tag_free(&scanner->tags.contents[i]);
|
|
124
121
|
}
|
|
@@ -195,22 +192,12 @@ static void deserialize(Scanner *scanner, const char *buffer, unsigned length) {
|
|
|
195
192
|
}
|
|
196
193
|
}
|
|
197
194
|
|
|
198
|
-
static void print_tag_name(String *tag_name) {
|
|
199
|
-
// printf("tag_size: %d\n", tag->tag_name.size);
|
|
200
|
-
for (uint32_t i = 0; i < tag_name->size; i++) {
|
|
201
|
-
printf("%c", tag_name->contents[i]);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
195
|
static String scan_html_tag_name(TSLexer *lexer) {
|
|
206
196
|
String tag_name = array_new();
|
|
207
197
|
while (iswalnum(lexer->lookahead) || lexer->lookahead == '-' || lexer->lookahead == ':') {
|
|
208
198
|
array_push(&tag_name, towupper(lexer->lookahead));
|
|
209
199
|
advance(lexer);
|
|
210
200
|
}
|
|
211
|
-
// printf("tag_name: ");
|
|
212
|
-
// print_tag_name(&tag_name);
|
|
213
|
-
// printf("\n");
|
|
214
201
|
return tag_name;
|
|
215
202
|
}
|
|
216
203
|
|
|
@@ -431,8 +418,6 @@ static String scan_mustache_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
431
418
|
array_push(&tag_name, lexer->lookahead);
|
|
432
419
|
advance(lexer);
|
|
433
420
|
}
|
|
434
|
-
// print_tag_name(&tag_name);
|
|
435
|
-
// printf("\n");
|
|
436
421
|
return tag_name;
|
|
437
422
|
}
|
|
438
423
|
|
|
@@ -445,17 +430,7 @@ static bool scan_mustache_start_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
445
430
|
MustacheTag tag = mustache_tag_new();
|
|
446
431
|
tag.tag_name = tag_name;
|
|
447
432
|
tag.html_tag_stack_size = scanner->tags.size;
|
|
448
|
-
// printf("pushing tag: ");
|
|
449
|
-
// print_tag_name(&tag.tag_name);
|
|
450
|
-
// printf("\n");
|
|
451
433
|
array_push(&scanner->mustache_tags, tag);
|
|
452
|
-
// printf("--------------------------------\n");
|
|
453
|
-
// for (unsigned i = 0; i < scanner->mustache_tags.size; i++) {
|
|
454
|
-
// printf("\tSTACK (START), tag_name: ");
|
|
455
|
-
// print_tag_name(&scanner->mustache_tags.contents[i]);
|
|
456
|
-
// printf("\n");
|
|
457
|
-
// }
|
|
458
|
-
// printf("--------------------------------\n");
|
|
459
434
|
lexer->result_symbol = MUSTACHE_START_TAG_NAME;
|
|
460
435
|
return true;
|
|
461
436
|
}
|
|
@@ -469,23 +444,11 @@ static bool scan_mustache_end_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
469
444
|
}
|
|
470
445
|
|
|
471
446
|
|
|
472
|
-
// Print whole stack
|
|
473
|
-
// printf("--------------------------------\n");
|
|
474
|
-
// printf("num tags: %d\n", scanner->mustache_tags.size);
|
|
475
|
-
// for (unsigned i = 0; i < scanner->mustache_tags.size; i++) {
|
|
476
|
-
// printf("\tSTACK (END), tag_name: ");
|
|
477
|
-
// print_tag_name(&scanner->mustache_tags.contents[i].tag_name);
|
|
478
|
-
// printf("\n");
|
|
479
|
-
// }
|
|
480
|
-
// printf("--------------------------------\n");
|
|
481
447
|
MustacheTag tag = mustache_tag_new();
|
|
482
448
|
tag.tag_name = tag_name;
|
|
483
449
|
if (scanner->mustache_tags.size > 0 && mustache_tag_eq(array_back(&scanner->mustache_tags), &tag)) {
|
|
484
450
|
MustacheTag popped_tag = array_pop(&scanner->mustache_tags);
|
|
485
451
|
mustache_tag_free(&popped_tag);
|
|
486
|
-
// printf("popped tag (correct): ");
|
|
487
|
-
// print_tag_name(&popped_tag.tag_name);
|
|
488
|
-
// printf("\n");
|
|
489
452
|
lexer->result_symbol = MUSTACHE_END_TAG_NAME;
|
|
490
453
|
} else {
|
|
491
454
|
if (scanner->mustache_tags.size > 0) {
|
|
@@ -501,7 +464,6 @@ static bool scan_mustache_end_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
501
464
|
|
|
502
465
|
static bool scan_mustache_end_tag_html_implicit_end_tag(Scanner *scanner, TSLexer *lexer) {
|
|
503
466
|
lexer->mark_end(lexer);
|
|
504
|
-
// printf("next char: %c\n", lexer->lookahead);
|
|
505
467
|
if (lexer->lookahead != '{') {
|
|
506
468
|
return false;
|
|
507
469
|
}
|
|
@@ -547,7 +509,6 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
|
|
|
547
509
|
|
|
548
510
|
|
|
549
511
|
if (valid_symbols[MUSTACHE_START_TAG_NAME]) {
|
|
550
|
-
// printf("MUSTACHE_START_TAG_NAME\n");
|
|
551
512
|
return scan_mustache_start_tag_name(scanner, lexer);
|
|
552
513
|
}
|
|
553
514
|
|
|
Binary file
|