···1-import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core';
2-import { Link } from '@tiptap/extension-link';
3-4-import type { LinkOptions } from '@tiptap/extension-link';
5-6-/**
7- * The input regex for Markdown links with title support, and multiple quotation marks (required
8- * in case the `Typography` extension is being included).
9- */
10-const inputRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)$/i;
11-12-/**
13- * The paste regex for Markdown links with title support, and multiple quotation marks (required
14- * in case the `Typography` extension is being included).
15- */
16-const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)/gi;
17-18-/**
19- * Input rule built specifically for the `Link` extension, which ignores the auto-linked URL in
20- * parentheses (e.g., `(https://doist.dev)`).
21- *
22- * @see https://github.com/ueberdosis/tiptap/discussions/1865
23- */
24-function linkInputRule(config: Parameters<typeof markInputRule>[0]) {
25- const defaultMarkInputRule = markInputRule(config);
26-27- return new InputRule({
28- find: config.find,
29- handler(props) {
30- const { tr } = props.state;
31-32- defaultMarkInputRule.handler(props);
33- tr.setMeta('preventAutolink', true);
34- }
35- });
36-}
37-38-/**
39- * Paste rule built specifically for the `Link` extension, which ignores the auto-linked URL in
40- * parentheses (e.g., `(https://doist.dev)`). This extension was inspired from the multiple
41- * implementations found in a Tiptap discussion at GitHub.
42- *
43- * @see https://github.com/ueberdosis/tiptap/discussions/1865
44- */
45-function linkPasteRule(config: Parameters<typeof markPasteRule>[0]) {
46- const defaultMarkPasteRule = markPasteRule(config);
47-48- return new PasteRule({
49- find: config.find,
50- handler(props) {
51- const { tr } = props.state;
52-53- defaultMarkPasteRule.handler(props);
54- tr.setMeta('preventAutolink', true);
55- }
56- });
57-}
58-59-/**
60- * The options available to customize the `RichTextLink` extension.
61- */
62-type RichTextLinkOptions = LinkOptions;
63-64-/**
65- * Custom extension that extends the built-in `Link` extension to add additional input/paste rules
66- * for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also
67- * adds support for the `title` attribute.
68- */
69-const RichTextLink = Link.extend<RichTextLinkOptions>({
70- inclusive: false,
71- addOptions() {
72- return {
73- ...this.parent?.(),
74- openOnClick: 'whenNotEditable'
75- };
76- },
77- addAttributes() {
78- return {
79- ...this.parent?.(),
80- title: {
81- default: null
82- }
83- };
84- },
85- addInputRules() {
86- return [
87- linkInputRule({
88- find: inputRegex,
89- type: this.type,
90-91- // We need to use `pop()` to remove the last capture groups from the match to
92- // satisfy Tiptap's `markPasteRule` expectation of having the content as the last
93- // capture group in the match (this makes the attribute order important)
94- getAttributes(match) {
95- return {
96- title: match.pop()?.trim(),
97- href: match.pop()?.trim()
98- };
99- }
100- })
101- ];
102- },
103- addPasteRules() {
104- return [
105- linkPasteRule({
106- find: pasteRegex,
107- type: this.type,
108-109- // We need to use `pop()` to remove the last capture groups from the match to
110- // satisfy Tiptap's `markInputRule` expectation of having the content as the last
111- // capture group in the match (this makes the attribute order important)
112- getAttributes(match) {
113- return {
114- title: match.pop()?.trim(),
115- href: match.pop()?.trim()
116- };
117- }
118- })
119- ];
120- }
121-});
122-123-export { RichTextLink };
124-125-export type { RichTextLinkOptions };
···1-export { default as MarkdownItem } from './MarkdownItem.svelte';
2-export { default as MarkdownText } from './MarkdownText.svelte';
3-export { default as MarkdownTextEditor } from './MarkdownTextEditor.svelte';
···1-export { default as PlainTextItem } from './PlainTextItem.svelte';
2-export { default as PlainTextEditor } from './PlainTextEditor.svelte';
3-export { default as PlainText } from './PlainText.svelte';
···1-import Heading from './Heading.svelte';
2-import Subheading from './Subheading.svelte';
3-4-export { Heading, Subheading };
···0000
-16
src/lib/website/foxui/index.ts
···1-import { type ClassValue, clsx } from 'clsx';
2-import { twMerge } from 'tailwind-merge';
3-4-export function cn(...inputs: ClassValue[]) {
5- return twMerge(clsx(inputs));
6-}
7-8-export * from './avatar';
9-export * from './bluesky-login';
10-export * from './button';
11-export * from './heading';
12-export * from './input';
13-export * from './label';
14-export * from './modal';
15-export * from './navbar';
16-export * from './sonner';
···1-import Root, {
2- type InputProps,
3- type InputSize,
4- type InputVariant,
5- inputVariants
6-} from './Input.svelte';
7-8-export { type InputProps, Root as Input, inputVariants, type InputSize, type InputVariant };