@stackbox/cms 0.0.5 → 0.1.1

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.
Files changed (119) hide show
  1. package/README.md +158 -10
  2. package/dist/AGENTS.md +218 -0
  3. package/dist/blocks.d.ts +6 -13
  4. package/dist/blocks.d.ts.map +1 -1
  5. package/dist/blocks.js +2 -0
  6. package/dist/blocks.js.map +1 -1
  7. package/dist/build.d.ts +14 -0
  8. package/dist/build.d.ts.map +1 -0
  9. package/dist/build.js +145 -0
  10. package/dist/build.js.map +1 -0
  11. package/dist/cache.d.ts +14 -0
  12. package/dist/cache.d.ts.map +1 -0
  13. package/dist/cache.js +93 -0
  14. package/dist/cache.js.map +1 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +16 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/index.d.ts +12 -8
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/link.d.ts +3 -7
  24. package/dist/link.d.ts.map +1 -1
  25. package/dist/link.js +12 -19
  26. package/dist/link.js.map +1 -1
  27. package/dist/merge-hooks.d.ts +3 -0
  28. package/dist/merge-hooks.d.ts.map +1 -0
  29. package/dist/merge-hooks.js +54 -0
  30. package/dist/merge-hooks.js.map +1 -0
  31. package/dist/pages.d.ts +15 -46
  32. package/dist/pages.d.ts.map +1 -1
  33. package/dist/pages.js +2 -0
  34. package/dist/pages.js.map +1 -1
  35. package/dist/plugin.d.ts +22 -0
  36. package/dist/plugin.d.ts.map +1 -0
  37. package/dist/plugin.js +156 -0
  38. package/dist/plugin.js.map +1 -0
  39. package/dist/plugins/blog/index.d.ts +6 -5
  40. package/dist/plugins/blog/index.d.ts.map +1 -1
  41. package/dist/plugins/blog/index.js +16 -0
  42. package/dist/plugins/blog/index.js.map +1 -1
  43. package/dist/plugins/random-quote/assets/quotes.json +230 -0
  44. package/dist/plugins/random-quote/index.d.ts +3 -1
  45. package/dist/plugins/random-quote/index.d.ts.map +1 -1
  46. package/dist/plugins/random-quote/index.js +15 -1
  47. package/dist/plugins/random-quote/index.js.map +1 -1
  48. package/dist/plugins/sitemap/index.d.ts +14 -0
  49. package/dist/plugins/sitemap/index.d.ts.map +1 -0
  50. package/dist/plugins/sitemap/index.js +119 -0
  51. package/dist/plugins/sitemap/index.js.map +1 -0
  52. package/dist/render-head.d.ts +2 -2
  53. package/dist/render-head.d.ts.map +1 -1
  54. package/dist/render-page.d.ts +2 -4
  55. package/dist/render-page.d.ts.map +1 -1
  56. package/dist/render-page.js +7 -3
  57. package/dist/render-page.js.map +1 -1
  58. package/dist/site.d.ts +10 -17
  59. package/dist/site.d.ts.map +1 -1
  60. package/dist/site.js +155 -7
  61. package/dist/site.js.map +1 -1
  62. package/dist/slot-content.d.ts +3 -19
  63. package/dist/slot-content.d.ts.map +1 -1
  64. package/dist/slot-content.js.map +1 -1
  65. package/dist/slot-handle.d.ts +7 -25
  66. package/dist/slot-handle.d.ts.map +1 -1
  67. package/dist/slot-handle.js +29 -14
  68. package/dist/slot-handle.js.map +1 -1
  69. package/dist/stackbox/context.d.ts +2 -51
  70. package/dist/stackbox/context.d.ts.map +1 -1
  71. package/dist/stackbox/context.js.map +1 -1
  72. package/dist/templates.d.ts +7 -57
  73. package/dist/templates.d.ts.map +1 -1
  74. package/dist/templates.js.map +1 -1
  75. package/dist/types.d.ts +281 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +2 -0
  78. package/dist/types.js.map +1 -0
  79. package/package.json +17 -6
  80. package/src/plugins/blog/AGENTS.md +5 -1
  81. package/src/plugins/blog/index.ts +22 -5
  82. package/src/plugins/random-quote/AGENTS.md +30 -7
  83. package/src/plugins/random-quote/index.ts +17 -1
  84. package/src/plugins/random-quote/public_assets/widget.css +5 -0
  85. package/src/plugins/sitemap/AGENTS.md +82 -0
  86. package/src/plugins/sitemap/index.ts +156 -0
  87. package/AGENTS.md +0 -87
  88. package/dist/modules/blog/module.d.ts +0 -20
  89. package/dist/modules/blog/module.d.ts.map +0 -1
  90. package/dist/modules/blog/module.js +0 -52
  91. package/dist/modules/blog/module.js.map +0 -1
  92. package/dist/modules/blog/posts.d.ts +0 -15
  93. package/dist/modules/blog/posts.d.ts.map +0 -1
  94. package/dist/modules/blog/posts.js +0 -46
  95. package/dist/modules/blog/posts.js.map +0 -1
  96. package/dist/modules.d.ts +0 -18
  97. package/dist/modules.d.ts.map +0 -1
  98. package/dist/modules.js +0 -25
  99. package/dist/modules.js.map +0 -1
  100. package/dist/plugins/blog/module.d.ts +0 -20
  101. package/dist/plugins/blog/module.d.ts.map +0 -1
  102. package/dist/plugins/blog/module.js +0 -52
  103. package/dist/plugins/blog/module.js.map +0 -1
  104. package/dist/plugins/blog/plugin.d.ts +0 -20
  105. package/dist/plugins/blog/plugin.d.ts.map +0 -1
  106. package/dist/plugins/blog/plugin.js +0 -52
  107. package/dist/plugins/blog/plugin.js.map +0 -1
  108. package/dist/plugins/random-quote/module.d.ts +0 -9
  109. package/dist/plugins/random-quote/module.d.ts.map +0 -1
  110. package/dist/plugins/random-quote/module.js +0 -31
  111. package/dist/plugins/random-quote/module.js.map +0 -1
  112. package/dist/plugins/random-quote/plugin.d.ts +0 -8
  113. package/dist/plugins/random-quote/plugin.d.ts.map +0 -1
  114. package/dist/plugins/random-quote/plugin.js +0 -31
  115. package/dist/plugins/random-quote/plugin.js.map +0 -1
  116. package/dist/plugins/random-quote/quotes.json +0 -230
  117. package/dist/public/_sb/plugins/random-quote/quotes.json +0 -230
  118. package/src/plugins/random-quote/public_assets/quotes.json +0 -230
  119. /package/{dist/plugins/random-quote/public_assets → src/plugins/random-quote/assets}/quotes.json +0 -0
@@ -1,6 +1,22 @@
1
1
  import { html } from "@hyperspan/html";
2
2
  import { createBlock } from "../../blocks.js";
3
- import bundledQuotes from "./public_assets/quotes.json" with { type: "json" };
3
+ import { createPlugin } from "../../plugin.js";
4
+ import bundledQuotes from "./assets/quotes.json" with { type: "json" };
5
+
6
+ export default createPlugin({
7
+ name: "sb-random-quote",
8
+ description:
9
+ "A block that renders a random inspirational quote, using bundled defaults or a site-supplied list.",
10
+ version: "1.0.0",
11
+ keywords: [
12
+ "random quote",
13
+ "quote of the day",
14
+ "inspirational quote",
15
+ "sidebar quote",
16
+ "quotation",
17
+ ],
18
+ root: import.meta.dirname,
19
+ });
4
20
 
5
21
  export type Quote = {
6
22
  text: string;
@@ -0,0 +1,5 @@
1
+ [data-block="random-quote"] {
2
+ margin: 0;
3
+ padding: 0.75rem 1rem;
4
+ border-left: 3px solid currentColor;
5
+ }
@@ -0,0 +1,82 @@
1
+ # Sitemap plugin — agent playbook
2
+
3
+ ## Use when
4
+
5
+ The user asks for any of:
6
+
7
+ - sitemap, sitemap.xml, XML sitemap
8
+ - SEO crawl list, search engine indexing URLs
9
+ - static sitemap file in the public folder
10
+
11
+ ## Do not
12
+
13
+ - Hand-roll sitemap XML — use `createSitemap()` or the default export
14
+ - Put `/sitemap.xml` in `createPage()` — the plugin registers that route
15
+ - Forget to register the plugin on `createSite({ plugins })`
16
+
17
+ ## Exports
18
+
19
+ - **default export** — `createSitemap()` registration; pass to `createSite({ plugins })`
20
+ - `createSitemap(options?)` — factory when you need `baseUrl`, `extraUrls`, or `exclude`
21
+ - `renderSitemapXml(site, options?)` — shared XML renderer (fetch + build use this)
22
+ - `collectSitemapUrls(site, options?)` — absolute `<loc>` URLs
23
+ - `SitemapOptions` — type
24
+
25
+ ## API
26
+
27
+ ```ts
28
+ import sitemapPlugin, { createSitemap } from "@stackbox/cms/plugins/sitemap";
29
+
30
+ createSitemap({
31
+ baseUrl?: string, // defaults to siteConfig.config.url
32
+ extraUrls?: string[], // site-relative or absolute
33
+ exclude?: string[] | ((path) => boolean),
34
+ });
35
+ ```
36
+
37
+ **URLs included**
38
+
39
+ - Every `createPage()` path (origin + path)
40
+ - `extraUrls`
41
+ - Pages with `meta.robots` containing `noindex` are excluded
42
+ - Paths in `exclude` are dropped
43
+
44
+ **Serving and static file**
45
+
46
+ - `fetch("/sitemap.xml")` when the plugin is registered
47
+ - `stackbox-cms build` writes `{publicDir}/sitemap.xml` via the plugin `build` hook
48
+
49
+ ## Files to create or update
50
+
51
+ | File | Action |
52
+ | --- | --- |
53
+ | `server.ts` | Register the default export or `createSitemap(...)` in `createSite({ plugins })` |
54
+ | `site.config.ts` | Ensure `url` is set (used as sitemap origin unless `baseUrl` is passed) |
55
+ | `package.json` | Add `"build": "stackbox-cms build"` |
56
+
57
+ ## Wiring example
58
+
59
+ ```ts
60
+ // server.ts
61
+ import sitemapPlugin from "@stackbox/cms/plugins/sitemap";
62
+
63
+ export default createSite(siteConfig, {
64
+ pages: [homePage, aboutPage],
65
+ plugins: [sitemapPlugin],
66
+ });
67
+ ```
68
+
69
+ ```ts
70
+ // With extra URLs and exclusions
71
+ import { createSitemap } from "@stackbox/cms/plugins/sitemap";
72
+
73
+ export default createSite(siteConfig, {
74
+ pages: [homePage, aboutPage],
75
+ plugins: [
76
+ createSitemap({
77
+ extraUrls: ["/llms.txt"],
78
+ exclude: ["/thanks"],
79
+ }),
80
+ ],
81
+ });
82
+ ```
@@ -0,0 +1,156 @@
1
+ import { writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import {
4
+ createPlugin,
5
+ } from "../../plugin.js";
6
+ import { normalizePathname } from "../../routing.js";
7
+ import type { Stackbox as SB } from "../../types.js";
8
+
9
+ export type SitemapOptions = {
10
+ /** Site origin. Defaults to `siteConfig.config.url`. */
11
+ baseUrl?: string;
12
+ /** Extra site-relative or absolute URLs. */
13
+ extraUrls?: readonly string[];
14
+ exclude?: readonly string[] | ((path: string) => boolean);
15
+ };
16
+
17
+ function resolveBaseUrl(site: SB.Site, options: SitemapOptions): string {
18
+ const raw = options.baseUrl ?? site.siteConfig.config.url;
19
+ if (typeof raw !== "string" || raw.trim().length === 0) {
20
+ throw new Error("sb-sitemap: baseUrl or siteConfig.url is required");
21
+ }
22
+ const url = raw.trim().replace(/\/+$/, "");
23
+ try {
24
+ new URL(url);
25
+ } catch {
26
+ throw new Error(`sb-sitemap: invalid base URL "${raw}"`);
27
+ }
28
+ return url;
29
+ }
30
+
31
+ function isExcluded(path: string, options: SitemapOptions): boolean {
32
+ const normalized = normalizePathname(path);
33
+ if (!options.exclude) {
34
+ return false;
35
+ }
36
+ if (typeof options.exclude === "function") {
37
+ return options.exclude(normalized);
38
+ }
39
+ return options.exclude.some(
40
+ (entry) => normalizePathname(entry) === normalized,
41
+ );
42
+ }
43
+
44
+ function isNoindexPage(page: { meta?: { robots?: string } }): boolean {
45
+ const robots = page.meta?.robots?.toLowerCase() ?? "";
46
+ return robots.includes("noindex");
47
+ }
48
+
49
+ export function collectSitemapUrls(
50
+ site: SB.Site,
51
+ options: SitemapOptions = {},
52
+ ): string[] {
53
+ const base = resolveBaseUrl(site, options);
54
+ const locs = new Set<string>();
55
+
56
+ for (const page of site.pages) {
57
+ if (isNoindexPage(page)) {
58
+ continue;
59
+ }
60
+ if (isExcluded(page.path, options)) {
61
+ continue;
62
+ }
63
+ locs.add(`${base}${normalizePathname(page.path)}`);
64
+ }
65
+
66
+ for (const extra of options.extraUrls ?? []) {
67
+ if (extra.startsWith("http://") || extra.startsWith("https://")) {
68
+ if (!isExcluded(extra, options)) {
69
+ locs.add(extra);
70
+ }
71
+ continue;
72
+ }
73
+ const path = normalizePathname(extra);
74
+ if (!isExcluded(path, options)) {
75
+ locs.add(`${base}${path}`);
76
+ }
77
+ }
78
+
79
+ return [...locs].sort();
80
+ }
81
+
82
+ function escapeXml(text: string): string {
83
+ return text
84
+ .replace(/&/g, "&amp;")
85
+ .replace(/</g, "&lt;")
86
+ .replace(/>/g, "&gt;")
87
+ .replace(/"/g, "&quot;")
88
+ .replace(/'/g, "&apos;");
89
+ }
90
+
91
+ export function renderSitemapXml(
92
+ site: SB.Site,
93
+ options: SitemapOptions = {},
94
+ ): string {
95
+ const urls = collectSitemapUrls(site, options);
96
+ const body = urls
97
+ .map((loc) => ` <url>\n <loc>${escapeXml(loc)}</loc>\n </url>`)
98
+ .join("\n");
99
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${body}\n</urlset>\n`;
100
+ }
101
+
102
+ function sitemapResponse(
103
+ request: globalThis.Request,
104
+ xml: string,
105
+ ): globalThis.Response {
106
+ const headers = { "content-type": "application/xml; charset=utf-8" };
107
+ if (request.method === "HEAD") {
108
+ const bytes = new TextEncoder().encode(xml);
109
+ return new globalThis.Response(null, {
110
+ status: 200,
111
+ headers: { ...headers, "content-length": String(bytes.byteLength) },
112
+ });
113
+ }
114
+ return new globalThis.Response(xml, { status: 200, headers });
115
+ }
116
+
117
+ function createSitemapRoutes(
118
+ ctx: SB.PluginRouteContext,
119
+ options: SitemapOptions,
120
+ ) {
121
+ return [
122
+ {
123
+ path: "/sitemap.xml",
124
+ fetch(request: globalThis.Request) {
125
+ const xml = renderSitemapXml(ctx.site, options);
126
+ return sitemapResponse(request, xml);
127
+ },
128
+ },
129
+ ] as const;
130
+ }
131
+
132
+ export function createSitemap(options: SitemapOptions = {}): SB.Plugin {
133
+ return createPlugin({
134
+ name: "sb-sitemap",
135
+ description:
136
+ "Generate sitemap.xml from site pages for search engines and static deploys.",
137
+ version: "1.0.0",
138
+ keywords: [
139
+ "sitemap",
140
+ "sitemap.xml",
141
+ "seo",
142
+ "search engines",
143
+ "xml sitemap",
144
+ ],
145
+ root: import.meta.dirname,
146
+ routes(ctx) {
147
+ return createSitemapRoutes(ctx, options);
148
+ },
149
+ build(ctx) {
150
+ const xml = renderSitemapXml(ctx.site, options);
151
+ writeFileSync(join(ctx.publicDir, "sitemap.xml"), xml, "utf8");
152
+ },
153
+ });
154
+ }
155
+
156
+ export default createSitemap();
package/AGENTS.md DELETED
@@ -1,87 +0,0 @@
1
- # @stackbox/cms — agent instructions
2
-
3
- Stackbox is a code-first CMS that assembles TypeScript into a **fetch-handler-compatible server**. Use these conventions when building or extending a site.
4
-
5
- ## Site conventions
6
-
7
- | Primitive | Factory | Purpose |
8
- | --- | --- | --- |
9
- | Site config | `createSiteConfig(config)` | Definition-time settings shared by templates and pages |
10
- | Site | `createSite(siteConfig, { pages })` | Runtime router with `fetch(request, env)` |
11
- | Template | `createTemplate({ siteConfig, slots, render })` | Reusable layout with named slots |
12
- | Page | `createPage(template, { path, title, slots })` | A single URL built from a template + slot content |
13
- | Block | `createBlock({ name, render })` | A content block placed into a slot at request time |
14
-
15
- **Project layout:**
16
-
17
- ```
18
- site.config.ts # createSiteConfig
19
- server.ts # createSite(...) — default export is the fetch handler
20
- templates/ # shared createTemplate() layouts
21
- pages/ # createPage() per route or feature
22
- content/ # markdown or other bundle-time content (per feature)
23
- ```
24
-
25
- The default export from `server.ts` implements `fetch(request, env)` and returns a `Response`. It works on Cloudflare Workers, Bun, Deno, and any runtime that speaks the fetch-handler pattern.
26
-
27
- ## Plugins vs blocks
28
-
29
- - **Plugin** — a packaged use-case under `@stackbox/cms/plugins/<name>` (e.g. blog). May export factories, content objects, blocks, types, and helpers.
30
- - **Block** — a core primitive via `createBlock()`. Renders HTML into a template slot. Usable inside or outside plugins.
31
-
32
- Slot content is `Block | string`. Plugin content arrays can interleave blocks and HTML strings.
33
-
34
- ## Plugin catalog
35
-
36
- Before implementing a use-case (blog, newsletter, docs, …), check this table. If the user's request matches a row, **read only that plugin's AGENTS.md** and follow it. Do not invent a parallel implementation.
37
-
38
- | Plugin | Import | Read when the user mentions | Instructions |
39
- | --- | --- | --- | --- |
40
- | blog | `@stackbox/cms/plugins/blog` | blog, posts, articles, journal, markdown posts, blog listing, blog page | `src/plugins/blog/AGENTS.md` |
41
- | random-quote | `@stackbox/cms/plugins/random-quote` | random quote, quote of the day, inspirational quote, sidebar quote | `src/plugins/random-quote/AGENTS.md` |
42
-
43
- When adding a new plugin to this package, add a row here and create `src/plugins/<name>/AGENTS.md` using the same heading structure as the blog plugin. Document all export kinds (factory, types, blocks, helpers).
44
-
45
- ## Plugin public assets
46
-
47
- Runtime files that must be **publicly available** (images, CSS, fonts, JSON served over HTTP) go in:
48
-
49
- ```
50
- src/plugins/<name>/public_assets/
51
- ```
52
-
53
- **Opt-in:** only plugins with a `public_assets/` folder get copied at build time. Do not edit the copy script when adding files.
54
-
55
- Build copies each `public_assets/` folder to:
56
-
57
- - `dist/public/_sb/plugins/<name>/` — served at `/_sb/plugins/<name>/...`
58
- - `dist/plugins/<name>/public_assets/` — so `import "./public_assets/..." with { type: "json" }` works in compiled JS
59
-
60
- Use `pluginAssetPath()` from `@stackbox/cms/link` for `<img src>`, `<link href>`, etc. Do not put site files under `/_sb/` — that prefix is reserved for Stackbox plugin assets.
61
-
62
- ```ts
63
- import { pluginAssetPath } from "@stackbox/cms/link";
64
-
65
- pluginAssetPath("random-quote", "photo.jpg");
66
- // → "/_sb/plugins/random-quote/photo.jpg"
67
- ```
68
-
69
- For data bundled into JS at build time, import from `./public_assets/...` in the plugin's `index.ts`.
70
-
71
- ## For site agents
72
-
73
- If you are working in a **consumer site repo** (not this package), read this file from the installed package:
74
-
75
- ```
76
- node_modules/@stackbox/cms/AGENTS.md
77
- ```
78
-
79
- Recommended snippet for the site's own `AGENTS.md`:
80
-
81
- ```md
82
- This site uses @stackbox/cms. Before adding features, read
83
- `node_modules/@stackbox/cms/AGENTS.md` and follow its plugin catalog.
84
- Do not reimplement bundled plugins.
85
- ```
86
-
87
- When a request matches a catalog row, open **only** that plugin's instructions file (e.g. `node_modules/@stackbox/cms/src/plugins/blog/AGENTS.md`).
@@ -1,20 +0,0 @@
1
- import type { PageMeta } from "../../pages.js";
2
- import type { DefaultSlotContent } from "../../slot-content.js";
3
- import { type BlogOptions } from "./posts.js";
4
- export type { BlogPost, BlogOptions } from "./posts.js";
5
- export type BlogPostContent = {
6
- path: string;
7
- title: string;
8
- meta?: PageMeta;
9
- content: DefaultSlotContent[];
10
- };
11
- export type BlogListingContent = {
12
- path: string;
13
- content: DefaultSlotContent[];
14
- };
15
- export type Blog = {
16
- readonly posts: readonly BlogPostContent[];
17
- readonly listings: readonly BlogListingContent[];
18
- };
19
- export declare function createBlog(options: BlogOptions): Blog;
20
- //# sourceMappingURL=module.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/blog/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAa,KAAK,WAAW,EAAiB,MAAM,YAAY,CAAC;AAExE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAClD,CAAC;AAwDF,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAQrD"}
@@ -1,52 +0,0 @@
1
- import { loadPosts } from "./posts.js";
2
- function postToContent(post) {
3
- return {
4
- path: post.path,
5
- title: post.title,
6
- meta: post.description ? { description: post.description } : undefined,
7
- content: [
8
- `<article data-content-type="article" data-slug="${post.slug}">
9
- <h1>${post.title}</h1>
10
- ${post.bodyHtml}
11
- </article>`,
12
- ],
13
- };
14
- }
15
- function listingPath(pathPrefix, page) {
16
- return page === 1 ? pathPrefix : `${pathPrefix}/page/${page}`;
17
- }
18
- function buildPostListHtml(posts) {
19
- return `<ul>${posts
20
- .map((post) => `<li><a href="${post.path}">${post.title}</a></li>`)
21
- .join("")}</ul>`;
22
- }
23
- function buildListingPages(posts, pathPrefix, postsPerPage) {
24
- if (posts.length === 0) {
25
- return [
26
- {
27
- path: pathPrefix,
28
- content: ["<p>No blog posts found.</p>"],
29
- },
30
- ];
31
- }
32
- const perPage = postsPerPage && postsPerPage > 0 ? postsPerPage : posts.length;
33
- const pages = [];
34
- for (let i = 0; i < posts.length; i += perPage) {
35
- const chunk = posts.slice(i, i + perPage);
36
- const page = i / perPage + 1;
37
- pages.push({
38
- path: listingPath(pathPrefix, page),
39
- content: [buildPostListHtml(chunk)],
40
- });
41
- }
42
- return pages;
43
- }
44
- export function createBlog(options) {
45
- const loaded = loadPosts(options);
46
- const pathPrefix = options.pathPrefix.replace(/\/+$/, "") || "/";
47
- return {
48
- posts: loaded.map(postToContent),
49
- listings: buildListingPages(loaded, pathPrefix, options.postsPerPage),
50
- };
51
- }
52
- //# sourceMappingURL=module.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/modules/blog/module.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAmC,MAAM,YAAY,CAAC;AAqBxE,SAAS,aAAa,CAAC,IAAc;IACnC,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QACtE,OAAO,EAAE;YACP,mDAAmD,IAAI,CAAC,IAAI;QAC1D,IAAI,CAAC,KAAK;IACd,IAAI,CAAC,QAAQ;WACN;SACN;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,IAAY;IACnD,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,SAAS,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB;IAC1C,OAAO,OAAO,KAAK;SAChB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,WAAW,CAAC;SAClE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAiB,EACjB,UAAkB,EAClB,YAAqB;IAErB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL;gBACE,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,CAAC,6BAA6B,CAAC;aACzC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,YAAY,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACjE,MAAM,KAAK,GAAyB,EAAE,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC;YACnC,OAAO,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IAEjE,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QAChC,QAAQ,EAAE,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC;KACtE,CAAC;AACJ,CAAC"}
@@ -1,15 +0,0 @@
1
- export type BlogPost = {
2
- slug: string;
3
- title: string;
4
- description?: string;
5
- path: string;
6
- bodyHtml: string;
7
- };
8
- export type BlogOptions = {
9
- contentPath: string;
10
- pathPrefix: string;
11
- /** Max posts per listing page. Omit to put all posts on one page. */
12
- postsPerPage?: number;
13
- };
14
- export declare function loadPosts(options: BlogOptions): BlogPost[];
15
- //# sourceMappingURL=posts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../../src/modules/blog/posts.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA8BF,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,EAAE,CAqB1D"}
@@ -1,46 +0,0 @@
1
- import { readFileSync, readdirSync } from "node:fs";
2
- import { basename, extname, join, resolve } from "node:path";
3
- import { marked } from "marked";
4
- function parseFrontmatter(raw) {
5
- if (!raw.startsWith("---")) {
6
- return { meta: {}, body: raw };
7
- }
8
- const end = raw.indexOf("\n---", 3);
9
- if (end === -1) {
10
- return { meta: {}, body: raw };
11
- }
12
- const frontmatter = raw.slice(3, end).trim();
13
- const body = raw.slice(end + 4).replace(/^\n/, "");
14
- const meta = {};
15
- for (const line of frontmatter.split("\n")) {
16
- const colon = line.indexOf(":");
17
- if (colon === -1)
18
- continue;
19
- const key = line.slice(0, colon).trim();
20
- const value = line.slice(colon + 1).trim().replace(/^["']|["']$/g, "");
21
- if (key)
22
- meta[key] = value;
23
- }
24
- return { meta, body };
25
- }
26
- export function loadPosts(options) {
27
- const absoluteDir = resolve(options.contentPath);
28
- const files = readdirSync(absoluteDir)
29
- .filter((name) => extname(name) === ".md")
30
- .sort();
31
- return files.map((filename) => {
32
- const raw = readFileSync(join(absoluteDir, filename), "utf8");
33
- const { meta, body } = parseFrontmatter(raw);
34
- const slug = meta.slug ?? basename(filename, ".md");
35
- const title = meta.title ?? slug;
36
- const prefix = options.pathPrefix.replace(/\/+$/, "");
37
- return {
38
- slug,
39
- title,
40
- description: meta.description,
41
- path: `${prefix}/${slug}`,
42
- bodyHtml: marked.parse(body),
43
- };
44
- });
45
- }
46
- //# sourceMappingURL=posts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"posts.js","sourceRoot":"","sources":["../../../src/modules/blog/posts.ts"],"names":[],"mappings":"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"}
package/dist/modules.d.ts DELETED
@@ -1,18 +0,0 @@
1
- import type { RenderContext } from "./pages.js";
2
- import type { HSHtml } from "@hyperspan/html";
3
- export type ModuleRenderResult = HSHtml | Promise<HSHtml>;
4
- export type Module = {
5
- readonly __kind: "module";
6
- readonly name: string;
7
- render(ctx: RenderContext): ModuleRenderResult;
8
- };
9
- type ModuleDef<TOptions = undefined> = {
10
- name: string;
11
- render(options: TOptions, ctx?: RenderContext): ModuleRenderResult;
12
- };
13
- export type ModuleOptionsOf<F> = F extends (options?: infer O) => unknown ? [O] extends [undefined] ? undefined : O : never;
14
- export type ModuleFactory<TOptions = undefined> = (options?: TOptions) => Module;
15
- export declare function createModule<TOptions = undefined>(def: ModuleDef<TOptions>): ModuleFactory<TOptions>;
16
- export declare function isModule(value: unknown): value is Module;
17
- export {};
18
- //# sourceMappingURL=modules.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,kBAAkB,CAAC;CAChD,CAAC;AAEF,KAAK,SAAS,CAAC,QAAQ,GAAG,SAAS,IAAI;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,kBAAkB,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,GACrE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GACrB,SAAS,GACT,CAAC,GACH,KAAK,CAAC;AAEV,MAAM,MAAM,aAAa,CAAC,QAAQ,GAAG,SAAS,IAAI,CAChD,OAAO,CAAC,EAAE,QAAQ,KACf,MAAM,CAAC;AAQZ,wBAAgB,YAAY,CAAC,QAAQ,GAAG,SAAS,EAC/C,GAAG,EAAE,SAAS,CAAC,QAAQ,CAAC,GACvB,aAAa,CAAC,QAAQ,CAAC,CAYzB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CASxD"}
package/dist/modules.js DELETED
@@ -1,25 +0,0 @@
1
- function validateModuleName(name) {
2
- if (!name || name.length === 0) {
3
- throw new Error("createModule(def): name is required");
4
- }
5
- }
6
- export function createModule(def) {
7
- validateModuleName(def.name);
8
- if (typeof def.render !== "function") {
9
- throw new Error("createModule(def): render is required");
10
- }
11
- return ((options) => ({
12
- __kind: "module",
13
- name: def.name,
14
- render: (ctx) => def.render(options, ctx),
15
- }));
16
- }
17
- export function isModule(value) {
18
- return (typeof value === "object" &&
19
- value !== null &&
20
- value.__kind === "module" &&
21
- typeof value.name === "string" &&
22
- value.name.length > 0 &&
23
- typeof value.render === "function");
24
- }
25
- //# sourceMappingURL=modules.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AA0BA,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAAwB;IAExB,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,CAAC,OAAkB,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,EAAE,QAAiB;QACzB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,MAAM,EAAE,CAAC,GAAkB,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,OAAmB,EAAE,GAAG,CAAC;KACrE,CAAC,CAA4B,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAgB,CAAC,MAAM,KAAK,QAAQ;QACrC,OAAQ,KAAgB,CAAC,IAAI,KAAK,QAAQ;QACzC,KAAgB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QACjC,OAAQ,KAAgB,CAAC,MAAM,KAAK,UAAU,CAC/C,CAAC;AACJ,CAAC"}
@@ -1,20 +0,0 @@
1
- import type { PageMeta } from "../../pages.js";
2
- import type { DefaultSlotContent } from "../../slot-content.js";
3
- import { type BlogOptions } from "./posts.js";
4
- export type { BlogPost, BlogOptions } from "./posts.js";
5
- export type BlogPostContent = {
6
- path: string;
7
- title: string;
8
- meta?: PageMeta;
9
- content: DefaultSlotContent[];
10
- };
11
- export type BlogListingContent = {
12
- path: string;
13
- content: DefaultSlotContent[];
14
- };
15
- export type Blog = {
16
- readonly posts: readonly BlogPostContent[];
17
- readonly listings: readonly BlogListingContent[];
18
- };
19
- export declare function createBlog(options: BlogOptions): Blog;
20
- //# sourceMappingURL=module.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/plugins/blog/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAa,KAAK,WAAW,EAAiB,MAAM,YAAY,CAAC;AAExE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAClD,CAAC;AAwDF,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAQrD"}
@@ -1,52 +0,0 @@
1
- import { loadPosts } from "./posts.js";
2
- function postToContent(post) {
3
- return {
4
- path: post.path,
5
- title: post.title,
6
- meta: post.description ? { description: post.description } : undefined,
7
- content: [
8
- `<article data-content-type="article" data-slug="${post.slug}">
9
- <h1>${post.title}</h1>
10
- ${post.bodyHtml}
11
- </article>`,
12
- ],
13
- };
14
- }
15
- function listingPath(pathPrefix, page) {
16
- return page === 1 ? pathPrefix : `${pathPrefix}/page/${page}`;
17
- }
18
- function buildPostListHtml(posts) {
19
- return `<ul>${posts
20
- .map((post) => `<li><a href="${post.path}">${post.title}</a></li>`)
21
- .join("")}</ul>`;
22
- }
23
- function buildListingPages(posts, pathPrefix, postsPerPage) {
24
- if (posts.length === 0) {
25
- return [
26
- {
27
- path: pathPrefix,
28
- content: ["<p>No blog posts found.</p>"],
29
- },
30
- ];
31
- }
32
- const perPage = postsPerPage && postsPerPage > 0 ? postsPerPage : posts.length;
33
- const pages = [];
34
- for (let i = 0; i < posts.length; i += perPage) {
35
- const chunk = posts.slice(i, i + perPage);
36
- const page = i / perPage + 1;
37
- pages.push({
38
- path: listingPath(pathPrefix, page),
39
- content: [buildPostListHtml(chunk)],
40
- });
41
- }
42
- return pages;
43
- }
44
- export function createBlog(options) {
45
- const loaded = loadPosts(options);
46
- const pathPrefix = options.pathPrefix.replace(/\/+$/, "") || "/";
47
- return {
48
- posts: loaded.map(postToContent),
49
- listings: buildListingPages(loaded, pathPrefix, options.postsPerPage),
50
- };
51
- }
52
- //# sourceMappingURL=module.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/plugins/blog/module.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAmC,MAAM,YAAY,CAAC;AAqBxE,SAAS,aAAa,CAAC,IAAc;IACnC,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QACtE,OAAO,EAAE;YACP,mDAAmD,IAAI,CAAC,IAAI;QAC1D,IAAI,CAAC,KAAK;IACd,IAAI,CAAC,QAAQ;WACN;SACN;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,IAAY;IACnD,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,SAAS,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB;IAC1C,OAAO,OAAO,KAAK;SAChB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,WAAW,CAAC;SAClE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAiB,EACjB,UAAkB,EAClB,YAAqB;IAErB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL;gBACE,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,CAAC,6BAA6B,CAAC;aACzC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,YAAY,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACjE,MAAM,KAAK,GAAyB,EAAE,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC;YACnC,OAAO,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IAEjE,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QAChC,QAAQ,EAAE,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC;KACtE,CAAC;AACJ,CAAC"}