Scroll code block into view after fence input rule

This commit is contained in:
Yuri Karamian
2026-08-07 21:50:34 +02:00
parent 23abd0a19a
commit 32ef51161d
2 changed files with 51 additions and 0 deletions
@@ -0,0 +1,49 @@
import { Extension } from '@tiptap/core';
import { Plugin, PluginKey } from '@tiptap/pm/state';
const CODE_FENCE_PATTERN = /^(?:```|~~~)(?:[a-z]+)?$/;
function isInputRulesPlugin(plugin: Plugin) {
return 'isInputRules' in plugin.spec && plugin.spec.isInputRules === true;
}
export function createCodeBlockInputScrollPlugin() {
return new Plugin({
key: new PluginKey('codeBlockInputScroll'),
appendTransaction(transactions, oldState, newState) {
const inputRulesPlugin = oldState.plugins.find(isInputRulesPlugin);
const wasKeyboardInputRule =
inputRulesPlugin !== undefined &&
transactions.some((transaction) => {
const metadata: unknown = transaction.getMeta(inputRulesPlugin);
return (
typeof metadata === 'object' &&
metadata !== null &&
'transform' in metadata &&
metadata.transform === transaction &&
'text' in metadata &&
metadata.text === '\n'
);
});
const { selection } = oldState;
const wasFenceParagraph =
selection.empty &&
selection.$from.parent.type.name === 'paragraph' &&
CODE_FENCE_PATTERN.test(selection.$from.parent.textContent);
const isCodeBlock = newState.selection.$from.parent.type.name === 'codeBlock';
return wasKeyboardInputRule && wasFenceParagraph && isCodeBlock
? newState.tr.scrollIntoView()
: null;
},
});
}
export const CodeBlockInputScroll = Extension.create({
name: 'codeBlockInputScroll',
addProseMirrorPlugins() {
return [createCodeBlockInputScrollPlugin()];
},
});