starlight-cannoli-plugins 2.8.3 → 2.9.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/README.md +4 -2
- package/dist/chunk-D3DPYGKF.js +96 -0
- package/dist/index.js +1 -1
- package/dist/plugins/starlight-dom-patches/page-script.d.ts +3 -2
- package/dist/plugins/starlight-dom-patches/page-script.js +51 -13
- package/dist/plugins/starlight-dom-patches.d.ts +13 -2
- package/dist/plugins/starlight-dom-patches.js +1 -1
- package/dist/styles/_starlight.scss +1 -16
- package/package.json +1 -1
- package/dist/chunk-OXJMUUGP.js +0 -50
package/README.md
CHANGED
|
@@ -398,7 +398,8 @@ An Astro integration that injects a client-side script to apply opt-in DOM patch
|
|
|
398
398
|
|
|
399
399
|
- `hideSingleLineGutters` (optional, default: `false`): Hides the line number gutter on Expressive Code blocks that contain only a single line.
|
|
400
400
|
- `syncTocLabelsFromHeadings` (optional, default: `false`): Copies the rendered HTML of each heading into its matching Starlight TOC anchor label, so the TOC properly reflects any custom markup (e.g. math) present in the heading.
|
|
401
|
-
- `
|
|
401
|
+
- `limitDetailsElementHeight` (optional, default: `false`): Limits the height of expanded `<details>` elements and makes their content scrollable.
|
|
402
|
+
- `offerToggleAllDetails` (optional, default: `false`): Injects an "Expand All Dropdowns" toggle checkbox into the right sidebar (before `nav[aria-labelledby="starlight__on-this-page"]`). Clicking it opens or closes every `<details>` element on the page at once. Only appears on pages that contain at least one visible `<details>` element.
|
|
402
403
|
- `offerTabbedContent` (optional, default: `false`): Injects a "Tabbed view" toggle checkbox immediately after `#starlight__on-this-page` in the right sidebar. When enabled by the user, the page's markdown content is reorganised into tabs — one per `<h2>` heading, plus an optional "Main" tab for any content that appears before the first `<h2>`. The toggle state is persisted to `localStorage`; active tab selection is not persisted. Only activates when the page has at least two sections (i.e. two or more `<h2>` elements, or one `<h2>` with pre-heading content). Has no effect on pages that lack `#starlight__on-this-page` (e.g. pages with the TOC disabled). Clicking a TOC anchor while tabs are enabled automatically switches to the tab containing the target heading. The generated elements use the classes `tabbed-content`, `tabbed-content-nav`, `tabbed-content-tab`, and `tabbed-content-panel` for styling; toggle button uses the existing `.toggle-checkbox-btn` class.
|
|
403
404
|
|
|
404
405
|
**Usage:**
|
|
@@ -414,7 +415,8 @@ export default defineConfig({
|
|
|
414
415
|
starlightDomPatches({
|
|
415
416
|
hideSingleLineGutters: true,
|
|
416
417
|
syncTocLabelsFromHeadings: true,
|
|
417
|
-
|
|
418
|
+
limitDetailsElementHeight: true,
|
|
419
|
+
offerToggleAllDetails: true,
|
|
418
420
|
offerTabbedContent: true,
|
|
419
421
|
}),
|
|
420
422
|
starlight({ title: "My Docs" }),
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/plugins/starlight-dom-patches/index.ts
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
var css = String.raw;
|
|
4
|
+
var js = String.raw;
|
|
5
|
+
var CONDITIONAL_CSS = {
|
|
6
|
+
limitDetailsElementHeight: {
|
|
7
|
+
enabled: css`
|
|
8
|
+
.main-pane details[open] {
|
|
9
|
+
max-width: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.main-pane details[open] > div.details-wrapper {
|
|
13
|
+
overflow: auto;
|
|
14
|
+
max-height: 67vh;
|
|
15
|
+
padding: 0 1em;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.main-pane details[open] p > img {
|
|
19
|
+
height: auto;
|
|
20
|
+
width: auto;
|
|
21
|
+
}
|
|
22
|
+
`,
|
|
23
|
+
disabled: css`
|
|
24
|
+
.main-pane details > *:not(summary) {
|
|
25
|
+
padding: 0 1rem;
|
|
26
|
+
margin: 1rem 0;
|
|
27
|
+
}
|
|
28
|
+
`
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function starlightDomPatches(options = {}) {
|
|
32
|
+
const {
|
|
33
|
+
hideSingleLineGutters = false,
|
|
34
|
+
syncTocLabelsFromHeadings = false,
|
|
35
|
+
limitDetailsElementHeight: limitDetailsElementHeightOption = false,
|
|
36
|
+
offerTabbedContent = false,
|
|
37
|
+
offerToggleAllDetails = false,
|
|
38
|
+
wrapDetailsContent
|
|
39
|
+
} = options;
|
|
40
|
+
if (wrapDetailsContent !== void 0) {
|
|
41
|
+
console.warn(
|
|
42
|
+
"[starlight-dom-patches] `wrapDetailsContent` is deprecated \u2014 use `limitDetailsElementHeight` instead."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const limitDetailsElementHeight = wrapDetailsContent ?? limitDetailsElementHeightOption;
|
|
46
|
+
return {
|
|
47
|
+
name: "starlight-dom-patches",
|
|
48
|
+
hooks: {
|
|
49
|
+
"astro:config:setup": ({ injectScript }) => {
|
|
50
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
51
|
+
let pageScriptUrl;
|
|
52
|
+
if (currentFile.endsWith(".ts")) {
|
|
53
|
+
pageScriptUrl = new URL("./page-script.ts", import.meta.url);
|
|
54
|
+
} else if (currentFile.endsWith("starlight-dom-patches.js")) {
|
|
55
|
+
pageScriptUrl = new URL(
|
|
56
|
+
"./starlight-dom-patches/page-script.js",
|
|
57
|
+
import.meta.url
|
|
58
|
+
);
|
|
59
|
+
} else {
|
|
60
|
+
pageScriptUrl = new URL(
|
|
61
|
+
"./plugins/starlight-dom-patches/page-script.js",
|
|
62
|
+
import.meta.url
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
for (const [key, entry] of Object.entries(CONDITIONAL_CSS)) {
|
|
66
|
+
const cssString = options[key] ? entry.enabled : entry.disabled;
|
|
67
|
+
if (cssString) {
|
|
68
|
+
injectScript(
|
|
69
|
+
"page",
|
|
70
|
+
js`{ const s = document.createElement("style"); s.textContent = ${JSON.stringify(cssString)}; document.head.appendChild(s); }`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const scriptPath = JSON.stringify(fileURLToPath(pageScriptUrl));
|
|
75
|
+
const imports = [
|
|
76
|
+
hideSingleLineGutters ? "hideSingleLineGutters" : null,
|
|
77
|
+
syncTocLabelsFromHeadings ? "syncTocLabelsFromHeadings" : null,
|
|
78
|
+
limitDetailsElementHeight ? "limitDetailsElementHeight" : null,
|
|
79
|
+
offerTabbedContent ? "tabbedH2Content" : null,
|
|
80
|
+
offerToggleAllDetails ? "toggleAllDetails" : null
|
|
81
|
+
].filter(Boolean);
|
|
82
|
+
if (imports.length === 0) return;
|
|
83
|
+
const calls = imports.map((fn) => `${fn}();`).join("\n");
|
|
84
|
+
injectScript(
|
|
85
|
+
"page",
|
|
86
|
+
`import { ${imports.join(", ")} } from ${scriptPath};
|
|
87
|
+
${calls}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
starlightDomPatches
|
|
96
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
declare function hideSingleLineGutters(): void;
|
|
2
2
|
declare function syncTocLabelsFromHeadings(): void;
|
|
3
3
|
declare function tabbedH2Content(): void;
|
|
4
|
-
declare function
|
|
4
|
+
declare function toggleAllDetails(): void;
|
|
5
|
+
declare function limitDetailsElementHeight(): void;
|
|
5
6
|
|
|
6
|
-
export { hideSingleLineGutters, syncTocLabelsFromHeadings, tabbedH2Content,
|
|
7
|
+
export { hideSingleLineGutters, limitDetailsElementHeight, syncTocLabelsFromHeadings, tabbedH2Content, toggleAllDetails };
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import "../../chunk-4VNS5WPM.js";
|
|
2
2
|
|
|
3
3
|
// src/plugins/starlight-dom-patches/page-script.ts
|
|
4
|
+
var TOC_NAV_SELECTOR = "nav[aria-labelledby='starlight__on-this-page']";
|
|
5
|
+
function appendToActionPanel(element) {
|
|
6
|
+
const tocNav = document.querySelector(TOC_NAV_SELECTOR);
|
|
7
|
+
if (!tocNav) return false;
|
|
8
|
+
let panel = tocNav.parentElement?.querySelector(
|
|
9
|
+
":scope > div.cannoli-actionable"
|
|
10
|
+
) ?? null;
|
|
11
|
+
if (!panel) {
|
|
12
|
+
panel = document.createElement("div");
|
|
13
|
+
panel.className = "cannoli-actionable";
|
|
14
|
+
tocNav.parentNode.insertBefore(panel, tocNav);
|
|
15
|
+
}
|
|
16
|
+
panel.appendChild(element);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
4
19
|
function hideSingleLineGutters() {
|
|
5
20
|
console.log("Hiding Single Line Gutters");
|
|
6
21
|
const codeElements = document.querySelectorAll(
|
|
@@ -48,15 +63,6 @@ function tabbedH2Content() {
|
|
|
48
63
|
);
|
|
49
64
|
return;
|
|
50
65
|
}
|
|
51
|
-
const tocNav = document.querySelector(
|
|
52
|
-
"nav[aria-labelledby='starlight__on-this-page']"
|
|
53
|
-
);
|
|
54
|
-
if (!tocNav) {
|
|
55
|
-
console.log(
|
|
56
|
-
"[tabbedH2Content] nav[aria-labelledby='starlight__on-this-page'] not found \u2014 aborting"
|
|
57
|
-
);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
66
|
const children = Array.from(container.children);
|
|
61
67
|
if (children.length === 0) {
|
|
62
68
|
console.log("[tabbedH2Content] content container is empty \u2014 aborting");
|
|
@@ -168,9 +174,9 @@ function tabbedH2Content() {
|
|
|
168
174
|
toggleText.textContent = "Tabbed view";
|
|
169
175
|
toggleLabel.appendChild(checkbox);
|
|
170
176
|
toggleLabel.appendChild(toggleText);
|
|
171
|
-
|
|
177
|
+
appendToActionPanel(toggleLabel);
|
|
172
178
|
console.log(
|
|
173
|
-
"[tabbedH2Content] toggle checkbox injected
|
|
179
|
+
"[tabbedH2Content] toggle checkbox injected into .cannoli-actionable panel"
|
|
174
180
|
);
|
|
175
181
|
const initialEnabled = localStorage.getItem(LS_KEY) === "enabled";
|
|
176
182
|
console.log(
|
|
@@ -183,7 +189,38 @@ function tabbedH2Content() {
|
|
|
183
189
|
localStorage.setItem(LS_KEY, checkbox.checked ? "enabled" : "disabled");
|
|
184
190
|
});
|
|
185
191
|
}
|
|
186
|
-
function
|
|
192
|
+
function toggleAllDetails() {
|
|
193
|
+
const detailsElements = document.querySelectorAll(
|
|
194
|
+
".main-pane details:not(.visually-hidden)"
|
|
195
|
+
);
|
|
196
|
+
if (detailsElements.length === 0) return;
|
|
197
|
+
const label = document.createElement("label");
|
|
198
|
+
label.id = "toggle-all-details-btn";
|
|
199
|
+
label.htmlFor = "toggle-all-details-checkbox";
|
|
200
|
+
label.className = "toggle-checkbox-btn";
|
|
201
|
+
const checkbox = document.createElement("input");
|
|
202
|
+
checkbox.type = "checkbox";
|
|
203
|
+
checkbox.id = "toggle-all-details-checkbox";
|
|
204
|
+
checkbox.setAttribute("aria-label", "Toggle all details open/closed");
|
|
205
|
+
const span = document.createElement("span");
|
|
206
|
+
span.className = "toggle-label";
|
|
207
|
+
span.textContent = "Expand All Dropdowns";
|
|
208
|
+
label.appendChild(checkbox);
|
|
209
|
+
label.appendChild(span);
|
|
210
|
+
appendToActionPanel(label);
|
|
211
|
+
let allOpen = false;
|
|
212
|
+
checkbox.addEventListener("change", () => {
|
|
213
|
+
document.body.dataset.bulkToggleActive = "true";
|
|
214
|
+
detailsElements.forEach((details) => {
|
|
215
|
+
details.open = !allOpen;
|
|
216
|
+
});
|
|
217
|
+
allOpen = !allOpen;
|
|
218
|
+
setTimeout(() => {
|
|
219
|
+
delete document.body.dataset.bulkToggleActive;
|
|
220
|
+
}, 10);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function limitDetailsElementHeight() {
|
|
187
224
|
console.log("Wrapping details element contents");
|
|
188
225
|
const detailsElements = document.querySelectorAll(".main-pane details");
|
|
189
226
|
detailsElements.forEach((details) => {
|
|
@@ -213,7 +250,8 @@ function wrapDetailsContent() {
|
|
|
213
250
|
}
|
|
214
251
|
export {
|
|
215
252
|
hideSingleLineGutters,
|
|
253
|
+
limitDetailsElementHeight,
|
|
216
254
|
syncTocLabelsFromHeadings,
|
|
217
255
|
tabbedH2Content,
|
|
218
|
-
|
|
256
|
+
toggleAllDetails
|
|
219
257
|
};
|
|
@@ -5,14 +5,25 @@ interface DomPatchesOptions {
|
|
|
5
5
|
hideSingleLineGutters?: boolean;
|
|
6
6
|
/** Copy rendered heading innerHTML into matching Starlight TOC anchor labels. @default false */
|
|
7
7
|
syncTocLabelsFromHeadings?: boolean;
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/** Limit the height of expanded `<details>` elements and make their content scrollable. @default false */
|
|
9
|
+
limitDetailsElementHeight?: boolean;
|
|
10
10
|
/**
|
|
11
11
|
* Inject a toggle checkbox (after `#starlight__on-this-page`) that reorganises page content
|
|
12
12
|
* into tabs driven by `<h2>` boundaries. Toggle state is persisted to localStorage.
|
|
13
13
|
* @default false
|
|
14
14
|
*/
|
|
15
15
|
offerTabbedContent?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Inject a "Expand All Dropdowns" toggle checkbox that opens or closes every
|
|
18
|
+
* `<details>` element on the page at once. Only appears on pages that contain
|
|
19
|
+
* at least one visible `<details>` element.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
offerToggleAllDetails?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Use `limitDetailsElementHeight` instead.
|
|
25
|
+
*/
|
|
26
|
+
wrapDetailsContent?: boolean;
|
|
16
27
|
}
|
|
17
28
|
/**
|
|
18
29
|
* Astro integration that injects a client-side script to apply DOM patches
|
|
@@ -76,21 +76,6 @@ starlight-toc ul > li {
|
|
|
76
76
|
html[data-theme="light"] & {
|
|
77
77
|
background: rgba(162, 171, 173, 0.08);
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
&[open] {
|
|
81
|
-
max-width: 100%;
|
|
82
|
-
|
|
83
|
-
> div.details-wrapper {
|
|
84
|
-
overflow: auto;
|
|
85
|
-
max-height: 67vh;
|
|
86
|
-
padding: 0 1em;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
p > img {
|
|
90
|
-
height: auto;
|
|
91
|
-
width: auto;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
79
|
}
|
|
95
80
|
|
|
96
81
|
/********** MathJax/LaTeX Styling **********/
|
|
@@ -186,7 +171,7 @@ div > div[class="page"] > svg {
|
|
|
186
171
|
}
|
|
187
172
|
}
|
|
188
173
|
|
|
189
|
-
|
|
174
|
+
.cannoli-actionable {
|
|
190
175
|
margin-bottom: 1rem;
|
|
191
176
|
}
|
|
192
177
|
|
package/package.json
CHANGED
package/dist/chunk-OXJMUUGP.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// src/plugins/starlight-dom-patches/index.ts
|
|
2
|
-
import { fileURLToPath } from "url";
|
|
3
|
-
function starlightDomPatches(options = {}) {
|
|
4
|
-
const {
|
|
5
|
-
hideSingleLineGutters = false,
|
|
6
|
-
syncTocLabelsFromHeadings = false,
|
|
7
|
-
wrapDetailsContent = false,
|
|
8
|
-
offerTabbedContent = false
|
|
9
|
-
} = options;
|
|
10
|
-
return {
|
|
11
|
-
name: "starlight-dom-patches",
|
|
12
|
-
hooks: {
|
|
13
|
-
"astro:config:setup": ({ injectScript }) => {
|
|
14
|
-
const currentFile = fileURLToPath(import.meta.url);
|
|
15
|
-
let pageScriptUrl;
|
|
16
|
-
if (currentFile.endsWith(".ts")) {
|
|
17
|
-
pageScriptUrl = new URL("./page-script.ts", import.meta.url);
|
|
18
|
-
} else if (currentFile.endsWith("starlight-dom-patches.js")) {
|
|
19
|
-
pageScriptUrl = new URL(
|
|
20
|
-
"./starlight-dom-patches/page-script.js",
|
|
21
|
-
import.meta.url
|
|
22
|
-
);
|
|
23
|
-
} else {
|
|
24
|
-
pageScriptUrl = new URL(
|
|
25
|
-
"./plugins/starlight-dom-patches/page-script.js",
|
|
26
|
-
import.meta.url
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
const scriptPath = JSON.stringify(fileURLToPath(pageScriptUrl));
|
|
30
|
-
const imports = [
|
|
31
|
-
hideSingleLineGutters ? "hideSingleLineGutters" : null,
|
|
32
|
-
syncTocLabelsFromHeadings ? "syncTocLabelsFromHeadings" : null,
|
|
33
|
-
wrapDetailsContent ? "wrapDetailsContent" : null,
|
|
34
|
-
offerTabbedContent ? "tabbedH2Content" : null
|
|
35
|
-
].filter(Boolean);
|
|
36
|
-
if (imports.length === 0) return;
|
|
37
|
-
const calls = imports.map((fn) => `${fn}();`).join("\n");
|
|
38
|
-
injectScript(
|
|
39
|
-
"page",
|
|
40
|
-
`import { ${imports.join(", ")} } from ${scriptPath};
|
|
41
|
-
${calls}`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export {
|
|
49
|
-
starlightDomPatches
|
|
50
|
-
};
|