Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/svelsky. editable svelte website with bluesky pds as backend flo-bit.dev/svelsky
Something went wrong. Try again.
3.5 kB · 125 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core';import { Link } from '@tiptap/extension-link';
import type { LinkOptions } from '@tiptap/extension-link';
/** * The input regex for Markdown links with title support, and multiple quotation marks (required * in case the `Typography` extension is being included). */const inputRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)$/i;
/** * The paste regex for Markdown links with title support, and multiple quotation marks (required * in case the `Typography` extension is being included). */const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)/gi;
/** * Input rule built specifically for the `Link` extension, which ignores the auto-linked URL in * parentheses (e.g., `(https://doist.dev)`). * * @see https://github.com/ueberdosis/tiptap/discussions/1865 */function linkInputRule(config: Parameters<typeof markInputRule>[0]) { const defaultMarkInputRule = markInputRule(config);
return new InputRule({ find: config.find, handler(props) { const { tr } = props.state;
defaultMarkInputRule.handler(props); tr.setMeta('preventAutolink', true); } });}
/** * Paste rule built specifically for the `Link` extension, which ignores the auto-linked URL in * parentheses (e.g., `(https://doist.dev)`). This extension was inspired from the multiple * implementations found in a Tiptap discussion at GitHub. * * @see https://github.com/ueberdosis/tiptap/discussions/1865 */function linkPasteRule(config: Parameters<typeof markPasteRule>[0]) { const defaultMarkPasteRule = markPasteRule(config);
return new PasteRule({ find: config.find, handler(props) { const { tr } = props.state;
defaultMarkPasteRule.handler(props); tr.setMeta('preventAutolink', true); } });}
/** * The options available to customize the `RichTextLink` extension. */type RichTextLinkOptions = LinkOptions;
/** * Custom extension that extends the built-in `Link` extension to add additional input/paste rules * for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also * adds support for the `title` attribute. */const RichTextLink = Link.extend<RichTextLinkOptions>({ inclusive: false, addOptions() { return { ...this.parent?.(), openOnClick: 'whenNotEditable' }; }, addAttributes() { return { ...this.parent?.(), title: { default: null } }; }, addInputRules() { return [ linkInputRule({ find: inputRegex, type: this.type,
// We need to use `pop()` to remove the last capture groups from the match to // satisfy Tiptap's `markPasteRule` expectation of having the content as the last // capture group in the match (this makes the attribute order important) getAttributes(match) { return { title: match.pop()?.trim(), href: match.pop()?.trim() }; } }) ]; }, addPasteRules() { return [ linkPasteRule({ find: pasteRegex, type: this.type,
// We need to use `pop()` to remove the last capture groups from the match to // satisfy Tiptap's `markInputRule` expectation of having the content as the last // capture group in the match (this makes the attribute order important) getAttributes(match) { return { title: match.pop()?.trim(), href: match.pop()?.trim() }; } }) ]; }});
export { RichTextLink };
export type { RichTextLinkOptions };