@t8/docsgen 0.1.81 → 0.1.82
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 +63 -31
- package/package.json +1 -1
- package/src/bin/parsing/buildNav.ts +71 -0
- package/src/bin/parsing/getInstallationCode.ts +6 -0
- package/src/bin/{getParsedContent.ts → parsing/getParsedContent.ts} +10 -117
- package/src/bin/parsing/getSectionPostprocess.ts +16 -0
- package/src/bin/parsing/joinLines.ts +3 -0
- package/src/bin/parsing/postprocessBadges.ts +19 -0
- package/src/bin/parsing/preprocessContent.ts +29 -0
- package/src/bin/setContent.ts +1 -1
package/dist/bin.js
CHANGED
|
@@ -421,8 +421,28 @@ ${navContent}
|
|
|
421
421
|
</nav>`;
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
// src/bin/
|
|
425
|
-
|
|
424
|
+
// src/bin/getTitle.ts
|
|
425
|
+
function getTitle(ctx, { cover, originalContent, withPackageURL } = {}) {
|
|
426
|
+
let { root, name, title: packageTitle, htmlTitle, scope } = ctx;
|
|
427
|
+
if (originalContent && ![name, packageTitle].includes(originalContent.trim()))
|
|
428
|
+
return originalContent;
|
|
429
|
+
if (cover && htmlTitle) return htmlTitle;
|
|
430
|
+
if (packageTitle) {
|
|
431
|
+
let escapedTitle = escapeHTML(packageTitle);
|
|
432
|
+
return withPackageURL ? `<a href="${root}" class="name">${escapedTitle}</a>` : `<span class="name">${escapedTitle}</span>`;
|
|
433
|
+
}
|
|
434
|
+
let scopeMatches = name?.match(/^(@[^/]+)\/?(.*)/);
|
|
435
|
+
if (!scope || !scopeMatches) {
|
|
436
|
+
let escapedName = escapeHTML(name);
|
|
437
|
+
return withPackageURL ? `<a href="${root}" class="name">${escapedName}</a>` : `<span class="name">${escapedName}</span>`;
|
|
438
|
+
}
|
|
439
|
+
let title = `<a href="${scope}" class="scope">${scopeMatches[1]}</a><span class="sep">/</span>`;
|
|
440
|
+
title += withPackageURL ? `<a href="${root}" class="name">${scopeMatches[2]}</a>` : `<span class="name">${scopeMatches[2]}</span>`;
|
|
441
|
+
return title;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/bin/parsing/getParsedContent.ts
|
|
445
|
+
var import_jsdom4 = require("jsdom");
|
|
426
446
|
var import_markdown_it = __toESM(require("markdown-it"));
|
|
427
447
|
|
|
428
448
|
// src/bin/getSlug.ts
|
|
@@ -436,13 +456,7 @@ function getSlug(title) {
|
|
|
436
456
|
return slug;
|
|
437
457
|
}
|
|
438
458
|
|
|
439
|
-
// src/bin/
|
|
440
|
-
var md = new import_markdown_it.default({
|
|
441
|
-
html: true
|
|
442
|
-
});
|
|
443
|
-
function joinLines(x) {
|
|
444
|
-
return x.join("\n").trim();
|
|
445
|
-
}
|
|
459
|
+
// src/bin/parsing/buildNav.ts
|
|
446
460
|
function buildNav(ctx, dom) {
|
|
447
461
|
let { root, contentDir, singlePage } = ctx;
|
|
448
462
|
let linkMap = {};
|
|
@@ -496,9 +510,13 @@ function buildNav(ctx, dom) {
|
|
|
496
510
|
linkMap
|
|
497
511
|
};
|
|
498
512
|
}
|
|
513
|
+
|
|
514
|
+
// src/bin/parsing/getInstallationCode.ts
|
|
499
515
|
function getInstallationCode(element) {
|
|
500
516
|
return element.querySelector("code")?.innerHTML.trim().match(/(\S\s*)?(npm (i|install) .*)/)?.[2];
|
|
501
517
|
}
|
|
518
|
+
|
|
519
|
+
// src/bin/parsing/getSectionPostprocess.ts
|
|
502
520
|
function getSectionPostprocess(linkMap) {
|
|
503
521
|
return (content) => {
|
|
504
522
|
let s = content;
|
|
@@ -510,6 +528,14 @@ function getSectionPostprocess(linkMap) {
|
|
|
510
528
|
return s;
|
|
511
529
|
};
|
|
512
530
|
}
|
|
531
|
+
|
|
532
|
+
// src/bin/parsing/joinLines.ts
|
|
533
|
+
function joinLines(x) {
|
|
534
|
+
return x.join("\n").trim();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/bin/parsing/postprocessBadges.ts
|
|
538
|
+
var import_jsdom3 = require("jsdom");
|
|
513
539
|
function postprocessBadges(content) {
|
|
514
540
|
let { document } = new import_jsdom3.JSDOM(content).window;
|
|
515
541
|
for (let img of document.querySelectorAll("img")) {
|
|
@@ -522,11 +548,37 @@ function postprocessBadges(content) {
|
|
|
522
548
|
}
|
|
523
549
|
return document.body.innerHTML;
|
|
524
550
|
}
|
|
551
|
+
|
|
552
|
+
// src/bin/parsing/preprocessContent.ts
|
|
553
|
+
var marker = {
|
|
554
|
+
show: {
|
|
555
|
+
start: "<!-- docsgen-show-start --",
|
|
556
|
+
end: "-- docsgen-show-end -->"
|
|
557
|
+
},
|
|
558
|
+
hide: {
|
|
559
|
+
start: "<!-- docsgen-hide-start -->",
|
|
560
|
+
end: "<!-- docsgen-hide-end -->"
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
function preprocessContent(s) {
|
|
564
|
+
let k0 = -1;
|
|
565
|
+
let k1 = -1;
|
|
566
|
+
while ((k0 = s.indexOf(marker.show.start, k1)) !== -1 && (k1 = s.indexOf(marker.show.end, k0)) !== -1)
|
|
567
|
+
s = `${s.slice(0, k0)}${s.slice(k0 + marker.show.start.length, k1)}${s.slice(k1 + marker.show.end.length)}`;
|
|
568
|
+
while ((k0 = s.indexOf(marker.hide.start, k1)) !== -1 && (k1 = s.indexOf(marker.hide.end, k0)) !== -1)
|
|
569
|
+
s = `${s.slice(0, k0 + marker.show.start.length - 1)}${s.slice(k0 + marker.show.start.length, k1)}${s.slice(k1 + marker.show.end.length + 2)}`;
|
|
570
|
+
return s;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/bin/parsing/getParsedContent.ts
|
|
574
|
+
var md = new import_markdown_it.default({
|
|
575
|
+
html: true
|
|
576
|
+
});
|
|
525
577
|
async function getParsedContent(ctx) {
|
|
526
578
|
let { singlePage, linkMap } = ctx;
|
|
527
579
|
let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
|
|
528
|
-
let content = md.render(rawContent);
|
|
529
|
-
let dom = new
|
|
580
|
+
let content = md.render(preprocessContent(rawContent));
|
|
581
|
+
let dom = new import_jsdom4.JSDOM(content);
|
|
530
582
|
let { nav, linkMap: navLinkMap } = buildNav(ctx, dom);
|
|
531
583
|
let badges = [];
|
|
532
584
|
let title = "";
|
|
@@ -608,26 +660,6 @@ async function getParsedContent(ctx) {
|
|
|
608
660
|
};
|
|
609
661
|
}
|
|
610
662
|
|
|
611
|
-
// src/bin/getTitle.ts
|
|
612
|
-
function getTitle(ctx, { cover, originalContent, withPackageURL } = {}) {
|
|
613
|
-
let { root, name, title: packageTitle, htmlTitle, scope } = ctx;
|
|
614
|
-
if (originalContent && ![name, packageTitle].includes(originalContent.trim()))
|
|
615
|
-
return originalContent;
|
|
616
|
-
if (cover && htmlTitle) return htmlTitle;
|
|
617
|
-
if (packageTitle) {
|
|
618
|
-
let escapedTitle = escapeHTML(packageTitle);
|
|
619
|
-
return withPackageURL ? `<a href="${root}" class="name">${escapedTitle}</a>` : `<span class="name">${escapedTitle}</span>`;
|
|
620
|
-
}
|
|
621
|
-
let scopeMatches = name?.match(/^(@[^/]+)\/?(.*)/);
|
|
622
|
-
if (!scope || !scopeMatches) {
|
|
623
|
-
let escapedName = escapeHTML(name);
|
|
624
|
-
return withPackageURL ? `<a href="${root}" class="name">${escapedName}</a>` : `<span class="name">${escapedName}</span>`;
|
|
625
|
-
}
|
|
626
|
-
let title = `<a href="${scope}" class="scope">${scopeMatches[1]}</a><span class="sep">/</span>`;
|
|
627
|
-
title += withPackageURL ? `<a href="${root}" class="name">${scopeMatches[2]}</a>` : `<span class="name">${scopeMatches[2]}</span>`;
|
|
628
|
-
return title;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
663
|
// src/bin/toFileContent.ts
|
|
632
664
|
function toFileContent(x) {
|
|
633
665
|
let s = x.replace(
|
package/package.json
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { JSDOM } from "jsdom";
|
|
2
|
+
import type { Context } from "../../types/Context";
|
|
3
|
+
import type { NavItem } from "../../types/NavItem";
|
|
4
|
+
import { getSlug } from "../getSlug";
|
|
5
|
+
|
|
6
|
+
export function buildNav(ctx: Context, dom: JSDOM) {
|
|
7
|
+
let { root, contentDir, singlePage } = ctx;
|
|
8
|
+
let linkMap: Record<string, string> = {};
|
|
9
|
+
|
|
10
|
+
let navItem: NavItem | null = null;
|
|
11
|
+
let nav: NavItem[] = [];
|
|
12
|
+
|
|
13
|
+
if (singlePage)
|
|
14
|
+
navItem = {
|
|
15
|
+
id: "Overview",
|
|
16
|
+
title: "Overview",
|
|
17
|
+
items: [],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
let headings =
|
|
21
|
+
dom.window.document.body.querySelectorAll("h2, h3, h4, h5, h6");
|
|
22
|
+
|
|
23
|
+
for (let element of headings) {
|
|
24
|
+
let tagName = element.tagName.toLowerCase();
|
|
25
|
+
|
|
26
|
+
let isSectionTitle = tagName === "h2";
|
|
27
|
+
let isSubsectionTitle = tagName === "h3";
|
|
28
|
+
let slug = getSlug(element.textContent);
|
|
29
|
+
|
|
30
|
+
let sectionId = isSectionTitle ? slug : (navItem?.id ?? "");
|
|
31
|
+
let link = `${root}${contentDir}/${sectionId}`;
|
|
32
|
+
|
|
33
|
+
let elementId = element.id || slug.toLowerCase().replace(/_/g, "-");
|
|
34
|
+
|
|
35
|
+
if (elementId)
|
|
36
|
+
linkMap[`#${elementId}`] = `${link}${isSectionTitle ? "" : `#${slug}`}`;
|
|
37
|
+
|
|
38
|
+
if (singlePage && isSectionTitle) {
|
|
39
|
+
if (navItem) {
|
|
40
|
+
element.id = slug;
|
|
41
|
+
navItem.items.push({
|
|
42
|
+
id: slug,
|
|
43
|
+
title: element.innerHTML.trim(),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
} else if (isSectionTitle) {
|
|
47
|
+
if (navItem) nav.push(navItem);
|
|
48
|
+
|
|
49
|
+
navItem = {
|
|
50
|
+
id: slug,
|
|
51
|
+
title: element.innerHTML.trim(),
|
|
52
|
+
items: [],
|
|
53
|
+
};
|
|
54
|
+
} else if (isSubsectionTitle) {
|
|
55
|
+
if (navItem) {
|
|
56
|
+
element.id = slug;
|
|
57
|
+
navItem.items.push({
|
|
58
|
+
id: slug,
|
|
59
|
+
title: element.innerHTML.trim(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (navItem) nav.push(navItem);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
nav,
|
|
69
|
+
linkMap,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -1,130 +1,23 @@
|
|
|
1
1
|
import { JSDOM } from "jsdom";
|
|
2
2
|
import Markdown from "markdown-it";
|
|
3
|
-
import type { Context } from "
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import type { Context } from "../../types/Context";
|
|
4
|
+
import { fetchText } from "../fetchText";
|
|
5
|
+
import { getLocation } from "../getLocation";
|
|
6
|
+
import { buildNav } from "./buildNav";
|
|
7
|
+
import { getInstallationCode } from "./getInstallationCode";
|
|
8
|
+
import { getSectionPostprocess } from "./getSectionPostprocess";
|
|
9
|
+
import { joinLines } from "./joinLines";
|
|
10
|
+
import { postprocessBadges } from "./postprocessBadges";
|
|
11
|
+
import { preprocessContent } from "./preprocessContent";
|
|
8
12
|
|
|
9
13
|
const md = new Markdown({
|
|
10
14
|
html: true,
|
|
11
15
|
});
|
|
12
16
|
|
|
13
|
-
function joinLines(x: string[]) {
|
|
14
|
-
return x.join("\n").trim();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function buildNav(ctx: Context, dom: JSDOM) {
|
|
18
|
-
let { root, contentDir, singlePage } = ctx;
|
|
19
|
-
let linkMap: Record<string, string> = {};
|
|
20
|
-
|
|
21
|
-
let navItem: NavItem | null = null;
|
|
22
|
-
let nav: NavItem[] = [];
|
|
23
|
-
|
|
24
|
-
if (singlePage)
|
|
25
|
-
navItem = {
|
|
26
|
-
id: "Overview",
|
|
27
|
-
title: "Overview",
|
|
28
|
-
items: [],
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
let headings =
|
|
32
|
-
dom.window.document.body.querySelectorAll("h2, h3, h4, h5, h6");
|
|
33
|
-
|
|
34
|
-
for (let element of headings) {
|
|
35
|
-
let tagName = element.tagName.toLowerCase();
|
|
36
|
-
|
|
37
|
-
let isSectionTitle = tagName === "h2";
|
|
38
|
-
let isSubsectionTitle = tagName === "h3";
|
|
39
|
-
let slug = getSlug(element.textContent);
|
|
40
|
-
|
|
41
|
-
let sectionId = isSectionTitle ? slug : (navItem?.id ?? "");
|
|
42
|
-
let link = `${root}${contentDir}/${sectionId}`;
|
|
43
|
-
|
|
44
|
-
let elementId = element.id || slug.toLowerCase().replace(/_/g, "-");
|
|
45
|
-
|
|
46
|
-
if (elementId)
|
|
47
|
-
linkMap[`#${elementId}`] = `${link}${isSectionTitle ? "" : `#${slug}`}`;
|
|
48
|
-
|
|
49
|
-
if (singlePage && isSectionTitle) {
|
|
50
|
-
if (navItem) {
|
|
51
|
-
element.id = slug;
|
|
52
|
-
navItem.items.push({
|
|
53
|
-
id: slug,
|
|
54
|
-
title: element.innerHTML.trim(),
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
} else if (isSectionTitle) {
|
|
58
|
-
if (navItem) nav.push(navItem);
|
|
59
|
-
|
|
60
|
-
navItem = {
|
|
61
|
-
id: slug,
|
|
62
|
-
title: element.innerHTML.trim(),
|
|
63
|
-
items: [],
|
|
64
|
-
};
|
|
65
|
-
} else if (isSubsectionTitle) {
|
|
66
|
-
if (navItem) {
|
|
67
|
-
element.id = slug;
|
|
68
|
-
navItem.items.push({
|
|
69
|
-
id: slug,
|
|
70
|
-
title: element.innerHTML.trim(),
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (navItem) nav.push(navItem);
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
nav,
|
|
80
|
-
linkMap,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function getInstallationCode(element: Element) {
|
|
85
|
-
return element
|
|
86
|
-
.querySelector("code")
|
|
87
|
-
?.innerHTML.trim()
|
|
88
|
-
.match(/(\S\s*)?(npm (i|install) .*)/)?.[2];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function getSectionPostprocess(linkMap: Record<string, string | undefined>) {
|
|
92
|
-
return (content: string) => {
|
|
93
|
-
let s = content;
|
|
94
|
-
|
|
95
|
-
s = s.replace(/<a href="([^"]+)">/g, (_, url) => {
|
|
96
|
-
let nextURL = linkMap[url] ?? url;
|
|
97
|
-
let attrs = /^(https?:)?\/\//.test(nextURL) ? ' target="_blank"' : "";
|
|
98
|
-
|
|
99
|
-
return `<a href="${nextURL}"${attrs}>`;
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return s;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function postprocessBadges(content: string) {
|
|
107
|
-
let { document } = new JSDOM(content).window;
|
|
108
|
-
|
|
109
|
-
for (let img of document.querySelectorAll("img")) {
|
|
110
|
-
let parent = img.parentElement;
|
|
111
|
-
|
|
112
|
-
if (!parent) continue;
|
|
113
|
-
|
|
114
|
-
let container = document.createElement("span");
|
|
115
|
-
container.className = "badge";
|
|
116
|
-
|
|
117
|
-
parent.insertBefore(container, img);
|
|
118
|
-
container.append(img);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return document.body.innerHTML;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
17
|
export async function getParsedContent(ctx: Context) {
|
|
125
18
|
let { singlePage, linkMap } = ctx;
|
|
126
19
|
let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
|
|
127
|
-
let content = md.render(rawContent);
|
|
20
|
+
let content = md.render(preprocessContent(rawContent));
|
|
128
21
|
let dom = new JSDOM(content);
|
|
129
22
|
|
|
130
23
|
let { nav, linkMap: navLinkMap } = buildNav(ctx, dom);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function getSectionPostprocess(
|
|
2
|
+
linkMap: Record<string, string | undefined>,
|
|
3
|
+
) {
|
|
4
|
+
return (content: string) => {
|
|
5
|
+
let s = content;
|
|
6
|
+
|
|
7
|
+
s = s.replace(/<a href="([^"]+)">/g, (_, url) => {
|
|
8
|
+
let nextURL = linkMap[url] ?? url;
|
|
9
|
+
let attrs = /^(https?:)?\/\//.test(nextURL) ? ' target="_blank"' : "";
|
|
10
|
+
|
|
11
|
+
return `<a href="${nextURL}"${attrs}>`;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return s;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { JSDOM } from "jsdom";
|
|
2
|
+
|
|
3
|
+
export function postprocessBadges(content: string) {
|
|
4
|
+
let { document } = new JSDOM(content).window;
|
|
5
|
+
|
|
6
|
+
for (let img of document.querySelectorAll("img")) {
|
|
7
|
+
let parent = img.parentElement;
|
|
8
|
+
|
|
9
|
+
if (!parent) continue;
|
|
10
|
+
|
|
11
|
+
let container = document.createElement("span");
|
|
12
|
+
container.className = "badge";
|
|
13
|
+
|
|
14
|
+
parent.insertBefore(container, img);
|
|
15
|
+
container.append(img);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return document.body.innerHTML;
|
|
19
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const marker = {
|
|
2
|
+
show: {
|
|
3
|
+
start: "<!-- docsgen-show-start --",
|
|
4
|
+
end: "-- docsgen-show-end -->",
|
|
5
|
+
},
|
|
6
|
+
hide: {
|
|
7
|
+
start: "<!-- docsgen-hide-start -->",
|
|
8
|
+
end: "<!-- docsgen-hide-end -->",
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function preprocessContent(s: string) {
|
|
13
|
+
let k0 = -1;
|
|
14
|
+
let k1 = -1;
|
|
15
|
+
|
|
16
|
+
while (
|
|
17
|
+
(k0 = s.indexOf(marker.show.start, k1)) !== -1 &&
|
|
18
|
+
(k1 = s.indexOf(marker.show.end, k0)) !== -1
|
|
19
|
+
)
|
|
20
|
+
s = `${s.slice(0, k0)}${s.slice(k0 + marker.show.start.length, k1)}${s.slice(k1 + marker.show.end.length)}`;
|
|
21
|
+
|
|
22
|
+
while (
|
|
23
|
+
(k0 = s.indexOf(marker.hide.start, k1)) !== -1 &&
|
|
24
|
+
(k1 = s.indexOf(marker.hide.end, k0)) !== -1
|
|
25
|
+
)
|
|
26
|
+
s = `${s.slice(0, k0 + marker.show.start.length - 1)}${s.slice(k0 + marker.show.start.length, k1)}${s.slice(k1 + marker.show.end.length + 2)}`;
|
|
27
|
+
|
|
28
|
+
return s;
|
|
29
|
+
}
|
package/src/bin/setContent.ts
CHANGED
|
@@ -10,9 +10,9 @@ import { getCounterContent } from "./getCounterContent";
|
|
|
10
10
|
import { getIcon } from "./getIcon";
|
|
11
11
|
import { getInjectedContent } from "./getInjectedContent";
|
|
12
12
|
import { getNav } from "./getNav";
|
|
13
|
-
import { getParsedContent } from "./getParsedContent";
|
|
14
13
|
import { getRepoLink } from "./getRepoLink";
|
|
15
14
|
import { getTitle } from "./getTitle";
|
|
15
|
+
import { getParsedContent } from "./parsing/getParsedContent";
|
|
16
16
|
import { stripHTML } from "./stripHTML";
|
|
17
17
|
import { toFileContent } from "./toFileContent";
|
|
18
18
|
|