markupress 0.0.1 → 0.1.0
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/LICENSE +21 -0
- package/README.md +365 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +48 -0
- package/dist/cli.js.map +1 -0
- package/dist/content.d.ts +59 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +382 -0
- package/dist/content.js.map +1 -0
- package/dist/controllers/code.d.ts +7 -0
- package/dist/controllers/code.d.ts.map +1 -0
- package/dist/controllers/code.js +31 -0
- package/dist/controllers/code.js.map +1 -0
- package/dist/controllers/outline.d.ts +8 -0
- package/dist/controllers/outline.d.ts.map +1 -0
- package/dist/controllers/outline.js +45 -0
- package/dist/controllers/outline.js.map +1 -0
- package/dist/controllers/shell.d.ts +9 -0
- package/dist/controllers/shell.d.ts.map +1 -0
- package/dist/controllers/shell.js +41 -0
- package/dist/controllers/shell.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +24 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +54 -0
- package/dist/markdown.js.map +1 -0
- package/dist/navigation.d.ts +51 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +71 -0
- package/dist/navigation.js.map +1 -0
- package/dist/site.d.ts +75 -0
- package/dist/site.d.ts.map +1 -0
- package/dist/site.js +169 -0
- package/dist/site.js.map +1 -0
- package/dist/styles.d.ts +6 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +49 -0
- package/dist/styles.js.map +1 -0
- package/dist/theme.d.ts +3 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +5 -0
- package/dist/theme.js.map +1 -0
- package/dist/versions.d.ts +19 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +130 -0
- package/dist/versions.js.map +1 -0
- package/package.json +70 -6
- package/styles/base.css +4 -0
- package/styles/prose.css +14 -0
- package/theme/outline.html +11 -0
- package/theme/shell.html +66 -0
- package/theme/theme.css +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { compileMarkdown } from './content.js';
|
|
2
|
+
export type { CompiledMarkdown, FrontMatter, MarkdownOptions, OutlineItem } from './content.js';
|
|
3
|
+
export { markdown } from './markdown.js';
|
|
4
|
+
export type { MarkdownPluginOptions } from './markdown.js';
|
|
5
|
+
export type { Link, NavItem, SidebarItem, SidebarNode } from './navigation.js';
|
|
6
|
+
export { buildSite, devSite, markupress, previewSite, siteOptions } from './site.js';
|
|
7
|
+
export type { DocumentationPage, DocumentationVersion, MarkupressOptions } from './site.js';
|
|
8
|
+
export { snapshotVersion, versionLinks } from './versions.js';
|
|
9
|
+
export type { VersionLink } from './versions.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC3D,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrF,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Public exports are introduced with implemented, verified product behavior.
|
|
2
|
+
export { compileMarkdown } from './content.js';
|
|
3
|
+
export { markdown } from './markdown.js';
|
|
4
|
+
export { buildSite, devSite, markupress, previewSite, siteOptions } from './site.js';
|
|
5
|
+
export { snapshotVersion, versionLinks } from './versions.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAErF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HtmlKitPlugin } from '@nextwebwg/htmlkit';
|
|
2
|
+
import { type CompiledMarkdown, type FrontMatter } from './content.js';
|
|
3
|
+
export interface MarkdownPluginOptions {
|
|
4
|
+
/** Directory that a page's root-relative images and files (/logo.svg) come from; without one they stay site URLs. */
|
|
5
|
+
readonly publicDir?: (file: string) => string | undefined;
|
|
6
|
+
/** Called with each compiled page and its URL, for example to catalog documents. */
|
|
7
|
+
readonly onPage?: (page: CompiledMarkdown & {
|
|
8
|
+
readonly file: string;
|
|
9
|
+
readonly href: string | undefined;
|
|
10
|
+
}) => void;
|
|
11
|
+
/** Stylesheet files every Markdown page component imports, such as a theme's prose styles. */
|
|
12
|
+
readonly styles?: readonly string[];
|
|
13
|
+
/** Number the lines of every highlighted code block unless its fence says `:no-line-numbers`. */
|
|
14
|
+
readonly lineNumbers?: boolean;
|
|
15
|
+
/** Front matter for a page that its own fields override, such as a folder's label and position on its index page. */
|
|
16
|
+
readonly frontmatter?: (file: string) => FrontMatter | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* An HTMLKit page plugin: each .md file compiles to an HTML Next page, which HTMLKit routes, orders,
|
|
20
|
+
* renders, and builds like an .html page. Links to other .md files and referenced files resolve
|
|
21
|
+
* through HTMLKit, so the plugin holds no routing of its own.
|
|
22
|
+
*/
|
|
23
|
+
export declare function markdown(options?: MarkdownPluginOptions): HtmlKitPlugin;
|
|
24
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAmB,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAExF,MAAM,WAAW,qBAAqB;IACpC,qHAAqH;IACrH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1D,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IAClH,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,iGAAiG;IACjG,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,qHAAqH;IACrH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;CAClE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,qBAA0B,GAAG,aAAa,CAkB3E"}
|
package/dist/markdown.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { compileMarkdown } from './content.js';
|
|
4
|
+
/**
|
|
5
|
+
* An HTMLKit page plugin: each .md file compiles to an HTML Next page, which HTMLKit routes, orders,
|
|
6
|
+
* renders, and builds like an .html page. Links to other .md files and referenced files resolve
|
|
7
|
+
* through HTMLKit, so the plugin holds no routing of its own.
|
|
8
|
+
*/
|
|
9
|
+
export function markdown(options = {}) {
|
|
10
|
+
return { name: 'markdown', pages: { extensions: ['.md'], async compile(source, page) {
|
|
11
|
+
const href = page.href(page.file);
|
|
12
|
+
// The URL, not the machine's path, names the page, so builds are reproducible.
|
|
13
|
+
const pageName = 'page-md-' + createHash('sha256').update(href ?? page.file).digest('hex').slice(0, 20);
|
|
14
|
+
// compileMarkdown also passes through links it already resolved; return those unchanged.
|
|
15
|
+
const resolved = new Set();
|
|
16
|
+
const frontmatter = options.frontmatter?.(page.file);
|
|
17
|
+
const compiled = await compileMarkdown(source, { file: page.file, pageName, ...(options.styles ? { styles: options.styles } : {}),
|
|
18
|
+
...(options.lineNumbers === undefined ? {} : { lineNumbers: options.lineNumbers }), ...(frontmatter ? { frontmatter } : {}), resolveLink(target, kind) {
|
|
19
|
+
if (resolved.has(target))
|
|
20
|
+
return target;
|
|
21
|
+
const url = link(target, kind, page, options);
|
|
22
|
+
resolved.add(url);
|
|
23
|
+
return url;
|
|
24
|
+
} });
|
|
25
|
+
options.onPage?.({ ...compiled, file: page.file, href });
|
|
26
|
+
return compiled.resource;
|
|
27
|
+
} } };
|
|
28
|
+
}
|
|
29
|
+
function link(href, kind, page, options) {
|
|
30
|
+
if (/^(?:[A-Za-z][A-Za-z\d+.-]*:|#|\/\/)/.test(href))
|
|
31
|
+
return href;
|
|
32
|
+
if (href.startsWith('/') && kind === 'link')
|
|
33
|
+
return href;
|
|
34
|
+
const [path, suffix = ''] = href.split(/(?=[?#])/, 2);
|
|
35
|
+
let target;
|
|
36
|
+
if (path.startsWith('/')) {
|
|
37
|
+
const directory = options.publicDir?.(page.file);
|
|
38
|
+
if (directory === undefined)
|
|
39
|
+
return href;
|
|
40
|
+
target = resolve(directory, '.' + decodeURIComponent(path));
|
|
41
|
+
}
|
|
42
|
+
else
|
|
43
|
+
target = resolve(dirname(page.file), decodeURIComponent(path));
|
|
44
|
+
if (path.endsWith('.md')) {
|
|
45
|
+
const url = page.href(target);
|
|
46
|
+
if (url === undefined)
|
|
47
|
+
throw new Error(`${page.file}: missing document ${href}.`);
|
|
48
|
+
return url + suffix;
|
|
49
|
+
}
|
|
50
|
+
if (kind === 'asset' || path.includes('.'))
|
|
51
|
+
return page.asset(target) + suffix;
|
|
52
|
+
return href;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,eAAe,EAA2C,MAAM,cAAc,CAAC;AAexF;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAO,GAA0B,EAAE;IAC1D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI;gBACjF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,+EAA+E;gBAC/E,MAAM,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACxG,yFAAyF;gBACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;gBACnC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/H,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI;wBACrJ,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;4BAAE,OAAO,MAAM,CAAC;wBACxC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;wBAC9C,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;wBAClB,OAAO,GAAG,CAAC;oBACb,CAAC,EAAE,CAAC,CAAC;gBACL,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzD,OAAO,QAAQ,CAAC,QAAQ,CAAC;YAC3B,CAAC,EAAE,EAAE,CAAC;AACR,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,IAAsB,EAAE,IAAiB,EAAE,OAA8B;IACnG,IAAI,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAsB,CAAC;IAC3E,IAAI,MAAc,CAAC;IACnB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;;QAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,sBAAsB,IAAI,GAAG,CAAC,CAAC;QAClF,OAAO,GAAG,GAAG,MAAM,CAAC;IACtB,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC/E,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { NavigationItem, NavigationNode } from '@nextwebwg/htmlkit';
|
|
2
|
+
import type { FrontMatter } from './content.js';
|
|
3
|
+
/** A top navigation or footer link. A path starting with `/` is a page of the selected version. */
|
|
4
|
+
export interface Link {
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly href: string;
|
|
7
|
+
}
|
|
8
|
+
/** A top navigation entry: a link, or a dropdown of links. */
|
|
9
|
+
export type NavItem = Link | {
|
|
10
|
+
readonly label: string;
|
|
11
|
+
readonly items: readonly Link[];
|
|
12
|
+
};
|
|
13
|
+
/** An explicit sidebar entry: a page by its path in the version (`/guide/install/`), a link, or a group. */
|
|
14
|
+
export type SidebarItem = string | Link | {
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly items: readonly SidebarItem[];
|
|
17
|
+
readonly collapsed?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** A sidebar entry as `<hk-nav>` renders it: a page or link with `href`, and a folder or group with `children`. */
|
|
20
|
+
export interface SidebarNode {
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly href?: string;
|
|
23
|
+
readonly current: string;
|
|
24
|
+
readonly open: boolean;
|
|
25
|
+
readonly depth: number;
|
|
26
|
+
readonly children: readonly SidebarNode[];
|
|
27
|
+
}
|
|
28
|
+
/** Whether a Markdown file is its folder's index page. */
|
|
29
|
+
export declare const isIndex: (file: string) => boolean;
|
|
30
|
+
interface Category {
|
|
31
|
+
readonly label?: string;
|
|
32
|
+
readonly position?: number;
|
|
33
|
+
readonly collapsed?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** A folder's group metadata. YAML also reads Docusaurus's JSON. */
|
|
36
|
+
export declare function category(directory: string): Category;
|
|
37
|
+
/**
|
|
38
|
+
* The front matter a folder's `_category` gives its index page: the label and position that HTMLKit's navigation
|
|
39
|
+
* tree reads from the index page as the folder's own. `top` is the version's content directory, whose index page
|
|
40
|
+
* is the version home and has no folder to order.
|
|
41
|
+
*/
|
|
42
|
+
export declare function categoryFrontMatter(file: string, top: string): FrontMatter | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* HTMLKit's navigation tree with Markupress's group policy: a folder stays open unless its `_category` collapses
|
|
45
|
+
* it, and one holding the current page is always open. `collapsed` tells whether a folder's index page URL starts closed.
|
|
46
|
+
*/
|
|
47
|
+
export declare function generatedSidebar(tree: readonly NavigationNode[], collapsed: (href: string) => boolean): SidebarNode[];
|
|
48
|
+
/** A configured sidebar, resolved against the version's pages so entries get their labels and current page. */
|
|
49
|
+
export declare function configuredSidebar(entries: readonly SidebarItem[], items: readonly NavigationItem[], href: (path: string) => string, current: string, depth?: number): SidebarNode[];
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,mGAAmG;AACnG,MAAM,WAAW,IAAI;IAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACvE,8DAA8D;AAC9D,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;CAAE,CAAC;AACzF,4GAA4G;AAC5G,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE3I,mHAAmH;AACnH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC3C;AAGD,0DAA0D;AAC1D,eAAO,MAAM,OAAO,SAAU,MAAM,YAA+B,CAAC;AAIpE,UAAU,QAAQ;IAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE;AACxG,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAYpD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAWtF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,WAAW,EAAE,CAGrH;AAED,+GAA+G;AAC/G,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,WAAW,EAAE,CAc9K"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join } from 'node:path';
|
|
3
|
+
import { parse } from 'yaml';
|
|
4
|
+
const index = /^(?:\d+\.)?index\.md$/;
|
|
5
|
+
/** Whether a Markdown file is its folder's index page. */
|
|
6
|
+
export const isIndex = (file) => index.test(basename(file));
|
|
7
|
+
// Markupress's own name, and Docusaurus's, so a migrated folder keeps its metadata.
|
|
8
|
+
const categoryFiles = ['_category.yml', '_category_.yml', '_category_.json'];
|
|
9
|
+
/** A folder's group metadata. YAML also reads Docusaurus's JSON. */
|
|
10
|
+
export function category(directory) {
|
|
11
|
+
const file = categoryFiles.map(name => join(directory, name)).find(existsSync);
|
|
12
|
+
if (file === undefined)
|
|
13
|
+
return {};
|
|
14
|
+
const value = parse(readFileSync(file, 'utf8'));
|
|
15
|
+
const fields = (value ?? {});
|
|
16
|
+
if (typeof fields !== 'object' || Array.isArray(fields))
|
|
17
|
+
throw new Error(`${file}: must be a mapping.`);
|
|
18
|
+
for (const [name, type] of [['label', 'string'], ['position', 'number'], ['collapsed', 'boolean']]) {
|
|
19
|
+
if (fields[name] !== undefined && typeof fields[name] !== type)
|
|
20
|
+
throw new Error(`${file}: ${name} must be a ${type}.`);
|
|
21
|
+
}
|
|
22
|
+
// HTMLKit's hk:order is a whole number, as a file's number prefix is.
|
|
23
|
+
if (fields.position !== undefined && !(Number.isSafeInteger(fields.position) && fields.position >= 0))
|
|
24
|
+
throw new Error(`${file}: position must be a whole number.`);
|
|
25
|
+
return fields;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The front matter a folder's `_category` gives its index page: the label and position that HTMLKit's navigation
|
|
29
|
+
* tree reads from the index page as the folder's own. `top` is the version's content directory, whose index page
|
|
30
|
+
* is the version home and has no folder to order.
|
|
31
|
+
*/
|
|
32
|
+
export function categoryFrontMatter(file, top) {
|
|
33
|
+
// HTMLKit labels and orders a folder only through its index page, so a _category without one could not apply.
|
|
34
|
+
for (let directory = dirname(file); directory.length > top.length; directory = dirname(directory)) {
|
|
35
|
+
const metadata = categoryFiles.map(name => join(directory, name)).find(existsSync);
|
|
36
|
+
if (metadata !== undefined && !readdirSync(directory).some(name => index.test(name))) {
|
|
37
|
+
throw new Error(`${metadata}: a folder's label, position and collapsed state apply through its index page; add an index.md to ${directory}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!isIndex(file) || dirname(file) === top)
|
|
41
|
+
return undefined;
|
|
42
|
+
const { label, position } = category(dirname(file));
|
|
43
|
+
return { ...(label === undefined ? {} : { sidebarLabel: label }), ...(position === undefined ? {} : { sidebarPosition: position }) };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* HTMLKit's navigation tree with Markupress's group policy: a folder stays open unless its `_category` collapses
|
|
47
|
+
* it, and one holding the current page is always open. `collapsed` tells whether a folder's index page URL starts closed.
|
|
48
|
+
*/
|
|
49
|
+
export function generatedSidebar(tree, collapsed) {
|
|
50
|
+
return tree.map(node => ({ ...node, open: node.open || (node.children.length > 0 && !(node.href !== undefined && collapsed(node.href))),
|
|
51
|
+
children: generatedSidebar(node.children, collapsed) }));
|
|
52
|
+
}
|
|
53
|
+
/** A configured sidebar, resolved against the version's pages so entries get their labels and current page. */
|
|
54
|
+
export function configuredSidebar(entries, items, href, current, depth = 0) {
|
|
55
|
+
return entries.map(entry => {
|
|
56
|
+
if (typeof entry === 'string') {
|
|
57
|
+
const page = items.find(item => item.href === href(entry));
|
|
58
|
+
if (page === undefined)
|
|
59
|
+
throw new Error(`sidebar: no page at ${entry}.`);
|
|
60
|
+
return { label: page.label, href: page.href, current: page.current, open: false, depth, children: [] };
|
|
61
|
+
}
|
|
62
|
+
if ('items' in entry) {
|
|
63
|
+
const children = configuredSidebar(entry.items, items, href, current, depth + 1);
|
|
64
|
+
return { label: entry.label, current: 'false', open: entry.collapsed !== true || children.some(holdsCurrent), depth, children };
|
|
65
|
+
}
|
|
66
|
+
const target = href(entry.href);
|
|
67
|
+
return { label: entry.label, href: target, current: target === current ? 'page' : 'false', open: false, depth, children: [] };
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const holdsCurrent = (node) => node.current === 'page' || node.children.some(holdsCurrent);
|
|
71
|
+
//# sourceMappingURL=navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"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"}
|
package/dist/site.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type ApplicationOptions, type ApplicationServer, type BuildResult, type HtmlKitPlugin, type ServerOptions } from '@nextwebwg/htmlkit';
|
|
2
|
+
import { type Link, type NavItem, type SidebarItem } from './navigation.js';
|
|
3
|
+
export interface DocumentationVersion {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly label?: string;
|
|
6
|
+
readonly directory: string;
|
|
7
|
+
/** Snapshot-owned public assets; active versions use the project's public directory. */
|
|
8
|
+
readonly publicDir?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MarkupressOptions {
|
|
11
|
+
readonly root?: string;
|
|
12
|
+
readonly contentDir?: string;
|
|
13
|
+
readonly base?: string;
|
|
14
|
+
readonly outDir?: string;
|
|
15
|
+
readonly title?: string;
|
|
16
|
+
readonly versions?: readonly DocumentationVersion[];
|
|
17
|
+
readonly defaultVersion?: string;
|
|
18
|
+
readonly host?: string;
|
|
19
|
+
readonly port?: number;
|
|
20
|
+
/** Number the lines of every highlighted code block unless its fence says `:no-line-numbers`. */
|
|
21
|
+
readonly lineNumbers?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* An HTML Next layout component, relative to the root, that replaces the Markupress shell. It receives the
|
|
24
|
+
* loader data its `<prop>` declarations name: see "Layout data" in the README.
|
|
25
|
+
*/
|
|
26
|
+
readonly layout?: string;
|
|
27
|
+
/** The logo before the title: one image, or one per theme. Paths starting with `/` are files in `public/`. */
|
|
28
|
+
readonly logo?: string | {
|
|
29
|
+
readonly light: string;
|
|
30
|
+
readonly dark?: string;
|
|
31
|
+
};
|
|
32
|
+
/** The site's icon, such as `/favicon.svg` from `public/`. */
|
|
33
|
+
readonly favicon?: string;
|
|
34
|
+
/** Top navigation: links, and dropdowns of links. A path starting with `/` is a page of the version being read. */
|
|
35
|
+
readonly nav?: readonly NavItem[];
|
|
36
|
+
/** Links at the end of the top navigation, each shown as its `icon` image (from `public/`) or its label. */
|
|
37
|
+
readonly social?: readonly (Link & {
|
|
38
|
+
readonly icon?: string;
|
|
39
|
+
})[];
|
|
40
|
+
/** Text of the badge beside the title. Without it, a site with several versions shows the selected version's label. */
|
|
41
|
+
readonly versionBadge?: string;
|
|
42
|
+
/** Explicit sidebars by section path (`/`, `/editor/`). Every other section's sidebar is generated from its folder. */
|
|
43
|
+
readonly sidebar?: Readonly<Record<string, readonly SidebarItem[]>>;
|
|
44
|
+
/** Footer link columns and a copyright line. */
|
|
45
|
+
readonly footer?: {
|
|
46
|
+
readonly columns?: readonly {
|
|
47
|
+
readonly title: string;
|
|
48
|
+
readonly items: readonly Link[];
|
|
49
|
+
}[];
|
|
50
|
+
readonly copyright?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export interface DocumentationPage {
|
|
54
|
+
readonly id: string;
|
|
55
|
+
readonly version: string;
|
|
56
|
+
readonly source: string;
|
|
57
|
+
/** Application-relative URL in its version, such as /v/current/guide/install/. */
|
|
58
|
+
readonly pathname: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Versioned documentation as an HTMLKit plugin. Markdown pages come from the markdown plugin, and
|
|
62
|
+
* HTMLKit routes them: each version's directory serves /v/<id>/, and the default version's also
|
|
63
|
+
* serves the site root. Markupress keeps only the version catalog its switcher needs.
|
|
64
|
+
*/
|
|
65
|
+
export declare function markupress(options?: MarkupressOptions): HtmlKitPlugin;
|
|
66
|
+
/**
|
|
67
|
+
* HTMLKit options for a Markupress site, as the CLI runs it: the site's own HTMLKit options (its `htmlkit.config.ts`)
|
|
68
|
+
* with `markupress()` added after their plugins. Markupress's own `base` and `outDir`, when set, win over HTMLKit's.
|
|
69
|
+
*/
|
|
70
|
+
export declare function siteOptions(options?: MarkupressOptions, htmlkit?: ApplicationOptions): ServerOptions;
|
|
71
|
+
export declare function buildSite(options?: MarkupressOptions): Promise<BuildResult>;
|
|
72
|
+
export declare function previewSite(options?: MarkupressOptions): Promise<ApplicationServer>;
|
|
73
|
+
/** HTMLKit's watcher recompiles Markdown and reloads open pages after each edit. */
|
|
74
|
+
export declare function devSite(options?: MarkupressOptions): Promise<ApplicationServer>;
|
|
75
|
+
//# sourceMappingURL=site.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"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"}
|
package/dist/site.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { buildApplication, devApplication, loadConfig, previewApplication } from '@nextwebwg/htmlkit';
|
|
6
|
+
import { markdown } from './markdown.js';
|
|
7
|
+
import { category, categoryFrontMatter, configuredSidebar, generatedSidebar, isIndex } from './navigation.js';
|
|
8
|
+
import { themeScript } from './theme.js';
|
|
9
|
+
import { versionLinks } from './versions.js';
|
|
10
|
+
function inside(root, path) {
|
|
11
|
+
const part = relative(root, path);
|
|
12
|
+
return part === '' || (!isAbsolute(part) && part !== '..' && !part.startsWith('../') && !part.startsWith('..\\'));
|
|
13
|
+
}
|
|
14
|
+
async function versions(options, root) {
|
|
15
|
+
if (options.versions)
|
|
16
|
+
return options.versions;
|
|
17
|
+
const manifest = join(root, 'versioned_docs/versions.json');
|
|
18
|
+
const snapshots = existsSync(manifest) ? JSON.parse(await readFile(manifest, 'utf8')) : [];
|
|
19
|
+
return [{ id: 'current', label: 'Current', directory: options.contentDir ?? 'docs' }, ...snapshots];
|
|
20
|
+
}
|
|
21
|
+
const shell = fileURLToPath(new URL('../theme/shell.html', import.meta.url));
|
|
22
|
+
const own = (path) => fileURLToPath(new URL(`../${path}`, import.meta.url));
|
|
23
|
+
// HTMLKit's css option is page-wide: Looma's :root tokens and its light/dark switch, and document defaults.
|
|
24
|
+
// A component's <style> is scoped to its own region, so these would never reach :root from the shell.
|
|
25
|
+
// theme.css also styles HTMLKit's built-in components, which no component's scoped style can reach.
|
|
26
|
+
const pageStyles = [...['tokens.css', 'theme-light.css', 'theme-dark.css'].map(file => fileURLToPath(import.meta.resolve(`@threadlabs/looma/${file}`))),
|
|
27
|
+
own('styles/base.css'), own('theme/theme.css')];
|
|
28
|
+
/**
|
|
29
|
+
* Versioned documentation as an HTMLKit plugin. Markdown pages come from the markdown plugin, and
|
|
30
|
+
* HTMLKit routes them: each version's directory serves /v/<id>/, and the default version's also
|
|
31
|
+
* serves the site root. Markupress keeps only the version catalog its switcher needs.
|
|
32
|
+
*/
|
|
33
|
+
export function markupress(options = {}) {
|
|
34
|
+
const defaultVersion = options.defaultVersion ?? 'current';
|
|
35
|
+
let root = resolve(options.root ?? process.cwd());
|
|
36
|
+
let editions = [];
|
|
37
|
+
const editionOf = (file) => editions.find(edition => inside(resolve(root, edition.directory), file));
|
|
38
|
+
// Compiled documents by version and source file. HTMLKit recompiles every page when it rediscovers, so a
|
|
39
|
+
// deleted file's stale entry is filtered by existence rather than cleared.
|
|
40
|
+
const documents = new Map();
|
|
41
|
+
const current = () => [...documents.values()].filter(doc => existsSync(doc.source));
|
|
42
|
+
const pages = markdown({
|
|
43
|
+
// Each Markdown page component imports the prose styles, so they style that page's region and nothing else.
|
|
44
|
+
styles: [own('styles/prose.css')],
|
|
45
|
+
...(options.lineNumbers === undefined ? {} : { lineNumbers: options.lineNumbers }),
|
|
46
|
+
publicDir: file => resolve(root, editionOf(file)?.publicDir ?? 'public'),
|
|
47
|
+
frontmatter(file) { const edition = editionOf(file); return edition && categoryFrontMatter(file, resolve(root, edition.directory)); },
|
|
48
|
+
onPage(page) {
|
|
49
|
+
const owners = editions.filter(edition => inside(resolve(root, edition.directory), page.file));
|
|
50
|
+
if (owners.length === 0 || page.href === undefined)
|
|
51
|
+
return;
|
|
52
|
+
// The page's URL is in the first version that serves its directory; others serve the same path.
|
|
53
|
+
const first = `/v/${owners[0].id}/`;
|
|
54
|
+
const path = page.href.slice(page.href.indexOf(first) + first.length);
|
|
55
|
+
const id = page.id ?? (path.slice(0, -1) || 'index');
|
|
56
|
+
for (const edition of owners) {
|
|
57
|
+
const twin = current().find(doc => doc.source !== page.file && doc.version === edition.id && doc.id === id);
|
|
58
|
+
if (twin)
|
|
59
|
+
throw new Error(`Documentation identity collision: ${twin.source} and ${page.file} (${id}).`);
|
|
60
|
+
documents.set(`${edition.id}\0${page.file}`, { id, version: edition.id, source: page.file, pathname: `/v/${edition.id}/${path}`,
|
|
61
|
+
aliases: page.aliases.map(alias => `/v/${edition.id}${alias}`), outline: page.outline,
|
|
62
|
+
page: { ...page.frontmatter, id, title: page.title, label: page.label } });
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
let layoutFile = shell;
|
|
67
|
+
async function load({ navigation, navigationTree, breadcrumbs, pager, url, base, propNames }) {
|
|
68
|
+
const path = '/' + url.pathname.slice(base.length);
|
|
69
|
+
const selected = /^\/v\/([^/]+)\//.exec(path)?.[1] ?? defaultVersion;
|
|
70
|
+
const requested = path.startsWith('/v/') ? path : `/v/${selected}${path}`;
|
|
71
|
+
const catalog = current();
|
|
72
|
+
const page = catalog.find(doc => doc.pathname === requested || doc.aliases.includes(requested));
|
|
73
|
+
// The default version also serves the root; its entries are marked current under /v/<id>/.
|
|
74
|
+
const within = { from: `/v/${selected}/`, current: base + (page?.pathname ?? requested).slice(1) };
|
|
75
|
+
const items = await navigation(within);
|
|
76
|
+
const data = { title: options.title ?? 'Documentation', home: base, navigation: items,
|
|
77
|
+
...await chrome(items, navigationTree, catalog.filter(doc => doc.version === selected), selected, within.current, base),
|
|
78
|
+
versions: versionLinks(catalog, editions, page?.id ?? 'index', selected, base),
|
|
79
|
+
crumbs: await breadcrumbs(within), ...await pager(within), outline: page?.outline ?? [], page: page?.page ?? {} };
|
|
80
|
+
// HTMLKit rejects props a layout does not declare, so a layout receives the data its contract names, and
|
|
81
|
+
// nested folder layouts' loaders read all of it from parent.markupress.
|
|
82
|
+
return { props: Object.fromEntries(propNames.filter(name => name in data).map(name => [name, data[name]])), data: { markupress: data } };
|
|
83
|
+
}
|
|
84
|
+
/** The shell around the page: top navigation, logo, badge, the section's sidebar and the footer. */
|
|
85
|
+
async function chrome(items, navigationTree, pages, selected, current, base) {
|
|
86
|
+
const home = `${base}v/${selected}/`;
|
|
87
|
+
const href = (to) => /^(?:[A-Za-z][\w+.-]*:|\/\/|#)/.test(to) || !to.startsWith('/') ? to : home + to.slice(1);
|
|
88
|
+
const file = (path) => path.startsWith('/') ? base + path.slice(1) : path;
|
|
89
|
+
// A link is the page itself, or an ancestor section of it (aria-current="true").
|
|
90
|
+
const link = ({ label, href: to }) => {
|
|
91
|
+
const target = href(to), path = target.split('#')[0];
|
|
92
|
+
return { label, href: target, current: target === current ? 'page' : path !== home && path.endsWith('/') && current.startsWith(path) ? 'true' : 'false' };
|
|
93
|
+
};
|
|
94
|
+
// The section is the longest configured sidebar path holding the page, else its top-level folder, else the root.
|
|
95
|
+
const path = '/' + current.slice(home.length);
|
|
96
|
+
const top = /^\/([^/]+)\//.exec(path)?.[1];
|
|
97
|
+
const section = Object.keys(options.sidebar ?? {}).filter(key => key !== '/' && path.startsWith(key)).sort((a, b) => b.length - a.length)[0]
|
|
98
|
+
?? (top !== undefined && items.some(item => item.href.startsWith(`${home}${top}/`) && item.href !== `${home}${top}/`) ? `/${top}/` : '/');
|
|
99
|
+
const explicit = options.sidebar?.[section];
|
|
100
|
+
// A _category's collapsed state is read on each render, so editing it applies in development.
|
|
101
|
+
const sources = new Map(pages.map(doc => [base + doc.pathname.slice(1), doc.source]));
|
|
102
|
+
const collapsed = (page) => { const source = sources.get(page); return source !== undefined && isIndex(source) && category(dirname(source)).collapsed === true; };
|
|
103
|
+
const logo = typeof options.logo === 'string' ? { light: options.logo, dark: options.logo } : options.logo;
|
|
104
|
+
const versions = editions.length > 1 ? editions.find(edition => edition.id === selected) : undefined;
|
|
105
|
+
return {
|
|
106
|
+
sidebar: explicit ? configuredSidebar(explicit, items, href, current)
|
|
107
|
+
: generatedSidebar(await navigationTree({ from: `/v/${selected}${section}`, current }), collapsed),
|
|
108
|
+
nav: (options.nav ?? []).map(item => {
|
|
109
|
+
if (!('items' in item))
|
|
110
|
+
return { ...link(item), items: [] };
|
|
111
|
+
const links = item.items.map(link);
|
|
112
|
+
return { label: item.label, href: '', current: links.some(entry => entry.current !== 'false') ? 'true' : 'false', items: links };
|
|
113
|
+
}),
|
|
114
|
+
logo: logo === undefined ? null : { light: file(logo.light), dark: file(logo.dark ?? logo.light) },
|
|
115
|
+
favicon: options.favicon === undefined ? null : file(options.favicon),
|
|
116
|
+
social: (options.social ?? []).map(entry => ({ label: entry.label, href: href(entry.href), icon: entry.icon === undefined ? '' : file(entry.icon) })),
|
|
117
|
+
badge: options.versionBadge ?? (versions ? versions.label ?? versions.id : ''),
|
|
118
|
+
footer: { columns: (options.footer?.columns ?? []).map(column => ({ title: column.title, items: column.items.map(link) })), copyright: options.footer?.copyright ?? '' },
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return { ...pages, name: 'markupress', async config(htmlkit) {
|
|
122
|
+
root = resolve(htmlkit.root ?? root);
|
|
123
|
+
editions = await versions(options, root);
|
|
124
|
+
const ids = new Set();
|
|
125
|
+
for (const edition of editions) {
|
|
126
|
+
if (!/^[A-Za-z0-9_-]+$/.test(edition.id) || ids.has(edition.id))
|
|
127
|
+
throw new Error(`Duplicate or invalid documentation version: ${edition.id}.`);
|
|
128
|
+
ids.add(edition.id);
|
|
129
|
+
const content = resolve(root, edition.directory);
|
|
130
|
+
if (!inside(root, content))
|
|
131
|
+
throw new Error(`Version ${edition.id}: directory must be inside the project.`);
|
|
132
|
+
if (!(await readdir(content)).some(name => /^(?:\d+\.)?index\.md$/.test(name)))
|
|
133
|
+
throw new Error(`Version ${edition.id}: a root index.md landing page is required.`);
|
|
134
|
+
}
|
|
135
|
+
const home = editions.find(edition => edition.id === defaultVersion);
|
|
136
|
+
if (home === undefined)
|
|
137
|
+
throw new Error(`Unknown defaultVersion: ${defaultVersion}.`);
|
|
138
|
+
for (const key of Object.keys(options.sidebar ?? {}))
|
|
139
|
+
if (!/^\/(?:[^/]+\/)*$/.test(key))
|
|
140
|
+
throw new Error(`sidebar: ${key} must be a path such as / or /guide/.`);
|
|
141
|
+
// The shell is the layout of Markupress's own folders only, so a site's other pages keep theirs.
|
|
142
|
+
if (options.layout !== undefined)
|
|
143
|
+
layoutFile = resolve(root, options.layout);
|
|
144
|
+
const layout = { component: layoutFile, server: { load } };
|
|
145
|
+
return { headScript: themeScript, css: pageStyles,
|
|
146
|
+
pages: [...editions.map(edition => ({ dir: edition.directory, prefix: `/v/${edition.id}/`, layout })), { dir: home.directory, layout }] };
|
|
147
|
+
} };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* HTMLKit options for a Markupress site, as the CLI runs it: the site's own HTMLKit options (its `htmlkit.config.ts`)
|
|
151
|
+
* with `markupress()` added after their plugins. Markupress's own `base` and `outDir`, when set, win over HTMLKit's.
|
|
152
|
+
*/
|
|
153
|
+
export function siteOptions(options = {}, htmlkit = {}) {
|
|
154
|
+
const root = resolve(options.root ?? htmlkit.root ?? process.cwd());
|
|
155
|
+
// markupress() already holds the markdown() plugin's pages; a second copy of either would compile .md twice.
|
|
156
|
+
const listed = htmlkit.plugins?.find(plugin => plugin.name === 'markupress' || plugin.name === 'markdown');
|
|
157
|
+
if (listed)
|
|
158
|
+
throw new Error(`htmlkit.config: the markupress command adds markupress(), which includes markdown(); remove ${listed.name}() from its plugins.`);
|
|
159
|
+
return { ...htmlkit, root, base: options.base ?? htmlkit.base ?? '/', outDir: resolve(root, options.outDir ?? htmlkit.outDir ?? 'site'),
|
|
160
|
+
plugins: [...htmlkit.plugins ?? [], markupress({ ...options, root })],
|
|
161
|
+
...(options.host === undefined ? {} : { host: options.host }), ...(options.port === undefined ? {} : { port: options.port }) };
|
|
162
|
+
}
|
|
163
|
+
// Each loads the site's htmlkit.config.ts or .js, as the htmlkit command would, so its plugins compose with Markupress.
|
|
164
|
+
const withConfig = async (options) => siteOptions(options, await loadConfig(resolve(options.root ?? process.cwd())));
|
|
165
|
+
export async function buildSite(options = {}) { return buildApplication(await withConfig(options)); }
|
|
166
|
+
export async function previewSite(options = {}) { return previewApplication(await withConfig(options)); }
|
|
167
|
+
/** HTMLKit's watcher recompiles Markdown and reloads open pages after each edit. */
|
|
168
|
+
export async function devSite(options = {}) { return devApplication(await withConfig(options)); }
|
|
169
|
+
//# sourceMappingURL=site.js.map
|
package/dist/site.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site.js","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"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"}
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAMA,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CA+BjH"}
|
package/dist/styles.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
4
|
+
import postcss from 'postcss';
|
|
5
|
+
import valueParser from 'postcss-value-parser';
|
|
6
|
+
/** CSS syntax is parsed by PostCSS; HTMLKit/Vite still compile and deliver the styles. */
|
|
7
|
+
export function stylesheet(css, file, rewrite) {
|
|
8
|
+
const root = postcss.parse(css, { from: file });
|
|
9
|
+
const dependencies = new Set();
|
|
10
|
+
const local = (value, imported = false) => {
|
|
11
|
+
if (/^(?:[A-Za-z][A-Za-z\d+.-]*:|\/|#)/.test(value) && !value.startsWith('file:'))
|
|
12
|
+
return value;
|
|
13
|
+
const clean = value.split(/[?#]/)[0];
|
|
14
|
+
let target;
|
|
15
|
+
if (value.startsWith('file:'))
|
|
16
|
+
target = fileURLToPath(value);
|
|
17
|
+
else if (imported && !value.startsWith('.')) {
|
|
18
|
+
try {
|
|
19
|
+
target = createRequire(pathToFileURL(file)).resolve(clean);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
target = resolve(dirname(file), clean);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else
|
|
26
|
+
target = resolve(dirname(file), clean);
|
|
27
|
+
dependencies.add(target);
|
|
28
|
+
return rewrite ? pathToFileURL(target).href + value.slice(clean.length) : value;
|
|
29
|
+
};
|
|
30
|
+
const transform = (value, imported) => {
|
|
31
|
+
const parsed = valueParser(value);
|
|
32
|
+
if (imported && parsed.nodes[0]?.type === 'string')
|
|
33
|
+
parsed.nodes[0].value = local(parsed.nodes[0].value, true);
|
|
34
|
+
parsed.walk(node => {
|
|
35
|
+
if (node.type === 'function' && node.value.toLowerCase() === 'url') {
|
|
36
|
+
const first = node.nodes[0];
|
|
37
|
+
if (first && (first.type === 'string' || first.type === 'word'))
|
|
38
|
+
first.value = local(first.value, imported);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
});
|
|
43
|
+
return parsed.toString();
|
|
44
|
+
};
|
|
45
|
+
root.walkAtRules('import', rule => { rule.params = transform(rule.params, true); });
|
|
46
|
+
root.walkDecls(declaration => { declaration.value = transform(declaration.value, false); });
|
|
47
|
+
return { css: root.toString(), files: [...dependencies] };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"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"}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** The Markupress plugin sets this as HTMLKit's headScript, which runs before first paint, so a saved theme never shows the default first. */
|
|
2
|
+
export declare const themeScript = "{ let saved = null; try { saved = localStorage.getItem('markupress:theme'); } catch { /* Storage can be disabled. */ }\ndocument.documentElement.dataset.theme = saved === 'dark' || (saved === null && matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; }\n";
|
|
3
|
+
//# sourceMappingURL=theme.d.ts.map
|