Thanks @marijn.
For those landing here, you’ll find my full code below (comments welcome). It dynamically adds the <small>
tag to the end of any text following the last ‘(’ in a heading. For example:
<h2>Hello World! (I mean it!)</h2>
becomes:
<h2>Hello World! <small>(I mean it!)</small></h2>
This is the code to add the <small>
tag to the schema:
const { nodes, marks } = require('prosemirror-schema-basic')
marks.small = {
excludes: '_', // Prevent any other mark from being applied to this mark
parseDOM: [{ tag: 'small' }],
toDOM: function toDOM(node) {
return ['small', { style: 'font-size:10px;color:dodgerblue' }]
}
}
mySchema = new Schema({ nodes, marks })
The plugin:
const { Plugin } = require("prosemirror-state")
const addSmallMark = new Plugin({
appendTransaction(tr, oldState, newState) {
// Initialize an empty transaction. We will enrich it so that, when applied,
// it adds the <small> tag to the end of any text following the last '('
// in a heading.
let newTr = newState.tr
// Loop through the transactions
_.each(tr, transaction => {
// Loop through the steps
_.each(transaction.steps, step => {
// Loop through positions affected by the step
step.getMap().forEach((oldStart, oldEnd, newStart, newEnd) => {
// Loop through nodes affected by the transaction in the new state
newState.doc.nodesBetween(newStart, newEnd, (parentNode, parentPos) => {
// We consider headings only
if (parentNode.type.name !== 'heading')
return
// Loop through children nodes of the heading
parentNode.forEach((childNode, childOffset) => {
// We consider text nodes only
if (!childNode.isText)
return
// See if the child node has a '(' near the end. If it doesn't, quit
const relativePos = childNode.text.lastIndexOf('(')
if (relativePos === -1)
return
// If it does, remove any <small> style up to the '(' and add
// a <small> style from the '(' to the end of the heading
const absolutePos = parentPos + childOffset + relativePos + 1 // Why +1 ?
const mark = mySchema.mark('small')
newTr = newTr.removeMark(parentPos, absolutePos, mark)
newTr = newTr.addMark(absolutePos, parentPos + parentNode.nodeSize, mark)
})
})
})
})
})
// Apply the transaction we have jsut built
return newTr
}
})