docmedown 0.1.6 → 0.1.7
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/cli.js +101 -5
- package/dist/docmedown.cjs +44 -44
- package/dist/docmedown.iife.js +311 -311
- package/dist/docmedown.mjs +3795 -3597
- package/dist/types/runtime/components/OfflineNotice.d.ts +6 -0
- package/dist/types/runtime/config-schema.d.ts +9 -0
- package/dist/types/runtime/markdown/inline-text.d.ts +11 -0
- package/dist/types/runtime/offline-export.d.ts +25 -0
- package/dist/types/runtime/types.d.ts +3 -0
- package/package.json +1 -1
- package/schemas/docs.schema.json +11 -0
- package/templates/docs.json +3 -0
package/dist/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ var import_commander = require("commander");
|
|
|
31
31
|
// package.json
|
|
32
32
|
var package_default = {
|
|
33
33
|
name: "docmedown",
|
|
34
|
-
version: "0.1.
|
|
34
|
+
version: "0.1.7",
|
|
35
35
|
description: "The simplest MarkDown documenter yet. CLI & Web Script React SPA documentation engine.",
|
|
36
36
|
main: "./dist/docmedown.cjs",
|
|
37
37
|
module: "./dist/docmedown.mjs",
|
|
@@ -240,6 +240,9 @@ var docSearchConfigSchema = import_zod.z.object({
|
|
|
240
240
|
placeholder: import_zod.z.string().optional(),
|
|
241
241
|
maxResults: import_zod.z.number().int().positive().max(100).optional()
|
|
242
242
|
}).strict();
|
|
243
|
+
var docOfflineConfigSchema = import_zod.z.object({
|
|
244
|
+
embedNestedDocs: import_zod.z.boolean().optional()
|
|
245
|
+
}).strict();
|
|
243
246
|
var docConfigSchema = import_zod.z.object({
|
|
244
247
|
$schema: import_zod.z.string().url("Must be an absolute URL.").optional(),
|
|
245
248
|
name: nonEmptyString.optional(),
|
|
@@ -260,6 +263,7 @@ var docConfigSchema = import_zod.z.object({
|
|
|
260
263
|
defaultCollapsed: import_zod.z.boolean().optional()
|
|
261
264
|
}).strict().optional(),
|
|
262
265
|
search: docSearchConfigSchema.optional(),
|
|
266
|
+
offline: docOfflineConfigSchema.optional(),
|
|
263
267
|
footer: import_zod.z.object({
|
|
264
268
|
copyright: import_zod.z.string().optional(),
|
|
265
269
|
links: import_zod.z.array(navLinkSchema).optional(),
|
|
@@ -314,6 +318,9 @@ var DEFAULT_CONFIG = {
|
|
|
314
318
|
placeholder: "Search documentation...",
|
|
315
319
|
maxResults: 10
|
|
316
320
|
},
|
|
321
|
+
offline: {
|
|
322
|
+
embedNestedDocs: true
|
|
323
|
+
},
|
|
317
324
|
footer: {
|
|
318
325
|
copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} DocMeDown. All rights reserved.`,
|
|
319
326
|
showBuiltWith: true
|
|
@@ -345,6 +352,10 @@ function normalizeConfig(userConfig = {}) {
|
|
|
345
352
|
...DEFAULT_CONFIG.search,
|
|
346
353
|
...parsedConfig.search
|
|
347
354
|
},
|
|
355
|
+
offline: {
|
|
356
|
+
...DEFAULT_CONFIG.offline,
|
|
357
|
+
...parsedConfig.offline
|
|
358
|
+
},
|
|
348
359
|
footer: {
|
|
349
360
|
...DEFAULT_CONFIG.footer,
|
|
350
361
|
...parsedConfig.footer
|
|
@@ -366,7 +377,7 @@ function escapeHtml(value) {
|
|
|
366
377
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
367
378
|
}
|
|
368
379
|
function createCompressedOfflineHtml(encodedGzip, title) {
|
|
369
|
-
const bootstrap = `(async()=>{try{const b=Uint8Array.from(atob(document.getElementById("d").textContent.trim()),c=>c.charCodeAt(0)),s=await new Response(new Blob([b]).stream().pipeThrough(new DecompressionStream("gzip"))).text(),e=JSON.parse(s);if(e.version!==${OFFLINE_FORMAT_VERSION})throw new Error("Unsupported offline format");window.__DOCMEDOWN_OFFLINE__=true;window.__DOCMEDOWN_DATA__=e.data;window.__DOCMEDOWN_CONFIG__=e.data.manifest.config;const u=URL.createObjectURL(new Blob([e.runtime],{type:"text/javascript"}))
|
|
380
|
+
const bootstrap = `(async()=>{try{const b=Uint8Array.from(atob(document.getElementById("d").textContent.trim()),c=>c.charCodeAt(0)),s=await new Response(new Blob([b]).stream().pipeThrough(new DecompressionStream("gzip"))).text(),e=JSON.parse(s);if(e.version!==${OFFLINE_FORMAT_VERSION})throw new Error("Unsupported offline format");window.__DOCMEDOWN_OFFLINE__=true;window.__DOCMEDOWN_DATA__=e.data;window.__DOCMEDOWN_CONFIG__=e.data.manifest.config;const u=URL.createObjectURL(new Blob([e.runtime],{type:"text/javascript"}));window.__DOCMEDOWN_RUNTIME_URL__=u;const j=document.createElement("script");j.src=u;j.onerror=()=>{URL.revokeObjectURL(u);throw new Error("Runtime bootstrap failed")};document.head.appendChild(j)}catch(e){document.getElementById("dmd-app").textContent="Could not open this offline documentation copy: "+e.message}})();`;
|
|
370
381
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="data:,"><title>${escapeHtml(title)}</title></head><body><div id="dmd-app">Opening offline documentation\u2026</div><script id="d" type="application/octet-stream">${encodedGzip}</script><script>${bootstrap}</script></body></html>`;
|
|
371
382
|
}
|
|
372
383
|
|
|
@@ -485,6 +496,49 @@ function mapManualSidebar(items) {
|
|
|
485
496
|
});
|
|
486
497
|
}
|
|
487
498
|
|
|
499
|
+
// src/runtime/markdown/inline-text.ts
|
|
500
|
+
var NAMED_HTML_ENTITIES = {
|
|
501
|
+
amp: "&",
|
|
502
|
+
lt: "<",
|
|
503
|
+
gt: ">",
|
|
504
|
+
quot: '"',
|
|
505
|
+
apos: "'",
|
|
506
|
+
nbsp: " ",
|
|
507
|
+
copy: "\xA9",
|
|
508
|
+
reg: "\xAE",
|
|
509
|
+
trade: "\u2122",
|
|
510
|
+
middot: "\xB7",
|
|
511
|
+
hellip: "\u2026",
|
|
512
|
+
mdash: "\u2014",
|
|
513
|
+
ndash: "\u2013",
|
|
514
|
+
bull: "\u2022",
|
|
515
|
+
deg: "\xB0",
|
|
516
|
+
times: "\xD7",
|
|
517
|
+
plusmn: "\xB1",
|
|
518
|
+
laquo: "\xAB",
|
|
519
|
+
raquo: "\xBB",
|
|
520
|
+
sect: "\xA7",
|
|
521
|
+
para: "\xB6"
|
|
522
|
+
};
|
|
523
|
+
function codePointToChar(code) {
|
|
524
|
+
return Number.isInteger(code) && code > 0 && code <= 1114111 ? String.fromCodePoint(code) : "";
|
|
525
|
+
}
|
|
526
|
+
function decodeHtmlEntities(value) {
|
|
527
|
+
return value.replace(/&#x([0-9a-f]+);/gi, (_match, hex) => codePointToChar(parseInt(hex, 16))).replace(/&#([0-9]+);/g, (_match, dec) => codePointToChar(Number(dec))).replace(/&([a-z][a-z0-9]*);/gi, (match, name) => NAMED_HTML_ENTITIES[name.toLowerCase()] ?? match);
|
|
528
|
+
}
|
|
529
|
+
var IMAGE_PATTERN = /!\[([^\]]*)\]\([^)]*\)/g;
|
|
530
|
+
var LINK_PATTERN = /\[([^\]]+)\]\([^)]*\)/g;
|
|
531
|
+
var CODE_PATTERN = /`([^`]+)`/g;
|
|
532
|
+
var BOLD_PATTERN = /\*\*([^*\n]+)\*\*/g;
|
|
533
|
+
var UNDERSCORE_BOLD_PATTERN = /__([^_\n]+)__/g;
|
|
534
|
+
var ITALIC_PATTERN = /\*([^*\n]+)\*/g;
|
|
535
|
+
var STRIKETHROUGH_PATTERN = /~~([^~\n]+)~~/g;
|
|
536
|
+
function inlineHeadingToPlainText(raw) {
|
|
537
|
+
return decodeHtmlEntities(
|
|
538
|
+
raw.replace(IMAGE_PATTERN, "$1").replace(LINK_PATTERN, "$1").replace(CODE_PATTERN, "$1").replace(BOLD_PATTERN, "$1").replace(UNDERSCORE_BOLD_PATTERN, "$1").replace(ITALIC_PATTERN, "$1").replace(STRIKETHROUGH_PATTERN, "$1")
|
|
539
|
+
).replace(/\s+/g, " ").trim();
|
|
540
|
+
}
|
|
541
|
+
|
|
488
542
|
// src/cli/utils/scanner.ts
|
|
489
543
|
function extractHeadings(content) {
|
|
490
544
|
const headings = [];
|
|
@@ -493,8 +547,9 @@ function extractHeadings(content) {
|
|
|
493
547
|
const match = line.match(/^(#{1,4})\s+(.+)$/);
|
|
494
548
|
if (match) {
|
|
495
549
|
const level = match[1].length;
|
|
496
|
-
const
|
|
497
|
-
const
|
|
550
|
+
const rawHeading = match[2].trim();
|
|
551
|
+
const text = inlineHeadingToPlainText(rawHeading);
|
|
552
|
+
const id = rawHeading.replace(/[#*`_]/g, "").toLowerCase().replace(/[^\w\s-]/g, "").trim().replace(/[\s_-]+/g, "-");
|
|
498
553
|
headings.push({ level, text, id });
|
|
499
554
|
}
|
|
500
555
|
}
|
|
@@ -615,6 +670,32 @@ function findNestedDocumentationRoots(targetDir) {
|
|
|
615
670
|
visit(targetDir);
|
|
616
671
|
return roots;
|
|
617
672
|
}
|
|
673
|
+
function collectNestedOfflineSites(targetDir) {
|
|
674
|
+
const sites = {};
|
|
675
|
+
for (const nestedRoot of findNestedDocumentationRoots(targetDir)) {
|
|
676
|
+
const key = import_node_path2.default.relative(targetDir, nestedRoot).replace(/\\/g, "/");
|
|
677
|
+
const nestedConfigPath = import_node_path2.default.join(nestedRoot, "docs.json");
|
|
678
|
+
let nestedConfig = normalizeConfig();
|
|
679
|
+
if (import_node_fs2.default.existsSync(nestedConfigPath)) {
|
|
680
|
+
nestedConfig = normalizeConfig(parseDocConfigJson(import_node_fs2.default.readFileSync(nestedConfigPath, "utf-8"), nestedConfigPath));
|
|
681
|
+
}
|
|
682
|
+
const nestedDocs = {};
|
|
683
|
+
for (const file of scanDirectory(nestedRoot)) {
|
|
684
|
+
const raw = import_node_fs2.default.readFileSync(import_node_path2.default.join(nestedRoot, file), "utf-8");
|
|
685
|
+
const slug = file.replace(/\.(md|mdx)$/i, "");
|
|
686
|
+
const cleanSlug = slug.toLowerCase() === "readme" || slug.toLowerCase() === "index" ? "README" : slug;
|
|
687
|
+
nestedDocs[cleanSlug] = raw;
|
|
688
|
+
nestedDocs[file] = raw;
|
|
689
|
+
}
|
|
690
|
+
sites[key] = {
|
|
691
|
+
name: nestedConfig.name || key,
|
|
692
|
+
manifest: generateManifest(nestedRoot, nestedConfig),
|
|
693
|
+
docs: nestedDocs,
|
|
694
|
+
componentsSource: bundleCustomComponents(import_node_path2.default.join(nestedRoot, ".dmd", "components.js"))
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
return sites;
|
|
698
|
+
}
|
|
618
699
|
function shouldWatchDocumentationSource(rootDir, changedPath) {
|
|
619
700
|
const relativePath = import_node_path2.default.relative(rootDir, changedPath).replace(/\\/g, "/");
|
|
620
701
|
const firstSegment = relativePath.split("/")[0];
|
|
@@ -682,9 +763,24 @@ async function buildCommand(targetDirArg = "./docs", options = {}) {
|
|
|
682
763
|
} else {
|
|
683
764
|
console.warn(import_chalk.default.yellow(" \u26A0 Local runtime bundle not found, linking CDN script."));
|
|
684
765
|
}
|
|
766
|
+
const embedNestedDocs = config.offline?.embedNestedDocs !== false;
|
|
767
|
+
const nestedSites = embedNestedDocs && options.buildNested !== false ? collectNestedOfflineSites(targetDir) : void 0;
|
|
768
|
+
const nestedCount = nestedSites ? Object.keys(nestedSites).length : 0;
|
|
769
|
+
if (nestedCount > 0) {
|
|
770
|
+
console.log(
|
|
771
|
+
import_chalk.default.green(
|
|
772
|
+
` \u2714 Embedded ${nestedCount} nested documentation site${nestedCount === 1 ? "" : "s"} into the offline bundle`
|
|
773
|
+
)
|
|
774
|
+
);
|
|
775
|
+
}
|
|
685
776
|
const envelope = {
|
|
686
777
|
version: OFFLINE_FORMAT_VERSION,
|
|
687
|
-
data: {
|
|
778
|
+
data: {
|
|
779
|
+
manifest,
|
|
780
|
+
docs: docsMap,
|
|
781
|
+
componentsSource,
|
|
782
|
+
...nestedSites && nestedCount > 0 ? { nestedSites } : {}
|
|
783
|
+
},
|
|
688
784
|
runtime: bundleJs
|
|
689
785
|
};
|
|
690
786
|
const encodedEnvelope = encodeCompressedOfflineEnvelope(envelope);
|