@ox-content/vite-plugin 3.0.0-alpha.16 → 3.0.0-alpha.18
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.cjs +99 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -39
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +23 -39
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +38 -18
- package/dist/index.mjs.map +1 -1
- package/dist/markdown-tables.d.cts +13 -16
- package/dist/markdown-tables.d.cts.map +1 -1
- package/dist/markdown-tables.d.mts +13 -16
- package/dist/markdown-tables.d.mts.map +1 -1
- package/dist/napi.cjs +44 -0
- package/dist/napi.cjs.map +1 -0
- package/dist/napi.mjs +34 -0
- package/dist/napi.mjs.map +1 -0
- package/dist/reader-chrome-client.cjs +103 -0
- package/dist/reader-chrome-client.d.cts +2 -0
- package/dist/reader-chrome-client.d.mts +2 -0
- package/dist/reader-chrome-client.mjs +102 -0
- package/dist/reader-chrome.cjs +109 -0
- package/dist/reader-chrome.cjs.map +1 -0
- package/dist/reader-chrome.d.cts +103 -0
- package/dist/reader-chrome.d.mts +103 -0
- package/dist/reader-chrome.mjs +98 -0
- package/dist/reader-chrome.mjs.map +1 -0
- package/dist/styles/all.css +2 -0
- package/dist/styles/core.css +53 -1
- package/dist/styles/reader-chrome.css +163 -0
- package/dist/styles/theme-transition.css +37 -0
- package/dist/styles/twitter-full.css +87 -13
- package/dist/theme-tokens.d.cts +18 -21
- package/dist/theme-tokens.d.cts.map +1 -1
- package/dist/theme-tokens.d.mts +18 -21
- package/dist/theme-tokens.d.mts.map +1 -1
- package/dist/theme-transition-client.cjs +161 -0
- package/dist/theme-transition-client.d.cts +21 -0
- package/dist/theme-transition-client.d.mts +21 -0
- package/dist/theme-transition-client.mjs +160 -0
- package/dist/twitter-client.cjs +84 -0
- package/dist/twitter-client.d.cts +11 -0
- package/dist/twitter-client.d.mts +11 -0
- package/dist/twitter-client.mjs +83 -0
- package/dist/vitepress.cjs +5 -43
- package/dist/vitepress.cjs.map +1 -1
- package/dist/vitepress.mjs +5 -31
- package/dist/vitepress.mjs.map +1 -1
- package/package.json +46 -4
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
label?: string;
|
|
1
|
+
export interface MarkdownTableEnhancementOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Tables to enhance. Defaults to Markdown content tables styled by
|
|
4
|
+
* `@ox-content/vite-plugin/styles/core.css`.
|
|
5
|
+
*/
|
|
6
|
+
selector?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Accessible name applied only when an overflowing table has no existing
|
|
9
|
+
* `aria-label` or `aria-labelledby`.
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
13
12
|
}
|
|
14
|
-
declare function markdownTableScrollLabel(locale?: string): string;
|
|
13
|
+
export declare function markdownTableScrollLabel(locale?: string): string;
|
|
15
14
|
/**
|
|
16
15
|
* Makes overflowing Markdown tables keyboard-scrollable without wrapping or
|
|
17
16
|
* replacing the native `<table>` element.
|
|
@@ -19,7 +18,5 @@ declare function markdownTableScrollLabel(locale?: string): string;
|
|
|
19
18
|
* Run this after rendering Markdown and again after layout-changing updates.
|
|
20
19
|
* Narrow tables stay out of the tab order when overflow can be measured.
|
|
21
20
|
*/
|
|
22
|
-
declare function enhanceMarkdownTables(root?: ParentNode, options?: MarkdownTableEnhancementOptions): number;
|
|
23
|
-
//#endregion
|
|
24
|
-
export { MarkdownTableEnhancementOptions, enhanceMarkdownTables, markdownTableScrollLabel };
|
|
21
|
+
export declare function enhanceMarkdownTables(root?: ParentNode, options?: MarkdownTableEnhancementOptions): number;
|
|
25
22
|
//# sourceMappingURL=markdown-tables.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-tables.d.cts","
|
|
1
|
+
{"version":3,"file":"markdown-tables.d.cts","sourceRoot":"","sources":["../../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,+BAA+B;IAC9C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,UAAU,EACjB,OAAO,GAAE,+BAAoC,GAC5C,MAAM,CA4CR"}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
label?: string;
|
|
1
|
+
export interface MarkdownTableEnhancementOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Tables to enhance. Defaults to Markdown content tables styled by
|
|
4
|
+
* `@ox-content/vite-plugin/styles/core.css`.
|
|
5
|
+
*/
|
|
6
|
+
selector?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Accessible name applied only when an overflowing table has no existing
|
|
9
|
+
* `aria-label` or `aria-labelledby`.
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
13
12
|
}
|
|
14
|
-
declare function markdownTableScrollLabel(locale?: string): string;
|
|
13
|
+
export declare function markdownTableScrollLabel(locale?: string): string;
|
|
15
14
|
/**
|
|
16
15
|
* Makes overflowing Markdown tables keyboard-scrollable without wrapping or
|
|
17
16
|
* replacing the native `<table>` element.
|
|
@@ -19,7 +18,5 @@ declare function markdownTableScrollLabel(locale?: string): string;
|
|
|
19
18
|
* Run this after rendering Markdown and again after layout-changing updates.
|
|
20
19
|
* Narrow tables stay out of the tab order when overflow can be measured.
|
|
21
20
|
*/
|
|
22
|
-
declare function enhanceMarkdownTables(root?: ParentNode, options?: MarkdownTableEnhancementOptions): number;
|
|
23
|
-
//#endregion
|
|
24
|
-
export { MarkdownTableEnhancementOptions, enhanceMarkdownTables, markdownTableScrollLabel };
|
|
21
|
+
export declare function enhanceMarkdownTables(root?: ParentNode, options?: MarkdownTableEnhancementOptions): number;
|
|
25
22
|
//# sourceMappingURL=markdown-tables.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-tables.d.mts","
|
|
1
|
+
{"version":3,"file":"markdown-tables.d.mts","sourceRoot":"","sources":["../../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,+BAA+B;IAC9C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,UAAU,EACjB,OAAO,GAAE,+BAAoC,GAC5C,MAAM,CA4CR"}
|
package/dist/napi.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/napi.ts
|
|
2
|
+
const requireNapi = (0, require("node:module").createRequire)(require("url").pathToFileURL(__filename).href);
|
|
3
|
+
function getDefaultExport(value) {
|
|
4
|
+
if (!value || typeof value !== "object" || !("default" in value)) return;
|
|
5
|
+
const defaultExport = value.default;
|
|
6
|
+
return defaultExport && typeof defaultExport === "object" ? defaultExport : void 0;
|
|
7
|
+
}
|
|
8
|
+
function normalizeNapiModule(mod) {
|
|
9
|
+
const defaultExport = getDefaultExport(mod);
|
|
10
|
+
return defaultExport ? {
|
|
11
|
+
...defaultExport,
|
|
12
|
+
...mod
|
|
13
|
+
} : mod;
|
|
14
|
+
}
|
|
15
|
+
async function importNapiModule() {
|
|
16
|
+
return normalizeNapiModule(await import("@ox-content/napi"));
|
|
17
|
+
}
|
|
18
|
+
let syncNapiModule;
|
|
19
|
+
function importNapiModuleSync() {
|
|
20
|
+
if (syncNapiModule) return syncNapiModule;
|
|
21
|
+
if (syncNapiModule === null) throw new Error("[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.");
|
|
22
|
+
try {
|
|
23
|
+
syncNapiModule = normalizeNapiModule(requireNapi("@ox-content/napi"));
|
|
24
|
+
return syncNapiModule;
|
|
25
|
+
} catch {
|
|
26
|
+
syncNapiModule = null;
|
|
27
|
+
throw new Error("[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
Object.defineProperty(exports, "importNapiModule", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function() {
|
|
34
|
+
return importNapiModule;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
Object.defineProperty(exports, "importNapiModuleSync", {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
get: function() {
|
|
40
|
+
return importNapiModuleSync;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=napi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"napi.cjs","names":["createRequire"],"sources":["../src/napi.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\ntype NapiModule = typeof import(\"@ox-content/napi\");\nconst requireNapi = createRequire(import.meta.url);\n\nfunction getDefaultExport(value: unknown): object | undefined {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return undefined;\n }\n\n const defaultExport = value.default;\n return defaultExport && typeof defaultExport === \"object\" ? defaultExport : undefined;\n}\n\nfunction normalizeNapiModule(mod: NapiModule): NapiModule {\n const defaultExport = getDefaultExport(mod);\n return defaultExport\n ? ({\n ...defaultExport,\n ...mod,\n } as NapiModule)\n : mod;\n}\n\nexport async function importNapiModule(): Promise<NapiModule> {\n return normalizeNapiModule((await import(\"@ox-content/napi\")) as NapiModule);\n}\n\nlet syncNapiModule: NapiModule | null | undefined;\n\nexport function importNapiModuleSync(): NapiModule {\n if (syncNapiModule) {\n return syncNapiModule;\n }\n\n if (syncNapiModule === null) {\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n\n try {\n const mod = requireNapi(\"@ox-content/napi\") as NapiModule;\n syncNapiModule = normalizeNapiModule(mod);\n return syncNapiModule;\n } catch {\n syncNapiModule = null;\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n}\n"],"mappings":";AAGA,MAAM,eAAA,wBAAcA,CAAAA,CAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B;AAEjD,SAAS,iBAAiB,OAAoC;CAC5D,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,aAAa,QACxD;CAGF,MAAM,gBAAgB,MAAM;CAC5B,OAAO,iBAAiB,OAAO,kBAAkB,WAAW,gBAAgB,KAAA;AAC9E;AAEA,SAAS,oBAAoB,KAA6B;CACxD,MAAM,gBAAgB,iBAAiB,GAAG;CAC1C,OAAO,gBACF;EACC,GAAG;EACH,GAAG;CACL,IACA;AACN;AAEA,eAAsB,mBAAwC;CAC5D,OAAO,oBAAqB,MAAM,OAAO,mBAAkC;AAC7E;AAEA,IAAI;AAEJ,SAAgB,uBAAmC;CACjD,IAAI,gBACF,OAAO;CAGT,IAAI,mBAAmB,MACrB,MAAM,IAAI,MACR,oFACF;CAGF,IAAI;EAEF,iBAAiB,oBADL,YAAY,kBACe,CAAC;EACxC,OAAO;CACT,QAAQ;EACN,iBAAiB;EACjB,MAAM,IAAI,MACR,oFACF;CACF;AACF"}
|
package/dist/napi.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region src/napi.ts
|
|
3
|
+
const requireNapi = createRequire(import.meta.url);
|
|
4
|
+
function getDefaultExport(value) {
|
|
5
|
+
if (!value || typeof value !== "object" || !("default" in value)) return;
|
|
6
|
+
const defaultExport = value.default;
|
|
7
|
+
return defaultExport && typeof defaultExport === "object" ? defaultExport : void 0;
|
|
8
|
+
}
|
|
9
|
+
function normalizeNapiModule(mod) {
|
|
10
|
+
const defaultExport = getDefaultExport(mod);
|
|
11
|
+
return defaultExport ? {
|
|
12
|
+
...defaultExport,
|
|
13
|
+
...mod
|
|
14
|
+
} : mod;
|
|
15
|
+
}
|
|
16
|
+
async function importNapiModule() {
|
|
17
|
+
return normalizeNapiModule(await import("@ox-content/napi"));
|
|
18
|
+
}
|
|
19
|
+
let syncNapiModule;
|
|
20
|
+
function importNapiModuleSync() {
|
|
21
|
+
if (syncNapiModule) return syncNapiModule;
|
|
22
|
+
if (syncNapiModule === null) throw new Error("[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.");
|
|
23
|
+
try {
|
|
24
|
+
syncNapiModule = normalizeNapiModule(requireNapi("@ox-content/napi"));
|
|
25
|
+
return syncNapiModule;
|
|
26
|
+
} catch {
|
|
27
|
+
syncNapiModule = null;
|
|
28
|
+
throw new Error("[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { importNapiModuleSync as n, importNapiModule as t };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=napi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"napi.mjs","names":[],"sources":["../src/napi.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\ntype NapiModule = typeof import(\"@ox-content/napi\");\nconst requireNapi = createRequire(import.meta.url);\n\nfunction getDefaultExport(value: unknown): object | undefined {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return undefined;\n }\n\n const defaultExport = value.default;\n return defaultExport && typeof defaultExport === \"object\" ? defaultExport : undefined;\n}\n\nfunction normalizeNapiModule(mod: NapiModule): NapiModule {\n const defaultExport = getDefaultExport(mod);\n return defaultExport\n ? ({\n ...defaultExport,\n ...mod,\n } as NapiModule)\n : mod;\n}\n\nexport async function importNapiModule(): Promise<NapiModule> {\n return normalizeNapiModule((await import(\"@ox-content/napi\")) as NapiModule);\n}\n\nlet syncNapiModule: NapiModule | null | undefined;\n\nexport function importNapiModuleSync(): NapiModule {\n if (syncNapiModule) {\n return syncNapiModule;\n }\n\n if (syncNapiModule === null) {\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n\n try {\n const mod = requireNapi(\"@ox-content/napi\") as NapiModule;\n syncNapiModule = normalizeNapiModule(mod);\n return syncNapiModule;\n } catch {\n syncNapiModule = null;\n throw new Error(\n \"[ox-content] @ox-content/napi is required. Please ensure the NAPI module is built.\",\n );\n }\n}\n"],"mappings":";;AAGA,MAAM,cAAc,cAAc,YAAY,GAAG;AAEjD,SAAS,iBAAiB,OAAoC;CAC5D,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,aAAa,QACxD;CAGF,MAAM,gBAAgB,MAAM;CAC5B,OAAO,iBAAiB,OAAO,kBAAkB,WAAW,gBAAgB,KAAA;AAC9E;AAEA,SAAS,oBAAoB,KAA6B;CACxD,MAAM,gBAAgB,iBAAiB,GAAG;CAC1C,OAAO,gBACF;EACC,GAAG;EACH,GAAG;CACL,IACA;AACN;AAEA,eAAsB,mBAAwC;CAC5D,OAAO,oBAAqB,MAAM,OAAO,mBAAkC;AAC7E;AAEA,IAAI;AAEJ,SAAgB,uBAAmC;CACjD,IAAI,gBACF,OAAO;CAGT,IAAI,mBAAmB,MACrB,MAAM,IAAI,MACR,oFACF;CAGF,IAAI;EAEF,iBAAiB,oBADL,YAAY,kBACe,CAAC;EACxC,OAAO;CACT,QAAQ;EACN,iBAAiB;EACjB,MAAM,IAAI,MACR,oFACF;CACF;AACF"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Generated from crates/ox_content_ssg/src/html/reader_chrome_runtime.js.
|
|
2
|
+
// Run npm/vite-plugin-ox-content/scripts/build-reader-chrome-client.mjs.
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
const oxReaderChromeInitializedRoots = new WeakSet();
|
|
6
|
+
const oxReaderChromeResetTimers = new WeakMap();
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line no-unused-vars
|
|
9
|
+
function initReaderChrome(rootInput) {
|
|
10
|
+
const fallbackDocument = typeof document === "undefined" ? undefined : document;
|
|
11
|
+
const root = rootInput ?? fallbackDocument;
|
|
12
|
+
if (!root || oxReaderChromeInitializedRoots.has(root)) return;
|
|
13
|
+
|
|
14
|
+
const scope = root.nodeType === 9 ? root : root;
|
|
15
|
+
const rootElement = root.nodeType === 9 ? root.documentElement : root;
|
|
16
|
+
if (!rootElement || typeof rootElement.querySelector !== "function") return;
|
|
17
|
+
|
|
18
|
+
const hasRootAttribute =
|
|
19
|
+
typeof rootElement.hasAttribute === "function"
|
|
20
|
+
? (name) => rootElement.hasAttribute(name)
|
|
21
|
+
: () => false;
|
|
22
|
+
const hasCopy =
|
|
23
|
+
hasRootAttribute("data-ox-copy") || Boolean(rootElement.querySelector("[data-ox-copy]"));
|
|
24
|
+
const hasBackToTop =
|
|
25
|
+
hasRootAttribute("data-ox-back-to-top") ||
|
|
26
|
+
Boolean(rootElement.querySelector(".ox-back-to-top[data-ox-back-to-top]"));
|
|
27
|
+
const hasReaderChrome = hasRootAttribute("data-ox-reader-chrome");
|
|
28
|
+
if (!hasReaderChrome && !hasCopy && !hasBackToTop) return;
|
|
29
|
+
|
|
30
|
+
oxReaderChromeInitializedRoots.add(root);
|
|
31
|
+
|
|
32
|
+
const reduced =
|
|
33
|
+
typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
34
|
+
if (reduced && rootElement.classList)
|
|
35
|
+
rootElement.classList.add("ox-reader-chrome--reduced-motion");
|
|
36
|
+
|
|
37
|
+
if (hasCopy && typeof scope.addEventListener === "function") {
|
|
38
|
+
scope.addEventListener("click", (event) => {
|
|
39
|
+
const button =
|
|
40
|
+
event.target instanceof Element ? event.target.closest("[data-ox-copy]") : null;
|
|
41
|
+
if (!(button instanceof HTMLButtonElement)) return;
|
|
42
|
+
if (event.defaultPrevented) return;
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
const container = button.closest(".ox-code");
|
|
45
|
+
const pre = container?.querySelector("pre");
|
|
46
|
+
const status = container?.querySelector("[data-ox-copy-status]");
|
|
47
|
+
const text = pre ? (pre.getAttribute("data-ox-code-source") ?? pre.textContent ?? "") : "";
|
|
48
|
+
if (!navigator.clipboard?.writeText) {
|
|
49
|
+
setReaderChromeCopyState(button, status, "failed");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
navigator.clipboard
|
|
53
|
+
.writeText(text)
|
|
54
|
+
.then(() => setReaderChromeCopyState(button, status, "copied"))
|
|
55
|
+
.catch(() => setReaderChromeCopyState(button, status, "failed"));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (hasBackToTop && fallbackDocument) {
|
|
60
|
+
const findBackToTop = () => rootElement.querySelector(".ox-back-to-top[data-ox-back-to-top]");
|
|
61
|
+
const sync = () => {
|
|
62
|
+
const top = findBackToTop();
|
|
63
|
+
if (top instanceof HTMLElement) top.hidden = window.scrollY < 320;
|
|
64
|
+
};
|
|
65
|
+
sync();
|
|
66
|
+
window.addEventListener("scroll", sync, { passive: true });
|
|
67
|
+
if (typeof scope.addEventListener === "function") {
|
|
68
|
+
scope.addEventListener("click", (event) => {
|
|
69
|
+
const button =
|
|
70
|
+
event.target instanceof Element
|
|
71
|
+
? event.target.closest(".ox-back-to-top[data-ox-back-to-top]")
|
|
72
|
+
: null;
|
|
73
|
+
if (!(button instanceof HTMLElement)) return;
|
|
74
|
+
if (event.defaultPrevented) return;
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
window.scrollTo({ top: 0, behavior: reduced ? "auto" : "smooth" });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function setReaderChromeCopyState(button, status, state) {
|
|
83
|
+
const previousTimer = oxReaderChromeResetTimers.get(button);
|
|
84
|
+
if (previousTimer) clearTimeout(previousTimer);
|
|
85
|
+
|
|
86
|
+
const label = state === "copied" ? "Copied" : state === "failed" ? "Copy failed" : "Copy code";
|
|
87
|
+
if (state) button.dataset.copyState = state;
|
|
88
|
+
else delete button.dataset.copyState;
|
|
89
|
+
button.setAttribute("aria-label", label);
|
|
90
|
+
button.setAttribute("title", label);
|
|
91
|
+
if (status) status.textContent = state ? label : "";
|
|
92
|
+
|
|
93
|
+
if (state) {
|
|
94
|
+
oxReaderChromeResetTimers.set(
|
|
95
|
+
button,
|
|
96
|
+
setTimeout(() => setReaderChromeCopyState(button, status, null), 1500),
|
|
97
|
+
);
|
|
98
|
+
} else {
|
|
99
|
+
oxReaderChromeResetTimers.delete(button);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { initReaderChrome };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Generated from crates/ox_content_ssg/src/html/reader_chrome_runtime.js.
|
|
2
|
+
// Run npm/vite-plugin-ox-content/scripts/build-reader-chrome-client.mjs.
|
|
3
|
+
|
|
4
|
+
const oxReaderChromeInitializedRoots = new WeakSet();
|
|
5
|
+
const oxReaderChromeResetTimers = new WeakMap();
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line no-unused-vars
|
|
8
|
+
function initReaderChrome(rootInput) {
|
|
9
|
+
const fallbackDocument = typeof document === "undefined" ? undefined : document;
|
|
10
|
+
const root = rootInput ?? fallbackDocument;
|
|
11
|
+
if (!root || oxReaderChromeInitializedRoots.has(root)) return;
|
|
12
|
+
|
|
13
|
+
const scope = root.nodeType === 9 ? root : root;
|
|
14
|
+
const rootElement = root.nodeType === 9 ? root.documentElement : root;
|
|
15
|
+
if (!rootElement || typeof rootElement.querySelector !== "function") return;
|
|
16
|
+
|
|
17
|
+
const hasRootAttribute =
|
|
18
|
+
typeof rootElement.hasAttribute === "function"
|
|
19
|
+
? (name) => rootElement.hasAttribute(name)
|
|
20
|
+
: () => false;
|
|
21
|
+
const hasCopy =
|
|
22
|
+
hasRootAttribute("data-ox-copy") || Boolean(rootElement.querySelector("[data-ox-copy]"));
|
|
23
|
+
const hasBackToTop =
|
|
24
|
+
hasRootAttribute("data-ox-back-to-top") ||
|
|
25
|
+
Boolean(rootElement.querySelector(".ox-back-to-top[data-ox-back-to-top]"));
|
|
26
|
+
const hasReaderChrome = hasRootAttribute("data-ox-reader-chrome");
|
|
27
|
+
if (!hasReaderChrome && !hasCopy && !hasBackToTop) return;
|
|
28
|
+
|
|
29
|
+
oxReaderChromeInitializedRoots.add(root);
|
|
30
|
+
|
|
31
|
+
const reduced =
|
|
32
|
+
typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
33
|
+
if (reduced && rootElement.classList)
|
|
34
|
+
rootElement.classList.add("ox-reader-chrome--reduced-motion");
|
|
35
|
+
|
|
36
|
+
if (hasCopy && typeof scope.addEventListener === "function") {
|
|
37
|
+
scope.addEventListener("click", (event) => {
|
|
38
|
+
const button =
|
|
39
|
+
event.target instanceof Element ? event.target.closest("[data-ox-copy]") : null;
|
|
40
|
+
if (!(button instanceof HTMLButtonElement)) return;
|
|
41
|
+
if (event.defaultPrevented) return;
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
const container = button.closest(".ox-code");
|
|
44
|
+
const pre = container?.querySelector("pre");
|
|
45
|
+
const status = container?.querySelector("[data-ox-copy-status]");
|
|
46
|
+
const text = pre ? (pre.getAttribute("data-ox-code-source") ?? pre.textContent ?? "") : "";
|
|
47
|
+
if (!navigator.clipboard?.writeText) {
|
|
48
|
+
setReaderChromeCopyState(button, status, "failed");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
navigator.clipboard
|
|
52
|
+
.writeText(text)
|
|
53
|
+
.then(() => setReaderChromeCopyState(button, status, "copied"))
|
|
54
|
+
.catch(() => setReaderChromeCopyState(button, status, "failed"));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (hasBackToTop && fallbackDocument) {
|
|
59
|
+
const findBackToTop = () => rootElement.querySelector(".ox-back-to-top[data-ox-back-to-top]");
|
|
60
|
+
const sync = () => {
|
|
61
|
+
const top = findBackToTop();
|
|
62
|
+
if (top instanceof HTMLElement) top.hidden = window.scrollY < 320;
|
|
63
|
+
};
|
|
64
|
+
sync();
|
|
65
|
+
window.addEventListener("scroll", sync, { passive: true });
|
|
66
|
+
if (typeof scope.addEventListener === "function") {
|
|
67
|
+
scope.addEventListener("click", (event) => {
|
|
68
|
+
const button =
|
|
69
|
+
event.target instanceof Element
|
|
70
|
+
? event.target.closest(".ox-back-to-top[data-ox-back-to-top]")
|
|
71
|
+
: null;
|
|
72
|
+
if (!(button instanceof HTMLElement)) return;
|
|
73
|
+
if (event.defaultPrevented) return;
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
window.scrollTo({ top: 0, behavior: reduced ? "auto" : "smooth" });
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function setReaderChromeCopyState(button, status, state) {
|
|
82
|
+
const previousTimer = oxReaderChromeResetTimers.get(button);
|
|
83
|
+
if (previousTimer) clearTimeout(previousTimer);
|
|
84
|
+
|
|
85
|
+
const label = state === "copied" ? "Copied" : state === "failed" ? "Copy failed" : "Copy code";
|
|
86
|
+
if (state) button.dataset.copyState = state;
|
|
87
|
+
else delete button.dataset.copyState;
|
|
88
|
+
button.setAttribute("aria-label", label);
|
|
89
|
+
button.setAttribute("title", label);
|
|
90
|
+
if (status) status.textContent = state ? label : "";
|
|
91
|
+
|
|
92
|
+
if (state) {
|
|
93
|
+
oxReaderChromeResetTimers.set(
|
|
94
|
+
button,
|
|
95
|
+
setTimeout(() => setReaderChromeCopyState(button, status, null), 1500),
|
|
96
|
+
);
|
|
97
|
+
} else {
|
|
98
|
+
oxReaderChromeResetTimers.delete(button);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { initReaderChrome };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./vitepress.cjs");
|
|
3
|
+
const require_napi = require("./napi.cjs");
|
|
4
|
+
//#region src/reader-chrome.ts
|
|
5
|
+
const EMPTY_ATTRIBUTES = Object.freeze({});
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the public reader-chrome option shape.
|
|
8
|
+
*
|
|
9
|
+
* `true` mirrors `ssg.readerChrome: true`: copy, outbound-link decoration, and
|
|
10
|
+
* back-to-top are enabled. Object fields default on, so `{ copy: false }`
|
|
11
|
+
* disables only the copy button.
|
|
12
|
+
*/
|
|
13
|
+
function resolveReaderChromeInput(input = true) {
|
|
14
|
+
if (!input) return false;
|
|
15
|
+
if (input === true) return {
|
|
16
|
+
copy: true,
|
|
17
|
+
externalLinks: true,
|
|
18
|
+
backToTop: true
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
copy: input.copy ?? true,
|
|
22
|
+
externalLinks: input.externalLinks ?? true,
|
|
23
|
+
backToTop: input.backToTop ?? true
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Apply the same native reader-chrome HTML transform used by the built-in SSG.
|
|
28
|
+
*
|
|
29
|
+
* This rewrites rendered article HTML. It wraps fenced `<pre>` blocks for copy
|
|
30
|
+
* controls and decorates outbound links when enabled. Back-to-top remains a
|
|
31
|
+
* document-shell control, so it is exposed through the asset helpers.
|
|
32
|
+
*/
|
|
33
|
+
function applyReaderChromeHtml(html, input = true) {
|
|
34
|
+
const chrome = resolveReaderChromeInput(input);
|
|
35
|
+
if (!chrome || !chrome.copy && !chrome.externalLinks) return html;
|
|
36
|
+
return require_napi.importNapiModuleSync().applySsgReaderChromeHtml(html, {
|
|
37
|
+
copy: chrome.copy,
|
|
38
|
+
externalLinks: chrome.externalLinks,
|
|
39
|
+
backToTop: chrome.backToTop
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Root attributes consumed by the browser runtime.
|
|
44
|
+
*/
|
|
45
|
+
function readerChromeAttributes(input = true) {
|
|
46
|
+
const chrome = resolveReaderChromeInput(input);
|
|
47
|
+
if (!readerChromeIsEnabled(chrome)) return EMPTY_ATTRIBUTES;
|
|
48
|
+
return {
|
|
49
|
+
"data-ox-reader-chrome": "",
|
|
50
|
+
...chrome.copy ? { "data-ox-copy": "" } : {},
|
|
51
|
+
...chrome.externalLinks ? { "data-ox-external-links": "" } : {},
|
|
52
|
+
...chrome.backToTop ? { "data-ox-back-to-top": "" } : {}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Render the root attributes as a leading-space HTML fragment.
|
|
57
|
+
*
|
|
58
|
+
* Useful in template strings: `<article${renderReaderChromeAttributes()}>`.
|
|
59
|
+
*/
|
|
60
|
+
function renderReaderChromeAttributes(input = true) {
|
|
61
|
+
return Object.keys(readerChromeAttributes(input)).map((name) => ` ${name}`).join("");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* CSS shared by the built-in SSG and custom hosts.
|
|
65
|
+
*/
|
|
66
|
+
function readerChromeCss(input = true) {
|
|
67
|
+
return readerChromeIsEnabled(resolveReaderChromeInput(input)) ? require_napi.importNapiModuleSync().getSsgReaderChromeCss() : "";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Auto-initializing script shared by the built-in SSG and custom hosts.
|
|
71
|
+
*/
|
|
72
|
+
function readerChromeScript(input = true) {
|
|
73
|
+
return readerChromeNeedsJs(resolveReaderChromeInput(input)) ? require_napi.importNapiModuleSync().getSsgReaderChromeScript() : "";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Inline stylesheet tag for hosts that do not import
|
|
77
|
+
* `@ox-content/vite-plugin/styles/reader-chrome.css`.
|
|
78
|
+
*/
|
|
79
|
+
function renderReaderChromeStyleTag(input = true) {
|
|
80
|
+
const css = readerChromeCss(input);
|
|
81
|
+
return css ? `<style data-ox-style="reader-chrome">\n${css}</style>` : "";
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Inline auto-init script for static hosts that do not bundle
|
|
85
|
+
* `@ox-content/vite-plugin/reader-chrome/client`.
|
|
86
|
+
*/
|
|
87
|
+
function renderReaderChromeScriptTag(input = true) {
|
|
88
|
+
const js = readerChromeScript(input);
|
|
89
|
+
return js ? `<script data-ox-script="reader-chrome">\n${js}<\/script>` : "";
|
|
90
|
+
}
|
|
91
|
+
function readerChromeIsEnabled(chrome) {
|
|
92
|
+
return Boolean(chrome && (chrome.copy || chrome.externalLinks || chrome.backToTop));
|
|
93
|
+
}
|
|
94
|
+
function readerChromeNeedsJs(chrome) {
|
|
95
|
+
return Boolean(chrome && (chrome.copy || chrome.backToTop));
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
exports.applyReaderChromeHtml = applyReaderChromeHtml;
|
|
99
|
+
exports.readerChromeAttributes = readerChromeAttributes;
|
|
100
|
+
exports.readerChromeCss = readerChromeCss;
|
|
101
|
+
exports.readerChromeIsEnabled = readerChromeIsEnabled;
|
|
102
|
+
exports.readerChromeNeedsJs = readerChromeNeedsJs;
|
|
103
|
+
exports.readerChromeScript = readerChromeScript;
|
|
104
|
+
exports.renderReaderChromeAttributes = renderReaderChromeAttributes;
|
|
105
|
+
exports.renderReaderChromeScriptTag = renderReaderChromeScriptTag;
|
|
106
|
+
exports.renderReaderChromeStyleTag = renderReaderChromeStyleTag;
|
|
107
|
+
exports.resolveReaderChromeInput = resolveReaderChromeInput;
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=reader-chrome.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader-chrome.cjs","names":["importNapiModuleSync"],"sources":["../src/reader-chrome.ts"],"sourcesContent":["import { importNapiModuleSync } from \"./napi\";\nimport type { ReaderChromeOptions, ResolvedReaderChrome } from \"./reader-chrome-options\";\n\nexport type { ReaderChromeOptions, ResolvedReaderChrome };\n\ntype EnabledReaderChrome = Exclude<ResolvedReaderChrome, false>;\n\nexport type ReaderChromeInput = boolean | ReaderChromeOptions | EnabledReaderChrome | undefined;\n\nconst EMPTY_ATTRIBUTES = Object.freeze({}) as Readonly<Record<string, \"\">>;\n\n/**\n * Resolve the public reader-chrome option shape.\n *\n * `true` mirrors `ssg.readerChrome: true`: copy, outbound-link decoration, and\n * back-to-top are enabled. Object fields default on, so `{ copy: false }`\n * disables only the copy button.\n */\nexport function resolveReaderChromeInput(input: ReaderChromeInput = true): ResolvedReaderChrome {\n if (!input) {\n return false;\n }\n if (input === true) {\n return { copy: true, externalLinks: true, backToTop: true };\n }\n return {\n copy: input.copy ?? true,\n externalLinks: input.externalLinks ?? true,\n backToTop: input.backToTop ?? true,\n };\n}\n\n/**\n * Apply the same native reader-chrome HTML transform used by the built-in SSG.\n *\n * This rewrites rendered article HTML. It wraps fenced `<pre>` blocks for copy\n * controls and decorates outbound links when enabled. Back-to-top remains a\n * document-shell control, so it is exposed through the asset helpers.\n */\nexport function applyReaderChromeHtml(html: string, input: ReaderChromeInput = true): string {\n const chrome = resolveReaderChromeInput(input);\n if (!chrome || (!chrome.copy && !chrome.externalLinks)) {\n return html;\n }\n return importNapiModuleSync().applySsgReaderChromeHtml(html, {\n copy: chrome.copy,\n externalLinks: chrome.externalLinks,\n backToTop: chrome.backToTop,\n });\n}\n\n/**\n * Root attributes consumed by the browser runtime.\n */\nexport function readerChromeAttributes(\n input: ReaderChromeInput = true,\n): Readonly<Record<string, \"\">> {\n const chrome = resolveReaderChromeInput(input);\n if (!readerChromeIsEnabled(chrome)) {\n return EMPTY_ATTRIBUTES;\n }\n\n return {\n \"data-ox-reader-chrome\": \"\",\n ...(chrome.copy ? { \"data-ox-copy\": \"\" as const } : {}),\n ...(chrome.externalLinks ? { \"data-ox-external-links\": \"\" as const } : {}),\n ...(chrome.backToTop ? { \"data-ox-back-to-top\": \"\" as const } : {}),\n };\n}\n\n/**\n * Render the root attributes as a leading-space HTML fragment.\n *\n * Useful in template strings: `<article${renderReaderChromeAttributes()}>`.\n */\nexport function renderReaderChromeAttributes(input: ReaderChromeInput = true): string {\n return Object.keys(readerChromeAttributes(input))\n .map((name) => ` ${name}`)\n .join(\"\");\n}\n\n/**\n * CSS shared by the built-in SSG and custom hosts.\n */\nexport function readerChromeCss(input: ReaderChromeInput = true): string {\n return readerChromeIsEnabled(resolveReaderChromeInput(input))\n ? importNapiModuleSync().getSsgReaderChromeCss()\n : \"\";\n}\n\n/**\n * Auto-initializing script shared by the built-in SSG and custom hosts.\n */\nexport function readerChromeScript(input: ReaderChromeInput = true): string {\n return readerChromeNeedsJs(resolveReaderChromeInput(input))\n ? importNapiModuleSync().getSsgReaderChromeScript()\n : \"\";\n}\n\n/**\n * Inline stylesheet tag for hosts that do not import\n * `@ox-content/vite-plugin/styles/reader-chrome.css`.\n */\nexport function renderReaderChromeStyleTag(input: ReaderChromeInput = true): string {\n const css = readerChromeCss(input);\n return css ? `<style data-ox-style=\"reader-chrome\">\\n${css}</style>` : \"\";\n}\n\n/**\n * Inline auto-init script for static hosts that do not bundle\n * `@ox-content/vite-plugin/reader-chrome/client`.\n */\nexport function renderReaderChromeScriptTag(input: ReaderChromeInput = true): string {\n const js = readerChromeScript(input);\n return js ? `<script data-ox-script=\"reader-chrome\">\\n${js}</script>` : \"\";\n}\n\nexport function readerChromeIsEnabled(\n chrome: ResolvedReaderChrome,\n): chrome is Exclude<ResolvedReaderChrome, false> {\n return Boolean(chrome && (chrome.copy || chrome.externalLinks || chrome.backToTop));\n}\n\nexport function readerChromeNeedsJs(chrome: ResolvedReaderChrome): boolean {\n return Boolean(chrome && (chrome.copy || chrome.backToTop));\n}\n"],"mappings":";;;;AASA,MAAM,mBAAmB,OAAO,OAAO,CAAC,CAAC;;;;;;;;AASzC,SAAgB,yBAAyB,QAA2B,MAA4B;CAC9F,IAAI,CAAC,OACH,OAAO;CAET,IAAI,UAAU,MACZ,OAAO;EAAE,MAAM;EAAM,eAAe;EAAM,WAAW;CAAK;CAE5D,OAAO;EACL,MAAM,MAAM,QAAQ;EACpB,eAAe,MAAM,iBAAiB;EACtC,WAAW,MAAM,aAAa;CAChC;AACF;;;;;;;;AASA,SAAgB,sBAAsB,MAAc,QAA2B,MAAc;CAC3F,MAAM,SAAS,yBAAyB,KAAK;CAC7C,IAAI,CAAC,UAAW,CAAC,OAAO,QAAQ,CAAC,OAAO,eACtC,OAAO;CAET,OAAOA,aAAAA,qBAAqB,CAAC,CAAC,yBAAyB,MAAM;EAC3D,MAAM,OAAO;EACb,eAAe,OAAO;EACtB,WAAW,OAAO;CACpB,CAAC;AACH;;;;AAKA,SAAgB,uBACd,QAA2B,MACG;CAC9B,MAAM,SAAS,yBAAyB,KAAK;CAC7C,IAAI,CAAC,sBAAsB,MAAM,GAC/B,OAAO;CAGT,OAAO;EACL,yBAAyB;EACzB,GAAI,OAAO,OAAO,EAAE,gBAAgB,GAAY,IAAI,CAAC;EACrD,GAAI,OAAO,gBAAgB,EAAE,0BAA0B,GAAY,IAAI,CAAC;EACxE,GAAI,OAAO,YAAY,EAAE,uBAAuB,GAAY,IAAI,CAAC;CACnE;AACF;;;;;;AAOA,SAAgB,6BAA6B,QAA2B,MAAc;CACpF,OAAO,OAAO,KAAK,uBAAuB,KAAK,CAAC,CAAC,CAC9C,KAAK,SAAS,IAAI,MAAM,CAAC,CACzB,KAAK,EAAE;AACZ;;;;AAKA,SAAgB,gBAAgB,QAA2B,MAAc;CACvE,OAAO,sBAAsB,yBAAyB,KAAK,CAAC,IACxDA,aAAAA,qBAAqB,CAAC,CAAC,sBAAsB,IAC7C;AACN;;;;AAKA,SAAgB,mBAAmB,QAA2B,MAAc;CAC1E,OAAO,oBAAoB,yBAAyB,KAAK,CAAC,IACtDA,aAAAA,qBAAqB,CAAC,CAAC,yBAAyB,IAChD;AACN;;;;;AAMA,SAAgB,2BAA2B,QAA2B,MAAc;CAClF,MAAM,MAAM,gBAAgB,KAAK;CACjC,OAAO,MAAM,0CAA0C,IAAI,YAAY;AACzE;;;;;AAMA,SAAgB,4BAA4B,QAA2B,MAAc;CACnF,MAAM,KAAK,mBAAmB,KAAK;CACnC,OAAO,KAAK,4CAA4C,GAAG,cAAa;AAC1E;AAEA,SAAgB,sBACd,QACgD;CAChD,OAAO,QAAQ,WAAW,OAAO,QAAQ,OAAO,iBAAiB,OAAO,UAAU;AACpF;AAEA,SAAgB,oBAAoB,QAAuC;CACzE,OAAO,QAAQ,WAAW,OAAO,QAAQ,OAAO,UAAU;AAC5D"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-control flags for `ssg.readerChrome`.
|
|
3
|
+
*
|
|
4
|
+
* Omitted fields stay on when the feature itself is enabled.
|
|
5
|
+
*/
|
|
6
|
+
export interface ReaderChromeOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Copy button on fenced code blocks. The clipboard is read in the browser,
|
|
9
|
+
* never at build time.
|
|
10
|
+
*
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
copy?: boolean;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Icon and `rel="noopener noreferrer"` on outbound `http(s)` links.
|
|
17
|
+
* Relative, hash, and same-document links are left alone.
|
|
18
|
+
*
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
externalLinks?: boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Back-to-top control that appears after the page is scrolled.
|
|
25
|
+
*
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
backToTop?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolved reader chrome. `false` means no extra markup or JS.
|
|
33
|
+
*/
|
|
34
|
+
export type ResolvedReaderChrome =
|
|
35
|
+
| false
|
|
36
|
+
| {
|
|
37
|
+
copy: boolean;
|
|
38
|
+
externalLinks: boolean;
|
|
39
|
+
backToTop: boolean;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type EnabledReaderChrome = Exclude<ResolvedReaderChrome, false>;
|
|
43
|
+
|
|
44
|
+
export type ReaderChromeInput =
|
|
45
|
+
| boolean
|
|
46
|
+
| ReaderChromeOptions
|
|
47
|
+
| EnabledReaderChrome
|
|
48
|
+
| undefined;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the public reader-chrome option shape.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveReaderChromeInput(
|
|
54
|
+
input?: ReaderChromeInput,
|
|
55
|
+
): ResolvedReaderChrome;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Apply the same native reader-chrome HTML transform used by the built-in SSG.
|
|
59
|
+
*/
|
|
60
|
+
export declare function applyReaderChromeHtml(
|
|
61
|
+
html: string,
|
|
62
|
+
input?: ReaderChromeInput,
|
|
63
|
+
): string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Root attributes consumed by the browser runtime.
|
|
67
|
+
*/
|
|
68
|
+
export declare function readerChromeAttributes(
|
|
69
|
+
input?: ReaderChromeInput,
|
|
70
|
+
): Readonly<Record<string, "">>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Render the root attributes as a leading-space HTML fragment.
|
|
74
|
+
*/
|
|
75
|
+
export declare function renderReaderChromeAttributes(input?: ReaderChromeInput): string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* CSS shared by the built-in SSG and custom hosts.
|
|
79
|
+
*/
|
|
80
|
+
export declare function readerChromeCss(input?: ReaderChromeInput): string;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Auto-initializing script shared by the built-in SSG and custom hosts.
|
|
84
|
+
*/
|
|
85
|
+
export declare function readerChromeScript(input?: ReaderChromeInput): string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Inline stylesheet tag for hosts that do not import
|
|
89
|
+
* `@ox-content/vite-plugin/styles/reader-chrome.css`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function renderReaderChromeStyleTag(input?: ReaderChromeInput): string;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Inline auto-init script for static hosts that do not bundle
|
|
95
|
+
* `@ox-content/vite-plugin/reader-chrome/client`.
|
|
96
|
+
*/
|
|
97
|
+
export declare function renderReaderChromeScriptTag(input?: ReaderChromeInput): string;
|
|
98
|
+
|
|
99
|
+
export declare function readerChromeIsEnabled(
|
|
100
|
+
chrome: ResolvedReaderChrome,
|
|
101
|
+
): chrome is Exclude<ResolvedReaderChrome, false>;
|
|
102
|
+
|
|
103
|
+
export declare function readerChromeNeedsJs(chrome: ResolvedReaderChrome): boolean;
|