@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 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
- function formatSource(source, options, params = {}) {
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, params);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reteps/tree-sitter-htmlmustache",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "HTML with Mustache/Handlebars template syntax grammar for tree-sitter",
5
5
  "repository": {
6
6
  "type": "git",
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 = 0,
10878
- .patch_version = 2,
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