@refrakt-md/content 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/dist/content-tree.d.ts +35 -0
- package/dist/content-tree.d.ts.map +1 -0
- package/dist/content-tree.js +71 -0
- package/dist/content-tree.js.map +1 -0
- package/dist/frontmatter.d.ts +18 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +15 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +19 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +94 -0
- package/dist/layout.js.map +1 -0
- package/dist/navigation.d.ts +29 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +14 -0
- package/dist/navigation.js.map +1 -0
- package/dist/router.d.ts +30 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +44 -0
- package/dist/router.js.map +1 -0
- package/dist/site.d.ts +26 -0
- package/dist/site.d.ts.map +1 -0
- package/dist/site.js +33 -0
- package/dist/site.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface ContentPage {
|
|
2
|
+
/** Absolute file path */
|
|
3
|
+
filePath: string;
|
|
4
|
+
/** Relative path from content root */
|
|
5
|
+
relativePath: string;
|
|
6
|
+
/** Raw file content */
|
|
7
|
+
raw: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ContentDirectory {
|
|
10
|
+
/** Directory name */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Absolute path */
|
|
13
|
+
dirPath: string;
|
|
14
|
+
/** Child pages */
|
|
15
|
+
pages: ContentPage[];
|
|
16
|
+
/** Child directories */
|
|
17
|
+
children: ContentDirectory[];
|
|
18
|
+
/** Layout file in this directory, if any */
|
|
19
|
+
layout?: ContentPage;
|
|
20
|
+
}
|
|
21
|
+
export interface ContentNode {
|
|
22
|
+
page: ContentPage;
|
|
23
|
+
directory: ContentDirectory;
|
|
24
|
+
}
|
|
25
|
+
export declare class ContentTree {
|
|
26
|
+
readonly root: ContentDirectory;
|
|
27
|
+
constructor(root: ContentDirectory);
|
|
28
|
+
/** Recursively walk a content directory and build the tree */
|
|
29
|
+
static fromDirectory(dirPath: string): Promise<ContentTree>;
|
|
30
|
+
/** All pages in the tree (depth-first) */
|
|
31
|
+
pages(): Generator<ContentPage>;
|
|
32
|
+
/** All layout files in the tree (depth-first) */
|
|
33
|
+
layouts(): Generator<ContentPage>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=content-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-tree.d.ts","sourceRoot":"","sources":["../src/content-tree.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,wBAAwB;IACxB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED,qBAAa,WAAW;aACM,IAAI,EAAE,gBAAgB;gBAAtB,IAAI,EAAE,gBAAgB;IAElD,8DAA8D;WACjD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAKjE,0CAA0C;IACzC,KAAK,IAAI,SAAS,CAAC,WAAW,CAAC;IAIhC,iDAAiD;IAChD,OAAO,IAAI,SAAS,CAAC,WAAW,CAAC;CAGnC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
export class ContentTree {
|
|
4
|
+
root;
|
|
5
|
+
constructor(root) {
|
|
6
|
+
this.root = root;
|
|
7
|
+
}
|
|
8
|
+
/** Recursively walk a content directory and build the tree */
|
|
9
|
+
static async fromDirectory(dirPath) {
|
|
10
|
+
const root = await readDirectory(dirPath, dirPath);
|
|
11
|
+
return new ContentTree(root);
|
|
12
|
+
}
|
|
13
|
+
/** All pages in the tree (depth-first) */
|
|
14
|
+
*pages() {
|
|
15
|
+
yield* walkPages(this.root);
|
|
16
|
+
}
|
|
17
|
+
/** All layout files in the tree (depth-first) */
|
|
18
|
+
*layouts() {
|
|
19
|
+
yield* walkLayouts(this.root);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function readDirectory(dirPath, rootPath) {
|
|
23
|
+
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
|
|
24
|
+
const dir = {
|
|
25
|
+
name: path.basename(dirPath),
|
|
26
|
+
dirPath,
|
|
27
|
+
pages: [],
|
|
28
|
+
children: [],
|
|
29
|
+
};
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
32
|
+
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
33
|
+
dir.children.push(await readDirectory(fullPath, rootPath));
|
|
34
|
+
}
|
|
35
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
36
|
+
const raw = await fs.promises.readFile(fullPath, 'utf-8');
|
|
37
|
+
const page = {
|
|
38
|
+
filePath: fullPath,
|
|
39
|
+
relativePath: path.relative(rootPath, fullPath),
|
|
40
|
+
raw,
|
|
41
|
+
};
|
|
42
|
+
if (entry.name === '_layout.md') {
|
|
43
|
+
dir.layout = page;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
dir.pages.push(page);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Sort pages by name for deterministic ordering
|
|
51
|
+
dir.pages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
52
|
+
dir.children.sort((a, b) => a.name.localeCompare(b.name));
|
|
53
|
+
return dir;
|
|
54
|
+
}
|
|
55
|
+
function* walkPages(dir) {
|
|
56
|
+
for (const page of dir.pages) {
|
|
57
|
+
yield page;
|
|
58
|
+
}
|
|
59
|
+
for (const child of dir.children) {
|
|
60
|
+
yield* walkPages(child);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function* walkLayouts(dir) {
|
|
64
|
+
if (dir.layout) {
|
|
65
|
+
yield dir.layout;
|
|
66
|
+
}
|
|
67
|
+
for (const child of dir.children) {
|
|
68
|
+
yield* walkLayouts(child);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=content-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-tree.js","sourceRoot":"","sources":["../src/content-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Frontmatter {
|
|
2
|
+
title?: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
slug?: string;
|
|
5
|
+
draft?: boolean;
|
|
6
|
+
redirect?: string;
|
|
7
|
+
order?: number;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parse YAML frontmatter from raw markdown content.
|
|
12
|
+
* Returns the frontmatter object and the content without frontmatter.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseFrontmatter(raw: string): {
|
|
15
|
+
frontmatter: Frontmatter;
|
|
16
|
+
content: string;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAW3F"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import yaml from 'yaml';
|
|
2
|
+
/**
|
|
3
|
+
* Parse YAML frontmatter from raw markdown content.
|
|
4
|
+
* Returns the frontmatter object and the content without frontmatter.
|
|
5
|
+
*/
|
|
6
|
+
export function parseFrontmatter(raw) {
|
|
7
|
+
const match = raw.match(/^---\r?\n([\s\S]*?\r?\n)?---\r?\n?([\s\S]*)$/);
|
|
8
|
+
if (!match) {
|
|
9
|
+
return { frontmatter: {}, content: raw };
|
|
10
|
+
}
|
|
11
|
+
const frontmatter = yaml.parse(match[1] ?? '') ?? {};
|
|
12
|
+
const content = match[2];
|
|
13
|
+
return { frontmatter, content };
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAYxB;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAExE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAgB,IAAI,EAAE,CAAC;IACpE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEzB,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ContentTree, type ContentNode, type ContentPage, type ContentDirectory } from './content-tree.js';
|
|
2
|
+
export { parseFrontmatter, type Frontmatter } from './frontmatter.js';
|
|
3
|
+
export { Router, type Route } from './router.js';
|
|
4
|
+
export { resolveLayouts, type ResolvedLayout, type Region } from './layout.js';
|
|
5
|
+
export { buildNavigation, type NavTree, type NavGroup, type NavItem } from './navigation.js';
|
|
6
|
+
export { loadContent, type Site, type SitePage } from './site.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3G,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ContentTree } from './content-tree.js';
|
|
2
|
+
export { parseFrontmatter } from './frontmatter.js';
|
|
3
|
+
export { Router } from './router.js';
|
|
4
|
+
export { resolveLayouts } from './layout.js';
|
|
5
|
+
export { buildNavigation } from './navigation.js';
|
|
6
|
+
export { loadContent } from './site.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA6D,MAAM,mBAAmB,CAAC;AAC3G,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAoC,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,eAAe,EAA6C,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAA4B,MAAM,WAAW,CAAC"}
|
package/dist/layout.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
|
2
|
+
import { ContentDirectory, ContentPage } from './content-tree.js';
|
|
3
|
+
export interface Region {
|
|
4
|
+
name: string;
|
|
5
|
+
mode: 'replace' | 'prepend' | 'append';
|
|
6
|
+
content: RenderableTreeNode[];
|
|
7
|
+
}
|
|
8
|
+
export interface ResolvedLayout {
|
|
9
|
+
/** The chain of layout files from root to nearest, in order */
|
|
10
|
+
chain: ContentPage[];
|
|
11
|
+
/** Merged regions after applying inheritance */
|
|
12
|
+
regions: Map<string, Region>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the layout chain for a page by walking up the directory tree.
|
|
16
|
+
* Collects all _layout.md files from the page's directory up to the root.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveLayouts(page: ContentPage, rootDir: ContentDirectory): ResolvedLayout;
|
|
19
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,kBAAkB,CAAC;AAGhF,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGlE,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,gDAAgD;IAChD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,gBAAgB,GACxB,cAAc,CAIhB"}
|
package/dist/layout.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import Markdoc from '@markdoc/markdoc';
|
|
2
|
+
const { Tag } = Markdoc;
|
|
3
|
+
import { tags, nodes } from '@refrakt-md/runes';
|
|
4
|
+
import { parseFrontmatter } from './frontmatter.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the layout chain for a page by walking up the directory tree.
|
|
7
|
+
* Collects all _layout.md files from the page's directory up to the root.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveLayouts(page, rootDir) {
|
|
10
|
+
const chain = findLayoutChain(page, rootDir);
|
|
11
|
+
const regions = mergeRegions(chain);
|
|
12
|
+
return { chain, regions };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Find all _layout.md files from root down to the page's directory.
|
|
16
|
+
*/
|
|
17
|
+
function findLayoutChain(page, rootDir) {
|
|
18
|
+
const parts = page.relativePath.split('/').slice(0, -1); // directory segments
|
|
19
|
+
const chain = [];
|
|
20
|
+
let current = rootDir;
|
|
21
|
+
// Root layout
|
|
22
|
+
if (current.layout) {
|
|
23
|
+
chain.push(current.layout);
|
|
24
|
+
}
|
|
25
|
+
// Walk down through directories toward the page
|
|
26
|
+
for (const part of parts) {
|
|
27
|
+
current = current.children.find(c => c.name === part);
|
|
28
|
+
if (!current)
|
|
29
|
+
break;
|
|
30
|
+
if (current.layout) {
|
|
31
|
+
chain.push(current.layout);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return chain;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a layout file through Markdoc and extract regions.
|
|
38
|
+
*/
|
|
39
|
+
function parseLayout(layoutPage) {
|
|
40
|
+
const { content } = parseFrontmatter(layoutPage.raw);
|
|
41
|
+
const ast = Markdoc.parse(content);
|
|
42
|
+
const config = { tags, nodes, variables: { generatedIds: new Set(), path: layoutPage.relativePath } };
|
|
43
|
+
const rendered = Markdoc.transform(ast, config);
|
|
44
|
+
const regions = [];
|
|
45
|
+
findRegions(rendered, regions);
|
|
46
|
+
return regions;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Recursively walk a rendered Tag tree to find data-region containers.
|
|
50
|
+
*/
|
|
51
|
+
function findRegions(node, results) {
|
|
52
|
+
if (Array.isArray(node)) {
|
|
53
|
+
for (const child of node) {
|
|
54
|
+
findRegions(child, results);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!Tag.isTag(node))
|
|
59
|
+
return;
|
|
60
|
+
const regionName = node.attributes['data-region'];
|
|
61
|
+
if (regionName) {
|
|
62
|
+
const mode = node.attributes['data-mode'] || 'replace';
|
|
63
|
+
results.push({ name: regionName, mode, content: node.children });
|
|
64
|
+
return; // Don't recurse into region children — they're the region's content
|
|
65
|
+
}
|
|
66
|
+
// Recurse into non-region tags (e.g., the layout wrapper div)
|
|
67
|
+
for (const child of node.children) {
|
|
68
|
+
findRegions(child, results);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Merge regions from a layout chain.
|
|
73
|
+
* Later layouts in the chain can replace, prepend, or append to earlier regions.
|
|
74
|
+
*/
|
|
75
|
+
function mergeRegions(chain) {
|
|
76
|
+
const merged = new Map();
|
|
77
|
+
for (const layoutPage of chain) {
|
|
78
|
+
const regions = parseLayout(layoutPage);
|
|
79
|
+
for (const { name, mode, content } of regions) {
|
|
80
|
+
const existing = merged.get(name);
|
|
81
|
+
if (!existing || mode === 'replace') {
|
|
82
|
+
merged.set(name, { name, mode, content });
|
|
83
|
+
}
|
|
84
|
+
else if (mode === 'prepend') {
|
|
85
|
+
merged.set(name, { name, mode: existing.mode, content: [...content, ...existing.content] });
|
|
86
|
+
}
|
|
87
|
+
else if (mode === 'append') {
|
|
88
|
+
merged.set(name, { name, mode: existing.mode, content: [...existing.content, ...content] });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return merged;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface NavItem {
|
|
2
|
+
/** Page slug or URL */
|
|
3
|
+
slug: string;
|
|
4
|
+
/** Display title */
|
|
5
|
+
title?: string;
|
|
6
|
+
/** Child items */
|
|
7
|
+
children: NavItem[];
|
|
8
|
+
}
|
|
9
|
+
export interface NavGroup {
|
|
10
|
+
/** Group title */
|
|
11
|
+
title: string;
|
|
12
|
+
/** Items in this group */
|
|
13
|
+
items: NavItem[];
|
|
14
|
+
}
|
|
15
|
+
export interface NavTree {
|
|
16
|
+
/** Navigation groups */
|
|
17
|
+
groups: NavGroup[];
|
|
18
|
+
/** Top-level items not in any group */
|
|
19
|
+
items: NavItem[];
|
|
20
|
+
/** Whether this nav supports sequential pagination */
|
|
21
|
+
ordered: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build a navigation tree from parsed {% nav %} rune output.
|
|
25
|
+
* This processes the rendered Tag tree from the nav rune into a
|
|
26
|
+
* structured navigation object.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildNavigation(navTag: unknown): NavTree;
|
|
29
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,wBAAwB;IACxB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,uCAAuC;IACvC,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAOxD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a navigation tree from parsed {% nav %} rune output.
|
|
3
|
+
* This processes the rendered Tag tree from the nav rune into a
|
|
4
|
+
* structured navigation object.
|
|
5
|
+
*/
|
|
6
|
+
export function buildNavigation(navTag) {
|
|
7
|
+
// TODO: Implement full nav tree building from rendered Tag output
|
|
8
|
+
return {
|
|
9
|
+
groups: [],
|
|
10
|
+
items: [],
|
|
11
|
+
ordered: false,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAyBA;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAe;IAC7C,kEAAkE;IAClE,OAAO;QACL,MAAM,EAAE,EAAE;QACV,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Frontmatter } from './frontmatter.js';
|
|
2
|
+
export interface Route {
|
|
3
|
+
/** The URL path for this page */
|
|
4
|
+
url: string;
|
|
5
|
+
/** The original relative file path */
|
|
6
|
+
filePath: string;
|
|
7
|
+
/** Whether this page is a draft */
|
|
8
|
+
draft: boolean;
|
|
9
|
+
/** Redirect target, if any */
|
|
10
|
+
redirect?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class Router {
|
|
13
|
+
private basePath;
|
|
14
|
+
constructor(basePath?: string);
|
|
15
|
+
/**
|
|
16
|
+
* Layer 1: File path → URL path
|
|
17
|
+
* - Strip .md extension
|
|
18
|
+
* - Convert index.md to /
|
|
19
|
+
* - Strip numeric prefixes (01-intro → intro)
|
|
20
|
+
*/
|
|
21
|
+
filePathToUrl(relativePath: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Layer 2: Apply frontmatter overrides
|
|
24
|
+
* - slug override replaces the computed URL
|
|
25
|
+
* - draft pages are flagged
|
|
26
|
+
* - redirect pages are flagged
|
|
27
|
+
*/
|
|
28
|
+
resolve(relativePath: string, frontmatter: Frontmatter): Route;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,KAAK;IACpB,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,MAAM;IACL,OAAO,CAAC,QAAQ;gBAAR,QAAQ,GAAE,MAAY;IAE1C;;;;;OAKG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAgB3C;;;;;OAKG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,KAAK;CAY/D"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
export class Router {
|
|
3
|
+
basePath;
|
|
4
|
+
constructor(basePath = '/') {
|
|
5
|
+
this.basePath = basePath;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Layer 1: File path → URL path
|
|
9
|
+
* - Strip .md extension
|
|
10
|
+
* - Convert index.md to /
|
|
11
|
+
* - Strip numeric prefixes (01-intro → intro)
|
|
12
|
+
*/
|
|
13
|
+
filePathToUrl(relativePath) {
|
|
14
|
+
let url = relativePath
|
|
15
|
+
.replace(/\.md$/, '')
|
|
16
|
+
.split(path.sep)
|
|
17
|
+
.map(segment => segment.replace(/^\d+-/, ''))
|
|
18
|
+
.join('/');
|
|
19
|
+
// index files map to directory root
|
|
20
|
+
if (url.endsWith('/index') || url === 'index') {
|
|
21
|
+
url = url.replace(/\/?index$/, '');
|
|
22
|
+
}
|
|
23
|
+
const base = this.basePath.endsWith('/') ? this.basePath.slice(0, -1) : this.basePath;
|
|
24
|
+
return `${base}/${url}` || '/';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Layer 2: Apply frontmatter overrides
|
|
28
|
+
* - slug override replaces the computed URL
|
|
29
|
+
* - draft pages are flagged
|
|
30
|
+
* - redirect pages are flagged
|
|
31
|
+
*/
|
|
32
|
+
resolve(relativePath, frontmatter) {
|
|
33
|
+
const url = frontmatter.slug
|
|
34
|
+
? (frontmatter.slug.startsWith('/') ? frontmatter.slug : `${this.basePath}${frontmatter.slug}`)
|
|
35
|
+
: this.filePathToUrl(relativePath);
|
|
36
|
+
return {
|
|
37
|
+
url,
|
|
38
|
+
filePath: relativePath,
|
|
39
|
+
draft: frontmatter.draft === true,
|
|
40
|
+
redirect: frontmatter.redirect,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAclC,MAAM,OAAO,MAAM;IACG;IAApB,YAAoB,WAAmB,GAAG;QAAtB,aAAQ,GAAR,QAAQ,CAAc;IAAG,CAAC;IAE9C;;;;;OAKG;IACH,aAAa,CAAC,YAAoB;QAChC,IAAI,GAAG,GAAG,YAAY;aACnB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;aACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;aACf,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;aAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,oCAAoC;QACpC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAC9C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtF,OAAO,GAAG,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,YAAoB,EAAE,WAAwB;QACpD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI;YAC1B,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;YAC/F,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAErC,OAAO;YACL,GAAG;YACH,QAAQ,EAAE,YAAY;YACtB,KAAK,EAAE,WAAW,CAAC,KAAK,KAAK,IAAI;YACjC,QAAQ,EAAE,WAAW,CAAC,QAAQ;SAC/B,CAAC;IACJ,CAAC;CACF"}
|
package/dist/site.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RenderableTreeNodes } from '@markdoc/markdoc';
|
|
2
|
+
import { ContentTree } from './content-tree.js';
|
|
3
|
+
import { Frontmatter } from './frontmatter.js';
|
|
4
|
+
import { Route } from './router.js';
|
|
5
|
+
import { ResolvedLayout } from './layout.js';
|
|
6
|
+
import { NavTree } from './navigation.js';
|
|
7
|
+
export interface Site {
|
|
8
|
+
/** The content tree */
|
|
9
|
+
tree: ContentTree;
|
|
10
|
+
/** All resolved pages with routes and layouts */
|
|
11
|
+
pages: SitePage[];
|
|
12
|
+
/** Navigation trees found in layouts */
|
|
13
|
+
navigation: NavTree[];
|
|
14
|
+
}
|
|
15
|
+
export interface SitePage {
|
|
16
|
+
route: Route;
|
|
17
|
+
frontmatter: Frontmatter;
|
|
18
|
+
content: string;
|
|
19
|
+
renderable: RenderableTreeNodes;
|
|
20
|
+
layout: ResolvedLayout;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load a content directory and resolve all pages, routes, layouts, and navigation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadContent(dirPath: string, basePath?: string): Promise<Site>;
|
|
26
|
+
//# sourceMappingURL=site.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAoB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAU,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAkB,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,WAAW,IAAI;IACnB,uBAAuB;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,wCAAwC;IACxC,UAAU,EAAE,OAAO,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,mBAAmB,CAAC;IAChC,MAAM,EAAE,cAAc,CAAC;CACxB;AASD;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBxF"}
|
package/dist/site.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Markdoc from '@markdoc/markdoc';
|
|
2
|
+
import { tags, nodes, extractHeadings } from '@refrakt-md/runes';
|
|
3
|
+
import { ContentTree } from './content-tree.js';
|
|
4
|
+
import { parseFrontmatter } from './frontmatter.js';
|
|
5
|
+
import { Router } from './router.js';
|
|
6
|
+
import { resolveLayouts } from './layout.js';
|
|
7
|
+
function transformContent(content, path) {
|
|
8
|
+
const ast = Markdoc.parse(content);
|
|
9
|
+
const headings = extractHeadings(ast);
|
|
10
|
+
const config = { tags, nodes, variables: { generatedIds: new Set(), path, headings } };
|
|
11
|
+
return Markdoc.transform(ast, config);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load a content directory and resolve all pages, routes, layouts, and navigation.
|
|
15
|
+
*/
|
|
16
|
+
export async function loadContent(dirPath, basePath = '/') {
|
|
17
|
+
const tree = await ContentTree.fromDirectory(dirPath);
|
|
18
|
+
const router = new Router(basePath);
|
|
19
|
+
const pages = [];
|
|
20
|
+
for (const page of tree.pages()) {
|
|
21
|
+
const { frontmatter, content } = parseFrontmatter(page.raw);
|
|
22
|
+
const route = router.resolve(page.relativePath, frontmatter);
|
|
23
|
+
const layout = resolveLayouts(page, tree.root);
|
|
24
|
+
const renderable = transformContent(content, route.url);
|
|
25
|
+
pages.push({ route, frontmatter, content, renderable, layout });
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
tree,
|
|
29
|
+
pages,
|
|
30
|
+
navigation: [], // TODO: Extract from resolved layouts
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# 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":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAe,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAS,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAC;AAoB7D,SAAS,gBAAgB,CAAC,OAAe,EAAE,IAAY;IACrD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,YAAY,EAAE,IAAI,GAAG,EAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;IAC/F,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,WAAmB,GAAG;IACvE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAChC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAExD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,IAAI;QACJ,KAAK;QACL,UAAU,EAAE,EAAE,EAAE,sCAAsC;KACvD,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@refrakt-md/content",
|
|
3
|
+
"description": "Content loading and transformation pipeline",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/refrakt-md/refrakt.git",
|
|
10
|
+
"directory": "packages/content"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/refrakt-md/refrakt/issues",
|
|
13
|
+
"homepage": "https://github.com/refrakt-md/refrakt",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"types": "dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@refrakt-md/runes": "0.1.0",
|
|
27
|
+
"@refrakt-md/types": "0.1.0",
|
|
28
|
+
"@markdoc/markdoc": "0.4.0",
|
|
29
|
+
"yaml": "^2.4.0"
|
|
30
|
+
}
|
|
31
|
+
}
|