Thanks for the fast response
that’s what I was thinking of, I had a go at both approaches yesterday:
undoInputHistory: addToHistory=false
I tried not adding it to the undo stack, but there’s a strange selection error that gets thrown inside history if you
undo twice, then attempt to redo: https://wandering-range.glitch.me/ (https://glitch.com/edit/#!/wandering-range?path=index.js) - could be an issue trying to reapply the undone transaction?
Forking input-rules
I had a go with forking the input-rules - it’s gets a bit tricky as we have the following case where if we wanted to modify the existing code to apply the text first, we need a way of being sure that can apply a transaction to this state rules[i].handler. :
let match = rules[i].match.exec(textBefore)
tr = match && rules[i].handler(state, match, from - (match[0].length - text.length), to)
if (!tr) continue
view.dispatch(tr.setMeta(this, ...));
My first naive attempt obviously failed because the original transaction the handler returned was bound to the state before we inserted the text 
let match = rules[i].match.exec(textBefore)
tr = match && rules[i].handler(state, match, from - (match[0].length - text.length), to)
if (!tr) continue
view.dispatch(view.state.tr.insertText(text));
view.dispatch(tr.setMeta(this, ...));
So I came up with something a little different (I’m so sorry
). I made the InputRule handler accept a transaction (instead of state), and pass it a transaction with the text state already applied (since we’re now applying the text first, the handler needs to know what the doc will look like).
let match = rules[i].match.exec(textBefore)
// Creates a tr with a view of what the doc will/could be
let tr = state.tr.insertText(text) as any;
tr = match && rules[i].handler(tr, match, from - (match[0].length - text.length), to + text.length)
if (!tr) continue
// Applies a new tr (as the old one changed)
view.dispatch(state.tr.insertText(text));
view.dispatch(rules[i].handler(view.state.tr, match!, from - (match![0].length - text.length), to + text.length));
This works - with minor changes to existing input rules - though my spidey-senses may be incorrectly firing when I feel like this isn’t the safest (or nicest way) to achieve this. I’ll probably continue having a look into this to see whether there’s a better way to structure this.
Other thoughts
From playing around with this though (and I’ll prempt this with “this is not a feature request”
) I did wonder whether it’d be possible to use a “HistoryStep” to flag to the history plugin that it should create a new undo marker in the middle of a transaction, i.e.
view.dispatch(
state.tr
.insertText('replacement')
.step(HistoryStep.create())
.replaceRangeWith(...)
)
It does come with the caveat that it doesn’t conceptually fulfil the purpose of a step to transform the document, but I feel it’d be a powerful way to support transactions that want to allow the users to rollback part of it on an undo.