diff --git a/packages/language-gfm/grammars/modern-tree-sitter-gfm-inline.cson b/packages/language-gfm/grammars/modern-tree-sitter-gfm-inline.cson new file mode 100644 index 0000000000..7f44177667 --- /dev/null +++ b/packages/language-gfm/grammars/modern-tree-sitter-gfm-inline.cson @@ -0,0 +1,10 @@ +scopeName: 'source.gfm.inline' +type: 'modern-tree-sitter' +parser: 'tree-sitter-markdown_inline' + +injectionRegex: '^(markdown-inline-internal)$' + +treeSitter: + parserSource: 'github:MDeiml/tree-sitter-markdown/tree-sitter-markdown-inline#28aa3baef73bd458d053b613b8bd10fd102b4405' + grammar: 'tree-sitter-markdown-inline/tree-sitter-markdown-inline.wasm' + highlightsQuery: 'tree-sitter-markdown-inline/highlights.scm' diff --git a/packages/language-gfm/grammars/modern-tree-sitter-gfm-with-frontmatter.cson b/packages/language-gfm/grammars/modern-tree-sitter-gfm-with-frontmatter.cson deleted file mode 100644 index 7cdb0977b3..0000000000 --- a/packages/language-gfm/grammars/modern-tree-sitter-gfm-with-frontmatter.cson +++ /dev/null @@ -1,30 +0,0 @@ -name: 'GitHub Markdown' -scopeName: 'source.gfm' -type: 'modern-tree-sitter' -# Generated from `savetheclocktower/tree-sitter-frontmatter`. -parser: 'tree-sitter-frontmatter' - -treeSitter: - grammar: 'tree-sitter/tree-sitter-frontmatter.wasm' - highlightsQuery: 'tree-sitter/tree-sitter-frontmatter/highlights.scm' - -fileTypes: [ - 'markdown' - 'md' - 'mdown' - 'mdwn' - 'mkd' - 'mkdn' - 'mkdown' - 'rmd' - 'ron' - 'workbook' -] - -firstLineRegex: '^---$' - -comments: - start: '' - blockStart: '' diff --git a/packages/language-gfm/grammars/modern-tree-sitter-gfm.cson b/packages/language-gfm/grammars/modern-tree-sitter-gfm.cson index 863370d1d9..b2cf67c6b5 100644 --- a/packages/language-gfm/grammars/modern-tree-sitter-gfm.cson +++ b/packages/language-gfm/grammars/modern-tree-sitter-gfm.cson @@ -1,15 +1,16 @@ -# This grammar doesn't have its own name because it's only meant to be injected. -scopeName: 'source.gfm.embedded' +scopeName: 'source.gfm' type: 'modern-tree-sitter' +name: 'GitHub Markdown' parser: 'tree-sitter-markdown' -injectionRegex: '(MARKDOWN|markdown|GFM|gfm)$' +injectionRegex: '^(markdown|MARKDOWN|gfm|GFM)$' treeSitter: - grammar: 'tree-sitter/tree-sitter-markdown.wasm' - highlightsQuery: 'tree-sitter/tree-sitter-markdown/highlights.scm' - foldsQuery: 'tree-sitter/tree-sitter-markdown/folds.scm' - tagsQuery: 'tree-sitter/tree-sitter-markdown/tags.scm' + parserSource: 'github:MDeiml/tree-sitter-markdown/tree-sitter-markdown#28aa3baef73bd458d053b613b8bd10fd102b4405' + grammar: 'tree-sitter-markdown/tree-sitter-markdown.wasm' + highlightsQuery: 'tree-sitter-markdown/highlights.scm' + foldsQuery: 'tree-sitter-markdown/folds.scm' + tagsQuery: 'tree-sitter-markdown/tags.scm' fileTypes: [ 'markdown' diff --git a/packages/language-gfm/grammars/tree-sitter-markdown-inline/highlights.scm b/packages/language-gfm/grammars/tree-sitter-markdown-inline/highlights.scm new file mode 100644 index 0000000000..0ec5313294 --- /dev/null +++ b/packages/language-gfm/grammars/tree-sitter-markdown-inline/highlights.scm @@ -0,0 +1,77 @@ +; BOLD/ITALIC/OTHER +; =============== + +(emphasis) @markup.italic.gfm + +(emphasis + . (emphasis_delimiter) @punctuation.definition.emphasis.begin.gfm) + +(emphasis + (emphasis_delimiter) @punctuation.definition.emphasis.end.gfm .) + +(strong_emphasis) @markup.bold.gfm +((strong_emphasis) @punctuation.definition.emphasis.begin.gfm + (#set! adjust.endAfterFirstMatchOf "^\\*\\*")) +((strong_emphasis) @punctuation.definition.emphasis.end.gfm + (#set! adjust.startBeforeFirstMatchOf "\\*\\*$")) + +(strikethrough) @markup.strike.gfm + +((strikethrough) @punctuation.definition.strike.begin.gfm + (#set! adjust.endAfterFirstMatchOf "^~~")) +((strikethrough) @punctuation.definition.strike.end.gfm + (#set! adjust.startBeforeFirstMatchOf "~~$")) + + +; INLINE/REPLACED +; =============== + +((uri_autolink) @markup.underline.link + (#set! adjust.startAfterFirstMatchOf "^<") + (#set! adjust.endBeforeFirstMatchOf ">$")) + +((uri_autolink) @punctuation.definition.begin.uri-autolink.gfm + (#set! adjust.endAfterFirstMatchOf "^<")) + +((uri_autolink) @punctuation.definition.end.uri-autolink.gfm + (#set! adjust.startBeforeFirstMatchOf ">$")) + +((link_text (image (image_description))) @_IGNORE_ + (#set! capture.final)) + +[(link_text) (image_description)] @string.unquoted.gfm @meta.link.text + +; The text inside []s in anchors/image syntax. +(full_reference_link + (link_label) @markup.underline.link.gfm + (#set! adjust.startAfterFirstMatchOf "^\\[") + (#set! adjust.endBeforeFirstMatchOf "]$")) + +(image + (link_destination) @markup.underline.link.gfm) + +(inline_link + (link_destination) @markup.underline.link.gfm) + +(link_title) @string.quoted.link-title.gfm + + +; CODE SPANS +; ========== + +(code_span) @meta.embedded.line.inline-code.gfm @markup.raw.inline.gfm + +(code_span + . (code_span_delimiter) @punctuation.definition.begin.string.inline-code.gfm) + +(code_span + (code_span_delimiter) @punctuation.definition.end.string.inline-code.gfm + .) + + +; MISC +; ==== + +(backslash_escape) @constant.character.escape.gfm + +(numeric_character_reference) @constant.character.entity.gfm diff --git a/packages/language-gfm/grammars/tree-sitter-markdown-inline/tree-sitter-markdown-inline.wasm b/packages/language-gfm/grammars/tree-sitter-markdown-inline/tree-sitter-markdown-inline.wasm new file mode 100755 index 0000000000..04618d113f Binary files /dev/null and b/packages/language-gfm/grammars/tree-sitter-markdown-inline/tree-sitter-markdown-inline.wasm differ diff --git a/packages/language-gfm/grammars/tree-sitter-markdown/folds.scm b/packages/language-gfm/grammars/tree-sitter-markdown/folds.scm new file mode 100644 index 0000000000..817b916852 --- /dev/null +++ b/packages/language-gfm/grammars/tree-sitter-markdown/folds.scm @@ -0,0 +1,11 @@ + +; Each individual list item can be folded if it's hard-wrapped. +((list_item) @fold + (#set! fold.endAt endPosition) + (#set! fold.adjustToEndOfPreviousRow true)) + +; Each section represents a heading and all the content underneath it until the +; next heading of equivalent or higher importance. +((section) @fold + (#set! fold.endAt endPosition) + (#set! fold.adjustToEndOfPreviousRow true)) diff --git a/packages/language-gfm/grammars/tree-sitter-markdown/highlights.scm b/packages/language-gfm/grammars/tree-sitter-markdown/highlights.scm new file mode 100644 index 0000000000..b17ba163ed --- /dev/null +++ b/packages/language-gfm/grammars/tree-sitter-markdown/highlights.scm @@ -0,0 +1,94 @@ +; HEADINGS +; ======== + +(setext_heading + heading_content: (_) @markup.heading.heading-1.gfm + (setext_h1_underline) @punctuation.definition.heading-underline.gfm) + +(setext_heading + heading_content: (_) @markup.heading.heading-2.gfm + (setext_h2_underline) @punctuation.definition.heading-underline.gfm) + +(atx_heading + (atx_h1_marker)) @markup.heading.heading-1.gfm + +(atx_heading + (atx_h2_marker)) @markup.heading.heading-2.gfm + +(atx_heading + (atx_h3_marker)) @markup.heading.heading-3.gfm + +(atx_heading + (atx_h4_marker)) @markup.heading.heading-4.gfm + +(atx_heading + (atx_h5_marker)) @markup.heading.heading-5.gfm + +(atx_heading + (atx_h6_marker)) @markup.heading.heading-6.gfm + + +; SECTIONS +; ======== + +(paragraph) @markup.paragraph.gfm +(thematic_break) @markup.horizontal-rule.gfm + +(block_quote) @markup.quote.blockquote.gfm +((block_quote_marker) @punctuation.definition.blockquote.gfm + (#set! adjust.startAndEndAroundFirstMatchOf "\\S")) + + +; LISTS +; ===== + +(list) @meta.list.gfm + +(list_item + (list_marker_dot) @punctuation.definition.list-item.gfm +) @markup.list.numbered + +(list_item + [ + (list_marker_star) + (list_marker_minus) + (list_marker_plus) + ] @punctuation.definition.list-item.gfm +) @markup.list.unnumbered + +(task_list_marker_unchecked) @punctuation.definition.task-marker.unchecked.gfm +(task_list_marker_checked) @punctuation.definition.task-marker.unchecked.gfm + +; CODE BLOCKS +; =========== + +(info_string) @storage.modifier.language._TEXT_.gfm + +(fenced_code_block + (code_fence_content) @markup.raw.block.fenced.gfm) @meta.embedded.block.fenced-code.gfm +(indented_code_block) @markup.raw.block.indented.gfm @meta.embedded.block.indented-code.gfm + + +; MISC +; ==== + +(pipe_table) @markup.other.table.gfm +(pipe_table_header + (pipe_table_cell) @markup.other.table-cell.header.gfm) +(pipe_table_row + (pipe_table_cell) @markup.other.table-cell.data.gfm) +(pipe_table_delimiter_row + (pipe_table_delimiter_cell + (_) @punctuation.separator.table-row.gfm) +) + + +; Link definitions + +(link_reference_definition + (link_label) + (link_destination) @markup.underline.link.gfm) + +((link_label) @meta.link.text + (#set! adjust.offsetStart 1) + (#set! adjust.offsetEnd -1)) diff --git a/packages/language-gfm/grammars/tree-sitter-markdown/tags.scm b/packages/language-gfm/grammars/tree-sitter-markdown/tags.scm new file mode 100644 index 0000000000..afe13abefa --- /dev/null +++ b/packages/language-gfm/grammars/tree-sitter-markdown/tags.scm @@ -0,0 +1,52 @@ + +; Each heading counts as a tag for symbol navigation purposes. We'll indicate a +; symbol's heading level with a certain number of dots prepended to the symbol +; name. + +((atx_heading + (atx_h1_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "· ")) + +((atx_heading + (atx_h2_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "·· ")) + +((atx_heading + (atx_h3_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "··· ")) + +((atx_heading + (atx_h4_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "···· ")) + +((atx_heading + (atx_h5_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "····· ")) + +((atx_heading + (atx_h6_marker) + heading_content: (_) @name) @definition.heading + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "······ ")) + +((setext_heading + heading_content: (_) @name) @definition.heading + (setext_h1_underline) + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "· ")) + +((setext_heading + heading_content: (_) @name) @definition.heading + (setext_h2_underline) + (#set! symbol.strip "(^\\s*|\\s*$)") + (#set! symbol.prepend "·· ")) diff --git a/packages/language-gfm/grammars/tree-sitter-markdown/tree-sitter-markdown.wasm b/packages/language-gfm/grammars/tree-sitter-markdown/tree-sitter-markdown.wasm new file mode 100755 index 0000000000..e248b73355 Binary files /dev/null and b/packages/language-gfm/grammars/tree-sitter-markdown/tree-sitter-markdown.wasm differ diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter.wasm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter.wasm deleted file mode 100755 index c8d0a8e37d..0000000000 Binary files a/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter.wasm and /dev/null differ diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter/highlights.scm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter/highlights.scm deleted file mode 100644 index a3f37189c2..0000000000 --- a/packages/language-gfm/grammars/tree-sitter/tree-sitter-frontmatter/highlights.scm +++ /dev/null @@ -1 +0,0 @@ -(front_matter) @meta.embedded.block.front-matter.gfm diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown.wasm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown.wasm deleted file mode 100755 index 872e944ed5..0000000000 Binary files a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown.wasm and /dev/null differ diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/folds.scm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/folds.scm deleted file mode 100644 index e52dd7fc1f..0000000000 --- a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/folds.scm +++ /dev/null @@ -1,22 +0,0 @@ -; TODO: Folds in Markdown files will have to wait until we can add "tags" to -; divided folds. We want an H1 section to be able to fold up everything until -; the next H1 in the file, an H2 to fold up everything until the next H2 _or_ -; H1, an H3 to fold up everything until the next H3 _or_ H2 _or_ H1… but this -; is not currently possible. - -; (atx_heading (atx_h1_marker)) @fold.start.h1 @fold.end.h1 @fold.end.h2 @fold.end.h3 @fold.end.h4 @fold.end.h5 @fold.end.h6 -; -; (atx_heading (atx_h2_marker)) @fold.start.h2 @fold.end.h2 @fold.end.h3 @fold.end.h4 @fold.end.h5 @fold.end.h6 -; -; (atx_heading (atx_h3_marker)) @fold.start.h3 @fold.end.h3 @fold.end.h4 @fold.end.h5 @fold.end.h6 -; -; (atx_heading (atx_h4_marker)) @fold.start.h4 @fold.end.h4 @fold.end.h5 @fold.end.h6 -; -; (atx_heading (atx_h5_marker)) @fold.start.h5 @fold.end.h5 @fold.end.h6 -; -; (atx_heading (atx_h6_marker)) @fold.start.h6 @fold.end.h6 -; -; ; [(atx_heading) (setext_heading)] @fold.end @fold.start - -((list_item) @fold - (#set! fold.endAt endPosition)) diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/highlights.scm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/highlights.scm deleted file mode 100644 index 42e12ebe69..0000000000 --- a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/highlights.scm +++ /dev/null @@ -1,188 +0,0 @@ -; HEADINGS -; ======== - -(setext_heading - (heading_content) @markup.heading.heading-1.gfm - (setext_h1_underline) @punctuation.definition.heading-underline.gfm) - -(setext_heading - (heading_content) @markup.heading.heading-2.gfm - (setext_h2_underline) @punctuation.definition.heading-underline.gfm) - -(atx_heading - (atx_h1_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-1.gfm - -(atx_heading - (atx_h2_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-2.gfm - -(atx_heading - (atx_h3_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-3.gfm - -(atx_heading - (atx_h4_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-4.gfm - -(atx_heading - (atx_h5_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-5.gfm - -(atx_heading - (atx_h6_marker) @punctuation.definition.heading.gfm - ) @markup.heading.heading-6.gfm - - -; SECTIONS -; ======== - -(paragraph) @markup.paragraph.gfm - -(thematic_break) @markup.horizontal-rule.gfm - -(block_quote) @markup.quote.blockquote.gfm -((block_quote) @punctuation.definition.blockquote.gfm - (#set! adjust.endAfterFirstMatchOf ">")) - - -; LISTS -; ===== - -; `markup.list` gets applied to individual list items, unintuitively. So let's -; scope the entire list. “Tight” vs “Loose” has to do with whether each `
` tags around it.
-
-[(tight_list) (loose_list)] @meta.list.gfm
-
-((list_item
- (list_marker) @punctuation.definition.list-item.gfm) @markup.list.unnumbered
- ; Instead of matching bullet or minus or plus, any not-digit here is
- ; guaranteed to be an unordered list.
- (#not-match? @punctuation.definition.list-item.gfm "^\\d"))
-
-((list_item
- (list_marker) @punctuation.definition.list-item.gfm) @markup.list.numbered
- (#match? @punctuation.definition.list-item.gfm "^\\d"))
-
-((task_list_item
- (list_marker) @punctuation.definition.list-item.gfm) @markup.list.unnumbered
- ; Instead of matching bullet or minus or plus, any not-digit here is
- ; guaranteed to be an unordered list.
- (#not-match? @punctuation.definition.list-item.gfm "^\\d"))
-
-((task_list_item
- (list_marker) @punctuation.definition.list-item.gfm) @markup.list.numbered
- (#match? @punctuation.definition.list-item.gfm "^\\d"))
-
-
-; INLINE/REPLACED
-; ===============
-
-; The text inside []s in anchors/image syntax.
-[(link_text) (image_description)] @string.unquoted.gfm @meta.link.text
-
-(link_label (text) @meta.link.text)
-
-; A URL between ()s in anchor syntax.
-(link_destination) @markup.underline.link.gfm
-((link) @punctuation.definition.begin.link.bracket.round.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "(?<=\\])\\("))
-((link) @punctuation.definition.end.link.bracket.round.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "\\)$"))
-
-((link) @punctuation.definition.begin.link.bracket.square.gfm
- (#set! adjust.endAfterFirstMatchOf "^\\["))
-((link) @punctuation.definition.end.link.bracket.square.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "\\](?=\\(|\\[)"))
-((link_reference_definition) @punctuation.definition.begin.link.bracket.square.gfm
- (#set! adjust.endAfterFirstMatchOf "^\\["))
-((link_reference_definition) @punctuation.definition.end.link.bracket.square.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "\\](?=\\(|\\[)"))
-((link_reference_definition) @punctuation.separator.link.colon.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf ":"))
-
-; A URL between <>s in autolink syntax.
-(uri_autolink (text) @markup.underline.link.gfm)
-((uri_autolink) @punctuation.definition.link.begin.bracket.angle.gfm
- (#set! adjust.endAfterFirstMatchOf "^<"))
-((uri_autolink) @punctuation.definition.link.end.bracket.angle.gfm
- (#set! adjust.startBeforeFirstMatchOf ">$"))
-
-; A link title: `[foo](http://example.com "Example web site")`
-((link_title) @string.quoted.double.link-title.gfm
- (#match? @string.quoted.double.link-title.gfm "^\"")
- (#set! capture.final true))
-
-((link_title) @punctuation.definition.string.begin.gfm
- (#match? @punctuation.definition.string.begin.gfm "^\"")
- (#set! adjust.endAfterFirstMatchOf "^\""))
-
-((link_title) @punctuation.definition.string.end.gfm
- (#match? @punctuation.definition.string.end.gfm "\"$")
- (#set! adjust.startBeforeFirstMatchOf "\"$"))
-
-; Out of laziness, let's throw all other kinds of link title into the generic
-; bin — they are all delimited _somehow_, right?
-(link_title) @string.quoted.link-title.gfm
-
-; Link labels in `[foo][bar]` syntax, where `bar` is associated with a URL via
-; a subsequent footnote, actually work correctly when one runs "Link: Open" in
-; Pulsar, so these should be treated like links.
-(link_label) @markup.underline.link.link-label.gfm
-
-(image) @meta.image.gfm
-
-
-; CODE BLOCKS
-; ===========
-
-(code_span) @meta.embedded.line.inline-code.gfm @markup.raw.inline.gfm
-(info_string) @storage.modifier.language._TEXT_.gfm
-
-(fenced_code_block
- (code_fence_content) @markup.raw.block.fenced.gfm) @meta.embedded.block.fenced-code.gfm
-(indented_code_block) @markup.raw.block.indented.gfm @meta.embedded.block.indented-code.gfm
-
-
-; BOLD/ITALIC/OTHER
-; =================
-
-(emphasis) @markup.italic.gfm
-(strong_emphasis) @markup.bold.gfm
-(strikethrough) @markup.strike.gfm
-
-((emphasis) @punctuation.delimiter.emphasis.begin.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "^(\\*|_)"))
-
-((emphasis) @punctuation.delimiter.emphasis.end.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "(\\*|_)$"))
-
-((strong_emphasis) @punctuation.delimiter.emphasis.begin.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "^(\\*{2}|_{2})"))
-
-((strong_emphasis) @punctuation.delimiter.emphasis.end.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "(\\*{2}|_{2})$"))
-
-((strikethrough) @punctuation.delimiter.strike.begin.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "^~~"))
-
-((strikethrough) @punctuation.delimiter.strike.begin.gfm
- (#set! adjust.startAndEndAroundFirstMatchOf "~~$"))
-
-; HTML
-; ====
-
-(html_comment) @comment.block.html
-
-; MISC
-; ====
-
-(table) @markup.other.table.gfm
-(table_header_row (table_cell) @markup.other.table-cell.header.gfm)
-(table_data_row (table_cell) @markup.other.table-cell.data.gfm)
-
-(table_delimiter_row (table_column_alignment) @punctuation.separator.table-row.gfm)
-
-
-(backslash_escape) @constant.character.escape.gfm
diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/indents.scm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/indents.scm
deleted file mode 100644
index 8aece2f967..0000000000
--- a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/indents.scm
+++ /dev/null
@@ -1,3 +0,0 @@
-; Intentionally empty indents.scm. By and large, indentation level should be
-; manually controlled by the user in Markdown; the best thing we can do is stay
-; out of the user's way.
diff --git a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/tags.scm b/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/tags.scm
deleted file mode 100644
index b776687599..0000000000
--- a/packages/language-gfm/grammars/tree-sitter/tree-sitter-markdown/tags.scm
+++ /dev/null
@@ -1,56 +0,0 @@
-
-((atx_heading
- (atx_h1_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "· ")
- (#set! symbol.icon "chevron-right"))
-
-((atx_heading
- (atx_h2_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "·· ")
- (#set! symbol.icon "chevron-right"))
-
-((atx_heading
- (atx_h3_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "··· ")
- (#set! symbol.icon "chevron-right"))
-
-((atx_heading
- (atx_h4_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "···· ")
- (#set! symbol.icon "chevron-right"))
-
-((atx_heading
- (atx_h5_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "····· ")
- (#set! symbol.icon "chevron-right"))
-
-((atx_heading
- (atx_h6_marker)
- (heading_content) @name) @definition.heading
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "······ ")
- (#set! symbol.icon "chevron-right"))
-
-((setext_heading
- (heading_content) @name) @definition.heading
- (setext_h1_underline)
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "· ")
- (#set! symbol.icon "chevron-right"))
-
-((setext_heading
- (heading_content) @name) @definition.heading
- (setext_h2_underline)
- (#set! symbol.strip "(^\\s*|\\s*$)")
- (#set! symbol.prepend "·· ")
- (#set! symbol.icon "chevron-right"))
diff --git a/packages/language-gfm/lib/main.js b/packages/language-gfm/lib/main.js
index d4c62e1b43..f85b2f4cd5 100644
--- a/packages/language-gfm/lib/main.js
+++ b/packages/language-gfm/lib/main.js
@@ -1,127 +1,74 @@
exports.activate = () => {
-
- // The top-level tree-sitter parser for `source.gfm` simply divides the text
- // into front matter (if it exists) and the remainder, which is directly
- // parsed as Markdown.
+ // Injection for YAML front matter.
//
- // We do this because the `ikatyang/tree-sitter-markdown` parser does not
- // recognize YAML front matter, but is otherwise a very strong Markdown
- // parser. If the `MDeiml/tree-sitter-markdown` parser became more stable,
- // we could consider switching, and then we wouldn't need this extra parser.
-
- // Hand off the front matter to the YAML injection.
+ // TODO: If people want fancy front matter support, like the ability to
+ // control the front matter description language, then we might try to employ
+ // the technique we used for the last Markdown parser and use
+ // `tree-sitter-frontmatter` as the outermost grammar.
atom.grammars.addInjectionPoint('source.gfm', {
- type: 'front_matter',
+ type: 'minus_metadata',
language: () => 'yaml',
- content(node) {
- return node.descendantsOfType('text');
- }
+ content: (node) => node
});
- // Hand off everything else to the Markdown injection.
+ // This is a two-phase parser. The outer parser handles block-level content;
+ // the inner parser handles inline content.
atom.grammars.addInjectionPoint('source.gfm', {
- type: 'remainder',
- language: () => 'markdown',
+ type: 'inline',
+ language: () => {
+ return 'markdown-inline-internal';
+ },
content: (node) => node,
+ includeChildren: true,
languageScope: null
});
- // The markdown injection has a scope name of `source.gfm.embedded` so we can
- // target it for the rest of these injections, but you can see above that we
- // suppress that scope name when we inject it into a document.
-
- // Highlight HTML blocks.
- atom.grammars.addInjectionPoint('source.gfm.embedded', {
- type: 'html_block',
+ // Create one HTML injection layer for all block-level HTML nodes.
+ atom.grammars.addInjectionPoint('source.gfm', {
+ type: 'document',
language: () => 'html',
- content: (node) => node,
+ content(node) {
+ return node.descendantsOfType('html_block');
+ },
includeChildren: true
});
- for (let nodeType of ['paragraph', 'table_cell']) {
- atom.grammars.addInjectionPoint('source.gfm.embedded', {
- type: nodeType,
- language(node) {
- let html = node.descendantsOfType([
- 'html_open_tag',
- 'html_close_tag',
- 'html_self_closing_tag'
- ]);
- if (html.length === 0) { return null; }
- return 'html';
- },
-
- content(node) {
- let html = node.descendantsOfType([
- 'html_open_tag',
- 'html_close_tag',
- 'html_self_closing_tag'
- ]);
- return html;
- },
-
- includeChildren: true
- });
- }
-
- // All code blocks of the form
- //
- // ```foo
- // (code goes here)
- // ```
- //
- // get injections on the theory that some grammar's `injectionRegex` will
- // match `foo`.
- atom.grammars.addInjectionPoint('source.gfm.embedded', {
+ // Injections for code blocks.
+ atom.grammars.addInjectionPoint('source.gfm', {
type: 'fenced_code_block',
language(node) {
- let language = node?.firstNamedChild;
- if (language?.type === 'info_string')
- return language.text;
-
- return null;
+ let infoString = node.descendantsOfType('language');
+ if (infoString.length === 0) return undefined;
+ return infoString[0]?.text;
},
content(node) {
- return node.descendantsOfType('code_fence_content');
+ let codeFenceContent = node.descendantsOfType('code_fence_content');
+ if (codeFenceContent.length === 0) return undefined;
+ return codeFenceContent[0];
},
- languageScope: (grammar) => `${grammar.scopeName}.embedded`,
includeChildren: true
});
-};
-
-
-// Since this parser isn't guaranteed to detect all URLs in paragraphs (see
-// https://github.com/pulsar-edit/pulsar/issues/885), we'll inject the
-// `hyperlink` parser into `text` nodes in paragraphs when there appear to be
-// URLs in them.
-exports.consumeHyperlinkInjection = (hyperlink) => {
-
- function textChildren(node) {
- let results = [];
- for (let i = 0; i < node.namedChildCount; i++) {
- let child = node.child(i);
- if (child.type === 'text') {
- results.push(child);
- }
- }
- return results;
- }
- hyperlink.addInjectionPoint('source.gfm.embedded', {
- types: ['paragraph'],
- // Override the language callback so that it doesn't test URLs that are
- // already handled in `uri_autolink` nodes.
+ // Another HTML injection for each inline node that covers inline HTML.
+ atom.grammars.addInjectionPoint('source.gfm.inline', {
+ type: 'inline',
language(node) {
- for (let child of textChildren(node)) {
- if (hyperlink.test(child)) {
- return 'hyperlink';
- }
- }
- return null;
+ // Attempt to cut down on the number of injection layers by returning
+ // `html` here only when there are HTML nodes in the inline tree.
+ let html = node.descendantsOfType('html_tag');
+ return html.length > 0 ? 'html' : undefined;
},
content(node) {
- return textChildren(node);
- }
+ return node.descendantsOfType('html_tag');
+ },
+ includeChildren: true
});
+};
+exports.consumeHyperlinkInjection = (hyperlink) => {
+ hyperlink.addInjectionPoint('source.gfm.inline', {
+ types: ['inline'],
+ content: (node) => node,
+ includeChildren: true
+ });
};
diff --git a/packages/language-hyperlink/lib/main.js b/packages/language-hyperlink/lib/main.js
index 16223af3a5..32cb002abd 100644
--- a/packages/language-hyperlink/lib/main.js
+++ b/packages/language-hyperlink/lib/main.js
@@ -49,7 +49,8 @@ module.exports = {
content(node) {
return options.content ? options.content(node) : node;
},
- languageScope: null
+ languageScope: options.languageScope ?? null,
+ includeChildren: options.includeChildren ?? false
});
}
},
diff --git a/packages/language-javascript/grammars/tree-sitter/highlights.scm b/packages/language-javascript/grammars/tree-sitter/highlights.scm
index 22e14f96cd..3fa44df58c 100644
--- a/packages/language-javascript/grammars/tree-sitter/highlights.scm
+++ b/packages/language-javascript/grammars/tree-sitter/highlights.scm
@@ -573,15 +573,27 @@
(export_statement
(identifier) @variable.other.assignment.export.js)
-; The "*" in `import * as Foo`
+; The "*" in `import * as Foo from 'bar'`
(import_clause
(namespace_import "*" @variable.other.assignment.import.all.js))
-; The "Foo" in `import * as Foo`
+; The "Foo" in `import * as Foo from 'bar'`
(import_clause
(namespace_import
(identifier) @variable.other.assignment.import.alias.js))
+; The "*" in `export * from 'bar'`
+(export_statement "*" @variable.other.assignment.export.all.js)
+
+; The "*" in `export * as Foo from 'bar'`
+(export_statement
+ (namespace_export "*" @variable.other.assignment.export.all.js))
+
+; The "*" in `export * as Foo from 'bar'`
+(export_statement
+ (namespace_export
+ (identifier) @variable.other.assignment.export.alias.js))
+
; COMMENTS
; ========
diff --git a/packages/language-python/grammars/ts/highlights.scm b/packages/language-python/grammars/ts/highlights.scm
index 03e8db4840..0e1c7a5ec1 100644
--- a/packages/language-python/grammars/ts/highlights.scm
+++ b/packages/language-python/grammars/ts/highlights.scm
@@ -37,13 +37,13 @@
(call
function: (identifier) @support.type.constructor.python
- (#match? @support.type.constructor.python "^[A-Z][a-z_]+")
+ (#match? @support.type.constructor.python "^[A-Z][A-Za-z_]+")
(#set! capture.final true))
(call
function: (attribute
attribute: (identifier) @support.type.constructor.python)
- (#match? @support.type.constructor.python "^[A-Z][a-z_]+")
+ (#match? @support.type.constructor.python "^[A-Z][A-Za-z_]+")
(#set! capture.final true))
(call
diff --git a/packages/language-python/grammars/ts/indents.scm b/packages/language-python/grammars/ts/indents.scm
index 670948ed16..9753893079 100644
--- a/packages/language-python/grammars/ts/indents.scm
+++ b/packages/language-python/grammars/ts/indents.scm
@@ -1,10 +1,16 @@
+; Excluding dictionary key/value separators…
(dictionary
(pair ":" @_IGNORE_
- (#set! capture.final true)))
+ (#set! capture.final)))
+; …lambda functions…
((lambda ":" @_IGNORE_)
- (#set! capture.final true))
+ (#set! capture.final))
+; …and type annotations on function parameters/class members…
+(":" @_IGNORE_ . (type) (#set! capture.final))
+
+; …all other colons we encounter hint at upcoming indents.
":" @indent
; When typing out "else" after an "if" statement, tree-sitter-python won't
diff --git a/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson b/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson
index d82927921a..bec61a5fe4 100644
--- a/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson
+++ b/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson
@@ -38,7 +38,7 @@ firstLineRegex: [
# Try to match `bash` exactly, or failing that, anything that ends in `sh`
# (for zsh/fish/etc.).
-injectionRegex: '(^(bash|BASH)$|sh^|SH^)'
+injectionRegex: '(^(bash|BASH)$|sh$|SH$)'
treeSitter:
parserSource: 'github:tree-sitter/tree-sitter-bash#8df9ea875d557a150d025d3a15b6e6a58624379a'
diff --git a/packages/language-typescript/grammars/common/highlights.scm b/packages/language-typescript/grammars/common/highlights.scm
index f34c12e50e..5b9d7cf535 100644
--- a/packages/language-typescript/grammars/common/highlights.scm
+++ b/packages/language-typescript/grammars/common/highlights.scm
@@ -17,6 +17,18 @@
(namespace_import
(identifier) @variable.other.assignment.import.namespace._LANG_)
+; The "*" in `export * from 'bar'`
+(export_statement "*" @variable.other.assignment.export.all.js)
+
+; The "*" in `export * as Foo from 'bar'`
+(export_statement
+ (namespace_export "*" @variable.other.assignment.export.all.js))
+
+; The "*" in `export * as Foo from 'bar'`
+(export_statement
+ (namespace_export
+ (identifier) @variable.other.assignment.export.alias.js))
+
; The "Foo" in `export { Foo }`
(export_specifier
name: (identifier) @variable.other.assignment.export._LANG_)
@@ -395,9 +407,17 @@
; TODO: We could add a special scope name to the entire suite of DOM types, but
; I don't have the strength for that right now.
-;
-((type_identifier) @support.storage.other.type._LANG_
- )
+; The "bar" in `const foo: bar.Baz`.
+(nested_type_identifier
+ module: (identifier) @support.storage.other.property._LANG_)
+
+; The "bar" and "thud" in `const foo: bar.thud.Baz`.
+(nested_identifier
+ (identifier) @support.storage.other.property._LANG_
+ (#is? test.descendantOfType "type_annotation"))
+
+; Any other type identifiers; the "Bar" in `const foo: Bar`.
+(type_identifier) @support.storage.other.type._LANG_
; SUPPORT
; =======
@@ -739,8 +759,8 @@
; Interpolations inside of template strings.
(template_substitution
- "${" @punctuation.definition.template-expression.begin._LANG_
- "}" @punctuation.definition.template-expression.end._LANG_
+ "${" @punctuation.section.embedded.begin._LANG_
+ "}" @punctuation.section.embedded.end._LANG_
) @meta.embedded.line.interpolation._LANG_
(string
@@ -793,6 +813,22 @@
"debugger"
] @keyword.control._TYPE_._LANG_
+
+; REGEX
+; =====
+
+(regex) @string.regexp.js
+(regex
+ "/" @punctuation.definition.string.begin.js
+ (#is? test.first))
+
+(regex
+ "/" @punctuation.definition.string.end.js
+ (#is? test.last))
+
+(regex_flags) @keyword.other.js
+
+
; OPERATORS
; =========
@@ -925,6 +961,10 @@
; All other sorts of blocks.
(statement_block) @meta.block._LANG_
+; The entirety of a type annotation, no matter how simple or complex (e.g.,
+; `Event`, `foo.Event`, `foo.bar.Event, foo.Event