@t8/docsgen 0.3.32 → 0.3.34
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 +384 -304
- package/package.json +1 -1
- package/src/bin/content/createDirs.ts +21 -0
- package/src/bin/content/getCSSRoot.ts +50 -0
- package/src/bin/{getCounterContent.ts → content/getCounterContent.ts} +1 -1
- package/src/bin/content/getDefaultCodeStyleContent.ts +9 -0
- package/src/bin/{getIcon.ts → content/getIcon.ts} +1 -1
- package/src/bin/content/getIconTag.ts +10 -0
- package/src/bin/content/getIndexContent.ts +119 -0
- package/src/bin/{getInjectedContent.ts → content/getInjectedContent.ts} +3 -3
- package/src/bin/{getNav.ts → content/getNav.ts} +44 -7
- package/src/bin/content/getPlainTitle.ts +12 -0
- package/src/bin/content/getRedirectContent.ts +31 -0
- package/src/bin/content/getSectionContent.ts +80 -0
- package/src/bin/content/getStartContent.ts +40 -0
- package/src/bin/content/tweakTypography.ts +5 -0
- package/src/bin/parsing/getParsedContent.ts +28 -5
- package/src/bin/setContent.ts +16 -300
- package/.lintincludes +0 -2
- package/biome.json +0 -35
- /package/src/bin/{toFileContent.ts → content/toFileContent.ts} +0 -0
package/dist/bin.js
CHANGED
|
@@ -278,14 +278,26 @@ async function setCName({ dir = "", name, cname, jsorg }) {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// src/bin/setContent.ts
|
|
281
|
-
import {
|
|
282
|
-
import {
|
|
283
|
-
import { dirname, join as join3 } from "node:path";
|
|
284
|
-
import { fileURLToPath } from "node:url";
|
|
285
|
-
import { promisify } from "node:util";
|
|
281
|
+
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
282
|
+
import { join as join5 } from "node:path";
|
|
286
283
|
|
|
287
|
-
// src/
|
|
288
|
-
|
|
284
|
+
// src/bin/content/createDirs.ts
|
|
285
|
+
import { access, mkdir } from "node:fs/promises";
|
|
286
|
+
import { join as join3 } from "node:path";
|
|
287
|
+
async function createDirs(ctx) {
|
|
288
|
+
let { dir = "", contentDir = "" } = ctx;
|
|
289
|
+
let dirs = [contentDir];
|
|
290
|
+
await Promise.all(
|
|
291
|
+
dirs.map(async (path) => {
|
|
292
|
+
let dirPath = join3(dir, path);
|
|
293
|
+
try {
|
|
294
|
+
await access(dirPath);
|
|
295
|
+
} catch {
|
|
296
|
+
await mkdir(dirPath);
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
);
|
|
300
|
+
}
|
|
289
301
|
|
|
290
302
|
// src/utils/escapeHTML.ts
|
|
291
303
|
var htmlEntityMap = [
|
|
@@ -302,70 +314,6 @@ function escapeHTML(x) {
|
|
|
302
314
|
return s;
|
|
303
315
|
}
|
|
304
316
|
|
|
305
|
-
// src/utils/escapeRegExp.ts
|
|
306
|
-
function escapeRegExp(s) {
|
|
307
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// src/bin/getCounterContent.ts
|
|
311
|
-
function getCounterContent({ ymid }) {
|
|
312
|
-
if (!ymid) return "";
|
|
313
|
-
return `
|
|
314
|
-
<script>
|
|
315
|
-
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
|
316
|
-
m[i].l=1*new Date();
|
|
317
|
-
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
|
318
|
-
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
|
319
|
-
(window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
|
|
320
|
-
ym(${ymid}, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
|
|
321
|
-
</script>
|
|
322
|
-
<noscript><div><img src="https://mc.yandex.com/watch/${ymid}" style="position:absolute;left:-9999px;" alt=""></div></noscript>
|
|
323
|
-
`.trim();
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// src/bin/getIcon.ts
|
|
327
|
-
var iconTypeMap = {
|
|
328
|
-
ico: "image/x-icon",
|
|
329
|
-
svg: "image/svg+xml",
|
|
330
|
-
png: "image/png",
|
|
331
|
-
gif: "image/gif",
|
|
332
|
-
jpg: "image/jpeg",
|
|
333
|
-
jpeg: "image/jpeg"
|
|
334
|
-
};
|
|
335
|
-
function getIcon({ favicon, faviconType }) {
|
|
336
|
-
let icon = {
|
|
337
|
-
url: favicon,
|
|
338
|
-
type: faviconType
|
|
339
|
-
};
|
|
340
|
-
if (icon.url && !icon.type) {
|
|
341
|
-
let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
|
|
342
|
-
if (ext) icon.type = iconTypeMap[ext];
|
|
343
|
-
}
|
|
344
|
-
return icon;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// src/bin/getInjectedContent.ts
|
|
348
|
-
function getInjectedContent(ctx, page, target, mode) {
|
|
349
|
-
let injectedContent = ctx[mode]?.[target];
|
|
350
|
-
if (!injectedContent) return "";
|
|
351
|
-
return (Array.isArray(injectedContent) ? injectedContent : [injectedContent]).reduce((s, item) => {
|
|
352
|
-
if (item === void 0) return s;
|
|
353
|
-
if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
|
|
354
|
-
let { content, pages } = item;
|
|
355
|
-
if (!content || pages && !pages.includes(page)) return s;
|
|
356
|
-
return `${s}${s ? "\n" : ""}${content}`;
|
|
357
|
-
}, "");
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// src/bin/getNav.ts
|
|
361
|
-
import { JSDOM as JSDOM2 } from "jsdom";
|
|
362
|
-
|
|
363
|
-
// src/bin/getNpmLink.ts
|
|
364
|
-
function getNpmLink({ npm }, className) {
|
|
365
|
-
if (!npm) return "";
|
|
366
|
-
return `<a href="${npm}"${className ? ` class="${className}"` : ""} target="_blank">npm</a>`;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
317
|
// src/bin/getRepoLink.ts
|
|
370
318
|
function getRepoLink({ repo }, className) {
|
|
371
319
|
if (!repo) return "";
|
|
@@ -373,82 +321,8 @@ function getRepoLink({ repo }, className) {
|
|
|
373
321
|
return `<a href="${repo}"${className ? ` class="${className}"` : ""} target="_blank">${caption}</a>`;
|
|
374
322
|
}
|
|
375
323
|
|
|
376
|
-
// src/bin/getNav.ts
|
|
377
|
-
async function getNav(ctx, navItems) {
|
|
378
|
-
let { name, root, contentDir, backstory, nav } = ctx;
|
|
379
|
-
let navContent = await fetchContent(nav);
|
|
380
|
-
let s = "";
|
|
381
|
-
if (navContent) {
|
|
382
|
-
let navDom = new JSDOM2(navContent).window.document.body;
|
|
383
|
-
for (let link of navDom.querySelectorAll("a")) {
|
|
384
|
-
if (link.dataset.name === name) {
|
|
385
|
-
let parent = link.parentElement;
|
|
386
|
-
link.remove();
|
|
387
|
-
while (parent && parent.innerHTML.trim() === "") {
|
|
388
|
-
let nextParent = parent.parentElement;
|
|
389
|
-
parent.remove();
|
|
390
|
-
parent = nextParent;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
navContent = navDom.innerHTML;
|
|
395
|
-
}
|
|
396
|
-
let navItemCount = 0;
|
|
397
|
-
if (navItems.length === 1) {
|
|
398
|
-
let { id, items } = navItems[0];
|
|
399
|
-
let itemLink = `${root}${contentDir}/${encodeURIComponent(id)}`;
|
|
400
|
-
for (let { id: id2, title } of items) {
|
|
401
|
-
s += `
|
|
402
|
-
<li><a href="${itemLink}#${encodeURIComponent(id2)}">${title}</a></li>`;
|
|
403
|
-
navItemCount++;
|
|
404
|
-
}
|
|
405
|
-
} else {
|
|
406
|
-
for (let { id, title, items } of navItems) {
|
|
407
|
-
let itemLink = `${root}${contentDir}/${encodeURIComponent(id)}`;
|
|
408
|
-
s += `
|
|
409
|
-
<li data-id="${id}"><a href="${itemLink}">${title}</a>`;
|
|
410
|
-
if (items.length !== 0) {
|
|
411
|
-
s += "\n <ul>";
|
|
412
|
-
for (let { id: id2, title: title2 } of items) {
|
|
413
|
-
s += `
|
|
414
|
-
<li><a href="${itemLink}#${encodeURIComponent(id2)}">${title2}</a></li>`;
|
|
415
|
-
navItemCount++;
|
|
416
|
-
}
|
|
417
|
-
s += "\n </ul>\n";
|
|
418
|
-
}
|
|
419
|
-
s += "</li>";
|
|
420
|
-
navItemCount++;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if ((!s || navItemCount < 2) && !navContent) return "";
|
|
424
|
-
s = s.trim();
|
|
425
|
-
s = s ? `<p class="title">Contents</p>
|
|
426
|
-
<ul>${s}
|
|
427
|
-
</ul>
|
|
428
|
-
` : "";
|
|
429
|
-
let repoLink = getRepoLink(ctx);
|
|
430
|
-
let npmLink = getNpmLink(ctx);
|
|
431
|
-
if (repoLink || npmLink || backstory)
|
|
432
|
-
s += `
|
|
433
|
-
<p class="title">Resources</p>
|
|
434
|
-
<ul>
|
|
435
|
-
${repoLink ? `<li>${repoLink}</li>` : ""}
|
|
436
|
-
${npmLink ? `<li>${npmLink}</li>` : ""}
|
|
437
|
-
${backstory ? `<li><a href="${backstory}">Backstory</a></li>` : ""}
|
|
438
|
-
</ul>
|
|
439
|
-
`;
|
|
440
|
-
s = s.trim();
|
|
441
|
-
s = s ? `<section>
|
|
442
|
-
${s}
|
|
443
|
-
</section>` : "";
|
|
444
|
-
return `<nav class="aux">
|
|
445
|
-
${s}
|
|
446
|
-
${navContent}
|
|
447
|
-
</nav>`;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
324
|
// src/bin/parsing/getParsedContent.ts
|
|
451
|
-
import { JSDOM as
|
|
325
|
+
import { JSDOM as JSDOM2 } from "jsdom";
|
|
452
326
|
import Markdown from "markdown-it";
|
|
453
327
|
|
|
454
328
|
// src/bin/getSlug.ts
|
|
@@ -576,13 +450,15 @@ function preprocessContent(s) {
|
|
|
576
450
|
var md = new Markdown({
|
|
577
451
|
html: true
|
|
578
452
|
});
|
|
453
|
+
var parsedContentCache = /* @__PURE__ */ new Map();
|
|
579
454
|
async function getParsedContent(ctx) {
|
|
455
|
+
let contentLocation = getLocation(ctx, "README.md", ctx.source);
|
|
456
|
+
let parsedContent = parsedContentCache.get(contentLocation);
|
|
457
|
+
if (parsedContent) return parsedContent;
|
|
580
458
|
let { singlePage, firstLineDescription, linkMap } = ctx;
|
|
581
|
-
let rawContent = await fetchContent(
|
|
582
|
-
getLocation(ctx, "README.md", ctx.source)
|
|
583
|
-
);
|
|
459
|
+
let rawContent = await fetchContent(contentLocation);
|
|
584
460
|
let content = md.render(preprocessContent(rawContent));
|
|
585
|
-
let dom = new
|
|
461
|
+
let dom = new JSDOM2(content);
|
|
586
462
|
let { nav, linkMap: navLinkMap } = buildNav(ctx, dom);
|
|
587
463
|
let badges = "";
|
|
588
464
|
let title = "";
|
|
@@ -650,7 +526,7 @@ async function getParsedContent(ctx) {
|
|
|
650
526
|
intro[i] = `<p><span class="li">${s}</span></p>`;
|
|
651
527
|
}
|
|
652
528
|
}
|
|
653
|
-
|
|
529
|
+
parsedContent = {
|
|
654
530
|
badges,
|
|
655
531
|
// postprocessBadges(joinLines(badges)),
|
|
656
532
|
title,
|
|
@@ -662,25 +538,66 @@ async function getParsedContent(ctx) {
|
|
|
662
538
|
sections: sections.map(postprocess),
|
|
663
539
|
nav
|
|
664
540
|
};
|
|
541
|
+
parsedContentCache.set(contentLocation, parsedContent);
|
|
542
|
+
return parsedContent;
|
|
665
543
|
}
|
|
666
544
|
|
|
667
|
-
// src/bin/
|
|
668
|
-
function
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
545
|
+
// src/bin/content/getCounterContent.ts
|
|
546
|
+
function getCounterContent({ ymid }) {
|
|
547
|
+
if (!ymid) return "";
|
|
548
|
+
return `
|
|
549
|
+
<script>
|
|
550
|
+
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
|
551
|
+
m[i].l=1*new Date();
|
|
552
|
+
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
|
553
|
+
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
|
554
|
+
(window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
|
|
555
|
+
ym(${ymid}, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
|
|
556
|
+
</script>
|
|
557
|
+
<noscript><div><img src="https://mc.yandex.com/watch/${ymid}" style="position:absolute;left:-9999px;" alt=""></div></noscript>
|
|
558
|
+
`.trim();
|
|
678
559
|
}
|
|
679
560
|
|
|
680
|
-
// src/bin/
|
|
561
|
+
// src/bin/content/getCSSRoot.ts
|
|
562
|
+
import { exec as defaultExec } from "node:child_process";
|
|
563
|
+
import { cp } from "node:fs/promises";
|
|
564
|
+
import { dirname, join as join4 } from "node:path";
|
|
565
|
+
import { fileURLToPath } from "node:url";
|
|
566
|
+
import { promisify } from "node:util";
|
|
567
|
+
|
|
568
|
+
// src/const/packageName.ts
|
|
569
|
+
var packageName = "@t8/docsgen";
|
|
570
|
+
|
|
571
|
+
// src/bin/content/getCSSRoot.ts
|
|
681
572
|
var exec = promisify(defaultExec);
|
|
682
573
|
var __filename = fileURLToPath(import.meta.url);
|
|
683
574
|
var __dirname = dirname(__filename);
|
|
575
|
+
var packageURL = "";
|
|
576
|
+
async function getCSSRoot(ctx, type) {
|
|
577
|
+
let { dir = "", assetsDir } = ctx;
|
|
578
|
+
let cssRoot = {
|
|
579
|
+
index: "",
|
|
580
|
+
content: ""
|
|
581
|
+
};
|
|
582
|
+
if (assetsDir) {
|
|
583
|
+
cssRoot.index = assetsDir;
|
|
584
|
+
cssRoot.content = `../${assetsDir}`;
|
|
585
|
+
await cp(join4(__dirname, "css"), join4(dir, cssRoot.index), {
|
|
586
|
+
force: true,
|
|
587
|
+
recursive: true
|
|
588
|
+
});
|
|
589
|
+
} else {
|
|
590
|
+
if (!packageURL) {
|
|
591
|
+
let packageVersion = (await exec(`npm view ${packageName} version`)).stdout.trim().split(".").slice(0, 2).join(".");
|
|
592
|
+
packageURL = `https://unpkg.com/${packageName}@${packageVersion}`;
|
|
593
|
+
}
|
|
594
|
+
cssRoot.index = `${packageURL}/dist/css`;
|
|
595
|
+
cssRoot.content = `${packageURL}/dist/css`;
|
|
596
|
+
}
|
|
597
|
+
return cssRoot[type];
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// src/bin/content/getDefaultCodeStyleContent.ts
|
|
684
601
|
function getDefaultCodeStyleContent(cssRoot) {
|
|
685
602
|
return `
|
|
686
603
|
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/styles/stackoverflow-light.min.css" media="(prefers-color-scheme: light)">
|
|
@@ -688,72 +605,87 @@ function getDefaultCodeStyleContent(cssRoot) {
|
|
|
688
605
|
<link rel="stylesheet" href="${cssRoot}/code.css">
|
|
689
606
|
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/highlight.min.js"></script>
|
|
690
607
|
<script>hljs.highlightAll()</script>
|
|
691
|
-
|
|
608
|
+
`.trim();
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// src/bin/content/getIcon.ts
|
|
612
|
+
var iconTypeMap = {
|
|
613
|
+
ico: "image/x-icon",
|
|
614
|
+
svg: "image/svg+xml",
|
|
615
|
+
png: "image/png",
|
|
616
|
+
gif: "image/gif",
|
|
617
|
+
jpg: "image/jpeg",
|
|
618
|
+
jpeg: "image/jpeg"
|
|
619
|
+
};
|
|
620
|
+
function getIcon({ favicon, faviconType }) {
|
|
621
|
+
let icon = {
|
|
622
|
+
url: favicon,
|
|
623
|
+
type: faviconType
|
|
624
|
+
};
|
|
625
|
+
if (icon.url && !icon.type) {
|
|
626
|
+
let ext = icon.url.split("/").at(-1)?.split(".").at(-1)?.toLowerCase();
|
|
627
|
+
if (ext) icon.type = iconTypeMap[ext];
|
|
628
|
+
}
|
|
629
|
+
return icon;
|
|
692
630
|
}
|
|
631
|
+
|
|
632
|
+
// src/bin/content/getIconTag.ts
|
|
633
|
+
function getIconTag(ctx) {
|
|
634
|
+
let { url, type } = getIcon(ctx);
|
|
635
|
+
return url ? `<link rel="icon"${type ? ` type="${type}"` : ""} href="${url}">` : "";
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// src/bin/content/getInjectedContent.ts
|
|
639
|
+
function getInjectedContent(ctx, page, target, mode) {
|
|
640
|
+
let injectedContent = ctx[mode]?.[target];
|
|
641
|
+
if (!injectedContent) return "";
|
|
642
|
+
return (Array.isArray(injectedContent) ? injectedContent : [injectedContent]).reduce((s, item) => {
|
|
643
|
+
if (item === void 0) return s;
|
|
644
|
+
if (typeof item === "string") return `${s}${s ? "\n" : ""}${item}`;
|
|
645
|
+
let { content, pages } = item;
|
|
646
|
+
if (!content || pages && !pages.includes(page)) return s;
|
|
647
|
+
return `${s}${s ? "\n" : ""}${content}`;
|
|
648
|
+
}, "");
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/bin/content/getPlainTitle.ts
|
|
652
|
+
async function getPlainTitle(ctx) {
|
|
653
|
+
let { name, title, htmlTitle } = ctx;
|
|
654
|
+
let { title: parsedTitle } = await getParsedContent(ctx);
|
|
655
|
+
return escapeHTML(title || stripHTML(htmlTitle || parsedTitle, true) || name);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// src/bin/content/toFileContent.ts
|
|
659
|
+
function toFileContent(x) {
|
|
660
|
+
let s = x.replace(
|
|
661
|
+
/\s+(\r?\n *<\/?(script|link|head|body|html|meta|title)[> ])/g,
|
|
662
|
+
"$1"
|
|
663
|
+
).replace(
|
|
664
|
+
/\s+(\r?\n *<\/?(main|header|footer|nav|section|div|h\d|p|ul|ol|li|table)[> ])/g,
|
|
665
|
+
"$1"
|
|
666
|
+
).trim();
|
|
667
|
+
return `${s}
|
|
668
|
+
`;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/bin/content/tweakTypography.ts
|
|
693
672
|
function tweakTypography(s = "") {
|
|
694
673
|
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");
|
|
695
674
|
}
|
|
696
|
-
|
|
675
|
+
|
|
676
|
+
// src/bin/content/getIndexContent.ts
|
|
677
|
+
async function getIndexContent(ctx) {
|
|
697
678
|
let {
|
|
698
|
-
dir = "",
|
|
699
|
-
assetsDir,
|
|
700
679
|
root,
|
|
701
680
|
contentDir = "",
|
|
702
681
|
name,
|
|
703
|
-
title,
|
|
704
682
|
htmlTitle,
|
|
705
683
|
description: packageDescription,
|
|
706
684
|
isDevDep,
|
|
707
|
-
backstory
|
|
708
|
-
redirect
|
|
685
|
+
backstory
|
|
709
686
|
} = ctx;
|
|
710
687
|
let counterContent = getCounterContent(ctx);
|
|
711
688
|
let escapedPackageDescription = escapeHTML(packageDescription);
|
|
712
|
-
let cssRoot = {
|
|
713
|
-
index: "",
|
|
714
|
-
content: ""
|
|
715
|
-
};
|
|
716
|
-
if (assetsDir) {
|
|
717
|
-
cssRoot.index = assetsDir;
|
|
718
|
-
cssRoot.content = `../${assetsDir}`;
|
|
719
|
-
await cp(join3(__dirname, "css"), join3(dir, cssRoot.index), {
|
|
720
|
-
force: true,
|
|
721
|
-
recursive: true
|
|
722
|
-
});
|
|
723
|
-
} else {
|
|
724
|
-
let packageVersion = (await exec(`npm view ${packageName} version`)).stdout.trim().split(".").slice(0, 2).join(".");
|
|
725
|
-
let packageUrl = `https://unpkg.com/${packageName}@${packageVersion}`;
|
|
726
|
-
cssRoot.index = `${packageUrl}/dist/css`;
|
|
727
|
-
cssRoot.content = `${packageUrl}/dist/css`;
|
|
728
|
-
}
|
|
729
|
-
let icon = getIcon(ctx);
|
|
730
|
-
let iconTag = icon.url ? `<link rel="icon"${icon.type ? ` type="${icon.type}"` : ""} href="${icon.url}">` : "";
|
|
731
|
-
if (redirect) {
|
|
732
|
-
let escapedRedirect = escapeHTML(redirect);
|
|
733
|
-
await writeFile2(
|
|
734
|
-
join3(dir, "index.html"),
|
|
735
|
-
toFileContent(`
|
|
736
|
-
<!DOCTYPE html>
|
|
737
|
-
<html lang="en" data-layout="redirect" class="blank">
|
|
738
|
-
<head>
|
|
739
|
-
${getInjectedContent(ctx, "redirect", "head", "prepend")}
|
|
740
|
-
<meta charset="utf-8">
|
|
741
|
-
<meta name="viewport" content="width=device-width">
|
|
742
|
-
<meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
|
|
743
|
-
${iconTag}
|
|
744
|
-
${getInjectedContent(ctx, "redirect", "head", "append")}
|
|
745
|
-
</head>
|
|
746
|
-
<body>
|
|
747
|
-
${getInjectedContent(ctx, "redirect", "body", "prepend")}
|
|
748
|
-
${counterContent}
|
|
749
|
-
${getInjectedContent(ctx, "redirect", "body", "append")}
|
|
750
|
-
<script>window.location.replace("${escapedRedirect}");</script>
|
|
751
|
-
</body>
|
|
752
|
-
</html>
|
|
753
|
-
`)
|
|
754
|
-
);
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
689
|
let {
|
|
758
690
|
title: parsedTitle,
|
|
759
691
|
description,
|
|
@@ -761,86 +693,15 @@ ${getInjectedContent(ctx, "redirect", "body", "append")}
|
|
|
761
693
|
features,
|
|
762
694
|
note,
|
|
763
695
|
installation,
|
|
764
|
-
sections,
|
|
765
696
|
nav
|
|
766
697
|
} = await getParsedContent(ctx);
|
|
767
|
-
let plainTitle =
|
|
768
|
-
title || stripHTML(htmlTitle || parsedTitle, true) || name
|
|
769
|
-
);
|
|
698
|
+
let plainTitle = await getPlainTitle(ctx);
|
|
770
699
|
let coverTitle = htmlTitle || parsedTitle || plainTitle;
|
|
771
700
|
let descriptionContent = tweakTypography(description) || (escapedPackageDescription ? `<p>${tweakTypography(escapedPackageDescription)}<p>` : "");
|
|
772
701
|
if (!installation || isDevDep !== void 0)
|
|
773
702
|
installation = `npm i${isDevDep ? " -D" : ""} ${name}`;
|
|
774
|
-
let
|
|
775
|
-
|
|
776
|
-
await Promise.all(
|
|
777
|
-
dirs.map(async (path) => {
|
|
778
|
-
let dirPath = join3(dir, path);
|
|
779
|
-
try {
|
|
780
|
-
await access(dirPath);
|
|
781
|
-
} catch {
|
|
782
|
-
await mkdir(dirPath);
|
|
783
|
-
}
|
|
784
|
-
})
|
|
785
|
-
);
|
|
786
|
-
await Promise.all([
|
|
787
|
-
...sections.map(
|
|
788
|
-
async (content, i) => writeFile2(
|
|
789
|
-
join3(dir, contentDir, `${nav[i]?.id ?? `_untitled_${i}`}.html`),
|
|
790
|
-
toFileContent(`
|
|
791
|
-
<!DOCTYPE html>
|
|
792
|
-
<html lang="en" data-layout="section">
|
|
793
|
-
<head>
|
|
794
|
-
${getInjectedContent(ctx, "section", "head", "prepend")}
|
|
795
|
-
<meta charset="utf-8">
|
|
796
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
797
|
-
<meta name="description" content="${plainTitle}: ${escapeHTML(stripHTML(nav[i]?.title, true))}">
|
|
798
|
-
<title>${escapeHTML(stripHTML(nav[i]?.title, true))} | ${plainTitle}</title>
|
|
799
|
-
<link rel="stylesheet" href="${cssRoot.content}/base.css">
|
|
800
|
-
<link rel="stylesheet" href="${cssRoot.content}/section.css">
|
|
801
|
-
${iconTag}
|
|
802
|
-
${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
|
|
803
|
-
${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
|
|
804
|
-
${getInjectedContent(ctx, "section", "head", "append")}
|
|
805
|
-
</head>
|
|
806
|
-
<body>
|
|
807
|
-
${getInjectedContent(ctx, "section", "body", "prepend")}
|
|
808
|
-
<div class="layout">
|
|
809
|
-
<div class="${navContent ? "" : "no-nav "}body">
|
|
810
|
-
<main>
|
|
811
|
-
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
812
|
-
${content}
|
|
813
|
-
|
|
814
|
-
<p class="pagenav">
|
|
815
|
-
<span class="prev">
|
|
816
|
-
<span class="icon">\u2190</span>
|
|
817
|
-
${nav[i - 1]?.id ? `<a href="${root}${contentDir}/${nav[i - 1]?.id}">${nav[i - 1]?.title}</a>` : `<a href="${root}">Intro</a>`}
|
|
818
|
-
</span>
|
|
819
|
-
<span class="sep">|</span>
|
|
820
|
-
${nav[i + 1]?.id ? `<span class="next"><a href="${root}${contentDir}/${nav[i + 1]?.id}">${nav[i + 1]?.title}</a> <span class="icon">\u2192</span></span>` : `<span class="repo">${getRepoLink(ctx)}</span>`}
|
|
821
|
-
</p>
|
|
822
|
-
</main>
|
|
823
|
-
${navContent ? "<hr>" : ""}
|
|
824
|
-
${navContent.replace(
|
|
825
|
-
new RegExp(
|
|
826
|
-
`(<li data-id="${escapeRegExp(nav[i]?.id)}">)<a href="[^"]+">([^<]+)</a>`
|
|
827
|
-
),
|
|
828
|
-
"$1<strong>$2</strong>"
|
|
829
|
-
)}
|
|
830
|
-
</div>
|
|
831
|
-
</div>
|
|
832
|
-
|
|
833
|
-
${content.includes("<pre><code ") ? getInjectedContent(ctx, "section", ":has-code", "append") || getDefaultCodeStyleContent(cssRoot.content) : ""}
|
|
834
|
-
${counterContent}
|
|
835
|
-
${getInjectedContent(ctx, "section", "body", "append")}
|
|
836
|
-
</body>
|
|
837
|
-
</html>
|
|
838
|
-
`)
|
|
839
|
-
)
|
|
840
|
-
),
|
|
841
|
-
writeFile2(
|
|
842
|
-
join3(dir, "index.html"),
|
|
843
|
-
toFileContent(`
|
|
703
|
+
let cssRoot = await getCSSRoot(ctx, "index");
|
|
704
|
+
return toFileContent(`
|
|
844
705
|
<!DOCTYPE html>
|
|
845
706
|
<html lang="en" data-layout="index">
|
|
846
707
|
<head>
|
|
@@ -849,9 +710,9 @@ ${getInjectedContent(ctx, "section", "body", "append")}
|
|
|
849
710
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
850
711
|
<meta name="description" content="${plainTitle}${escapedPackageDescription ? `: ${escapedPackageDescription}` : ""}">
|
|
851
712
|
<title>${plainTitle}${escapedPackageDescription ? ` | ${escapedPackageDescription}` : ""}</title>
|
|
852
|
-
<link rel="stylesheet" href="${cssRoot
|
|
853
|
-
<link rel="stylesheet" href="${cssRoot
|
|
854
|
-
${
|
|
713
|
+
<link rel="stylesheet" href="${cssRoot}/base.css">
|
|
714
|
+
<link rel="stylesheet" href="${cssRoot}/index.css">
|
|
715
|
+
${getIconTag(ctx)}
|
|
855
716
|
<link rel="prefetch" href="${root}start">
|
|
856
717
|
${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
|
|
857
718
|
${getInjectedContent(ctx, "index", "head", "append")}
|
|
@@ -892,16 +753,216 @@ ${intro || features || note ? `
|
|
|
892
753
|
</main>
|
|
893
754
|
</div>
|
|
894
755
|
|
|
895
|
-
${[description, intro, features, note].some((s) => s.includes("<pre><code ")) ? getInjectedContent(ctx, "index", ":has-code", "append") || getDefaultCodeStyleContent(cssRoot
|
|
756
|
+
${[description, intro, features, note].some((s) => s.includes("<pre><code ")) ? getInjectedContent(ctx, "index", ":has-code", "append") || getDefaultCodeStyleContent(cssRoot) : ""}
|
|
896
757
|
${counterContent}
|
|
897
758
|
${getInjectedContent(ctx, "index", "body", "append")}
|
|
898
759
|
</body>
|
|
899
760
|
</html>
|
|
900
|
-
|
|
761
|
+
`);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/bin/content/getRedirectContent.ts
|
|
765
|
+
function getRedirectContent(ctx) {
|
|
766
|
+
let { redirect } = ctx;
|
|
767
|
+
let escapedRedirect = escapeHTML(redirect);
|
|
768
|
+
return toFileContent(`
|
|
769
|
+
<!DOCTYPE html>
|
|
770
|
+
<html lang="en" data-layout="redirect" class="blank">
|
|
771
|
+
<head>
|
|
772
|
+
${getInjectedContent(ctx, "redirect", "head", "prepend")}
|
|
773
|
+
<meta charset="utf-8">
|
|
774
|
+
<meta name="viewport" content="width=device-width">
|
|
775
|
+
<meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
|
|
776
|
+
${getIconTag(ctx)}
|
|
777
|
+
${getInjectedContent(ctx, "redirect", "head", "append")}
|
|
778
|
+
</head>
|
|
779
|
+
<body>
|
|
780
|
+
${getInjectedContent(ctx, "redirect", "body", "prepend")}
|
|
781
|
+
${getCounterContent(ctx)}
|
|
782
|
+
${getInjectedContent(ctx, "redirect", "body", "append")}
|
|
783
|
+
<script>window.location.replace("${escapedRedirect}");</script>
|
|
784
|
+
</body>
|
|
785
|
+
</html>
|
|
786
|
+
`);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/utils/escapeRegExp.ts
|
|
790
|
+
function escapeRegExp(s) {
|
|
791
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// src/bin/content/getNav.ts
|
|
795
|
+
import { JSDOM as JSDOM3 } from "jsdom";
|
|
796
|
+
|
|
797
|
+
// src/bin/getNpmLink.ts
|
|
798
|
+
function getNpmLink({ npm }, className) {
|
|
799
|
+
if (!npm) return "";
|
|
800
|
+
return `<a href="${npm}"${className ? ` class="${className}"` : ""} target="_blank">npm</a>`;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// src/bin/content/getNav.ts
|
|
804
|
+
var cachedNavContent = /* @__PURE__ */ new Map();
|
|
805
|
+
async function getNavContent({ name, nav }) {
|
|
806
|
+
if (!nav) return "";
|
|
807
|
+
let navContent = cachedNavContent.get(nav);
|
|
808
|
+
if (navContent !== void 0) return navContent;
|
|
809
|
+
navContent = await fetchContent(nav);
|
|
810
|
+
if (navContent) {
|
|
811
|
+
let navDom = new JSDOM3(navContent).window.document.body;
|
|
812
|
+
for (let link of navDom.querySelectorAll("a")) {
|
|
813
|
+
if (link.dataset.name === name) {
|
|
814
|
+
let parent = link.parentElement;
|
|
815
|
+
link.remove();
|
|
816
|
+
while (parent && parent.innerHTML.trim() === "") {
|
|
817
|
+
let nextParent = parent.parentElement;
|
|
818
|
+
parent.remove();
|
|
819
|
+
parent = nextParent;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
navContent = navDom.innerHTML;
|
|
824
|
+
}
|
|
825
|
+
cachedNavContent.set(nav, navContent);
|
|
826
|
+
return navContent;
|
|
827
|
+
}
|
|
828
|
+
async function getNav(ctx, navItems) {
|
|
829
|
+
let { name, root, contentDir, backstory } = ctx;
|
|
830
|
+
let navContent = await getNavContent(ctx);
|
|
831
|
+
let s = "";
|
|
832
|
+
if (navContent) {
|
|
833
|
+
let navDom = new JSDOM3(navContent).window.document.body;
|
|
834
|
+
for (let link of navDom.querySelectorAll("a")) {
|
|
835
|
+
if (link.dataset.name === name) {
|
|
836
|
+
let parent = link.parentElement;
|
|
837
|
+
link.remove();
|
|
838
|
+
while (parent && parent.innerHTML.trim() === "") {
|
|
839
|
+
let nextParent = parent.parentElement;
|
|
840
|
+
parent.remove();
|
|
841
|
+
parent = nextParent;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
navContent = navDom.innerHTML;
|
|
846
|
+
}
|
|
847
|
+
let navItemCount = 0;
|
|
848
|
+
if (navItems.length === 1) {
|
|
849
|
+
let { id, items } = navItems[0];
|
|
850
|
+
let itemLink = `${root}${contentDir}/${encodeURIComponent(id)}`;
|
|
851
|
+
for (let { id: id2, title } of items) {
|
|
852
|
+
s += `
|
|
853
|
+
<li><a href="${itemLink}#${encodeURIComponent(id2)}">${title}</a></li>`;
|
|
854
|
+
navItemCount++;
|
|
855
|
+
}
|
|
856
|
+
} else {
|
|
857
|
+
for (let { id, title, items } of navItems) {
|
|
858
|
+
let itemLink = `${root}${contentDir}/${encodeURIComponent(id)}`;
|
|
859
|
+
s += `
|
|
860
|
+
<li data-id="${id}"><a href="${itemLink}">${title}</a>`;
|
|
861
|
+
if (items.length !== 0) {
|
|
862
|
+
s += "\n <ul>";
|
|
863
|
+
for (let { id: id2, title: title2 } of items) {
|
|
864
|
+
s += `
|
|
865
|
+
<li><a href="${itemLink}#${encodeURIComponent(id2)}">${title2}</a></li>`;
|
|
866
|
+
navItemCount++;
|
|
867
|
+
}
|
|
868
|
+
s += "\n </ul>\n";
|
|
869
|
+
}
|
|
870
|
+
s += "</li>";
|
|
871
|
+
navItemCount++;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
if ((!s || navItemCount < 2) && !navContent) return "";
|
|
875
|
+
s = s.trim();
|
|
876
|
+
s = s ? `<p class="title">Contents</p>
|
|
877
|
+
<ul>${s}
|
|
878
|
+
</ul>
|
|
879
|
+
` : "";
|
|
880
|
+
let repoLink = getRepoLink(ctx);
|
|
881
|
+
let npmLink = getNpmLink(ctx);
|
|
882
|
+
if (repoLink || npmLink || backstory)
|
|
883
|
+
s += `
|
|
884
|
+
<p class="title">Resources</p>
|
|
885
|
+
<ul>
|
|
886
|
+
${repoLink ? `<li>${repoLink}</li>` : ""}
|
|
887
|
+
${npmLink ? `<li>${npmLink}</li>` : ""}
|
|
888
|
+
${backstory ? `<li><a href="${backstory}">Backstory</a></li>` : ""}
|
|
889
|
+
</ul>
|
|
890
|
+
`;
|
|
891
|
+
s = s.trim();
|
|
892
|
+
s = s ? `<section>
|
|
893
|
+
${s}
|
|
894
|
+
</section>` : "";
|
|
895
|
+
return `<nav class="aux">
|
|
896
|
+
${s}
|
|
897
|
+
${navContent}
|
|
898
|
+
</nav>`;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// src/bin/content/getSectionContent.ts
|
|
902
|
+
async function getSectionContent(ctx, index) {
|
|
903
|
+
let { root, contentDir = "" } = ctx;
|
|
904
|
+
let cssRoot = await getCSSRoot(ctx, "content");
|
|
905
|
+
let { sections, nav } = await getParsedContent(ctx);
|
|
906
|
+
let content = sections[index];
|
|
907
|
+
let navContent = await getNav(ctx, nav);
|
|
908
|
+
let plainTitle = await getPlainTitle(ctx);
|
|
909
|
+
return toFileContent(`
|
|
910
|
+
<!DOCTYPE html>
|
|
911
|
+
<html lang="en" data-layout="section">
|
|
912
|
+
<head>
|
|
913
|
+
${getInjectedContent(ctx, "section", "head", "prepend")}
|
|
914
|
+
<meta charset="utf-8">
|
|
915
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
916
|
+
<meta name="description" content="${plainTitle}: ${escapeHTML(stripHTML(nav[index]?.title, true))}">
|
|
917
|
+
<title>${escapeHTML(stripHTML(nav[index]?.title, true))} | ${plainTitle}</title>
|
|
918
|
+
<link rel="stylesheet" href="${cssRoot}/base.css">
|
|
919
|
+
<link rel="stylesheet" href="${cssRoot}/section.css">
|
|
920
|
+
${getIconTag(ctx)}
|
|
921
|
+
${nav[index + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[index + 1]?.id}">` : ""}
|
|
922
|
+
${nav[index - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[index - 1]?.id}">` : ""}
|
|
923
|
+
${getInjectedContent(ctx, "section", "head", "append")}
|
|
924
|
+
</head>
|
|
925
|
+
<body>
|
|
926
|
+
${getInjectedContent(ctx, "section", "body", "prepend")}
|
|
927
|
+
<div class="layout">
|
|
928
|
+
<div class="${navContent ? "" : "no-nav "}body">
|
|
929
|
+
<main>
|
|
930
|
+
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
931
|
+
${content}
|
|
932
|
+
|
|
933
|
+
<p class="pagenav">
|
|
934
|
+
<span class="prev">
|
|
935
|
+
<span class="icon">\u2190</span>
|
|
936
|
+
${nav[index - 1]?.id ? `<a href="${root}${contentDir}/${nav[index - 1]?.id}">${nav[index - 1]?.title}</a>` : `<a href="${root}">Intro</a>`}
|
|
937
|
+
</span>
|
|
938
|
+
<span class="sep">|</span>
|
|
939
|
+
${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>`}
|
|
940
|
+
</p>
|
|
941
|
+
</main>
|
|
942
|
+
${navContent ? "<hr>" : ""}
|
|
943
|
+
${navContent.replace(
|
|
944
|
+
new RegExp(
|
|
945
|
+
`(<li data-id="${escapeRegExp(nav[index]?.id)}">)<a href="[^"]+">([^<]+)</a>`
|
|
901
946
|
),
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
947
|
+
"$1<strong>$2</strong>"
|
|
948
|
+
)}
|
|
949
|
+
</div>
|
|
950
|
+
</div>
|
|
951
|
+
|
|
952
|
+
${content.includes("<pre><code ") ? getInjectedContent(ctx, "section", ":has-code", "append") || getDefaultCodeStyleContent(cssRoot) : ""}
|
|
953
|
+
${getCounterContent(ctx)}
|
|
954
|
+
${getInjectedContent(ctx, "section", "body", "append")}
|
|
955
|
+
</body>
|
|
956
|
+
</html>
|
|
957
|
+
`);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// src/bin/content/getStartContent.ts
|
|
961
|
+
async function getStartContent(ctx) {
|
|
962
|
+
let { root, contentDir = "" } = ctx;
|
|
963
|
+
let { nav } = await getParsedContent(ctx);
|
|
964
|
+
let plainTitle = await getPlainTitle(ctx);
|
|
965
|
+
return toFileContent(`
|
|
905
966
|
<!DOCTYPE html>
|
|
906
967
|
<html lang="en" data-layout="start" class="blank">
|
|
907
968
|
<head>
|
|
@@ -910,8 +971,8 @@ ${getInjectedContent(ctx, "index", "body", "append")}
|
|
|
910
971
|
<meta name="viewport" content="width=device-width">
|
|
911
972
|
<meta http-equiv="refresh" content="0; URL=${root}${contentDir}/${nav[0]?.id}">
|
|
912
973
|
<title>${plainTitle}</title>
|
|
913
|
-
<link rel="stylesheet" href="${
|
|
914
|
-
${
|
|
974
|
+
<link rel="stylesheet" href="${await getCSSRoot(ctx, "index")}/base.css">
|
|
975
|
+
${getIconTag(ctx)}
|
|
915
976
|
<script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
|
|
916
977
|
${getInjectedContent(ctx, "start", "head", "append")}
|
|
917
978
|
</head>
|
|
@@ -921,18 +982,37 @@ ${getInjectedContent(ctx, "start", "body", "prepend")}
|
|
|
921
982
|
<h1>${plainTitle}</h1>
|
|
922
983
|
</div>
|
|
923
984
|
|
|
924
|
-
${
|
|
985
|
+
${getCounterContent(ctx)}
|
|
925
986
|
${getInjectedContent(ctx, "start", "body", "append")}
|
|
926
987
|
</body>
|
|
927
988
|
</html>
|
|
928
|
-
|
|
929
|
-
|
|
989
|
+
`);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// src/bin/setContent.ts
|
|
993
|
+
async function setContent(ctx) {
|
|
994
|
+
let { dir = "", contentDir = "", redirect } = ctx;
|
|
995
|
+
if (redirect) {
|
|
996
|
+
await writeFile2(join5(dir, "index.html"), getRedirectContent(ctx));
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
let { sections, nav } = await getParsedContent(ctx);
|
|
1000
|
+
await createDirs(ctx);
|
|
1001
|
+
await Promise.all([
|
|
1002
|
+
...sections.map(
|
|
1003
|
+
async (_, i) => writeFile2(
|
|
1004
|
+
join5(dir, contentDir, `${nav[i]?.id ?? `_Section_${i + 1}`}.html`),
|
|
1005
|
+
await getSectionContent(ctx, i)
|
|
1006
|
+
)
|
|
1007
|
+
),
|
|
1008
|
+
writeFile2(join5(dir, "index.html"), await getIndexContent(ctx)),
|
|
1009
|
+
writeFile2(join5(dir, "start.html"), await getStartContent(ctx))
|
|
930
1010
|
]);
|
|
931
1011
|
}
|
|
932
1012
|
|
|
933
1013
|
// src/bin/setImages.ts
|
|
934
1014
|
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
935
|
-
import { join as
|
|
1015
|
+
import { join as join6 } from "node:path";
|
|
936
1016
|
|
|
937
1017
|
// src/utils/getIconContent.ts
|
|
938
1018
|
function getIconContent(baseColor = "gray") {
|
|
@@ -952,7 +1032,7 @@ function getIconContent(baseColor = "gray") {
|
|
|
952
1032
|
// src/bin/setImages.ts
|
|
953
1033
|
async function setImages({ dir = "", favicon }) {
|
|
954
1034
|
if (favicon) return;
|
|
955
|
-
await writeFile3(
|
|
1035
|
+
await writeFile3(join6(dir, "./favicon.svg"), `${getIconContent()}
|
|
956
1036
|
`);
|
|
957
1037
|
}
|
|
958
1038
|
|