@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.
@@ -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
- { value: "auto", label: Astro.locals.t("themeSelect.auto"), icon: "laptop" },
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 === "auto"}
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
- parseScheme,
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.scheme === "auto"
104
+ current.theme === "system"
99
105
  ? systemScheme.matches
100
106
  ? "light"
101
107
  : "dark"
102
- : current.scheme;
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.scheme;
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.scheme === "auto") applyPreferences();
127
+ if (current.theme === "system") applyPreferences();
122
128
  });
123
129
  window.addEventListener("storage", (event) => {
124
130
  if (
125
131
  !event.key ||
126
- ["cookbook-theme", "cookbook-appearance"].includes(event.key)
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.scheme = parseScheme(input.value);
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.25.3",
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.25.3",
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",