@t8/docsgen 0.1.4 → 0.1.6

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/bin.js CHANGED
@@ -92,6 +92,17 @@ async function fetchText(location) {
92
92
  return (await (0, import_promises.readFile)(location)).toString();
93
93
  }
94
94
 
95
+ // src/bin/getLocation.ts
96
+ function getLocation(ctx, path, preferredLocation) {
97
+ let { repo, mainBranch = "main" } = ctx;
98
+ if (preferredLocation) return preferredLocation;
99
+ let ghId = repo?.startsWith("https://github.com/") ? repo.replace("https://github.com/", "").split("/").slice(0, 2).join("/") : "";
100
+ let urlPath = path.replace(/^\.?\//, "");
101
+ if (ghId)
102
+ return `https://raw.githubusercontent.com/${ghId}/refs/heads/${mainBranch}/${urlPath}`;
103
+ return path;
104
+ }
105
+
95
106
  // src/bin/toRepoURL.ts
96
107
  function toRepoURL(x) {
97
108
  if (!x) return "";
@@ -122,11 +133,6 @@ function toConfig(metadata) {
122
133
  var config = null;
123
134
  async function getConfig() {
124
135
  if (config) return config;
125
- let metadata = {};
126
- try {
127
- metadata = JSON.parse(await fetchText("./package.json"));
128
- } catch {
129
- }
130
136
  let localConfig = {};
131
137
  try {
132
138
  localConfig = JSON.parse(
@@ -142,10 +148,18 @@ async function getConfig() {
142
148
  mainBranch: "main",
143
149
  root: "/",
144
150
  contentDir: "x",
145
- ...toConfig(metadata),
146
151
  ...localConfig,
147
152
  ...A(args)
148
153
  };
154
+ try {
155
+ let rawContent = await fetchText(getLocation(config, "package.json"));
156
+ let metadata = JSON.parse(rawContent);
157
+ config = {
158
+ ...toConfig(metadata),
159
+ ...config
160
+ };
161
+ } catch {
162
+ }
149
163
  if (!config.root?.endsWith("/")) config.root = `${config.root ?? ""}/`;
150
164
  return config;
151
165
  }
@@ -225,6 +239,27 @@ ym(${ymid}, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true
225
239
  `.trim();
226
240
  }
227
241
 
242
+ // src/bin/getIcon.ts
243
+ var iconTypeMap = {
244
+ ico: "image/x-icon",
245
+ svg: "image/svg+xml",
246
+ png: "image/png",
247
+ gif: "image/gif",
248
+ jpg: "image/jpeg",
249
+ jpeg: "image/jpeg"
250
+ };
251
+ function getIcon({ favicon, faviconType }) {
252
+ let icon = {
253
+ url: favicon,
254
+ type: faviconType
255
+ };
256
+ if (icon.url && !icon.type) {
257
+ let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
258
+ if (ext) icon.type = iconTypeMap[ext];
259
+ }
260
+ return icon;
261
+ }
262
+
228
263
  // src/bin/getNav.ts
229
264
  var import_jsdom = require("jsdom");
230
265
 
@@ -373,8 +408,9 @@ function getSectionPostprocess(linkMap) {
373
408
  };
374
409
  }
375
410
  async function getParsedContent(ctx) {
376
- let { source = "README.md", singlePage } = ctx;
377
- let content = md.render(await fetchText(source));
411
+ let { singlePage } = ctx;
412
+ let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
413
+ let content = md.render(rawContent);
378
414
  let dom = new import_jsdom2.JSDOM(content);
379
415
  let { nav, linkMap } = buildNav(ctx, dom);
380
416
  let badges = [];
@@ -436,13 +472,12 @@ async function getParsedContent(ctx) {
436
472
 
437
473
  // src/bin/getTitle.ts
438
474
  function getTitle(ctx, { cover, originalContent, withPackageURL } = {}) {
439
- let { root, name, title: packageTitle, scope, theme } = ctx;
475
+ let { root, name, title: packageTitle, htmlTitle, scope } = ctx;
440
476
  if (originalContent && ![name, packageTitle].includes(originalContent.trim()))
441
477
  return originalContent;
478
+ if (cover && htmlTitle) return htmlTitle;
442
479
  if (packageTitle) {
443
480
  let escapedTitle = escapeHTML(packageTitle);
444
- if (cover && theme === "t8" && packageTitle.startsWith("T8 "))
445
- return `<a href="/">T8</a> <span class="name">${packageTitle.replace(/^T8 /, "")}</span>`;
446
481
  return withPackageURL ? `<a href="${root}" class="name">${escapedTitle}</a>` : `<span class="name">${escapedTitle}</span>`;
447
482
  }
448
483
  let scopeMatches = name?.match(/^(@[^/]+)\/?(.*)/);
@@ -482,18 +517,11 @@ async function setContent(ctx) {
482
517
  let packageVersion = (await exec(`npm view ${packageName} version`)).stdout.trim().split(".").slice(0, 2).join(".");
483
518
  let packageUrl = `https://unpkg.com/${packageName}@${packageVersion}`;
484
519
  let rootAttrs = "";
485
- let icon = {
486
- url: `${root}favicon.svg`,
487
- type: "image/svg+xml"
488
- };
489
520
  if (theme) rootAttrs += ` data-theme="${escapeHTML(theme)}"`;
490
521
  if (colorScheme)
491
522
  rootAttrs += ` style="--color-scheme: ${escapeHTML(colorScheme)}"`;
492
- if (theme === "t8")
493
- icon = {
494
- url: "/assets/t8.png",
495
- type: "image/png"
496
- };
523
+ let icon = getIcon(ctx);
524
+ let iconTag = icon.url ? `<link rel="icon"${icon.type ? ` type="${icon.type}"` : ""} href="${icon.url}">` : "";
497
525
  if (redirect) {
498
526
  let escapedRedirect = escapeHTML(redirect);
499
527
  await (0, import_promises4.writeFile)(
@@ -505,6 +533,7 @@ async function setContent(ctx) {
505
533
  <meta charset="utf-8">
506
534
  <meta name="viewport" content="width=device-width">
507
535
  <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
536
+ ${iconTag}
508
537
  </head>
509
538
  <body>
510
539
  ${counterContent}
@@ -536,14 +565,14 @@ ${counterContent}
536
565
  <!DOCTYPE html>
537
566
  <html lang="en"${rootAttrs}>
538
567
  <head>
539
- <meta charset="utf-8">
540
- <meta name="viewport" content="width=device-width, initial-scale=1">
541
- <title>${escapeHTML(nav[i]?.title)} | ${escapedTitle}</title>
542
- <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
543
- <link rel="stylesheet" href="${packageUrl}/dist/css/section.css">
544
- <link rel="icon" type="${icon.type}" href="${icon.url}">
545
- ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
546
- ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
568
+ <meta charset="utf-8">
569
+ <meta name="viewport" content="width=device-width, initial-scale=1">
570
+ <title>${escapeHTML(nav[i]?.title)} | ${escapedTitle}</title>
571
+ <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
572
+ <link rel="stylesheet" href="${packageUrl}/dist/css/section.css">
573
+ ${iconTag}
574
+ ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
575
+ ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
547
576
  </head>
548
577
  <body>
549
578
  <div class="layout">
@@ -589,14 +618,14 @@ ${counterContent}
589
618
  <!DOCTYPE html>
590
619
  <html lang="en"${rootAttrs}>
591
620
  <head>
592
- <meta charset="utf-8">
593
- <meta name="viewport" content="width=device-width, initial-scale=1">
594
- <title>${escapedTitle}${packageDescription ? ` | ${escapeHTML(packageDescription)}` : ""}</title>
595
- <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
596
- <link rel="stylesheet" href="${packageUrl}/dist/css/index.css">
597
- <link rel="icon" type="${icon.type}" href="${icon.url}">
598
- <link rel="prefetch" href="${root}start">
599
- ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
621
+ <meta charset="utf-8">
622
+ <meta name="viewport" content="width=device-width, initial-scale=1">
623
+ <title>${escapedTitle}${packageDescription ? ` | ${escapeHTML(packageDescription)}` : ""}</title>
624
+ <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
625
+ <link rel="stylesheet" href="${packageUrl}/dist/css/index.css">
626
+ ${iconTag}
627
+ <link rel="prefetch" href="${root}start">
628
+ ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
600
629
  </head>
601
630
  <body>
602
631
  <div class="layout">
@@ -650,7 +679,7 @@ ${counterContent}
650
679
  <meta http-equiv="refresh" content="0; URL=${root}${contentDir}/${nav[0]?.id}">
651
680
  <title>${escapedTitle}</title>
652
681
  <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
653
- <link rel="icon" type="${icon.type}" href="${icon.url}">
682
+ ${iconTag}
654
683
  <script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
655
684
  </head>
656
685
  <body>
@@ -670,8 +699,8 @@ ${counterContent}
670
699
  var import_promises5 = require("node:fs/promises");
671
700
  var import_node_path4 = require("node:path");
672
701
 
673
- // src/utils/getIcon.ts
674
- function getIcon(baseColor = "gray") {
702
+ // src/utils/getIconContent.ts
703
+ function getIconContent(baseColor = "gray") {
675
704
  return `
676
705
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
677
706
  <style>.b{fill:${baseColor};}.c0{fill:oklch(from ${baseColor} calc(100*(.78 - l)) 0 0 / .5);}.c1{fill:oklch(from ${baseColor} calc(100*(.78 - l)) 0 0 / .3);}.c2{fill:none;}</style>
@@ -688,8 +717,11 @@ function getIcon(baseColor = "gray") {
688
717
  // src/bin/setImages.ts
689
718
  async function setImages({ dir = "", colorScheme, favicon }) {
690
719
  if (favicon) return;
691
- await (0, import_promises5.writeFile)((0, import_node_path4.join)(dir, "./favicon.svg"), `${getIcon(colorScheme)}
692
- `);
720
+ await (0, import_promises5.writeFile)(
721
+ (0, import_node_path4.join)(dir, "./favicon.svg"),
722
+ `${getIconContent(colorScheme)}
723
+ `
724
+ );
693
725
  }
694
726
 
695
727
  // src/bin/createFiles.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/docsgen",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "",
5
5
  "main": "dist/bin.js",
6
6
  "bin": {
@@ -2,6 +2,7 @@ import { parseArgs } from "args-json";
2
2
  import type { BinConfig } from "../types/BinConfig";
3
3
  import type { PackageMetadata } from "../types/PackageMetadata";
4
4
  import { fetchText } from "./fetchText";
5
+ import { getLocation } from "./getLocation";
5
6
  import { toConfig } from "./toConfig";
6
7
 
7
8
  let config: BinConfig | null = null;
@@ -9,12 +10,6 @@ let config: BinConfig | null = null;
9
10
  export async function getConfig(): Promise<BinConfig> {
10
11
  if (config) return config;
11
12
 
12
- let metadata: PackageMetadata = {};
13
-
14
- try {
15
- metadata = JSON.parse(await fetchText("./package.json")) as PackageMetadata;
16
- } catch {}
17
-
18
13
  let localConfig: BinConfig = {};
19
14
 
20
15
  try {
@@ -33,11 +28,20 @@ export async function getConfig(): Promise<BinConfig> {
33
28
  mainBranch: "main",
34
29
  root: "/",
35
30
  contentDir: "x",
36
- ...toConfig(metadata),
37
31
  ...localConfig,
38
32
  ...parseArgs<BinConfig>(args),
39
33
  };
40
34
 
35
+ try {
36
+ let rawContent = await fetchText(getLocation(config, "package.json"));
37
+ let metadata = JSON.parse(rawContent) as PackageMetadata;
38
+
39
+ config = {
40
+ ...toConfig(metadata),
41
+ ...config,
42
+ };
43
+ } catch {}
44
+
41
45
  if (!config.root?.endsWith("/")) config.root = `${config.root ?? ""}/`;
42
46
 
43
47
  return config;
@@ -0,0 +1,30 @@
1
+ import type { Context } from "../types/Context";
2
+
3
+ const iconTypeMap: Record<string, string> = {
4
+ ico: "image/x-icon",
5
+ svg: "image/svg+xml",
6
+ png: "image/png",
7
+ gif: "image/gif",
8
+ jpg: "image/jpeg",
9
+ jpeg: "image/jpeg",
10
+ };
11
+
12
+ type Icon = {
13
+ url?: string | undefined;
14
+ type?: string | undefined;
15
+ };
16
+
17
+ export function getIcon({ favicon, faviconType }: Context) {
18
+ let icon: Icon = {
19
+ url: favicon,
20
+ type: faviconType,
21
+ };
22
+
23
+ if (icon.url && !icon.type) {
24
+ let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
25
+
26
+ if (ext) icon.type = iconTypeMap[ext];
27
+ }
28
+
29
+ return icon;
30
+ }
@@ -0,0 +1,22 @@
1
+ import type { Context } from "../types/Context";
2
+
3
+ export function getLocation(
4
+ ctx: Context,
5
+ path: string,
6
+ preferredLocation?: string | undefined,
7
+ ) {
8
+ let { repo, mainBranch = "main" } = ctx;
9
+
10
+ if (preferredLocation) return preferredLocation;
11
+
12
+ let ghId = repo?.startsWith("https://github.com/")
13
+ ? repo.replace("https://github.com/", "").split("/").slice(0, 2).join("/")
14
+ : "";
15
+
16
+ let urlPath = path.replace(/^\.?\//, "");
17
+
18
+ if (ghId)
19
+ return `https://raw.githubusercontent.com/${ghId}/refs/heads/${mainBranch}/${urlPath}`;
20
+
21
+ return path;
22
+ }
@@ -3,6 +3,7 @@ import Markdown from "markdown-it";
3
3
  import type { Context } from "../types/Context";
4
4
  import type { NavItem } from "../types/NavItem";
5
5
  import { fetchText } from "./fetchText";
6
+ import { getLocation } from "./getLocation";
6
7
  import { getSlug } from "./getSlug";
7
8
 
8
9
  const md = new Markdown({
@@ -103,8 +104,9 @@ function getSectionPostprocess(linkMap: Record<string, string>) {
103
104
  }
104
105
 
105
106
  export async function getParsedContent(ctx: Context) {
106
- let { source = "README.md", singlePage } = ctx;
107
- let content = md.render(await fetchText(source));
107
+ let { singlePage } = ctx;
108
+ let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
109
+ let content = md.render(rawContent);
108
110
  let dom = new JSDOM(content);
109
111
 
110
112
  let { nav, linkMap } = buildNav(ctx, dom);
@@ -11,17 +11,16 @@ export function getTitle(
11
11
  ctx: Context,
12
12
  { cover, originalContent, withPackageURL }: GetTitleParams = {},
13
13
  ) {
14
- let { root, name, title: packageTitle, scope, theme } = ctx;
14
+ let { root, name, title: packageTitle, htmlTitle, scope } = ctx;
15
15
 
16
16
  if (originalContent && ![name, packageTitle].includes(originalContent.trim()))
17
17
  return originalContent;
18
18
 
19
+ if (cover && htmlTitle) return htmlTitle;
20
+
19
21
  if (packageTitle) {
20
22
  let escapedTitle = escapeHTML(packageTitle);
21
23
 
22
- if (cover && theme === "t8" && packageTitle.startsWith("T8 "))
23
- return `<a href="/">T8</a> <span class="name">${packageTitle.replace(/^T8 /, "")}</span>`;
24
-
25
24
  return withPackageURL
26
25
  ? `<a href="${root}" class="name">${escapedTitle}</a>`
27
26
  : `<span class="name">${escapedTitle}</span>`;
@@ -7,6 +7,7 @@ import type { Context } from "../types/Context";
7
7
  import { escapeHTML } from "../utils/escapeHTML";
8
8
  import { escapeRegExp } from "../utils/escapeRegExp";
9
9
  import { getCounterContent } from "./getCounterContent";
10
+ import { getIcon } from "./getIcon";
10
11
  import { getNav } from "./getNav";
11
12
  import { getParsedContent } from "./getParsedContent";
12
13
  import { getRepoLink } from "./getRepoLink";
@@ -42,21 +43,15 @@ export async function setContent(ctx: Context) {
42
43
  let packageUrl = `https://unpkg.com/${packageName}@${packageVersion}`;
43
44
  let rootAttrs = "";
44
45
 
45
- let icon = {
46
- url: `${root}favicon.svg`,
47
- type: "image/svg+xml",
48
- };
49
-
50
46
  if (theme) rootAttrs += ` data-theme="${escapeHTML(theme)}"`;
51
47
 
52
48
  if (colorScheme)
53
49
  rootAttrs += ` style="--color-scheme: ${escapeHTML(colorScheme)}"`;
54
50
 
55
- if (theme === "t8")
56
- icon = {
57
- url: "/assets/t8.png",
58
- type: "image/png",
59
- };
51
+ let icon = getIcon(ctx);
52
+ let iconTag = icon.url
53
+ ? `<link rel="icon"${icon.type ? ` type="${icon.type}"` : ""} href="${icon.url}">`
54
+ : "";
60
55
 
61
56
  if (redirect) {
62
57
  let escapedRedirect = escapeHTML(redirect);
@@ -70,6 +65,7 @@ export async function setContent(ctx: Context) {
70
65
  <meta charset="utf-8">
71
66
  <meta name="viewport" content="width=device-width">
72
67
  <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
68
+ ${iconTag}
73
69
  </head>
74
70
  <body>
75
71
  ${counterContent}
@@ -108,14 +104,14 @@ ${counterContent}
108
104
  <!DOCTYPE html>
109
105
  <html lang="en"${rootAttrs}>
110
106
  <head>
111
- <meta charset="utf-8">
112
- <meta name="viewport" content="width=device-width, initial-scale=1">
113
- <title>${escapeHTML(nav[i]?.title)} | ${escapedTitle}</title>
114
- <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
115
- <link rel="stylesheet" href="${packageUrl}/dist/css/section.css">
116
- <link rel="icon" type="${icon.type}" href="${icon.url}">
117
- ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
118
- ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
107
+ <meta charset="utf-8">
108
+ <meta name="viewport" content="width=device-width, initial-scale=1">
109
+ <title>${escapeHTML(nav[i]?.title)} | ${escapedTitle}</title>
110
+ <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
111
+ <link rel="stylesheet" href="${packageUrl}/dist/css/section.css">
112
+ ${iconTag}
113
+ ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
114
+ ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
119
115
  </head>
120
116
  <body>
121
117
  <div class="layout">
@@ -165,14 +161,14 @@ ${counterContent}
165
161
  <!DOCTYPE html>
166
162
  <html lang="en"${rootAttrs}>
167
163
  <head>
168
- <meta charset="utf-8">
169
- <meta name="viewport" content="width=device-width, initial-scale=1">
170
- <title>${escapedTitle}${packageDescription ? ` | ${escapeHTML(packageDescription)}` : ""}</title>
171
- <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
172
- <link rel="stylesheet" href="${packageUrl}/dist/css/index.css">
173
- <link rel="icon" type="${icon.type}" href="${icon.url}">
174
- <link rel="prefetch" href="${root}start">
175
- ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
164
+ <meta charset="utf-8">
165
+ <meta name="viewport" content="width=device-width, initial-scale=1">
166
+ <title>${escapedTitle}${packageDescription ? ` | ${escapeHTML(packageDescription)}` : ""}</title>
167
+ <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
168
+ <link rel="stylesheet" href="${packageUrl}/dist/css/index.css">
169
+ ${iconTag}
170
+ <link rel="prefetch" href="${root}start">
171
+ ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
176
172
  </head>
177
173
  <body>
178
174
  <div class="layout">
@@ -234,7 +230,7 @@ ${counterContent}
234
230
  <meta http-equiv="refresh" content="0; URL=${root}${contentDir}/${nav[0]?.id}">
235
231
  <title>${escapedTitle}</title>
236
232
  <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
237
- <link rel="icon" type="${icon.type}" href="${icon.url}">
233
+ ${iconTag}
238
234
  <script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
239
235
  </head>
240
236
  <body>
@@ -1,10 +1,13 @@
1
1
  import { writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import type { Context } from "../types/Context";
4
- import { getIcon } from "../utils/getIcon";
4
+ import { getIconContent } from "../utils/getIconContent";
5
5
 
6
6
  export async function setImages({ dir = "", colorScheme, favicon }: Context) {
7
7
  if (favicon) return;
8
8
 
9
- await writeFile(join(dir, "./favicon.svg"), `${getIcon(colorScheme)}\n`);
9
+ await writeFile(
10
+ join(dir, "./favicon.svg"),
11
+ `${getIconContent(colorScheme)}\n`,
12
+ );
10
13
  }
@@ -8,6 +8,7 @@ export type EntryConfig = {
8
8
  theme?: Theme;
9
9
  name?: string;
10
10
  title?: string;
11
+ htmlTitle?: string;
11
12
  description?: string;
12
13
  version?: string;
13
14
  repo?: string;
@@ -39,6 +40,7 @@ export type EntryConfig = {
39
40
  nav?: string;
40
41
  /** Favicon URL. */
41
42
  favicon?: string;
43
+ faviconType?: string;
42
44
  /** Scope URL. */
43
45
  scope?: string;
44
46
  /** Redirection URL. */
@@ -1,4 +1,4 @@
1
- export function getIcon(baseColor = "gray") {
1
+ export function getIconContent(baseColor = "gray") {
2
2
  return `
3
3
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
4
4
  <style>.b{fill:${baseColor};}.c0{fill:oklch(from ${baseColor} calc(100*(.78 - l)) 0 0 / .5);}.c1{fill:oklch(from ${baseColor} calc(100*(.78 - l)) 0 0 / .3);}.c2{fill:none;}</style>