@reteps/tree-sitter-htmlmustache 0.7.1 → 0.7.3
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 +100 -4
- package/package.json +1 -1
- package/src/parser.c +2 -2
- package/src/scanner.c +11 -0
- package/tree-sitter-htmlmustache.wasm +0 -0
package/cli/out/main.js
CHANGED
|
@@ -4030,6 +4030,59 @@ function formatDocument2(tree, document, options, params = {}) {
|
|
|
4030
4030
|
return [{ range: fullRange, newText: formatted }];
|
|
4031
4031
|
}
|
|
4032
4032
|
|
|
4033
|
+
// lsp/server/src/embeddedRegions.ts
|
|
4034
|
+
function getEmbeddedLanguageId(node) {
|
|
4035
|
+
if (node.type === "html_style_element") {
|
|
4036
|
+
return "css";
|
|
4037
|
+
}
|
|
4038
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
4039
|
+
const child = node.child(i);
|
|
4040
|
+
if (child?.type === "html_start_tag") {
|
|
4041
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
4042
|
+
const attr = child.child(j);
|
|
4043
|
+
if (attr?.type === "html_attribute") {
|
|
4044
|
+
let name = "";
|
|
4045
|
+
let value = "";
|
|
4046
|
+
for (let k = 0; k < attr.childCount; k++) {
|
|
4047
|
+
const part = attr.child(k);
|
|
4048
|
+
if (part?.type === "html_attribute_name") name = part.text.toLowerCase();
|
|
4049
|
+
if (part?.type === "html_quoted_attribute_value") value = part.text.replace(/^["']|["']$/g, "").toLowerCase();
|
|
4050
|
+
if (part?.type === "html_attribute_value") value = part.text.toLowerCase();
|
|
4051
|
+
}
|
|
4052
|
+
if (name === "type" && (value === "text/typescript" || value === "ts")) {
|
|
4053
|
+
return "typescript";
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
return "javascript";
|
|
4060
|
+
}
|
|
4061
|
+
function collectEmbeddedRegions(rootNode) {
|
|
4062
|
+
const regions = [];
|
|
4063
|
+
const walk = (node) => {
|
|
4064
|
+
if (node.type === "html_script_element" || node.type === "html_style_element") {
|
|
4065
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
4066
|
+
const child = node.child(i);
|
|
4067
|
+
if (child?.type === "html_raw_text") {
|
|
4068
|
+
regions.push({
|
|
4069
|
+
startIndex: child.startIndex,
|
|
4070
|
+
content: child.text,
|
|
4071
|
+
languageId: getEmbeddedLanguageId(node)
|
|
4072
|
+
});
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
return;
|
|
4076
|
+
}
|
|
4077
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
4078
|
+
const child = node.child(i);
|
|
4079
|
+
if (child) walk(child);
|
|
4080
|
+
}
|
|
4081
|
+
};
|
|
4082
|
+
walk(rootNode);
|
|
4083
|
+
return regions;
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4033
4086
|
// cli/src/format.ts
|
|
4034
4087
|
var USAGE2 = `Usage: htmlmustache format [options] [patterns...]
|
|
4035
4088
|
|
|
@@ -4137,10 +4190,53 @@ function resolveSettings(flags, filePath) {
|
|
|
4137
4190
|
configFile
|
|
4138
4191
|
};
|
|
4139
4192
|
}
|
|
4140
|
-
|
|
4193
|
+
var LANGUAGE_TO_PRETTIER_PARSER = {
|
|
4194
|
+
javascript: "babel",
|
|
4195
|
+
typescript: "typescript",
|
|
4196
|
+
css: "css"
|
|
4197
|
+
};
|
|
4198
|
+
var prettierModule;
|
|
4199
|
+
async function getPrettier() {
|
|
4200
|
+
if (prettierModule !== void 0) return prettierModule;
|
|
4201
|
+
try {
|
|
4202
|
+
prettierModule = await import("prettier");
|
|
4203
|
+
return prettierModule;
|
|
4204
|
+
} catch {
|
|
4205
|
+
prettierModule = null;
|
|
4206
|
+
return null;
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
async function formatEmbeddedRegions(tree, options) {
|
|
4210
|
+
const result = /* @__PURE__ */ new Map();
|
|
4211
|
+
const prettier = await getPrettier();
|
|
4212
|
+
if (!prettier) return result;
|
|
4213
|
+
const regions = collectEmbeddedRegions(tree.rootNode);
|
|
4214
|
+
if (regions.length === 0) return result;
|
|
4215
|
+
await Promise.all(
|
|
4216
|
+
regions.map(async (region) => {
|
|
4217
|
+
const parser2 = LANGUAGE_TO_PRETTIER_PARSER[region.languageId];
|
|
4218
|
+
if (!parser2) return;
|
|
4219
|
+
try {
|
|
4220
|
+
const formatted = await prettier.format(region.content, {
|
|
4221
|
+
parser: parser2,
|
|
4222
|
+
tabWidth: options.tabSize,
|
|
4223
|
+
useTabs: !options.insertSpaces
|
|
4224
|
+
});
|
|
4225
|
+
result.set(region.startIndex, formatted);
|
|
4226
|
+
} catch {
|
|
4227
|
+
}
|
|
4228
|
+
})
|
|
4229
|
+
);
|
|
4230
|
+
return result;
|
|
4231
|
+
}
|
|
4232
|
+
async function formatSource(source, options, params = {}) {
|
|
4141
4233
|
const tree = parseDocument(source);
|
|
4234
|
+
const embeddedFormatted = await formatEmbeddedRegions(tree, options);
|
|
4142
4235
|
const document = TextDocument.create("file:///stdin", "htmlmustache", 1, source);
|
|
4143
|
-
const edits = formatDocument2(tree, document, options,
|
|
4236
|
+
const edits = formatDocument2(tree, document, options, {
|
|
4237
|
+
...params,
|
|
4238
|
+
embeddedFormatted: embeddedFormatted.size > 0 ? embeddedFormatted : void 0
|
|
4239
|
+
});
|
|
4144
4240
|
if (edits.length === 0) return source;
|
|
4145
4241
|
return edits[0].newText;
|
|
4146
4242
|
}
|
|
@@ -4157,7 +4253,7 @@ async function run2(args) {
|
|
|
4157
4253
|
await initializeParser();
|
|
4158
4254
|
const { options, ...params } = resolveSettings(flags);
|
|
4159
4255
|
const source = import_node_fs2.default.readFileSync(0, "utf-8");
|
|
4160
|
-
const formatted = formatSource(source, options, params);
|
|
4256
|
+
const formatted = await formatSource(source, options, params);
|
|
4161
4257
|
process.stdout.write(formatted);
|
|
4162
4258
|
return 0;
|
|
4163
4259
|
}
|
|
@@ -4181,7 +4277,7 @@ async function run2(args) {
|
|
|
4181
4277
|
const displayPath = import_node_path2.default.relative(cwd, file) || file;
|
|
4182
4278
|
const source = import_node_fs2.default.readFileSync(file, "utf-8");
|
|
4183
4279
|
const { options, ...params } = resolveSettings(flags, file);
|
|
4184
|
-
const formatted = formatSource(source, options, params);
|
|
4280
|
+
const formatted = await formatSource(source, options, params);
|
|
4185
4281
|
const changed = formatted !== source;
|
|
4186
4282
|
if (changed) changedCount++;
|
|
4187
4283
|
if (flags.check) {
|
package/package.json
CHANGED
package/src/parser.c
CHANGED
|
@@ -10874,8 +10874,8 @@ TS_PUBLIC const TSLanguage *tree_sitter_htmlmustache(void) {
|
|
|
10874
10874
|
.max_reserved_word_set_size = 0,
|
|
10875
10875
|
.metadata = {
|
|
10876
10876
|
.major_version = 0,
|
|
10877
|
-
.minor_version =
|
|
10878
|
-
.patch_version =
|
|
10877
|
+
.minor_version = 4,
|
|
10878
|
+
.patch_version = 1,
|
|
10879
10879
|
},
|
|
10880
10880
|
};
|
|
10881
10881
|
return &language;
|
package/src/scanner.c
CHANGED
|
@@ -386,6 +386,17 @@ static bool scan_end_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
386
386
|
|
|
387
387
|
Tag tag = tag_for_name(tag_name);
|
|
388
388
|
if (scanner->tags.size > 0 && tag_eq(array_back(&scanner->tags), &tag)) {
|
|
389
|
+
// Don't close HTML tags that were opened before the current mustache section.
|
|
390
|
+
// This prevents e.g. </div> inside {{#section}}...{{/section}} from closing
|
|
391
|
+
// an outer <div> that was opened before the section started.
|
|
392
|
+
if (scanner->mustache_tags.size > 0) {
|
|
393
|
+
MustacheTag *current_mustache_tag = array_back(&scanner->mustache_tags);
|
|
394
|
+
if (scanner->tags.size <= current_mustache_tag->html_tag_stack_size) {
|
|
395
|
+
lexer->result_symbol = HTML_ERRONEOUS_END_TAG_NAME;
|
|
396
|
+
tag_free(&tag);
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
389
400
|
pop_html_tag(scanner);
|
|
390
401
|
lexer->result_symbol = HTML_END_TAG_NAME;
|
|
391
402
|
} else {
|
|
Binary file
|