@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,165 @@
1
+ function parseCookieHeader(header) {
2
+ const cookies = {};
3
+ for (const part of header.split(";")) {
4
+ const trimmed = part.trim();
5
+ if (!trimmed)
6
+ continue;
7
+ const eq = trimmed.indexOf("=");
8
+ if (eq === -1)
9
+ continue;
10
+ const name = trimmed.slice(0, eq).trim();
11
+ const value = trimmed.slice(eq + 1).trim();
12
+ if (name)
13
+ cookies[name] = decodeURIComponent(value);
14
+ }
15
+ return cookies;
16
+ }
17
+ function serializeCookie(name, value, options) {
18
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
19
+ if (options?.maxAge !== undefined)
20
+ cookie += `; Max-Age=${options.maxAge}`;
21
+ if (options?.domain)
22
+ cookie += `; Domain=${options.domain}`;
23
+ if (options?.path)
24
+ cookie += `; Path=${options.path}`;
25
+ else
26
+ cookie += "; Path=/";
27
+ if (options?.expires)
28
+ cookie += `; Expires=${options.expires.toUTCString()}`;
29
+ if (options?.httpOnly)
30
+ cookie += "; HttpOnly";
31
+ if (options?.secure)
32
+ cookie += "; Secure";
33
+ if (options?.sameSite === true)
34
+ cookie += "; SameSite=Strict";
35
+ else if (options?.sameSite) {
36
+ const s = options.sameSite === "strict" ? "Strict" : "Lax";
37
+ cookie += `; SameSite=${s}`;
38
+ }
39
+ return cookie;
40
+ }
41
+ function createCookies(req, responseHeaders, parsed) {
42
+ return {
43
+ _req: req,
44
+ _responseHeaders: responseHeaders,
45
+ _parsedCookies: parsed,
46
+ _encrypt: undefined,
47
+ _decrypt: undefined,
48
+ get(name) {
49
+ return parsed[name];
50
+ },
51
+ set(name, value, options) {
52
+ if (!responseHeaders)
53
+ return;
54
+ parsed[name] = value;
55
+ responseHeaders.append("Set-Cookie", serializeCookie(name, value, options));
56
+ },
57
+ delete(name) {
58
+ if (!responseHeaders)
59
+ return;
60
+ delete parsed[name];
61
+ responseHeaders.append("Set-Cookie", serializeCookie(name, "", { maxAge: 0, path: "/" }));
62
+ },
63
+ };
64
+ }
65
+ function buildResponse(res, body, init = {}) {
66
+ const headers = new Headers(init.headers);
67
+ res.headers.forEach((value, key) => {
68
+ if (!headers.has(key))
69
+ headers.set(key, value);
70
+ });
71
+ for (const value of res.headers.getSetCookie?.() ?? []) {
72
+ headers.append("Set-Cookie", value);
73
+ }
74
+ if (body !== null && !headers.has("Content-Type") && typeof body === "string") {
75
+ headers.set("Content-Type", "text/plain; charset=utf-8");
76
+ }
77
+ const status = init.status ?? res.status ?? 200;
78
+ return new globalThis.Response(body, { ...init, status, headers });
79
+ }
80
+ function createStackboxResponse(reqCookies) {
81
+ const headers = new Headers();
82
+ const resCookies = createCookies(reqCookies._req, headers, { ...reqCookies._parsedCookies });
83
+ const res = {
84
+ cookies: resCookies,
85
+ headers,
86
+ status: undefined,
87
+ async html(html, options = {}) {
88
+ res.status = options.status ?? 200;
89
+ const outHeaders = new Headers(options.headers);
90
+ if (!outHeaders.has("Content-Type")) {
91
+ outHeaders.set("Content-Type", "text/html; charset=utf-8");
92
+ }
93
+ return buildResponse(res, html, { ...options, headers: outHeaders });
94
+ },
95
+ async json(json, options = {}) {
96
+ res.status = options.status ?? 200;
97
+ const outHeaders = new Headers(options.headers);
98
+ if (!outHeaders.has("Content-Type")) {
99
+ outHeaders.set("Content-Type", "application/json; charset=utf-8");
100
+ }
101
+ return buildResponse(res, JSON.stringify(json), {
102
+ ...options,
103
+ headers: outHeaders,
104
+ });
105
+ },
106
+ async text(text, options = {}) {
107
+ res.status = options.status ?? 200;
108
+ return buildResponse(res, text, options);
109
+ },
110
+ async redirect(url, options = {}) {
111
+ const outHeaders = new Headers(options.headers);
112
+ outHeaders.set("Location", url);
113
+ res.status = options.status ?? 302;
114
+ return buildResponse(res, null, { ...options, headers: outHeaders });
115
+ },
116
+ async error(error, options = {}) {
117
+ res.status = options.status ?? 500;
118
+ return buildResponse(res, error.message, options);
119
+ },
120
+ async notFound(options = {}) {
121
+ res.status = options.status ?? 400 + 4;
122
+ return buildResponse(res, "Not Found", { ...options, status: res.status });
123
+ },
124
+ async merge(response) {
125
+ const merged = new Headers(response.headers);
126
+ res.headers.forEach((value, key) => {
127
+ if (!merged.has(key))
128
+ merged.set(key, value);
129
+ });
130
+ for (const value of res.headers.getSetCookie?.() ?? []) {
131
+ merged.append("Set-Cookie", value);
132
+ }
133
+ return new globalThis.Response(response.body, {
134
+ status: response.status,
135
+ statusText: response.statusText,
136
+ headers: merged,
137
+ });
138
+ },
139
+ };
140
+ return res;
141
+ }
142
+ export function createContext(raw, env = {}) {
143
+ const url = new URL(raw.url);
144
+ const parsed = parseCookieHeader(raw.headers.get("Cookie") ?? "");
145
+ const reqHeaders = new Headers(raw.headers);
146
+ const reqCookies = createCookies(raw, undefined, parsed);
147
+ const req = {
148
+ url,
149
+ raw,
150
+ method: raw.method.toUpperCase(),
151
+ headers: reqHeaders,
152
+ query: url.searchParams,
153
+ cookies: reqCookies,
154
+ text: () => raw.text(),
155
+ json: () => raw.json(),
156
+ formData: () => raw.formData(),
157
+ urlencoded: async () => {
158
+ const text = await raw.text();
159
+ return new URLSearchParams(text);
160
+ },
161
+ };
162
+ const res = createStackboxResponse(reqCookies);
163
+ return { env, req, res };
164
+ }
165
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/stackbox/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { type HSHtml } from "@hyperspan/html";
2
+ import type { z } from "zod";
3
+ import { type SiteConfig } from "./site.js";
4
+ import type { PageRenderView } from "./pages.js";
5
+ import { type TemplateSlotsFrom } from "./slot-handle.js";
6
+ export type SlotOptions = {
7
+ required?: boolean;
8
+ primary?: true;
9
+ schema?: z.ZodTypeAny;
10
+ };
11
+ export type SlotDefinition = {
12
+ name: string;
13
+ options?: SlotOptions;
14
+ };
15
+ export type SlotMeta = {
16
+ isDefault: boolean;
17
+ required: boolean;
18
+ schema?: z.ZodTypeAny;
19
+ };
20
+ export type TemplateRenderContext<S extends readonly SlotDefinition[] = readonly SlotDefinition[]> = {
21
+ head?: HSHtml;
22
+ siteConfig: SiteConfig;
23
+ page: PageRenderView;
24
+ slots: TemplateSlotsFrom<S>;
25
+ };
26
+ /** Widened render signature stored on descriptors at runtime. */
27
+ export type TemplateRenderFn = (ctx: {
28
+ head?: HSHtml;
29
+ siteConfig: SiteConfig;
30
+ page: PageRenderView;
31
+ slots: Record<string, import("./slot-handle.js").Slot>;
32
+ }) => HSHtml;
33
+ export type TemplateDescriptor<Slots extends string = string, RequiredSlots extends Slots = never, Definitions extends readonly SlotDefinition[] = readonly SlotDefinition[]> = {
34
+ readonly __kind: "template";
35
+ siteConfig: SiteConfig;
36
+ formatPageTitle: (title: string) => string;
37
+ render: TemplateRenderFn;
38
+ slots: Record<Slots, SlotMeta>;
39
+ requiredSlots: readonly RequiredSlots[];
40
+ readonly __definitions?: Definitions;
41
+ };
42
+ export type SlotNamesFrom<S extends readonly SlotDefinition[]> = S[number]["name"];
43
+ export type RequiredSlotNamesFrom<S extends readonly SlotDefinition[]> = Extract<S[number], {
44
+ options: {
45
+ required: true;
46
+ };
47
+ } | {
48
+ options: {
49
+ primary: true;
50
+ };
51
+ }>["name"];
52
+ export declare function isTemplate(value: unknown): value is TemplateDescriptor;
53
+ export declare class TemplateBuildError extends Error {
54
+ constructor(message: string);
55
+ }
56
+ export declare function createTemplate<const S extends readonly SlotDefinition[]>(def: {
57
+ siteConfig: SiteConfig;
58
+ slots: S;
59
+ title?: (pageTitle: string, siteConfig: SiteConfig) => string;
60
+ render: (ctx: TemplateRenderContext<S>) => HSHtml;
61
+ }): TemplateDescriptor<SlotNamesFrom<S>, RequiredSlotNamesFrom<S>, S>;
62
+ export type { Slot, TemplateSlotsFrom } from "./slot-handle.js";
63
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { render } from "@hyperspan/html";
2
+ import { isSiteConfig } from "./site.js";
3
+ import { buildStubSlots, slotSentinel, } from "./slot-handle.js";
4
+ export function isTemplate(value) {
5
+ return (typeof value === "object" &&
6
+ value !== null &&
7
+ value.__kind === "template" &&
8
+ isSiteConfig(value.siteConfig) &&
9
+ typeof value.formatPageTitle === "function" &&
10
+ typeof value.render === "function" &&
11
+ typeof value.slots === "object" &&
12
+ value.slots !== null &&
13
+ Array.isArray(value.requiredSlots));
14
+ }
15
+ function defaultFormatPageTitle(pageTitle, siteConfig) {
16
+ const suffix = siteConfig.config.titleSuffix;
17
+ return typeof suffix === "string" ? pageTitle + suffix : pageTitle;
18
+ }
19
+ export class TemplateBuildError extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = "TemplateBuildError";
23
+ }
24
+ }
25
+ function validateSlotDefinitions(definitions) {
26
+ if (definitions.length === 0) {
27
+ throw new TemplateBuildError("template must define at least one slot");
28
+ }
29
+ const entries = [];
30
+ const seen = new Set();
31
+ let primaryCount = 0;
32
+ for (const def of definitions) {
33
+ if (!def.name || def.name.length === 0) {
34
+ throw new TemplateBuildError("slot name must be non-empty");
35
+ }
36
+ if (seen.has(def.name)) {
37
+ throw new TemplateBuildError(`duplicate slot name "${def.name}"`);
38
+ }
39
+ seen.add(def.name);
40
+ const opts = def.options ?? {};
41
+ const isDefault = opts.primary === true;
42
+ if (isDefault) {
43
+ primaryCount++;
44
+ }
45
+ entries.push({
46
+ name: def.name,
47
+ isDefault,
48
+ required: opts.required === true || opts.primary === true,
49
+ schema: opts.schema,
50
+ });
51
+ }
52
+ if (primaryCount !== 1) {
53
+ throw new TemplateBuildError(`exactly one slot must have options.primary: true; found ${primaryCount}`);
54
+ }
55
+ return entries;
56
+ }
57
+ function validateRenderOutput(html, slotNames) {
58
+ for (const name of slotNames) {
59
+ if (!html.includes(slotSentinel(name))) {
60
+ throw new TemplateBuildError(`slot "${name}" must be rendered via slots.${name}.render()`);
61
+ }
62
+ }
63
+ }
64
+ const stubPage = {
65
+ __kind: "page",
66
+ path: "/",
67
+ title: "Template validation",
68
+ };
69
+ export function createTemplate(def) {
70
+ if (!isSiteConfig(def.siteConfig)) {
71
+ throw new TemplateBuildError("createTemplate({ siteConfig }): siteConfig must be from createSiteConfig()");
72
+ }
73
+ const formatPageTitle = def.title
74
+ ? (pageTitle) => def.title(pageTitle, def.siteConfig)
75
+ : (pageTitle) => defaultFormatPageTitle(pageTitle, def.siteConfig);
76
+ const entries = validateSlotDefinitions(def.slots);
77
+ const stubSlots = buildStubSlots(def.slots);
78
+ const validationHtml = render(def.render({
79
+ siteConfig: def.siteConfig,
80
+ page: stubPage,
81
+ slots: stubSlots,
82
+ }));
83
+ validateRenderOutput(validationHtml, entries.map((entry) => entry.name));
84
+ const slots = {};
85
+ const requiredSlots = [];
86
+ for (const entry of entries) {
87
+ slots[entry.name] = {
88
+ isDefault: entry.isDefault,
89
+ required: entry.required,
90
+ schema: entry.schema,
91
+ };
92
+ if (entry.required) {
93
+ requiredSlots.push(entry.name);
94
+ }
95
+ }
96
+ return {
97
+ __kind: "template",
98
+ siteConfig: def.siteConfig,
99
+ formatPageTitle,
100
+ render: def.render,
101
+ slots,
102
+ requiredSlots,
103
+ __definitions: def.slots,
104
+ };
105
+ }
106
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackbox/cms",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Stackbox CMS engine",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -12,6 +12,11 @@
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/stackboxcms/cms.git"
14
14
  },
15
+ "files": [
16
+ "dist",
17
+ "AGENTS.md",
18
+ "src/plugins"
19
+ ],
15
20
  "exports": {
16
21
  ".": {
17
22
  "types": "./dist/index.d.ts",
@@ -34,7 +39,7 @@
34
39
  "build": "tsc -p tsconfig.json && node scripts/copy-plugin-assets.mjs",
35
40
  "test": "npm run build && node --import tsx --test test/*.test.ts",
36
41
  "typecheck": "tsc --noEmit -p tsconfig.json",
37
- "prepublishOnly": "npm run build"
42
+ "prepack": "npm run build"
38
43
  },
39
44
  "dependencies": {
40
45
  "@hyperspan/html": "^1.0.3",
@@ -1,8 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(node -e \"import\\('@hyperspan/html'\\).then\\(m => console.log\\('html export:', typeof m.html\\)\\)\")",
5
- "Bash(npm run *)"
6
- ]
7
- }
8
- }
@@ -1,30 +0,0 @@
1
- import { cpSync, existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
-
5
- const root = join(dirname(fileURLToPath(import.meta.url)), "..");
6
- const pluginsDir = join(root, "src/plugins");
7
-
8
- if (!existsSync(pluginsDir)) {
9
- process.exit(0);
10
- }
11
-
12
- for (const name of readdirSync(pluginsDir)) {
13
- const pluginDir = join(pluginsDir, name);
14
- if (!statSync(pluginDir).isDirectory()) {
15
- continue;
16
- }
17
-
18
- const publicAssets = join(pluginDir, "public_assets");
19
- if (!existsSync(publicAssets)) {
20
- continue;
21
- }
22
-
23
- const publicDest = join(root, "dist/public/_sb/plugins", name);
24
- mkdirSync(dirname(publicDest), { recursive: true });
25
- cpSync(publicAssets, publicDest, { recursive: true });
26
-
27
- const importDest = join(root, "dist/plugins", name, "public_assets");
28
- mkdirSync(dirname(importDest), { recursive: true });
29
- cpSync(publicAssets, importDest, { recursive: true });
30
- }
package/src/blocks.ts DELETED
@@ -1,58 +0,0 @@
1
- import type { RenderContext } from "./pages.js";
2
- import type { HSHtml } from "@hyperspan/html";
3
-
4
- export type BlockRenderResult = HSHtml | Promise<HSHtml>;
5
-
6
- export type Block = {
7
- readonly __kind: "block";
8
- readonly name: string;
9
- render(ctx: RenderContext): BlockRenderResult;
10
- };
11
-
12
- type BlockDef<TOptions = undefined> = {
13
- name: string;
14
- render(options: TOptions, ctx?: RenderContext): BlockRenderResult;
15
- };
16
-
17
- export type BlockOptionsOf<F> = F extends (options?: infer O) => unknown
18
- ? [O] extends [undefined]
19
- ? undefined
20
- : O
21
- : never;
22
-
23
- export type BlockFactory<TOptions = undefined> = (
24
- options?: TOptions,
25
- ) => Block;
26
-
27
- function validateBlockName(name: string): void {
28
- if (!name || name.length === 0) {
29
- throw new Error("createBlock(def): name is required");
30
- }
31
- }
32
-
33
- export function createBlock<TOptions = undefined>(
34
- def: BlockDef<TOptions>,
35
- ): BlockFactory<TOptions> {
36
- validateBlockName(def.name);
37
-
38
- if (typeof def.render !== "function") {
39
- throw new Error("createBlock(def): render is required");
40
- }
41
-
42
- return ((options?: TOptions) => ({
43
- __kind: "block" as const,
44
- name: def.name,
45
- render: (ctx: RenderContext) => def.render(options as TOptions, ctx),
46
- })) as BlockFactory<TOptions>;
47
- }
48
-
49
- export function isBlock(value: unknown): value is Block {
50
- return (
51
- typeof value === "object" &&
52
- value !== null &&
53
- (value as Block).__kind === "block" &&
54
- typeof (value as Block).name === "string" &&
55
- (value as Block).name.length > 0 &&
56
- typeof (value as Block).render === "function"
57
- );
58
- }
package/src/index.ts DELETED
@@ -1,67 +0,0 @@
1
- export { html } from "@hyperspan/html";
2
- export {
3
- createBlock,
4
- isBlock,
5
- type Block,
6
- type BlockFactory,
7
- type BlockOptionsOf,
8
- type BlockRenderResult,
9
- } from "./blocks.js";
10
- export {
11
- createPage,
12
- isPage,
13
- PageValidationError,
14
- toPageRenderView,
15
- validateSlotContentItem,
16
- type Page,
17
- type PageMeta,
18
- type PageRenderView,
19
- type RenderContext,
20
- type SitePage,
21
- } from "./pages.js";
22
- export { renderStandardHead } from "./render-head.js";
23
- export { renderPage, RenderError } from "./render-page.js";
24
- export { matchPagePath, normalizePathname } from "./routing.js";
25
- export {
26
- createSite,
27
- createSiteConfig,
28
- isSite,
29
- isSiteConfig,
30
- SiteError,
31
- type Site,
32
- type SiteConfig,
33
- } from "./site.js";
34
- export { createContext, Stackbox } from "./stackbox/context.js";
35
- export {
36
- anySlotContentSchema,
37
- blockSlotContentSchema,
38
- slotHasContent,
39
- SlotContentValidationError,
40
- stringSlotContentSchema,
41
- type DefaultSlotContent,
42
- type PageSlotsInput,
43
- type SlotContentFromDefinition,
44
- } from "./slot-content.js";
45
- export {
46
- buildPageSlots,
47
- buildStubSlots,
48
- renderSlotContent,
49
- slotSentinel,
50
- SLOT_SENTINEL_PREFIX,
51
- type Slot,
52
- type SlotRenderValue,
53
- type TemplateSlotsFrom,
54
- } from "./slot-handle.js";
55
- export {
56
- createTemplate,
57
- isTemplate,
58
- TemplateBuildError,
59
- type RequiredSlotNamesFrom,
60
- type SlotDefinition,
61
- type SlotMeta,
62
- type SlotNamesFrom,
63
- type SlotOptions,
64
- type TemplateDescriptor,
65
- type TemplateRenderContext,
66
- type TemplateRenderFn,
67
- } from "./templates.js";