@t8/docsgen 0.4.18 → 0.4.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 +40 -35
- package/dist/css/section.css +23 -24
- package/package.json +1 -1
- package/src/bin/content/getSectionContent.ts +7 -20
- package/src/bin/parsing/getSectionPostprocess.ts +44 -7
- package/src/css/section.css +23 -24
package/dist/bin.js
CHANGED
|
@@ -349,7 +349,7 @@ async function getRepoMetadata({
|
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
// src/bin/parsing/getParsedContent.ts
|
|
352
|
-
import { JSDOM as
|
|
352
|
+
import { JSDOM as JSDOM3 } from "jsdom";
|
|
353
353
|
import Markdown from "markdown-it";
|
|
354
354
|
|
|
355
355
|
// src/bin/getSlug.ts
|
|
@@ -424,15 +424,40 @@ function getInstallationCode(element) {
|
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
// src/bin/parsing/getSectionPostprocess.ts
|
|
427
|
+
import { JSDOM as JSDOM2 } from "jsdom";
|
|
428
|
+
function isPreviewURL(url) {
|
|
429
|
+
return url.startsWith("https://codesandbox.io/p/sandbox/");
|
|
430
|
+
}
|
|
431
|
+
function getPreviewContent(url, title) {
|
|
432
|
+
let { pathname, searchParams } = new URL(url);
|
|
433
|
+
let sandboxId = pathname.split("/").at(-1);
|
|
434
|
+
let file = searchParams.get("file");
|
|
435
|
+
let previewURL = new URL(`https://codesandbox.io/embed/${sandboxId}`);
|
|
436
|
+
let previewContent = title ? `<legend>${title}</legend>` : "";
|
|
437
|
+
previewURL.searchParams.set("view", "preview");
|
|
438
|
+
if (file) previewURL.searchParams.set("module", file);
|
|
439
|
+
previewContent += `<iframe src="${previewURL.href}"${title ? ` title="${title}"` : ""} sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" loading="lazy"></iframe>`;
|
|
440
|
+
return previewContent;
|
|
441
|
+
}
|
|
427
442
|
function getSectionPostprocess(linkMap) {
|
|
428
443
|
return (content) => {
|
|
429
|
-
let
|
|
430
|
-
|
|
431
|
-
let
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
444
|
+
let { document } = new JSDOM2(content).window;
|
|
445
|
+
for (let a of document.querySelectorAll("a")) {
|
|
446
|
+
let href = a.getAttribute("href");
|
|
447
|
+
if (href === null) continue;
|
|
448
|
+
if (isPreviewURL(href) && a.parentElement) {
|
|
449
|
+
let preview = document.createElement("fieldset");
|
|
450
|
+
preview.innerHTML = getPreviewContent(href, a.innerHTML);
|
|
451
|
+
a.parentElement.insertBefore(preview, a);
|
|
452
|
+
a.remove();
|
|
453
|
+
} else {
|
|
454
|
+
let nextHref = linkMap[href] ?? href;
|
|
455
|
+
a.setAttribute("href", nextHref);
|
|
456
|
+
if (/^(https?:)?\/\//.test(nextHref))
|
|
457
|
+
a.setAttribute("target", "_blank");
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return document.body.innerHTML;
|
|
436
461
|
};
|
|
437
462
|
}
|
|
438
463
|
|
|
@@ -485,7 +510,7 @@ async function getParsedContent(ctx) {
|
|
|
485
510
|
let { singlePage, firstLineDescription, linkMap } = ctx;
|
|
486
511
|
let rawContent = await fetchContent(contentLocation);
|
|
487
512
|
let content = md.render(preprocessContent(rawContent));
|
|
488
|
-
let dom = new
|
|
513
|
+
let dom = new JSDOM3(content);
|
|
489
514
|
let { nav, linkMap: navLinkMap } = buildNav(ctx, dom);
|
|
490
515
|
let badges = "";
|
|
491
516
|
let title = "";
|
|
@@ -801,17 +826,8 @@ function escapeRegExp(s) {
|
|
|
801
826
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
802
827
|
}
|
|
803
828
|
|
|
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
|
-
|
|
813
829
|
// src/bin/content/getNav.ts
|
|
814
|
-
import { JSDOM as
|
|
830
|
+
import { JSDOM as JSDOM4 } from "jsdom";
|
|
815
831
|
|
|
816
832
|
// src/bin/getNpmLink.ts
|
|
817
833
|
function getNpmLink({ npm }, className) {
|
|
@@ -825,7 +841,7 @@ async function getNav(ctx, navItems) {
|
|
|
825
841
|
let navContent = await fetchContent(nav);
|
|
826
842
|
let s = "";
|
|
827
843
|
if (navContent) {
|
|
828
|
-
let navDom = new
|
|
844
|
+
let navDom = new JSDOM4(navContent).window.document.body;
|
|
829
845
|
for (let link of navDom.querySelectorAll("a")) {
|
|
830
846
|
if (link.dataset.name === name) {
|
|
831
847
|
let parent = link.parentElement;
|
|
@@ -896,12 +912,10 @@ ${navContent}
|
|
|
896
912
|
// src/bin/content/getSectionContent.ts
|
|
897
913
|
async function getSectionContent(ctx, index) {
|
|
898
914
|
let { root, contentDir = "" } = ctx;
|
|
899
|
-
let descriptionContent = escapeHTML(tweakTypography(ctx.description));
|
|
900
|
-
let cssRoot = await getCSSRoot(ctx, "content");
|
|
901
915
|
let { sections, nav } = await getParsedContent(ctx);
|
|
916
|
+
let cssRoot = await getCSSRoot(ctx, "content");
|
|
902
917
|
let content = sections[index];
|
|
903
918
|
let navContent = await getNav(ctx, nav);
|
|
904
|
-
let mainTitle = await getMainTitle(ctx);
|
|
905
919
|
let plainTitle = await getPlainTitle(ctx);
|
|
906
920
|
return toFileContent(`
|
|
907
921
|
<!DOCTYPE html>
|
|
@@ -922,11 +936,9 @@ async function getSectionContent(ctx, index) {
|
|
|
922
936
|
<body>
|
|
923
937
|
${getInjectedContent(ctx, "section", "body", "prepend")}
|
|
924
938
|
<div class="layout">
|
|
925
|
-
<header class="compact">
|
|
926
|
-
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
927
|
-
</header>
|
|
928
939
|
<div class="${navContent ? "" : "no-nav "}body">
|
|
929
940
|
<main>
|
|
941
|
+
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
930
942
|
${content}
|
|
931
943
|
|
|
932
944
|
<p class="pagenav">
|
|
@@ -935,22 +947,15 @@ ${content}
|
|
|
935
947
|
${nav[index + 1]?.id ? `<span class="next"><a href="${root}${contentDir}/${nav[index + 1]?.id}">${nav[index + 1]?.title}</a> <span class="icon">\u2192</span></span>` : `<span class="repo">${getRepoLink(ctx)}</span>`}
|
|
936
948
|
</p>
|
|
937
949
|
</main>
|
|
938
|
-
|
|
950
|
+
${navContent && `<hr>
|
|
939
951
|
<aside class="aux">
|
|
940
|
-
<div class="header" hidden>
|
|
941
|
-
<h1>${mainTitle}</h1>
|
|
942
|
-
<div class="description">
|
|
943
|
-
<p>${descriptionContent}</p>
|
|
944
|
-
<p class="installation">${await getInstallationContent(ctx)}</p>
|
|
945
|
-
</div>
|
|
946
|
-
</div>
|
|
947
952
|
${navContent.replace(
|
|
948
953
|
new RegExp(
|
|
949
954
|
`(<li data-id="${escapeRegExp(nav[index]?.id)}">)<a href="[^"]+">([^<]+)</a>`
|
|
950
955
|
),
|
|
951
956
|
"$1<strong>$2</strong>"
|
|
952
957
|
)}
|
|
953
|
-
</aside
|
|
958
|
+
</aside>`}
|
|
954
959
|
</div>
|
|
955
960
|
</div>
|
|
956
961
|
|
package/dist/css/section.css
CHANGED
|
@@ -80,29 +80,10 @@ aside {
|
|
|
80
80
|
var(--aux-background-end)
|
|
81
81
|
);
|
|
82
82
|
border-right: 0.05em solid var(--aux-border-color);
|
|
83
|
-
padding:
|
|
83
|
+
padding: 0 var(--content-padding-x);
|
|
84
84
|
margin: 0;
|
|
85
85
|
box-sizing: border-box;
|
|
86
86
|
}
|
|
87
|
-
aside > .header {
|
|
88
|
-
display: block;
|
|
89
|
-
margin: 0.5rem 0 0.25rem;
|
|
90
|
-
}
|
|
91
|
-
aside > .header .description p:not(.installation) {
|
|
92
|
-
font-size: 0.9em;
|
|
93
|
-
margin: 0.35em 0 0;
|
|
94
|
-
}
|
|
95
|
-
aside > .header .description p.installation {
|
|
96
|
-
margin: 1em 0 0;
|
|
97
|
-
}
|
|
98
|
-
aside > .header .installation code {
|
|
99
|
-
display: inline-block;
|
|
100
|
-
background: transparent;
|
|
101
|
-
border: 0.05em solid;
|
|
102
|
-
border-radius: 0.5em;
|
|
103
|
-
padding: 0.35em 0.75em;
|
|
104
|
-
margin: 0;
|
|
105
|
-
}
|
|
106
87
|
aside h1 {
|
|
107
88
|
font-size: 1.3rem;
|
|
108
89
|
margin: 0;
|
|
@@ -113,7 +94,7 @@ aside nav {
|
|
|
113
94
|
aside section {
|
|
114
95
|
width: 100%;
|
|
115
96
|
max-width: 16em;
|
|
116
|
-
padding:
|
|
97
|
+
padding: var(--content-padding-y) 0;
|
|
117
98
|
box-sizing: border-box;
|
|
118
99
|
}
|
|
119
100
|
aside section + section {
|
|
@@ -179,9 +160,6 @@ aside li > strong {
|
|
|
179
160
|
padding: 0.25rem var(--content-padding-x) 0.35rem;
|
|
180
161
|
margin: 0;
|
|
181
162
|
}
|
|
182
|
-
aside > .header {
|
|
183
|
-
display: none;
|
|
184
|
-
}
|
|
185
163
|
aside nav {
|
|
186
164
|
font-size: inherit;
|
|
187
165
|
}
|
|
@@ -246,6 +224,13 @@ main h1 {
|
|
|
246
224
|
color: var(--secondary-color);
|
|
247
225
|
margin: 0;
|
|
248
226
|
}
|
|
227
|
+
main h1 a,
|
|
228
|
+
main h1 a:link,
|
|
229
|
+
main h1 a:visited,
|
|
230
|
+
main h1 a:hover,
|
|
231
|
+
main h1 a:active {
|
|
232
|
+
--color: var(--secondary-color);
|
|
233
|
+
}
|
|
249
234
|
h1 .sep {
|
|
250
235
|
margin: 0 0.1em;
|
|
251
236
|
}
|
|
@@ -265,6 +250,20 @@ main h2 {
|
|
|
265
250
|
main h2:first-child {
|
|
266
251
|
margin-top: 0;
|
|
267
252
|
}
|
|
253
|
+
main fieldset {
|
|
254
|
+
border: 0.05em solid var(--secondary-color);
|
|
255
|
+
}
|
|
256
|
+
main fieldset legend {
|
|
257
|
+
font-size: 0.8em;
|
|
258
|
+
color: var(--secondary-color);
|
|
259
|
+
}
|
|
260
|
+
main fieldset iframe {
|
|
261
|
+
width: 100%;
|
|
262
|
+
height: 360px;
|
|
263
|
+
background: var(--code-block-background);
|
|
264
|
+
border: none;
|
|
265
|
+
overflow: hidden;
|
|
266
|
+
}
|
|
268
267
|
|
|
269
268
|
.pagenav {
|
|
270
269
|
--icon-width: 1.25em;
|
package/package.json
CHANGED
|
@@ -9,24 +9,17 @@ import { getCSSRoot } from "./getCSSRoot.ts";
|
|
|
9
9
|
import { getDefaultCodeStyleContent } from "./getDefaultCodeStyleContent.ts";
|
|
10
10
|
import { getIconTag } from "./getIconTag.ts";
|
|
11
11
|
import { getInjectedContent } from "./getInjectedContent.ts";
|
|
12
|
-
import { getInstallationContent } from "./getInstallationContent.ts";
|
|
13
|
-
import { getMainTitle } from "./getMainTitle.ts";
|
|
14
12
|
import { getNav } from "./getNav.ts";
|
|
15
13
|
import { getPlainTitle } from "./getPlainTitle.ts";
|
|
16
14
|
import { toFileContent } from "./toFileContent.ts";
|
|
17
|
-
import { tweakTypography } from "./tweakTypography.ts";
|
|
18
15
|
|
|
19
16
|
export async function getSectionContent(ctx: Context, index: number) {
|
|
20
17
|
let { root, contentDir = "" } = ctx;
|
|
21
|
-
let descriptionContent = escapeHTML(tweakTypography(ctx.description));
|
|
22
|
-
|
|
23
|
-
let cssRoot = await getCSSRoot(ctx, "content");
|
|
24
18
|
let { sections, nav } = await getParsedContent(ctx);
|
|
19
|
+
let cssRoot = await getCSSRoot(ctx, "content");
|
|
25
20
|
|
|
26
21
|
let content = sections[index];
|
|
27
22
|
let navContent = await getNav(ctx, nav);
|
|
28
|
-
|
|
29
|
-
let mainTitle = await getMainTitle(ctx);
|
|
30
23
|
let plainTitle = await getPlainTitle(ctx);
|
|
31
24
|
|
|
32
25
|
return toFileContent(`
|
|
@@ -48,11 +41,9 @@ export async function getSectionContent(ctx: Context, index: number) {
|
|
|
48
41
|
<body>
|
|
49
42
|
${getInjectedContent(ctx, "section", "body", "prepend")}
|
|
50
43
|
<div class="layout">
|
|
51
|
-
<header class="compact">
|
|
52
|
-
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
53
|
-
</header>
|
|
54
44
|
<div class="${navContent ? "" : "no-nav "}body">
|
|
55
45
|
<main>
|
|
46
|
+
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
56
47
|
${content}
|
|
57
48
|
|
|
58
49
|
<p class="pagenav">
|
|
@@ -60,22 +51,18 @@ ${content}
|
|
|
60
51
|
${nav[index + 1]?.id ? `<span class="next"><a href="${root}${contentDir}/${nav[index + 1]?.id}">${nav[index + 1]?.title}</a> <span class="icon">→</span></span>` : `<span class="repo">${getRepoLink(ctx)}</span>`}
|
|
61
52
|
</p>
|
|
62
53
|
</main>
|
|
63
|
-
|
|
54
|
+
${
|
|
55
|
+
navContent &&
|
|
56
|
+
`<hr>
|
|
64
57
|
<aside class="aux">
|
|
65
|
-
<div class="header" hidden>
|
|
66
|
-
<h1>${mainTitle}</h1>
|
|
67
|
-
<div class="description">
|
|
68
|
-
<p>${descriptionContent}</p>
|
|
69
|
-
<p class="installation">${await getInstallationContent(ctx)}</p>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
58
|
${navContent.replace(
|
|
73
59
|
new RegExp(
|
|
74
60
|
`(<li data-id="${escapeRegExp(nav[index]?.id)}">)<a href="[^"]+">([^<]+)</a>`,
|
|
75
61
|
),
|
|
76
62
|
"$1<strong>$2</strong>",
|
|
77
63
|
)}
|
|
78
|
-
</aside
|
|
64
|
+
</aside>`
|
|
65
|
+
}
|
|
79
66
|
</div>
|
|
80
67
|
</div>
|
|
81
68
|
|
|
@@ -1,16 +1,53 @@
|
|
|
1
|
+
import { JSDOM } from "jsdom";
|
|
2
|
+
|
|
3
|
+
function isPreviewURL(url: string) {
|
|
4
|
+
return url.startsWith("https://codesandbox.io/p/sandbox/");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getPreviewContent(url: string, title?: string) {
|
|
8
|
+
let { pathname, searchParams } = new URL(url);
|
|
9
|
+
let sandboxId = pathname.split("/").at(-1);
|
|
10
|
+
let file = searchParams.get("file");
|
|
11
|
+
|
|
12
|
+
let previewURL = new URL(`https://codesandbox.io/embed/${sandboxId}`);
|
|
13
|
+
let previewContent = title ? `<legend>${title}</legend>` : "";
|
|
14
|
+
|
|
15
|
+
previewURL.searchParams.set("view", "preview");
|
|
16
|
+
|
|
17
|
+
if (file) previewURL.searchParams.set("module", file);
|
|
18
|
+
|
|
19
|
+
previewContent += `<iframe src="${previewURL.href}"${title ? ` title="${title}"` : ""} sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" loading="lazy"></iframe>`;
|
|
20
|
+
|
|
21
|
+
return previewContent;
|
|
22
|
+
}
|
|
23
|
+
|
|
1
24
|
export function getSectionPostprocess(
|
|
2
25
|
linkMap: Record<string, string | undefined>,
|
|
3
26
|
) {
|
|
4
27
|
return (content: string) => {
|
|
5
|
-
let
|
|
28
|
+
let { document } = new JSDOM(content).window;
|
|
29
|
+
|
|
30
|
+
for (let a of document.querySelectorAll("a")) {
|
|
31
|
+
let href = a.getAttribute("href");
|
|
32
|
+
|
|
33
|
+
if (href === null) continue;
|
|
34
|
+
|
|
35
|
+
if (isPreviewURL(href) && a.parentElement) {
|
|
36
|
+
let preview = document.createElement("fieldset");
|
|
37
|
+
|
|
38
|
+
preview.innerHTML = getPreviewContent(href, a.innerHTML);
|
|
6
39
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
40
|
+
a.parentElement.insertBefore(preview, a);
|
|
41
|
+
a.remove();
|
|
42
|
+
} else {
|
|
43
|
+
let nextHref = linkMap[href] ?? href;
|
|
10
44
|
|
|
11
|
-
|
|
12
|
-
|
|
45
|
+
a.setAttribute("href", nextHref);
|
|
46
|
+
if (/^(https?:)?\/\//.test(nextHref))
|
|
47
|
+
a.setAttribute("target", "_blank");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
13
50
|
|
|
14
|
-
return
|
|
51
|
+
return document.body.innerHTML;
|
|
15
52
|
};
|
|
16
53
|
}
|
package/src/css/section.css
CHANGED
|
@@ -80,29 +80,10 @@ aside {
|
|
|
80
80
|
var(--aux-background-end)
|
|
81
81
|
);
|
|
82
82
|
border-right: 0.05em solid var(--aux-border-color);
|
|
83
|
-
padding:
|
|
83
|
+
padding: 0 var(--content-padding-x);
|
|
84
84
|
margin: 0;
|
|
85
85
|
box-sizing: border-box;
|
|
86
86
|
}
|
|
87
|
-
aside > .header {
|
|
88
|
-
display: block;
|
|
89
|
-
margin: 0.5rem 0 0.25rem;
|
|
90
|
-
}
|
|
91
|
-
aside > .header .description p:not(.installation) {
|
|
92
|
-
font-size: 0.9em;
|
|
93
|
-
margin: 0.35em 0 0;
|
|
94
|
-
}
|
|
95
|
-
aside > .header .description p.installation {
|
|
96
|
-
margin: 1em 0 0;
|
|
97
|
-
}
|
|
98
|
-
aside > .header .installation code {
|
|
99
|
-
display: inline-block;
|
|
100
|
-
background: transparent;
|
|
101
|
-
border: 0.05em solid;
|
|
102
|
-
border-radius: 0.5em;
|
|
103
|
-
padding: 0.35em 0.75em;
|
|
104
|
-
margin: 0;
|
|
105
|
-
}
|
|
106
87
|
aside h1 {
|
|
107
88
|
font-size: 1.3rem;
|
|
108
89
|
margin: 0;
|
|
@@ -113,7 +94,7 @@ aside nav {
|
|
|
113
94
|
aside section {
|
|
114
95
|
width: 100%;
|
|
115
96
|
max-width: 16em;
|
|
116
|
-
padding:
|
|
97
|
+
padding: var(--content-padding-y) 0;
|
|
117
98
|
box-sizing: border-box;
|
|
118
99
|
}
|
|
119
100
|
aside section + section {
|
|
@@ -179,9 +160,6 @@ aside li > strong {
|
|
|
179
160
|
padding: 0.25rem var(--content-padding-x) 0.35rem;
|
|
180
161
|
margin: 0;
|
|
181
162
|
}
|
|
182
|
-
aside > .header {
|
|
183
|
-
display: none;
|
|
184
|
-
}
|
|
185
163
|
aside nav {
|
|
186
164
|
font-size: inherit;
|
|
187
165
|
}
|
|
@@ -246,6 +224,13 @@ main h1 {
|
|
|
246
224
|
color: var(--secondary-color);
|
|
247
225
|
margin: 0;
|
|
248
226
|
}
|
|
227
|
+
main h1 a,
|
|
228
|
+
main h1 a:link,
|
|
229
|
+
main h1 a:visited,
|
|
230
|
+
main h1 a:hover,
|
|
231
|
+
main h1 a:active {
|
|
232
|
+
--color: var(--secondary-color);
|
|
233
|
+
}
|
|
249
234
|
h1 .sep {
|
|
250
235
|
margin: 0 0.1em;
|
|
251
236
|
}
|
|
@@ -265,6 +250,20 @@ main h2 {
|
|
|
265
250
|
main h2:first-child {
|
|
266
251
|
margin-top: 0;
|
|
267
252
|
}
|
|
253
|
+
main fieldset {
|
|
254
|
+
border: 0.05em solid var(--secondary-color);
|
|
255
|
+
}
|
|
256
|
+
main fieldset legend {
|
|
257
|
+
font-size: 0.8em;
|
|
258
|
+
color: var(--secondary-color);
|
|
259
|
+
}
|
|
260
|
+
main fieldset iframe {
|
|
261
|
+
width: 100%;
|
|
262
|
+
height: 360px;
|
|
263
|
+
background: var(--code-block-background);
|
|
264
|
+
border: none;
|
|
265
|
+
overflow: hidden;
|
|
266
|
+
}
|
|
268
267
|
|
|
269
268
|
.pagenav {
|
|
270
269
|
--icon-width: 1.25em;
|