@tenphi/renderer 0.25.3 → 0.26.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/components/MainContent.styles.js +3 -0
- package/dist/components/Pagination.styles.js +1 -1
- package/dist/components/Preview.astro +10 -5
- package/dist/components/Sidebar.styles.js +3 -0
- package/dist/components/appearance-bootstrap.js +21 -13
- package/dist/components/appearance-preferences.test.ts +63 -27
- package/dist/components/appearance-preferences.ts +23 -16
- package/dist/components/props.d.ts +2 -0
- package/dist/components/props.d.ts.map +1 -1
- package/dist/components/props.ts +2 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/overrides/ThemeSelect.astro +16 -9
- package/dist/preview-document.d.ts +14 -0
- package/dist/preview-document.d.ts.map +1 -0
- package/dist/preview-document.js +33 -0
- package/dist/preview-document.js.map +1 -0
- package/package.json +2 -2
|
@@ -11,7 +11,11 @@ const id = `appearance-${crypto.randomUUID()}`;
|
|
|
11
11
|
const schemes = [
|
|
12
12
|
{ value: "light", label: Astro.locals.t("themeSelect.light"), icon: "sun" },
|
|
13
13
|
{ value: "dark", label: Astro.locals.t("themeSelect.dark"), icon: "moon" },
|
|
14
|
-
{
|
|
14
|
+
{
|
|
15
|
+
value: "system",
|
|
16
|
+
label: Astro.locals.t("themeSelect.auto"),
|
|
17
|
+
icon: "laptop",
|
|
18
|
+
},
|
|
15
19
|
] as const;
|
|
16
20
|
const contrasts = [
|
|
17
21
|
{ value: "normal", label: ui.normalContrast, icon: "normal" },
|
|
@@ -46,7 +50,7 @@ const contrasts = [
|
|
|
46
50
|
name={`${id}-scheme`}
|
|
47
51
|
value={value}
|
|
48
52
|
data-appearance-scheme
|
|
49
|
-
checked={value === "
|
|
53
|
+
checked={value === "system"}
|
|
50
54
|
/>
|
|
51
55
|
<Icon name={icon} />
|
|
52
56
|
<span>{label}</span>
|
|
@@ -83,9 +87,11 @@ const contrasts = [
|
|
|
83
87
|
|
|
84
88
|
<script>
|
|
85
89
|
import {
|
|
90
|
+
APPEARANCE_KEY,
|
|
91
|
+
LEGACY_THEME_KEY,
|
|
86
92
|
loadPreferences,
|
|
87
93
|
storePreferences,
|
|
88
|
-
|
|
94
|
+
parseTheme,
|
|
89
95
|
parseContrast,
|
|
90
96
|
} from "../components/appearance-preferences.js";
|
|
91
97
|
import { initializePopoverMotion } from "../client/popover-motion.js";
|
|
@@ -95,11 +101,11 @@ const contrasts = [
|
|
|
95
101
|
|
|
96
102
|
function applyPreferences(): void {
|
|
97
103
|
document.documentElement.dataset.theme =
|
|
98
|
-
current.
|
|
104
|
+
current.theme === "system"
|
|
99
105
|
? systemScheme.matches
|
|
100
106
|
? "light"
|
|
101
107
|
: "dark"
|
|
102
|
-
: current.
|
|
108
|
+
: current.theme;
|
|
103
109
|
if (current.contrast === "system") {
|
|
104
110
|
delete document.documentElement.dataset.contrast;
|
|
105
111
|
} else {
|
|
@@ -108,7 +114,7 @@ const contrasts = [
|
|
|
108
114
|
document
|
|
109
115
|
.querySelectorAll<HTMLInputElement>("[data-appearance-scheme]")
|
|
110
116
|
.forEach((input) => {
|
|
111
|
-
input.checked = input.value === current.
|
|
117
|
+
input.checked = input.value === current.theme;
|
|
112
118
|
});
|
|
113
119
|
document
|
|
114
120
|
.querySelectorAll<HTMLInputElement>("[data-appearance-contrast]")
|
|
@@ -118,12 +124,13 @@ const contrasts = [
|
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
systemScheme.addEventListener("change", () => {
|
|
121
|
-
if (current.
|
|
127
|
+
if (current.theme === "system") applyPreferences();
|
|
122
128
|
});
|
|
123
129
|
window.addEventListener("storage", (event) => {
|
|
124
130
|
if (
|
|
125
131
|
!event.key ||
|
|
126
|
-
|
|
132
|
+
event.key === APPEARANCE_KEY ||
|
|
133
|
+
event.key === LEGACY_THEME_KEY
|
|
127
134
|
) {
|
|
128
135
|
current = loadPreferences();
|
|
129
136
|
applyPreferences();
|
|
@@ -139,7 +146,7 @@ const contrasts = [
|
|
|
139
146
|
const input = event.target;
|
|
140
147
|
if (!(input instanceof HTMLInputElement)) return;
|
|
141
148
|
if (input.hasAttribute("data-appearance-scheme")) {
|
|
142
|
-
current.
|
|
149
|
+
current.theme = parseTheme(input.value);
|
|
143
150
|
} else if (input.hasAttribute("data-appearance-contrast")) {
|
|
144
151
|
current.contrast = parseContrast(input.value);
|
|
145
152
|
} else return;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PreviewProps } from "./components/props.js";
|
|
2
|
+
//#region src/preview-document.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Build a Preview's frame document and its "View source" text. Public scripts
|
|
5
|
+
* are inlined so they run in the opaque-origin sandbox without a request.
|
|
6
|
+
*/
|
|
7
|
+
declare function buildPreview({ html, css, javascript, scripts }: Omit<PreviewProps, "title">, publicDir: string, page: string): Promise<{
|
|
8
|
+
document: string;
|
|
9
|
+
source: string;
|
|
10
|
+
sandbox: string;
|
|
11
|
+
}>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { buildPreview };
|
|
14
|
+
//# sourceMappingURL=preview-document.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-document.d.ts","names":[],"sources":["../src/preview-document.ts"],"mappings":";;;;;;iBAQsB,eAElB,MACA,KACA,YACA,WACC,KAAK,wBACR,mBACA,eAAY"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
//#region src/preview-document.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build a Preview's frame document and its "View source" text. Public scripts
|
|
6
|
+
* are inlined so they run in the opaque-origin sandbox without a request.
|
|
7
|
+
*/
|
|
8
|
+
async function buildPreview({ html = "", css = "", javascript, scripts = [] }, publicDir, page) {
|
|
9
|
+
const files = await Promise.all(scripts.map((src) => readPublicScript(src, publicDir, page)));
|
|
10
|
+
const markup = `<!doctype html><meta charset="utf-8"><style>${css}</style>${html}`;
|
|
11
|
+
const authored = javascript ? inlineScript(javascript) : "";
|
|
12
|
+
return {
|
|
13
|
+
document: markup + files.map(inlineScript).join("") + authored,
|
|
14
|
+
source: markup + scripts.map((src) => `<script src="${src}"><\/script>`).join("") + authored,
|
|
15
|
+
sandbox: scripts.length || javascript ? "allow-scripts" : ""
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function inlineScript(code) {
|
|
19
|
+
return `<script>${code.replace(/<\/(script)/gi, "<\\/$1")}<\/script>`;
|
|
20
|
+
}
|
|
21
|
+
async function readPublicScript(src, publicDir, page) {
|
|
22
|
+
const error = `Preview on ${page}: script ${src} must be a readable file in the site's public directory, such as /demo/button.js.`;
|
|
23
|
+
if (!/^\/(?!\/)/.test(src) || src.split(/[\\/]/).includes("..")) throw Error(error);
|
|
24
|
+
try {
|
|
25
|
+
return await readFile(join(publicDir, src), "utf8");
|
|
26
|
+
} catch {
|
|
27
|
+
throw Error(error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { buildPreview };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=preview-document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-document.js","names":[],"sources":["../src/preview-document.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PreviewProps } from \"./components/props.js\";\n\n/**\n * Build a Preview's frame document and its \"View source\" text. Public scripts\n * are inlined so they run in the opaque-origin sandbox without a request.\n */\nexport async function buildPreview(\n {\n html = \"\",\n css = \"\",\n javascript,\n scripts = [],\n }: Omit<PreviewProps, \"title\">,\n publicDir: string,\n page: string,\n) {\n const files = await Promise.all(\n scripts.map((src) => readPublicScript(src, publicDir, page)),\n );\n const markup = `<!doctype html><meta charset=\"utf-8\"><style>${css}</style>${html}`;\n const authored = javascript ? inlineScript(javascript) : \"\";\n return {\n document: markup + files.map(inlineScript).join(\"\") + authored,\n source:\n markup +\n scripts.map((src) => `<script src=\"${src}\"></script>`).join(\"\") +\n authored,\n sandbox: scripts.length || javascript ? \"allow-scripts\" : \"\",\n };\n}\n\n// The HTML parser ends a script at the first `</script`, even inside a string.\nfunction inlineScript(code: string) {\n return `<script>${code.replace(/<\\/(script)/gi, \"<\\\\/$1\")}</script>`;\n}\n\nasync function readPublicScript(src: string, publicDir: string, page: string) {\n const error = `Preview on ${page}: script ${src} must be a readable file in the site's public directory, such as /demo/button.js.`;\n if (!/^\\/(?!\\/)/.test(src) || src.split(/[\\\\/]/).includes(\"..\"))\n throw Error(error);\n try {\n return await readFile(join(publicDir, src), \"utf8\");\n } catch {\n throw Error(error);\n }\n}\n"],"mappings":";;;;;;;AAQA,eAAsB,aACpB,EACE,OAAO,IACP,MAAM,IACN,YACA,UAAU,CAAC,KAEb,WACA,MACA;CACA,MAAM,QAAQ,MAAM,QAAQ,IAC1B,QAAQ,KAAK,QAAQ,iBAAiB,KAAK,WAAW,IAAI,CAAC,CAC7D;CACA,MAAM,SAAS,+CAA+C,IAAI,UAAU;CAC5E,MAAM,WAAW,aAAa,aAAa,UAAU,IAAI;CACzD,OAAO;EACL,UAAU,SAAS,MAAM,IAAI,YAAY,CAAC,CAAC,KAAK,EAAE,IAAI;EACtD,QACE,SACA,QAAQ,KAAK,QAAQ,gBAAgB,IAAI,aAAY,CAAC,CAAC,KAAK,EAAE,IAC9D;EACF,SAAS,QAAQ,UAAU,aAAa,kBAAkB;CAC5D;AACF;AAGA,SAAS,aAAa,MAAc;CAClC,OAAO,WAAW,KAAK,QAAQ,iBAAiB,QAAQ,EAAE;AAC5D;AAEA,eAAe,iBAAiB,KAAa,WAAmB,MAAc;CAC5E,MAAM,QAAQ,cAAc,KAAK,WAAW,IAAI;CAChD,IAAI,CAAC,YAAY,KAAK,GAAG,KAAK,IAAI,MAAM,OAAO,CAAC,CAAC,SAAS,IAAI,GAC5D,MAAM,MAAM,KAAK;CACnB,IAAI;EACF,OAAO,MAAM,SAAS,KAAK,WAAW,GAAG,GAAG,MAAM;CACpD,QAAQ;EACN,MAAM,MAAM,KAAK;CACnB;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenphi/renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Astro renderer and Tasty theme for Cookbook",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@fontsource-variable/jetbrains-mono": "^5.3.0",
|
|
62
62
|
"@fontsource-variable/onest": "^5.3.0",
|
|
63
63
|
"@pagefind/default-ui": "1.5.2",
|
|
64
|
-
"@tenphi/docs": "0.
|
|
64
|
+
"@tenphi/docs": "0.26.0",
|
|
65
65
|
"@tenphi/eslint-plugin-tasty": "1.6.0",
|
|
66
66
|
"@tenphi/glaze": "2.0.1",
|
|
67
67
|
"@tenphi/tasty": "3.9.10",
|