joplin-plugin-minimap 1.1.1
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/LICENSE +21 -0
- package/README.md +69 -0
- package/package.json +17 -0
- package/publish/index.js +68 -0
- package/publish/manifest.json +13 -0
- package/publish/minimap-view.js +148 -0
- package/publish/minimap.css +116 -0
- package/publish/minimapContentScript.js +20 -0
- package/publish/plugin.jpl +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 lim0513
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Joplin Minimap
|
|
2
|
+
|
|
3
|
+
A hover-to-expand table of contents minimap for the [Joplin](https://joplinapp.org/) note viewer — heading tick marks on the right edge that expand into a clickable outline.
|
|
4
|
+
|
|
5
|
+
[中文说明](README-CN.md) | [日本語](README-JA.md)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Tick Bar Minimap** — Each heading is shown as a small horizontal bar on the right edge of the note viewer; bar length reflects the heading level (H1 longest)
|
|
10
|
+
- **Hover to Expand** — Move the mouse over the bars and they expand into a full table of contents overlay, indented by level, with long titles ellipsized
|
|
11
|
+
- **Click to Jump** — Click any entry to smooth-scroll to that heading
|
|
12
|
+
- **Reading Position** — The section currently in view is highlighted automatically
|
|
13
|
+
- **Live Rebuild** — Rebuilds itself when you switch notes or edit content (listens to `joplin-noteDidUpdate` with a MutationObserver fallback)
|
|
14
|
+
- **Theme Aware** — Follows light and dark themes automatically (colors derive from `currentColor`)
|
|
15
|
+
- **Unobtrusive** — Hidden for notes with fewer than 2 headings, hidden when printing/exporting, never steals focus or keyboard input
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
### From the Joplin plugin repository (once published)
|
|
20
|
+
|
|
21
|
+
1. In Joplin, go to **Tools → Options → Plugins**
|
|
22
|
+
2. Search for **Joplin Minimap**
|
|
23
|
+
3. Install and restart Joplin
|
|
24
|
+
|
|
25
|
+
### From file
|
|
26
|
+
|
|
27
|
+
1. Download `plugin.jpl` from the [latest release](https://github.com/lim0513/joplin-minimap/releases/latest)
|
|
28
|
+
2. In Joplin, go to **Tools → Options → Plugins**
|
|
29
|
+
3. Click the gear icon and select **Install from file**
|
|
30
|
+
4. Choose the downloaded `.jpl` file
|
|
31
|
+
5. Restart Joplin
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Open any note with 2 or more headings in the **rendered Markdown viewer** (reading view, or the preview side of the split editor):
|
|
36
|
+
|
|
37
|
+
- A column of tick bars appears at the right edge
|
|
38
|
+
- **Hover** over it to expand the full table of contents
|
|
39
|
+
- **Click** an entry to jump to that heading
|
|
40
|
+
|
|
41
|
+
Note: the minimap only appears in the rendered viewer, not in the plain Markdown editor or the Rich Text editor.
|
|
42
|
+
|
|
43
|
+
## How It Works
|
|
44
|
+
|
|
45
|
+
A markdown-it content script injects two assets into the rendered viewer: `minimap-view.js` builds the minimap dynamically from the rendered `h1`–`h6` elements after each render, and `minimap.css` handles the collapsed/expanded styling. The Markdown rendering itself is untouched.
|
|
46
|
+
|
|
47
|
+
## Settings
|
|
48
|
+
|
|
49
|
+
Configurable in **Tools → Options → Joplin Minimap**:
|
|
50
|
+
|
|
51
|
+
- **Minimum headings** — hide the minimap when the note has fewer headings than this (default 2)
|
|
52
|
+
- **Expanded panel width (px)** — maximum width of the hover-expanded table of contents (default 240)
|
|
53
|
+
- **Distance from right edge (px)** — gap between the minimap and the viewer's right edge (default 6)
|
|
54
|
+
|
|
55
|
+
Changed settings apply on the next render (switch notes or edit the note).
|
|
56
|
+
|
|
57
|
+
## Development
|
|
58
|
+
|
|
59
|
+
Zero dependencies — no `npm install` needed:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm run dist
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This builds `dist/` (loadable via Joplin's **Development plugins** setting pointed at the project root) and `publish/` including `publish/plugin.jpl`.
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "joplin-plugin-minimap",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "A hover-to-expand table of contents minimap for the Joplin note viewer",
|
|
5
|
+
"author": "lim0513",
|
|
6
|
+
"homepage": "https://github.com/lim0513/joplin-minimap",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/lim0513/joplin-minimap.git"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dist": "node build.js && node scripts/pack-jpl.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["joplin-plugin", "joplin", "toc", "outline", "minimap", "table-of-contents", "viewer"],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"files": ["publish"]
|
|
17
|
+
}
|
package/publish/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* Joplin Minimap — plugin entry (runs in the plugin host, Node context).
|
|
2
|
+
* Registers the settings UI and a markdown-it content script whose only job
|
|
3
|
+
* is to inject the minimap assets (JS + CSS) into the rendered note viewer.
|
|
4
|
+
* The viewer asset fetches settings via webviewApi.postMessage -> onMessage.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// SettingItemType numeric values: Int=1, String=2, Bool=3 (no 'api' import in plain JS)
|
|
8
|
+
const TYPE_INT = 1;
|
|
9
|
+
|
|
10
|
+
joplin.plugins.register({
|
|
11
|
+
onStart: async function () {
|
|
12
|
+
await joplin.settings.registerSection('minimap', {
|
|
13
|
+
label: 'Joplin Minimap',
|
|
14
|
+
iconName: 'fas fa-list',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
await joplin.settings.registerSettings({
|
|
19
|
+
'minimapMinHeadings': {
|
|
20
|
+
value: 2,
|
|
21
|
+
minimum: 1,
|
|
22
|
+
type: TYPE_INT,
|
|
23
|
+
section: 'minimap',
|
|
24
|
+
public: true,
|
|
25
|
+
label: 'Minimum headings',
|
|
26
|
+
description: 'Hide the minimap when the note has fewer headings than this. Default: 2.',
|
|
27
|
+
},
|
|
28
|
+
'minimapPanelWidth': {
|
|
29
|
+
value: 240,
|
|
30
|
+
minimum: 120,
|
|
31
|
+
type: TYPE_INT,
|
|
32
|
+
section: 'minimap',
|
|
33
|
+
public: true,
|
|
34
|
+
label: 'Expanded panel width (px)',
|
|
35
|
+
description: 'Maximum width of the hover-expanded table of contents. Default: 240.',
|
|
36
|
+
},
|
|
37
|
+
'minimapRightOffset': {
|
|
38
|
+
value: 6,
|
|
39
|
+
minimum: 0,
|
|
40
|
+
type: TYPE_INT,
|
|
41
|
+
section: 'minimap',
|
|
42
|
+
public: true,
|
|
43
|
+
label: 'Distance from right edge (px)',
|
|
44
|
+
description: 'Gap between the minimap and the right edge of the viewer. Default: 6.',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('Joplin Minimap: registerSettings failed:', error);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await joplin.contentScripts.register(
|
|
52
|
+
'markdownItPlugin',
|
|
53
|
+
'joplin-minimap',
|
|
54
|
+
'./minimapContentScript.js'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
await joplin.contentScripts.onMessage('joplin-minimap', async function (message) {
|
|
58
|
+
if (message === 'getSettings') {
|
|
59
|
+
return {
|
|
60
|
+
minHeadings: await joplin.settings.value('minimapMinHeadings'),
|
|
61
|
+
panelWidth: await joplin.settings.value('minimapPanelWidth'),
|
|
62
|
+
rightOffset: await joplin.settings.value('minimapRightOffset'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 1,
|
|
3
|
+
"id": "com.github.joplin-minimap",
|
|
4
|
+
"app_min_version": "2.8",
|
|
5
|
+
"version": "1.1.1",
|
|
6
|
+
"name": "Joplin Minimap",
|
|
7
|
+
"description": "A hover-to-expand table of contents minimap for the note viewer. Shows heading tick marks on the right edge; hover to expand into a full ToC, click to jump.",
|
|
8
|
+
"author": "lim0513",
|
|
9
|
+
"homepage_url": "https://github.com/lim0513/joplin-minimap",
|
|
10
|
+
"repository_url": "https://github.com/lim0513/joplin-minimap",
|
|
11
|
+
"keywords": ["toc", "outline", "minimap", "table-of-contents"],
|
|
12
|
+
"categories": ["appearance", "viewer"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/* Joplin Minimap - runs inside the rendered note viewer.
|
|
2
|
+
* Collects h1-h6 from the rendered DOM, draws collapsed tick bars on the
|
|
3
|
+
* right edge, expands into a full ToC on hover, and jumps on click.
|
|
4
|
+
* Rebuilds itself whenever the note content changes (note switch, edit).
|
|
5
|
+
*/
|
|
6
|
+
(function () {
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
// Defaults; overridden from Joplin's plugin settings (Tools > Options > Minimap)
|
|
10
|
+
// when webviewApi is available in this webview.
|
|
11
|
+
var settings = { minHeadings: 2, panelWidth: 240, rightOffset: 6 };
|
|
12
|
+
|
|
13
|
+
function loadSettings() {
|
|
14
|
+
if (typeof webviewApi === 'undefined' || !webviewApi.postMessage) {
|
|
15
|
+
return Promise.resolve();
|
|
16
|
+
}
|
|
17
|
+
return webviewApi.postMessage('joplin-minimap', 'getSettings').then(function (s) {
|
|
18
|
+
if (s && typeof s.minHeadings === 'number') settings = s;
|
|
19
|
+
}).catch(function () { /* keep defaults (e.g. print/export context) */ });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Only ever install one instance of the watcher per webview session.
|
|
23
|
+
if (window.__jpMinimapInstalled) return;
|
|
24
|
+
window.__jpMinimapInstalled = true;
|
|
25
|
+
|
|
26
|
+
var cleanup = null; // removes listeners belonging to the current build
|
|
27
|
+
|
|
28
|
+
function build() {
|
|
29
|
+
if (cleanup) { cleanup(); cleanup = null; }
|
|
30
|
+
|
|
31
|
+
var old = document.getElementById('jp-minimap');
|
|
32
|
+
if (old) old.remove();
|
|
33
|
+
|
|
34
|
+
var root = document.getElementById('rendered-md') || document.body;
|
|
35
|
+
var headings = Array.prototype.slice.call(
|
|
36
|
+
root.querySelectorAll('h1, h2, h3, h4, h5, h6')
|
|
37
|
+
);
|
|
38
|
+
if (headings.length < settings.minHeadings) return;
|
|
39
|
+
|
|
40
|
+
var nav = document.createElement('nav');
|
|
41
|
+
nav.id = 'jp-minimap';
|
|
42
|
+
nav.style.right = settings.rightOffset + 'px';
|
|
43
|
+
nav.style.setProperty('--jp-mm-width', settings.panelWidth + 'px');
|
|
44
|
+
// The viewer DOM can be editable in some contexts; make sure the
|
|
45
|
+
// minimap never shows a caret or accepts keyboard input.
|
|
46
|
+
nav.setAttribute('contenteditable', 'false');
|
|
47
|
+
nav.addEventListener('mousedown', function (e) { e.preventDefault(); });
|
|
48
|
+
// Own the wheel entirely while the cursor is over the minimap:
|
|
49
|
+
// scroll the ToC list ourselves and never let the event chain
|
|
50
|
+
// through to the note underneath (scroll chaining feels erratic).
|
|
51
|
+
nav.addEventListener('wheel', function (e) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
list.scrollTop += e.deltaY;
|
|
54
|
+
}, { passive: false });
|
|
55
|
+
|
|
56
|
+
var list = document.createElement('div');
|
|
57
|
+
list.className = 'jp-mm-list';
|
|
58
|
+
|
|
59
|
+
var items = headings.map(function (h) {
|
|
60
|
+
var level = Number(h.tagName.charAt(1));
|
|
61
|
+
|
|
62
|
+
// NOT an <a>: Joplin's viewer shows a "Ctrl+click to open" tooltip
|
|
63
|
+
// on anchors and treats them as external links.
|
|
64
|
+
var item = document.createElement('div');
|
|
65
|
+
item.className = 'jp-mm-item jp-mm-l' + level;
|
|
66
|
+
|
|
67
|
+
var bar = document.createElement('span');
|
|
68
|
+
bar.className = 'jp-mm-bar';
|
|
69
|
+
|
|
70
|
+
var label = document.createElement('span');
|
|
71
|
+
label.className = 'jp-mm-label';
|
|
72
|
+
label.textContent = (h.textContent || '').trim();
|
|
73
|
+
|
|
74
|
+
item.appendChild(bar);
|
|
75
|
+
item.appendChild(label);
|
|
76
|
+
|
|
77
|
+
item.addEventListener('click', function () {
|
|
78
|
+
h.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
list.appendChild(item);
|
|
82
|
+
return item;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
nav.appendChild(list);
|
|
86
|
+
document.body.appendChild(nav);
|
|
87
|
+
|
|
88
|
+
function updateActive() {
|
|
89
|
+
var activeIndex = 0;
|
|
90
|
+
for (var i = 0; i < headings.length; i++) {
|
|
91
|
+
if (headings[i].getBoundingClientRect().top <= 90) activeIndex = i;
|
|
92
|
+
}
|
|
93
|
+
for (var j = 0; j < items.length; j++) {
|
|
94
|
+
items[j].classList.toggle('jp-mm-active', j === activeIndex);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
document.addEventListener('scroll', updateActive, { passive: true, capture: true });
|
|
99
|
+
updateActive();
|
|
100
|
+
|
|
101
|
+
cleanup = function () {
|
|
102
|
+
document.removeEventListener('scroll', updateActive, { capture: true });
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function settingsAndBuild() {
|
|
107
|
+
loadSettings().then(build);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var timer = null;
|
|
111
|
+
function scheduleBuild() {
|
|
112
|
+
clearTimeout(timer);
|
|
113
|
+
timer = setTimeout(settingsAndBuild, 150);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// True if a mutation was caused by the minimap itself (avoid rebuild loops).
|
|
117
|
+
function isOwnMutation(m) {
|
|
118
|
+
if (m.target && m.target.closest && m.target.closest('#jp-minimap')) return true;
|
|
119
|
+
var nodes = Array.prototype.slice.call(m.addedNodes)
|
|
120
|
+
.concat(Array.prototype.slice.call(m.removedNodes));
|
|
121
|
+
if (!nodes.length) return false;
|
|
122
|
+
return nodes.every(function (n) {
|
|
123
|
+
return n.id === 'jp-minimap' || (n.closest && n.closest('#jp-minimap'));
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function watch() {
|
|
128
|
+
// Joplin fires this after each note render/update.
|
|
129
|
+
document.addEventListener('joplin-noteDidUpdate', scheduleBuild);
|
|
130
|
+
|
|
131
|
+
// Fallback: watch for the rendered content being swapped out
|
|
132
|
+
// (note switch replaces the DOM without re-running this script).
|
|
133
|
+
var mo = new MutationObserver(function (mutations) {
|
|
134
|
+
for (var i = 0; i < mutations.length; i++) {
|
|
135
|
+
if (!isOwnMutation(mutations[i])) { scheduleBuild(); return; }
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
mo.observe(document.body, { childList: true, subtree: true });
|
|
139
|
+
|
|
140
|
+
settingsAndBuild();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (document.readyState === 'loading') {
|
|
144
|
+
document.addEventListener('DOMContentLoaded', watch);
|
|
145
|
+
} else {
|
|
146
|
+
watch();
|
|
147
|
+
}
|
|
148
|
+
})();
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* Joplin Minimap — collapsed tick bars, hover-expanded ToC panel.
|
|
2
|
+
* Colors use currentColor / rgba so it follows both light and dark themes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
#jp-minimap {
|
|
6
|
+
user-select: none;
|
|
7
|
+
-webkit-user-select: none;
|
|
8
|
+
caret-color: transparent;
|
|
9
|
+
cursor: default;
|
|
10
|
+
position: fixed;
|
|
11
|
+
top: 50%;
|
|
12
|
+
right: 6px;
|
|
13
|
+
transform: translateY(-50%);
|
|
14
|
+
z-index: 9999;
|
|
15
|
+
font-size: 12.5px;
|
|
16
|
+
line-height: 1.35;
|
|
17
|
+
color: inherit;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.jp-mm-list {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
align-items: flex-end;
|
|
24
|
+
padding: 8px 6px;
|
|
25
|
+
max-height: 84vh;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
border-radius: 10px;
|
|
28
|
+
transition: background 0.15s ease, box-shadow 0.15s ease;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.jp-mm-item {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: flex-end;
|
|
35
|
+
padding: 3px 4px;
|
|
36
|
+
border-radius: 6px;
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
color: inherit;
|
|
39
|
+
opacity: 0.5;
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
outline: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ---- collapsed state: tick bars, width by heading level ---- */
|
|
45
|
+
|
|
46
|
+
.jp-mm-bar {
|
|
47
|
+
display: block;
|
|
48
|
+
height: 2px;
|
|
49
|
+
border-radius: 1px;
|
|
50
|
+
background: currentColor;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.jp-mm-l1 .jp-mm-bar { width: 18px; }
|
|
54
|
+
.jp-mm-l2 .jp-mm-bar { width: 13px; }
|
|
55
|
+
.jp-mm-l3 .jp-mm-bar { width: 9px; }
|
|
56
|
+
.jp-mm-l4 .jp-mm-bar { width: 7px; }
|
|
57
|
+
.jp-mm-l5 .jp-mm-bar { width: 5px; }
|
|
58
|
+
.jp-mm-l6 .jp-mm-bar { width: 5px; }
|
|
59
|
+
|
|
60
|
+
.jp-mm-label { display: none; }
|
|
61
|
+
|
|
62
|
+
/* ---- expanded state (hover) ---- */
|
|
63
|
+
|
|
64
|
+
#jp-minimap:hover .jp-mm-list {
|
|
65
|
+
align-items: stretch;
|
|
66
|
+
overflow-y: auto;
|
|
67
|
+
overscroll-behavior: contain;
|
|
68
|
+
background: rgba(127, 127, 127, 0.16);
|
|
69
|
+
backdrop-filter: blur(10px);
|
|
70
|
+
-webkit-backdrop-filter: blur(10px);
|
|
71
|
+
box-shadow: 0 6px 28px rgba(0, 0, 0, 0.28);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#jp-minimap:hover .jp-mm-bar { display: none; }
|
|
75
|
+
|
|
76
|
+
#jp-minimap:hover .jp-mm-item { justify-content: flex-start; }
|
|
77
|
+
|
|
78
|
+
#jp-minimap:hover .jp-mm-label {
|
|
79
|
+
display: block;
|
|
80
|
+
max-width: var(--jp-mm-width, 240px);
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
text-overflow: ellipsis;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* indent by heading level when expanded */
|
|
87
|
+
#jp-minimap:hover .jp-mm-l2 { padding-left: 16px; }
|
|
88
|
+
#jp-minimap:hover .jp-mm-l3 { padding-left: 28px; }
|
|
89
|
+
#jp-minimap:hover .jp-mm-l4 { padding-left: 40px; }
|
|
90
|
+
#jp-minimap:hover .jp-mm-l5 { padding-left: 52px; }
|
|
91
|
+
#jp-minimap:hover .jp-mm-l6 { padding-left: 52px; }
|
|
92
|
+
|
|
93
|
+
/* ---- shared states ---- */
|
|
94
|
+
|
|
95
|
+
.jp-mm-item:hover {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
background: rgba(127, 127, 127, 0.22);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.jp-mm-active { opacity: 1; }
|
|
101
|
+
|
|
102
|
+
#jp-minimap:hover .jp-mm-active {
|
|
103
|
+
background: rgba(127, 127, 127, 0.18);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* slim scrollbar in the expanded panel */
|
|
107
|
+
.jp-mm-list::-webkit-scrollbar { width: 4px; }
|
|
108
|
+
.jp-mm-list::-webkit-scrollbar-thumb {
|
|
109
|
+
background: rgba(127, 127, 127, 0.4);
|
|
110
|
+
border-radius: 2px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* don't show over printed/exported output */
|
|
114
|
+
@media print {
|
|
115
|
+
#jp-minimap { display: none; }
|
|
116
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* Content script: no markdown transformation needed.
|
|
2
|
+
* We only ship two assets into the rendered viewer:
|
|
3
|
+
* - minimap-view.js builds the minimap from the rendered DOM
|
|
4
|
+
* - minimap.css collapsed tick bars + hover-expanded ToC panel
|
|
5
|
+
*/
|
|
6
|
+
module.exports = {
|
|
7
|
+
default: function (_context) {
|
|
8
|
+
return {
|
|
9
|
+
plugin: function (_markdownIt, _options) {
|
|
10
|
+
// intentionally empty — rendering is untouched
|
|
11
|
+
},
|
|
12
|
+
assets: function () {
|
|
13
|
+
return [
|
|
14
|
+
{ name: 'minimap.css' },
|
|
15
|
+
{ name: 'minimap-view.js' },
|
|
16
|
+
];
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
};
|
|
Binary file
|