@reteps/tree-sitter-htmlmustache 0.8.0 → 0.9.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/README.md +49 -33
- package/browser/out/browser/index.d.ts +43 -0
- package/browser/out/browser/index.d.ts.map +1 -0
- package/browser/out/browser/index.mjs +3612 -0
- package/browser/out/browser/index.mjs.map +7 -0
- package/browser/out/core/collectErrors.d.ts +36 -0
- package/browser/out/core/collectErrors.d.ts.map +1 -0
- package/browser/out/core/configSchema.d.ts +63 -0
- package/browser/out/core/configSchema.d.ts.map +1 -0
- package/browser/out/core/customCodeTags.d.ts +34 -0
- package/browser/out/core/customCodeTags.d.ts.map +1 -0
- package/browser/out/core/diagnostic.d.ts +24 -0
- package/browser/out/core/diagnostic.d.ts.map +1 -0
- package/browser/out/core/embeddedRegions.d.ts +12 -0
- package/browser/out/core/embeddedRegions.d.ts.map +1 -0
- package/browser/out/core/formatting/classifier.d.ts +68 -0
- package/browser/out/core/formatting/classifier.d.ts.map +1 -0
- package/browser/out/core/formatting/embedded.d.ts +19 -0
- package/browser/out/core/formatting/embedded.d.ts.map +1 -0
- package/browser/out/core/formatting/formatters.d.ts +85 -0
- package/browser/out/core/formatting/formatters.d.ts.map +1 -0
- package/browser/out/core/formatting/index.d.ts +44 -0
- package/browser/out/core/formatting/index.d.ts.map +1 -0
- package/browser/out/core/formatting/ir.d.ts +100 -0
- package/browser/out/core/formatting/ir.d.ts.map +1 -0
- package/browser/out/core/formatting/mergeOptions.d.ts +18 -0
- package/browser/out/core/formatting/mergeOptions.d.ts.map +1 -0
- package/browser/out/core/formatting/printer.d.ts +18 -0
- package/browser/out/core/formatting/printer.d.ts.map +1 -0
- package/browser/out/core/formatting/utils.d.ts +39 -0
- package/browser/out/core/formatting/utils.d.ts.map +1 -0
- package/browser/out/core/grammar.d.ts +3 -0
- package/browser/out/core/grammar.d.ts.map +1 -0
- package/browser/out/core/htmlBalanceChecker.d.ts +23 -0
- package/browser/out/core/htmlBalanceChecker.d.ts.map +1 -0
- package/browser/out/core/mustacheChecks.d.ts +24 -0
- package/browser/out/core/mustacheChecks.d.ts.map +1 -0
- package/browser/out/core/nodeHelpers.d.ts +54 -0
- package/browser/out/core/nodeHelpers.d.ts.map +1 -0
- package/browser/out/core/ruleMetadata.d.ts +12 -0
- package/browser/out/core/ruleMetadata.d.ts.map +1 -0
- package/browser/out/core/selectorMatcher.d.ts +74 -0
- package/browser/out/core/selectorMatcher.d.ts.map +1 -0
- package/cli/out/main.js +168 -122
- package/package.json +21 -3
- package/src/browser/browser.test.ts +207 -0
- package/src/browser/index.ts +128 -0
- package/src/browser/tsconfig.json +18 -0
- package/src/core/collectErrors.ts +233 -0
- package/src/core/configSchema.ts +273 -0
- package/src/core/customCodeTags.ts +159 -0
- package/src/core/diagnostic.ts +45 -0
- package/src/core/embeddedRegions.ts +70 -0
- package/src/core/formatting/classifier.ts +549 -0
- package/src/core/formatting/embedded.ts +56 -0
- package/src/core/formatting/formatters.ts +1272 -0
- package/src/core/formatting/index.ts +185 -0
- package/src/core/formatting/ir.ts +202 -0
- package/src/core/formatting/mergeOptions.ts +34 -0
- package/src/core/formatting/printer.ts +242 -0
- package/src/core/formatting/utils.ts +193 -0
- package/src/core/grammar.ts +2 -0
- package/src/core/htmlBalanceChecker.ts +382 -0
- package/src/core/mustacheChecks.ts +504 -0
- package/src/core/nodeHelpers.ts +126 -0
- package/src/core/ruleMetadata.ts +63 -0
- package/src/core/selectorMatcher.ts +719 -0
package/cli/out/main.js
CHANGED
|
@@ -525,11 +525,16 @@ var import_node_path = __toESM(require("node:path"));
|
|
|
525
525
|
// cli/src/wasm.ts
|
|
526
526
|
var path = __toESM(require("node:path"));
|
|
527
527
|
var import_web_tree_sitter = require("web-tree-sitter");
|
|
528
|
+
|
|
529
|
+
// src/core/grammar.ts
|
|
530
|
+
var GRAMMAR_WASM_FILENAME = "tree-sitter-htmlmustache.wasm";
|
|
531
|
+
|
|
532
|
+
// cli/src/wasm.ts
|
|
528
533
|
var parser;
|
|
529
534
|
async function initializeParser() {
|
|
530
535
|
await import_web_tree_sitter.Parser.init();
|
|
531
536
|
parser = new import_web_tree_sitter.Parser();
|
|
532
|
-
const wasmPath = path.resolve(__dirname, "..", "..",
|
|
537
|
+
const wasmPath = path.resolve(__dirname, "..", "..", GRAMMAR_WASM_FILENAME);
|
|
533
538
|
const language = await import_web_tree_sitter.Language.load(wasmPath);
|
|
534
539
|
parser.setLanguage(language);
|
|
535
540
|
}
|
|
@@ -545,7 +550,7 @@ function parseDocument(source) {
|
|
|
545
550
|
var fs = __toESM(require("fs"), 1);
|
|
546
551
|
var path2 = __toESM(require("path"), 1);
|
|
547
552
|
|
|
548
|
-
//
|
|
553
|
+
// src/core/ruleMetadata.ts
|
|
549
554
|
var RULES = [
|
|
550
555
|
{
|
|
551
556
|
name: "nestedDuplicateSections",
|
|
@@ -598,7 +603,7 @@ var RULE_DEFAULTS = Object.fromEntries(
|
|
|
598
603
|
RULES.map((r2) => [r2.name, r2.defaultSeverity])
|
|
599
604
|
);
|
|
600
605
|
|
|
601
|
-
//
|
|
606
|
+
// src/core/configSchema.ts
|
|
602
607
|
var VALID_CSS_DISPLAY_VALUES = /* @__PURE__ */ new Set([
|
|
603
608
|
"block",
|
|
604
609
|
"inline",
|
|
@@ -648,7 +653,6 @@ function parseRuleEntry(key, value) {
|
|
|
648
653
|
if (!options) return { severity };
|
|
649
654
|
return { severity, ...options };
|
|
650
655
|
}
|
|
651
|
-
var CONFIG_FILENAME = ".htmlmustache.jsonc";
|
|
652
656
|
function parseJsonc(text2) {
|
|
653
657
|
let result = "";
|
|
654
658
|
let i2 = 0;
|
|
@@ -687,21 +691,6 @@ function parseJsonc(text2) {
|
|
|
687
691
|
result = result.replace(/,\s*([}\]])/g, "$1");
|
|
688
692
|
return JSON.parse(result);
|
|
689
693
|
}
|
|
690
|
-
function findConfigFile(startDir) {
|
|
691
|
-
let dir = path2.resolve(startDir);
|
|
692
|
-
const root = path2.parse(dir).root;
|
|
693
|
-
while (true) {
|
|
694
|
-
const candidate = path2.join(dir, CONFIG_FILENAME);
|
|
695
|
-
try {
|
|
696
|
-
fs.accessSync(candidate, fs.constants.R_OK);
|
|
697
|
-
return candidate;
|
|
698
|
-
} catch {
|
|
699
|
-
}
|
|
700
|
-
const parent = path2.dirname(dir);
|
|
701
|
-
if (parent === dir || dir === root) return null;
|
|
702
|
-
dir = parent;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
694
|
var VALID_INDENT_MODES = /* @__PURE__ */ new Set(["never", "always", "attribute"]);
|
|
706
695
|
function parseCustomTagArray(arr) {
|
|
707
696
|
if (!Array.isArray(arr)) return [];
|
|
@@ -801,6 +790,24 @@ function validateConfig(raw) {
|
|
|
801
790
|
}
|
|
802
791
|
return config;
|
|
803
792
|
}
|
|
793
|
+
|
|
794
|
+
// lsp/server/src/configFile.ts
|
|
795
|
+
var CONFIG_FILENAME = ".htmlmustache.jsonc";
|
|
796
|
+
function findConfigFile(startDir) {
|
|
797
|
+
let dir = path2.resolve(startDir);
|
|
798
|
+
const root = path2.parse(dir).root;
|
|
799
|
+
while (true) {
|
|
800
|
+
const candidate = path2.join(dir, CONFIG_FILENAME);
|
|
801
|
+
try {
|
|
802
|
+
fs.accessSync(candidate, fs.constants.R_OK);
|
|
803
|
+
return candidate;
|
|
804
|
+
} catch {
|
|
805
|
+
}
|
|
806
|
+
const parent = path2.dirname(dir);
|
|
807
|
+
if (parent === dir || dir === root) return null;
|
|
808
|
+
dir = parent;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
804
811
|
function loadConfigFileForPath(filePath) {
|
|
805
812
|
const dir = path2.dirname(path2.resolve(filePath));
|
|
806
813
|
const configPath = findConfigFile(dir);
|
|
@@ -814,7 +821,7 @@ function loadConfigFileForPath(filePath) {
|
|
|
814
821
|
}
|
|
815
822
|
}
|
|
816
823
|
|
|
817
|
-
//
|
|
824
|
+
// src/core/nodeHelpers.ts
|
|
818
825
|
var MUSTACHE_SECTION_TYPES = /* @__PURE__ */ new Set([
|
|
819
826
|
"mustache_section",
|
|
820
827
|
"mustache_inverted_section"
|
|
@@ -878,7 +885,7 @@ function getPartialName(node) {
|
|
|
878
885
|
return child ? child.text.trim() : null;
|
|
879
886
|
}
|
|
880
887
|
|
|
881
|
-
//
|
|
888
|
+
// src/core/htmlBalanceChecker.ts
|
|
882
889
|
function getTagNameLower(element) {
|
|
883
890
|
return getTagName(element)?.toLowerCase() ?? null;
|
|
884
891
|
}
|
|
@@ -1175,7 +1182,7 @@ function checkHtmlBalance(rootNode) {
|
|
|
1175
1182
|
return allErrors;
|
|
1176
1183
|
}
|
|
1177
1184
|
|
|
1178
|
-
//
|
|
1185
|
+
// src/core/mustacheChecks.ts
|
|
1179
1186
|
function checkNestedSameNameSections(rootNode) {
|
|
1180
1187
|
const errors = [];
|
|
1181
1188
|
function visit(node, ancestors) {
|
|
@@ -1834,7 +1841,7 @@ function m(e2, { recursive: t2 = true, list: s2 = true } = {}) {
|
|
|
1834
1841
|
return c2;
|
|
1835
1842
|
}
|
|
1836
1843
|
|
|
1837
|
-
//
|
|
1844
|
+
// src/core/selectorMatcher.ts
|
|
1838
1845
|
var MUSTACHE_KIND_PSEUDO = /* @__PURE__ */ new Set([
|
|
1839
1846
|
"m-section",
|
|
1840
1847
|
"m-inverted",
|
|
@@ -1963,6 +1970,7 @@ function segmentFromCompound(ast) {
|
|
|
1963
1970
|
let kind;
|
|
1964
1971
|
let name = null;
|
|
1965
1972
|
let pathRegex;
|
|
1973
|
+
let rootOnly = false;
|
|
1966
1974
|
const attributes = [];
|
|
1967
1975
|
const descendantChecks = [];
|
|
1968
1976
|
const forbidChange = (requested) => {
|
|
@@ -2021,6 +2029,11 @@ function segmentFromCompound(ast) {
|
|
|
2021
2029
|
if (!applyNegatedSubtree(token.subtree, attributes, descendantChecks)) return null;
|
|
2022
2030
|
break;
|
|
2023
2031
|
}
|
|
2032
|
+
if (token.name === "root") {
|
|
2033
|
+
rootOnly = true;
|
|
2034
|
+
if (kind === void 0) kind = "html";
|
|
2035
|
+
break;
|
|
2036
|
+
}
|
|
2024
2037
|
return null;
|
|
2025
2038
|
}
|
|
2026
2039
|
default:
|
|
@@ -2030,9 +2043,12 @@ function segmentFromCompound(ast) {
|
|
|
2030
2043
|
if (kind === void 0) {
|
|
2031
2044
|
kind = "html";
|
|
2032
2045
|
}
|
|
2046
|
+
if (rootOnly) {
|
|
2047
|
+
if (name !== null || attributes.length > 0 || kind !== "html") return null;
|
|
2048
|
+
}
|
|
2033
2049
|
const isHtml = kind === "html";
|
|
2034
2050
|
const finalAttrs = isHtml ? attributes : [];
|
|
2035
|
-
return { kind, name, pathRegex, attributes: finalAttrs, descendantChecks, combinator: "descendant" };
|
|
2051
|
+
return { kind, rootOnly, name, pathRegex, attributes: finalAttrs, descendantChecks, combinator: "descendant" };
|
|
2036
2052
|
}
|
|
2037
2053
|
function mustacheKindFromMarker(name) {
|
|
2038
2054
|
switch (name) {
|
|
@@ -2227,7 +2243,11 @@ function matchesName(actual, segment) {
|
|
|
2227
2243
|
if (segment.pathRegex) return segment.pathRegex.test(actual);
|
|
2228
2244
|
return actual === segment.name;
|
|
2229
2245
|
}
|
|
2230
|
-
function nodeMatchesSegment(node, segment) {
|
|
2246
|
+
function nodeMatchesSegment(node, segment, rootNode) {
|
|
2247
|
+
if (segment.rootOnly) {
|
|
2248
|
+
if (node !== rootNode) return false;
|
|
2249
|
+
return checkDescendants(node, segment.descendantChecks);
|
|
2250
|
+
}
|
|
2231
2251
|
switch (segment.kind) {
|
|
2232
2252
|
case "html": {
|
|
2233
2253
|
if (!HTML_ELEMENT_TYPES.has(node.type)) return false;
|
|
@@ -2271,7 +2291,10 @@ function checkAncestors(ancestors, segments, segIdx, childCombinator) {
|
|
|
2271
2291
|
if (childCombinator === "child") {
|
|
2272
2292
|
for (let a2 = ancestors.length - 1; a2 >= 0; a2--) {
|
|
2273
2293
|
const entry = ancestors[a2];
|
|
2274
|
-
if (entry.kind !== ancestorKind)
|
|
2294
|
+
if (entry.kind !== ancestorKind) {
|
|
2295
|
+
if (ancestorKind === "root" && entry.kind === "html") return false;
|
|
2296
|
+
continue;
|
|
2297
|
+
}
|
|
2275
2298
|
if (!matchesName(entry.name, segment)) return false;
|
|
2276
2299
|
if (segment.kind === "html" && !checkAttributes(entry.node, segment.attributes)) return false;
|
|
2277
2300
|
if (!checkDescendants(entry.node, segment.descendantChecks)) return false;
|
|
@@ -2292,12 +2315,13 @@ function checkAncestors(ancestors, segments, segIdx, childCombinator) {
|
|
|
2292
2315
|
return false;
|
|
2293
2316
|
}
|
|
2294
2317
|
function ancestorKindForSegment(segment) {
|
|
2318
|
+
if (segment.rootOnly) return "root";
|
|
2295
2319
|
if (segment.kind === "html") return "html";
|
|
2296
2320
|
if (segment.kind === "section") return "section";
|
|
2297
2321
|
if (segment.kind === "inverted") return "inverted";
|
|
2298
2322
|
return null;
|
|
2299
2323
|
}
|
|
2300
|
-
function getReportNode(node) {
|
|
2324
|
+
function getReportNode(node, rootNode) {
|
|
2301
2325
|
if (HTML_ELEMENT_TYPES.has(node.type)) {
|
|
2302
2326
|
const startTag = node.children.find(
|
|
2303
2327
|
(c2) => c2.type === "html_start_tag" || c2.type === "html_self_closing_tag"
|
|
@@ -2310,15 +2334,26 @@ function getReportNode(node) {
|
|
|
2310
2334
|
);
|
|
2311
2335
|
return begin ?? node;
|
|
2312
2336
|
}
|
|
2337
|
+
if (rootNode && node === rootNode) {
|
|
2338
|
+
return {
|
|
2339
|
+
type: node.type,
|
|
2340
|
+
text: "",
|
|
2341
|
+
startPosition: node.startPosition,
|
|
2342
|
+
endPosition: { row: node.startPosition.row, column: node.startPosition.column + 1 },
|
|
2343
|
+
startIndex: node.startIndex,
|
|
2344
|
+
endIndex: Math.min(node.startIndex + 1, node.endIndex),
|
|
2345
|
+
children: []
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2313
2348
|
return node;
|
|
2314
2349
|
}
|
|
2315
2350
|
function matchAlternative(rootNode, segments) {
|
|
2316
2351
|
const results = [];
|
|
2317
2352
|
const lastSegment = segments[segments.length - 1];
|
|
2318
2353
|
function walk(node, ancestors) {
|
|
2319
|
-
if (nodeMatchesSegment(node, lastSegment)) {
|
|
2354
|
+
if (nodeMatchesSegment(node, lastSegment, rootNode)) {
|
|
2320
2355
|
if (segments.length === 1 || checkAncestors(ancestors, segments, segments.length - 2, lastSegment.combinator)) {
|
|
2321
|
-
results.push(getReportNode(node));
|
|
2356
|
+
results.push(getReportNode(node, rootNode));
|
|
2322
2357
|
}
|
|
2323
2358
|
}
|
|
2324
2359
|
let newAncestors = ancestors;
|
|
@@ -2331,7 +2366,7 @@ function matchAlternative(rootNode, segments) {
|
|
|
2331
2366
|
}
|
|
2332
2367
|
for (const child of node.children) walk(child, newAncestors);
|
|
2333
2368
|
}
|
|
2334
|
-
walk(rootNode, []);
|
|
2369
|
+
walk(rootNode, [{ kind: "root", name: "", node: rootNode }]);
|
|
2335
2370
|
return results;
|
|
2336
2371
|
}
|
|
2337
2372
|
function matchSelector(rootNode, selector) {
|
|
@@ -2348,7 +2383,15 @@ function matchSelector(rootNode, selector) {
|
|
|
2348
2383
|
return allResults;
|
|
2349
2384
|
}
|
|
2350
2385
|
|
|
2351
|
-
//
|
|
2386
|
+
// src/core/collectErrors.ts
|
|
2387
|
+
var selectorCache = /* @__PURE__ */ new Map();
|
|
2388
|
+
function parseSelectorCached(raw) {
|
|
2389
|
+
const hit = selectorCache.get(raw);
|
|
2390
|
+
if (hit !== void 0) return hit;
|
|
2391
|
+
const parsed = parseSelector(raw);
|
|
2392
|
+
selectorCache.set(raw, parsed);
|
|
2393
|
+
return parsed;
|
|
2394
|
+
}
|
|
2352
2395
|
var ERROR_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
2353
2396
|
"ERROR",
|
|
2354
2397
|
"mustache_erroneous_section_end",
|
|
@@ -2479,7 +2522,7 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
2479
2522
|
if (disabledRules.has(rule.id)) continue;
|
|
2480
2523
|
const severity = rule.severity ?? "error";
|
|
2481
2524
|
if (severity === "off") continue;
|
|
2482
|
-
const parsed =
|
|
2525
|
+
const parsed = parseSelectorCached(rule.selector);
|
|
2483
2526
|
if (!parsed) continue;
|
|
2484
2527
|
const matches = matchSelector(tree.rootNode, parsed);
|
|
2485
2528
|
for (const node of matches) {
|
|
@@ -2492,20 +2535,32 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
2492
2535
|
);
|
|
2493
2536
|
}
|
|
2494
2537
|
|
|
2538
|
+
// src/core/diagnostic.ts
|
|
2539
|
+
function toFix(r2) {
|
|
2540
|
+
return { range: [r2.startIndex, r2.endIndex], newText: r2.newText };
|
|
2541
|
+
}
|
|
2542
|
+
function toDiagnostic(err) {
|
|
2543
|
+
const { node } = err;
|
|
2544
|
+
return {
|
|
2545
|
+
line: node.startPosition.row + 1,
|
|
2546
|
+
column: node.startPosition.column + 1,
|
|
2547
|
+
endLine: node.endPosition.row + 1,
|
|
2548
|
+
endColumn: node.endPosition.column + 1,
|
|
2549
|
+
message: err.message,
|
|
2550
|
+
severity: err.severity ?? "error",
|
|
2551
|
+
ruleName: err.ruleName,
|
|
2552
|
+
fix: err.fix && err.fix.length > 0 ? err.fix.map(toFix) : void 0,
|
|
2553
|
+
fixDescription: err.fixDescription
|
|
2554
|
+
};
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2495
2557
|
// cli/src/check.ts
|
|
2496
2558
|
function collectErrors2(tree, file, rules, customTagNames, customRules) {
|
|
2497
2559
|
const errors = collectErrors(tree, rules, customTagNames, customRules);
|
|
2498
2560
|
return errors.map((error) => ({
|
|
2499
2561
|
file,
|
|
2500
|
-
line: error.node.startPosition.row + 1,
|
|
2501
|
-
column: error.node.startPosition.column + 1,
|
|
2502
|
-
endLine: error.node.endPosition.row + 1,
|
|
2503
|
-
endColumn: error.node.endPosition.column + 1,
|
|
2504
|
-
message: error.message,
|
|
2505
2562
|
nodeText: error.node.text,
|
|
2506
|
-
|
|
2507
|
-
fix: error.fix,
|
|
2508
|
-
fixDescription: error.fixDescription
|
|
2563
|
+
...toDiagnostic(error)
|
|
2509
2564
|
}));
|
|
2510
2565
|
}
|
|
2511
2566
|
function formatError(error, source) {
|
|
@@ -2617,8 +2672,9 @@ function resolveFiles(cliPatterns) {
|
|
|
2617
2672
|
function applyFixes(source, errors) {
|
|
2618
2673
|
const replacements = [];
|
|
2619
2674
|
for (const error of errors) {
|
|
2620
|
-
if (error.fix)
|
|
2621
|
-
|
|
2675
|
+
if (!error.fix) continue;
|
|
2676
|
+
for (const edit of error.fix) {
|
|
2677
|
+
replacements.push({ startIndex: edit.range[0], endIndex: edit.range[1], newText: edit.newText });
|
|
2622
2678
|
}
|
|
2623
2679
|
}
|
|
2624
2680
|
if (replacements.length === 0) return source;
|
|
@@ -2946,7 +3002,7 @@ function getWellformedEdit(textEdit) {
|
|
|
2946
3002
|
return textEdit;
|
|
2947
3003
|
}
|
|
2948
3004
|
|
|
2949
|
-
//
|
|
3005
|
+
// src/core/formatting/printer.ts
|
|
2950
3006
|
function print(doc, options) {
|
|
2951
3007
|
const output = [];
|
|
2952
3008
|
const state = { indentLevel: 0, mode: "break", groupModes: /* @__PURE__ */ new Map() };
|
|
@@ -3096,7 +3152,7 @@ function makeIndent(level, options) {
|
|
|
3096
3152
|
return options.indentUnit.repeat(level);
|
|
3097
3153
|
}
|
|
3098
3154
|
|
|
3099
|
-
//
|
|
3155
|
+
// src/core/formatting/ir.ts
|
|
3100
3156
|
var hardline = { type: "hardline" };
|
|
3101
3157
|
var softline = { type: "softline" };
|
|
3102
3158
|
var line = { type: "line" };
|
|
@@ -3148,7 +3204,7 @@ function isLine(doc) {
|
|
|
3148
3204
|
return typeof doc === "object" && doc.type === "line";
|
|
3149
3205
|
}
|
|
3150
3206
|
|
|
3151
|
-
//
|
|
3207
|
+
// src/core/formatting/utils.ts
|
|
3152
3208
|
function normalizeText(text2) {
|
|
3153
3209
|
return text2.split("\n").map((line2) => line2.replace(/[ \t]+/g, " ").trim()).filter((line2, i2, arr) => line2 || i2 > 0 && i2 < arr.length - 1).join("\n");
|
|
3154
3210
|
}
|
|
@@ -3224,7 +3280,7 @@ function getIgnoreDirective(node) {
|
|
|
3224
3280
|
return null;
|
|
3225
3281
|
}
|
|
3226
3282
|
|
|
3227
|
-
//
|
|
3283
|
+
// src/core/customCodeTags.ts
|
|
3228
3284
|
function isCodeTag(config) {
|
|
3229
3285
|
return !!(config.languageAttribute || config.languageDefault);
|
|
3230
3286
|
}
|
|
@@ -3253,7 +3309,7 @@ function getAttributeValue(node, attrName) {
|
|
|
3253
3309
|
return null;
|
|
3254
3310
|
}
|
|
3255
3311
|
|
|
3256
|
-
//
|
|
3312
|
+
// src/core/formatting/classifier.ts
|
|
3257
3313
|
var EMPTY_MAP = /* @__PURE__ */ new Map();
|
|
3258
3314
|
var CSS_DISPLAY_MAP = {
|
|
3259
3315
|
// Block elements
|
|
@@ -3555,7 +3611,7 @@ function shouldTreatAsBlock(node, index, nodes, customTags = EMPTY_MAP) {
|
|
|
3555
3611
|
return isHtmlEl && !shouldHtmlElementStayInline(node, index, nodes, customTags) || isMustacheSec && !isInTextFlow(node, index, nodes) || isBlockLevel(node, customTags) && !isInTextFlow(node, index, nodes);
|
|
3556
3612
|
}
|
|
3557
3613
|
|
|
3558
|
-
//
|
|
3614
|
+
// src/core/formatting/formatters.ts
|
|
3559
3615
|
function isAttributeTruthy(value) {
|
|
3560
3616
|
if (value === null || value === "" || value === "false" || value === "0") {
|
|
3561
3617
|
return false;
|
|
@@ -4447,46 +4503,12 @@ function trimDoc(doc) {
|
|
|
4447
4503
|
return doc;
|
|
4448
4504
|
}
|
|
4449
4505
|
|
|
4450
|
-
//
|
|
4451
|
-
var import_editorconfig = require("editorconfig");
|
|
4452
|
-
var import_url = require("url");
|
|
4453
|
-
function getEditorConfigOptions(uri) {
|
|
4454
|
-
try {
|
|
4455
|
-
if (!uri.startsWith("file://")) {
|
|
4456
|
-
return {};
|
|
4457
|
-
}
|
|
4458
|
-
const filePath = (0, import_url.fileURLToPath)(uri);
|
|
4459
|
-
const config = (0, import_editorconfig.parseSync)(filePath);
|
|
4460
|
-
const result = {};
|
|
4461
|
-
if (config.indent_style === "space") {
|
|
4462
|
-
result.insertSpaces = true;
|
|
4463
|
-
} else if (config.indent_style === "tab") {
|
|
4464
|
-
result.insertSpaces = false;
|
|
4465
|
-
}
|
|
4466
|
-
if (typeof config.indent_size === "number") {
|
|
4467
|
-
result.tabSize = config.indent_size;
|
|
4468
|
-
} else if (config.indent_size === "tab" && typeof config.tab_width === "number") {
|
|
4469
|
-
result.tabSize = config.tab_width;
|
|
4470
|
-
}
|
|
4471
|
-
return result;
|
|
4472
|
-
} catch {
|
|
4473
|
-
return {};
|
|
4474
|
-
}
|
|
4475
|
-
}
|
|
4476
|
-
function mergeOptions(lspOptions, uri, configFile) {
|
|
4477
|
-
let tabSize = lspOptions.tabSize;
|
|
4478
|
-
let insertSpaces = lspOptions.insertSpaces;
|
|
4479
|
-
if (configFile?.indentSize !== void 0) tabSize = configFile.indentSize;
|
|
4480
|
-
const ec = getEditorConfigOptions(uri);
|
|
4481
|
-
if (ec.tabSize !== void 0) tabSize = ec.tabSize;
|
|
4482
|
-
if (ec.insertSpaces !== void 0) insertSpaces = ec.insertSpaces;
|
|
4483
|
-
return { tabSize, insertSpaces };
|
|
4484
|
-
}
|
|
4506
|
+
// src/core/formatting/mergeOptions.ts
|
|
4485
4507
|
function createIndentUnit(options) {
|
|
4486
4508
|
return options.insertSpaces ? " ".repeat(options.tabSize) : " ";
|
|
4487
4509
|
}
|
|
4488
4510
|
|
|
4489
|
-
//
|
|
4511
|
+
// src/core/formatting/index.ts
|
|
4490
4512
|
function buildCustomTagMap(customTags) {
|
|
4491
4513
|
if (!customTags || customTags.length === 0) return void 0;
|
|
4492
4514
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -4496,12 +4518,9 @@ function buildCustomTagMap(customTags) {
|
|
|
4496
4518
|
return map;
|
|
4497
4519
|
}
|
|
4498
4520
|
function formatDocument2(tree, document, options, params = {}) {
|
|
4499
|
-
const { printWidth = 80, embeddedFormatted, mustacheSpaces, noBreakDelimiters
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
if (tree.rootNode.hasError) {
|
|
4503
|
-
return [];
|
|
4504
|
-
}
|
|
4521
|
+
const { printWidth = 80, embeddedFormatted, mustacheSpaces, noBreakDelimiters } = params;
|
|
4522
|
+
const indentUnit = createIndentUnit(options);
|
|
4523
|
+
if (tree.rootNode.hasError) return [];
|
|
4505
4524
|
const customTagMap = buildCustomTagMap(params.customTags);
|
|
4506
4525
|
const context = {
|
|
4507
4526
|
document,
|
|
@@ -4519,7 +4538,7 @@ function formatDocument2(tree, document, options, params = {}) {
|
|
|
4519
4538
|
return [{ range: fullRange, newText: formatted }];
|
|
4520
4539
|
}
|
|
4521
4540
|
|
|
4522
|
-
//
|
|
4541
|
+
// src/core/embeddedRegions.ts
|
|
4523
4542
|
function getEmbeddedLanguageId(node) {
|
|
4524
4543
|
if (node.type === "html_style_element") {
|
|
4525
4544
|
return "css";
|
|
@@ -4572,6 +4591,62 @@ function collectEmbeddedRegions(rootNode) {
|
|
|
4572
4591
|
return regions;
|
|
4573
4592
|
}
|
|
4574
4593
|
|
|
4594
|
+
// src/core/formatting/embedded.ts
|
|
4595
|
+
var LANGUAGE_TO_PRETTIER_PARSER = {
|
|
4596
|
+
javascript: "babel",
|
|
4597
|
+
typescript: "typescript",
|
|
4598
|
+
css: "css"
|
|
4599
|
+
};
|
|
4600
|
+
async function formatEmbeddedRegions(rootNode, options, prettier) {
|
|
4601
|
+
const result = /* @__PURE__ */ new Map();
|
|
4602
|
+
if (!prettier) return result;
|
|
4603
|
+
const regions = collectEmbeddedRegions(rootNode);
|
|
4604
|
+
if (regions.length === 0) return result;
|
|
4605
|
+
await Promise.all(
|
|
4606
|
+
regions.map(async (region) => {
|
|
4607
|
+
const parser2 = LANGUAGE_TO_PRETTIER_PARSER[region.languageId];
|
|
4608
|
+
if (!parser2) return;
|
|
4609
|
+
try {
|
|
4610
|
+
const formatted = await prettier.format(region.content, {
|
|
4611
|
+
parser: parser2,
|
|
4612
|
+
tabWidth: options.tabSize,
|
|
4613
|
+
useTabs: !options.insertSpaces
|
|
4614
|
+
});
|
|
4615
|
+
result.set(region.startIndex, formatted);
|
|
4616
|
+
} catch {
|
|
4617
|
+
}
|
|
4618
|
+
})
|
|
4619
|
+
);
|
|
4620
|
+
return result;
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4623
|
+
// lsp/server/src/formatting/editorconfig.ts
|
|
4624
|
+
var import_editorconfig = require("editorconfig");
|
|
4625
|
+
var import_url = require("url");
|
|
4626
|
+
function getEditorConfigOptions(uri) {
|
|
4627
|
+
try {
|
|
4628
|
+
if (!uri.startsWith("file://")) {
|
|
4629
|
+
return {};
|
|
4630
|
+
}
|
|
4631
|
+
const filePath = (0, import_url.fileURLToPath)(uri);
|
|
4632
|
+
const config = (0, import_editorconfig.parseSync)(filePath);
|
|
4633
|
+
const result = {};
|
|
4634
|
+
if (config.indent_style === "space") {
|
|
4635
|
+
result.insertSpaces = true;
|
|
4636
|
+
} else if (config.indent_style === "tab") {
|
|
4637
|
+
result.insertSpaces = false;
|
|
4638
|
+
}
|
|
4639
|
+
if (typeof config.indent_size === "number") {
|
|
4640
|
+
result.tabSize = config.indent_size;
|
|
4641
|
+
} else if (config.indent_size === "tab" && typeof config.tab_width === "number") {
|
|
4642
|
+
result.tabSize = config.tab_width;
|
|
4643
|
+
}
|
|
4644
|
+
return result;
|
|
4645
|
+
} catch {
|
|
4646
|
+
return {};
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
|
|
4575
4650
|
// cli/src/format.ts
|
|
4576
4651
|
var USAGE2 = `Usage: htmlmustache format [options] [patterns...]
|
|
4577
4652
|
|
|
@@ -4675,15 +4750,9 @@ function resolveSettings(flags, filePath) {
|
|
|
4675
4750
|
printWidth,
|
|
4676
4751
|
mustacheSpaces,
|
|
4677
4752
|
noBreakDelimiters,
|
|
4678
|
-
customTags
|
|
4679
|
-
configFile
|
|
4753
|
+
customTags
|
|
4680
4754
|
};
|
|
4681
4755
|
}
|
|
4682
|
-
var LANGUAGE_TO_PRETTIER_PARSER = {
|
|
4683
|
-
javascript: "babel",
|
|
4684
|
-
typescript: "typescript",
|
|
4685
|
-
css: "css"
|
|
4686
|
-
};
|
|
4687
4756
|
var prettierModule;
|
|
4688
4757
|
async function getPrettier() {
|
|
4689
4758
|
if (prettierModule !== void 0) return prettierModule;
|
|
@@ -4695,32 +4764,9 @@ async function getPrettier() {
|
|
|
4695
4764
|
return null;
|
|
4696
4765
|
}
|
|
4697
4766
|
}
|
|
4698
|
-
async function formatEmbeddedRegions(tree, options) {
|
|
4699
|
-
const result = /* @__PURE__ */ new Map();
|
|
4700
|
-
const prettier = await getPrettier();
|
|
4701
|
-
if (!prettier) return result;
|
|
4702
|
-
const regions = collectEmbeddedRegions(tree.rootNode);
|
|
4703
|
-
if (regions.length === 0) return result;
|
|
4704
|
-
await Promise.all(
|
|
4705
|
-
regions.map(async (region) => {
|
|
4706
|
-
const parser2 = LANGUAGE_TO_PRETTIER_PARSER[region.languageId];
|
|
4707
|
-
if (!parser2) return;
|
|
4708
|
-
try {
|
|
4709
|
-
const formatted = await prettier.format(region.content, {
|
|
4710
|
-
parser: parser2,
|
|
4711
|
-
tabWidth: options.tabSize,
|
|
4712
|
-
useTabs: !options.insertSpaces
|
|
4713
|
-
});
|
|
4714
|
-
result.set(region.startIndex, formatted);
|
|
4715
|
-
} catch {
|
|
4716
|
-
}
|
|
4717
|
-
})
|
|
4718
|
-
);
|
|
4719
|
-
return result;
|
|
4720
|
-
}
|
|
4721
4767
|
async function formatSource(source, options, params = {}) {
|
|
4722
4768
|
const tree = parseDocument(source);
|
|
4723
|
-
const embeddedFormatted = await formatEmbeddedRegions(tree, options);
|
|
4769
|
+
const embeddedFormatted = await formatEmbeddedRegions(tree.rootNode, options, await getPrettier());
|
|
4724
4770
|
const document = TextDocument.create("file:///stdin", "htmlmustache", 1, source);
|
|
4725
4771
|
const edits = formatDocument2(tree, document, options, {
|
|
4726
4772
|
...params,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reteps/tree-sitter-htmlmustache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "HTML with Mustache/Handlebars template syntax grammar for tree-sitter",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
"htmlmustache": "cli/out/main.js"
|
|
16
16
|
},
|
|
17
17
|
"types": "bindings/node",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./bindings/node/index.d.ts",
|
|
21
|
+
"default": "./bindings/node/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./browser": {
|
|
24
|
+
"types": "./browser/out/browser/index.d.ts",
|
|
25
|
+
"import": "./browser/out/browser/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./tree-sitter-htmlmustache.wasm": "./tree-sitter-htmlmustache.wasm",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
18
30
|
"keywords": [
|
|
19
31
|
"incremental",
|
|
20
32
|
"parsing",
|
|
@@ -32,7 +44,8 @@
|
|
|
32
44
|
"queries/*",
|
|
33
45
|
"src/**",
|
|
34
46
|
"*.wasm",
|
|
35
|
-
"cli/out/*"
|
|
47
|
+
"cli/out/*",
|
|
48
|
+
"browser/out/**"
|
|
36
49
|
],
|
|
37
50
|
"dependencies": {
|
|
38
51
|
"chalk": "^5.6.2",
|
|
@@ -43,6 +56,7 @@
|
|
|
43
56
|
"peerDependencies": {
|
|
44
57
|
"node-addon-api": "^8.2.2",
|
|
45
58
|
"node-gyp-build": "^4.8.2",
|
|
59
|
+
"prettier": "^3.0.0",
|
|
46
60
|
"tree-sitter": "^0.25.0"
|
|
47
61
|
},
|
|
48
62
|
"peerDependenciesMeta": {
|
|
@@ -52,6 +66,9 @@
|
|
|
52
66
|
"node-gyp-build": {
|
|
53
67
|
"optional": true
|
|
54
68
|
},
|
|
69
|
+
"prettier": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
55
72
|
"tree-sitter": {
|
|
56
73
|
"optional": true
|
|
57
74
|
}
|
|
@@ -81,8 +98,9 @@
|
|
|
81
98
|
"scripts": {
|
|
82
99
|
"install": "node-gyp-build || exit 0",
|
|
83
100
|
"build": "tree-sitter build --wasm",
|
|
84
|
-
"prepack": "tree-sitter build --wasm && node cli/esbuild.mjs",
|
|
101
|
+
"prepack": "tree-sitter build --wasm && node cli/esbuild.mjs && node browser/esbuild.mjs && tsc -p src/browser/tsconfig.json",
|
|
85
102
|
"build:cli": "node cli/esbuild.mjs",
|
|
103
|
+
"build:browser": "node browser/esbuild.mjs && tsc -p src/browser/tsconfig.json",
|
|
86
104
|
"check": "node cli/out/check.js check",
|
|
87
105
|
"lint": "eslint .",
|
|
88
106
|
"format": "prettier --write .",
|