@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 CHANGED
@@ -1715,16 +1715,39 @@ function loadConfigFileForPath(filePath) {
1715
1715
  }
1716
1716
  }
1717
1717
 
1718
- // lsp/server/src/htmlBalanceChecker.ts
1719
- function getTagName(element) {
1720
- const startTag = element.children.find((c) => c.type === "html_start_tag");
1721
- if (!startTag) return null;
1722
- const tagNameNode = startTag.children.find((c) => c.type === "html_tag_name");
1723
- return tagNameNode?.text?.toLowerCase() ?? null;
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 getErroneousEndTagName(node) {
1726
- const nameNode = node.children.find((c) => c.type === "html_erroneous_end_tag_name");
1727
- return nameNode?.text?.toLowerCase() ?? null;
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 = getTagName(node);
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 = getErroneousEndTagName(node);
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 = getTagName(node);
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.type === "mustache_section" || node.type === "mustache_inverted_section") {
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.type !== "mustache_section" && current.type !== "mustache_inverted_section" || current.type !== next.type) {
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
- // cli/src/check.ts
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
- var ERROR_NODE_TYPES = /* @__PURE__ */ new Set([
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
- file,
2231
- line: node.startPosition.row + 1,
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 rootNode = tree.rootNode;
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
- ...checkDuplicateAttributes(rootNode)
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
- file,
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 = collectErrors(tree2, displayPath);
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 = collectErrors(tree, displayPath);
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 customCodeTags = /* @__PURE__ */ new Set();
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 = getTagName2(node);
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 (type === "html_script_element" || type === "html_style_element" || type === "html_raw_element") {
3176
+ if (isRawContentElement(node)) {
3119
3177
  return "block";
3120
3178
  }
3121
- if (type === "mustache_section" || type === "mustache_inverted_section") {
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 (type === "mustache_section" || type === "mustache_inverted_section") {
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 (type === "html_script_element" || type === "html_style_element" || type === "html_raw_element") {
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 (type === "html_script_element" || type === "html_style_element" || type === "html_raw_element") {
3219
+ if (isRawContentElement(node)) {
3162
3220
  return true;
3163
3221
  }
3164
3222
  if (type === "html_element") {
3165
- const tagName = getTagName2(node);
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 (type === "html_script_element" || type === "html_style_element" || type === "html_raw_element") {
3247
+ if (isRawContentElement(node)) {
3190
3248
  return true;
3191
3249
  }
3192
- if (type === "mustache_section" || type === "mustache_inverted_section") {
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 isHtmlElement = node.type === "html_element" || node.type === "html_script_element" || node.type === "html_style_element" || node.type === "html_raw_element";
3302
- const isMustacheSection = node.type === "mustache_section" || node.type === "mustache_inverted_section";
3303
- return isHtmlElement && !shouldHtmlElementStayInline(node, index, nodes) || isMustacheSection && !isInTextFlow(node, index, nodes) || isBlockLevel(node) && !isInTextFlow(node, index, nodes);
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 display = getCSSDisplay(node);
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.type === "html_script_element" || child.type === "html_style_element" || child.type === "html_raw_element" || isBlockLevel(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.type === "html_script_element" || child.type === "html_style_element" || child.type === "html_raw_element";
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.type === "html_script_element" || child.type === "html_style_element" || child.type === "html_raw_element";
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: customCodeTags2, printWidth = 80, embeddedFormatted, mustacheSpaces, customCodeTagConfigs, configFile } = params;
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: customCodeTags2 ? new Set(customCodeTags2.map((t) => t.toLowerCase())) : void 0,
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 customCodeTags2;
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
- customCodeTags2 = parsed.tagNames;
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: customCodeTags2,
4342
+ customCodeTags,
4286
4343
  customCodeTagConfigs,
4287
4344
  configFile
4288
4345
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reteps/tree-sitter-htmlmustache",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "HTML with Mustache/Handlebars template syntax grammar for tree-sitter",
5
5
  "repository": {
6
6
  "type": "git",
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
- // printf("[S] serialized_tag_count: %d\n", serialized_tag_count);
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