tiptap/packages/core/src/inputRules/wrappingInputRule.ts
Philipp Kühn 723b955cec
feat: Integrate input rules and paste rules into the core (#1997)
* refactoring

* improve link regex

* WIP: add new markPasteRule und linkify to image mark

* move copy of inputrule to core

* trigger codeblock inputrule on enter

* refactoring

* add regex match to markpasterulematch

* refactoring

* improve link regex

* WIP: add new markPasteRule und linkify to image mark

* move copy of inputrule to core

* trigger codeblock inputrule on enter

* refactoring

* add regex match to markpasterulematch

* update linkify

* wip

* wip

* log

* wip

* remove debug code

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* rename matcher

* add data to ExtendedRegExpMatchArray

* remove logging

* add code option to marks, prevent inputrules in code mark

* remove link regex

* fix codeblock inputrule on enter

* refactoring

* refactoring

* refactoring

* refactoring

* fix position bug

* add test

* export InputRule and PasteRule

* clean up link demo

* fix types
2021-10-08 15:02:09 +02:00

60 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { InputRule, InputRuleFinder } from '../InputRule'
import { NodeType, Node as ProseMirrorNode } from 'prosemirror-model'
import { findWrapping, canJoin } from 'prosemirror-transform'
import { ExtendedRegExpMatchArray } from '../types'
import callOrReturn from '../utilities/callOrReturn'
/**
* Build an input rule for automatically wrapping a textblock when a
* given string is typed. When using a regular expresion youll
* probably want the regexp to start with `^`, so that the pattern can
* only occur at the start of a textblock.
*
* `type` is the type of node to wrap in.
*
* By default, if theres a node with the same type above the newly
* wrapped node, the rule will try to join those
* two nodes. You can pass a join predicate, which takes a regular
* expression match and the node before the wrapped node, and can
* return a boolean to indicate whether a join should happen.
*/
export default function wrappingInputRule(config: {
find: InputRuleFinder,
type: NodeType,
getAttributes?:
| Record<string, any>
| ((match: ExtendedRegExpMatchArray) => Record<string, any>)
| false
| null
,
joinPredicate?: (match: ExtendedRegExpMatchArray, node: ProseMirrorNode) => boolean,
}) {
return new InputRule({
find: config.find,
handler: ({ state, range, match }) => {
const attributes = callOrReturn(config.getAttributes, undefined, match) || {}
const tr = state.tr.delete(range.from, range.to)
const $start = tr.doc.resolve(range.from)
const blockRange = $start.blockRange()
const wrapping = blockRange && findWrapping(blockRange, config.type, attributes)
if (!wrapping) {
return null
}
tr.wrap(blockRange, wrapping)
const before = tr.doc.resolve(range.from - 1).nodeBefore
if (
before
&& before.type === config.type
&& canJoin(tr.doc, range.from - 1)
&& (!config.joinPredicate || config.joinPredicate(match, before))
) {
tr.join(range.from - 1)
}
},
})
}