Skip to content

Commit 2d716fc

Browse files
committed
feat(injections): enable language-specific code block syntax highlighting
# Add support for parsing [source,language] attributes in code blocks - Enhance block_attributes grammar to parse source block language specifications - Add source_block_attributes rule with type and language fields - Add language_identifier rule to capture programming language names - Update injections.scm with language-specific injection patterns for: - Python, JavaScript, Rust, Go, HTML, CSS, JSON, YAML, Bash - Add comprehensive test files for various programming languages - Resolve conflicts between attribute parsing rules This enables proper syntax highlighting within AsciiDoc code blocks in editors that support Tree Sitter language injections (like Zed, Neovim, etc.). BREAKING CHANGE: block_attributes now has a more structured AST with source_block_attributes as a distinct node type instead of generic content.
1 parent a300fa1 commit 2d716fc

9 files changed

Lines changed: 72483 additions & 70355 deletions

grammar.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ module.exports = grammar({
4242
[$.ordered_list_item],
4343
[$.description_item],
4444
[$.callout_item],
45-
[$.inline_element, $.explicit_link]
45+
[$.inline_element, $.explicit_link],
46+
[$.attribute_content, $.role_list]
4647
],
4748

4849
rules: {
@@ -301,11 +302,23 @@ module.exports = grammar({
301302

302303
block_attributes: $ => prec(3, seq(
303304
'[',
304-
/[^\]\r\n]+/, // attribute content
305+
choice(
306+
$.source_block_attributes,
307+
field('content', $.attribute_content)
308+
),
305309
']',
306310
$._line_ending
307311
)),
308312

313+
source_block_attributes: $ => prec(100, seq(
314+
field('type', token('source')),
315+
token(','),
316+
field('language', $.language_identifier)
317+
)),
318+
319+
language_identifier: $ => /[a-zA-Z][a-zA-Z0-9_+-]*/,
320+
attribute_content: $ => /[^\]\r\n]+/,
321+
309322
id_and_roles: $ => seq(
310323
'[',
311324
/#[^\]\r\n]+/, // content starting with # for ID

queries/injections.scm

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,92 @@
11
; AsciiDoc language injections for embedded syntax highlighting
22

3-
; Code blocks with language specified in metadata
4-
; TODO: This would require parsing block attributes to detect language
5-
; For now, we'll use simpler patterns
3+
; Language-specific code blocks - Now supported!
4+
; Extract language from [source,language] attributes
5+
(listing_block
6+
(metadata
7+
(block_attributes
8+
(source_block_attributes
9+
language: (language_identifier) @injection.language)))
10+
content: (block_content) @injection.content)
11+
12+
; Fallback: Generic source blocks with language detection from content
13+
((listing_block
14+
(metadata
15+
(block_attributes
16+
content: (attribute_content) @_lang
17+
(#match? @_lang "source,python")))
18+
content: (block_content) @injection.content)
19+
(#set! injection.language "python"))
20+
21+
((listing_block
22+
(metadata
23+
(block_attributes
24+
content: (attribute_content) @_lang
25+
(#match? @_lang "source,javascript")))
26+
content: (block_content) @injection.content)
27+
(#set! injection.language "javascript"))
28+
29+
((listing_block
30+
(metadata
31+
(block_attributes
32+
content: (attribute_content) @_lang
33+
(#match? @_lang "source,rust")))
34+
content: (block_content) @injection.content)
35+
(#set! injection.language "rust"))
36+
37+
((listing_block
38+
(metadata
39+
(block_attributes
40+
content: (attribute_content) @_lang
41+
(#match? @_lang "source,json")))
42+
content: (block_content) @injection.content)
43+
(#set! injection.language "json"))
44+
45+
((listing_block
46+
(metadata
47+
(block_attributes
48+
content: (attribute_content) @_lang
49+
(#match? @_lang "source,yaml")))
50+
content: (block_content) @injection.content)
51+
(#set! injection.language "yaml"))
52+
53+
((listing_block
54+
(metadata
55+
(block_attributes
56+
content: (attribute_content) @_lang
57+
(#match? @_lang "source,html")))
58+
content: (block_content) @injection.content)
59+
(#set! injection.language "html"))
60+
61+
((listing_block
62+
(metadata
63+
(block_attributes
64+
content: (attribute_content) @_lang
65+
(#match? @_lang "source,css")))
66+
content: (block_content) @injection.content)
67+
(#set! injection.language "css"))
68+
69+
((listing_block
70+
(metadata
71+
(block_attributes
72+
content: (attribute_content) @_lang
73+
(#match? @_lang "source,go")))
74+
content: (block_content) @injection.content)
75+
(#set! injection.language "go"))
76+
77+
((listing_block
78+
(metadata
79+
(block_attributes
80+
content: (attribute_content) @_lang
81+
(#match? @_lang "source,bash")))
82+
content: (block_content) @injection.content)
83+
(#set! injection.language "bash"))
684

785
; Math content injection (math_macro is a simple token)
886
(math_macro) @injection.content
987
(#set! injection.language "latex")
1088

11-
; Generic code blocks (listing blocks often contain code)
89+
; Generic code blocks without language specification
1290
(listing_block
1391
(block_content) @injection.content
1492
(#set! injection.language "text"))

src/grammar.json

Lines changed: 56 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/node-types.json

Lines changed: 61 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)