···11-import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core';
22-import { Link } from '@tiptap/extension-link';
33-44-import type { LinkOptions } from '@tiptap/extension-link';
55-66-/**
77- * The input regex for Markdown links with title support, and multiple quotation marks (required
88- * in case the `Typography` extension is being included).
99- */
1010-const inputRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)$/i;
1111-1212-/**
1313- * The paste regex for Markdown links with title support, and multiple quotation marks (required
1414- * in case the `Typography` extension is being included).
1515- */
1616-const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)/gi;
1717-1818-/**
1919- * Input rule built specifically for the `Link` extension, which ignores the auto-linked URL in
2020- * parentheses (e.g., `(https://doist.dev)`).
2121- *
2222- * @see https://github.com/ueberdosis/tiptap/discussions/1865
2323- */
2424-function linkInputRule(config: Parameters<typeof markInputRule>[0]) {
2525- const defaultMarkInputRule = markInputRule(config);
2626-2727- return new InputRule({
2828- find: config.find,
2929- handler(props) {
3030- const { tr } = props.state;
3131-3232- defaultMarkInputRule.handler(props);
3333- tr.setMeta('preventAutolink', true);
3434- }
3535- });
3636-}
3737-3838-/**
3939- * Paste rule built specifically for the `Link` extension, which ignores the auto-linked URL in
4040- * parentheses (e.g., `(https://doist.dev)`). This extension was inspired from the multiple
4141- * implementations found in a Tiptap discussion at GitHub.
4242- *
4343- * @see https://github.com/ueberdosis/tiptap/discussions/1865
4444- */
4545-function linkPasteRule(config: Parameters<typeof markPasteRule>[0]) {
4646- const defaultMarkPasteRule = markPasteRule(config);
4747-4848- return new PasteRule({
4949- find: config.find,
5050- handler(props) {
5151- const { tr } = props.state;
5252-5353- defaultMarkPasteRule.handler(props);
5454- tr.setMeta('preventAutolink', true);
5555- }
5656- });
5757-}
5858-5959-/**
6060- * The options available to customize the `RichTextLink` extension.
6161- */
6262-type RichTextLinkOptions = LinkOptions;
6363-6464-/**
6565- * Custom extension that extends the built-in `Link` extension to add additional input/paste rules
6666- * for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also
6767- * adds support for the `title` attribute.
6868- */
6969-const RichTextLink = Link.extend<RichTextLinkOptions>({
7070- inclusive: false,
7171- addOptions() {
7272- return {
7373- ...this.parent?.(),
7474- openOnClick: 'whenNotEditable'
7575- };
7676- },
7777- addAttributes() {
7878- return {
7979- ...this.parent?.(),
8080- title: {
8181- default: null
8282- }
8383- };
8484- },
8585- addInputRules() {
8686- return [
8787- linkInputRule({
8888- find: inputRegex,
8989- type: this.type,
9090-9191- // We need to use `pop()` to remove the last capture groups from the match to
9292- // satisfy Tiptap's `markPasteRule` expectation of having the content as the last
9393- // capture group in the match (this makes the attribute order important)
9494- getAttributes(match) {
9595- return {
9696- title: match.pop()?.trim(),
9797- href: match.pop()?.trim()
9898- };
9999- }
100100- })
101101- ];
102102- },
103103- addPasteRules() {
104104- return [
105105- linkPasteRule({
106106- find: pasteRegex,
107107- type: this.type,
108108-109109- // We need to use `pop()` to remove the last capture groups from the match to
110110- // satisfy Tiptap's `markInputRule` expectation of having the content as the last
111111- // capture group in the match (this makes the attribute order important)
112112- getAttributes(match) {
113113- return {
114114- title: match.pop()?.trim(),
115115- href: match.pop()?.trim()
116116- };
117117- }
118118- })
119119- ];
120120- }
121121-});
122122-123123-export { RichTextLink };
124124-125125-export type { RichTextLinkOptions };
-3
src/lib/website/components/markdown/index.ts
···11-export { default as MarkdownItem } from './MarkdownItem.svelte';
22-export { default as MarkdownText } from './MarkdownText.svelte';
33-export { default as MarkdownTextEditor } from './MarkdownTextEditor.svelte';
···11-export { default as PlainTextItem } from './PlainTextItem.svelte';
22-export { default as PlainTextEditor } from './PlainTextEditor.svelte';
33-export { default as PlainText } from './PlainText.svelte';
···11-export {
22- default as Button,
33- type ButtonProps,
44- type ButtonSize,
55- type ButtonVariant,
66- buttonVariants
77-} from './Button.svelte';
···11-import Heading from './Heading.svelte';
22-import Subheading from './Subheading.svelte';
33-44-export { Heading, Subheading };
-16
src/lib/website/foxui/index.ts
···11-import { type ClassValue, clsx } from 'clsx';
22-import { twMerge } from 'tailwind-merge';
33-44-export function cn(...inputs: ClassValue[]) {
55- return twMerge(clsx(inputs));
66-}
77-88-export * from './avatar';
99-export * from './bluesky-login';
1010-export * from './button';
1111-export * from './heading';
1212-export * from './input';
1313-export * from './label';
1414-export * from './modal';
1515-export * from './navbar';
1616-export * from './sonner';
···11-import Root, {
22- type InputProps,
33- type InputSize,
44- type InputVariant,
55- inputVariants
66-} from './Input.svelte';
77-88-export { type InputProps, Root as Input, inputVariants, type InputSize, type InputVariant };