diff --git a/CHANGELOG.md b/CHANGELOG.md index db0e412168..20adb7ea2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ - Project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) ## [Unreleased] +- Added a new modern tree sitter "test" for highlight query - `ancestorTypeNearerThan` + that matches if it finds the _first_ type as an ancestor, but _not matches_ if + any "other" ancestors are found before +- Syntax quoting and unquoting in Clojure now highlights correctly, and also + highlights full qualified keywords differently than generated ones +- `content` field of addInjectionPoint for modern-tree-sitter now supports a second + `buffer` argument, for better customization if one wants to +- EDN is back to be detected as Clojure (for compatibility) but highlights as EDN +- Fixed syntax quoting on Clojure grammar (newer tree-sitter), fixed some + injection points on Clojure. Added support for highligting metadata, and added + better support for "def" elements (example - don't syntax `default` or + `definition` as a `def`, but highlights `p/defresolver`) ## 1.117.0 diff --git a/packages/language-clojure/grammars/clojure.cson b/packages/language-clojure/grammars/clojure.cson index 2f929ff69b..d712d7094b 100644 --- a/packages/language-clojure/grammars/clojure.cson +++ b/packages/language-clojure/grammars/clojure.cson @@ -2,6 +2,8 @@ 'fileTypes': [ 'boot' 'clj' + 'clje' + 'cljr' 'clj.hl' 'cljc' 'cljs' diff --git a/packages/language-clojure/grammars/tree-sitter-clojure.cson b/packages/language-clojure/grammars/tree-sitter-clojure.cson index b0657b7cd4..41f1ba9359 100644 --- a/packages/language-clojure/grammars/tree-sitter-clojure.cson +++ b/packages/language-clojure/grammars/tree-sitter-clojure.cson @@ -7,15 +7,19 @@ parser: 'tree-sitter-clojure' 'fileTypes': [ 'boot' 'clj' + 'clje' + 'cljr' 'clj.hl' 'cljc' 'cljs' 'cljs.hl' 'cljx' 'clojure' + 'edn' 'bb' 'joke' 'joker' + 'jank' ] 'firstLineMatch': '''(?x) # Hashbang @@ -37,6 +41,11 @@ parser: 'tree-sitter-clojure' ) ''' treeSitter: + parserSource: 'github:mauricioszabo/tree-sitter-clojure#inner-strings' grammar: 'ts/grammar.wasm' - highlightsQuery: 'ts/highlights.scm' + highlightsQuery: [ + 'ts/highlights.scm' + 'ts/edn-highlights.scm' + ] foldsQuery: 'ts/folds.scm' + tagsQuery: 'ts/tags.scm' diff --git a/packages/language-clojure/grammars/tree-sitter-edn.cson b/packages/language-clojure/grammars/tree-sitter-edn.cson index c3368c9ece..53ca204175 100644 --- a/packages/language-clojure/grammars/tree-sitter-edn.cson +++ b/packages/language-clojure/grammars/tree-sitter-edn.cson @@ -1,13 +1,16 @@ name: 'Clojure EDN' scopeName: 'source.edn' type: 'modern-tree-sitter' -injectionRegExp: '^source-edn$' +injectionRegExp: '^source-clojure-edn$' parser: 'tree-sitter-clojure' fileTypes: [ - 'edn' ] treeSitter: + parserSource: 'github:mauricioszabo/tree-sitter-clojure#inner-strings' grammar: 'ts/grammar.wasm' - highlightsQuery: 'ts/edn-highlights.scm' + highlightsQuery: [ + 'ts/edn-only-highlights.scm' + 'ts/edn-highlights.scm' + ] foldsQuery: 'ts/folds.scm' diff --git a/packages/language-clojure/grammars/tree-sitter-quoted.cson b/packages/language-clojure/grammars/tree-sitter-quoted.cson deleted file mode 100644 index 73c7513b59..0000000000 --- a/packages/language-clojure/grammars/tree-sitter-quoted.cson +++ /dev/null @@ -1,9 +0,0 @@ -scopeName: 'source.quoted.clojure' -type: 'modern-tree-sitter' -injectionRegExp: '^source-quoted-clojure$' -parser: 'tree-sitter-clojure' - -treeSitter: - grammar: 'ts/grammar.wasm' - highlightsQuery: 'ts/edn-highlights.scm' - foldsQuery: 'ts/folds.scm' diff --git a/packages/language-clojure/grammars/ts/edn-highlights.scm b/packages/language-clojure/grammars/ts/edn-highlights.scm index f5dcb2e976..38d0d0018f 100644 --- a/packages/language-clojure/grammars/ts/edn-highlights.scm +++ b/packages/language-clojure/grammars/ts/edn-highlights.scm @@ -1,9 +1,4 @@ ;; Collections -(list_lit - "(" @punctuation.section.list.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") - ")" @punctuation.section.list.end) -@meta.list - (vec_lit "[" @punctuation.section.vector.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") "]" @punctuation.section.vector.end) @@ -19,9 +14,19 @@ "}" @punctuation.section.set.end) @meta.set +(meta_lit) @meta.metadata.clojure + ((regex_lit) @string.regexp (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) ((sym_lit) @meta.symbol (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) ((kwd_lit) @constant.keyword (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) +(str_lit + "\"" @punctuation.definition.string.begin.clojure + (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + (#is? test.first)) +(str_lit + "\"" @punctuation.definition.string.end.clojure + (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + (#is? test.last)) ((str_lit) @string.quoted.double (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) ((num_lit) @constant.numeric (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) ((nil_lit) @constant.language (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) diff --git a/packages/language-clojure/grammars/ts/edn-only-highlights.scm b/packages/language-clojure/grammars/ts/edn-only-highlights.scm new file mode 100644 index 0000000000..f7c4aa7931 --- /dev/null +++ b/packages/language-clojure/grammars/ts/edn-only-highlights.scm @@ -0,0 +1,4 @@ +(list_lit + "(" @punctuation.section.list.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + ")" @punctuation.section.list.end) +@meta.list diff --git a/packages/language-clojure/grammars/ts/grammar.wasm b/packages/language-clojure/grammars/ts/grammar.wasm index e50647edd9..d9cf4c2c2a 100755 Binary files a/packages/language-clojure/grammars/ts/grammar.wasm and b/packages/language-clojure/grammars/ts/grammar.wasm differ diff --git a/packages/language-clojure/grammars/ts/highlights.scm b/packages/language-clojure/grammars/ts/highlights.scm index b2a34546aa..d031cdda01 100644 --- a/packages/language-clojure/grammars/ts/highlights.scm +++ b/packages/language-clojure/grammars/ts/highlights.scm @@ -1,4 +1,44 @@ +;; "Special" things +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData clojure.dismissTag) + . + (sym_lit) @storage.control (#eq? @storage.control "do")) + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData clojure.dismissTag) + . + (sym_lit) @keyword.control.conditional.if (#eq? @keyword.control.conditional.if "if")) + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData clojure.dismissTag) + . + (sym_lit) @keyword.control.conditional.when (#eq? @keyword.control.conditional.when "when")) + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData clojure.dismissTag) + . + (sym_lit) @keyword.control.js.clojure (#eq? @keyword.control.js.clojure "js*")) + +;; Syntax quoting +((syn_quoting_lit) + @meta.syntax-quoted + (#is? test.ancestorTypeNearerThan "syn_quoting_lit unquoting_lit")) + +((sym_lit) @meta.symbol.syntax-quoted + (#is? test.ancestorTypeNearerThan "syn_quoting_lit unquoting_lit") + (#match? @meta.symbol.syntax-quoted "[^#]$")) + +((sym_lit) @meta.symbol.generated + (#is? test.ancestorTypeNearerThan "syn_quoting_lit unquoting_lit") + (#match? @meta.symbol.generated "#$")) + ;; Function calls +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData clojure.dismissTag) + . + (sym_lit) @keyword.control.conditional.cond (#match? @keyword.control.conditional.cond "^cond(|.|-{1,2}>)$")) + +;; Other function calls (anon_fn_lit "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") . @@ -48,14 +88,22 @@ "(" . (kwd_lit) @invalid.deprecated (#eq? @invalid.deprecated ":use") - (#is? test.descendantOfNodeWithData isNamespace) - (#is? test.config language-clojure.markDeprecations)) + (#is? test.config language-clojure.markDeprecations) + (#is? test.descendantOfNodeWithData isNamespace)) ;; Definition (list_lit "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") . - (sym_lit) @keyword.control (#match? @keyword.control "^def") + (sym_lit) @keyword.control (#match? @keyword.control "^def(on[^\s]*|test|macro|n|n-|protocol|record|struct|)$") + . + (sym_lit) @meta.definition.global @entity.global + ")" @punctuation.section.expression.end) + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "/def") . (sym_lit) @meta.definition.global @entity.global ")" @punctuation.section.expression.end) @@ -76,39 +124,3 @@ (sym_lit) @keyword.control (#eq? @keyword.control "comment") (#is-not? test.config language-clojure.commentTag) ")" @punctuation.section.expression.end) - -;;; COPY-PASTED from edn-highlights. -;; IF you need to add something here, add to edn-highlights -;; and then paste here, but DON'T PASTE the first `list_lit` - -;; Collections -(vec_lit - "[" @punctuation.section.vector.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") - "]" @punctuation.section.vector.end) -@meta.vector - -(map_lit - "{" @punctuation.section.map.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") - "}" @punctuation.section.map.end) -@meta.map - -(set_lit - ("#" "{") @punctuation.section.set.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") - "}" @punctuation.section.set.end) -@meta.set - -((regex_lit) @string.regexp (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((sym_lit) @meta.symbol (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((kwd_lit) @constant.keyword (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((str_lit) @string.quoted.double (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((num_lit) @constant.numeric (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((nil_lit) @constant.language (#is-not? test.descendantOfNodeWithData "clojure.dismissTag")) -((bool_lit) @constant.language (#is-not? test.descendantOfNodeWithData clojure.dismissTag)) -(comment) @comment.line.semicolon -((dis_expr) - @comment.block.clojure - (#is? test.config language-clojure.dismissTag) - (#set! clojure.dismissTag true) - (#set! capture.final true)) - -("ERROR" @invalid.illegal) diff --git a/packages/language-clojure/grammars/ts/tags.scm b/packages/language-clojure/grammars/ts/tags.scm new file mode 100644 index 0000000000..f5f7e60bc6 --- /dev/null +++ b/packages/language-clojure/grammars/ts/tags.scm @@ -0,0 +1,47 @@ +(list_lit + "(" (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "defmacro") + . + (sym_lit) @name + ")") @definition.constructor + +(list_lit + "(" (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "def(protocol|struct|record)") + . + (sym_lit) @name + ")") @definition.struct + +(list_lit + "(" (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "^def(on[^\s]*|test|macro|n|n-)$") + . + (sym_lit) @name + ")") @definition.function + +(list_lit + "(" (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "^def(on[^\s]*|test|macro|n|n-)$") + . + (sym_lit) @name + ")") @definition.variable + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "/def.") + . + (sym_lit) @name + ")") @definition.function + +(list_lit + "(" @punctuation.section.expression.begin (#is-not? test.descendantOfNodeWithData "clojure.dismissTag") + . + (sym_lit) @keyword.control (#match? @keyword.control "/def") + . + (sym_lit) @name + ")") @definition.variable diff --git a/packages/language-clojure/lib/main.js b/packages/language-clojure/lib/main.js index 48090ef4db..8a1bb3b760 100644 --- a/packages/language-clojure/lib/main.js +++ b/packages/language-clojure/lib/main.js @@ -1,39 +1,50 @@ +const path = require('path'); + exports.activate = function() { if (!atom.grammars.addInjectionPoint) return; + const notDisChild = (node) => { + let parent = node.parent + while(parent) { + if(parent.type === 'dis_expr') return null + parent = parent.parent + } + return node + } + atom.grammars.addInjectionPoint('source.clojure', { type: 'quoting_lit', - language: () => 'source-edn', - content: (node) => { - let parent = node.parent - while(parent) { - if(parent.type === 'dis_expr') return null - parent = parent.parent - } - return node - }, + language: () => 'source-clojure-edn', + content: notDisChild, includeChildren: true, - languageScope: 'source.edn', + languageScope: 'source.clojure', coverShallowerScopes: true }); atom.grammars.addInjectionPoint('source.clojure', { - type: 'syn_quoting_lit', - language: () => 'source-quoted-clojure', - content: (node) => node, + type: 'source', + language: () => 'source-clojure-edn', + content: (node, buffer) => { + if (path.extname(buffer.getPath() ?? '') === '.edn') { + return node + } + }, includeChildren: true, - languageScope: 'source.quoted.clojure', + languageScope: 'source.clojure', coverShallowerScopes: true }); - ['unquoting_lit', 'unquote_splicing_lit'].forEach(scope => { - atom.grammars.addInjectionPoint('source.quoted.clojure', { - type: scope, - language: () => 'source-clojure', - content: (node) => node, - includeChildren: true, - languageScope: 'source.clojure', - coverShallowerScopes: true - }); - }) + atom.grammars.addInjectionPoint('source.clojure', { + type: 'list_lit', + language(node) { + if(node.children[1].text === 'js*') { + return 'javascript' + } + }, + content(node) { + if(node.children[2].type === 'str_lit') { + return node.children[2].children[1]; + } + }, + }); } diff --git a/packages/language-clojure/settings/language-clojure.cson b/packages/language-clojure/settings/language-clojure.cson index 5df9983685..71e5a73ad6 100644 --- a/packages/language-clojure/settings/language-clojure.cson +++ b/packages/language-clojure/settings/language-clojure.cson @@ -1,6 +1,7 @@ '.source.clojure': 'editor': 'commentStart': '; ' + 'nonWordCharacters': '/\\()"\':,;~^[]{}`' 'commentDelimiters': 'line': ';' 'autocomplete': diff --git a/packages/language-clojure/spec/fixtures/tokens.clj b/packages/language-clojure/spec/fixtures/tokens.clj index 065de51cf6..f49c3e5a3a 100644 --- a/packages/language-clojure/spec/fixtures/tokens.clj +++ b/packages/language-clojure/spec/fixtures/tokens.clj @@ -18,10 +18,41 @@ ; ^ !entity.name.function ; ^ constant.numeric +(deftest abc (+ a b)) +; ^ keyword.control +; ^ entity.global + +(defmacro abc [a b]) +; ^ keyword.control +; ^ entity.global + +(defonce a "A STRING") + ; <- keyword.control + ; ^ entity.global + +(defaults a) +; ^ !keyword.control +; ^ !entity.global + +(s/defn foobar [a b]) +; ^ keyword.control +; ^ entity.global + +(defprotocol FooBar + ; ^ keyword.control + ; ^ entity.global + (-eq [this other])) + +(defrecord Lol [a b]) + ; ^ keyword.control + ; ^ entity.global + (def a "A STRING") ; <- keyword.control ; ^ entity.global + ; ^ punctuation.definition.string.begin ; ^ string.quoted.double + ; ^ punctuation.definition.string.end #{'foo} ; <- punctuation.section.set.begin @@ -72,12 +103,19 @@ error/ ; ^ meta.symbol ; ^ !entity.name.function -`(call param ~(call)) +`(call param param# ~(call something param#)) ; ^ meta.symbol -; ^ !entity.name.function -; ^ meta.symbol -; ^ !entity.name.function -; ^ entity.name.function +; ^ entity.name.function +; ^ meta.symbol.syntax-quoted +; ^ meta.symbol.generated +; ^ !meta.symbol.syntax-quoted +; ^ entity.name.function +; ^ !meta.syntax-quoted +; ^ !meta.symbol.syntax-quoted +; ^ !meta.symbol.generated +(call param param#) +; ^ !meta.symbol.syntax-quoted +; ^ !meta.symbol.generated ;; Comments ; ^ comment.line.semicolon @@ -109,3 +147,57 @@ error/ (ns other.namespace (:use [foo.bar])) ; ^ invalid.deprecated + +^{:some :meta} (def foo 10) +; ^ meta.metadata.clojure + +#_ +(+ '1 `(+ ba)) +; ^ comment.block +; ^ !constant.numeric +; ^ !punctuation +; ^ comment.block +; ^ !constant.keyword + +;; Special forms (core language features) +(do :foo) +; ^ storage.control +#_ +(do :foo) +; ^ !storage.control +(if true 10) +; ^ keyword.control.conditional.if +#_ +(if true 10) +; ^ !keyword.control.conditional.if +(when true 10) +; ^ keyword.control.conditional.when +#_ +(when true 10) +; ^ !keyword.control.conditional.when +(cond true 10) +; ^ keyword.control.conditional.cond +#_ +(cond true 10) +; ^ !keyword.control.conditional.cond +(condp true 10) +; ^ keyword.control.conditional.cond +#_ +(condp true 10) +; ^ !keyword.control.conditional.cond +(cond-> true 10) +; ^ keyword.control.conditional.cond +#_ +(cond-> true 10) +; ^ !keyword.control.conditional.cond + +;; Specific stuff +[js* "console.log('abc');", "'foo'"] +; ^ !keyword.control.js.clojure +; ^ !support.class.builtin.console.js + +(js* "console.log('abc');", "'foo'") +; ^ keyword.control.js.clojure +; ^ support.class.builtin.console.js +; ^ string.quoted.single.js +; ^ !string.quoted.single.js diff --git a/packages/language-clojure/spec/fixtures/tokens.edn b/packages/language-clojure/spec/fixtures/tokens.edn new file mode 100644 index 0000000000..c6fda24884 --- /dev/null +++ b/packages/language-clojure/spec/fixtures/tokens.edn @@ -0,0 +1,68 @@ +(ns foobar) +; <- punctuation.section.list.begin +; ^ meta.symbol +; ^ meta.symbol +; ^ punctuation.section.list.end + +"A STRING" +; <- punctuation.definition.string.begin +; ^ string.quoted.double +; ^ punctuation.definition.string.end + +#{foo} +; <- punctuation.section.set.begin +; ^ meta.symbol +; ^ punctuation.section.set.end + +{:key "value"} +; <- punctuation.section.map.begin +; ^ constant.keyword +; ^ meta.map +; ^ punctuation.section.map.end + +;; Primitives +10 +; <- constant.numeric +10.2 +; <- constant.numeric +10M +; <- constant.numeric +10N +; <- constant.numeric +10/2 +; <- constant.numeric +:key +; <- constant.keyword +symbol +; <- meta.symbol +"A string" +; ^ string.quoted.double +#"A regular expression" +; <- string.regexp +nil +; <- constant.language +true +; <- constant.language +false +; <- constant.language +error/ +; <- meta.symbol +; ^ invalid.illegal + +;; Comments +; ^ comment.line.semicolon + +#_ +(+ 1 2 3 (+ 4 5)) +; ^ comment.block +; ^ comment.block + +#_ +(+ '1 '(:foo)) +; ^ comment.block +; ^ !constant.numeric +; ^ comment.block +; ^ !constant.keyword + +^{:some :meta} (def foo 10) +; ^ meta.metadata.clojure diff --git a/packages/language-clojure/spec/tokenizer-spec.js b/packages/language-clojure/spec/tokenizer-spec.js index a12e608511..22a442e8f6 100644 --- a/packages/language-clojure/spec/tokenizer-spec.js +++ b/packages/language-clojure/spec/tokenizer-spec.js @@ -7,8 +7,9 @@ function setConfigForLanguageMode(mode) { } describe('Clojure grammars', () => { - beforeEach(async () => { + await atom.packages.activatePackage('language-c'); + await atom.packages.activatePackage('language-javascript'); await atom.packages.activatePackage('language-clojure'); }); @@ -25,6 +26,12 @@ describe('Clojure grammars', () => { await runGrammarTests(path.join(__dirname, 'fixtures', 'tokens.clj'), /;/) }); + it('tokenizes EDN using modern tree-sitter parser', async () => { + setConfigForLanguageMode('modern-tree-sitter'); + atom.config.set('language-clojure.dismissTag', true); + await runGrammarTests(path.join(__dirname, 'fixtures', 'tokens.edn'), /;/) + }); + it('tokenizes the editor using modern tree-sitter, but with all default configs toggled', async () => { setConfigForLanguageMode('modern-tree-sitter'); atom.config.set('language-clojure.dismissTag', false); diff --git a/src/scope-resolver.js b/src/scope-resolver.js index bd89e086e6..8e8df72fae 100644 --- a/src/scope-resolver.js +++ b/src/scope-resolver.js @@ -745,6 +745,20 @@ ScopeResolver.TESTS = { return false; }, + // Passes if there's an ancestor, but fails if the ancestor type matches + // the second,third,etc argument + ancestorTypeNearerThan(node, types) { + let [target, ...rejected] = types.split(/\s+/); + rejected = new Set(rejected) + let current = node; + while (current.parent) { + current = current.parent; + if (rejected.has(current.type)) { return false; } + if (target === current.type) { return true; } + } + return false; + }, + // Passes if this node has at least one descendant of the given type(s). ancestorOfType(node, type) { let target = type.includes(' ') ? type.split(/\s+/) : type; diff --git a/src/tree-sitter-language-mode.js b/src/tree-sitter-language-mode.js index 136dd82ae5..d4970bca82 100644 --- a/src/tree-sitter-language-mode.js +++ b/src/tree-sitter-language-mode.js @@ -875,7 +875,7 @@ class LanguageLayer { ); if (!grammar) continue; - const contentNodes = injectionPoint.content(node); + const contentNodes = injectionPoint.content(node, this.buffer); if (!contentNodes) continue; const injectionNodes = [].concat(contentNodes); diff --git a/src/wasm-tree-sitter-language-mode.js b/src/wasm-tree-sitter-language-mode.js index b28fbc8793..a893985d04 100644 --- a/src/wasm-tree-sitter-language-mode.js +++ b/src/wasm-tree-sitter-language-mode.js @@ -4351,7 +4351,7 @@ class LanguageLayer { // Does it offer us a node, or array of nodes, which a new injection // layer should use for its content? - const contentNodes = injectionPoint.content(node); + const contentNodes = injectionPoint.content(node, this.buffer); if (!contentNodes) { continue; } const injectionNodes = [].concat(contentNodes);