@docs.plus/extension-hyperlink 1.5.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,255 @@
1
+ import { Editor, Mark } from '@tiptap/core';
2
+ import { EditorView } from '@tiptap/pm/view';
3
+ import { Placement } from '@floating-ui/dom';
4
+ export { registerCustomProtocol } from 'linkifyjs';
5
+
6
+ interface LinkProtocolOptions {
7
+ scheme: string;
8
+ optionalSlashes?: boolean;
9
+ }
10
+ type HyperlinkAttributes = {
11
+ href: string | null;
12
+ target: string | null;
13
+ rel: string | null;
14
+ class: string | null;
15
+ title: string | null;
16
+ image: string | null;
17
+ [key: string]: unknown;
18
+ };
19
+ type PreviewHyperlinkOptions = {
20
+ editor: Editor;
21
+ view: EditorView;
22
+ link: HTMLAnchorElement;
23
+ nodePos: number;
24
+ attrs: HyperlinkAttributes;
25
+ linkCoords: {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ };
31
+ validate?: (url: string) => boolean;
32
+ };
33
+ type CreateHyperlinkOptions = {
34
+ editor: Editor;
35
+ extensionName: string;
36
+ attributes: Partial<HyperlinkAttributes>;
37
+ validate?: (url: string) => boolean;
38
+ };
39
+ interface HyperlinkOptions {
40
+ autolink: boolean;
41
+ protocols: Array<LinkProtocolOptions | string>;
42
+ openOnClick: boolean;
43
+ linkOnPaste: boolean;
44
+ HTMLAttributes: Partial<HyperlinkAttributes>;
45
+ popovers: {
46
+ previewHyperlink?: ((options: PreviewHyperlinkOptions) => HTMLElement | null) | null;
47
+ createHyperlink?: ((options: CreateHyperlinkOptions) => HTMLElement | null) | null;
48
+ };
49
+ validate?: (url: string) => boolean;
50
+ }
51
+ declare module '@tiptap/core' {
52
+ interface Commands<ReturnType> {
53
+ hyperlink: {
54
+ editHyperlinkText: (text: string) => ReturnType;
55
+ editHyperlinkHref: (href: string) => ReturnType;
56
+ editHyperlink: (attributes?: {
57
+ newText?: string;
58
+ newURL?: string;
59
+ title?: string;
60
+ image?: string;
61
+ }) => ReturnType;
62
+ setHyperlink: (attributes?: {
63
+ href: string;
64
+ target?: string | null;
65
+ }) => ReturnType;
66
+ unsetHyperlink: () => ReturnType;
67
+ };
68
+ }
69
+ }
70
+ declare const Hyperlink: Mark<HyperlinkOptions, any>;
71
+
72
+ interface FloatingToolbarOptions {
73
+ referenceElement?: HTMLElement;
74
+ coordinates?: {
75
+ x: number;
76
+ y: number;
77
+ width?: number;
78
+ height?: number;
79
+ contextElement?: HTMLElement;
80
+ };
81
+ content: HTMLElement;
82
+ placement?: Placement;
83
+ offset?: number;
84
+ showArrow?: boolean;
85
+ className?: string;
86
+ zIndex?: number;
87
+ onShow?: () => void;
88
+ onHide?: () => void;
89
+ }
90
+ interface FloatingToolbarInstance {
91
+ element: HTMLElement;
92
+ show: () => void;
93
+ hide: () => void;
94
+ destroy: () => void;
95
+ isVisible: () => boolean;
96
+ setContent: (content: HTMLElement) => void;
97
+ updateReference: (referenceElement?: HTMLElement, coordinates?: FloatingToolbarOptions['coordinates']) => void;
98
+ }
99
+ declare const DEFAULT_OFFSET = 8;
100
+ declare function createFloatingToolbar(options: FloatingToolbarOptions): FloatingToolbarInstance;
101
+ declare const getCurrentToolbar: () => FloatingToolbarInstance | null;
102
+ declare const isToolbarVisible: () => boolean;
103
+ declare const hideCurrentToolbar: () => void;
104
+ declare const destroyCurrentToolbar: () => void;
105
+ declare const updateCurrentToolbarPosition: (referenceElement?: HTMLElement, coordinates?: FloatingToolbarOptions["coordinates"]) => void;
106
+
107
+ declare function createHyperlinkPopover(options: CreateHyperlinkOptions): HTMLElement | null;
108
+
109
+ type EditHyperlinkModalOptions = {
110
+ editor: Editor;
111
+ validate?: (url: string) => boolean;
112
+ view: EditorView;
113
+ link: HTMLAnchorElement;
114
+ linkCoords: {
115
+ x: number;
116
+ y: number;
117
+ width: number;
118
+ height: number;
119
+ };
120
+ onBack?: () => void;
121
+ markName?: string;
122
+ };
123
+ declare function editHyperlinkPopover(options: EditHyperlinkModalOptions): void;
124
+
125
+ declare function previewHyperlinkPopover(options: PreviewHyperlinkOptions): HTMLElement;
126
+
127
+ declare const copyToClipboard: (text: string, callback?: (success: boolean) => void) => Promise<boolean>;
128
+
129
+ declare const createHTMLElement: <K extends keyof HTMLElementTagNameMap>(type: K, props?: Partial<HTMLElementTagNameMap[K]>) => HTMLElementTagNameMap[K];
130
+
131
+ interface IconProps {
132
+ size?: number;
133
+ fill?: string;
134
+ }
135
+ declare const Copy: ({ size, fill }?: IconProps) => string;
136
+ declare const LinkOff: ({ size, fill }?: IconProps) => string;
137
+ declare const Link: ({ size, fill }?: IconProps) => string;
138
+ declare const Pencil: ({ size, fill }?: IconProps) => string;
139
+ declare const Title: ({ size, fill }?: IconProps) => string;
140
+
141
+ declare const normalizeHref: (raw: string) => string;
142
+ /**
143
+ * Shape we depend on from a linkifyjs match (plus autolink's
144
+ * manually-constructed special-scheme entries, which also set `type`).
145
+ * Loosened to avoid importing linkifyjs types across the public boundary.
146
+ */
147
+ type LinkifyMatchLike = {
148
+ type: string;
149
+ value: string;
150
+ href: string;
151
+ };
152
+ /**
153
+ * Canonicalize a linkifyjs match for storage.
154
+ *
155
+ * linkifyjs defaults URL matches to `http://…`; we prefer `https://` to
156
+ * stay consistent with the create popover and markdown input rule, so
157
+ * URL matches run through `normalizeHref(value)`. Non-URL matches
158
+ * (emails → `mailto:`, etc.) already carry a meaningful scheme in `href`
159
+ * and are returned unchanged.
160
+ */
161
+ declare const normalizeLinkifyHref: (link: LinkifyMatchLike) => string;
162
+
163
+ /**
164
+ * Special URL schemes and their corresponding SVG icons
165
+ * Based on: https://github.com/bhagyas/app-urls
166
+ */
167
+ type SpecialUrlInfo = {
168
+ type: string;
169
+ title: string;
170
+ /**
171
+ * Icon identifier hint for consumers (e.g. `'HiMail'`, `'FaWhatsapp'`).
172
+ * Not rendered by the extension — consumers map this to their own icon
173
+ * components (React icons, SVG sprites, etc.).
174
+ */
175
+ icon: string;
176
+ category: 'communication' | 'social' | 'productivity' | 'entertainment' | 'shopping' | 'development' | 'apple' | 'other';
177
+ };
178
+ /**
179
+ * Detect special URL and return corresponding info
180
+ */
181
+ declare const getSpecialUrlInfo: (url: string) => SpecialUrlInfo | null;
182
+ /**
183
+ * Get all available categories
184
+ */
185
+ declare const getCategories: () => string[];
186
+ /**
187
+ * Get URLs by category
188
+ */
189
+ declare const getUrlsByCategory: (category: string) => Record<string, SpecialUrlInfo>;
190
+
191
+ /** Schemes that must never be used as link hrefs (XSS vectors). */
192
+ declare const DANGEROUS_SCHEME_RE: RegExp;
193
+ type ValidateURLOptions = {
194
+ customValidator?: (url: string) => boolean;
195
+ };
196
+ /**
197
+ * Validates URLs including both standard web URLs and special app/protocol schemes
198
+ *
199
+ * Supports:
200
+ * - Standard web URLs (http, https, ftp)
201
+ * - Email addresses (mailto:)
202
+ * - Phone numbers (tel:, sms:)
203
+ * - App deep links (whatsapp:, discord:, etc.)
204
+ * - Apple app schemes (maps:, music:, etc.)
205
+ * - Development tools (github:, vscode:, etc.)
206
+ * - Domain-based detection (wa.me, t.me, etc.)
207
+ *
208
+ * For http(s)/ftp(s) URLs, the host must also look real — a TLD dot,
209
+ * `localhost`, or an IP literal. This rejects scheme-prefixed typos like
210
+ * `https://googlecom` that linkifyjs alone would accept.
211
+ *
212
+ * @param url - The URL string to validate
213
+ * @param options - Optional configuration
214
+ * @param options.customValidator - Custom validation function to apply additional checks
215
+ * @returns true if the URL is valid, false otherwise
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * validateURL('https://example.com') // true
220
+ * validateURL('mailto:user@example.com') // true
221
+ * validateURL('tel:+1234567890') // true
222
+ * validateURL('whatsapp://send?text=hello') // true
223
+ * validateURL('wa.me/1234567890') // true
224
+ * validateURL('https://googlecom') // false (no TLD, no localhost, no IP)
225
+ * validateURL('invalid-url') // false
226
+ * ```
227
+ */
228
+ declare const validateURL: (url: string, options?: ValidateURLOptions) => boolean;
229
+ /**
230
+ * Get the scheme/protocol from a URL
231
+ * @param url - The URL to extract scheme from
232
+ * @returns The scheme (e.g., 'https', 'mailto', 'tel') or null if invalid
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * getUrlScheme('https://example.com') // 'https'
237
+ * getUrlScheme('mailto:user@example.com') // 'mailto'
238
+ * getUrlScheme('invalid') // null
239
+ * ```
240
+ */
241
+ declare const getUrlScheme: (url: string) => string | null;
242
+ /**
243
+ * Check if a URL is a special app/protocol scheme (not http/https)
244
+ * @param url - The URL to check
245
+ * @returns true if it's a special scheme, false for standard web URLs
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * isSpecialSchemeUrl('mailto:user@example.com') // true
250
+ * isSpecialSchemeUrl('https://example.com') // false
251
+ * ```
252
+ */
253
+ declare const isSpecialSchemeUrl: (url: string) => boolean;
254
+
255
+ export { Copy, type CreateHyperlinkOptions, DANGEROUS_SCHEME_RE, DEFAULT_OFFSET, type FloatingToolbarInstance, type FloatingToolbarOptions, Hyperlink, type HyperlinkAttributes, type HyperlinkOptions, Link, LinkOff, type LinkProtocolOptions, type LinkifyMatchLike, Pencil, type PreviewHyperlinkOptions, type SpecialUrlInfo, Title, copyToClipboard, createFloatingToolbar, createHTMLElement, createHyperlinkPopover, Hyperlink as default, destroyCurrentToolbar, editHyperlinkPopover, getCategories, getCurrentToolbar, getSpecialUrlInfo, getUrlScheme, getUrlsByCategory, hideCurrentToolbar, isSpecialSchemeUrl, isToolbarVisible, normalizeHref, normalizeLinkifyHref, previewHyperlinkPopover, updateCurrentToolbarPosition, validateURL };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,255 @@
1
- export * from "./hyperlink";
2
- export * from "./helpers/tippyHelper";
3
- export * from "./modals/previewHyperlink";
4
- export * from "./modals/setHyperlink";
5
- import { previewHyperlinkModal } from "./modals/previewHyperlink";
6
- import { setHyperlinkModal } from "./modals/setHyperlink";
7
- import Tooltip from "./helpers/tippyHelper";
8
- import { Hyperlink } from "./hyperlink";
9
- export { Hyperlink, Tooltip, previewHyperlinkModal, setHyperlinkModal };
1
+ import { Editor, Mark } from '@tiptap/core';
2
+ import { EditorView } from '@tiptap/pm/view';
3
+ import { Placement } from '@floating-ui/dom';
4
+ export { registerCustomProtocol } from 'linkifyjs';
5
+
6
+ interface LinkProtocolOptions {
7
+ scheme: string;
8
+ optionalSlashes?: boolean;
9
+ }
10
+ type HyperlinkAttributes = {
11
+ href: string | null;
12
+ target: string | null;
13
+ rel: string | null;
14
+ class: string | null;
15
+ title: string | null;
16
+ image: string | null;
17
+ [key: string]: unknown;
18
+ };
19
+ type PreviewHyperlinkOptions = {
20
+ editor: Editor;
21
+ view: EditorView;
22
+ link: HTMLAnchorElement;
23
+ nodePos: number;
24
+ attrs: HyperlinkAttributes;
25
+ linkCoords: {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ };
31
+ validate?: (url: string) => boolean;
32
+ };
33
+ type CreateHyperlinkOptions = {
34
+ editor: Editor;
35
+ extensionName: string;
36
+ attributes: Partial<HyperlinkAttributes>;
37
+ validate?: (url: string) => boolean;
38
+ };
39
+ interface HyperlinkOptions {
40
+ autolink: boolean;
41
+ protocols: Array<LinkProtocolOptions | string>;
42
+ openOnClick: boolean;
43
+ linkOnPaste: boolean;
44
+ HTMLAttributes: Partial<HyperlinkAttributes>;
45
+ popovers: {
46
+ previewHyperlink?: ((options: PreviewHyperlinkOptions) => HTMLElement | null) | null;
47
+ createHyperlink?: ((options: CreateHyperlinkOptions) => HTMLElement | null) | null;
48
+ };
49
+ validate?: (url: string) => boolean;
50
+ }
51
+ declare module '@tiptap/core' {
52
+ interface Commands<ReturnType> {
53
+ hyperlink: {
54
+ editHyperlinkText: (text: string) => ReturnType;
55
+ editHyperlinkHref: (href: string) => ReturnType;
56
+ editHyperlink: (attributes?: {
57
+ newText?: string;
58
+ newURL?: string;
59
+ title?: string;
60
+ image?: string;
61
+ }) => ReturnType;
62
+ setHyperlink: (attributes?: {
63
+ href: string;
64
+ target?: string | null;
65
+ }) => ReturnType;
66
+ unsetHyperlink: () => ReturnType;
67
+ };
68
+ }
69
+ }
70
+ declare const Hyperlink: Mark<HyperlinkOptions, any>;
71
+
72
+ interface FloatingToolbarOptions {
73
+ referenceElement?: HTMLElement;
74
+ coordinates?: {
75
+ x: number;
76
+ y: number;
77
+ width?: number;
78
+ height?: number;
79
+ contextElement?: HTMLElement;
80
+ };
81
+ content: HTMLElement;
82
+ placement?: Placement;
83
+ offset?: number;
84
+ showArrow?: boolean;
85
+ className?: string;
86
+ zIndex?: number;
87
+ onShow?: () => void;
88
+ onHide?: () => void;
89
+ }
90
+ interface FloatingToolbarInstance {
91
+ element: HTMLElement;
92
+ show: () => void;
93
+ hide: () => void;
94
+ destroy: () => void;
95
+ isVisible: () => boolean;
96
+ setContent: (content: HTMLElement) => void;
97
+ updateReference: (referenceElement?: HTMLElement, coordinates?: FloatingToolbarOptions['coordinates']) => void;
98
+ }
99
+ declare const DEFAULT_OFFSET = 8;
100
+ declare function createFloatingToolbar(options: FloatingToolbarOptions): FloatingToolbarInstance;
101
+ declare const getCurrentToolbar: () => FloatingToolbarInstance | null;
102
+ declare const isToolbarVisible: () => boolean;
103
+ declare const hideCurrentToolbar: () => void;
104
+ declare const destroyCurrentToolbar: () => void;
105
+ declare const updateCurrentToolbarPosition: (referenceElement?: HTMLElement, coordinates?: FloatingToolbarOptions["coordinates"]) => void;
106
+
107
+ declare function createHyperlinkPopover(options: CreateHyperlinkOptions): HTMLElement | null;
108
+
109
+ type EditHyperlinkModalOptions = {
110
+ editor: Editor;
111
+ validate?: (url: string) => boolean;
112
+ view: EditorView;
113
+ link: HTMLAnchorElement;
114
+ linkCoords: {
115
+ x: number;
116
+ y: number;
117
+ width: number;
118
+ height: number;
119
+ };
120
+ onBack?: () => void;
121
+ markName?: string;
122
+ };
123
+ declare function editHyperlinkPopover(options: EditHyperlinkModalOptions): void;
124
+
125
+ declare function previewHyperlinkPopover(options: PreviewHyperlinkOptions): HTMLElement;
126
+
127
+ declare const copyToClipboard: (text: string, callback?: (success: boolean) => void) => Promise<boolean>;
128
+
129
+ declare const createHTMLElement: <K extends keyof HTMLElementTagNameMap>(type: K, props?: Partial<HTMLElementTagNameMap[K]>) => HTMLElementTagNameMap[K];
130
+
131
+ interface IconProps {
132
+ size?: number;
133
+ fill?: string;
134
+ }
135
+ declare const Copy: ({ size, fill }?: IconProps) => string;
136
+ declare const LinkOff: ({ size, fill }?: IconProps) => string;
137
+ declare const Link: ({ size, fill }?: IconProps) => string;
138
+ declare const Pencil: ({ size, fill }?: IconProps) => string;
139
+ declare const Title: ({ size, fill }?: IconProps) => string;
140
+
141
+ declare const normalizeHref: (raw: string) => string;
142
+ /**
143
+ * Shape we depend on from a linkifyjs match (plus autolink's
144
+ * manually-constructed special-scheme entries, which also set `type`).
145
+ * Loosened to avoid importing linkifyjs types across the public boundary.
146
+ */
147
+ type LinkifyMatchLike = {
148
+ type: string;
149
+ value: string;
150
+ href: string;
151
+ };
152
+ /**
153
+ * Canonicalize a linkifyjs match for storage.
154
+ *
155
+ * linkifyjs defaults URL matches to `http://…`; we prefer `https://` to
156
+ * stay consistent with the create popover and markdown input rule, so
157
+ * URL matches run through `normalizeHref(value)`. Non-URL matches
158
+ * (emails → `mailto:`, etc.) already carry a meaningful scheme in `href`
159
+ * and are returned unchanged.
160
+ */
161
+ declare const normalizeLinkifyHref: (link: LinkifyMatchLike) => string;
162
+
163
+ /**
164
+ * Special URL schemes and their corresponding SVG icons
165
+ * Based on: https://github.com/bhagyas/app-urls
166
+ */
167
+ type SpecialUrlInfo = {
168
+ type: string;
169
+ title: string;
170
+ /**
171
+ * Icon identifier hint for consumers (e.g. `'HiMail'`, `'FaWhatsapp'`).
172
+ * Not rendered by the extension — consumers map this to their own icon
173
+ * components (React icons, SVG sprites, etc.).
174
+ */
175
+ icon: string;
176
+ category: 'communication' | 'social' | 'productivity' | 'entertainment' | 'shopping' | 'development' | 'apple' | 'other';
177
+ };
178
+ /**
179
+ * Detect special URL and return corresponding info
180
+ */
181
+ declare const getSpecialUrlInfo: (url: string) => SpecialUrlInfo | null;
182
+ /**
183
+ * Get all available categories
184
+ */
185
+ declare const getCategories: () => string[];
186
+ /**
187
+ * Get URLs by category
188
+ */
189
+ declare const getUrlsByCategory: (category: string) => Record<string, SpecialUrlInfo>;
190
+
191
+ /** Schemes that must never be used as link hrefs (XSS vectors). */
192
+ declare const DANGEROUS_SCHEME_RE: RegExp;
193
+ type ValidateURLOptions = {
194
+ customValidator?: (url: string) => boolean;
195
+ };
196
+ /**
197
+ * Validates URLs including both standard web URLs and special app/protocol schemes
198
+ *
199
+ * Supports:
200
+ * - Standard web URLs (http, https, ftp)
201
+ * - Email addresses (mailto:)
202
+ * - Phone numbers (tel:, sms:)
203
+ * - App deep links (whatsapp:, discord:, etc.)
204
+ * - Apple app schemes (maps:, music:, etc.)
205
+ * - Development tools (github:, vscode:, etc.)
206
+ * - Domain-based detection (wa.me, t.me, etc.)
207
+ *
208
+ * For http(s)/ftp(s) URLs, the host must also look real — a TLD dot,
209
+ * `localhost`, or an IP literal. This rejects scheme-prefixed typos like
210
+ * `https://googlecom` that linkifyjs alone would accept.
211
+ *
212
+ * @param url - The URL string to validate
213
+ * @param options - Optional configuration
214
+ * @param options.customValidator - Custom validation function to apply additional checks
215
+ * @returns true if the URL is valid, false otherwise
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * validateURL('https://example.com') // true
220
+ * validateURL('mailto:user@example.com') // true
221
+ * validateURL('tel:+1234567890') // true
222
+ * validateURL('whatsapp://send?text=hello') // true
223
+ * validateURL('wa.me/1234567890') // true
224
+ * validateURL('https://googlecom') // false (no TLD, no localhost, no IP)
225
+ * validateURL('invalid-url') // false
226
+ * ```
227
+ */
228
+ declare const validateURL: (url: string, options?: ValidateURLOptions) => boolean;
229
+ /**
230
+ * Get the scheme/protocol from a URL
231
+ * @param url - The URL to extract scheme from
232
+ * @returns The scheme (e.g., 'https', 'mailto', 'tel') or null if invalid
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * getUrlScheme('https://example.com') // 'https'
237
+ * getUrlScheme('mailto:user@example.com') // 'mailto'
238
+ * getUrlScheme('invalid') // null
239
+ * ```
240
+ */
241
+ declare const getUrlScheme: (url: string) => string | null;
242
+ /**
243
+ * Check if a URL is a special app/protocol scheme (not http/https)
244
+ * @param url - The URL to check
245
+ * @returns true if it's a special scheme, false for standard web URLs
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * isSpecialSchemeUrl('mailto:user@example.com') // true
250
+ * isSpecialSchemeUrl('https://example.com') // false
251
+ * ```
252
+ */
253
+ declare const isSpecialSchemeUrl: (url: string) => boolean;
254
+
255
+ export { Copy, type CreateHyperlinkOptions, DANGEROUS_SCHEME_RE, DEFAULT_OFFSET, type FloatingToolbarInstance, type FloatingToolbarOptions, Hyperlink, type HyperlinkAttributes, type HyperlinkOptions, Link, LinkOff, type LinkProtocolOptions, type LinkifyMatchLike, Pencil, type PreviewHyperlinkOptions, type SpecialUrlInfo, Title, copyToClipboard, createFloatingToolbar, createHTMLElement, createHyperlinkPopover, Hyperlink as default, destroyCurrentToolbar, editHyperlinkPopover, getCategories, getCurrentToolbar, getSpecialUrlInfo, getUrlScheme, getUrlsByCategory, hideCurrentToolbar, isSpecialSchemeUrl, isToolbarVisible, normalizeHref, normalizeLinkifyHref, previewHyperlinkPopover, updateCurrentToolbarPosition, validateURL };