@t8/docsgen 0.4.14 → 0.4.16

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
@@ -241,7 +241,7 @@ async function getConfig() {
241
241
  config = {
242
242
  mainBranch: "main",
243
243
  root: "/",
244
- contentDir: "x",
244
+ contentDir: "docs",
245
245
  ...localConfig,
246
246
  ...(0, import_args_json.parseArgs)(args)
247
247
  };
@@ -266,10 +266,10 @@ import { promisify as promisify2 } from "node:util";
266
266
  // src/bin/cleanup.ts
267
267
  import { rm } from "node:fs/promises";
268
268
  import { join } from "node:path";
269
- async function cleanup({ dir = "" }) {
269
+ async function cleanup({ dir = "", contentDir }) {
270
270
  await Promise.all(
271
- ["x", "index.html", "start.html"].map((path) => {
272
- return rm(join(dir, path), { force: true, recursive: true });
271
+ [contentDir, "index.html"].map((path) => {
272
+ return path && rm(join(dir, path), { force: true, recursive: true });
273
273
  })
274
274
  );
275
275
  }
@@ -325,105 +325,6 @@ function escapeHTML(x) {
325
325
  return s;
326
326
  }
327
327
 
328
- // src/bin/content/getCounterContent.ts
329
- function getCounterContent({ ymid }) {
330
- if (!ymid) return "";
331
- return `
332
- <script>
333
- (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
334
- m[i].l=1*new Date();
335
- for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
336
- k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
337
- (window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
338
- ym(${ymid}, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
339
- </script>
340
- <noscript><div><img src="https://mc.yandex.com/watch/${ymid}" style="position:absolute;left:-9999px;" alt=""></div></noscript>
341
- `.trim();
342
- }
343
-
344
- // src/bin/content/getIcon.ts
345
- var iconTypeMap = {
346
- ico: "image/x-icon",
347
- svg: "image/svg+xml",
348
- png: "image/png",
349
- gif: "image/gif",
350
- jpg: "image/jpeg",
351
- jpeg: "image/jpeg"
352
- };
353
- function getIcon({ favicon, faviconType }) {
354
- let icon = {
355
- url: favicon,
356
- type: faviconType
357
- };
358
- if (icon.url && !icon.type) {
359
- let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
360
- if (ext) icon.type = iconTypeMap[ext];
361
- }
362
- return icon;
363
- }
364
-
365
- // src/bin/content/getIconTag.ts
366
- function getIconTag(ctx) {
367
- let { url, type } = getIcon(ctx);
368
- return url ? `<link rel="icon"${type ? ` type="${type}"` : ""} href="${url}">` : "";
369
- }
370
-
371
- // src/bin/content/getInjectedContent.ts
372
- function getInjectedContent(ctx, page, target, mode) {
373
- let injectedContent = ctx[mode]?.[target];
374
- if (!injectedContent) return "";
375
- return (Array.isArray(injectedContent) ? injectedContent : [injectedContent]).reduce((s, item) => {
376
- if (item === void 0) return s;
377
- if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
378
- let { content, pages } = item;
379
- if (!content || pages && !pages.includes(page)) return s;
380
- return `${s}${s ? "\n" : ""}${content}`;
381
- }, "");
382
- }
383
-
384
- // src/bin/content/toFileContent.ts
385
- function toFileContent(x) {
386
- let s = x.replace(
387
- /\s+(\r?\n *<\/?(script|link|head|body|html|meta|title)[> ])/g,
388
- "$1"
389
- ).replace(
390
- /\s+(\r?\n *<\/?(main|header|footer|nav|section|div|h\d|p|ul|ol|li|table)[> ])/g,
391
- "$1"
392
- ).trim();
393
- return `${s}
394
- `;
395
- }
396
-
397
- // src/bin/content/getRedirectContent.ts
398
- function getRedirectContent(ctx) {
399
- let { redirect } = ctx;
400
- let escapedRedirect = escapeHTML(redirect);
401
- return toFileContent(`
402
- <!DOCTYPE html>
403
- <html lang="en" data-layout="redirect" class="blank">
404
- <head>
405
- ${getInjectedContent(ctx, "redirect", "head", "prepend")}
406
- <meta charset="utf-8">
407
- <meta name="viewport" content="width=device-width">
408
- <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
409
- ${getIconTag(ctx)}
410
- ${getInjectedContent(ctx, "redirect", "head", "append")}
411
- </head>
412
- <body>
413
- ${getInjectedContent(ctx, "redirect", "body", "prepend")}
414
- ${getCounterContent(ctx)}
415
- ${getInjectedContent(ctx, "redirect", "body", "append")}
416
- <script>window.location.replace("${escapedRedirect}");</script>
417
- </body>
418
- </html>
419
- `);
420
- }
421
-
422
- // src/utils/escapeRegExp.ts
423
- function escapeRegExp(s) {
424
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
425
- }
426
-
427
328
  // src/bin/getRepoLink.ts
428
329
  function getRepoLink({ repo }, className) {
429
330
  if (!repo) return "";
@@ -431,6 +332,22 @@ function getRepoLink({ repo }, className) {
431
332
  return `<a href="${repo}"${className ? ` class="${className}"` : ""} target="_blank">${caption}</a>`;
432
333
  }
433
334
 
335
+ // src/bin/getRepoMetadata.ts
336
+ async function getRepoMetadata({
337
+ repo
338
+ }) {
339
+ if (repo?.startsWith("https://github.com/")) {
340
+ try {
341
+ let repoMetadata = await fetchContent(
342
+ repo.replace("https://github.com/", "https://api.github.com/repos/")
343
+ );
344
+ return JSON.parse(repoMetadata);
345
+ } catch {
346
+ }
347
+ }
348
+ return {};
349
+ }
350
+
434
351
  // src/bin/parsing/getParsedContent.ts
435
352
  import { JSDOM as JSDOM2 } from "jsdom";
436
353
  import Markdown from "markdown-it";
@@ -652,6 +569,22 @@ async function getParsedContent(ctx) {
652
569
  return parsedContent;
653
570
  }
654
571
 
572
+ // src/bin/content/getCounterContent.ts
573
+ function getCounterContent({ ymid }) {
574
+ if (!ymid) return "";
575
+ return `
576
+ <script>
577
+ (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
578
+ m[i].l=1*new Date();
579
+ for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
580
+ k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
581
+ (window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
582
+ ym(${ymid}, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
583
+ </script>
584
+ <noscript><div><img src="https://mc.yandex.com/watch/${ymid}" style="position:absolute;left:-9999px;" alt=""></div></noscript>
585
+ `.trim();
586
+ }
587
+
655
588
  // src/bin/content/getCSSRoot.ts
656
589
  import { exec as defaultExec } from "node:child_process";
657
590
  import { cp } from "node:fs/promises";
@@ -709,13 +642,44 @@ function getDefaultCodeStyleContent(cssRoot) {
709
642
  `.trim();
710
643
  }
711
644
 
712
- // src/bin/content/getInstallationContent.ts
713
- async function getInstallationContent(ctx) {
714
- let { name, isDevDep } = ctx;
715
- let { installation } = await getParsedContent(ctx);
716
- if (!installation || isDevDep !== void 0)
717
- installation = `npm i${isDevDep ? " -D" : ""} ${name}`;
718
- return `<code>${escapeHTML(installation)}</code>`;
645
+ // src/bin/content/getIcon.ts
646
+ var iconTypeMap = {
647
+ ico: "image/x-icon",
648
+ svg: "image/svg+xml",
649
+ png: "image/png",
650
+ gif: "image/gif",
651
+ jpg: "image/jpeg",
652
+ jpeg: "image/jpeg"
653
+ };
654
+ function getIcon({ favicon, faviconType }) {
655
+ let icon = {
656
+ url: favicon,
657
+ type: faviconType
658
+ };
659
+ if (icon.url && !icon.type) {
660
+ let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
661
+ if (ext) icon.type = iconTypeMap[ext];
662
+ }
663
+ return icon;
664
+ }
665
+
666
+ // src/bin/content/getIconTag.ts
667
+ function getIconTag(ctx) {
668
+ let { url, type } = getIcon(ctx);
669
+ return url ? `<link rel="icon"${type ? ` type="${type}"` : ""} href="${url}">` : "";
670
+ }
671
+
672
+ // src/bin/content/getInjectedContent.ts
673
+ function getInjectedContent(ctx, page, target, mode) {
674
+ let injectedContent = ctx[mode]?.[target];
675
+ if (!injectedContent) return "";
676
+ return (Array.isArray(injectedContent) ? injectedContent : [injectedContent]).reduce((s, item) => {
677
+ if (item === void 0) return s;
678
+ if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
679
+ let { content, pages } = item;
680
+ if (!content || pages && !pages.includes(page)) return s;
681
+ return `${s}${s ? "\n" : ""}${content}`;
682
+ }, "");
719
683
  }
720
684
 
721
685
  // src/bin/content/getPlainTitle.ts
@@ -733,6 +697,119 @@ async function getMainTitle(ctx) {
733
697
  return htmlTitle || parsedTitle || plainTitle;
734
698
  }
735
699
 
700
+ // src/bin/content/toFileContent.ts
701
+ function toFileContent(x) {
702
+ let s = x.replace(
703
+ /\s+(\r?\n *<\/?(script|link|head|body|html|meta|title)[> ])/g,
704
+ "$1"
705
+ ).replace(
706
+ /\s+(\r?\n *<\/?(main|header|footer|nav|section|div|h\d|p|ul|ol|li|table)[> ])/g,
707
+ "$1"
708
+ ).trim();
709
+ return `${s}
710
+ `;
711
+ }
712
+
713
+ // src/bin/content/tweakTypography.ts
714
+ function tweakTypography(s = "") {
715
+ return s.replace(/\b(for|in|on|at|to|with|a|an|the|its)\s+/gi, "$1\xA0").replace(/\b(React)\s+(apps?)\b/gi, "$1\xA0$2");
716
+ }
717
+
718
+ // src/bin/content/getIndexContent.ts
719
+ async function getIndexContent(ctx) {
720
+ let {
721
+ root,
722
+ contentDir = "",
723
+ description: packageDescription,
724
+ backstory
725
+ } = ctx;
726
+ let counterContent = getCounterContent(ctx);
727
+ let escapedPackageDescription = escapeHTML(packageDescription);
728
+ let repoDescription = (await getRepoMetadata(ctx)).description;
729
+ let { description, nav } = await getParsedContent(ctx);
730
+ let descriptionContent = escapeHTML(
731
+ tweakTypography(repoDescription || description)
732
+ );
733
+ let plainTitle = await getPlainTitle(ctx);
734
+ let cssRoot = await getCSSRoot(ctx, "index");
735
+ let links = [
736
+ `<a href="${root}${contentDir}" class="primary">Docs</a>`,
737
+ getRepoLink(ctx),
738
+ backstory ? `<a href="${backstory}">Backstory</a>` : ""
739
+ ].filter((x) => x !== "");
740
+ let sep = '&nbsp;<span class="sep">\xB7</span> ';
741
+ return toFileContent(`
742
+ <!DOCTYPE html>
743
+ <html lang="en" data-layout="index" class="aux">
744
+ <head>
745
+ ${getInjectedContent(ctx, "index", "head", "prepend")}
746
+ <meta charset="utf-8">
747
+ <meta name="viewport" content="width=device-width, initial-scale=1">
748
+ <meta name="description" content="${plainTitle}${escapedPackageDescription ? `: ${escapedPackageDescription}` : ""}">
749
+ <title>${plainTitle}${escapedPackageDescription ? ` | ${escapedPackageDescription}` : ""}</title>
750
+ <link rel="stylesheet" href="${cssRoot}/base.css">
751
+ <link rel="stylesheet" href="${cssRoot}/index.css">
752
+ ${getIconTag(ctx)}
753
+ <link rel="prefetch" href="${root}${contentDir}">
754
+ ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
755
+ ${getInjectedContent(ctx, "index", "head", "append")}
756
+ </head>
757
+ <body>
758
+ ${getInjectedContent(ctx, "index", "body", "prepend")}
759
+ <div class="layout">
760
+ <main>
761
+ <h1>${await getMainTitle(ctx)}</h1>
762
+ <p class="description">${descriptionContent}</p>
763
+ ${links.length === 0 ? "" : `<p class="links">${links.join(sep)}</p>`}
764
+ </main>
765
+ </div>
766
+ ${[descriptionContent].some((s) => s.includes("<pre><code ")) ? getInjectedContent(ctx, "index", ":has-code", "append") || getDefaultCodeStyleContent(cssRoot) : ""}
767
+ ${counterContent}
768
+ ${getInjectedContent(ctx, "index", "body", "append")}
769
+ </body>
770
+ </html>
771
+ `);
772
+ }
773
+
774
+ // src/bin/content/getRedirectContent.ts
775
+ function getRedirectContent(ctx) {
776
+ let { redirect } = ctx;
777
+ let escapedRedirect = escapeHTML(redirect);
778
+ return toFileContent(`
779
+ <!DOCTYPE html>
780
+ <html lang="en" data-layout="redirect" class="blank">
781
+ <head>
782
+ ${getInjectedContent(ctx, "redirect", "head", "prepend")}
783
+ <meta charset="utf-8">
784
+ <meta name="viewport" content="width=device-width">
785
+ <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
786
+ ${getIconTag(ctx)}
787
+ ${getInjectedContent(ctx, "redirect", "head", "append")}
788
+ </head>
789
+ <body>
790
+ ${getInjectedContent(ctx, "redirect", "body", "prepend")}
791
+ ${getCounterContent(ctx)}
792
+ ${getInjectedContent(ctx, "redirect", "body", "append")}
793
+ <script>window.location.replace("${escapedRedirect}");</script>
794
+ </body>
795
+ </html>
796
+ `);
797
+ }
798
+
799
+ // src/utils/escapeRegExp.ts
800
+ function escapeRegExp(s) {
801
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
802
+ }
803
+
804
+ // src/bin/content/getInstallationContent.ts
805
+ async function getInstallationContent(ctx) {
806
+ let { name, isDevDep } = ctx;
807
+ let { installation } = await getParsedContent(ctx);
808
+ if (!installation || isDevDep !== void 0)
809
+ installation = `npm i${isDevDep ? " -D" : ""} ${name}`;
810
+ return `<code>${escapeHTML(installation)}</code>`;
811
+ }
812
+
736
813
  // src/bin/content/getNav.ts
737
814
  import { JSDOM as JSDOM3 } from "jsdom";
738
815
 
@@ -816,11 +893,6 @@ ${navContent}
816
893
  </nav>`;
817
894
  }
818
895
 
819
- // src/bin/content/tweakTypography.ts
820
- function tweakTypography(s = "") {
821
- return s.replace(/\b(for|in|on|at|to|with|a|an|the|its)\s+/gi, "$1\xA0").replace(/\b(React)\s+(apps?)\b/gi, "$1\xA0$2");
822
- }
823
-
824
896
  // src/bin/content/getSectionContent.ts
825
897
  async function getSectionContent(ctx, index) {
826
898
  let { root, contentDir = "" } = ctx;
@@ -892,10 +964,11 @@ ${getInjectedContent(ctx, "section", "body", "append")}
892
964
  }
893
965
 
894
966
  // src/bin/content/getStartContent.ts
895
- async function getStartContent(ctx, delay = 0) {
967
+ async function getStartContent(ctx, delay) {
896
968
  let { root, contentDir = "" } = ctx;
897
969
  let { nav } = await getParsedContent(ctx);
898
970
  let plainTitle = await getPlainTitle(ctx);
971
+ let jsRedirect = `window.location.replace("${root}${contentDir}/${nav[0]?.id}");`;
899
972
  return toFileContent(`
900
973
  <!DOCTYPE html>
901
974
  <html lang="en" data-layout="start" class="blank">
@@ -903,11 +976,11 @@ async function getStartContent(ctx, delay = 0) {
903
976
  ${getInjectedContent(ctx, "start", "head", "prepend")}
904
977
  <meta charset="utf-8">
905
978
  <meta name="viewport" content="width=device-width">
906
- <meta http-equiv="refresh" content="${delay}; URL=${root}${contentDir}/${nav[0]?.id}">
979
+ <meta http-equiv="refresh" content="${delay ?? 0}; URL=${root}${contentDir}/${nav[0]?.id}">
907
980
  <title>${plainTitle}</title>
908
- <link rel="stylesheet" href="${await getCSSRoot(ctx, "index")}/base.css">
981
+ <link rel="stylesheet" href="${await getCSSRoot(ctx, "content")}/base.css">
909
982
  ${getIconTag(ctx)}
910
- <script>setTimeout(() => { window.location.replace("${root}${contentDir}/${nav[0]?.id}"); }, ${delay * 1e3});</script>
983
+ <script>${delay === void 0 ? jsRedirect : `setTimeout(() => { ${jsRedirect} }, ${delay * 1e3});`}</script>
911
984
  ${getInjectedContent(ctx, "start", "head", "append")}
912
985
  </head>
913
986
  <body>
@@ -939,9 +1012,8 @@ async function setContent(ctx) {
939
1012
  await getSectionContent(ctx, i)
940
1013
  )
941
1014
  ),
942
- // writeFile(join(dir, "index.html"), await getIndexContent(ctx)),
943
- writeFile2(join5(dir, "index.html"), await getStartContent(ctx, 3)),
944
- writeFile2(join5(dir, "start.html"), await getStartContent(ctx))
1015
+ writeFile2(join5(dir, "index.html"), await getIndexContent(ctx)),
1016
+ writeFile2(join5(dir, contentDir, "index.html"), await getStartContent(ctx))
945
1017
  ]);
946
1018
  }
947
1019
 
@@ -1,254 +1,42 @@
1
1
  :root {
2
- --max-content-width: 38em;
3
- }
4
- body {
5
- min-height: 100vh;
2
+ line-height: 1.35;
6
3
  }
7
4
  .layout {
8
5
  display: flex;
6
+ min-height: 90vh;
9
7
  flex-direction: column;
10
- min-height: 95vh;
11
8
  align-items: center;
12
9
  justify-content: center;
13
- }
14
- @media (max-width: 840px) {
15
- :root {
16
- --content-padding-x: 1.75rem;
17
- }
18
- .layout {
19
- min-height: 100vh;
20
- }
21
- }
22
-
23
- main {
24
- display: flex;
25
- width: 100%;
26
- align-items: flex-start;
27
- justify-content: center;
28
- padding: 0;
29
- margin: 0;
10
+ padding: var(--content-padding-y) var(--content-padding-x);
30
11
  box-sizing: border-box;
31
12
  }
32
- @media (max-width: 840px) {
33
- main {
34
- min-height: 100vh;
35
- flex-direction: column;
36
- margin: 0;
37
- }
38
- }
39
-
40
- h1 {
41
- max-width: 16rem;
42
- font-size: 1.6em;
43
- font-weight: 900;
44
- margin: 1rem 0;
45
- }
46
- @media (max-width: 840px) {
47
- h1 {
48
- max-width: none;
49
- }
50
- }
51
- h1 > a,
52
- h1 > a:link,
53
- h1 > a:hover,
54
- h1 > a:visited,
55
- h1 > a:active {
56
- border-bottom: none;
57
- }
58
- h1 sup {
59
- font-size: 0.5em;
60
- }
61
- header {
62
- display: block;
13
+ main {
14
+ width: 500px;
63
15
  text-align: center;
64
- padding: 0 var(--content-padding-x);
65
- }
66
- .description {
67
- margin: 0;
68
- }
69
- .description p {
70
- margin: 0;
71
- }
72
- .description p + p {
73
- margin-top: 0.75em;
74
- }
75
- .description em {
76
- font-style: normal;
77
- }
78
- .actions {
79
- margin: 1.25rem 0;
80
- }
81
- .actions .sep {
82
- display: block;
83
- height: 0.01em;
84
- font-size: 0;
85
- overflow: hidden;
86
- margin: 0.35rem 0;
87
- }
88
- .actions .primary {
89
- font-weight: bold;
90
- }
91
- .ref {
92
- font-size: 0.9em;
93
- }
94
- @media (max-width: 840px) {
95
- .actions .sep {
96
- margin: 0.5rem 0;
97
- }
98
- }
99
-
100
- section {
101
- width: 50%;
102
- min-height: 100vh;
103
- align-self: stretch;
104
- padding: 0;
105
16
  box-sizing: border-box;
106
17
  }
107
- section .section-content {
108
- max-width: var(--max-content-width);
109
- padding: 15vh 2.5em;
110
- box-sizing: border-box;
111
- }
112
- section.intro-title {
113
- display: flex;
114
- width: 40%;
115
- flex-direction: column;
116
- align-items: flex-end;
117
- text-align: right;
118
- line-height: 1.3;
119
- color: var(--emphatic-color);
120
- background: linear-gradient(
121
- to right,
122
- var(--aux-background),
123
- var(--aux-background-end)
124
- );
125
- border-right: 0.05em solid var(--aux-border-color);
126
- }
127
- section.intro-title .section-content {
128
- display: flex;
129
- flex-direction: column;
130
- align-items: flex-end;
131
- max-width: 24em;
132
- }
133
- section.intro-title:last-of-type {
134
- width: 100%;
135
- min-height: 100vh;
136
- justify-content: center;
137
- align-items: center;
138
- text-align: center;
139
- }
140
- section.intro-title:last-of-type .section-content {
141
- max-width: 36em;
142
- align-items: center;
143
- }
144
- section.intro {
145
- display: flex;
146
- width: 60%;
147
- flex-direction: column;
18
+ main .links {
19
+ font-size: 1.2em;
148
20
  }
149
- section.intro .section-content {
150
- width: 100%;
151
- }
152
- section.intro pre {
153
- margin: 1.75em 0;
154
- }
155
- @media (max-width: 840px) {
156
- section {
157
- width: auto;
158
- max-width: 100%;
159
- min-height: auto;
160
- }
161
- section .section-content {
162
- max-width: 100%;
163
- padding: 1rem var(--content-padding-x);
164
- }
165
- section.intro-title {
166
- flex: auto;
167
- width: auto;
168
- align-items: center;
169
- justify-content: center;
170
- text-align: center;
171
- background: linear-gradient(
172
- to bottom,
173
- var(--aux-background),
174
- var(--aux-background-end)
175
- );
176
- border-right: none;
177
- border-bottom: 0.05em solid var(--aux-border-color);
178
- }
179
- section.intro-title .section-content {
180
- min-height: 35vh;
181
- align-items: center;
182
- padding-top: 2rem;
183
- padding-bottom: 2.5rem;
184
- }
185
- section.intro-title:last-child .section-content {
186
- max-width: 100%;
187
- padding-bottom: 2.5rem;
188
- }
189
- section.intro {
190
- width: auto;
191
- flex: none;
192
- justify-content: flex-start;
193
- align-items: center;
194
- }
195
- section.intro .section-content {
196
- padding-top: 0.75rem;
197
- }
198
- }
199
- .features {
200
- --list-padding-x: 1.25rem;
201
- --list-item-padding-x: 0.35rem;
202
- margin: 1em 0;
203
- }
204
- .features h2 {
205
- font-size: 1.25em;
206
- font-style: italic;
207
- border: none;
208
- padding: 0.1em calc(var(--list-padding-x) + var(--list-item-padding-x));
209
- margin: 0.75em 0 0.5em;
21
+ main .links .sep {
22
+ display: inline-block;
23
+ margin: 0 0.15em;
210
24
  }
211
- .features > ul {
212
- list-style: circle;
213
- padding: 0;
214
- padding-inline-start: var(--list-padding-x);
215
- margin: 0.5em 0 0;
25
+ main .links .primary {
26
+ font-weight: bold;
216
27
  }
217
- .features > ul > li {
218
- padding: 0.25em var(--list-item-padding-x);
28
+ main p {
219
29
  margin: 0;
220
- box-sizing: border-box;
221
- }
222
- .features > ul > li + li {
223
- border-top: 0.075em solid var(--line-color);
224
- }
225
- @media (max-width: 840px) {
226
- .features h2 {
227
- text-align: center;
228
- }
229
- .features > ul > li {
230
- width: 100%;
231
- }
232
30
  }
233
- .features > ul > li > ul {
234
- list-style: disc;
31
+ main p.description {
32
+ margin-top: 1rem;
235
33
  }
236
- .note {
237
- margin: 1em 0;
34
+ main p.links {
35
+ margin-top: 1rem;
238
36
  }
239
37
  @media (max-width: 840px) {
240
- .note {
241
- padding: 0;
38
+ main {
39
+ width: auto;
40
+ max-width: 500px;
242
41
  }
243
42
  }
244
- p.installation {
245
- margin: 0;
246
- }
247
- .installation code {
248
- background: transparent;
249
- }
250
-
251
- .li {
252
- display: inline-block;
253
- margin: 0.25em 0;
254
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/docsgen",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "description": "",
5
5
  "main": "dist/bin.js",
6
6
  "type": "module",
@@ -2,10 +2,10 @@ import { rm } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import type { Context } from "../types/Context.ts";
4
4
 
5
- export async function cleanup({ dir = "" }: Context) {
5
+ export async function cleanup({ dir = "", contentDir }: Context) {
6
6
  await Promise.all(
7
- ["x", "index.html", "start.html"].map((path) => {
8
- return rm(join(dir, path), { force: true, recursive: true });
7
+ [contentDir, "index.html"].map((path) => {
8
+ return path && rm(join(dir, path), { force: true, recursive: true });
9
9
  }),
10
10
  );
11
11
  }
@@ -1,17 +1,17 @@
1
1
  import type { Context } from "../../types/Context.ts";
2
2
  import { escapeHTML } from "../../utils/escapeHTML.ts";
3
3
  import { getRepoLink } from "../getRepoLink.ts";
4
+ import { getRepoMetadata } from "../getRepoMetadata.ts";
4
5
  import { getParsedContent } from "../parsing/getParsedContent.ts";
5
6
  import { getCounterContent } from "./getCounterContent.ts";
6
7
  import { getCSSRoot } from "./getCSSRoot.ts";
7
8
  import { getDefaultCodeStyleContent } from "./getDefaultCodeStyleContent.ts";
8
- import { getDescriptionContent } from "./getDescriptionContent.ts";
9
9
  import { getIconTag } from "./getIconTag.ts";
10
10
  import { getInjectedContent } from "./getInjectedContent.ts";
11
- import { getInstallationContent } from "./getInstallationContent.ts";
12
11
  import { getMainTitle } from "./getMainTitle.ts";
13
12
  import { getPlainTitle } from "./getPlainTitle.ts";
14
13
  import { toFileContent } from "./toFileContent.ts";
14
+ import { tweakTypography } from "./tweakTypography.ts";
15
15
 
16
16
  export async function getIndexContent(ctx: Context) {
17
17
  let {
@@ -23,15 +23,27 @@ export async function getIndexContent(ctx: Context) {
23
23
 
24
24
  let counterContent = getCounterContent(ctx);
25
25
  let escapedPackageDescription = escapeHTML(packageDescription);
26
+ let repoDescription = (await getRepoMetadata(ctx)).description;
26
27
 
27
- let { description, intro, features, note, nav } = await getParsedContent(ctx);
28
+ let { description, nav } = await getParsedContent(ctx);
29
+ let descriptionContent = escapeHTML(
30
+ tweakTypography(repoDescription || description),
31
+ );
28
32
 
29
33
  let plainTitle = await getPlainTitle(ctx);
30
34
  let cssRoot = await getCSSRoot(ctx, "index");
31
35
 
36
+ let links = [
37
+ `<a href="${root}${contentDir}" class="primary">Docs</a>`,
38
+ getRepoLink(ctx),
39
+ backstory ? `<a href="${backstory}">Backstory</a>` : "",
40
+ ].filter((x) => x !== "");
41
+
42
+ let sep = '&nbsp;<span class="sep">·</span> ';
43
+
32
44
  return toFileContent(`
33
45
  <!DOCTYPE html>
34
- <html lang="en" data-layout="index">
46
+ <html lang="en" data-layout="index" class="aux">
35
47
  <head>
36
48
  ${getInjectedContent(ctx, "index", "head", "prepend")}
37
49
  <meta charset="utf-8">
@@ -41,7 +53,7 @@ export async function getIndexContent(ctx: Context) {
41
53
  <link rel="stylesheet" href="${cssRoot}/base.css">
42
54
  <link rel="stylesheet" href="${cssRoot}/index.css">
43
55
  ${getIconTag(ctx)}
44
- <link rel="prefetch" href="${root}start">
56
+ <link rel="prefetch" href="${root}${contentDir}">
45
57
  ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
46
58
  ${getInjectedContent(ctx, "index", "head", "append")}
47
59
  </head>
@@ -49,44 +61,13 @@ export async function getIndexContent(ctx: Context) {
49
61
  ${getInjectedContent(ctx, "index", "body", "prepend")}
50
62
  <div class="layout">
51
63
  <main>
52
- <section class="aux intro-title">
53
- <div class="section-content">
54
- ${getInjectedContent(ctx, "index", "cover", "prepend")}
55
- <h1>${await getMainTitle(ctx)}</h1>
56
- <div class="description">
57
- ${await getDescriptionContent(ctx)}
58
- </div>
59
- <p class="actions">
60
- <a href="${root}start" class="primary">Docs</a>
61
- <span class="sep"> • </span>
62
- ${getRepoLink(ctx)}
63
- </p>
64
- ${backstory ? `<p class="ref"><a href="${backstory}">Backstory</a></p>` : ""}
65
- <p class="installation">${await getInstallationContent(ctx)}</p>
66
- ${getInjectedContent(ctx, "index", "cover", "append")}
67
- </div>
68
- </section>
69
- ${
70
- intro || features || note
71
- ? `
72
- <section class="intro">
73
- <div class="section-content">
74
- ${intro ? `<div class="intro">${intro}</div>` : ""}
75
- ${features ? `<div class="features">${features}</div>` : ""}
76
- ${note ? `<div class="note">${note}</div>` : ""}
77
- <p class="pagenav">
78
- <span class="next"><a href="${root}start">To the docs</a> <span class="icon">→</span></span>
79
- </p>
80
- </div>
81
- </section>
82
- `
83
- : ""
84
- }
64
+ <h1>${await getMainTitle(ctx)}</h1>
65
+ <p class="description">${descriptionContent}</p>
66
+ ${links.length === 0 ? "" : `<p class="links">${links.join(sep)}</p>`}
85
67
  </main>
86
68
  </div>
87
-
88
69
  ${
89
- [description, intro, features, note].some((s) => s.includes("<pre><code "))
70
+ [descriptionContent].some((s) => s.includes("<pre><code "))
90
71
  ? getInjectedContent(ctx, "index", ":has-code", "append") ||
91
72
  getDefaultCodeStyleContent(cssRoot)
92
73
  : ""
@@ -2,7 +2,6 @@ import type { Context } from "../../types/Context.ts";
2
2
  import { escapeHTML } from "../../utils/escapeHTML.ts";
3
3
  import { escapeRegExp } from "../../utils/escapeRegExp.ts";
4
4
  import { getRepoLink } from "../getRepoLink.ts";
5
- // import { getRepoMetadata } from "../getRepoMetadata.ts";
6
5
  import { getParsedContent } from "../parsing/getParsedContent.ts";
7
6
  import { stripHTML } from "../stripHTML.ts";
8
7
  import { getCounterContent } from "./getCounterContent.ts";
@@ -19,8 +18,6 @@ import { tweakTypography } from "./tweakTypography.ts";
19
18
 
20
19
  export async function getSectionContent(ctx: Context, index: number) {
21
20
  let { root, contentDir = "" } = ctx;
22
- // let repoDescription =
23
- // index === 0 ? (await getRepoMetadata(ctx)).description : "";
24
21
  let descriptionContent = escapeHTML(tweakTypography(ctx.description));
25
22
 
26
23
  let cssRoot = await getCSSRoot(ctx, "content");
@@ -7,11 +7,13 @@ import { getInjectedContent } from "./getInjectedContent.ts";
7
7
  import { getPlainTitle } from "./getPlainTitle.ts";
8
8
  import { toFileContent } from "./toFileContent.ts";
9
9
 
10
- export async function getStartContent(ctx: Context, delay = 0) {
10
+ export async function getStartContent(ctx: Context, delay?: number) {
11
11
  let { root, contentDir = "" } = ctx;
12
12
  let { nav } = await getParsedContent(ctx);
13
13
  let plainTitle = await getPlainTitle(ctx);
14
14
 
15
+ let jsRedirect = `window.location.replace("${root}${contentDir}/${nav[0]?.id}");`;
16
+
15
17
  return toFileContent(`
16
18
  <!DOCTYPE html>
17
19
  <html lang="en" data-layout="start" class="blank">
@@ -19,11 +21,11 @@ export async function getStartContent(ctx: Context, delay = 0) {
19
21
  ${getInjectedContent(ctx, "start", "head", "prepend")}
20
22
  <meta charset="utf-8">
21
23
  <meta name="viewport" content="width=device-width">
22
- <meta http-equiv="refresh" content="${delay}; URL=${root}${contentDir}/${nav[0]?.id}">
24
+ <meta http-equiv="refresh" content="${delay ?? 0}; URL=${root}${contentDir}/${nav[0]?.id}">
23
25
  <title>${plainTitle}</title>
24
- <link rel="stylesheet" href="${await getCSSRoot(ctx, "index")}/base.css">
26
+ <link rel="stylesheet" href="${await getCSSRoot(ctx, "content")}/base.css">
25
27
  ${getIconTag(ctx)}
26
- <script>setTimeout(() => { window.location.replace("${root}${contentDir}/${nav[0]?.id}"); }, ${delay * 1000});</script>
28
+ <script>${delay === undefined ? jsRedirect : `setTimeout(() => { ${jsRedirect} }, ${delay * 1000});`}</script>
27
29
  ${getInjectedContent(ctx, "start", "head", "append")}
28
30
  </head>
29
31
  <body>
@@ -68,7 +68,7 @@ export async function getConfig(): Promise<Config> {
68
68
  config = {
69
69
  mainBranch: "main",
70
70
  root: "/",
71
- contentDir: "x",
71
+ contentDir: "docs",
72
72
  ...localConfig,
73
73
  ...parseArgs<Config>(args),
74
74
  };
@@ -2,7 +2,7 @@ import { writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import type { Context } from "../types/Context.ts";
4
4
  import { createDirs } from "./content/createDirs.ts";
5
- // import { getIndexContent } from "./content/getIndexContent.ts";
5
+ import { getIndexContent } from "./content/getIndexContent.ts";
6
6
  import { getRedirectContent } from "./content/getRedirectContent.ts";
7
7
  import { getSectionContent } from "./content/getSectionContent.ts";
8
8
  import { getStartContent } from "./content/getStartContent.ts";
@@ -27,8 +27,7 @@ export async function setContent(ctx: Context) {
27
27
  await getSectionContent(ctx, i),
28
28
  ),
29
29
  ),
30
- // writeFile(join(dir, "index.html"), await getIndexContent(ctx)),
31
- writeFile(join(dir, "index.html"), await getStartContent(ctx, 3)),
32
- writeFile(join(dir, "start.html"), await getStartContent(ctx)),
30
+ writeFile(join(dir, "index.html"), await getIndexContent(ctx)),
31
+ writeFile(join(dir, contentDir, "index.html"), await getStartContent(ctx)),
33
32
  ]);
34
33
  }
package/src/css/index.css CHANGED
@@ -1,254 +1,42 @@
1
1
  :root {
2
- --max-content-width: 38em;
3
- }
4
- body {
5
- min-height: 100vh;
2
+ line-height: 1.35;
6
3
  }
7
4
  .layout {
8
5
  display: flex;
6
+ min-height: 90vh;
9
7
  flex-direction: column;
10
- min-height: 95vh;
11
8
  align-items: center;
12
9
  justify-content: center;
13
- }
14
- @media (max-width: 840px) {
15
- :root {
16
- --content-padding-x: 1.75rem;
17
- }
18
- .layout {
19
- min-height: 100vh;
20
- }
21
- }
22
-
23
- main {
24
- display: flex;
25
- width: 100%;
26
- align-items: flex-start;
27
- justify-content: center;
28
- padding: 0;
29
- margin: 0;
10
+ padding: var(--content-padding-y) var(--content-padding-x);
30
11
  box-sizing: border-box;
31
12
  }
32
- @media (max-width: 840px) {
33
- main {
34
- min-height: 100vh;
35
- flex-direction: column;
36
- margin: 0;
37
- }
38
- }
39
-
40
- h1 {
41
- max-width: 16rem;
42
- font-size: 1.6em;
43
- font-weight: 900;
44
- margin: 1rem 0;
45
- }
46
- @media (max-width: 840px) {
47
- h1 {
48
- max-width: none;
49
- }
50
- }
51
- h1 > a,
52
- h1 > a:link,
53
- h1 > a:hover,
54
- h1 > a:visited,
55
- h1 > a:active {
56
- border-bottom: none;
57
- }
58
- h1 sup {
59
- font-size: 0.5em;
60
- }
61
- header {
62
- display: block;
13
+ main {
14
+ width: 500px;
63
15
  text-align: center;
64
- padding: 0 var(--content-padding-x);
65
- }
66
- .description {
67
- margin: 0;
68
- }
69
- .description p {
70
- margin: 0;
71
- }
72
- .description p + p {
73
- margin-top: 0.75em;
74
- }
75
- .description em {
76
- font-style: normal;
77
- }
78
- .actions {
79
- margin: 1.25rem 0;
80
- }
81
- .actions .sep {
82
- display: block;
83
- height: 0.01em;
84
- font-size: 0;
85
- overflow: hidden;
86
- margin: 0.35rem 0;
87
- }
88
- .actions .primary {
89
- font-weight: bold;
90
- }
91
- .ref {
92
- font-size: 0.9em;
93
- }
94
- @media (max-width: 840px) {
95
- .actions .sep {
96
- margin: 0.5rem 0;
97
- }
98
- }
99
-
100
- section {
101
- width: 50%;
102
- min-height: 100vh;
103
- align-self: stretch;
104
- padding: 0;
105
16
  box-sizing: border-box;
106
17
  }
107
- section .section-content {
108
- max-width: var(--max-content-width);
109
- padding: 15vh 2.5em;
110
- box-sizing: border-box;
111
- }
112
- section.intro-title {
113
- display: flex;
114
- width: 40%;
115
- flex-direction: column;
116
- align-items: flex-end;
117
- text-align: right;
118
- line-height: 1.3;
119
- color: var(--emphatic-color);
120
- background: linear-gradient(
121
- to right,
122
- var(--aux-background),
123
- var(--aux-background-end)
124
- );
125
- border-right: 0.05em solid var(--aux-border-color);
126
- }
127
- section.intro-title .section-content {
128
- display: flex;
129
- flex-direction: column;
130
- align-items: flex-end;
131
- max-width: 24em;
132
- }
133
- section.intro-title:last-of-type {
134
- width: 100%;
135
- min-height: 100vh;
136
- justify-content: center;
137
- align-items: center;
138
- text-align: center;
139
- }
140
- section.intro-title:last-of-type .section-content {
141
- max-width: 36em;
142
- align-items: center;
143
- }
144
- section.intro {
145
- display: flex;
146
- width: 60%;
147
- flex-direction: column;
18
+ main .links {
19
+ font-size: 1.2em;
148
20
  }
149
- section.intro .section-content {
150
- width: 100%;
151
- }
152
- section.intro pre {
153
- margin: 1.75em 0;
154
- }
155
- @media (max-width: 840px) {
156
- section {
157
- width: auto;
158
- max-width: 100%;
159
- min-height: auto;
160
- }
161
- section .section-content {
162
- max-width: 100%;
163
- padding: 1rem var(--content-padding-x);
164
- }
165
- section.intro-title {
166
- flex: auto;
167
- width: auto;
168
- align-items: center;
169
- justify-content: center;
170
- text-align: center;
171
- background: linear-gradient(
172
- to bottom,
173
- var(--aux-background),
174
- var(--aux-background-end)
175
- );
176
- border-right: none;
177
- border-bottom: 0.05em solid var(--aux-border-color);
178
- }
179
- section.intro-title .section-content {
180
- min-height: 35vh;
181
- align-items: center;
182
- padding-top: 2rem;
183
- padding-bottom: 2.5rem;
184
- }
185
- section.intro-title:last-child .section-content {
186
- max-width: 100%;
187
- padding-bottom: 2.5rem;
188
- }
189
- section.intro {
190
- width: auto;
191
- flex: none;
192
- justify-content: flex-start;
193
- align-items: center;
194
- }
195
- section.intro .section-content {
196
- padding-top: 0.75rem;
197
- }
198
- }
199
- .features {
200
- --list-padding-x: 1.25rem;
201
- --list-item-padding-x: 0.35rem;
202
- margin: 1em 0;
203
- }
204
- .features h2 {
205
- font-size: 1.25em;
206
- font-style: italic;
207
- border: none;
208
- padding: 0.1em calc(var(--list-padding-x) + var(--list-item-padding-x));
209
- margin: 0.75em 0 0.5em;
21
+ main .links .sep {
22
+ display: inline-block;
23
+ margin: 0 0.15em;
210
24
  }
211
- .features > ul {
212
- list-style: circle;
213
- padding: 0;
214
- padding-inline-start: var(--list-padding-x);
215
- margin: 0.5em 0 0;
25
+ main .links .primary {
26
+ font-weight: bold;
216
27
  }
217
- .features > ul > li {
218
- padding: 0.25em var(--list-item-padding-x);
28
+ main p {
219
29
  margin: 0;
220
- box-sizing: border-box;
221
- }
222
- .features > ul > li + li {
223
- border-top: 0.075em solid var(--line-color);
224
- }
225
- @media (max-width: 840px) {
226
- .features h2 {
227
- text-align: center;
228
- }
229
- .features > ul > li {
230
- width: 100%;
231
- }
232
30
  }
233
- .features > ul > li > ul {
234
- list-style: disc;
31
+ main p.description {
32
+ margin-top: 1rem;
235
33
  }
236
- .note {
237
- margin: 1em 0;
34
+ main p.links {
35
+ margin-top: 1rem;
238
36
  }
239
37
  @media (max-width: 840px) {
240
- .note {
241
- padding: 0;
38
+ main {
39
+ width: auto;
40
+ max-width: 500px;
242
41
  }
243
42
  }
244
- p.installation {
245
- margin: 0;
246
- }
247
- .installation code {
248
- background: transparent;
249
- }
250
-
251
- .li {
252
- display: inline-block;
253
- margin: 0.25em 0;
254
- }