@stackbox/cms 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +119 -7
  2. package/dist/AGENTS.md +215 -0
  3. package/dist/blocks.d.ts +11 -0
  4. package/dist/blocks.d.ts.map +1 -0
  5. package/dist/blocks.js +27 -0
  6. package/dist/blocks.js.map +1 -0
  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 +16 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +15 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/link.d.ts +6 -0
  24. package/dist/link.d.ts.map +1 -0
  25. package/dist/link.js +121 -0
  26. package/dist/link.js.map +1 -0
  27. package/dist/modules.d.ts +18 -0
  28. package/dist/modules.d.ts.map +1 -0
  29. package/dist/modules.js +25 -0
  30. package/dist/modules.js.map +1 -0
  31. package/dist/pages.d.ts +24 -0
  32. package/dist/pages.d.ts.map +1 -0
  33. package/dist/pages.js +87 -0
  34. package/dist/pages.js.map +1 -0
  35. package/dist/plugin.d.ts +22 -0
  36. package/dist/plugin.d.ts.map +1 -0
  37. package/dist/plugin.js +155 -0
  38. package/dist/plugin.js.map +1 -0
  39. package/dist/plugins/blog/index.d.ts +21 -0
  40. package/dist/plugins/blog/index.d.ts.map +1 -0
  41. package/dist/plugins/blog/index.js +68 -0
  42. package/dist/plugins/blog/index.js.map +1 -0
  43. package/dist/plugins/blog/posts.d.ts +15 -0
  44. package/dist/plugins/blog/posts.d.ts.map +1 -0
  45. package/dist/plugins/blog/posts.js +46 -0
  46. package/dist/plugins/blog/posts.js.map +1 -0
  47. package/dist/plugins/random-quote/assets/quotes.json +230 -0
  48. package/dist/plugins/random-quote/index.d.ts +14 -0
  49. package/dist/plugins/random-quote/index.d.ts.map +1 -0
  50. package/dist/plugins/random-quote/index.js +35 -0
  51. package/dist/plugins/random-quote/index.js.map +1 -0
  52. package/dist/plugins/sitemap/index.d.ts +14 -0
  53. package/dist/plugins/sitemap/index.d.ts.map +1 -0
  54. package/dist/plugins/sitemap/index.js +119 -0
  55. package/dist/plugins/sitemap/index.js.map +1 -0
  56. package/dist/render-head.d.ts +7 -0
  57. package/dist/render-head.d.ts.map +1 -0
  58. package/dist/render-head.js +27 -0
  59. package/dist/render-head.js.map +1 -0
  60. package/dist/render-page.d.ts +4 -0
  61. package/dist/render-page.d.ts.map +1 -0
  62. package/dist/render-page.js +34 -0
  63. package/dist/render-page.js.map +1 -0
  64. package/dist/routing.d.ts +3 -0
  65. package/dist/routing.d.ts.map +1 -0
  66. package/dist/routing.js +11 -0
  67. package/dist/routing.js.map +1 -0
  68. package/dist/site.d.ts +14 -0
  69. package/dist/site.d.ts.map +1 -0
  70. package/dist/site.js +233 -0
  71. package/dist/site.js.map +1 -0
  72. package/dist/slot-content.d.ts +14 -0
  73. package/dist/slot-content.d.ts.map +1 -0
  74. package/dist/slot-content.js +34 -0
  75. package/dist/slot-content.js.map +1 -0
  76. package/dist/slot-handle.d.ts +14 -0
  77. package/dist/slot-handle.d.ts.map +1 -0
  78. package/dist/slot-handle.js +83 -0
  79. package/dist/slot-handle.js.map +1 -0
  80. package/dist/stackbox/context.d.ts +3 -0
  81. package/dist/stackbox/context.d.ts.map +1 -0
  82. package/dist/stackbox/context.js +165 -0
  83. package/dist/stackbox/context.js.map +1 -0
  84. package/dist/templates.d.ts +13 -0
  85. package/dist/templates.d.ts.map +1 -0
  86. package/dist/templates.js +106 -0
  87. package/dist/templates.js.map +1 -0
  88. package/dist/types.d.ts +277 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +2 -0
  91. package/dist/types.js.map +1 -0
  92. package/package.json +18 -3
  93. package/src/plugins/blog/AGENTS.md +5 -1
  94. package/src/plugins/blog/index.ts +22 -5
  95. package/src/plugins/random-quote/AGENTS.md +30 -7
  96. package/src/plugins/random-quote/index.ts +17 -1
  97. package/src/plugins/random-quote/public_assets/widget.css +5 -0
  98. package/src/plugins/sitemap/AGENTS.md +82 -0
  99. package/src/plugins/sitemap/index.ts +156 -0
  100. package/.claude/settings.local.json +0 -8
  101. package/AGENTS.md +0 -87
  102. package/scripts/copy-plugin-assets.mjs +0 -30
  103. package/src/blocks.ts +0 -58
  104. package/src/index.ts +0 -67
  105. package/src/link.ts +0 -158
  106. package/src/pages.ts +0 -198
  107. package/src/render-head.ts +0 -32
  108. package/src/render-page.ts +0 -51
  109. package/src/routing.ts +0 -14
  110. package/src/site.ts +0 -160
  111. package/src/slot-content.ts +0 -77
  112. package/src/slot-handle.ts +0 -131
  113. package/src/stackbox/context.ts +0 -257
  114. package/src/templates.ts +0 -230
  115. package/test/async-render.test.ts +0 -103
  116. package/test/blog.test.ts +0 -93
  117. package/test/fetch-routing.test.ts +0 -76
  118. package/test/plugin-assets.test.ts +0 -80
  119. package/test/random-quote.test.ts +0 -55
  120. package/test/stackbox-context.test.ts +0 -44
  121. package/tsconfig.json +0 -20
  122. /package/src/plugins/random-quote/{public_assets → assets}/quotes.json +0 -0
@@ -0,0 +1,83 @@
1
+ import { html, renderAsync } from "@hyperspan/html";
2
+ import { isBlock } from "./blocks.js";
3
+ import { validateSlotContentItem, } from "./slot-content.js";
4
+ export class RenderError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "RenderError";
8
+ }
9
+ }
10
+ export const SLOT_SENTINEL_PREFIX = "<!--__STACKBOX_SLOT__:";
11
+ export function slotSentinel(name) {
12
+ return `${SLOT_SENTINEL_PREFIX}${name}-->`;
13
+ }
14
+ async function renderSlotItemHtml(slotName, item, ctx, schema) {
15
+ try {
16
+ validateSlotContentItem(slotName, item, schema);
17
+ }
18
+ catch (err) {
19
+ throw new RenderError(err instanceof Error ? err.message : String(err));
20
+ }
21
+ if (typeof item === "string") {
22
+ return item;
23
+ }
24
+ if (isBlock(item)) {
25
+ const rendered = await item.render(ctx);
26
+ return renderAsync(rendered);
27
+ }
28
+ throw new RenderError("invalid slot content; expected block or HTML string");
29
+ }
30
+ export function renderSlotContent(slotName, items, ctx, schema) {
31
+ return Promise.all(items.map(async (item, index) => {
32
+ let htmlString = await renderSlotItemHtml(slotName, item, ctx, schema);
33
+ const hook = ctx.hooks?.renderSlotItem;
34
+ if (hook && ctx.page) {
35
+ htmlString = await hook(htmlString, {
36
+ item: item,
37
+ slot: slotName,
38
+ index,
39
+ page: ctx.page,
40
+ ctx: ctx.ctx,
41
+ });
42
+ }
43
+ return html.raw(htmlString);
44
+ })).then((chunks) => html `${chunks}`);
45
+ }
46
+ export function createStubSlot(definition) {
47
+ return {
48
+ name: definition.name,
49
+ definition,
50
+ content: [],
51
+ render() {
52
+ return html.raw(slotSentinel(definition.name));
53
+ },
54
+ };
55
+ }
56
+ export function createPageSlot(definition, content, ctx) {
57
+ const schema = definition.options?.schema;
58
+ return {
59
+ name: definition.name,
60
+ definition,
61
+ content,
62
+ render() {
63
+ return renderSlotContent(definition.name, content, ctx, schema);
64
+ },
65
+ };
66
+ }
67
+ export function buildStubSlots(definitions) {
68
+ const slots = {};
69
+ for (const def of definitions) {
70
+ slots[def.name] = createStubSlot(def);
71
+ }
72
+ return slots;
73
+ }
74
+ export function buildPageSlots(page, ctx) {
75
+ const slots = {};
76
+ const definitions = page.template.__definitions ?? [];
77
+ for (const def of definitions) {
78
+ const content = page.slots[def.name] ?? [];
79
+ slots[def.name] = createPageSlot(def, content, ctx);
80
+ }
81
+ return slots;
82
+ }
83
+ //# sourceMappingURL=slot-handle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot-handle.js","sourceRoot":"","sources":["../src/slot-handle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Stackbox as SB } from "../types.js";
2
+ export declare function createContext<TEnv extends Record<string, unknown> = Record<string, unknown>>(raw: globalThis.Request, env?: TEnv): SB.Context<TEnv>;
3
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/stackbox/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,aAAa,CAAC;AA+JlD,wBAAgB,aAAa,CAC3B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,GAAE,IAAiB,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAyBnE"}
@@ -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,13 @@
1
+ import { type HSHtml } from "@hyperspan/html";
2
+ import type { Stackbox as SB } from "./types.js";
3
+ export declare function isTemplate(value: unknown): value is SB.TemplateDescriptor;
4
+ export declare class TemplateBuildError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ export declare function createTemplate<const S extends readonly SB.SlotDefinition[]>(def: {
8
+ siteConfig: SB.SiteConfig;
9
+ slots: S;
10
+ title?: (pageTitle: string, siteConfig: SB.SiteConfig) => string;
11
+ render: (ctx: SB.TemplateRenderContext<S>) => HSHtml;
12
+ }): SB.TemplateDescriptor<SB.SlotNamesFrom<S>, SB.RequiredSlotNamesFrom<S>, S>;
13
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAOtD,OAAO,KAAK,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC,kBAAkB,CAYzE;AAiBD,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAgED,wBAAgB,cAAc,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,cAAc,EAAE,EACzE,GAAG,EAAE;IACH,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,KAAK,MAAM,CAAC;IACjE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;CACtD,GACA,EAAE,CAAC,kBAAkB,CACtB,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EACnB,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAC3B,CAAC,CACF,CAmDA"}
@@ -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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"}