@willbooster/tree-sitter-markdown 0.0.0-placeholder.0 → 1.0.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.
@@ -0,0 +1,474 @@
1
+ // This grammar only concerns the inline structure according to the CommonMark Spec
2
+ // (https://spec.commonmark.org/0.30/#inlines)
3
+ // For more information see README.md
4
+
5
+ /// <reference types="tree-sitter-cli/dsl" />
6
+
7
+ const common = require('../common/common');
8
+
9
+ // Levels used for dynmic precedence. Ideally
10
+ // n * PRECEDENCE_LEVEL_EMPHASIS > PRECEDENCE_LEVEL_LINK for any n, so maybe the
11
+ // maginuted of these values should be increased in the future
12
+ const PRECEDENCE_LEVEL_EMPHASIS = 1;
13
+ const PRECEDENCE_LEVEL_LINK = 10;
14
+ const PRECEDENCE_LEVEL_HTML = 100;
15
+
16
+ // Punctuation characters as specified in
17
+ // https://github.github.com/gfm/#ascii-punctuation-character
18
+ const PUNCTUATION_CHARACTERS_REGEX = '!-/:-@\\[-`\\{-~';
19
+
20
+
21
+ // !!!
22
+ // Notice the call to `add_inline_rules` which generates some additional rules related to parsing
23
+ // inline contents in different contexts.
24
+ // !!!
25
+ module.exports = grammar(add_inline_rules({
26
+ name: 'markdown_inline',
27
+
28
+ externals: $ => [
29
+ // An `$._error` token is never valid and gets emmited to kill invalid parse branches. Concretely
30
+ // this is used to decide wether a newline closes a paragraph and together and it gets emitted
31
+ // when trying to parse the `$._trigger_error` token in `$.link_title`.
32
+ $._error,
33
+ $._trigger_error,
34
+
35
+ // Opening and closing delimiters for code spans. These are sequences of one or more backticks.
36
+ // An opening token does not mean the text after has to be a code span if there is no closing token
37
+ $._code_span_start,
38
+ $._code_span_close,
39
+
40
+ // Opening and closing delimiters for emphasis.
41
+ $._emphasis_open_star,
42
+ $._emphasis_open_underscore,
43
+ $._emphasis_close_star,
44
+ $._emphasis_close_underscore,
45
+
46
+ // For emphasis we need to tell the parser if the last character was a whitespace (or the
47
+ // beginning of a line) or a punctuation. These tokens never actually get emitted.
48
+ $._last_token_whitespace,
49
+ $._last_token_punctuation,
50
+
51
+ $._strikethrough_open,
52
+ $._strikethrough_close,
53
+
54
+ // Opening and closing delimiters for latex. These are sequences of one or more dollar signs.
55
+ // An opening token does not mean the text after has to be latex if there is no closing token
56
+ $._latex_span_start,
57
+ $._latex_span_close,
58
+
59
+ // Token emmited when encountering opening delimiters for a leaf span
60
+ // e.g. a code span, that does not have a matching closing span
61
+ $._unclosed_span
62
+ ],
63
+ precedences: $ => [
64
+ // [$._strong_emphasis_star, $._inline_element_no_star],
65
+ [$._strong_emphasis_star_no_link, $._inline_element_no_star_no_link],
66
+ // [$._strong_emphasis_underscore, $._inline_element_no_underscore],
67
+ [$._strong_emphasis_underscore_no_link, $._inline_element_no_underscore_no_link],
68
+ [$.hard_line_break, $._whitespace],
69
+ [$.hard_line_break, $._text_base],
70
+ ],
71
+ // More conflicts are defined in `add_inline_rules`
72
+ conflicts: $ => [
73
+
74
+ [$._closing_tag, $._text_base],
75
+ [$._open_tag, $._text_base],
76
+ [$._html_comment, $._text_base],
77
+ [$._processing_instruction, $._text_base],
78
+ [$._declaration, $._text_base],
79
+ [$._cdata_section, $._text_base],
80
+
81
+ [$._link_text_non_empty, $._inline_element],
82
+ [$._link_text_non_empty, $._inline_element_no_star],
83
+ [$._link_text_non_empty, $._inline_element_no_underscore],
84
+ [$._link_text_non_empty, $._inline_element_no_tilde],
85
+ [$._link_text, $._inline_element],
86
+ [$._link_text, $._inline_element_no_star],
87
+ [$._link_text, $._inline_element_no_underscore],
88
+ [$._link_text, $._inline_element_no_tilde],
89
+
90
+ [$._image_description, $._image_description_non_empty, $._text_base],
91
+ // [$._image_description, $._image_description_non_empty, $._text_inline],
92
+ // [$._image_description, $._image_description_non_empty, $._text_inline_no_star],
93
+ // [$._image_description, $._image_description_non_empty, $._text_inline_no_underscore],
94
+
95
+ [$._image_shortcut_link, $._image_description],
96
+ [$.shortcut_link, $._link_text],
97
+ [$.link_destination, $.link_title],
98
+ [$._link_destination_parenthesis, $.link_title],
99
+
100
+ [$.wiki_link, $._inline_element],
101
+ [$.wiki_link, $._inline_element_no_star],
102
+ [$.wiki_link, $._inline_element_no_underscore],
103
+ [$.wiki_link, $._inline_element_no_tilde],
104
+ ],
105
+ extras: $ => [],
106
+
107
+ rules: {
108
+ inline: $ => seq(optional($._last_token_whitespace), $._inline),
109
+
110
+ ...common.rules,
111
+
112
+
113
+ // A lot of inlines are defined in `add_inline_rules`, including:
114
+ //
115
+ // * collections of inlines
116
+ // * emphasis
117
+ // * textual content
118
+ //
119
+ // This is done to reduce code duplication, as some inlines need to be parsed differently
120
+ // depending on the context. For example inlines in ATX headings may not contain newlines.
121
+
122
+ code_span: $ => seq(
123
+ alias($._code_span_start, $.code_span_delimiter),
124
+ repeat(choice($._text_base, '[', ']', $._soft_line_break, $._html_tag)),
125
+ alias($._code_span_close, $.code_span_delimiter)
126
+ ),
127
+
128
+ latex_block: $ => seq(
129
+ alias($._latex_span_start, $.latex_span_delimiter),
130
+ repeat(choice($._text_base, '[', ']', $._soft_line_break, $._html_tag, $.backslash_escape)),
131
+ alias($._latex_span_close, $.latex_span_delimiter),
132
+ ),
133
+
134
+ // Different kinds of links:
135
+ // * inline links (https://github.github.com/gfm/#inline-link)
136
+ // * full reference links (https://github.github.com/gfm/#full-reference-link)
137
+ // * collapsed reference links (https://github.github.com/gfm/#collapsed-reference-link)
138
+ // * shortcut links (https://github.github.com/gfm/#shortcut-reference-link)
139
+ //
140
+ // Dynamic precedence is distributed as granular as possible to help the parser decide
141
+ // while parsing which branch is the most important.
142
+ //
143
+ // https://github.github.com/gfm/#links
144
+ _link_text: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, choice(
145
+ $._link_text_non_empty,
146
+ seq('[', ']')
147
+ )),
148
+ _link_text_non_empty: $ => seq('[', alias($._inline_no_link, $.link_text), ']'),
149
+ shortcut_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, $._link_text_non_empty),
150
+ full_reference_link: $ => prec.dynamic(2 * PRECEDENCE_LEVEL_LINK, seq(
151
+ $._link_text,
152
+ $.link_label
153
+ )),
154
+ collapsed_reference_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, seq(
155
+ $._link_text,
156
+ '[',
157
+ ']'
158
+ )),
159
+ inline_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, seq(
160
+ $._link_text,
161
+ '(',
162
+ repeat(choice($._whitespace, $._soft_line_break)),
163
+ optional(seq(
164
+ choice(
165
+ seq(
166
+ $.link_destination,
167
+ optional(seq(
168
+ repeat1(choice($._whitespace, $._soft_line_break)),
169
+ $.link_title
170
+ ))
171
+ ),
172
+ $.link_title,
173
+ ),
174
+ repeat(choice($._whitespace, $._soft_line_break)),
175
+ )),
176
+ ')'
177
+ )),
178
+
179
+ wiki_link: $ => prec.dynamic(2 * PRECEDENCE_LEVEL_LINK, seq(
180
+ '[', '[',
181
+ alias($._wiki_link_destination, $.link_destination),
182
+ optional(seq(
183
+ '|',
184
+ alias($._wiki_link_text, $.link_text)
185
+ )),
186
+ ']', ']'
187
+ )
188
+ ),
189
+
190
+ _wiki_link_destination: $ => repeat1(choice(
191
+ $._word,
192
+ common.punctuation_without($, ['[',']', '|']),
193
+ $._whitespace,
194
+ )),
195
+
196
+ _wiki_link_text: $ => repeat1(choice(
197
+ $._word,
198
+ common.punctuation_without($, ['[',']']),
199
+ $._whitespace,
200
+ )),
201
+
202
+ // Images work exactly like links with a '!' added in front.
203
+ //
204
+ // https://github.github.com/gfm/#images
205
+ image: $ => choice(
206
+ $._image_inline_link,
207
+ $._image_shortcut_link,
208
+ $._image_full_reference_link,
209
+ $._image_collapsed_reference_link
210
+ ),
211
+ _image_inline_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, seq(
212
+ $._image_description,
213
+ '(',
214
+ repeat(choice($._whitespace, $._soft_line_break)),
215
+ optional(seq(
216
+ choice(
217
+ seq(
218
+ $.link_destination,
219
+ optional(seq(
220
+ repeat1(choice($._whitespace, $._soft_line_break)),
221
+ $.link_title
222
+ ))
223
+ ),
224
+ $.link_title,
225
+ ),
226
+ repeat(choice($._whitespace, $._soft_line_break)),
227
+ )),
228
+ ')'
229
+ )),
230
+ _image_shortcut_link: $ => prec.dynamic(3 * PRECEDENCE_LEVEL_LINK, $._image_description_non_empty),
231
+ _image_full_reference_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, seq($._image_description, $.link_label)),
232
+ _image_collapsed_reference_link: $ => prec.dynamic(PRECEDENCE_LEVEL_LINK, seq($._image_description, '[', ']')),
233
+ _image_description: $ => prec.dynamic(3 * PRECEDENCE_LEVEL_LINK, choice($._image_description_non_empty, seq('!', '[', prec(1, ']')))),
234
+ _image_description_non_empty: $ => seq('!', '[', alias($._inline, $.image_description), prec(1, ']')),
235
+
236
+ // Autolinks. Uri autolinks actually accept protocolls of arbitrary length which does not
237
+ // align with the spec. This is because the binary for the grammar gets to large if done
238
+ // otherwise as tree-sitters code generation is not very concise for this type of regex.
239
+ //
240
+ // Email autolinks do not match every valid email (emails normally should not be parsed
241
+ // using regexes), but this is how they are defined in the spec.
242
+ //
243
+ // https://github.github.com/gfm/#autolinks
244
+ uri_autolink: $ => /<[a-zA-Z][a-zA-Z0-9+\.\-][a-zA-Z0-9+\.\-]*:[^ \t\r\n<>]*>/,
245
+ email_autolink: $ =>
246
+ /<[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*>/,
247
+
248
+ // Raw html. As with html blocks we do not emit additional information as this is best done
249
+ // by a proper html tree-sitter grammar.
250
+ //
251
+ // https://github.github.com/gfm/#raw-html
252
+ _html_tag: $ => choice($._open_tag, $._closing_tag, $._html_comment, $._processing_instruction, $._declaration, $._cdata_section),
253
+ _open_tag: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq('<', $._tag_name, repeat($._attribute), repeat(choice($._whitespace, $._soft_line_break)), optional('/'), '>')),
254
+ _closing_tag: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq('<', '/', $._tag_name, repeat(choice($._whitespace, $._soft_line_break)), '>')),
255
+ _tag_name: $ => seq($._word_no_digit, repeat(choice($._word_no_digit, $._digits, '-'))),
256
+ _attribute: $ => seq(repeat1(choice($._whitespace, $._soft_line_break)), $._attribute_name, repeat(choice($._whitespace, $._soft_line_break)), '=', repeat(choice($._whitespace, $._soft_line_break)), $._attribute_value),
257
+ _attribute_name: $ => /[a-zA-Z_:][a-zA-Z0-9_\.:\-]*/,
258
+ _attribute_value: $ => choice(
259
+ /[^ \t\r\n"'=<>`]+/,
260
+ seq("'", repeat(choice($._word, $._whitespace, $._soft_line_break, common.punctuation_without($, ["'"]))), "'"),
261
+ seq('"', repeat(choice($._word, $._whitespace, $._soft_line_break, common.punctuation_without($, ['"']))), '"'),
262
+ ),
263
+ _html_comment: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq(
264
+ '<!--',
265
+ optional(seq(
266
+ choice(
267
+ $._word,
268
+ $._whitespace,
269
+ $._soft_line_break,
270
+ common.punctuation_without($, ['-', '>']),
271
+ seq(
272
+ '-',
273
+ common.punctuation_without($, ['>']),
274
+ )
275
+ ),
276
+ repeat(prec.right(choice(
277
+ $._word,
278
+ $._whitespace,
279
+ $._soft_line_break,
280
+ common.punctuation_without($, ['-']),
281
+ seq(
282
+ '-',
283
+ choice(
284
+ $._word,
285
+ $._whitespace,
286
+ $._soft_line_break,
287
+ common.punctuation_without($, ['-']),
288
+ )
289
+ )
290
+ ))),
291
+ )),
292
+ '-->'
293
+ )),
294
+ _processing_instruction: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq(
295
+ '<?',
296
+ repeat(prec.right(choice(
297
+ $._word,
298
+ $._whitespace,
299
+ $._soft_line_break,
300
+ common.punctuation_without($, []),
301
+ ))),
302
+ '?>'
303
+ )),
304
+ _declaration: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq(
305
+ /<![A-Z]+/,
306
+ choice(
307
+ $._whitespace,
308
+ $._soft_line_break,
309
+ ),
310
+ repeat(prec.right(choice(
311
+ $._word,
312
+ $._whitespace,
313
+ $._soft_line_break,
314
+ common.punctuation_without($, ['>']),
315
+ ))),
316
+ '>'
317
+ )),
318
+ _cdata_section: $ => prec.dynamic(PRECEDENCE_LEVEL_HTML, seq(
319
+ '<![CDATA[',
320
+ repeat(prec.right(choice(
321
+ $._word,
322
+ $._whitespace,
323
+ $._soft_line_break,
324
+ common.punctuation_without($, []),
325
+ ))),
326
+ ']]>'
327
+ )),
328
+
329
+ // A hard line break.
330
+ //
331
+ // https://github.github.com/gfm/#hard-line-breaks
332
+ hard_line_break: $ => seq(choice('\\', $._whitespace_ge_2), $._soft_line_break),
333
+ _text: $ => choice($._word, common.punctuation_without($, []), $._whitespace),
334
+
335
+ // Whitespace is divided into single whitespaces and multiple whitespaces as wee need this
336
+ // information for hard line breaks.
337
+ _whitespace_ge_2: $ => /\t| [ \t]+/,
338
+ _whitespace: $ => seq(choice($._whitespace_ge_2, / /), optional($._last_token_whitespace)),
339
+
340
+ // Other than whitespace we tokenize into strings of digits, punctuation characters
341
+ // (handled by `common.punctuation_without`) and strings of any other characters. This way the
342
+ // lexer does not have to many different states, which makes it a lot easier to make
343
+ // conflicts work.
344
+ _word: $ => choice($._word_no_digit, $._digits),
345
+ _word_no_digit: $ => new RegExp('[^' + PUNCTUATION_CHARACTERS_REGEX + ' \\t\\n\\r0-9]+(_+[^' + PUNCTUATION_CHARACTERS_REGEX + ' \\t\\n\\r0-9]+)*'),
346
+ _digits: $ => /[0-9][0-9_]*/,
347
+ _soft_line_break: $ => seq($._newline_token, optional($._last_token_whitespace)),
348
+
349
+ _inline_base: $ => prec.right(repeat1(choice(
350
+ $.image,
351
+ $._soft_line_break,
352
+ $.backslash_escape,
353
+ $.hard_line_break,
354
+ $.uri_autolink,
355
+ $.email_autolink,
356
+ $.entity_reference,
357
+ $.numeric_character_reference,
358
+ (common.EXTENSION_LATEX ? $.latex_block : choice()),
359
+ $.code_span,
360
+ alias($._html_tag, $.html_tag),
361
+ $._text_base,
362
+ common.EXTENSION_TAGS ? $.tag : choice(),
363
+ $._unclosed_span,
364
+ ))),
365
+ _text_base: $ => choice(
366
+ $._word,
367
+ common.punctuation_without($, ['[', ']']),
368
+ $._whitespace,
369
+ '<!--',
370
+ /<![A-Z]+/,
371
+ '<?',
372
+ '<![CDATA[',
373
+ ),
374
+ _text_inline_no_link: $ => choice(
375
+ $._text_base,
376
+ $._emphasis_open_star,
377
+ $._emphasis_open_underscore,
378
+ $._unclosed_span,
379
+ ),
380
+
381
+ ...(common.EXTENSION_TAGS ? {
382
+ tag: $ => /#[0-9]*[a-zA-Z_\-\/][a-zA-Z_\-\/0-9]*/,
383
+ } : {}),
384
+
385
+ },
386
+ }));
387
+
388
+ // This function adds some extra inline rules. This is done to reduce code duplication, as some
389
+ // rules may not contain newlines, characters like '*' and '_', ... depending on the context.
390
+ //
391
+ // This is by far the most ugly part of this code and should be cleaned up.
392
+ function add_inline_rules(grammar) {
393
+ let conflicts = [];
394
+ for (let link of [true, false]) {
395
+ let suffix_link = link ? "" : "_no_link";
396
+ for (let delimiter of [false, "star", "underscore", "tilde"]) {
397
+ let suffix_delimiter = delimiter ? "_no_" + delimiter : "";
398
+ let suffix = suffix_delimiter + suffix_link;
399
+ grammar.rules["_inline_element" + suffix] = $ => {
400
+ let elements = [
401
+ $._inline_base,
402
+ alias($['_emphasis_star' + suffix_link], $.emphasis),
403
+ alias($['_strong_emphasis_star' + suffix_link], $.strong_emphasis),
404
+ alias($['_emphasis_underscore' + suffix_link], $.emphasis),
405
+ alias($['_strong_emphasis_underscore' + suffix_link], $.strong_emphasis),
406
+ ];
407
+ if (common.EXTENSION_STRIKETHROUGH) {
408
+ elements.push(alias($['_strikethrough' + suffix_link], $.strikethrough));
409
+ }
410
+ if (delimiter !== "star") {
411
+ elements.push($._emphasis_open_star);
412
+ }
413
+ if (delimiter !== "underscore") {
414
+ elements.push($._emphasis_open_underscore);
415
+ }
416
+ if (delimiter !== "tilde") {
417
+ elements.push($._strikethrough_open);
418
+ }
419
+ if (link) {
420
+ elements = elements.concat([
421
+ $.shortcut_link,
422
+ $.full_reference_link,
423
+ $.collapsed_reference_link,
424
+ $.inline_link,
425
+ // (common.EXTENSION_WIKI_LINK && $.wiki_link),
426
+ seq(choice('[', ']'), optional($._last_token_punctuation)),
427
+ ]);
428
+ if (common.EXTENSION_WIKI_LINK) {
429
+ elements.push($.wiki_link);
430
+ }
431
+ }
432
+ return choice(...elements);
433
+ };
434
+ grammar.rules["_inline" + suffix] = $ => repeat1($["_inline_element" + suffix]);
435
+ if (delimiter !== "star") {
436
+ conflicts.push(['_emphasis_star' + suffix_link, '_inline_element' + suffix_delimiter + suffix_link]);
437
+ conflicts.push(['_emphasis_star' + suffix_link, '_strong_emphasis_star' + suffix_link, '_inline_element' + suffix_delimiter + suffix_link]);
438
+ }
439
+ if (delimiter == 'star' || delimiter == 'underscore') {
440
+ conflicts.push(['_strong_emphasis_' + delimiter + suffix_link, '_inline_element_no_' + delimiter]);
441
+ }
442
+ if (delimiter !== "underscore") {
443
+ conflicts.push(['_emphasis_underscore' + suffix_link, '_inline_element' + suffix_delimiter + suffix_link]);
444
+ conflicts.push(['_emphasis_underscore' + suffix_link, '_strong_emphasis_underscore' + suffix_link, '_inline_element' + suffix_delimiter + suffix_link]);
445
+ }
446
+ if (delimiter !== "tilde") {
447
+ conflicts.push(['_strikethrough' + suffix_link, '_inline_element' + suffix_delimiter + suffix_link]);
448
+ }
449
+ }
450
+
451
+ if (common.EXTENSION_STRIKETHROUGH) {
452
+ grammar.rules['_strikethrough' + suffix_link] = $ => prec.dynamic(PRECEDENCE_LEVEL_EMPHASIS, seq(alias($._strikethrough_open, $.emphasis_delimiter), optional($._last_token_punctuation), $['_inline' + '_no_tilde' + suffix_link], alias($._strikethrough_close, $.emphasis_delimiter)));
453
+ }
454
+ grammar.rules['_emphasis_star' + suffix_link] = $ => prec.dynamic(PRECEDENCE_LEVEL_EMPHASIS, seq(alias($._emphasis_open_star, $.emphasis_delimiter), optional($._last_token_punctuation), $['_inline' + '_no_star' + suffix_link], alias($._emphasis_close_star, $.emphasis_delimiter)));
455
+ grammar.rules['_strong_emphasis_star' + suffix_link] = $ => prec.dynamic(2 * PRECEDENCE_LEVEL_EMPHASIS, seq(alias($._emphasis_open_star, $.emphasis_delimiter), $['_emphasis_star' + suffix_link], alias($._emphasis_close_star, $.emphasis_delimiter)));
456
+ grammar.rules['_emphasis_underscore' + suffix_link] = $ => prec.dynamic(PRECEDENCE_LEVEL_EMPHASIS, seq(alias($._emphasis_open_underscore, $.emphasis_delimiter), optional($._last_token_punctuation), $['_inline' + '_no_underscore' + suffix_link], alias($._emphasis_close_underscore, $.emphasis_delimiter)));
457
+ grammar.rules['_strong_emphasis_underscore' + suffix_link] = $ => prec.dynamic(2 * PRECEDENCE_LEVEL_EMPHASIS, seq(alias($._emphasis_open_underscore, $.emphasis_delimiter), $['_emphasis_underscore' + suffix_link], alias($._emphasis_close_underscore, $.emphasis_delimiter)));
458
+ }
459
+
460
+ let old = grammar.conflicts
461
+ grammar.conflicts = $ => {
462
+ let cs = old($);
463
+ for (let conflict of conflicts) {
464
+ let c = [];
465
+ for (let rule of conflict) {
466
+ c.push($[rule]);
467
+ }
468
+ cs.push(c);
469
+ }
470
+ return cs;
471
+ }
472
+
473
+ return grammar;
474
+ }
@@ -0,0 +1,56 @@
1
+ ; From nvim-treesitter/nvim-treesitter
2
+ [
3
+ (code_span)
4
+ (link_title)
5
+ ] @text.literal
6
+
7
+ [
8
+ (emphasis_delimiter)
9
+ (code_span_delimiter)
10
+ ] @punctuation.delimiter
11
+
12
+ (emphasis) @text.emphasis
13
+
14
+ (strong_emphasis) @text.strong
15
+
16
+ [
17
+ (link_destination)
18
+ (uri_autolink)
19
+ ] @text.uri
20
+
21
+ [
22
+ (link_label)
23
+ (link_text)
24
+ (image_description)
25
+ ] @text.reference
26
+
27
+ [
28
+ (backslash_escape)
29
+ (hard_line_break)
30
+ ] @string.escape
31
+
32
+ (image
33
+ [
34
+ "!"
35
+ "["
36
+ "]"
37
+ "("
38
+ ")"
39
+ ] @punctuation.delimiter)
40
+
41
+ (inline_link
42
+ [
43
+ "["
44
+ "]"
45
+ "("
46
+ ")"
47
+ ] @punctuation.delimiter)
48
+
49
+ (shortcut_link
50
+ [
51
+ "["
52
+ "]"
53
+ ] @punctuation.delimiter)
54
+
55
+ ; NOTE: extension not enabled by default
56
+ ; (wiki_link ["[" "|" "]"] @punctuation.delimiter)
@@ -0,0 +1,5 @@
1
+ ((html_tag) @injection.content
2
+ (#set! injection.language "html"))
3
+
4
+ ((latex_block) @injection.content
5
+ (#set! injection.language "latex"))