@emkodev/emroute 1.7.3 → 1.8.0-beta.2

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 (238) hide show
  1. package/README.md +1 -1
  2. package/core/component/abstract.component.ts +74 -0
  3. package/{src → core}/component/page.component.ts +3 -61
  4. package/core/component/widget.component.ts +54 -0
  5. package/core/pipeline/pipeline.ts +224 -0
  6. package/{src/renderer/ssr → core/renderer}/html.renderer.ts +26 -47
  7. package/{src/renderer/ssr → core/renderer}/md.renderer.ts +22 -41
  8. package/{src/renderer/ssr → core/renderer}/ssr.renderer.ts +44 -58
  9. package/{src/route → core/router}/route.resolver.ts +1 -10
  10. package/core/router/route.trie.ts +175 -0
  11. package/core/runtime/abstract.runtime.ts +47 -0
  12. package/core/server/emroute.server.ts +324 -0
  13. package/core/type/component.type.ts +39 -0
  14. package/core/type/element.type.ts +10 -0
  15. package/core/type/logger.type.ts +20 -0
  16. package/core/type/markdown.type.ts +8 -0
  17. package/core/type/route-tree.type.ts +28 -0
  18. package/core/type/route.type.ts +75 -0
  19. package/core/type/widget.type.ts +27 -0
  20. package/core/util/html.util.ts +50 -0
  21. package/{src → core}/util/md.util.ts +3 -5
  22. package/{src/route → core/util}/route-tree.util.ts +0 -2
  23. package/{src → core}/util/widget-resolve.util.ts +15 -46
  24. package/{src → core}/widget/widget.parser.ts +2 -23
  25. package/core/widget/widget.registry.ts +36 -0
  26. package/dist/core/component/abstract.component.d.ts +48 -0
  27. package/dist/core/component/abstract.component.js +42 -0
  28. package/dist/core/component/abstract.component.js.map +1 -0
  29. package/dist/core/component/page.component.d.ts +23 -0
  30. package/dist/core/component/page.component.js +49 -0
  31. package/dist/core/component/page.component.js.map +1 -0
  32. package/dist/core/component/widget.component.d.ts +17 -0
  33. package/dist/core/component/widget.component.js +37 -0
  34. package/dist/core/component/widget.component.js.map +1 -0
  35. package/dist/core/pipeline/pipeline.d.ts +61 -0
  36. package/dist/core/pipeline/pipeline.js +189 -0
  37. package/dist/core/pipeline/pipeline.js.map +1 -0
  38. package/dist/{src/renderer/ssr → core/renderer}/html.renderer.d.ts +8 -24
  39. package/dist/{src/renderer/ssr → core/renderer}/html.renderer.js +20 -35
  40. package/dist/core/renderer/html.renderer.js.map +1 -0
  41. package/dist/{src/renderer/ssr → core/renderer}/md.renderer.d.ts +6 -21
  42. package/dist/{src/renderer/ssr → core/renderer}/md.renderer.js +16 -32
  43. package/dist/core/renderer/md.renderer.js.map +1 -0
  44. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.d.ts +11 -27
  45. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.js +33 -37
  46. package/dist/core/renderer/ssr.renderer.js.map +1 -0
  47. package/dist/{src/route → core/router}/route.resolver.d.ts +1 -8
  48. package/dist/{src/route → core/router}/route.resolver.js +0 -1
  49. package/dist/core/router/route.resolver.js.map +1 -0
  50. package/dist/core/router/route.trie.d.ts +32 -0
  51. package/dist/core/router/route.trie.js +152 -0
  52. package/dist/core/router/route.trie.js.map +1 -0
  53. package/dist/core/runtime/abstract.runtime.d.ts +32 -0
  54. package/dist/core/runtime/abstract.runtime.js +26 -0
  55. package/dist/core/runtime/abstract.runtime.js.map +1 -0
  56. package/dist/core/server/emroute.server.d.ts +48 -0
  57. package/dist/core/server/emroute.server.js +239 -0
  58. package/dist/core/server/emroute.server.js.map +1 -0
  59. package/dist/core/server/server.type.d.ts +45 -0
  60. package/dist/core/server/server.type.js +11 -0
  61. package/dist/core/server/server.type.js.map +1 -0
  62. package/dist/core/type/component.type.d.ts +37 -0
  63. package/dist/core/type/component.type.js +7 -0
  64. package/dist/core/type/component.type.js.map +1 -0
  65. package/dist/core/type/element.type.d.ts +9 -0
  66. package/dist/core/type/element.type.js +5 -0
  67. package/dist/core/type/element.type.js.map +1 -0
  68. package/dist/core/type/logger.type.d.ts +14 -0
  69. package/dist/core/type/logger.type.js +8 -0
  70. package/dist/core/type/logger.type.js.map +1 -0
  71. package/dist/core/type/markdown.type.d.ts +7 -0
  72. package/dist/core/type/markdown.type.js +5 -0
  73. package/dist/core/type/markdown.type.js.map +1 -0
  74. package/dist/{src → core}/type/route-tree.type.d.ts +0 -12
  75. package/dist/{src → core}/type/route-tree.type.js +0 -1
  76. package/dist/core/type/route-tree.type.js.map +1 -0
  77. package/dist/core/type/route.type.d.ts +62 -0
  78. package/dist/core/type/route.type.js +7 -0
  79. package/dist/core/type/route.type.js.map +1 -0
  80. package/dist/core/type/widget.type.d.ts +27 -0
  81. package/dist/core/type/widget.type.js +5 -0
  82. package/dist/core/type/widget.type.js.map +1 -0
  83. package/dist/core/util/html.util.d.ts +14 -0
  84. package/dist/core/util/html.util.js +43 -0
  85. package/dist/core/util/html.util.js.map +1 -0
  86. package/dist/{src → core}/util/md.util.d.ts +0 -1
  87. package/dist/{src → core}/util/md.util.js +0 -2
  88. package/dist/core/util/md.util.js.map +1 -0
  89. package/dist/{src/route → core/util}/route-tree.util.js +0 -2
  90. package/dist/core/util/route-tree.util.js.map +1 -0
  91. package/dist/core/util/widget-resolve.util.d.ts +28 -0
  92. package/dist/{src → core}/util/widget-resolve.util.js +12 -42
  93. package/dist/core/util/widget-resolve.util.js.map +1 -0
  94. package/dist/{src → core}/widget/widget.parser.d.ts +0 -13
  95. package/dist/{src → core}/widget/widget.parser.js +1 -22
  96. package/dist/core/widget/widget.parser.js.map +1 -0
  97. package/dist/core/widget/widget.registry.d.ts +14 -0
  98. package/dist/core/widget/widget.registry.js +26 -0
  99. package/dist/core/widget/widget.registry.js.map +1 -0
  100. package/dist/emroute.js +1092 -1220
  101. package/dist/emroute.js.map +36 -5
  102. package/dist/runtime/abstract.runtime.d.ts +41 -7
  103. package/dist/runtime/abstract.runtime.js +404 -9
  104. package/dist/runtime/abstract.runtime.js.map +1 -1
  105. package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +1 -0
  106. package/dist/runtime/bun/fs/bun-fs.runtime.js +15 -1
  107. package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
  108. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +2 -0
  109. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +8 -0
  110. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
  111. package/dist/runtime/fetch.runtime.d.ts +3 -3
  112. package/dist/runtime/fetch.runtime.js +3 -3
  113. package/dist/runtime/sitemap.generator.d.ts +1 -1
  114. package/dist/runtime/sitemap.generator.js +1 -1
  115. package/dist/runtime/sitemap.generator.js.map +1 -1
  116. package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +1 -0
  117. package/dist/runtime/universal/fs/universal-fs.runtime.js +15 -1
  118. package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
  119. package/dist/server/build.util.d.ts +9 -10
  120. package/dist/server/build.util.js +11 -31
  121. package/dist/server/build.util.js.map +1 -1
  122. package/dist/server/codegen.util.d.ts +1 -1
  123. package/dist/server/emroute.server.d.ts +8 -35
  124. package/dist/server/emroute.server.js +7 -351
  125. package/dist/server/emroute.server.js.map +1 -1
  126. package/dist/server/esbuild-manifest.plugin.js +1 -1
  127. package/dist/server/esbuild-manifest.plugin.js.map +1 -1
  128. package/dist/server/server-api.type.d.ts +3 -71
  129. package/dist/server/server-api.type.js +1 -8
  130. package/dist/server/server-api.type.js.map +1 -1
  131. package/dist/src/element/component.element.d.ts +6 -14
  132. package/dist/src/element/component.element.js +13 -40
  133. package/dist/src/element/component.element.js.map +1 -1
  134. package/dist/src/element/markdown.element.d.ts +2 -2
  135. package/dist/src/element/markdown.element.js +3 -2
  136. package/dist/src/element/markdown.element.js.map +1 -1
  137. package/dist/src/index.d.ts +15 -14
  138. package/dist/src/index.js +8 -8
  139. package/dist/src/index.js.map +1 -1
  140. package/dist/src/renderer/spa/emroute.app.d.ts +50 -0
  141. package/dist/src/renderer/spa/emroute.app.js +246 -0
  142. package/dist/src/renderer/spa/emroute.app.js.map +1 -0
  143. package/dist/src/renderer/spa/mod.d.ts +17 -16
  144. package/dist/src/renderer/spa/mod.js +9 -9
  145. package/dist/src/renderer/spa/mod.js.map +1 -1
  146. package/dist/src/renderer/spa/thin-client.d.ts +3 -3
  147. package/dist/src/renderer/spa/thin-client.js +7 -7
  148. package/dist/src/renderer/spa/thin-client.js.map +1 -1
  149. package/dist/src/route/route.core.d.ts +3 -3
  150. package/dist/src/util/html.util.d.ts +5 -22
  151. package/dist/src/util/html.util.js +8 -56
  152. package/dist/src/util/html.util.js.map +1 -1
  153. package/dist/src/widget/breadcrumb.widget.d.ts +2 -2
  154. package/dist/src/widget/breadcrumb.widget.js +2 -2
  155. package/dist/src/widget/breadcrumb.widget.js.map +1 -1
  156. package/dist/src/widget/page-title.widget.d.ts +1 -1
  157. package/dist/src/widget/page-title.widget.js +1 -1
  158. package/dist/src/widget/page-title.widget.js.map +1 -1
  159. package/package.json +8 -8
  160. package/runtime/abstract.runtime.ts +433 -17
  161. package/runtime/bun/fs/bun-fs.runtime.ts +15 -1
  162. package/runtime/bun/sqlite/bun-sqlite.runtime.ts +9 -0
  163. package/runtime/fetch.runtime.ts +3 -3
  164. package/runtime/sitemap.generator.ts +2 -2
  165. package/runtime/universal/fs/universal-fs.runtime.ts +15 -1
  166. package/server/build.util.ts +17 -43
  167. package/server/codegen.util.ts +1 -1
  168. package/server/emroute.server.ts +12 -426
  169. package/src/element/component.element.ts +14 -54
  170. package/src/element/markdown.element.ts +4 -3
  171. package/src/index.ts +22 -19
  172. package/src/renderer/spa/{thin-client.ts → emroute.app.ts} +19 -20
  173. package/src/renderer/spa/mod.ts +22 -22
  174. package/src/util/html.util.ts +16 -61
  175. package/src/widget/breadcrumb.widget.ts +3 -3
  176. package/src/widget/page-title.widget.ts +1 -1
  177. package/dist/src/component/abstract.component.d.ts +0 -199
  178. package/dist/src/component/abstract.component.js +0 -84
  179. package/dist/src/component/abstract.component.js.map +0 -1
  180. package/dist/src/component/page.component.d.ts +0 -74
  181. package/dist/src/component/page.component.js +0 -107
  182. package/dist/src/component/page.component.js.map +0 -1
  183. package/dist/src/component/widget.component.d.ts +0 -47
  184. package/dist/src/component/widget.component.js +0 -69
  185. package/dist/src/component/widget.component.js.map +0 -1
  186. package/dist/src/renderer/ssr/html.renderer.js.map +0 -1
  187. package/dist/src/renderer/ssr/md.renderer.js.map +0 -1
  188. package/dist/src/renderer/ssr/ssr.renderer.js.map +0 -1
  189. package/dist/src/route/route-tree.util.js.map +0 -1
  190. package/dist/src/route/route.matcher.d.ts +0 -86
  191. package/dist/src/route/route.matcher.js +0 -214
  192. package/dist/src/route/route.matcher.js.map +0 -1
  193. package/dist/src/route/route.resolver.js.map +0 -1
  194. package/dist/src/route/route.trie.d.ts +0 -38
  195. package/dist/src/route/route.trie.js +0 -206
  196. package/dist/src/route/route.trie.js.map +0 -1
  197. package/dist/src/type/element.type.d.ts +0 -19
  198. package/dist/src/type/element.type.js +0 -9
  199. package/dist/src/type/element.type.js.map +0 -1
  200. package/dist/src/type/logger.type.d.ts +0 -17
  201. package/dist/src/type/logger.type.js +0 -9
  202. package/dist/src/type/logger.type.js.map +0 -1
  203. package/dist/src/type/markdown.type.d.ts +0 -20
  204. package/dist/src/type/markdown.type.js +0 -2
  205. package/dist/src/type/markdown.type.js.map +0 -1
  206. package/dist/src/type/route-tree.type.js.map +0 -1
  207. package/dist/src/type/route.type.d.ts +0 -94
  208. package/dist/src/type/route.type.js +0 -8
  209. package/dist/src/type/route.type.js.map +0 -1
  210. package/dist/src/type/widget.type.d.ts +0 -55
  211. package/dist/src/type/widget.type.js +0 -10
  212. package/dist/src/type/widget.type.js.map +0 -1
  213. package/dist/src/util/logger.util.d.ts +0 -26
  214. package/dist/src/util/logger.util.js +0 -80
  215. package/dist/src/util/logger.util.js.map +0 -1
  216. package/dist/src/util/md.util.js.map +0 -1
  217. package/dist/src/util/widget-resolve.util.d.ts +0 -52
  218. package/dist/src/util/widget-resolve.util.js.map +0 -1
  219. package/dist/src/widget/widget.parser.js.map +0 -1
  220. package/dist/src/widget/widget.registry.d.ts +0 -23
  221. package/dist/src/widget/widget.registry.js +0 -42
  222. package/dist/src/widget/widget.registry.js.map +0 -1
  223. package/runtime/bun/esbuild-runtime-loader.plugin.ts +0 -112
  224. package/server/esbuild-manifest.plugin.ts +0 -209
  225. package/server/server-api.type.ts +0 -101
  226. package/src/component/abstract.component.ts +0 -231
  227. package/src/component/widget.component.ts +0 -85
  228. package/src/route/route.core.ts +0 -371
  229. package/src/route/route.trie.ts +0 -265
  230. package/src/type/element.type.ts +0 -22
  231. package/src/type/logger.type.ts +0 -24
  232. package/src/type/markdown.type.ts +0 -21
  233. package/src/type/route-tree.type.ts +0 -51
  234. package/src/type/route.type.ts +0 -124
  235. package/src/type/widget.type.ts +0 -65
  236. package/src/util/logger.util.ts +0 -83
  237. package/src/widget/widget.registry.ts +0 -51
  238. /package/dist/{src/route → core/util}/route-tree.util.d.ts +0 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pure HTML utilities. No DOM, no browser APIs.
3
+ */
4
+ /** HTML attribute name marking a widget as server-rendered. */
5
+ export const SSR_ATTR = 'ssr';
6
+ /** HTML attribute name for lazy-loading widgets. */
7
+ export const LAZY_ATTR = 'lazy';
8
+ const BLOCKED_PROTOCOLS = /^(javascript|data|vbscript):/i;
9
+ /** Throw if a redirect URL uses a dangerous protocol. */
10
+ export function assertSafeRedirect(url) {
11
+ if (BLOCKED_PROTOCOLS.test(url.trim())) {
12
+ throw new Error(`Unsafe redirect URL blocked: ${url}`);
13
+ }
14
+ }
15
+ export function escapeHtml(text) {
16
+ return text
17
+ .replaceAll('&', '&')
18
+ .replaceAll('<', '&lt;')
19
+ .replaceAll('>', '&gt;')
20
+ .replaceAll('"', '&quot;')
21
+ .replaceAll("'", '&#39;')
22
+ .replaceAll('`', '&#96;');
23
+ }
24
+ export function unescapeHtml(text) {
25
+ return text
26
+ .replaceAll('&#96;', '`')
27
+ .replaceAll('&#39;', "'")
28
+ .replaceAll('&quot;', '"')
29
+ .replaceAll('&gt;', '>')
30
+ .replaceAll('&lt;', '<')
31
+ .replaceAll('&amp;', '&');
32
+ }
33
+ export function scopeWidgetCss(css, widgetName) {
34
+ return `@scope (widget-${widgetName}) {\n${css}\n}`;
35
+ }
36
+ /** Status code to message mapping. */
37
+ export const STATUS_MESSAGES = {
38
+ 401: 'Unauthorized',
39
+ 403: 'Forbidden',
40
+ 404: 'Not Found',
41
+ 500: 'Internal Server Error',
42
+ };
43
+ //# sourceMappingURL=html.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.util.js","sourceRoot":"","sources":["../../../core/util/html.util.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAE9B,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC,MAAM,iBAAiB,GAAG,+BAA+B,CAAC;AAE1D,yDAAyD;AACzD,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI;SACR,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC;SACxB,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC;SACxB,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC;SACzB,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC;SACvB,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC;SACvB,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,UAAkB;IAC5D,OAAO,kBAAkB,UAAU,QAAQ,GAAG,KAAK,CAAC;AACtD,CAAC;AAED,sCAAsC;AACtC,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,uBAAuB;CAC7B,CAAC"}
@@ -4,5 +4,4 @@
4
4
  * Rewrites internal absolute links in markdown to include a base path prefix.
5
5
  * Skips fenced code blocks and links already under a known base path.
6
6
  */
7
- /** Rewrite internal absolute links in markdown to include the base path prefix. */
8
7
  export declare function rewriteMdLinks(markdown: string, base: string, skipPrefixes: string[]): string;
@@ -4,10 +4,8 @@
4
4
  * Rewrites internal absolute links in markdown to include a base path prefix.
5
5
  * Skips fenced code blocks and links already under a known base path.
6
6
  */
7
- /** Rewrite internal absolute links in markdown to include the base path prefix. */
8
7
  export function rewriteMdLinks(markdown, base, skipPrefixes) {
9
8
  const prefix = base + '/';
10
- // Negative lookahead: skip links already under a known base path
11
9
  const skip = skipPrefixes.map((p) => p.slice(1) + '/').join('|');
12
10
  const inlineRe = new RegExp(`\\]\\(\\/(?!${skip})`, 'g');
13
11
  const refRe = new RegExp(`^(\\[[^\\]]+\\]:\\s+)\\/(?!${skip})`, 'g');
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md.util.js","sourceRoot":"","sources":["../../../core/util/md.util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAY,EAAE,YAAsB;IACnF,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;IAC1B,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,eAAe,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,8BAA8B,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,WAAW,GAAG,CAAC,WAAW,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,IAAI,WAAW;YAAE,SAAS;QAE1B,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;QACzD,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -15,7 +15,6 @@ export function resolveTargetNode(node, name, isRoot) {
15
15
  if (name === 'index') {
16
16
  if (isRoot)
17
17
  return node;
18
- // Non-root index → wildcard catch-all
19
18
  node.wildcard ??= { param: 'rest', child: {} };
20
19
  return node.wildcard.child;
21
20
  }
@@ -24,7 +23,6 @@ export function resolveTargetNode(node, name, isRoot) {
24
23
  node.dynamic ??= { param, child: {} };
25
24
  return node.dynamic.child;
26
25
  }
27
- // Static segment
28
26
  node.children ??= {};
29
27
  node.children[name] ??= {};
30
28
  return node.children[name];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-tree.util.js","sourceRoot":"","sources":["../../../core/util/route-tree.util.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAe,EAAE,IAAY,EAAE,MAAe;IAC9E,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,CAAC,QAAQ,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC;IACrB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Widget Resolve Utilities
3
+ *
4
+ * Server-side resolution of <widget-*> tags in HTML.
5
+ * Calls getData() + renderHTML() on widgets and injects SSR hydration data.
6
+ */
7
+ import type { Component } from '../component/abstract.component.ts';
8
+ import type { ContextProvider } from '../type/component.type.ts';
9
+ import { type Logger } from '../type/logger.type.ts';
10
+ import type { RouteInfo } from '../type/route.type.ts';
11
+ /** Maximum nesting depth for widgets to prevent infinite loops */
12
+ export declare const MAX_WIDGET_DEPTH = 10;
13
+ /**
14
+ * Recursively resolve widgets in content with depth limit.
15
+ */
16
+ export declare function resolveRecursively<T>(content: string, parse: (content: string) => T[], resolve: (widget: T) => Promise<string>, replace: (content: string, replacements: Map<T, string>) => string, depth?: number, logger?: Logger): Promise<string>;
17
+ /**
18
+ * Resolve <widget-*> tags in HTML by calling getData() + renderHTML().
19
+ */
20
+ export declare function resolveWidgetTags(html: string, registry: {
21
+ get(name: string): Component | undefined;
22
+ }, routeInfo: RouteInfo, loadFiles?: (widgetName: string) => Promise<{
23
+ html?: string;
24
+ md?: string;
25
+ css?: string;
26
+ }>, contextProvider?: ContextProvider, logger?: Logger): Promise<string>;
27
+ /** Parse HTML attribute string into params object. */
28
+ export declare function parseAttrsToParams(attrsString: string): Record<string, unknown>;
@@ -4,25 +4,14 @@
4
4
  * Server-side resolution of <widget-*> tags in HTML.
5
5
  * Calls getData() + renderHTML() on widgets and injects SSR hydration data.
6
6
  */
7
- import { logger } from "../type/logger.type.js";
7
+ import { defaultLogger } from "../type/logger.type.js";
8
8
  import { LAZY_ATTR, SSR_ATTR } from "./html.util.js";
9
9
  /** Maximum nesting depth for widgets to prevent infinite loops */
10
10
  export const MAX_WIDGET_DEPTH = 10;
11
11
  /**
12
12
  * Recursively resolve widgets in content with depth limit.
13
- *
14
- * Generic utility used by both HTML and Markdown widget resolution.
15
- * Each depth level processes all widgets concurrently, then recurses
16
- * into each rendered result to resolve nested widgets.
17
- *
18
- * @param content - Content containing widgets
19
- * @param parse - Find widgets in content
20
- * @param resolve - Resolve a single widget to rendered output
21
- * @param replace - Replace widgets with resolved content
22
- * @param depth - Current recursion depth (internal)
23
- * @returns Content with all widgets recursively resolved
24
13
  */
25
- export async function resolveRecursively(content, parse, resolve, replace, depth = 0) {
14
+ export async function resolveRecursively(content, parse, resolve, replace, depth = 0, logger = defaultLogger) {
26
15
  if (depth >= MAX_WIDGET_DEPTH) {
27
16
  logger.warn(`Widget nesting depth limit reached (${MAX_WIDGET_DEPTH}). ` +
28
17
  'Possible circular dependency or excessive nesting.');
@@ -34,33 +23,18 @@ export async function resolveRecursively(content, parse, resolve, replace, depth
34
23
  const replacements = new Map();
35
24
  await Promise.all(widgets.map(async (widget) => {
36
25
  let rendered = await resolve(widget);
37
- // Recursively resolve any nested widgets in the rendered output
38
- rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1);
26
+ rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1, logger);
39
27
  replacements.set(widget, rendered);
40
28
  }));
41
29
  return replace(content, replacements);
42
30
  }
43
31
  /**
44
- * Resolve <widget-*> tags in HTML by calling getData() + renderHTML()
45
- * via the widget registry. Injects rendered content and boolean ssr attribute.
46
- *
47
- * Supports nested widgets: if a widget's renderHTML() returns HTML containing
48
- * other <widget-*> tags, those will be resolved recursively up to MAX_WIDGET_DEPTH.
49
- *
50
- * Before: <widget-crypto-price coin="bitcoin"></widget-crypto-price>
51
- * After: <widget-crypto-price coin="bitcoin" ssr><template shadowrootmode="open"><span>$42,000</span></template></widget-crypto-price>
52
- *
53
- * When a widget has `exposeSsrData = true`, the getData() result is serialized
54
- * as JSON text in the light DOM (alongside the shadow root template):
55
- * After: <widget-crypto-price coin="bitcoin" ssr><template shadowrootmode="open"><span>$42,000</span></template>{"price":42000}</widget-crypto-price>
32
+ * Resolve <widget-*> tags in HTML by calling getData() + renderHTML().
56
33
  */
57
- export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextProvider) {
34
+ export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextProvider, logger = defaultLogger) {
58
35
  const tagPattern = /<widget-(?<name>[a-z][a-z0-9-]*)(?<attrs>\s[^>]*)?>(?<content>.*?)<\/widget-\k<name>>/gis;
59
- // Wrapping info stored per-match so replace() can apply it after recursion
60
36
  const wrappers = new Map();
61
- // Matches standalone ssr attribute (boolean or with value), not as substring of another value
62
37
  const ssrAttrPattern = new RegExp(`\\s${SSR_ATTR}(?:\\s|=|$)`);
63
- // Parse: find unprocessed widget tags
64
38
  const parse = (content) => {
65
39
  const matches = content.matchAll(tagPattern).toArray();
66
40
  return matches.filter((match) => {
@@ -68,18 +42,17 @@ export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextP
68
42
  return !ssrAttrPattern.test(attrsString);
69
43
  });
70
44
  };
71
- // Resolve: render a single widget's inner content (no outer tag wrapping — that's in replace)
72
45
  const resolve = async (match) => {
73
46
  const widgetName = match.groups.name;
74
47
  const attrsString = match.groups.attrs?.trim() ?? '';
75
48
  const widget = registry.get(widgetName);
76
49
  if (!widget)
77
- return match[0]; // no widget found — leave original tag as-is
50
+ return match[0];
78
51
  const params = parseAttrsToParams(attrsString);
79
52
  try {
80
53
  let files;
81
54
  if (loadFiles) {
82
- files = await loadFiles(widgetName, widget.files);
55
+ files = await loadFiles(widgetName);
83
56
  }
84
57
  const baseContext = {
85
58
  ...routeInfo,
@@ -90,7 +63,6 @@ export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextP
90
63
  const context = contextProvider ? contextProvider(baseContext) : baseContext;
91
64
  const data = await widget.getData({ params, context });
92
65
  const rendered = widget.renderHTML({ data, params, context });
93
- // Store wrapping info — applied in replace() after recursion resolves nested widgets
94
66
  wrappers.set(match, {
95
67
  tagName: `widget-${widgetName}`,
96
68
  attrs: attrsString ? ` ${attrsString}` : '',
@@ -100,10 +72,9 @@ export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextP
100
72
  }
101
73
  catch (e) {
102
74
  logger.error(`[SSR HTML] Widget "${widgetName}" render failed`, e instanceof Error ? e : undefined);
103
- return match[0]; // render failed — leave original tag as-is
75
+ return match[0];
104
76
  }
105
77
  };
106
- // Replace: wrap resolved content in outer tag + DSD template, then substitute by index
107
78
  const replace = (content, replacements) => {
108
79
  let result = content;
109
80
  const entries = [...replacements.entries()].sort((a, b) => b[0].index - a[0].index);
@@ -114,14 +85,14 @@ export function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextP
114
85
  const lightDomData = wrap?.ssrData ? wrap.ssrData : '';
115
86
  const replacement = wrap
116
87
  ? `<${wrap.tagName}${wrap.attrs} ${SSR_ATTR}><template shadowrootmode="open">${innerHtml}</template>${lightDomData}</${wrap.tagName}>`
117
- : innerHtml; // no wrapper = unresolved widget, innerHtml is the original tag
88
+ : innerHtml;
118
89
  result = result.slice(0, start) + replacement + result.slice(end);
119
90
  }
120
91
  return result;
121
92
  };
122
- return resolveRecursively(html, parse, resolve, replace);
93
+ return resolveRecursively(html, parse, resolve, replace, 0, logger);
123
94
  }
124
- /** Parse HTML attribute string into params object (kebab→camelCase, JSON.parse with string fallback). */
95
+ /** Parse HTML attribute string into params object. */
125
96
  export function parseAttrsToParams(attrsString) {
126
97
  const params = {};
127
98
  if (!attrsString)
@@ -129,7 +100,7 @@ export function parseAttrsToParams(attrsString) {
129
100
  const attrPattern = /(?<attr>[a-z][a-z0-9-]*)(?:="(?<dq>[^"]*)"|='(?<sq>[^']*)'|=(?<uq>[^\s>]+))?/gi;
130
101
  for (const match of attrsString.matchAll(attrPattern)) {
131
102
  const { attr: attrName, dq, sq, uq } = match.groups;
132
- if (attrName === SSR_ATTR || attrName === LAZY_ATTR)
103
+ if (!attrName || attrName === SSR_ATTR || attrName === LAZY_ATTR)
133
104
  continue;
134
105
  const key = attrName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
135
106
  const rawValue = dq ?? sq ?? uq;
@@ -147,7 +118,6 @@ export function parseAttrsToParams(attrsString) {
147
118
  }
148
119
  return params;
149
120
  }
150
- /** Escape a value for use in a single-quoted HTML attribute. */
151
121
  function escapeAttr(value) {
152
122
  return value.replaceAll('&', '&amp;').replaceAll("'", '&#39;');
153
123
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-resolve.util.js","sourceRoot":"","sources":["../../../core/util/widget-resolve.util.ts"],"names":[],"mappings":"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"}
@@ -9,18 +9,5 @@
9
9
  * ```
10
10
  */
11
11
  import type { ParsedWidgetBlock } from '../type/widget.type.ts';
12
- /**
13
- * Parse all widget blocks from markdown content.
14
- *
15
- * @param markdown - Markdown content to parse
16
- * @returns Array of parsed widget blocks with positions
17
- */
18
12
  export declare function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[];
19
- /**
20
- * Replace widget blocks in markdown with rendered content.
21
- *
22
- * @param markdown - Original markdown content
23
- * @param replacements - Map of parsed blocks to replacement strings
24
- * @returns Markdown with widget blocks replaced
25
- */
26
13
  export declare function replaceWidgetBlocks(markdown: string, replacements: Map<ParsedWidgetBlock, string>): string;
@@ -8,17 +8,7 @@
8
8
  * {"key": "value"}
9
9
  * ```
10
10
  */
11
- /**
12
- * Pattern to match widget fenced code blocks.
13
- * Captures: widget name, params content
14
- */
15
11
  const WIDGET_PATTERN = /```widget:(?<name>[a-z][a-z0-9-]*)\n(?<params>.*?)```/gs;
16
- /**
17
- * Parse all widget blocks from markdown content.
18
- *
19
- * @param markdown - Markdown content to parse
20
- * @returns Array of parsed widget blocks with positions
21
- */
22
12
  export function parseWidgetBlocks(markdown) {
23
13
  const blocks = [];
24
14
  for (const match of markdown.matchAll(WIDGET_PATTERN)) {
@@ -28,12 +18,11 @@ export function parseWidgetBlocks(markdown) {
28
18
  const startIndex = match.index;
29
19
  const block = {
30
20
  fullMatch,
31
- widgetName,
21
+ widgetName: widgetName,
32
22
  params: null,
33
23
  startIndex,
34
24
  endIndex: startIndex + fullMatch.length,
35
25
  };
36
- // Parse JSON params if present
37
26
  if (paramsJson) {
38
27
  try {
39
28
  const parsed = JSON.parse(paramsJson);
@@ -49,23 +38,13 @@ export function parseWidgetBlocks(markdown) {
49
38
  }
50
39
  }
51
40
  else {
52
- // Empty params is valid - use empty object
53
41
  block.params = {};
54
42
  }
55
43
  blocks.push(block);
56
44
  }
57
45
  return blocks;
58
46
  }
59
- /**
60
- * Replace widget blocks in markdown with rendered content.
61
- *
62
- * @param markdown - Original markdown content
63
- * @param replacements - Map of parsed blocks to replacement strings
64
- * @returns Markdown with widget blocks replaced
65
- */
66
47
  export function replaceWidgetBlocks(markdown, replacements) {
67
- // Sort blocks by position descending to replace from end first
68
- // This preserves indices during replacement
69
48
  const sortedBlocks = [...replacements.entries()].sort(([a], [b]) => b.startIndex - a.startIndex);
70
49
  let result = markdown;
71
50
  for (const [block, replacement] of sortedBlocks) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.parser.js","sourceRoot":"","sources":["../../../core/widget/widget.parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,cAAc,GAAG,yDAAyD,CAAC;AAEjF,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACtD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,MAAO,CAAC;QAC9D,MAAM,UAAU,GAAG,SAAU,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;QAE/B,MAAM,KAAK,GAAsB;YAC/B,SAAS;YACT,UAAU,EAAE,UAAW;YACvB,MAAM,EAAE,IAAI;YACZ,UAAU;YACV,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC,MAAM;SACxC,CAAC;QAEF,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5E,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,UAAU,GAAG,8BAA8B,CAAC;gBACpD,CAAC;YACH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,KAAK,CAAC,UAAU,GAAG,iBAAiB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACnF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;QACpB,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,YAA4C;IAE5C,MAAM,YAAY,GAAG,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACnD,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAC1C,CAAC;IAEF,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,KAAK,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,YAAY,EAAE,CAAC;QAChD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Widget Registry
3
+ *
4
+ * Name → Component lookup. Used by all renderers.
5
+ * Pages are NOT in this registry — they live in the routes manifest.
6
+ */
7
+ import type { WidgetComponent } from '../component/widget.component.ts';
8
+ export declare class WidgetRegistry {
9
+ private entries;
10
+ add(widget: WidgetComponent, modulePath?: string): void;
11
+ get(name: string): WidgetComponent | undefined;
12
+ getModulePath(name: string): string | undefined;
13
+ [Symbol.iterator](): IterableIterator<WidgetComponent>;
14
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Widget Registry
3
+ *
4
+ * Name → Component lookup. Used by all renderers.
5
+ * Pages are NOT in this registry — they live in the routes manifest.
6
+ */
7
+ export class WidgetRegistry {
8
+ entries = new Map();
9
+ add(widget, modulePath) {
10
+ this.entries.set(widget.name, { widget, modulePath });
11
+ }
12
+ get(name) {
13
+ return this.entries.get(name)?.widget;
14
+ }
15
+ getModulePath(name) {
16
+ return this.entries.get(name)?.modulePath;
17
+ }
18
+ [Symbol.iterator]() {
19
+ const entries = this.entries.values();
20
+ return (function* () {
21
+ for (const entry of entries)
22
+ yield entry.widget;
23
+ })();
24
+ }
25
+ }
26
+ //# sourceMappingURL=widget.registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.registry.js","sourceRoot":"","sources":["../../../core/widget/widget.registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,OAAO,cAAc;IACjB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnD,GAAG,CAAC,MAAuB,EAAE,UAAmB;QAC9C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACxC,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC5C,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,CAAC,QAAQ,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,OAAO;gBAAE,MAAM,KAAK,CAAC,MAAM,CAAC;QAClD,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;CACF"}