@docs.plus/extension-hyperlink 2.0.0 → 2.1.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.
package/dist/index.d.cts CHANGED
@@ -6,7 +6,7 @@ export { registerCustomProtocol } from 'linkifyjs';
6
6
  /**
7
7
  * Canonicalize a user-supplied href so stored marks point somewhere
8
8
  * absolute (bare `google.com` would otherwise resolve against
9
- * `document.baseURI` at render time). See README → Normalization for
9
+ * `document.baseURI` at render time). See docs/url-handling.md for
10
10
  * the full pipeline order.
11
11
  */
12
12
  declare const normalizeHref: (raw: string, defaultProtocol?: string) => string;
@@ -22,18 +22,14 @@ type LinkifyMatchLike = {
22
22
  };
23
23
 
24
24
  /**
25
- * Schemes blocked at every write boundary: `javascript:` / `vbscript:`
26
- * (script execution), `data:` (arbitrary HTML), `file:` (local FS),
27
- * `blob:` (in-page memory; never legitimate in stored content).
28
- *
29
- * Twin of `extension-hypermultimedia`'s copy. Adding a scheme to one and not
30
- * the other opens a hole in the twin, so preflight diffs them byte-for-byte.
25
+ * Blocked schemes: `javascript:`/`vbscript:` (script), `data:`, `file:`, `blob:`.
26
+ * Twin of hypermultimedia's copy — preflight diffs them byte-for-byte.
31
27
  */
32
28
  declare const DANGEROUS_SCHEME_RE: RegExp;
33
29
  /**
34
30
  * Single XSS gate used at every read/write boundary. Returns `false`
35
31
  * for nullish/empty hrefs and any scheme matched by
36
- * {@link DANGEROUS_SCHEME_RE}. See README → Security.
32
+ * {@link DANGEROUS_SCHEME_RE}. See docs/security.md.
37
33
  */
38
34
  declare const isSafeHref: (href: string | null | undefined) => href is string;
39
35
  type ValidateURLOptions = {
@@ -42,7 +38,7 @@ type ValidateURLOptions = {
42
38
  /**
43
39
  * Shape-validate a URL: web schemes with a plausible host, app schemes from
44
40
  * the `getSpecialUrlInfo` catalog, and bare E.164 phones. Rejects schemes
45
- * matched by {@link DANGEROUS_SCHEME_RE}. See README → Validation.
41
+ * matched by {@link DANGEROUS_SCHEME_RE}. See docs/url-handling.md.
46
42
  */
47
43
  declare const validateURL: (url: string, options?: ValidateURLOptions) => boolean;
48
44
 
@@ -85,14 +81,12 @@ interface URLDecisions {
85
81
  detect(text: string): boolean;
86
82
  }
87
83
 
88
- /** Deps every interaction (input rule, paste rule, autolink, paste handler, click handler) reads. */
89
84
  interface LinkContext {
90
85
  type: MarkType;
91
86
  editor: Editor;
92
- /** URL Decisions pipeline; one per `createLinkContext` call (the extension allocates one per editor, cached on `storage.context`). */
87
+ /** One URL Decisions pipeline per editor (cached on `storage.context`). */
93
88
  urls: URLDecisions;
94
89
  options: HyperlinkOptions;
95
- /** Convenience accessor for `options.validate`. */
96
90
  validate?: (url: string) => boolean;
97
91
  /** Preview popover factory, or `null` when the host opted out. */
98
92
  previewPopover: ((options: PreviewHyperlinkOptions) => HTMLElement | null) | null;
@@ -111,13 +105,12 @@ type EditHyperlinkAttributes = {
111
105
  image?: string;
112
106
  };
113
107
  interface HyperlinkPublicCommands<ReturnType> {
114
- /** Write the hyperlink mark; returns `false` when `href` is missing or fails the gate. See README → Commands. */
108
+ /** Write the hyperlink mark; returns `false` when `href` is missing or fails the gate. See docs/api.md → Commands. */
115
109
  setHyperlink: (attributes: SetHyperlinkAttributes) => ReturnType;
116
- /** Remove the hyperlink mark from the current selection. */
117
110
  unsetHyperlink: () => ReturnType;
118
- /** Toggle the hyperlink mark; same gates as `setHyperlink`. */
111
+ /** Toggle; same gates as `setHyperlink`. */
119
112
  toggleHyperlink: (attributes: SetHyperlinkAttributes) => ReturnType;
120
- /** Open the create popover (configured `popovers.createHyperlink` or the prebuilt fallback); no-op only when the factory returns `null`. See README → Commands. */
113
+ /** Open the create popover (configured `popovers.createHyperlink` or the prebuilt fallback); no-op only when the factory returns `null`. See docs/api.md → Commands. */
121
114
  openCreateHyperlinkPopover: (attributes?: Partial<HyperlinkAttributes>) => ReturnType;
122
115
  editHyperlinkText: (text: string) => ReturnType;
123
116
  editHyperlinkHref: (href: string) => ReturnType;
@@ -149,7 +142,7 @@ type IsAllowedUriContext = {
149
142
  };
150
143
  /**
151
144
  * `Extra` extends the built-ins with consumer-typed fields; it defaults to
152
- * `Record<string, unknown>` to keep the v2 open index signature. Example: README → TypeScript.
145
+ * `Record<string, unknown>` to keep the v2 open index signature. Example: docs/api.md → TypeScript.
153
146
  */
154
147
  type HyperlinkAttributes<Extra extends Record<string, unknown> = Record<string, unknown>> = {
155
148
  href: string | null;
@@ -199,7 +192,7 @@ interface HyperlinkOptions {
199
192
  createHyperlink?: ((options: CreateHyperlinkOptions) => HTMLElement | null) | null;
200
193
  };
201
194
  validate?: (url: string) => boolean;
202
- /** Scheme used by `normalizeHref` to promote bare domains. Default `'https'`. See README → Options. */
195
+ /** Scheme used by `normalizeHref` to promote bare domains. Default `'https'`. See docs/api.md → Options. */
203
196
  defaultProtocol: string;
204
197
  /** URI policy hook — runs AFTER `isSafeHref`, BEFORE the mark is written. Mirrors `@tiptap/extension-link`. */
205
198
  isAllowedUri?: (uri: string, ctx: IsAllowedUriContext) => boolean;
@@ -207,7 +200,7 @@ interface HyperlinkOptions {
207
200
  shouldAutoLink?: (uri: string) => boolean;
208
201
  /** Click inside a link selects the whole mark range (editable mode only). Mirrors `@tiptap/extension-link`. */
209
202
  enableClickSelection: boolean;
210
- /** ArrowRight at the right edge of a link exits the mark. Mirrors `@tiptap/extension-link`. */
203
+ /** ArrowRight at the right edge of a link drops a stored link mark. Mirrors `@tiptap/extension-link`. */
211
204
  exitable: boolean;
212
205
  }
213
206
  /** Extension storage; one slot per editor instance. */
@@ -220,46 +213,6 @@ interface HyperlinkStorage {
220
213
  }
221
214
  declare const Hyperlink: Mark<HyperlinkOptions, HyperlinkStorage>;
222
215
 
223
- interface BuildPreviewOptionsFromAnchorArgs {
224
- editor: Editor;
225
- link: HTMLAnchorElement;
226
- /** Prefer this ProseMirror position before falling back to DOM similarity. */
227
- nodePos?: number;
228
- /** Forwarded onto the returned options; usually the configured `validate` option. */
229
- validate?: (url: string) => boolean;
230
- /** Preserve the host's composed navigation gate when rebuilding preview from edit/back. */
231
- isAllowedUri?: (uri: string) => boolean;
232
- /** Mark name to look up; defaults to `'hyperlink'`. Override only if the schema mark was renamed. */
233
- markName?: string;
234
- }
235
- /**
236
- * Exists so the edit popover's Back button and BYO `editHyperlink` factories
237
- * share one `posAtDOM → mark.attrs` lookup. The DOM `link.href` property is
238
- * never the raw-href fallback — it resolves relative hrefs against
239
- * `document.baseURI`, leaking the host origin into a stored attribute.
240
- */
241
- declare function buildPreviewOptionsFromAnchor({ editor, link, nodePos: preferredNodePos, validate, isAllowedUri, markName }: BuildPreviewOptionsFromAnchorArgs): PreviewHyperlinkOptions;
242
-
243
- /**
244
- * Open the create-hyperlink popover anchored to the current selection.
245
- * Returns `false` when the host opted out (factory returned `null`).
246
- */
247
- declare function openCreateHyperlink(editor: Editor, attributes?: Partial<HyperlinkAttributes>): boolean;
248
-
249
- /**
250
- * Open the edit popover anchored to a hyperlink. The prebuilt popover's
251
- * Back button closes over `opts`, so no extra wiring is needed to
252
- * return to the preview.
253
- */
254
- declare function openEditHyperlink(opts: EditHyperlinkOptions): void;
255
-
256
- /**
257
- * Returns `false` when the host opted out (factory returned `null`, e.g. a
258
- * mobile bottom sheet). The click handler gates caret placement on it —
259
- * `.focus()` on an opting-out host makes iOS Safari scroll the editor.
260
- */
261
- declare function openPreviewHyperlink(opts: PreviewHyperlinkOptions): boolean;
262
-
263
216
  type PopoverKind = 'preview' | 'edit' | 'create' | (string & {});
264
217
  type VirtualCoordinates = {
265
218
  getBoundingClientRect: () => {
@@ -276,9 +229,7 @@ interface ManagedPopover {
276
229
  updateReference: (referenceElement?: HTMLElement, coordinates?: VirtualCoordinates) => void;
277
230
  }
278
231
  type AdoptMetadata = {
279
- /** The popover's root element — what subscribers attach focus rings, scroll-freezes, or DOM observers to. */
280
232
  element: HTMLElement;
281
- /** The anchor the popover is glued to — `null` for virtual-coords popovers (e.g. selection-anchored create). */
282
233
  referenceElement: HTMLElement | null;
283
234
  };
284
235
  type ControllerState = {
@@ -354,10 +305,44 @@ interface Popover {
354
305
  declare const DEFAULT_OFFSET = 8;
355
306
  declare function createPopover(options: PopoverOptions): Popover;
356
307
 
357
- /** Hide the shared tooltip bubble and cancel any pending show. */
358
- declare function hideTooltip(): void;
359
- /** Show `label` above `target` after a short hover/focus delay. Returns a detach function for surfaces that re-render in place. */
360
- declare function attachTooltip(target: HTMLElement, label: string): () => void;
308
+ interface BuildPreviewOptionsFromAnchorArgs {
309
+ editor: Editor;
310
+ link: HTMLAnchorElement;
311
+ /** Prefer this ProseMirror position before falling back to DOM similarity. */
312
+ nodePos?: number;
313
+ validate?: (url: string) => boolean;
314
+ /** Preserve the host's composed navigation gate when rebuilding preview from edit/back. */
315
+ isAllowedUri?: (uri: string) => boolean;
316
+ /** Mark name to look up; defaults to `'hyperlink'`. Override only if the schema mark was renamed. */
317
+ markName?: string;
318
+ }
319
+ /**
320
+ * Exists so the edit popover's Back button and BYO `editHyperlink` factories
321
+ * share one `posAtDOM → mark.attrs` lookup. The DOM `link.href` property is
322
+ * never the raw-href fallback — it resolves relative hrefs against
323
+ * `document.baseURI`, leaking the host origin into a stored attribute.
324
+ */
325
+ declare function buildPreviewOptionsFromAnchor({ editor, link, nodePos: preferredNodePos, validate, isAllowedUri, markName }: BuildPreviewOptionsFromAnchorArgs): PreviewHyperlinkOptions;
326
+
327
+ /**
328
+ * Open the create-hyperlink popover anchored to the current selection.
329
+ * Returns `false` when the host opted out (factory returned `null`).
330
+ */
331
+ declare function openCreateHyperlink(editor: Editor, attributes?: Partial<HyperlinkAttributes>): boolean;
332
+
333
+ /**
334
+ * Open the edit popover anchored to a hyperlink. The prebuilt popover's
335
+ * Back button closes over `opts`, so no extra wiring is needed to
336
+ * return to the preview.
337
+ */
338
+ declare function openEditHyperlink(opts: EditHyperlinkOptions): void;
339
+
340
+ /**
341
+ * Returns `false` when the host opted out (factory returned `null`, e.g. a
342
+ * mobile bottom sheet). The click handler gates caret placement on it —
343
+ * `.focus()` on an opting-out host makes iOS Safari scroll the editor.
344
+ */
345
+ declare function openPreviewHyperlink(opts: PreviewHyperlinkOptions): boolean;
361
346
 
362
347
  declare function createHyperlinkPopover(options: CreateHyperlinkOptions): HTMLElement;
363
348
 
@@ -365,11 +350,13 @@ declare function editHyperlinkPopover(options: EditHyperlinkOptions): HTMLElemen
365
350
 
366
351
  declare function previewHyperlinkPopover(options: PreviewHyperlinkOptions): HTMLElement;
367
352
 
353
+ declare function hideTooltip(): void;
354
+ /** Returns a detach function for surfaces that re-render in place. */
355
+ declare function attachTooltip(target: HTMLElement, label: string): () => void;
356
+
368
357
  /**
369
- * `window.open` features string for safe navigation — every
370
- * `window.open(href, '_blank', …)` call needs this explicit arg or the
371
- * opened tab can read `window.opener` and the Referer leaks. Re-exported
372
- * so downstream popovers pin the same value.
358
+ * Required `window.open` features. Without this arg the opened tab can
359
+ * read `window.opener` and the Referer leaks. Re-exported so popovers pin it.
373
360
  */
374
361
  declare const SAFE_WINDOW_FEATURES: "noopener,noreferrer";
375
362
 
@@ -385,17 +372,10 @@ declare const Copy: ({ size, fill }?: IconProps) => string;
385
372
  declare const LinkOff: ({ size, fill }?: IconProps) => string;
386
373
  declare const Pencil: ({ size, fill }?: IconProps) => string;
387
374
 
375
+ /** Catalog of app schemes and well-known domains. Source: https://github.com/bhagyas/app-urls */
388
376
  /**
389
- * Special URL schemes and well-known domains the extension classifies
390
- * for the preview popover.
391
- *
392
- * Catalog source: https://github.com/bhagyas/app-urls
393
- */
394
- /**
395
- * String-literal union so consumers can declare a
396
- * `Partial<Record<SpecialUrlType, …>>` icon map with exhaustive
397
- * autocomplete — type-only, zero runtime bytes. Naming convention lives
398
- * in this package's AGENTS.md.
377
+ * Type-only union for consumer icon maps (`Partial<Record<SpecialUrlType, …>>`).
378
+ * Zero runtime bytes. Naming convention is in this package's AGENTS.md.
399
379
  */
400
380
  type SpecialUrlType = 'email' | 'phone' | 'sms' | 'facetime' | 'facetime-audio' | 'whatsapp' | 'telegram' | 'discord' | 'skype' | 'slack' | 'twitter' | 'facebook' | 'instagram' | 'linkedin' | 'snapchat' | 'reddit' | 'tiktok' | 'zoom' | 'teams' | 'webex' | 'meet' | 'calendar' | 'reminders' | 'contacts' | 'maps' | 'music' | 'apple-tv' | 'notes' | 'photos' | 'shortcuts' | 'app-store' | 'github' | 'gitlab' | 'vscode' | 'notion' | 'obsidian' | 'figma' | 'youtube' | 'spotify' | 'netflix' | 'twitch' | 'amazon' | 'uber' | 'lyft';
401
381
  type SpecialUrlInfo = {
@@ -404,10 +384,8 @@ type SpecialUrlInfo = {
404
384
  category: 'communication' | 'social' | 'productivity' | 'entertainment' | 'shopping' | 'development' | 'apple' | 'other';
405
385
  };
406
386
  /**
407
- * Classify `url` against the catalog (scheme prefix or host suffix).
408
- * Returns `null` for plain web URLs — the consumer should fall back to
409
- * a generic favicon. Mapping `type`/`category` to an icon is the
410
- * consumer's job; the extension stays brand-neutral on purpose.
387
+ * Classify `url` against the catalog. `null` means a plain web URL (favicon).
388
+ * Icon mapping is the consumer's job; this package stays brand-neutral.
411
389
  */
412
390
  declare const getSpecialUrlInfo: (url: string) => SpecialUrlInfo | null;
413
391
 
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { registerCustomProtocol } from 'linkifyjs';
6
6
  /**
7
7
  * Canonicalize a user-supplied href so stored marks point somewhere
8
8
  * absolute (bare `google.com` would otherwise resolve against
9
- * `document.baseURI` at render time). See README → Normalization for
9
+ * `document.baseURI` at render time). See docs/url-handling.md for
10
10
  * the full pipeline order.
11
11
  */
12
12
  declare const normalizeHref: (raw: string, defaultProtocol?: string) => string;
@@ -22,18 +22,14 @@ type LinkifyMatchLike = {
22
22
  };
23
23
 
24
24
  /**
25
- * Schemes blocked at every write boundary: `javascript:` / `vbscript:`
26
- * (script execution), `data:` (arbitrary HTML), `file:` (local FS),
27
- * `blob:` (in-page memory; never legitimate in stored content).
28
- *
29
- * Twin of `extension-hypermultimedia`'s copy. Adding a scheme to one and not
30
- * the other opens a hole in the twin, so preflight diffs them byte-for-byte.
25
+ * Blocked schemes: `javascript:`/`vbscript:` (script), `data:`, `file:`, `blob:`.
26
+ * Twin of hypermultimedia's copy — preflight diffs them byte-for-byte.
31
27
  */
32
28
  declare const DANGEROUS_SCHEME_RE: RegExp;
33
29
  /**
34
30
  * Single XSS gate used at every read/write boundary. Returns `false`
35
31
  * for nullish/empty hrefs and any scheme matched by
36
- * {@link DANGEROUS_SCHEME_RE}. See README → Security.
32
+ * {@link DANGEROUS_SCHEME_RE}. See docs/security.md.
37
33
  */
38
34
  declare const isSafeHref: (href: string | null | undefined) => href is string;
39
35
  type ValidateURLOptions = {
@@ -42,7 +38,7 @@ type ValidateURLOptions = {
42
38
  /**
43
39
  * Shape-validate a URL: web schemes with a plausible host, app schemes from
44
40
  * the `getSpecialUrlInfo` catalog, and bare E.164 phones. Rejects schemes
45
- * matched by {@link DANGEROUS_SCHEME_RE}. See README → Validation.
41
+ * matched by {@link DANGEROUS_SCHEME_RE}. See docs/url-handling.md.
46
42
  */
47
43
  declare const validateURL: (url: string, options?: ValidateURLOptions) => boolean;
48
44
 
@@ -85,14 +81,12 @@ interface URLDecisions {
85
81
  detect(text: string): boolean;
86
82
  }
87
83
 
88
- /** Deps every interaction (input rule, paste rule, autolink, paste handler, click handler) reads. */
89
84
  interface LinkContext {
90
85
  type: MarkType;
91
86
  editor: Editor;
92
- /** URL Decisions pipeline; one per `createLinkContext` call (the extension allocates one per editor, cached on `storage.context`). */
87
+ /** One URL Decisions pipeline per editor (cached on `storage.context`). */
93
88
  urls: URLDecisions;
94
89
  options: HyperlinkOptions;
95
- /** Convenience accessor for `options.validate`. */
96
90
  validate?: (url: string) => boolean;
97
91
  /** Preview popover factory, or `null` when the host opted out. */
98
92
  previewPopover: ((options: PreviewHyperlinkOptions) => HTMLElement | null) | null;
@@ -111,13 +105,12 @@ type EditHyperlinkAttributes = {
111
105
  image?: string;
112
106
  };
113
107
  interface HyperlinkPublicCommands<ReturnType> {
114
- /** Write the hyperlink mark; returns `false` when `href` is missing or fails the gate. See README → Commands. */
108
+ /** Write the hyperlink mark; returns `false` when `href` is missing or fails the gate. See docs/api.md → Commands. */
115
109
  setHyperlink: (attributes: SetHyperlinkAttributes) => ReturnType;
116
- /** Remove the hyperlink mark from the current selection. */
117
110
  unsetHyperlink: () => ReturnType;
118
- /** Toggle the hyperlink mark; same gates as `setHyperlink`. */
111
+ /** Toggle; same gates as `setHyperlink`. */
119
112
  toggleHyperlink: (attributes: SetHyperlinkAttributes) => ReturnType;
120
- /** Open the create popover (configured `popovers.createHyperlink` or the prebuilt fallback); no-op only when the factory returns `null`. See README → Commands. */
113
+ /** Open the create popover (configured `popovers.createHyperlink` or the prebuilt fallback); no-op only when the factory returns `null`. See docs/api.md → Commands. */
121
114
  openCreateHyperlinkPopover: (attributes?: Partial<HyperlinkAttributes>) => ReturnType;
122
115
  editHyperlinkText: (text: string) => ReturnType;
123
116
  editHyperlinkHref: (href: string) => ReturnType;
@@ -149,7 +142,7 @@ type IsAllowedUriContext = {
149
142
  };
150
143
  /**
151
144
  * `Extra` extends the built-ins with consumer-typed fields; it defaults to
152
- * `Record<string, unknown>` to keep the v2 open index signature. Example: README → TypeScript.
145
+ * `Record<string, unknown>` to keep the v2 open index signature. Example: docs/api.md → TypeScript.
153
146
  */
154
147
  type HyperlinkAttributes<Extra extends Record<string, unknown> = Record<string, unknown>> = {
155
148
  href: string | null;
@@ -199,7 +192,7 @@ interface HyperlinkOptions {
199
192
  createHyperlink?: ((options: CreateHyperlinkOptions) => HTMLElement | null) | null;
200
193
  };
201
194
  validate?: (url: string) => boolean;
202
- /** Scheme used by `normalizeHref` to promote bare domains. Default `'https'`. See README → Options. */
195
+ /** Scheme used by `normalizeHref` to promote bare domains. Default `'https'`. See docs/api.md → Options. */
203
196
  defaultProtocol: string;
204
197
  /** URI policy hook — runs AFTER `isSafeHref`, BEFORE the mark is written. Mirrors `@tiptap/extension-link`. */
205
198
  isAllowedUri?: (uri: string, ctx: IsAllowedUriContext) => boolean;
@@ -207,7 +200,7 @@ interface HyperlinkOptions {
207
200
  shouldAutoLink?: (uri: string) => boolean;
208
201
  /** Click inside a link selects the whole mark range (editable mode only). Mirrors `@tiptap/extension-link`. */
209
202
  enableClickSelection: boolean;
210
- /** ArrowRight at the right edge of a link exits the mark. Mirrors `@tiptap/extension-link`. */
203
+ /** ArrowRight at the right edge of a link drops a stored link mark. Mirrors `@tiptap/extension-link`. */
211
204
  exitable: boolean;
212
205
  }
213
206
  /** Extension storage; one slot per editor instance. */
@@ -220,46 +213,6 @@ interface HyperlinkStorage {
220
213
  }
221
214
  declare const Hyperlink: Mark<HyperlinkOptions, HyperlinkStorage>;
222
215
 
223
- interface BuildPreviewOptionsFromAnchorArgs {
224
- editor: Editor;
225
- link: HTMLAnchorElement;
226
- /** Prefer this ProseMirror position before falling back to DOM similarity. */
227
- nodePos?: number;
228
- /** Forwarded onto the returned options; usually the configured `validate` option. */
229
- validate?: (url: string) => boolean;
230
- /** Preserve the host's composed navigation gate when rebuilding preview from edit/back. */
231
- isAllowedUri?: (uri: string) => boolean;
232
- /** Mark name to look up; defaults to `'hyperlink'`. Override only if the schema mark was renamed. */
233
- markName?: string;
234
- }
235
- /**
236
- * Exists so the edit popover's Back button and BYO `editHyperlink` factories
237
- * share one `posAtDOM → mark.attrs` lookup. The DOM `link.href` property is
238
- * never the raw-href fallback — it resolves relative hrefs against
239
- * `document.baseURI`, leaking the host origin into a stored attribute.
240
- */
241
- declare function buildPreviewOptionsFromAnchor({ editor, link, nodePos: preferredNodePos, validate, isAllowedUri, markName }: BuildPreviewOptionsFromAnchorArgs): PreviewHyperlinkOptions;
242
-
243
- /**
244
- * Open the create-hyperlink popover anchored to the current selection.
245
- * Returns `false` when the host opted out (factory returned `null`).
246
- */
247
- declare function openCreateHyperlink(editor: Editor, attributes?: Partial<HyperlinkAttributes>): boolean;
248
-
249
- /**
250
- * Open the edit popover anchored to a hyperlink. The prebuilt popover's
251
- * Back button closes over `opts`, so no extra wiring is needed to
252
- * return to the preview.
253
- */
254
- declare function openEditHyperlink(opts: EditHyperlinkOptions): void;
255
-
256
- /**
257
- * Returns `false` when the host opted out (factory returned `null`, e.g. a
258
- * mobile bottom sheet). The click handler gates caret placement on it —
259
- * `.focus()` on an opting-out host makes iOS Safari scroll the editor.
260
- */
261
- declare function openPreviewHyperlink(opts: PreviewHyperlinkOptions): boolean;
262
-
263
216
  type PopoverKind = 'preview' | 'edit' | 'create' | (string & {});
264
217
  type VirtualCoordinates = {
265
218
  getBoundingClientRect: () => {
@@ -276,9 +229,7 @@ interface ManagedPopover {
276
229
  updateReference: (referenceElement?: HTMLElement, coordinates?: VirtualCoordinates) => void;
277
230
  }
278
231
  type AdoptMetadata = {
279
- /** The popover's root element — what subscribers attach focus rings, scroll-freezes, or DOM observers to. */
280
232
  element: HTMLElement;
281
- /** The anchor the popover is glued to — `null` for virtual-coords popovers (e.g. selection-anchored create). */
282
233
  referenceElement: HTMLElement | null;
283
234
  };
284
235
  type ControllerState = {
@@ -354,10 +305,44 @@ interface Popover {
354
305
  declare const DEFAULT_OFFSET = 8;
355
306
  declare function createPopover(options: PopoverOptions): Popover;
356
307
 
357
- /** Hide the shared tooltip bubble and cancel any pending show. */
358
- declare function hideTooltip(): void;
359
- /** Show `label` above `target` after a short hover/focus delay. Returns a detach function for surfaces that re-render in place. */
360
- declare function attachTooltip(target: HTMLElement, label: string): () => void;
308
+ interface BuildPreviewOptionsFromAnchorArgs {
309
+ editor: Editor;
310
+ link: HTMLAnchorElement;
311
+ /** Prefer this ProseMirror position before falling back to DOM similarity. */
312
+ nodePos?: number;
313
+ validate?: (url: string) => boolean;
314
+ /** Preserve the host's composed navigation gate when rebuilding preview from edit/back. */
315
+ isAllowedUri?: (uri: string) => boolean;
316
+ /** Mark name to look up; defaults to `'hyperlink'`. Override only if the schema mark was renamed. */
317
+ markName?: string;
318
+ }
319
+ /**
320
+ * Exists so the edit popover's Back button and BYO `editHyperlink` factories
321
+ * share one `posAtDOM → mark.attrs` lookup. The DOM `link.href` property is
322
+ * never the raw-href fallback — it resolves relative hrefs against
323
+ * `document.baseURI`, leaking the host origin into a stored attribute.
324
+ */
325
+ declare function buildPreviewOptionsFromAnchor({ editor, link, nodePos: preferredNodePos, validate, isAllowedUri, markName }: BuildPreviewOptionsFromAnchorArgs): PreviewHyperlinkOptions;
326
+
327
+ /**
328
+ * Open the create-hyperlink popover anchored to the current selection.
329
+ * Returns `false` when the host opted out (factory returned `null`).
330
+ */
331
+ declare function openCreateHyperlink(editor: Editor, attributes?: Partial<HyperlinkAttributes>): boolean;
332
+
333
+ /**
334
+ * Open the edit popover anchored to a hyperlink. The prebuilt popover's
335
+ * Back button closes over `opts`, so no extra wiring is needed to
336
+ * return to the preview.
337
+ */
338
+ declare function openEditHyperlink(opts: EditHyperlinkOptions): void;
339
+
340
+ /**
341
+ * Returns `false` when the host opted out (factory returned `null`, e.g. a
342
+ * mobile bottom sheet). The click handler gates caret placement on it —
343
+ * `.focus()` on an opting-out host makes iOS Safari scroll the editor.
344
+ */
345
+ declare function openPreviewHyperlink(opts: PreviewHyperlinkOptions): boolean;
361
346
 
362
347
  declare function createHyperlinkPopover(options: CreateHyperlinkOptions): HTMLElement;
363
348
 
@@ -365,11 +350,13 @@ declare function editHyperlinkPopover(options: EditHyperlinkOptions): HTMLElemen
365
350
 
366
351
  declare function previewHyperlinkPopover(options: PreviewHyperlinkOptions): HTMLElement;
367
352
 
353
+ declare function hideTooltip(): void;
354
+ /** Returns a detach function for surfaces that re-render in place. */
355
+ declare function attachTooltip(target: HTMLElement, label: string): () => void;
356
+
368
357
  /**
369
- * `window.open` features string for safe navigation — every
370
- * `window.open(href, '_blank', …)` call needs this explicit arg or the
371
- * opened tab can read `window.opener` and the Referer leaks. Re-exported
372
- * so downstream popovers pin the same value.
358
+ * Required `window.open` features. Without this arg the opened tab can
359
+ * read `window.opener` and the Referer leaks. Re-exported so popovers pin it.
373
360
  */
374
361
  declare const SAFE_WINDOW_FEATURES: "noopener,noreferrer";
375
362
 
@@ -385,17 +372,10 @@ declare const Copy: ({ size, fill }?: IconProps) => string;
385
372
  declare const LinkOff: ({ size, fill }?: IconProps) => string;
386
373
  declare const Pencil: ({ size, fill }?: IconProps) => string;
387
374
 
375
+ /** Catalog of app schemes and well-known domains. Source: https://github.com/bhagyas/app-urls */
388
376
  /**
389
- * Special URL schemes and well-known domains the extension classifies
390
- * for the preview popover.
391
- *
392
- * Catalog source: https://github.com/bhagyas/app-urls
393
- */
394
- /**
395
- * String-literal union so consumers can declare a
396
- * `Partial<Record<SpecialUrlType, …>>` icon map with exhaustive
397
- * autocomplete — type-only, zero runtime bytes. Naming convention lives
398
- * in this package's AGENTS.md.
377
+ * Type-only union for consumer icon maps (`Partial<Record<SpecialUrlType, …>>`).
378
+ * Zero runtime bytes. Naming convention is in this package's AGENTS.md.
399
379
  */
400
380
  type SpecialUrlType = 'email' | 'phone' | 'sms' | 'facetime' | 'facetime-audio' | 'whatsapp' | 'telegram' | 'discord' | 'skype' | 'slack' | 'twitter' | 'facebook' | 'instagram' | 'linkedin' | 'snapchat' | 'reddit' | 'tiktok' | 'zoom' | 'teams' | 'webex' | 'meet' | 'calendar' | 'reminders' | 'contacts' | 'maps' | 'music' | 'apple-tv' | 'notes' | 'photos' | 'shortcuts' | 'app-store' | 'github' | 'gitlab' | 'vscode' | 'notion' | 'obsidian' | 'figma' | 'youtube' | 'spotify' | 'netflix' | 'twitch' | 'amazon' | 'uber' | 'lyft';
401
381
  type SpecialUrlInfo = {
@@ -404,10 +384,8 @@ type SpecialUrlInfo = {
404
384
  category: 'communication' | 'social' | 'productivity' | 'entertainment' | 'shopping' | 'development' | 'apple' | 'other';
405
385
  };
406
386
  /**
407
- * Classify `url` against the catalog (scheme prefix or host suffix).
408
- * Returns `null` for plain web URLs — the consumer should fall back to
409
- * a generic favicon. Mapping `type`/`category` to an icon is the
410
- * consumer's job; the extension stays brand-neutral on purpose.
387
+ * Classify `url` against the catalog. `null` means a plain web URL (favicon).
388
+ * Icon mapping is the consumer's job; this package stays brand-neutral.
411
389
  */
412
390
  declare const getSpecialUrlInfo: (url: string) => SpecialUrlInfo | null;
413
391