@stackbox/cms 0.0.4 → 0.0.5

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 (113) hide show
  1. package/dist/blocks.d.ts +18 -0
  2. package/dist/blocks.d.ts.map +1 -0
  3. package/dist/blocks.js +25 -0
  4. package/dist/blocks.js.map +1 -0
  5. package/dist/index.d.ts +12 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +12 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/link.d.ts +10 -0
  10. package/dist/link.d.ts.map +1 -0
  11. package/dist/link.js +128 -0
  12. package/dist/link.js.map +1 -0
  13. package/dist/modules/blog/module.d.ts +20 -0
  14. package/dist/modules/blog/module.d.ts.map +1 -0
  15. package/dist/modules/blog/module.js +52 -0
  16. package/dist/modules/blog/module.js.map +1 -0
  17. package/dist/modules/blog/posts.d.ts +15 -0
  18. package/dist/modules/blog/posts.d.ts.map +1 -0
  19. package/dist/modules/blog/posts.js +46 -0
  20. package/dist/modules/blog/posts.js.map +1 -0
  21. package/dist/modules.d.ts +18 -0
  22. package/dist/modules.d.ts.map +1 -0
  23. package/dist/modules.js +25 -0
  24. package/dist/modules.js.map +1 -0
  25. package/dist/pages.d.ts +55 -0
  26. package/dist/pages.d.ts.map +1 -0
  27. package/dist/pages.js +85 -0
  28. package/dist/pages.js.map +1 -0
  29. package/dist/plugins/blog/index.d.ts +20 -0
  30. package/dist/plugins/blog/index.d.ts.map +1 -0
  31. package/dist/plugins/blog/index.js +52 -0
  32. package/dist/plugins/blog/index.js.map +1 -0
  33. package/dist/plugins/blog/module.d.ts +20 -0
  34. package/dist/plugins/blog/module.d.ts.map +1 -0
  35. package/dist/plugins/blog/module.js +52 -0
  36. package/dist/plugins/blog/module.js.map +1 -0
  37. package/dist/plugins/blog/plugin.d.ts +20 -0
  38. package/dist/plugins/blog/plugin.d.ts.map +1 -0
  39. package/dist/plugins/blog/plugin.js +52 -0
  40. package/dist/plugins/blog/plugin.js.map +1 -0
  41. package/dist/plugins/blog/posts.d.ts +15 -0
  42. package/dist/plugins/blog/posts.d.ts.map +1 -0
  43. package/dist/plugins/blog/posts.js +46 -0
  44. package/dist/plugins/blog/posts.js.map +1 -0
  45. package/dist/plugins/random-quote/index.d.ts +12 -0
  46. package/dist/plugins/random-quote/index.d.ts.map +1 -0
  47. package/dist/plugins/random-quote/index.js +21 -0
  48. package/dist/plugins/random-quote/index.js.map +1 -0
  49. package/dist/plugins/random-quote/module.d.ts +9 -0
  50. package/dist/plugins/random-quote/module.d.ts.map +1 -0
  51. package/dist/plugins/random-quote/module.js +31 -0
  52. package/dist/plugins/random-quote/module.js.map +1 -0
  53. package/dist/plugins/random-quote/plugin.d.ts +8 -0
  54. package/dist/plugins/random-quote/plugin.d.ts.map +1 -0
  55. package/dist/plugins/random-quote/plugin.js +31 -0
  56. package/dist/plugins/random-quote/plugin.js.map +1 -0
  57. package/dist/plugins/random-quote/public_assets/quotes.json +230 -0
  58. package/dist/plugins/random-quote/quotes.json +230 -0
  59. package/dist/public/_sb/plugins/random-quote/quotes.json +230 -0
  60. package/dist/render-head.d.ts +7 -0
  61. package/dist/render-head.d.ts.map +1 -0
  62. package/dist/render-head.js +27 -0
  63. package/dist/render-head.js.map +1 -0
  64. package/dist/render-page.d.ts +6 -0
  65. package/dist/render-page.d.ts.map +1 -0
  66. package/dist/render-page.js +30 -0
  67. package/dist/render-page.js.map +1 -0
  68. package/dist/routing.d.ts +3 -0
  69. package/dist/routing.d.ts.map +1 -0
  70. package/dist/routing.js +11 -0
  71. package/dist/routing.js.map +1 -0
  72. package/dist/site.d.ts +21 -0
  73. package/dist/site.d.ts.map +1 -0
  74. package/dist/site.js +102 -0
  75. package/dist/site.js.map +1 -0
  76. package/dist/slot-content.d.ts +30 -0
  77. package/dist/slot-content.d.ts.map +1 -0
  78. package/dist/slot-content.js +34 -0
  79. package/dist/slot-content.js.map +1 -0
  80. package/dist/slot-handle.d.ts +32 -0
  81. package/dist/slot-handle.d.ts.map +1 -0
  82. package/dist/slot-handle.js +68 -0
  83. package/dist/slot-handle.js.map +1 -0
  84. package/dist/stackbox/context.d.ts +52 -0
  85. package/dist/stackbox/context.d.ts.map +1 -0
  86. package/dist/stackbox/context.js +165 -0
  87. package/dist/stackbox/context.js.map +1 -0
  88. package/dist/templates.d.ts +63 -0
  89. package/dist/templates.d.ts.map +1 -0
  90. package/dist/templates.js +106 -0
  91. package/dist/templates.js.map +1 -0
  92. package/package.json +7 -2
  93. package/.claude/settings.local.json +0 -8
  94. package/scripts/copy-plugin-assets.mjs +0 -30
  95. package/src/blocks.ts +0 -58
  96. package/src/index.ts +0 -67
  97. package/src/link.ts +0 -158
  98. package/src/pages.ts +0 -198
  99. package/src/render-head.ts +0 -32
  100. package/src/render-page.ts +0 -51
  101. package/src/routing.ts +0 -14
  102. package/src/site.ts +0 -160
  103. package/src/slot-content.ts +0 -77
  104. package/src/slot-handle.ts +0 -131
  105. package/src/stackbox/context.ts +0 -257
  106. package/src/templates.ts +0 -230
  107. package/test/async-render.test.ts +0 -103
  108. package/test/blog.test.ts +0 -93
  109. package/test/fetch-routing.test.ts +0 -76
  110. package/test/plugin-assets.test.ts +0 -80
  111. package/test/random-quote.test.ts +0 -55
  112. package/test/stackbox-context.test.ts +0 -44
  113. package/tsconfig.json +0 -20
@@ -0,0 +1,18 @@
1
+ import type { RenderContext } from "./pages.js";
2
+ import type { HSHtml } from "@hyperspan/html";
3
+ export type BlockRenderResult = HSHtml | Promise<HSHtml>;
4
+ export type Block = {
5
+ readonly __kind: "block";
6
+ readonly name: string;
7
+ render(ctx: RenderContext): BlockRenderResult;
8
+ };
9
+ type BlockDef<TOptions = undefined> = {
10
+ name: string;
11
+ render(options: TOptions, ctx?: RenderContext): BlockRenderResult;
12
+ };
13
+ export type BlockOptionsOf<F> = F extends (options?: infer O) => unknown ? [O] extends [undefined] ? undefined : O : never;
14
+ export type BlockFactory<TOptions = undefined> = (options?: TOptions) => Block;
15
+ export declare function createBlock<TOptions = undefined>(def: BlockDef<TOptions>): BlockFactory<TOptions>;
16
+ export declare function isBlock(value: unknown): value is Block;
17
+ export {};
18
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,iBAAiB,CAAC;CAC/C,CAAC;AAEF,KAAK,QAAQ,CAAC,QAAQ,GAAG,SAAS,IAAI;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,iBAAiB,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,GACpE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GACrB,SAAS,GACT,CAAC,GACH,KAAK,CAAC;AAEV,MAAM,MAAM,YAAY,CAAC,QAAQ,GAAG,SAAS,IAAI,CAC/C,OAAO,CAAC,EAAE,QAAQ,KACf,KAAK,CAAC;AAQX,wBAAgB,WAAW,CAAC,QAAQ,GAAG,SAAS,EAC9C,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,GACtB,YAAY,CAAC,QAAQ,CAAC,CAYxB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAStD"}
package/dist/blocks.js ADDED
@@ -0,0 +1,25 @@
1
+ function validateBlockName(name) {
2
+ if (!name || name.length === 0) {
3
+ throw new Error("createBlock(def): name is required");
4
+ }
5
+ }
6
+ export function createBlock(def) {
7
+ validateBlockName(def.name);
8
+ if (typeof def.render !== "function") {
9
+ throw new Error("createBlock(def): render is required");
10
+ }
11
+ return ((options) => ({
12
+ __kind: "block",
13
+ name: def.name,
14
+ render: (ctx) => def.render(options, ctx),
15
+ }));
16
+ }
17
+ export function isBlock(value) {
18
+ return (typeof value === "object" &&
19
+ value !== null &&
20
+ value.__kind === "block" &&
21
+ typeof value.name === "string" &&
22
+ value.name.length > 0 &&
23
+ typeof value.render === "function");
24
+ }
25
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AA0BA,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,GAAuB;IAEvB,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE5B,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,CAAC,CAAC,OAAkB,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,EAAE,OAAgB;QACxB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,MAAM,EAAE,CAAC,GAAkB,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,OAAmB,EAAE,GAAG,CAAC;KACrE,CAAC,CAA2B,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAe,CAAC,MAAM,KAAK,OAAO;QACnC,OAAQ,KAAe,CAAC,IAAI,KAAK,QAAQ;QACxC,KAAe,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAChC,OAAQ,KAAe,CAAC,MAAM,KAAK,UAAU,CAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { html } from "@hyperspan/html";
2
+ export { createBlock, isBlock, type Block, type BlockFactory, type BlockOptionsOf, type BlockRenderResult, } from "./blocks.js";
3
+ export { createPage, isPage, PageValidationError, toPageRenderView, validateSlotContentItem, type Page, type PageMeta, type PageRenderView, type RenderContext, type SitePage, } from "./pages.js";
4
+ export { renderStandardHead } from "./render-head.js";
5
+ export { renderPage, RenderError } from "./render-page.js";
6
+ export { matchPagePath, normalizePathname } from "./routing.js";
7
+ export { createSite, createSiteConfig, isSite, isSiteConfig, SiteError, type Site, type SiteConfig, } from "./site.js";
8
+ export { createContext, Stackbox } from "./stackbox/context.js";
9
+ export { anySlotContentSchema, blockSlotContentSchema, slotHasContent, SlotContentValidationError, stringSlotContentSchema, type DefaultSlotContent, type PageSlotsInput, type SlotContentFromDefinition, } from "./slot-content.js";
10
+ export { buildPageSlots, buildStubSlots, renderSlotContent, slotSentinel, SLOT_SENTINEL_PREFIX, type Slot, type SlotRenderValue, type TemplateSlotsFrom, } from "./slot-handle.js";
11
+ export { createTemplate, isTemplate, TemplateBuildError, type RequiredSlotNamesFrom, type SlotDefinition, type SlotMeta, type SlotNamesFrom, type SlotOptions, type TemplateDescriptor, type TemplateRenderContext, type TemplateRenderFn, } from "./templates.js";
12
+ //# 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,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,WAAW,EACX,OAAO,EACP,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,MAAM,EACN,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,YAAY,EACZ,SAAS,EACT,KAAK,IAAI,EACT,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,0BAA0B,EAC1B,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,KAAK,IAAI,EACT,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export { html } from "@hyperspan/html";
2
+ export { createBlock, isBlock, } from "./blocks.js";
3
+ export { createPage, isPage, PageValidationError, toPageRenderView, validateSlotContentItem, } from "./pages.js";
4
+ export { renderStandardHead } from "./render-head.js";
5
+ export { renderPage, RenderError } from "./render-page.js";
6
+ export { matchPagePath, normalizePathname } from "./routing.js";
7
+ export { createSite, createSiteConfig, isSite, isSiteConfig, SiteError, } from "./site.js";
8
+ export { createContext } from "./stackbox/context.js";
9
+ export { anySlotContentSchema, blockSlotContentSchema, slotHasContent, SlotContentValidationError, stringSlotContentSchema, } from "./slot-content.js";
10
+ export { buildPageSlots, buildStubSlots, renderSlotContent, slotSentinel, SLOT_SENTINEL_PREFIX, } from "./slot-handle.js";
11
+ export { createTemplate, isTemplate, TemplateBuildError, } from "./templates.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,WAAW,EACX,OAAO,GAKR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,MAAM,EACN,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,GAMxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,YAAY,EACZ,SAAS,GAGV,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAY,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,0BAA0B,EAC1B,uBAAuB,GAIxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,GAIrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,UAAU,EACV,kBAAkB,GASnB,MAAM,gBAAgB,CAAC"}
package/dist/link.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export declare const PLUGIN_PUBLIC_PREFIX = "/_sb/plugins";
2
+ export declare function pluginAssetPath(pluginName: string, relativePath: string): string;
3
+ export type PluginAssetRequest = {
4
+ plugin: string;
5
+ relativePath: string;
6
+ };
7
+ export declare function parsePluginAssetRequest(pathname: string): PluginAssetRequest | null;
8
+ export declare function getPluginPublicRootDir(): string;
9
+ export declare function servePluginAsset(pathname: string, method: string): globalThis.Response | null;
10
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AA8BnD,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAShF;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI,CAkC3B;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAa/C;AAwBD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,UAAU,CAAC,QAAQ,GAAG,IAAI,CA4B5B"}
package/dist/link.js ADDED
@@ -0,0 +1,128 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join, normalize, sep } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { normalizePathname } from "./routing.js";
5
+ export const PLUGIN_PUBLIC_PREFIX = "/_sb/plugins";
6
+ const CONTENT_TYPES = {
7
+ ".css": "text/css; charset=utf-8",
8
+ ".gif": "image/gif",
9
+ ".html": "text/html; charset=utf-8",
10
+ ".jpeg": "image/jpeg",
11
+ ".jpg": "image/jpeg",
12
+ ".js": "text/javascript; charset=utf-8",
13
+ ".json": "application/json; charset=utf-8",
14
+ ".png": "image/png",
15
+ ".svg": "image/svg+xml",
16
+ ".txt": "text/plain; charset=utf-8",
17
+ ".webp": "image/webp",
18
+ ".woff": "font/woff",
19
+ ".woff2": "font/woff2",
20
+ };
21
+ function assertSafeSegment(segment, label) {
22
+ if (!segment ||
23
+ segment === "." ||
24
+ segment === ".." ||
25
+ segment.includes("/") ||
26
+ segment.includes("\\")) {
27
+ throw new Error(`pluginAssetPath: invalid ${label}`);
28
+ }
29
+ }
30
+ export function pluginAssetPath(pluginName, relativePath) {
31
+ assertSafeSegment(pluginName, "plugin name");
32
+ const segments = relativePath
33
+ .split(/[/\\]+/)
34
+ .filter((segment) => segment.length > 0);
35
+ for (const segment of segments) {
36
+ assertSafeSegment(segment, "relative path segment");
37
+ }
38
+ return `${PLUGIN_PUBLIC_PREFIX}/${pluginName}/${segments.join("/")}`;
39
+ }
40
+ export function parsePluginAssetRequest(pathname) {
41
+ const normalized = normalizePathname(pathname);
42
+ const prefix = `${PLUGIN_PUBLIC_PREFIX}/`;
43
+ if (!normalized.startsWith(prefix)) {
44
+ return null;
45
+ }
46
+ const rest = normalized.slice(prefix.length);
47
+ const slash = rest.indexOf("/");
48
+ if (slash <= 0 || slash === rest.length - 1) {
49
+ return null;
50
+ }
51
+ const plugin = rest.slice(0, slash);
52
+ const relativePath = rest.slice(slash + 1);
53
+ if (!plugin ||
54
+ !relativePath ||
55
+ relativePath.includes("..") ||
56
+ relativePath.includes("\\")) {
57
+ return null;
58
+ }
59
+ try {
60
+ assertSafeSegment(plugin, "plugin name");
61
+ for (const segment of relativePath.split("/")) {
62
+ assertSafeSegment(segment, "relative path segment");
63
+ }
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ return { plugin, relativePath };
69
+ }
70
+ export function getPluginPublicRootDir() {
71
+ const here = dirname(fileURLToPath(import.meta.url));
72
+ const fromDist = join(here, "public", "_sb", "plugins");
73
+ if (existsSync(fromDist)) {
74
+ return fromDist;
75
+ }
76
+ const fromSrcDev = join(here, "..", "dist", "public", "_sb", "plugins");
77
+ if (existsSync(fromSrcDev)) {
78
+ return fromSrcDev;
79
+ }
80
+ return fromDist;
81
+ }
82
+ function contentTypeForPath(relativePath) {
83
+ const dot = relativePath.lastIndexOf(".");
84
+ if (dot === -1) {
85
+ return "application/octet-stream";
86
+ }
87
+ return CONTENT_TYPES[relativePath.slice(dot).toLowerCase()] ??
88
+ "application/octet-stream";
89
+ }
90
+ function resolvePluginAssetFile(request) {
91
+ const root = getPluginPublicRootDir();
92
+ const absolute = normalize(join(root, request.plugin, request.relativePath));
93
+ const rootWithSep = root.endsWith(sep) ? root : `${root}${sep}`;
94
+ if (!absolute.startsWith(rootWithSep)) {
95
+ return null;
96
+ }
97
+ if (!existsSync(absolute)) {
98
+ return null;
99
+ }
100
+ return absolute;
101
+ }
102
+ export function servePluginAsset(pathname, method) {
103
+ const request = parsePluginAssetRequest(pathname);
104
+ if (!request) {
105
+ return null;
106
+ }
107
+ const filePath = resolvePluginAssetFile(request);
108
+ if (!filePath) {
109
+ return new globalThis.Response("Not Found", { status: 404 });
110
+ }
111
+ const contentType = contentTypeForPath(request.relativePath);
112
+ if (method === "HEAD") {
113
+ const body = readFileSync(filePath);
114
+ return new globalThis.Response(null, {
115
+ status: 200,
116
+ headers: {
117
+ "content-type": contentType,
118
+ "content-length": String(body.byteLength),
119
+ },
120
+ });
121
+ }
122
+ const body = readFileSync(filePath);
123
+ return new globalThis.Response(body, {
124
+ status: 200,
125
+ headers: { "content-type": contentType },
126
+ });
127
+ }
128
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAEnD,MAAM,aAAa,GAA2B;IAC5C,MAAM,EAAE,yBAAyB;IACjC,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,0BAA0B;IACnC,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,gCAAgC;IACvC,OAAO,EAAE,iCAAiC;IAC1C,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,2BAA2B;IACnC,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,WAAW;IACpB,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF,SAAS,iBAAiB,CAAC,OAAe,EAAE,KAAa;IACvD,IACE,CAAC,OAAO;QACR,OAAO,KAAK,GAAG;QACf,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EACtB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAkB,EAAE,YAAoB;IACtE,iBAAiB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,YAAY;SAC1B,KAAK,CAAC,QAAQ,CAAC;SACf,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,iBAAiB,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,GAAG,oBAAoB,IAAI,UAAU,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACvE,CAAC;AAOD,MAAM,UAAU,uBAAuB,CACrC,QAAgB;IAEhB,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,GAAG,oBAAoB,GAAG,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC3C,IACE,CAAC,MAAM;QACP,CAAC,YAAY;QACb,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC3B,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC3B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACzC,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,iBAAiB,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACxE,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB,CAAC,YAAoB;IAC9C,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,OAAO,0BAA0B,CAAC;IACpC,CAAC;IACD,OAAO,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,0BAA0B,CAAC;AAC/B,CAAC;AAED,SAAS,sBAAsB,CAAC,OAA2B;IACzD,MAAM,IAAI,GAAG,sBAAsB,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC;IAChE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,MAAc;IAEd,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE;YACnC,MAAM,EAAE,GAAG;YACX,OAAO,EAAE;gBACP,cAAc,EAAE,WAAW;gBAC3B,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;aAC1C;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE;QACnC,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE;KACzC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,20 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,52 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,15 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,46 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posts.js","sourceRoot":"","sources":["../../../src/modules/blog/posts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,25 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,55 @@
1
+ import type { SiteConfig } from "./site.js";
2
+ import type { Stackbox } from "./stackbox/context.js";
3
+ import { type SlotDefinition, type SlotNamesFrom, type RequiredSlotNamesFrom, type TemplateDescriptor } from "./templates.js";
4
+ import { type DefaultSlotContent, type PageSlotsInput } from "./slot-content.js";
5
+ export type PageMeta = {
6
+ description?: string;
7
+ robots?: string;
8
+ canonical?: string;
9
+ ogTitle?: string;
10
+ ogDescription?: string;
11
+ ogImage?: string;
12
+ twitterCard?: string;
13
+ };
14
+ export type RenderContext = {
15
+ siteConfig: SiteConfig;
16
+ ctx?: Stackbox.Context;
17
+ };
18
+ export type Page<Slots extends string = string, RequiredSlots extends Slots = never, Definitions extends readonly SlotDefinition[] = readonly SlotDefinition[]> = {
19
+ readonly __kind: "page";
20
+ path: string;
21
+ template: TemplateDescriptor<Slots, RequiredSlots, Definitions>;
22
+ title: string;
23
+ meta?: PageMeta;
24
+ slots: PageSlotsInput<Definitions, RequiredSlots>;
25
+ };
26
+ /** Widened page type for site builds mixing templates and required slots. */
27
+ export type SitePage = {
28
+ readonly __kind: "page";
29
+ path: string;
30
+ template: TemplateDescriptor<string, string>;
31
+ title: string;
32
+ meta?: PageMeta;
33
+ slots: Partial<Record<string, DefaultSlotContent[]>>;
34
+ };
35
+ /** Page fields passed to template render (slot content lives on `slots`). */
36
+ export type PageRenderView = Omit<Page, "template" | "slots">;
37
+ export declare function toPageRenderView({ template: _template, slots: _slots, ...view }: SitePage): PageRenderView;
38
+ export declare function isPage(value: unknown): value is Page;
39
+ export declare class PageValidationError extends Error {
40
+ constructor(message: string);
41
+ }
42
+ export declare function createPage(template: TemplateDescriptor<string, string>, def: {
43
+ path: string;
44
+ title: string;
45
+ meta?: PageMeta;
46
+ slots: Partial<Record<string, DefaultSlotContent[]>>;
47
+ }): SitePage;
48
+ export declare function createPage<const S extends readonly SlotDefinition[]>(template: TemplateDescriptor<SlotNamesFrom<S>, RequiredSlotNamesFrom<S>, S>, def: {
49
+ path: string;
50
+ title: string;
51
+ meta?: PageMeta;
52
+ slots: PageSlotsInput<S, RequiredSlotNamesFrom<S>>;
53
+ }): Page<SlotNamesFrom<S>, RequiredSlotNamesFrom<S>, S>;
54
+ export { validateSlotContentItem } from "./slot-content.js";
55
+ //# sourceMappingURL=pages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"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"}
package/dist/pages.js ADDED
@@ -0,0 +1,85 @@
1
+ import { isTemplate, } from "./templates.js";
2
+ import { slotHasContent, SlotContentValidationError, validateSlotContentItem, } from "./slot-content.js";
3
+ export function toPageRenderView({ template: _template, slots: _slots, ...view }) {
4
+ return view;
5
+ }
6
+ export function isPage(value) {
7
+ return (typeof value === "object" &&
8
+ value !== null &&
9
+ value.__kind === "page" &&
10
+ typeof value.path === "string" &&
11
+ value.path.length > 0 &&
12
+ isTemplate(value.template) &&
13
+ typeof value.title === "string" &&
14
+ value.title.length > 0 &&
15
+ typeof value.slots === "object" &&
16
+ value.slots !== null);
17
+ }
18
+ export class PageValidationError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = "PageValidationError";
22
+ }
23
+ }
24
+ function validatePagePath(path) {
25
+ if (!path || !path.startsWith("/")) {
26
+ throw new PageValidationError('path must start with "/"');
27
+ }
28
+ if (path.includes("..")) {
29
+ throw new PageValidationError("path must not contain '..'");
30
+ }
31
+ const lastSegment = path.split("/").pop() ?? "";
32
+ if (lastSegment.includes(".")) {
33
+ throw new PageValidationError("path must not include a file extension");
34
+ }
35
+ }
36
+ function validatePageSlotContent(template, slots) {
37
+ const templateSlotNames = new Set(Object.keys(template.slots));
38
+ for (const key of Object.keys(slots)) {
39
+ if (!templateSlotNames.has(key)) {
40
+ throw new PageValidationError(`unknown slot "${key}" for this template`);
41
+ }
42
+ const items = slots[key];
43
+ if (!Array.isArray(items)) {
44
+ throw new PageValidationError(`slot "${key}" must be an array of content items`);
45
+ }
46
+ const schema = template.slots[key]?.schema;
47
+ for (const item of items) {
48
+ try {
49
+ validateSlotContentItem(key, item, schema);
50
+ }
51
+ catch (err) {
52
+ if (err instanceof SlotContentValidationError) {
53
+ throw new PageValidationError(err.message);
54
+ }
55
+ throw err;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ export function createPage(template, def) {
61
+ if (!isTemplate(template)) {
62
+ throw new PageValidationError("template must be created with createTemplate()");
63
+ }
64
+ validatePagePath(def.path);
65
+ if (!def.title || def.title.trim().length === 0) {
66
+ throw new PageValidationError("title is required");
67
+ }
68
+ validatePageSlotContent(template, def.slots);
69
+ for (const required of template.requiredSlots) {
70
+ const items = def.slots[required];
71
+ if (!items || items.length === 0 || !slotHasContent(items)) {
72
+ throw new PageValidationError(`required slot "${required}" must have at least one block or non-empty HTML string`);
73
+ }
74
+ }
75
+ return {
76
+ __kind: "page",
77
+ path: def.path,
78
+ template,
79
+ title: def.title,
80
+ meta: def.meta,
81
+ slots: def.slots,
82
+ };
83
+ }
84
+ export { validateSlotContentItem } from "./slot-content.js";
85
+ //# sourceMappingURL=pages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
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=index.d.ts.map