@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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/blog/index.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=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/blog/index.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,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/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"}
@@ -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/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"}
@@ -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=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/blog/plugin.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=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/plugins/blog/plugin.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/plugins/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/plugins/blog/posts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type Quote = {
2
+ text: string;
3
+ author: string;
4
+ };
5
+ export type RandomQuoteBlockOptions = {
6
+ /** Custom quotes. Omit to use bundled defaults. */
7
+ quotes?: readonly Quote[];
8
+ };
9
+ export declare const defaultQuotes: readonly Quote[];
10
+ export declare function pickRandomQuote(quotes: readonly Quote[]): Quote;
11
+ export declare const randomQuoteBlock: import("../../blocks.js").BlockFactory<RandomQuoteBlockOptions | undefined>;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/random-quote/index.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,mDAAmD;IACnD,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,SAAS,KAAK,EAAkB,CAAC;AAE7D,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,KAAK,CAK/D;AAED,eAAO,MAAM,gBAAgB,6EAS3B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { html } from "@hyperspan/html";
2
+ import { createBlock } from "../../blocks.js";
3
+ import bundledQuotes from "./public_assets/quotes.json" with { type: "json" };
4
+ export const defaultQuotes = bundledQuotes;
5
+ export function pickRandomQuote(quotes) {
6
+ if (quotes.length === 0) {
7
+ throw new Error("random-quote: quotes must contain at least one quote");
8
+ }
9
+ return quotes[Math.floor(Math.random() * quotes.length)];
10
+ }
11
+ export const randomQuoteBlock = createBlock({
12
+ name: "random-quote",
13
+ render(options) {
14
+ const quote = pickRandomQuote(options?.quotes ?? defaultQuotes);
15
+ return html `<blockquote data-block="random-quote" cite="${quote.author}">
16
+ <p>${quote.text}</p>
17
+ <footer>— ${quote.author}</footer>
18
+ </blockquote>`;
19
+ },
20
+ });
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/random-quote/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,aAAa,MAAM,6BAA6B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAY9E,MAAM,CAAC,MAAM,aAAa,GAAqB,aAAa,CAAC;AAE7D,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM,CAAC,OAAiC;QACtC,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,EAAE,MAAM,IAAI,aAAa,CAAC,CAAC;QAChE,OAAO,IAAI,CAAA,+CAA+C,KAAK,CAAC,MAAM;OACnE,KAAK,CAAC,IAAI;cACH,KAAK,CAAC,MAAM;cACZ,CAAC;IACb,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type Quote = {
2
+ id: number;
3
+ text: string;
4
+ author: string;
5
+ };
6
+ export declare function loadQuotes(): Quote[];
7
+ export declare function pickRandomQuote(quotes?: readonly Quote[]): Quote;
8
+ export declare const randomQuoteBlock: import("../../blocks.js").BlockFactory<undefined>;
9
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/plugins/random-quote/module.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,wBAAgB,UAAU,IAAI,KAAK,EAAE,CAUpC;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,SAAS,KAAK,EAAiB,GAAG,KAAK,CAK9E;AAED,eAAO,MAAM,gBAAgB,mDAS3B,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { html } from "@hyperspan/html";
5
+ import { createBlock } from "../../blocks.js";
6
+ let cachedQuotes;
7
+ export function loadQuotes() {
8
+ if (cachedQuotes) {
9
+ return cachedQuotes;
10
+ }
11
+ const dir = dirname(fileURLToPath(import.meta.url));
12
+ cachedQuotes = JSON.parse(readFileSync(join(dir, "quotes.json"), "utf8"));
13
+ return cachedQuotes;
14
+ }
15
+ export function pickRandomQuote(quotes = loadQuotes()) {
16
+ if (quotes.length === 0) {
17
+ throw new Error("random-quote: quotes.json must contain at least one quote");
18
+ }
19
+ return quotes[Math.floor(Math.random() * quotes.length)];
20
+ }
21
+ export const randomQuoteBlock = createBlock({
22
+ name: "random-quote",
23
+ render() {
24
+ const quote = pickRandomQuote();
25
+ return html `<blockquote data-block="random-quote" cite="${quote.author}">
26
+ <p>${quote.text}</p>
27
+ <footer>— ${quote.author}</footer>
28
+ </blockquote>`;
29
+ },
30
+ });
31
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/plugins/random-quote/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAQ9C,IAAI,YAAiC,CAAC;AAEtC,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,YAAY,GAAG,IAAI,CAAC,KAAK,CACvB,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CACpC,CAAC;IACb,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAA2B,UAAU,EAAE;IACrE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM;QACJ,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,OAAO,IAAI,CAAA,+CAA+C,KAAK,CAAC,MAAM;OACnE,KAAK,CAAC,IAAI;cACH,KAAK,CAAC,MAAM;cACZ,CAAC;IACb,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type Quote = {
2
+ text: string;
3
+ author: string;
4
+ };
5
+ export declare function loadQuotes(): Quote[];
6
+ export declare function pickRandomQuote(quotes?: readonly Quote[]): Quote;
7
+ export declare const randomQuoteBlock: import("../../blocks.js").BlockFactory<undefined>;
8
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/random-quote/plugin.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,wBAAgB,UAAU,IAAI,KAAK,EAAE,CAUpC;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,SAAS,KAAK,EAAiB,GAAG,KAAK,CAK9E;AAED,eAAO,MAAM,gBAAgB,mDAS3B,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { html } from "@hyperspan/html";
5
+ import { createBlock } from "../../blocks.js";
6
+ let cachedQuotes;
7
+ export function loadQuotes() {
8
+ if (cachedQuotes) {
9
+ return cachedQuotes;
10
+ }
11
+ const dir = dirname(fileURLToPath(import.meta.url));
12
+ cachedQuotes = JSON.parse(readFileSync(join(dir, "quotes.json"), "utf8"));
13
+ return cachedQuotes;
14
+ }
15
+ export function pickRandomQuote(quotes = loadQuotes()) {
16
+ if (quotes.length === 0) {
17
+ throw new Error("random-quote: quotes.json must contain at least one quote");
18
+ }
19
+ return quotes[Math.floor(Math.random() * quotes.length)];
20
+ }
21
+ export const randomQuoteBlock = createBlock({
22
+ name: "random-quote",
23
+ render() {
24
+ const quote = pickRandomQuote();
25
+ return html `<blockquote data-block="random-quote" cite="${quote.author}">
26
+ <p>${quote.text}</p>
27
+ <footer>— ${quote.author}</footer>
28
+ </blockquote>`;
29
+ },
30
+ });
31
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/plugins/random-quote/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAO9C,IAAI,YAAiC,CAAC;AAEtC,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,YAAY,GAAG,IAAI,CAAC,KAAK,CACvB,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CACpC,CAAC;IACb,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAA2B,UAAU,EAAE;IACrE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM;QACJ,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,OAAO,IAAI,CAAA,+CAA+C,KAAK,CAAC,MAAM;OACnE,KAAK,CAAC,IAAI;cACH,KAAK,CAAC,MAAM;cACZ,CAAC;IACb,CAAC;CACF,CAAC,CAAC"}