Color mode

Hover Preview

Quartz/Obsidian-Publish style popover previews for internal links. Hovering or focusing a note link shows its title and a short excerpt without leaving the page.

日本語

Overview

At build time hoverPreviewPlugin() builds a preview index from the content manifest (permalink → { title, excerpt, slug }) and injects it once into every page that contains internal links as an inert <script type="application/json" data-rb-hover-preview> block. The client entry initHoverPreview reads that payload and attaches hover, focus, and touch handlers to the matching links.

The excerpt is plain text extracted from the rendered HTML: tags are stripped, whitespace is collapsed, and the result is truncated to excerptLength characters. Pages without internal links are left untouched, and the payload is bounded by maxEntries when set.

Usage

ts
import { defineConfig } from "@riebeckite/core";
import { hoverPreviewPlugin } from "@riebeckite/plugin-hover-preview";
 
export default defineConfig({
  // ...
  plugins: [hoverPreviewPlugin()],
});

hoverPreviewPlugin() registers the style asset, the client entry, and the build-time payload injection. hoverPreview is an alias of the same factory.

The client entry takes no arguments. Behavior is carried by data attributes on the payload script, so the plugin works even when the client initializer is called without options.

Options

Option Default Description
delay 120 Milliseconds before the popover appears.
excerptLength 160 Maximum excerpt length in characters.
maxEntries unset Upper bound on entries stored in the page payload.
selector a[href^="/"] Selector for internal links that receive a preview.
className rb-hover-preview Base class of the popover element.
includeTitles true Whether the popover shows the target entry title.
ts
hoverPreviewPlugin({
  delay: 200,
  excerptLength: 120,
  maxEntries: 200,
  selector: 'a[href^="/notes/"]',
});

API

  • hoverPreviewPlugin(options?) — plugin factory
  • hoverPreview — alias of hoverPreviewPlugin
  • resolveHoverPreviewOptions(options?) — applies defaults and returns a ResolvedHoverPreviewOptions
  • buildPreviewIndex(entries, options) — builds a HoverPreviewIndex (permalink → { title, excerpt, slug })
  • htmlToPlainText(html) / createExcerpt(html, length) — excerpt helpers
  • initHoverPreview() — browser initializer (also via @riebeckite/plugin-hover-preview/client)
  • Constants: HOVER_PREVIEW_ATTRIBUTE, HOVER_PREVIEW_SCRIPT_ID
  • Types: HoverPreviewOptions, ResolvedHoverPreviewOptions, HoverPreviewEntry, HoverPreviewIndex

See also

History

1 changesCollapseExpand
1 + <!-- Generated from packages/plugins/hover-preview/README.md. Do not edit this page directly; edit the package README and run `pnpm docs:sync`. -->
2 +
3 + # Hover Preview
4 +
5 + Quartz/Obsidian-Publish style popover previews for internal links. Hovering or
6 + focusing a note link shows its title and a short excerpt without leaving the
7 + page.
8 +
9 + [日本語](./hover-preview.md)
10 +
11 + ## Overview
12 +
13 + At build time `hoverPreviewPlugin()` builds a preview index from the content
14 + manifest (`permalink` → `{ title, excerpt, slug }`) and injects it once into
15 + every page that contains internal links as an inert
16 + `<script type="application/json" data-rb-hover-preview>` block. The client
17 + entry `initHoverPreview` reads that payload and attaches hover, focus, and touch
18 + handlers to the matching links.
19 +
20 + The excerpt is plain text extracted from the rendered HTML: tags are stripped,
21 + whitespace is collapsed, and the result is truncated to `excerptLength`
22 + characters. Pages without internal links are left untouched, and the payload is
23 + bounded by `maxEntries` when set.
24 +
25 + ## Usage
26 +
27 + ```ts
28 + import { defineConfig } from "@riebeckite/core";
29 + import { hoverPreviewPlugin } from "@riebeckite/plugin-hover-preview";
30 +
31 + export default defineConfig({
32 + // ...
33 + plugins: [hoverPreviewPlugin()],
34 + });
35 + ```
36 +
37 + `hoverPreviewPlugin()` registers the style asset, the client entry, and the
38 + build-time payload injection. `hoverPreview` is an alias of the same factory.
39 +
40 + The client entry takes no arguments. Behavior is carried by data attributes on
41 + the payload script, so the plugin works even when the client initializer is
42 + called without options.
43 +
44 + ## Options
45 +
46 + | Option | Default | Description |
47 + | --------------- | -------------- | ------------------------------------------------------ |
48 + | `delay` | `120` | Milliseconds before the popover appears. |
49 + | `excerptLength` | `160` | Maximum excerpt length in characters. |
50 + | `maxEntries` | unset | Upper bound on entries stored in the page payload. |
51 + | `selector` | `a[href^="/"]` | Selector for internal links that receive a preview. |
52 + | `className` | `rb-hover-preview` | Base class of the popover element. |
53 + | `includeTitles` | `true` | Whether the popover shows the target entry title. |
54 +
55 + ```ts
56 + hoverPreviewPlugin({
57 + delay: 200,
58 + excerptLength: 120,
59 + maxEntries: 200,
60 + selector: 'a[href^="/notes/"]',
61 + });
62 + ```
63 +
64 + ## API
65 +
66 + - `hoverPreviewPlugin(options?)` — plugin factory
67 + - `hoverPreview` — alias of `hoverPreviewPlugin`
68 + - `resolveHoverPreviewOptions(options?)` — applies defaults and returns a
69 + `ResolvedHoverPreviewOptions`
70 + - `buildPreviewIndex(entries, options)` — builds a `HoverPreviewIndex`
71 + (`permalink` → `{ title, excerpt, slug }`)
72 + - `htmlToPlainText(html)` / `createExcerpt(html, length)` — excerpt helpers
73 + - `initHoverPreview()` — browser initializer (also via
74 + `@riebeckite/plugin-hover-preview/client`)
75 + - Constants: `HOVER_PREVIEW_ATTRIBUTE`, `HOVER_PREVIEW_SCRIPT_ID`
76 + - Types: `HoverPreviewOptions`, `ResolvedHoverPreviewOptions`,
77 + `HoverPreviewEntry`, `HoverPreviewIndex`
78 +
79 + ## See also
80 +
81 + - [Plugin guide](../reference/plugin-api.en.md)
82 +