hi @marijn , thank you for providing such a useful feature with blockwrapper—it has been a great help in our development.
I noticed that when multiple blockwrappers are nested at the same position, their rendering order seems unstable. It would be great to have a parameter or configuration to ensure a stable order, for example by allowing explicit priorities.
Here is a small demo illustrating the issue.
import {basicSetup, EditorView} from "codemirror"
import {BlockWrapper, ViewPlugin} from "@codemirror/view"
import {Range} from "@codemirror/state"
import {syntaxTree} from "@codemirror/language"
import {markdown} from "@codemirror/lang-markdown"
import {languages} from "@codemirror/language-data"
let view = new EditorView({
doc: "Hello\n\n```javascript\nlet x = 'y'\n```\nWorld\n```javascript\nlet x = 'y'\n```",
extensions: [
basicSetup,
markdown({codeLanguages: languages}),
EditorView.theme({
".cm-fenced-code-block-red > .cm-line": {
backgroundColor: "rgba(255 0 0 / 0.5)"
},
".cm-fenced-code-block-blue > .cm-line": {
backgroundColor: "rgba(0 0 255 / 0.5)"
},
".cm-fenced-code-block-green > .cm-line": {
backgroundColor: "rgba(0 255 0 / 0.5)"
}
}),
ViewPlugin.fromClass(class {}, {
provide: () => EditorView.blockWrappers.of(view => {
const ranges = []
for (const {from, to} of view.visibleRanges) {
syntaxTree(view.state).iterate({
from, to,
enter: node => {
if (node.name === 'FencedCode') {
ranges.push(BlockWrapper.create({
tagName: 'div',
attributes: {'class': 'cm-fenced-code-block-red'}
}).range(node.from, node.to))
ranges.push(BlockWrapper.create({
tagName: 'div',
attributes: {'class': 'cm-fenced-code-block-blue'}
}).range(node.from, node.to))
ranges.push(BlockWrapper.create({
tagName: 'div',
attributes: {'class': 'cm-fenced-code-block-green'}
}).range(node.from, node.to))
}
}
})
}
return BlockWrapper.set(ranges)
})
})
],
parent: document.body
})
