@t8/docsgen 0.1.18 → 0.1.20

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
@@ -104,6 +104,15 @@ function getLocation(ctx, path, preferredLocation) {
104
104
  return path;
105
105
  }
106
106
 
107
+ // src/bin/stripHTML.ts
108
+ var import_jsdom = require("jsdom");
109
+ function stripHTML(content) {
110
+ try {
111
+ return new import_jsdom.JSDOM(content).window.document.body.textContent;
112
+ } catch {
113
+ }
114
+ }
115
+
107
116
  // src/bin/toRepoURL.ts
108
117
  function toRepoURL(x) {
109
118
  if (!x) return "";
@@ -143,6 +152,22 @@ async function addMetadata(config2) {
143
152
  return config2;
144
153
  }
145
154
  }
155
+ function deriveMissingProps(config2) {
156
+ let { dir, root, title, htmlTitle } = config2;
157
+ if (htmlTitle && !title) title = stripHTML(htmlTitle);
158
+ if (dir && !root) root = `/${dir}/`;
159
+ if (!root?.endsWith("/")) root = `${root ?? ""}/`;
160
+ return {
161
+ ...config2,
162
+ dir,
163
+ root,
164
+ title,
165
+ htmlTitle
166
+ };
167
+ }
168
+ async function reviseConfig(config2) {
169
+ return deriveMissingProps(await addMetadata(config2));
170
+ }
146
171
  var config = null;
147
172
  async function getConfig() {
148
173
  if (config) return config;
@@ -165,9 +190,8 @@ async function getConfig() {
165
190
  ...A(args)
166
191
  };
167
192
  if (config.entries)
168
- config.entries = await Promise.all(config.entries.map(addMetadata));
169
- else await addMetadata(config);
170
- if (!config.root?.endsWith("/")) config.root = `${config.root ?? ""}/`;
193
+ config.entries = await Promise.all(config.entries.map(reviseConfig));
194
+ else config = await reviseConfig(config);
171
195
  return config;
172
196
  }
173
197
 
@@ -267,8 +291,21 @@ function getIcon({ favicon, faviconType }) {
267
291
  return icon;
268
292
  }
269
293
 
294
+ // src/bin/getInjectedContent.ts
295
+ function getInjectedContent(ctx, page, target, mode = "append") {
296
+ let injectedContent = ctx[mode]?.[target];
297
+ if (!injectedContent) return "";
298
+ return (Array.isArray(injectedContent) ? injectedContent : [injectedContent]).reduce((s, item) => {
299
+ if (item === void 0) return s;
300
+ if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
301
+ let { content, pages } = item;
302
+ if (!content || pages && !pages.includes(page)) return s;
303
+ return `${s}${s ? "\n" : ""}${content}`;
304
+ }, "");
305
+ }
306
+
270
307
  // src/bin/getNav.ts
271
- var import_jsdom = require("jsdom");
308
+ var import_jsdom2 = require("jsdom");
272
309
 
273
310
  // src/bin/getRepoLink.ts
274
311
  function getRepoLink({ repo }, className) {
@@ -283,7 +320,7 @@ async function getNav(ctx, navItems) {
283
320
  let navContent = await fetchText(nav);
284
321
  let s = "";
285
322
  if (navContent) {
286
- let navDom = new import_jsdom.JSDOM(navContent).window.document.body;
323
+ let navDom = new import_jsdom2.JSDOM(navContent).window.document.body;
287
324
  for (let link of navDom.querySelectorAll("a")) {
288
325
  if (link.dataset.name === name) {
289
326
  let parent = link.parentElement;
@@ -331,7 +368,7 @@ ${navContent}
331
368
  }
332
369
 
333
370
  // src/bin/getParsedContent.ts
334
- var import_jsdom2 = require("jsdom");
371
+ var import_jsdom3 = require("jsdom");
335
372
  var import_markdown_it = __toESM(require("markdown-it"));
336
373
 
337
374
  // src/bin/getSlug.ts
@@ -415,7 +452,7 @@ function getSectionPostprocess(linkMap) {
415
452
  };
416
453
  }
417
454
  function postprocessBadges(content) {
418
- let { document } = new import_jsdom2.JSDOM(content).window;
455
+ let { document } = new import_jsdom3.JSDOM(content).window;
419
456
  for (let img of document.querySelectorAll("img")) {
420
457
  let parent = img.parentElement;
421
458
  if (!parent) continue;
@@ -430,7 +467,7 @@ async function getParsedContent(ctx) {
430
467
  let { singlePage } = ctx;
431
468
  let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
432
469
  let content = md.render(rawContent);
433
- let dom = new import_jsdom2.JSDOM(content);
470
+ let dom = new import_jsdom3.JSDOM(content);
434
471
  let { nav, linkMap } = buildNav(ctx, dom);
435
472
  let badges = [];
436
473
  let title = "";
@@ -511,7 +548,7 @@ function getTitle(ctx, { cover, originalContent, withPackageURL } = {}) {
511
548
 
512
549
  // src/bin/toFileContent.ts
513
550
  function toFileContent(x) {
514
- return `${x.trim()}
551
+ return `${x.replace(/\s+(<\/(head|body)>)/g, "\n$1").trim()}
515
552
  `;
516
553
  }
517
554
 
@@ -552,9 +589,11 @@ async function setContent(ctx) {
552
589
  <meta name="viewport" content="width=device-width">
553
590
  <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
554
591
  ${iconTag}
592
+ ${getInjectedContent(ctx, "redirect", "head")}
555
593
  </head>
556
594
  <body>
557
595
  ${counterContent}
596
+ ${getInjectedContent(ctx, "redirect", "body")}
558
597
  <script>window.location.replace("${escapedRedirect}");</script>
559
598
  </body>
560
599
  </html>
@@ -592,6 +631,7 @@ ${counterContent}
592
631
  ${iconTag}
593
632
  ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
594
633
  ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
634
+ ${getInjectedContent(ctx, "section", "head")}
595
635
  </head>
596
636
  <body>
597
637
  <div class="layout">
@@ -626,6 +666,7 @@ ${content.includes("<pre><code ") ? `
626
666
  <script>hljs.highlightAll()</script>
627
667
  `.trim() : ""}
628
668
  ${counterContent}
669
+ ${getInjectedContent(ctx, "section", "body")}
629
670
  </body>
630
671
  </html>
631
672
  `)
@@ -646,6 +687,7 @@ ${counterContent}
646
687
  ${iconTag}
647
688
  <link rel="prefetch" href="${root}start">
648
689
  ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
690
+ ${getInjectedContent(ctx, "index", "head")}
649
691
  </head>
650
692
  <body>
651
693
  <div class="layout">
@@ -685,6 +727,7 @@ ${[description, features].some((s) => s.includes("<pre><code ")) ? `
685
727
  <script>hljs.highlightAll()</script>
686
728
  `.trim() : ""}
687
729
  ${counterContent}
730
+ ${getInjectedContent(ctx, "index", "body")}
688
731
  </body>
689
732
  </html>
690
733
  `)
@@ -702,6 +745,7 @@ ${counterContent}
702
745
  <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
703
746
  ${iconTag}
704
747
  <script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
748
+ ${getInjectedContent(ctx, "start", "head")}
705
749
  </head>
706
750
  <body>
707
751
  <div class="layout">
@@ -709,6 +753,7 @@ ${counterContent}
709
753
  </div>
710
754
 
711
755
  ${counterContent}
756
+ ${getInjectedContent(ctx, "start", "body")}
712
757
  </body>
713
758
  </html>
714
759
  `)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/docsgen",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "",
5
5
  "main": "dist/bin.js",
6
6
  "bin": {
@@ -4,6 +4,7 @@ import type { EntryConfig } from "../types/EntryConfig";
4
4
  import type { PackageMetadata } from "../types/PackageMetadata";
5
5
  import { fetchText } from "./fetchText";
6
6
  import { getLocation } from "./getLocation";
7
+ import { stripHTML } from "./stripHTML";
7
8
  import { toConfig } from "./toConfig";
8
9
 
9
10
  async function addMetadata(config: EntryConfig) {
@@ -20,6 +21,26 @@ async function addMetadata(config: EntryConfig) {
20
21
  }
21
22
  }
22
23
 
24
+ function deriveMissingProps(config: EntryConfig) {
25
+ let { dir, root, title, htmlTitle } = config;
26
+
27
+ if (htmlTitle && !title) title = stripHTML(htmlTitle);
28
+ if (dir && !root) root = `/${dir}/`;
29
+ if (!root?.endsWith("/")) root = `${root ?? ""}/`;
30
+
31
+ return {
32
+ ...config,
33
+ dir,
34
+ root,
35
+ title,
36
+ htmlTitle,
37
+ };
38
+ }
39
+
40
+ async function reviseConfig(config: EntryConfig) {
41
+ return deriveMissingProps(await addMetadata(config));
42
+ }
43
+
23
44
  let config: BinConfig | null = null;
24
45
 
25
46
  export async function getConfig(): Promise<BinConfig> {
@@ -48,10 +69,8 @@ export async function getConfig(): Promise<BinConfig> {
48
69
  };
49
70
 
50
71
  if (config.entries)
51
- config.entries = await Promise.all(config.entries.map(addMetadata));
52
- else await addMetadata(config);
53
-
54
- if (!config.root?.endsWith("/")) config.root = `${config.root ?? ""}/`;
72
+ config.entries = await Promise.all(config.entries.map(reviseConfig));
73
+ else config = await reviseConfig(config);
55
74
 
56
75
  return config;
57
76
  }
@@ -0,0 +1,28 @@
1
+ import type { ContentInjectionTarget } from "../types/ContentInjectionTarget";
2
+ import type { Context } from "../types/Context";
3
+ import type { Page } from "../types/Page";
4
+
5
+ export function getInjectedContent(
6
+ ctx: Context,
7
+ page: Page,
8
+ target: ContentInjectionTarget,
9
+ mode: "append" | undefined = "append",
10
+ ) {
11
+ let injectedContent = ctx[mode]?.[target];
12
+
13
+ if (!injectedContent) return "";
14
+
15
+ return (
16
+ Array.isArray(injectedContent) ? injectedContent : [injectedContent]
17
+ ).reduce((s, item) => {
18
+ if (item === undefined) return s;
19
+
20
+ if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
21
+
22
+ let { content, pages } = item;
23
+
24
+ if (!content || (pages && !pages.includes(page))) return s;
25
+
26
+ return `${s}${s ? "\n" : ""}${content}`;
27
+ }, "");
28
+ }
@@ -8,6 +8,7 @@ import { escapeHTML } from "../utils/escapeHTML";
8
8
  import { escapeRegExp } from "../utils/escapeRegExp";
9
9
  import { getCounterContent } from "./getCounterContent";
10
10
  import { getIcon } from "./getIcon";
11
+ import { getInjectedContent } from "./getInjectedContent";
11
12
  import { getNav } from "./getNav";
12
13
  import { getParsedContent } from "./getParsedContent";
13
14
  import { getRepoLink } from "./getRepoLink";
@@ -65,9 +66,11 @@ export async function setContent(ctx: Context) {
65
66
  <meta name="viewport" content="width=device-width">
66
67
  <meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
67
68
  ${iconTag}
69
+ ${getInjectedContent(ctx, "redirect", "head")}
68
70
  </head>
69
71
  <body>
70
72
  ${counterContent}
73
+ ${getInjectedContent(ctx, "redirect", "body")}
71
74
  <script>window.location.replace("${escapedRedirect}");</script>
72
75
  </body>
73
76
  </html>
@@ -112,6 +115,7 @@ ${counterContent}
112
115
  ${iconTag}
113
116
  ${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
114
117
  ${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
118
+ ${getInjectedContent(ctx, "section", "head")}
115
119
  </head>
116
120
  <body>
117
121
  <div class="layout">
@@ -150,6 +154,7 @@ ${
150
154
  : ""
151
155
  }
152
156
  ${counterContent}
157
+ ${getInjectedContent(ctx, "section", "body")}
153
158
  </body>
154
159
  </html>
155
160
  `),
@@ -170,6 +175,7 @@ ${counterContent}
170
175
  ${iconTag}
171
176
  <link rel="prefetch" href="${root}start">
172
177
  ${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
178
+ ${getInjectedContent(ctx, "index", "head")}
173
179
  </head>
174
180
  <body>
175
181
  <div class="layout">
@@ -217,6 +223,7 @@ ${
217
223
  : ""
218
224
  }
219
225
  ${counterContent}
226
+ ${getInjectedContent(ctx, "index", "body")}
220
227
  </body>
221
228
  </html>
222
229
  `),
@@ -234,6 +241,7 @@ ${counterContent}
234
241
  <link rel="stylesheet" href="${packageUrl}/dist/css/base.css">
235
242
  ${iconTag}
236
243
  <script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
244
+ ${getInjectedContent(ctx, "start", "head")}
237
245
  </head>
238
246
  <body>
239
247
  <div class="layout">
@@ -241,6 +249,7 @@ ${counterContent}
241
249
  </div>
242
250
 
243
251
  ${counterContent}
252
+ ${getInjectedContent(ctx, "start", "body")}
244
253
  </body>
245
254
  </html>
246
255
  `),
@@ -0,0 +1,7 @@
1
+ import { JSDOM } from "jsdom";
2
+
3
+ export function stripHTML(content: string) {
4
+ try {
5
+ return new JSDOM(content).window.document.body.textContent;
6
+ } catch {}
7
+ }
@@ -1,3 +1,3 @@
1
1
  export function toFileContent(x: string) {
2
- return `${x.trim()}\n`;
2
+ return `${x.replace(/\s+(<\/(head|body)>)/g, "\n$1").trim()}\n`;
3
3
  }
@@ -0,0 +1,14 @@
1
+ import type { ContentInjectionTarget } from "./ContentInjectionTarget";
2
+ import type { Page } from "./Page";
3
+
4
+ type InjectedContent =
5
+ | string
6
+ | undefined
7
+ | {
8
+ content?: string | undefined;
9
+ pages?: Page[];
10
+ };
11
+
12
+ export type ContentInjectionMap<T extends ContentInjectionTarget> = Partial<
13
+ Record<T, InjectedContent | InjectedContent[]>
14
+ >;
@@ -0,0 +1 @@
1
+ export type ContentInjectionTarget = "head" | "body";
@@ -1,3 +1,4 @@
1
+ import type { ContentInjectionMap } from "./ContentInjectionMap";
1
2
  import type { Theme } from "./Theme";
2
3
 
3
4
  export type EntryConfig = {
@@ -58,4 +59,5 @@ export type EntryConfig = {
58
59
  */
59
60
  jsorg?: boolean | string;
60
61
  ymid?: number | string;
62
+ append?: ContentInjectionMap<"head" | "body">;
61
63
  };
@@ -0,0 +1 @@
1
+ export type Page = "index" | "start" | "section" | "redirect";