@zeix/le-truc 0.15.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 (406) hide show
  1. package/.ai-context.md +234 -0
  2. package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
  3. package/.editorconfig +12 -0
  4. package/.github/copilot-instructions.md +62 -0
  5. package/.github/workflows/codeql.yml +108 -0
  6. package/.github/workflows/static.yml +43 -0
  7. package/.prettierrc +17 -0
  8. package/CLAUDE.md +215 -0
  9. package/CODE_OF_CONDUCT.md +128 -0
  10. package/CONTRIBUTING.md +160 -0
  11. package/LICENSE +21 -0
  12. package/README.md +474 -0
  13. package/biome.json +295 -0
  14. package/bun.lock +239 -0
  15. package/docs/about.html +105 -0
  16. package/docs/assets/main.css +1 -0
  17. package/docs/assets/main.js +10 -0
  18. package/docs/assets/main.js.map +66 -0
  19. package/docs/components.html +293 -0
  20. package/docs/data-flow.html +308 -0
  21. package/docs/examples/basic-button.html +367 -0
  22. package/docs/examples/basic-counter.html +188 -0
  23. package/docs/examples/basic-hello.html +138 -0
  24. package/docs/examples/basic-number.html +271 -0
  25. package/docs/examples/basic-pluralize.html +214 -0
  26. package/docs/examples/card-callout.html +152 -0
  27. package/docs/examples/card-mediaqueries.html +138 -0
  28. package/docs/examples/context-media.html +198 -0
  29. package/docs/examples/empty.html +37 -0
  30. package/docs/examples/form-checkbox.html +233 -0
  31. package/docs/examples/form-combobox.html +420 -0
  32. package/docs/examples/form-listbox.html +434 -0
  33. package/docs/examples/form-radiogroup.html +296 -0
  34. package/docs/examples/form-spinbutton.html +402 -0
  35. package/docs/examples/form-textbox.html +361 -0
  36. package/docs/examples/layout.html +67 -0
  37. package/docs/examples/module-carousel.html +552 -0
  38. package/docs/examples/module-catalog.html +241 -0
  39. package/docs/examples/module-codeblock.html +270 -0
  40. package/docs/examples/module-dialog.html +343 -0
  41. package/docs/examples/module-lazyload.html +289 -0
  42. package/docs/examples/module-list.html +197 -0
  43. package/docs/examples/module-pagination.html +283 -0
  44. package/docs/examples/module-scrollarea.html +447 -0
  45. package/docs/examples/module-tabgroup.html +526 -0
  46. package/docs/examples/module-todo.html +367 -0
  47. package/docs/examples/module-with-type.html +63 -0
  48. package/docs/examples/nested-components.html +88 -0
  49. package/docs/examples/recursive.html +56 -0
  50. package/docs/examples/simple-text.html +39 -0
  51. package/docs/examples/snippet.html +93 -0
  52. package/docs/examples/with-styles.html +75 -0
  53. package/docs/getting-started.html +143 -0
  54. package/docs/index.html +112 -0
  55. package/docs/sitemap.xml +28 -0
  56. package/docs/styling.html +160 -0
  57. package/docs/sw.js +112 -0
  58. package/docs-src/api/README.md +478 -0
  59. package/docs-src/api/_media/LICENSE +21 -0
  60. package/docs-src/api/classes/CircularDependencyError.md +299 -0
  61. package/docs-src/api/classes/CircularMutationError.md +301 -0
  62. package/docs-src/api/classes/ContextRequestEvent.md +590 -0
  63. package/docs-src/api/classes/DependencyTimeoutError.md +301 -0
  64. package/docs-src/api/classes/InvalidCallbackError.md +303 -0
  65. package/docs-src/api/classes/InvalidComponentNameError.md +295 -0
  66. package/docs-src/api/classes/InvalidCustomElementError.md +301 -0
  67. package/docs-src/api/classes/InvalidEffectsError.md +301 -0
  68. package/docs-src/api/classes/InvalidPropertyNameError.md +307 -0
  69. package/docs-src/api/classes/InvalidReactivesError.md +307 -0
  70. package/docs-src/api/classes/InvalidSignalValueError.md +303 -0
  71. package/docs-src/api/classes/MissingElementError.md +307 -0
  72. package/docs-src/api/classes/NullishSignalValueError.md +299 -0
  73. package/docs-src/api/classes/StoreKeyExistsError.md +303 -0
  74. package/docs-src/api/classes/StoreKeyRangeError.md +299 -0
  75. package/docs-src/api/classes/StoreKeyReadonlyError.md +303 -0
  76. package/docs-src/api/functions/asBoolean.md +21 -0
  77. package/docs-src/api/functions/asEnum.md +31 -0
  78. package/docs-src/api/functions/asInteger.md +39 -0
  79. package/docs-src/api/functions/asJSON.md +49 -0
  80. package/docs-src/api/functions/asNumber.md +37 -0
  81. package/docs-src/api/functions/asString.md +37 -0
  82. package/docs-src/api/functions/createCollection.md +83 -0
  83. package/docs-src/api/functions/createSensor.md +71 -0
  84. package/docs-src/api/functions/dangerouslySetInnerHTML.md +48 -0
  85. package/docs-src/api/functions/defineComponent.md +65 -0
  86. package/docs-src/api/functions/isCollection.md +37 -0
  87. package/docs-src/api/functions/isParser.md +41 -0
  88. package/docs-src/api/functions/match.md +47 -0
  89. package/docs-src/api/functions/on.md +58 -0
  90. package/docs-src/api/functions/pass.md +53 -0
  91. package/docs-src/api/functions/provideContexts.md +47 -0
  92. package/docs-src/api/functions/read.md +47 -0
  93. package/docs-src/api/functions/requestContext.md +51 -0
  94. package/docs-src/api/functions/resolve.md +40 -0
  95. package/docs-src/api/functions/runEffects.md +51 -0
  96. package/docs-src/api/functions/runElementEffects.md +57 -0
  97. package/docs-src/api/functions/schedule.md +33 -0
  98. package/docs-src/api/functions/setAttribute.md +48 -0
  99. package/docs-src/api/functions/setProperty.md +52 -0
  100. package/docs-src/api/functions/setStyle.md +48 -0
  101. package/docs-src/api/functions/setText.md +42 -0
  102. package/docs-src/api/functions/show.md +42 -0
  103. package/docs-src/api/functions/toSignal.md +37 -0
  104. package/docs-src/api/functions/toggleAttribute.md +48 -0
  105. package/docs-src/api/functions/toggleClass.md +48 -0
  106. package/docs-src/api/functions/updateElement.md +53 -0
  107. package/docs-src/api/globals.md +131 -0
  108. package/docs-src/api/type-aliases/Cleanup.md +27 -0
  109. package/docs-src/api/type-aliases/Collection.md +91 -0
  110. package/docs-src/api/type-aliases/CollectionListener.md +27 -0
  111. package/docs-src/api/type-aliases/Component.md +17 -0
  112. package/docs-src/api/type-aliases/ComponentProp.md +11 -0
  113. package/docs-src/api/type-aliases/ComponentProps.md +11 -0
  114. package/docs-src/api/type-aliases/ComponentSetup.md +31 -0
  115. package/docs-src/api/type-aliases/ComponentUI.md +27 -0
  116. package/docs-src/api/type-aliases/Computed.md +49 -0
  117. package/docs-src/api/type-aliases/ComputedCallback.md +29 -0
  118. package/docs-src/api/type-aliases/Context.md +33 -0
  119. package/docs-src/api/type-aliases/ContextType.md +19 -0
  120. package/docs-src/api/type-aliases/DangerouslySetInnerHTMLOptions.md +27 -0
  121. package/docs-src/api/type-aliases/DiffResult.md +61 -0
  122. package/docs-src/api/type-aliases/Effect.md +35 -0
  123. package/docs-src/api/type-aliases/EffectCallback.md +23 -0
  124. package/docs-src/api/type-aliases/Effects.md +21 -0
  125. package/docs-src/api/type-aliases/ElementEffects.md +21 -0
  126. package/docs-src/api/type-aliases/ElementFromKey.md +21 -0
  127. package/docs-src/api/type-aliases/ElementQueries.md +27 -0
  128. package/docs-src/api/type-aliases/ElementUpdater.md +131 -0
  129. package/docs-src/api/type-aliases/EventHandler.md +31 -0
  130. package/docs-src/api/type-aliases/EventType.md +17 -0
  131. package/docs-src/api/type-aliases/Fallback.md +21 -0
  132. package/docs-src/api/type-aliases/Initializers.md +21 -0
  133. package/docs-src/api/type-aliases/LooseReader.md +31 -0
  134. package/docs-src/api/type-aliases/MatchHandlers.md +77 -0
  135. package/docs-src/api/type-aliases/MaybeCleanup.md +23 -0
  136. package/docs-src/api/type-aliases/MaybeSignal.md +17 -0
  137. package/docs-src/api/type-aliases/Parser.md +39 -0
  138. package/docs-src/api/type-aliases/ParserOrFallback.md +21 -0
  139. package/docs-src/api/type-aliases/PassedProp.md +25 -0
  140. package/docs-src/api/type-aliases/PassedProps.md +21 -0
  141. package/docs-src/api/type-aliases/Reactive.md +25 -0
  142. package/docs-src/api/type-aliases/Reader.md +31 -0
  143. package/docs-src/api/type-aliases/ReservedWords.md +11 -0
  144. package/docs-src/api/type-aliases/ResolveResult.md +29 -0
  145. package/docs-src/api/type-aliases/SensorEvents.md +25 -0
  146. package/docs-src/api/type-aliases/Signal.md +41 -0
  147. package/docs-src/api/type-aliases/State.md +85 -0
  148. package/docs-src/api/type-aliases/Store.md +29 -0
  149. package/docs-src/api/type-aliases/UI.md +11 -0
  150. package/docs-src/api/type-aliases/UnknownContext.md +13 -0
  151. package/docs-src/api/variables/CONTEXT_REQUEST.md +11 -0
  152. package/docs-src/api/variables/UNSET.md +23 -0
  153. package/docs-src/api/variables/batch.md +25 -0
  154. package/docs-src/api/variables/createComputed.md +41 -0
  155. package/docs-src/api/variables/createEffect.md +35 -0
  156. package/docs-src/api/variables/createState.md +37 -0
  157. package/docs-src/api/variables/createStore.md +42 -0
  158. package/docs-src/api/variables/diff.md +43 -0
  159. package/docs-src/api/variables/isAbortError.md +33 -0
  160. package/docs-src/api/variables/isAsyncFunction.md +39 -0
  161. package/docs-src/api/variables/isComputed.md +37 -0
  162. package/docs-src/api/variables/isEqual.md +49 -0
  163. package/docs-src/api/variables/isFunction.md +39 -0
  164. package/docs-src/api/variables/isMutableSignal.md +37 -0
  165. package/docs-src/api/variables/isNumber.md +33 -0
  166. package/docs-src/api/variables/isRecord.md +39 -0
  167. package/docs-src/api/variables/isRecordOrArray.md +39 -0
  168. package/docs-src/api/variables/isSignal.md +37 -0
  169. package/docs-src/api/variables/isState.md +37 -0
  170. package/docs-src/api/variables/isStore.md +37 -0
  171. package/docs-src/api/variables/isString.md +33 -0
  172. package/docs-src/api/variables/isSymbol.md +33 -0
  173. package/docs-src/api/variables/toError.md +33 -0
  174. package/docs-src/api/variables/valueString.md +33 -0
  175. package/docs-src/includes/menu.html +44 -0
  176. package/docs-src/pages/about.md +89 -0
  177. package/docs-src/pages/components.md +437 -0
  178. package/docs-src/pages/data-flow.md +449 -0
  179. package/docs-src/pages/getting-started.md +170 -0
  180. package/docs-src/pages/index.md +98 -0
  181. package/docs-src/pages/styling.md +165 -0
  182. package/eslint.config.js +64 -0
  183. package/examples/_common/clear.ts +49 -0
  184. package/examples/_common/fetch.ts +160 -0
  185. package/examples/_common/focus.ts +45 -0
  186. package/examples/_common/highlight.ts +5 -0
  187. package/examples/_global.css +463 -0
  188. package/examples/basic-button/basic-button.css +176 -0
  189. package/examples/basic-button/basic-button.html +46 -0
  190. package/examples/basic-button/basic-button.spec.ts +160 -0
  191. package/examples/basic-button/basic-button.ts +45 -0
  192. package/examples/basic-button/copyToClipboard.ts +37 -0
  193. package/examples/basic-counter/basic-counter.css +21 -0
  194. package/examples/basic-counter/basic-counter.html +24 -0
  195. package/examples/basic-counter/basic-counter.spec.ts +85 -0
  196. package/examples/basic-counter/basic-counter.ts +43 -0
  197. package/examples/basic-hello/basic-hello.html +34 -0
  198. package/examples/basic-hello/basic-hello.spec.ts +110 -0
  199. package/examples/basic-hello/basic-hello.ts +36 -0
  200. package/examples/basic-number/basic-number.html +79 -0
  201. package/examples/basic-number/basic-number.spec.ts +175 -0
  202. package/examples/basic-number/basic-number.ts +124 -0
  203. package/examples/basic-pluralize/basic-pluralize.html +64 -0
  204. package/examples/basic-pluralize/basic-pluralize.spec.ts +258 -0
  205. package/examples/basic-pluralize/basic-pluralize.ts +82 -0
  206. package/examples/card-callout/card-callout.css +79 -0
  207. package/examples/card-callout/card-callout.html +5 -0
  208. package/examples/card-mediaqueries/card-mediaqueries.html +29 -0
  209. package/examples/card-mediaqueries/card-mediaqueries.spec.ts +300 -0
  210. package/examples/card-mediaqueries/card-mediaqueries.ts +41 -0
  211. package/examples/context-media/context-media.html +3 -0
  212. package/examples/context-media/context-media.ts +127 -0
  213. package/examples/form-checkbox/form-checkbox.css +70 -0
  214. package/examples/form-checkbox/form-checkbox.html +13 -0
  215. package/examples/form-checkbox/form-checkbox.spec.ts +357 -0
  216. package/examples/form-checkbox/form-checkbox.ts +50 -0
  217. package/examples/form-checkbox/vanilla-checkbox.ts +101 -0
  218. package/examples/form-combobox/form-combobox.css +118 -0
  219. package/examples/form-combobox/form-combobox.html +74 -0
  220. package/examples/form-combobox/form-combobox.spec.ts +977 -0
  221. package/examples/form-combobox/form-combobox.ts +128 -0
  222. package/examples/form-listbox/form-listbox.css +71 -0
  223. package/examples/form-listbox/form-listbox.html +67 -0
  224. package/examples/form-listbox/form-listbox.spec.ts +1050 -0
  225. package/examples/form-listbox/form-listbox.ts +196 -0
  226. package/examples/form-listbox/mocks/timezones.json +495 -0
  227. package/examples/form-radiogroup/form-radiogroup.css +87 -0
  228. package/examples/form-radiogroup/form-radiogroup.html +51 -0
  229. package/examples/form-radiogroup/form-radiogroup.spec.ts +515 -0
  230. package/examples/form-radiogroup/form-radiogroup.ts +58 -0
  231. package/examples/form-spinbutton/form-spinbutton.css +95 -0
  232. package/examples/form-spinbutton/form-spinbutton.html +96 -0
  233. package/examples/form-spinbutton/form-spinbutton.spec.ts +688 -0
  234. package/examples/form-spinbutton/form-spinbutton.ts +111 -0
  235. package/examples/form-textbox/form-textbox.css +104 -0
  236. package/examples/form-textbox/form-textbox.html +53 -0
  237. package/examples/form-textbox/form-textbox.spec.ts +542 -0
  238. package/examples/form-textbox/form-textbox.ts +104 -0
  239. package/examples/main.css +22 -0
  240. package/examples/main.ts +23 -0
  241. package/examples/module-carousel/module-carousel.css +113 -0
  242. package/examples/module-carousel/module-carousel.html +208 -0
  243. package/examples/module-carousel/module-carousel.spec.ts +523 -0
  244. package/examples/module-carousel/module-carousel.ts +131 -0
  245. package/examples/module-catalog/module-catalog.css +22 -0
  246. package/examples/module-catalog/module-catalog.html +82 -0
  247. package/examples/module-catalog/module-catalog.spec.ts +396 -0
  248. package/examples/module-catalog/module-catalog.ts +37 -0
  249. package/examples/module-codeblock/module-codeblock.css +95 -0
  250. package/examples/module-codeblock/module-codeblock.html +28 -0
  251. package/examples/module-codeblock/module-codeblock.ts +47 -0
  252. package/examples/module-demo/module-demo.css +13 -0
  253. package/examples/module-dialog/module-dialog.css +96 -0
  254. package/examples/module-dialog/module-dialog.html +66 -0
  255. package/examples/module-dialog/module-dialog.spec.ts +557 -0
  256. package/examples/module-dialog/module-dialog.ts +81 -0
  257. package/examples/module-lazyload/mocks/empty.html +1 -0
  258. package/examples/module-lazyload/mocks/module-with-type.html +27 -0
  259. package/examples/module-lazyload/mocks/nested-components.html +52 -0
  260. package/examples/module-lazyload/mocks/recursive.html +20 -0
  261. package/examples/module-lazyload/mocks/simple-text.html +3 -0
  262. package/examples/module-lazyload/mocks/snippet.html +57 -0
  263. package/examples/module-lazyload/mocks/with-styles.html +39 -0
  264. package/examples/module-lazyload/module-lazyload.html +132 -0
  265. package/examples/module-lazyload/module-lazyload.spec.ts +734 -0
  266. package/examples/module-lazyload/module-lazyload.ts +89 -0
  267. package/examples/module-list/module-list.html +30 -0
  268. package/examples/module-list/module-list.spec.ts +592 -0
  269. package/examples/module-list/module-list.ts +99 -0
  270. package/examples/module-pagination/module-pagination.css +79 -0
  271. package/examples/module-pagination/module-pagination.html +16 -0
  272. package/examples/module-pagination/module-pagination.spec.ts +701 -0
  273. package/examples/module-pagination/module-pagination.ts +88 -0
  274. package/examples/module-scrollarea/module-scrollarea.css +77 -0
  275. package/examples/module-scrollarea/module-scrollarea.html +189 -0
  276. package/examples/module-scrollarea/module-scrollarea.spec.ts +445 -0
  277. package/examples/module-scrollarea/module-scrollarea.ts +81 -0
  278. package/examples/module-tabgroup/module-tabgroup.css +55 -0
  279. package/examples/module-tabgroup/module-tabgroup.html +269 -0
  280. package/examples/module-tabgroup/module-tabgroup.spec.ts +631 -0
  281. package/examples/module-tabgroup/module-tabgroup.ts +102 -0
  282. package/examples/module-toc/module-toc.css +34 -0
  283. package/examples/module-todo/module-todo.css +84 -0
  284. package/examples/module-todo/module-todo.html +92 -0
  285. package/examples/module-todo/module-todo.spec.ts +528 -0
  286. package/examples/module-todo/module-todo.ts +91 -0
  287. package/examples/section-hero/section-hero.css +37 -0
  288. package/examples/section-menu/section-menu.css +81 -0
  289. package/examples/server.ts +95 -0
  290. package/examples/test-setup.md +314 -0
  291. package/index.dev.js +1688 -0
  292. package/index.dev.ts +127 -0
  293. package/index.js +3 -0
  294. package/index.js.map +42 -0
  295. package/index.ts +127 -0
  296. package/package.json +64 -0
  297. package/playwright.config.ts +31 -0
  298. package/server/BUILD_SYSTEM.md +428 -0
  299. package/server/SERVER.md +286 -0
  300. package/server/build.ts +91 -0
  301. package/server/config.ts +130 -0
  302. package/server/effects/api.ts +28 -0
  303. package/server/effects/css.ts +31 -0
  304. package/server/effects/examples.ts +109 -0
  305. package/server/effects/js.ts +32 -0
  306. package/server/effects/menu.ts +34 -0
  307. package/server/effects/pages.ts +178 -0
  308. package/server/effects/service-worker.ts +57 -0
  309. package/server/effects/sitemap.ts +27 -0
  310. package/server/file-signals.ts +361 -0
  311. package/server/file-watcher.ts +77 -0
  312. package/server/io.ts +174 -0
  313. package/server/layout-engine.ts +470 -0
  314. package/server/layout-utils.ts +615 -0
  315. package/server/layouts/api.html +76 -0
  316. package/server/layouts/base.html +37 -0
  317. package/server/layouts/blog.html +115 -0
  318. package/server/layouts/example.html +104 -0
  319. package/server/layouts/overview.html +165 -0
  320. package/server/layouts/page.html +36 -0
  321. package/server/layouts/test.html +24 -0
  322. package/server/markdoc-helpers.ts +217 -0
  323. package/server/markdoc.config.ts +29 -0
  324. package/server/schema/callout.markdoc.ts +17 -0
  325. package/server/schema/carousel.markdoc.ts +118 -0
  326. package/server/schema/demo.markdoc.ts +74 -0
  327. package/server/schema/fence.markdoc.ts +84 -0
  328. package/server/schema/heading.markdoc.ts +23 -0
  329. package/server/schema/hero.markdoc.ts +59 -0
  330. package/server/schema/section.markdoc.ts +10 -0
  331. package/server/schema/slide.markdoc.ts +17 -0
  332. package/server/schema/source.markdoc.ts +53 -0
  333. package/server/schema/tabgroup.markdoc.ts +102 -0
  334. package/server/serve.ts +635 -0
  335. package/server/templates/README.md +352 -0
  336. package/server/templates/constants.ts +236 -0
  337. package/server/templates/fragments.ts +159 -0
  338. package/server/templates/hmr.ts +269 -0
  339. package/server/templates/menu.ts +33 -0
  340. package/server/templates/performance-hints.ts +94 -0
  341. package/server/templates/service-worker.ts +403 -0
  342. package/server/templates/sitemap.ts +57 -0
  343. package/server/templates/toc.ts +41 -0
  344. package/server/templates/utils.ts +378 -0
  345. package/src/component.ts +215 -0
  346. package/src/context.ts +156 -0
  347. package/src/effects/attribute.ts +82 -0
  348. package/src/effects/class.ts +28 -0
  349. package/src/effects/event.ts +67 -0
  350. package/src/effects/html.ts +60 -0
  351. package/src/effects/method.ts +57 -0
  352. package/src/effects/pass.ts +103 -0
  353. package/src/effects/property.ts +57 -0
  354. package/src/effects/style.ts +34 -0
  355. package/src/effects/text.ts +28 -0
  356. package/src/effects.ts +412 -0
  357. package/src/errors.ts +160 -0
  358. package/src/parsers/boolean.ts +14 -0
  359. package/src/parsers/json.ts +33 -0
  360. package/src/parsers/number.ts +55 -0
  361. package/src/parsers/string.ts +32 -0
  362. package/src/parsers.ts +90 -0
  363. package/src/scheduler.ts +47 -0
  364. package/src/signals/collection.ts +253 -0
  365. package/src/signals/sensor.ts +131 -0
  366. package/src/ui.ts +236 -0
  367. package/src/util.ts +187 -0
  368. package/tsconfig.json +34 -0
  369. package/types/examples/basic-button/basic-button.d.ts +16 -0
  370. package/types/examples/basic-hello/basic-hello.d.ts +18 -0
  371. package/types/index.d.ts +27 -0
  372. package/types/index.dev.d.ts +27 -0
  373. package/types/src/collection.d.ts +27 -0
  374. package/types/src/component.d.ts +32 -0
  375. package/types/src/context.d.ts +85 -0
  376. package/types/src/effects/attribute.d.ts +23 -0
  377. package/types/src/effects/callMethod.d.ts +23 -0
  378. package/types/src/effects/class.d.ts +13 -0
  379. package/types/src/effects/dangerouslySetInnerHTML.d.ts +18 -0
  380. package/types/src/effects/event.d.ts +18 -0
  381. package/types/src/effects/html.d.ts +17 -0
  382. package/types/src/effects/method.d.ts +22 -0
  383. package/types/src/effects/pass.d.ts +18 -0
  384. package/types/src/effects/property.d.ts +22 -0
  385. package/types/src/effects/setAttribute.d.ts +24 -0
  386. package/types/src/effects/setProperty.d.ts +23 -0
  387. package/types/src/effects/setStyle.d.ts +14 -0
  388. package/types/src/effects/setText.d.ts +13 -0
  389. package/types/src/effects/style.d.ts +13 -0
  390. package/types/src/effects/text.d.ts +12 -0
  391. package/types/src/effects/toggleClass.d.ts +14 -0
  392. package/types/src/effects.d.ts +153 -0
  393. package/types/src/errors.d.ts +99 -0
  394. package/types/src/events.d.ts +27 -0
  395. package/types/src/extractors.d.ts +23 -0
  396. package/types/src/parsers/boolean.d.ts +10 -0
  397. package/types/src/parsers/json.d.ts +13 -0
  398. package/types/src/parsers/number.d.ts +21 -0
  399. package/types/src/parsers/string.d.ts +19 -0
  400. package/types/src/parsers.d.ts +41 -0
  401. package/types/src/scheduler.d.ts +11 -0
  402. package/types/src/sensor.d.ts +27 -0
  403. package/types/src/signals/collection.d.ts +32 -0
  404. package/types/src/signals/sensor.d.ts +27 -0
  405. package/types/src/ui.d.ts +37 -0
  406. package/types/src/util.d.ts +65 -0
@@ -0,0 +1,37 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+
7
+ <!-- Page title/description (child layouts may override the title when extending) -->
8
+ <title>{{ title }} – Le Truc Docs</title>
9
+ <meta name="description" content="{{ description }}" />
10
+
11
+ <!-- Core assets (server provides `base-path`, `css-hash` and `js-hash`) -->
12
+ <link
13
+ rel="preload"
14
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
15
+ as="style"
16
+ />
17
+ <link
18
+ rel="modulepreload"
19
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
20
+ />
21
+ <link
22
+ rel="stylesheet"
23
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
24
+ />
25
+ <script
26
+ type="module"
27
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
28
+ ></script>
29
+
30
+ <!-- Additional per-layout head fragment injected by child layouts -->
31
+ {{ head }}
32
+ </head>
33
+
34
+ <body class="{{ section }} {{ body-class }}">
35
+ {{ content }}
36
+ </body>
37
+ </html>
@@ -0,0 +1,115 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{ title }} – Le Truc Blog</title>
7
+ <meta name="description" content="{{ description }}" />
8
+ <meta name="author" content="{{ author }}" />
9
+ <meta name="article:published_time" content="{{ published-date }}" />
10
+ <meta name="article:modified_time" content="{{ modified-date }}" />
11
+ <link
12
+ rel="preload"
13
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
14
+ as="style"
15
+ />
16
+ <link
17
+ rel="modulepreload"
18
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
19
+ />
20
+ <link
21
+ rel="stylesheet"
22
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
23
+ />
24
+ <script
25
+ type="module"
26
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
27
+ ></script>
28
+ </head>
29
+ <body class="blog">
30
+ <context-router>
31
+ <header class="content-grid">
32
+ <a href="#main" class="skiplink visually-hidden">
33
+ Skip to main content
34
+ </a>
35
+ <h1 class="content">Le Truc Docs <small>Version 0.15.0</small></h1>
36
+ {{ include 'menu.html' }}
37
+ <card-callout class="content danger" hidden>
38
+ <p class="error" role="alert" aria-live="assertive"></p>
39
+ </card-callout>
40
+ </header>
41
+ <div class="blog-header">
42
+ <div class="content-grid">
43
+ <div class="content">
44
+ <h1 class="blog-title">{{ title }}</h1>
45
+ <p class="blog-subtitle">{{ description }}</p>
46
+ <div class="blog-meta">
47
+ <div class="blog-meta-item">
48
+ <span>📅</span>
49
+ <time datetime="{{ published-date }}">{{ published-date-formatted }}</time>
50
+ </div>
51
+ <div class="blog-meta-item">
52
+ <span></span>👤</span>
53
+ <span>{{ author }}</span>
54
+ </div>
55
+ <div class="blog-meta-item">
56
+ <span>⏱</span>
57
+ <span>{{ reading-time }} min read</span>
58
+ </div>
59
+ </div>
60
+ <div class="blog-tags">
61
+ {{ blog-tags }}
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ <main id="main" class="content-grid">
67
+ <div class="content">
68
+ <div class="grid" style="grid-template-columns: 1fr 300px; gap: 2rem;">
69
+ <div class="blog-content">
70
+ <article>
71
+ {{ content }}
72
+ </article>
73
+ <div class="blog-author">
74
+ <img src="{{ author-avatar }}" alt="{{ author }}" class="blog-author-avatar" />
75
+ <div class="blog-author-info">
76
+ <h3>{{ author }}</h3>
77
+ <p class="blog-author-bio">{{ author-bio }}</p>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ <aside class="blog-toc">
82
+ <h3>Table of Contents</h3>
83
+ {{ toc }}
84
+ </aside>
85
+ </div>
86
+ </div>
87
+ </main>
88
+ <div class="blog-nav">
89
+ <div class="content-grid">
90
+ <div class="content">
91
+ <nav class="blog-nav-links" aria-label="Blog navigation">
92
+ <a href="{{ prev-post }}" class="blog-nav-link prev">
93
+ <span class="blog-nav-label">← Previous</span>
94
+ <span class="blog-nav-title">{{ prev-post-title }}</span>
95
+ </a>
96
+ <a href="/blog/" class="blog-nav-link">
97
+ 📋 All Posts
98
+ </a>
99
+ <a href="{{ next-post }}" class="blog-nav-link next">
100
+ <span class="blog-nav-label">Next →</span>
101
+ <span class="blog-nav-title">{{ next-post-title }}</span>
102
+ </a>
103
+ </nav>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ <footer class="content-grid">
108
+ <div class="content">
109
+ <h2 class="visually-hidden">Footer</h2>
110
+ <p>© 2024 – 2025 Zeix AG</p>
111
+ </div>
112
+ </footer>
113
+ </context-router>
114
+ </body>
115
+ </html>
@@ -0,0 +1,104 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{ title }} – Le Truc Examples</title>
7
+ <meta name="description" content="{{ description }}" />
8
+ <link
9
+ rel="preload"
10
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
11
+ as="style"
12
+ />
13
+ <link
14
+ rel="modulepreload"
15
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
16
+ />
17
+ <link
18
+ rel="stylesheet"
19
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
20
+ />
21
+ <script
22
+ type="module"
23
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
24
+ ></script>
25
+ </head>
26
+ <body class="example">
27
+ <context-router>
28
+ <header class="content-grid">
29
+ <a href="#main" class="skiplink visually-hidden">
30
+ Skip to main content
31
+ </a>
32
+ <h1 class="content">Le Truc Docs <small>Version 0.15.0</small></h1>
33
+ {{ include 'menu.html' }}
34
+ <card-callout class="content danger" hidden>
35
+ <p class="error" role="alert" aria-live="assertive"></p>
36
+ </card-callout>
37
+ </header>
38
+ <div class="example-header">
39
+ <div class="content-grid">
40
+ <div class="content">
41
+ <h1 class="example-title">{{ example-name }}</h1>
42
+ <p class="example-subtitle">{{ example-description }}</p>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ <div class="example-meta">
47
+ <div class="content-grid">
48
+ <div class="content">
49
+ <div class="example-tags">
50
+ <span
51
+ class="example-tag example-difficulty {{ example-difficulty }}"
52
+ >{{ example-difficulty }}</span
53
+ >
54
+ {{ example-tags }}
55
+ </div>
56
+ <div class="example-actions">
57
+ <a
58
+ href="/test/{{ example-slug }}.html"
59
+ class="example-action primary"
60
+ >
61
+ ▶ Live Demo
62
+ </a>
63
+ <a
64
+ href="{{ example-source }}"
65
+ class="example-action secondary"
66
+ target="_blank"
67
+ rel="noopener"
68
+ >
69
+ 📄 View Source
70
+ </a>
71
+ {{ example-actions }}
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ <main id="main" class="content-grid">
77
+ <div class="content example-content">{{ content }}</div>
78
+ </main>
79
+ <div class="example-nav">
80
+ <div class="content-grid">
81
+ <div class="content">
82
+ <nav class="example-nav-links" aria-label="Example navigation">
83
+ <a href="{{ prev-example }}" class="example-nav-link">
84
+ ← {{ prev-example-title }}
85
+ </a>
86
+ <a href="/examples/" class="example-nav-link">
87
+ 📋 All Examples
88
+ </a>
89
+ <a href="{{ next-example }}" class="example-nav-link">
90
+ {{ next-example-title }} →
91
+ </a>
92
+ </nav>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ <footer class="content-grid">
97
+ <div class="content">
98
+ <h2 class="visually-hidden">Footer</h2>
99
+ <p>© 2024 – 2025 Zeix AG</p>
100
+ </div>
101
+ </footer>
102
+ </context-router>
103
+ </body>
104
+ </html>
@@ -0,0 +1,165 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{ title }} – Le Truc Docs</title>
7
+ <meta name="description" content="{{ description }}" />
8
+ <link
9
+ rel="preload"
10
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
11
+ as="style"
12
+ />
13
+ <link
14
+ rel="modulepreload"
15
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
16
+ />
17
+ <link
18
+ rel="stylesheet"
19
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
20
+ />
21
+ <script
22
+ type="module"
23
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
24
+ ></script>
25
+ </head>
26
+ <body class="{{ section }} overview">
27
+ <context-router>
28
+ <header class="content-grid">
29
+ <a href="#main" class="skiplink visually-hidden">
30
+ Skip to main content
31
+ </a>
32
+ <h1 class="content">Le Truc Docs <small>Version 0.15.0</small></h1>
33
+ {{ include 'menu.html' }}
34
+ <card-callout class="content danger" hidden>
35
+ <p class="error" role="alert" aria-live="assertive"></p>
36
+ </card-callout>
37
+ </header>
38
+ <div class="overview-header">
39
+ <div class="content-grid">
40
+ <div class="content">
41
+ <h1 class="overview-title">{{ overview-title }}</h1>
42
+ <p class="overview-subtitle">{{ overview-description }}</p>
43
+ <div class="overview-stats">{{ overview-stats }}</div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <div class="overview-filters">
48
+ <div class="content-grid">
49
+ <div class="content">
50
+ <div class="overview-filter-bar">
51
+ <input
52
+ type="search"
53
+ class="overview-search"
54
+ placeholder="{{ search-placeholder }}"
55
+ aria-label="Search {{ overview-type }}"
56
+ />
57
+ <select
58
+ class="overview-filter-select"
59
+ aria-label="Filter by category"
60
+ >
61
+ <option value="">All Categories</option>
62
+ {{ filter-options }}
63
+ </select>
64
+ <div class="overview-sort">
65
+ <span>Sort:</span>
66
+ <button class="overview-sort-btn active" data-sort="name">
67
+ Name
68
+ </button>
69
+ <button class="overview-sort-btn" data-sort="date">Date</button>
70
+ <button class="overview-sort-btn" data-sort="popularity">
71
+ Popular
72
+ </button>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ <main id="main" class="content-grid">
79
+ <div class="content overview-content">
80
+ <div class="overview-grid" id="overview-grid">{{ content }}</div>
81
+ <div class="overview-empty" id="overview-empty" style="display: none">
82
+ <div class="overview-empty-icon">🔍</div>
83
+ <h3>No results found</h3>
84
+ <p>Try adjusting your search or filter criteria.</p>
85
+ </div>
86
+ <nav class="overview-pagination" aria-label="Pagination">
87
+ {{ pagination }}
88
+ </nav>
89
+ </div>
90
+ </main>
91
+ <footer class="content-grid">
92
+ <div class="content">
93
+ <h2 class="visually-hidden">Footer</h2>
94
+ <p>© 2024 – 2025 Zeix AG</p>
95
+ </div>
96
+ </footer>
97
+ </context-router>
98
+ <script>
99
+ // Simple search and filter functionality
100
+ document.addEventListener('DOMContentLoaded', function () {
101
+ const searchInput = document.querySelector('.overview-search')
102
+ const filterSelect = document.querySelector('.overview-filter-select')
103
+ const sortBtns = document.querySelectorAll('.overview-sort-btn')
104
+ const grid = document.getElementById('overview-grid')
105
+ const empty = document.getElementById('overview-empty')
106
+ const cards = Array.from(grid.querySelectorAll('.overview-card'))
107
+
108
+ function filterAndSort() {
109
+ const searchTerm = searchInput.value.toLowerCase()
110
+ const filterValue = filterSelect.value
111
+ const sortValue = document.querySelector('.overview-sort-btn.active')
112
+ .dataset.sort
113
+
114
+ let visibleCards = cards.filter(card => {
115
+ const title = card
116
+ .querySelector('.overview-card-title')
117
+ .textContent.toLowerCase()
118
+ const description = card
119
+ .querySelector('.overview-card-description')
120
+ .textContent.toLowerCase()
121
+ const matchesSearch =
122
+ !searchTerm
123
+ || title.includes(searchTerm)
124
+ || description.includes(searchTerm)
125
+
126
+ const category = card.dataset.category || ''
127
+ const matchesFilter = !filterValue || category === filterValue
128
+
129
+ return matchesSearch && matchesFilter
130
+ })
131
+
132
+ // Sort cards
133
+ visibleCards.sort((a, b) => {
134
+ const aValue =
135
+ a.dataset[sortValue]
136
+ || a.querySelector('.overview-card-title').textContent
137
+ const bValue =
138
+ b.dataset[sortValue]
139
+ || b.querySelector('.overview-card-title').textContent
140
+ return aValue.localeCompare(bValue)
141
+ })
142
+
143
+ // Show/hide cards
144
+ cards.forEach(card => {
145
+ card.style.display = visibleCards.includes(card) ? '' : 'none'
146
+ })
147
+
148
+ // Show/hide empty state
149
+ empty.style.display = visibleCards.length === 0 ? '' : 'none'
150
+ }
151
+
152
+ searchInput.addEventListener('input', filterAndSort)
153
+ filterSelect.addEventListener('change', filterAndSort)
154
+
155
+ sortBtns.forEach(btn => {
156
+ btn.addEventListener('click', function () {
157
+ sortBtns.forEach(b => b.classList.remove('active'))
158
+ this.classList.add('active')
159
+ filterAndSort()
160
+ })
161
+ })
162
+ })
163
+ </script>
164
+ </body>
165
+ </html>
@@ -0,0 +1,36 @@
1
+ {{ extends 'base.html' }}
2
+
3
+ <head>
4
+ <title>{{ title }} – Le Truc Docs</title>
5
+ <meta name="description" content="{{ description }}" />
6
+ </head>
7
+
8
+ <body class="{{ section }} {{ body-class }}">
9
+ <a href="#main" class="skiplink visually-hidden">Skip to main content</a>
10
+
11
+ <context-router>
12
+ <header class="content-grid">
13
+ <h1 class="content">Le Truc Docs <small>Version 0.15.0</small></h1>
14
+
15
+ <!-- Optional shared navigation include -->
16
+ {{ include 'menu.html' }}
17
+
18
+ <!-- Page-level callout used by client scripts (hidden by default) -->
19
+ <card-callout class="content danger" hidden>
20
+ <p class="error" role="alert" aria-live="assertive"></p>
21
+ </card-callout>
22
+ </header>
23
+
24
+ <main id="main" class="content-grid">
25
+ <!-- Rendered page content or child-layout inner body -->
26
+ {{ content }}
27
+ </main>
28
+
29
+ <footer class="content-grid">
30
+ <div class="content">
31
+ <h2 class="visually-hidden">Footer</h2>
32
+ <p>© 2024 – 2025 Zeix AG</p>
33
+ </div>
34
+ </footer>
35
+ </context-router>
36
+ </body>
@@ -0,0 +1,24 @@
1
+ {{ extends 'base.html' }}
2
+
3
+ <head>
4
+ <title>{{ title }} – Le Truc Component Test</title>
5
+ <meta name="description" content="Testing {{ component-name }} component" />
6
+ </head>
7
+
8
+ <body class="test">
9
+ <header class="content-grid">
10
+ <a href="#main" class="skiplink visually-hidden">Skip to main content</a>
11
+ <h1 class="content">{{ title }} <small>Le Truc 0.15.0</small></h1>
12
+ <card-callout class="content danger" hidden>
13
+ <p class="error" role="alert" aria-live="assertive"></p>
14
+ </card-callout>
15
+ </header>
16
+ <main id="main" class="content-grid">
17
+ <section class="content">{{content}}</section>
18
+ </main>
19
+ <footer class="content-grid">
20
+ <div class="content">
21
+ <h2 class="visually-hidden">Footer</h2>
22
+ </div>
23
+ </footer>
24
+ </body>
@@ -0,0 +1,217 @@
1
+ import Markdoc, {
2
+ type Node,
3
+ type RenderableTreeNode,
4
+ Tag,
5
+ } from '@markdoc/markdoc'
6
+ import markdocConfig from './markdoc.config'
7
+ import { generateSlug as templateSlug } from './templates/utils'
8
+
9
+ // Common attribute definitions for reuse across schemas
10
+ export const classAttribute = {
11
+ type: String,
12
+ }
13
+
14
+ export const idAttribute = {
15
+ type: String,
16
+ }
17
+
18
+ export const styleAttribute = {
19
+ type: String,
20
+ }
21
+
22
+ export const titleAttribute = {
23
+ type: String,
24
+ }
25
+
26
+ export const requiredTitleAttribute = {
27
+ type: String,
28
+ required: true,
29
+ }
30
+
31
+ // Common children arrays for different content types
32
+ export const standardChildren = [
33
+ 'paragraph',
34
+ 'heading',
35
+ 'list',
36
+ 'blockquote',
37
+ 'hr',
38
+ 'fence',
39
+ 'callout',
40
+ 'tag',
41
+ 'inline',
42
+ ]
43
+
44
+ export const richChildren = [
45
+ 'paragraph',
46
+ 'heading',
47
+ 'list',
48
+ 'item',
49
+ 'blockquote',
50
+ 'hr',
51
+ 'fence',
52
+ 'callout',
53
+ 'tag',
54
+ 'inline',
55
+ 'text',
56
+ 'strong',
57
+ 'em',
58
+ 'code',
59
+ 'link',
60
+ ]
61
+
62
+ // Common attribute sets
63
+ export const commonAttributes = {
64
+ class: classAttribute,
65
+ id: idAttribute,
66
+ }
67
+
68
+ export const styledAttributes = {
69
+ ...commonAttributes,
70
+ style: styleAttribute,
71
+ }
72
+
73
+ // Text extraction utility used by multiple schemas
74
+ export function extractTextFromNode(node: Node): string {
75
+ if (node.type === 'text') {
76
+ return node.attributes.content || ''
77
+ }
78
+ if (node.children) {
79
+ return node.children.map(extractTextFromNode).join('')
80
+ }
81
+ return ''
82
+ }
83
+
84
+ // Transform child nodes with markdoc config
85
+ export function transformChildrenWithConfig(
86
+ children: Node[],
87
+ ): RenderableTreeNode[] {
88
+ return children.map((child: Node) => Markdoc.transform(child, markdocConfig))
89
+ }
90
+
91
+ // Split content by separator nodes (used by carousel, tabgroup, demo)
92
+ export function splitContentBySeparator(
93
+ children: Node[],
94
+ separatorType: string = 'hr',
95
+ ): Node[][] {
96
+ const sections: Node[][] = []
97
+ let currentSection: Node[] = []
98
+
99
+ for (const child of children) {
100
+ if (child.type === separatorType) {
101
+ if (currentSection.length > 0) {
102
+ sections.push(currentSection)
103
+ currentSection = []
104
+ }
105
+ } else {
106
+ currentSection.push(child)
107
+ }
108
+ }
109
+
110
+ // Add the last section if it has content
111
+ if (currentSection.length > 0) {
112
+ sections.push(currentSection)
113
+ }
114
+
115
+ return sections
116
+ }
117
+
118
+ // Generate unique ID from text
119
+ export function generateUniqueId(text: string, prefix?: string): string {
120
+ const baseId = text
121
+ .toLowerCase()
122
+ .replace(/[^a-z0-9]+/g, '-')
123
+ .replace(/^-|-$/g, '')
124
+
125
+ return prefix ? `${prefix}_${baseId}` : baseId
126
+ }
127
+
128
+ // Create navigation button
129
+ export function createNavigationButton(
130
+ type: 'prev' | 'next',
131
+ label?: string,
132
+ ): Tag {
133
+ const defaultLabels = { prev: '❮', next: '❯' }
134
+ const ariaLabels = { prev: 'Previous', next: 'Next' }
135
+
136
+ return new Tag(
137
+ 'button',
138
+ {
139
+ type: 'button',
140
+ class: type,
141
+ 'aria-label': ariaLabels[type],
142
+ },
143
+ [label || defaultLabels[type]],
144
+ )
145
+ }
146
+
147
+ // Create tab button for navigation
148
+ export function createTabButton(options: {
149
+ id: string
150
+ label: string
151
+ controls: string
152
+ selected?: boolean
153
+ index?: number
154
+ }): Tag {
155
+ const { id, label, controls, selected = false, index = 0 } = options
156
+
157
+ return new Tag(
158
+ 'button',
159
+ {
160
+ role: 'tab',
161
+ id,
162
+ 'aria-controls': controls,
163
+ 'aria-label': label,
164
+ 'aria-selected': String(selected),
165
+ 'data-index': String(index),
166
+ tabindex: selected ? '0' : '-1',
167
+ },
168
+ ['●'],
169
+ )
170
+ }
171
+
172
+ // Create accessible heading with anchor
173
+ export function createAccessibleHeading(
174
+ level: number,
175
+ text: string,
176
+ attributes: Record<string, any> = {},
177
+ ): Tag {
178
+ const slug = generateSlug(text)
179
+
180
+ return new Tag(`h${level}`, { id: slug, ...attributes }, [
181
+ new Tag('a', { name: slug, class: 'anchor', href: `#${slug}` }, [
182
+ new Tag('span', { class: 'permalink' }, ['🔗']),
183
+ new Tag('span', { class: 'title' }, [text]),
184
+ ]),
185
+ ])
186
+ }
187
+
188
+ // Create visually hidden heading for accessibility
189
+ export function createVisuallyHiddenHeading(text: string): Tag {
190
+ return new Tag('h2', { class: 'visually-hidden' }, [text])
191
+ }
192
+
193
+ export function postProcessHtml(html: string, section?: string): string {
194
+ // Fix internal links (.md -> .html)
195
+ html = html.replace(
196
+ /href="([^"]*\.md)"/g,
197
+ (_, href) => `href="${href.replace(/\.md$/, '.html')}"`,
198
+ )
199
+
200
+ // Wrap API pages
201
+ if (section === 'api') {
202
+ html = `<section class="api-content">\n${html}\n</section>`
203
+ }
204
+
205
+ return html
206
+ }
207
+
208
+ export function generateSlug(text: string): string {
209
+ // Decode HTML entities first
210
+ const decoded = text
211
+ .replace(/&quot;/g, '"')
212
+ .replace(/&#39;/g, "'")
213
+ .replace(/&amp;/g, '&')
214
+
215
+ // Use the existing slug generator
216
+ return templateSlug(decoded)
217
+ }