@t8/docsgen 0.1.81 → 0.1.83
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 +65 -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 +32 -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,39 @@ 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
|
+
k0 = -1;
|
|
569
|
+
k1 = -1;
|
|
570
|
+
while ((k0 = s.indexOf(marker.hide.start, k1)) !== -1 && (k1 = s.indexOf(marker.hide.end, k0)) !== -1)
|
|
571
|
+
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)}`;
|
|
572
|
+
return s;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/bin/parsing/getParsedContent.ts
|
|
576
|
+
var md = new import_markdown_it.default({
|
|
577
|
+
html: true
|
|
578
|
+
});
|
|
525
579
|
async function getParsedContent(ctx) {
|
|
526
580
|
let { singlePage, linkMap } = ctx;
|
|
527
581
|
let rawContent = await fetchText(getLocation(ctx, "README.md", ctx.source));
|
|
528
|
-
let content = md.render(rawContent);
|
|
529
|
-
let dom = new
|
|
582
|
+
let content = md.render(preprocessContent(rawContent));
|
|
583
|
+
let dom = new import_jsdom4.JSDOM(content);
|
|
530
584
|
let { nav, linkMap: navLinkMap } = buildNav(ctx, dom);
|
|
531
585
|
let badges = [];
|
|
532
586
|
let title = "";
|
|
@@ -608,26 +662,6 @@ async function getParsedContent(ctx) {
|
|
|
608
662
|
};
|
|
609
663
|
}
|
|
610
664
|
|
|
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
665
|
// src/bin/toFileContent.ts
|
|
632
666
|
function toFileContent(x) {
|
|
633
667
|
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,32 @@
|
|
|
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
|
+
k0 = -1;
|
|
23
|
+
k1 = -1;
|
|
24
|
+
|
|
25
|
+
while (
|
|
26
|
+
(k0 = s.indexOf(marker.hide.start, k1)) !== -1 &&
|
|
27
|
+
(k1 = s.indexOf(marker.hide.end, k0)) !== -1
|
|
28
|
+
)
|
|
29
|
+
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)}`;
|
|
30
|
+
|
|
31
|
+
return s;
|
|
32
|
+
}
|
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
|
|