@supersoniks/concorde 5.1.2 → 5.1.3-immutable.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 (497) hide show
  1. package/.agents/skills/concorde-docs/SKILL.md +1 -1
  2. package/.claude/skills +1 -0
  3. package/.github/workflows/ci.yml +21 -0
  4. package/.github-export-ignore +30 -0
  5. package/CONTRIBUTING.md +59 -0
  6. package/DEV.md +54 -0
  7. package/LICENSE +21 -0
  8. package/OPEN_SOURCE_CHECKPOINT.md +133 -0
  9. package/README.md +1 -1
  10. package/ai/README.md +29 -41
  11. package/ai/skills/concorde/SKILL.md +54 -324
  12. package/ai/skills/concorde/rules/composition.md +32 -0
  13. package/ai/skills/concorde/rules/data.md +47 -0
  14. package/ai/skills/concorde/rules/http.md +25 -0
  15. package/ai/skills/concorde/rules/lists-forms.md +35 -0
  16. package/ai/skills/concorde/rules/styling.md +46 -0
  17. package/ai/skills/concorde/rules/troubleshooting.md +45 -0
  18. package/build-infos.json +1 -1
  19. package/concorde-core.bundle.js +177 -177
  20. package/concorde-core.es.js +5183 -5018
  21. package/custom-elements-manifest.public.config.mjs +8 -0
  22. package/{.tmp-cem/custom-elements.json → custom-elements.json} +11722 -8868
  23. package/dist/concorde-core.bundle.js +177 -177
  24. package/dist/concorde-core.es.js +5183 -5018
  25. package/dist/docs-mock-api-sw.js +58 -223
  26. package/dist/docs-mock-api-sw.js.map +4 -4
  27. package/dist/img/og-concorde.jpg +0 -0
  28. package/dist/robots.txt +11 -10
  29. package/docs/assets/index-CD4WyL6o.css +1 -0
  30. package/docs/assets/index-D_alEsng.js +12122 -0
  31. package/docs/crawl/core/components/functional/date/date.html +190 -0
  32. package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
  33. package/docs/crawl/core/components/functional/if/if.html +27 -0
  34. package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
  35. package/docs/crawl/core/components/functional/list/list.html +70 -0
  36. package/docs/crawl/core/components/functional/mix/mix.html +45 -0
  37. package/docs/crawl/core/components/functional/queue/queue.html +96 -0
  38. package/docs/crawl/core/components/functional/router/router.html +106 -0
  39. package/docs/{core → crawl/core}/components/functional/sdui/sdui-extension-points.html +8 -9
  40. package/docs/crawl/core/components/functional/sdui/sdui.html +368 -0
  41. package/docs/crawl/core/components/functional/states/states.html +66 -0
  42. package/docs/crawl/core/components/functional/submit/submit.html +160 -0
  43. package/docs/{core → crawl/core}/components/functional/subscriber/subscriber.html +5 -6
  44. package/docs/crawl/core/components/functional/value/value.html +51 -0
  45. package/docs/{core → crawl/core}/components/ui/alert/alert.html +63 -53
  46. package/docs/{core → crawl/core}/components/ui/alert-messages/alert-messages.html +5 -6
  47. package/docs/{core → crawl/core}/components/ui/badge/badge.html +33 -33
  48. package/docs/crawl/core/components/ui/button/button.html +150 -0
  49. package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
  50. package/docs/{core → crawl/core}/components/ui/card/card.html +11 -12
  51. package/docs/{core → crawl/core}/components/ui/divider/divider.html +14 -14
  52. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
  53. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +266 -0
  54. package/docs/{core → crawl/core}/components/ui/form/form-actions/form-actions.html +23 -23
  55. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +121 -0
  56. package/docs/crawl/core/components/ui/form/input/input.html +109 -0
  57. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
  58. package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
  59. package/docs/crawl/core/components/ui/form/select/select.html +73 -0
  60. package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
  61. package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
  62. package/docs/crawl/core/components/ui/group/group.html +104 -0
  63. package/docs/{core → crawl/core}/components/ui/icon/icon.html +9 -10
  64. package/docs/crawl/core/components/ui/image/image.html +298 -0
  65. package/docs/{core → crawl/core}/components/ui/link/link.html +11 -12
  66. package/docs/crawl/core/components/ui/loader/loader.html +124 -0
  67. package/docs/{core → crawl/core}/components/ui/menu/menu.html +33 -34
  68. package/docs/crawl/core/components/ui/modal/modal.html +342 -0
  69. package/docs/crawl/core/components/ui/pop/pop.html +296 -0
  70. package/docs/{core → crawl/core}/components/ui/progress/progress.html +7 -8
  71. package/docs/crawl/core/components/ui/table/table.html +545 -0
  72. package/docs/crawl/core/components/ui/theme/theme.html +131 -0
  73. package/docs/crawl/core/components/ui/toast/toast.html +233 -0
  74. package/docs/crawl/core/components/ui/tooltip/tooltip.html +140 -0
  75. package/docs/{docs/getting-started → crawl/docs/_core-concept}/dataFlow.html +29 -26
  76. package/docs/crawl/docs/_core-concept/overview.html +66 -0
  77. package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
  78. package/docs/crawl/docs/_decorators/ancestor-attribute.html +117 -0
  79. package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
  80. package/docs/crawl/docs/_decorators/bind.html +141 -0
  81. package/docs/crawl/docs/_decorators/get.html +149 -0
  82. package/docs/crawl/docs/_decorators/handle.html +165 -0
  83. package/docs/crawl/docs/_decorators/on-assign.html +355 -0
  84. package/docs/crawl/docs/_decorators/patch.html +78 -0
  85. package/docs/crawl/docs/_decorators/post.html +139 -0
  86. package/docs/crawl/docs/_decorators/publish.html +61 -0
  87. package/docs/crawl/docs/_decorators/put.html +78 -0
  88. package/docs/crawl/docs/_decorators/subscribe.html +109 -0
  89. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
  90. package/docs/crawl/docs/_directives/sub.html +93 -0
  91. package/docs/{docs/getting-started → crawl/docs/_getting-started}/ai-agents.html +11 -12
  92. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
  93. package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
  94. package/docs/{docs/getting-started → crawl/docs/_getting-started}/create-a-component.html +14 -11
  95. package/docs/{docs/getting-started → crawl/docs/_getting-started}/my-first-component.html +22 -13
  96. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
  97. package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
  98. package/docs/crawl/docs/_getting-started/start.html +76 -0
  99. package/docs/{docs/getting-started → crawl/docs/_getting-started}/theming.html +9 -10
  100. package/docs/{docs/misc → crawl/docs/_misc}/api-configuration.html +18 -18
  101. package/docs/{docs/misc → crawl/docs/_misc}/dataProviderKey.html +11 -12
  102. package/docs/{docs/misc → crawl/docs/_misc}/docs-mock-api.html +28 -25
  103. package/docs/{docs/misc → crawl/docs/_misc}/dynamic-path.html +15 -16
  104. package/docs/{docs/misc → crawl/docs/_misc}/endpoint.html +15 -16
  105. package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
  106. package/docs/{docs/misc → crawl/docs/_misc}/html-integration.html +15 -12
  107. package/docs/crawl/hubs/decorators.html +547 -0
  108. package/docs/crawl/hubs/form-components.html +381 -0
  109. package/docs/crawl/hubs/remote-data.html +452 -0
  110. package/docs/crawl/index.html +103 -0
  111. package/docs/docs-mock-api-sw.js +223 -58
  112. package/docs/docs-mock-api-sw.js.map +4 -4
  113. package/docs/index.html +68 -95
  114. package/docs/llms-full.txt +3610 -2231
  115. package/docs/llms.txt +86 -94
  116. package/docs/robots.txt +10 -11
  117. package/docs/sitemap.xml +84 -78
  118. package/docs/src/core/components/functional/date/date.md +231 -91
  119. package/docs/src/core/components/functional/fetch/fetch.md +83 -66
  120. package/docs/src/core/components/functional/if/if.md +3 -28
  121. package/docs/src/core/components/functional/jsonata/jsonata.md +37 -42
  122. package/docs/src/core/components/functional/list/list.md +43 -99
  123. package/docs/src/core/components/functional/mix/mix.md +26 -31
  124. package/docs/src/core/components/functional/queue/queue.md +61 -40
  125. package/docs/src/core/components/functional/router/router.md +65 -64
  126. package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  127. package/docs/src/core/components/functional/sdui/component-catalog.json +1 -1
  128. package/docs/src/core/components/functional/sdui/example.json +86 -19
  129. package/docs/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
  130. package/docs/src/core/components/functional/sdui/sdui.md +358 -187
  131. package/docs/src/core/components/functional/states/states.md +61 -86
  132. package/docs/src/core/components/functional/submit/submit.md +72 -64
  133. package/docs/src/core/components/functional/value/value.md +22 -34
  134. package/docs/src/core/components/ui/alert/alert.md +58 -48
  135. package/docs/src/core/components/ui/badge/badge.md +34 -27
  136. package/docs/src/core/components/ui/button/button.md +106 -139
  137. package/docs/src/core/components/ui/captcha/captcha.md +32 -17
  138. package/docs/src/core/components/ui/card/card.md +6 -6
  139. package/docs/src/core/components/ui/divider/divider.md +11 -8
  140. package/docs/src/core/components/ui/form/checkbox/checkbox.md +42 -90
  141. package/docs/src/core/components/ui/form/fieldset/fieldset.md +75 -31
  142. package/docs/src/core/components/ui/form/form-actions/form-actions.md +16 -14
  143. package/docs/src/core/components/ui/form/form-layout/form-layout.md +29 -19
  144. package/docs/src/core/components/ui/form/input/input.md +95 -95
  145. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -0
  146. package/docs/src/core/components/ui/form/radio/radio.md +34 -55
  147. package/docs/src/core/components/ui/form/select/select.md +45 -60
  148. package/docs/src/core/components/ui/form/switch/switch.md +34 -57
  149. package/docs/src/core/components/ui/form/textarea/textarea.md +38 -55
  150. package/docs/src/core/components/ui/group/group.md +33 -35
  151. package/docs/src/core/components/ui/icon/icon.md +4 -4
  152. package/docs/src/core/components/ui/image/image.md +107 -41
  153. package/docs/src/core/components/ui/link/link.md +6 -6
  154. package/docs/src/core/components/ui/loader/loader.md +55 -30
  155. package/docs/src/core/components/ui/menu/menu.md +27 -27
  156. package/docs/src/core/components/ui/modal/modal.md +96 -72
  157. package/docs/src/core/components/ui/pop/pop.md +158 -80
  158. package/docs/src/core/components/ui/progress/progress.md +2 -2
  159. package/docs/src/core/components/ui/table/table.md +255 -91
  160. package/docs/src/core/components/ui/theme/theme.md +36 -11
  161. package/docs/src/core/components/ui/toast/toast.md +117 -48
  162. package/docs/src/core/components/ui/tooltip/tooltip.md +62 -27
  163. package/docs/{docs/getting-started → src/docs/_core-concept}/dataFlow.md +18 -17
  164. package/docs/src/docs/_core-concept/overview.md +57 -0
  165. package/docs/src/docs/_core-concept/subscriber.md +75 -0
  166. package/docs/src/docs/_decorators/ancestor-attribute.md +128 -0
  167. package/docs/src/docs/_decorators/auto-subscribe.md +202 -0
  168. package/docs/src/docs/_decorators/bind.md +167 -0
  169. package/docs/src/docs/_decorators/get.md +162 -0
  170. package/docs/src/docs/_decorators/handle.md +175 -0
  171. package/docs/src/docs/_decorators/on-assign.md +390 -0
  172. package/docs/src/docs/_decorators/patch.md +70 -0
  173. package/docs/src/docs/_decorators/post.md +146 -0
  174. package/docs/src/docs/_decorators/publish.md +55 -0
  175. package/docs/src/docs/_decorators/put.md +70 -0
  176. package/docs/src/docs/_decorators/subscribe.md +100 -0
  177. package/docs/src/docs/_decorators/wait-for-ancestors.md +163 -0
  178. package/docs/src/docs/_directives/sub.md +91 -0
  179. package/docs/src/docs/{getting-started → _getting-started}/ai-agents.md +3 -3
  180. package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
  181. package/docs/src/docs/_getting-started/concorde-outside.md +33 -0
  182. package/docs/{docs/getting-started → src/docs/_getting-started}/create-a-component.md +6 -3
  183. package/docs/src/docs/{getting-started → _getting-started}/my-first-component.md +14 -5
  184. package/docs/src/docs/_getting-started/my-first-subscriber.md +120 -0
  185. package/docs/src/docs/_getting-started/pubsub.md +37 -0
  186. package/docs/src/docs/{getting-started → _getting-started}/start.md +13 -1
  187. package/docs/src/docs/{getting-started → _getting-started}/theming.md +2 -2
  188. package/docs/src/docs/{misc → _misc}/api-configuration.md +12 -10
  189. package/docs/src/docs/{misc → _misc}/dataProviderKey.md +4 -4
  190. package/docs/{docs/misc → src/docs/_misc}/docs-mock-api.md +13 -12
  191. package/docs/{docs/misc → src/docs/_misc}/dynamic-path.md +8 -8
  192. package/docs/{docs/misc → src/docs/_misc}/endpoint.md +8 -8
  193. package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
  194. package/docs/{docs/misc → src/docs/_misc}/html-integration.md +5 -4
  195. package/docs/src/docs/search/docs-search.json +4375 -2420
  196. package/docs/src/tsconfig.declarations.json +22 -0
  197. package/docs/src/tsconfig.emit.json +23 -0
  198. package/docs/src/tsconfig.json +2 -23
  199. package/gitlab/job_github_mirror.sh +39 -0
  200. package/index.html +89 -0
  201. package/package.json +22 -4
  202. package/public/img/og-concorde.jpg +0 -0
  203. package/scripts/ai-init.mjs +104 -379
  204. package/scripts/ai-init.test.mjs +81 -239
  205. package/scripts/docs-markdown-vite-plugin.ts +11 -5
  206. package/scripts/docs-public-url.mjs +6 -0
  207. package/scripts/docs.htaccess +7 -0
  208. package/scripts/generate-cem.mjs +244 -0
  209. package/scripts/generate-cem.test.mjs +122 -0
  210. package/scripts/generate-crawl-docs.mjs +29 -5
  211. package/scripts/generate-sdui-catalog.mjs +11 -10
  212. package/scripts/github-export.mjs +150 -0
  213. package/scripts/post-build-docs.js +3 -0
  214. package/scripts/post-build.mjs +0 -0
  215. package/scripts/pre-publish.mjs +2 -1
  216. package/scripts/site-pages.mjs +212 -0
  217. package/scripts/site-pages.test.mjs +116 -0
  218. package/site-pages/about.md +22 -0
  219. package/site-pages/privacy.md +32 -0
  220. package/src/core/components/functional/date/date.md +1 -1
  221. package/src/core/components/functional/example/example.ts +3 -1
  222. package/src/core/components/functional/if/if.ts +0 -0
  223. package/src/core/components/functional/list/list.demo.ts +0 -0
  224. package/src/core/components/functional/list/list.md +6 -2
  225. package/src/core/components/functional/list/list.ts +17 -4
  226. package/src/core/components/functional/mix/mix.md +0 -0
  227. package/src/core/components/functional/router/router.demo.ts +0 -0
  228. package/src/core/components/functional/router/router.ts +0 -0
  229. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
  230. package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  231. package/src/core/components/functional/sdui/component-catalog.json +2 -2
  232. package/src/core/components/functional/sdui/example.json +0 -0
  233. package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
  234. package/src/core/components/functional/sdui/sdui.ts +33 -8
  235. package/src/core/components/functional/sdui/types.ts +0 -0
  236. package/src/core/components/functional/states/states.ts +0 -0
  237. package/src/core/components/functional/submit/submit.spec.ts +60 -0
  238. package/src/core/components/functional/submit/submit.ts +6 -3
  239. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  240. package/src/core/components/functional/value/value.md +0 -0
  241. package/src/core/components/functional/value/value.ts +0 -0
  242. package/src/core/components/ui/_css/size.ts +0 -0
  243. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  244. package/src/core/components/ui/card/card.md +1 -1
  245. package/src/core/components/ui/form/input/input.md +19 -1
  246. package/src/core/components/ui/form/input/input.ts +8 -2
  247. package/src/core/components/ui/form/radio/radio.md +14 -0
  248. package/src/core/components/ui/image/image.md +17 -17
  249. package/src/core/components/ui/modal/modal.md +2 -2
  250. package/src/core/decorators/subscriber/bind.ts +9 -14
  251. package/src/core/decorators/subscriber/subscribe.ts +15 -9
  252. package/src/core/decorators/subscriber/subscribe.type-test.ts +14 -5
  253. package/src/core/mixins/Subscriber.ts +0 -0
  254. package/src/core/utils/DataBindObserver.ts +0 -0
  255. package/src/core/utils/Objects.ts +0 -0
  256. package/src/core/utils/PublisherProxy.ts +166 -125
  257. package/src/core/utils/deepReadonly.spec.ts +66 -0
  258. package/src/core/utils/deepReadonly.ts +71 -0
  259. package/src/core/utils/immutableValue.spec.ts +58 -0
  260. package/src/core/utils/immutableValue.ts +116 -0
  261. package/src/core/utils/nestedDotForm.spec.ts +88 -0
  262. package/src/core/utils/publisherImmutable.spec.ts +127 -0
  263. package/src/core/utils/route.ts +0 -0
  264. package/src/core/utils/strictGet.spec.ts +61 -0
  265. package/src/core/utils/strictGet.ts +102 -0
  266. package/src/css.d.ts +19 -0
  267. package/src/docs/components/docs-demo-sources.ts +3 -3
  268. package/src/docs/decorators/bind.md +23 -24
  269. package/src/docs/docs-location.spec.ts +10 -0
  270. package/src/docs/docs-location.ts +10 -0
  271. package/src/docs/example/decorators-demo-bind-demos.ts +11 -28
  272. package/src/docs/example/docs-toggle-demos.ts +1 -1
  273. package/src/docs/example/users.ts +0 -0
  274. package/src/docs/getting-started/ai-agents.md +51 -51
  275. package/src/docs/getting-started/dataFlow.md +2 -2
  276. package/src/docs/home/home.ts +3 -1
  277. package/src/docs/misc/publisher-get-immutability-docs-crawl.json +902 -0
  278. package/src/docs/misc/publisher-get-immutability-docs-recheck.json +13 -0
  279. package/src/docs/misc/publisher-get-immutability-study.md +229 -0
  280. package/src/docs/navigation/navigation.ts +5 -1
  281. package/src/docs/search/docs-search.json +358 -58
  282. package/src/docs/search/markdown-renderer.ts +6 -1
  283. package/src/docs/tailwind/css/docs/content.css +4 -5
  284. package/src/tsconfig.declarations.json +22 -0
  285. package/src/tsconfig.emit.json +23 -0
  286. package/src/tsconfig.json +53 -5
  287. package/src/tsconfig.tsbuildinfo +1 -1
  288. package/.taste-skill/after/desktop-fold.jpg +0 -0
  289. package/.taste-skill/after/desktop-page-01.jpg +0 -0
  290. package/.taste-skill/after/desktop-page-02.jpg +0 -0
  291. package/.taste-skill/after/desktop-page-03.jpg +0 -0
  292. package/.taste-skill/after/mobile-fold.jpg +0 -0
  293. package/.taste-skill/after/mobile-page-01.jpg +0 -0
  294. package/.taste-skill/after/report.json +0 -4103
  295. package/.taste-skill/after/tablet-fold.jpg +0 -0
  296. package/.taste-skill/after/tablet-page-01.jpg +0 -0
  297. package/.taste-skill/after/tablet-page-02.jpg +0 -0
  298. package/.taste-skill/before/desktop-fold.jpg +0 -0
  299. package/.taste-skill/before/desktop-page-01.jpg +0 -0
  300. package/.taste-skill/before/desktop-page-02.jpg +0 -0
  301. package/.taste-skill/before/mobile-fold.jpg +0 -0
  302. package/.taste-skill/before/mobile-page-01.jpg +0 -0
  303. package/.taste-skill/before/report.json +0 -2556
  304. package/.taste-skill/before/tablet-fold.jpg +0 -0
  305. package/.taste-skill/before/tablet-page-01.jpg +0 -0
  306. package/.taste-skill/direction.json +0 -510
  307. package/.taste-skill/notes.md +0 -84
  308. package/.taste-skill/prod/desktop-fold.jpg +0 -0
  309. package/.taste-skill/prod/desktop-page-01.jpg +0 -0
  310. package/.taste-skill/prod/desktop-page-02.jpg +0 -0
  311. package/.taste-skill/prod/desktop-page-03.jpg +0 -0
  312. package/.taste-skill/prod/mobile-fold.jpg +0 -0
  313. package/.taste-skill/prod/mobile-page-01.jpg +0 -0
  314. package/.taste-skill/prod/mobile-page-02.jpg +0 -0
  315. package/.taste-skill/prod/report.json +0 -1973
  316. package/.taste-skill/prod/tablet-fold.jpg +0 -0
  317. package/.taste-skill/prod/tablet-page-01.jpg +0 -0
  318. package/.taste-skill/prod/tablet-page-02.jpg +0 -0
  319. package/AUDIT.md +0 -228
  320. package/PLAN-AMELIORATION.md +0 -220
  321. package/PLAN-DOCS-AGENTS.md +0 -80
  322. package/ai/AGENTS.md +0 -56
  323. package/ai/cursor/rules/concorde-menu.mdc +0 -15
  324. package/ai/cursor/rules/concorde-scope.mdc +0 -14
  325. package/ai/cursor/rules/concorde-theme.mdc +0 -13
  326. package/ai/cursor/rules/concorde.mdc +0 -66
  327. package/ai/jetbrains/rules/concorde.md +0 -53
  328. package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
  329. package/ai/skills/concorde-imports/SKILL.md +0 -78
  330. package/ai/skills/concorde-menu/SKILL.md +0 -74
  331. package/ai/skills/concorde-scope/SKILL.md +0 -70
  332. package/ai/skills/concorde-theme/SKILL.md +0 -57
  333. package/docs/.htaccess +0 -75
  334. package/docs/404.html +0 -15
  335. package/docs/404.md +0 -5
  336. package/docs/assets/index-BgG6FFPt.js +0 -11765
  337. package/docs/assets/index-x89XINSG.css +0 -1
  338. package/docs/core/components/functional/date/date.html +0 -211
  339. package/docs/core/components/functional/date/date.md +0 -150
  340. package/docs/core/components/functional/fetch/fetch.html +0 -180
  341. package/docs/core/components/functional/fetch/fetch.md +0 -108
  342. package/docs/core/components/functional/if/if.html +0 -65
  343. package/docs/core/components/functional/if/if.md +0 -34
  344. package/docs/core/components/functional/jsonata/jsonata.html +0 -110
  345. package/docs/core/components/functional/jsonata/jsonata.md +0 -61
  346. package/docs/core/components/functional/list/list.html +0 -198
  347. package/docs/core/components/functional/list/list.md +0 -121
  348. package/docs/core/components/functional/mix/mix.html +0 -78
  349. package/docs/core/components/functional/mix/mix.md +0 -46
  350. package/docs/core/components/functional/queue/queue.html +0 -155
  351. package/docs/core/components/functional/queue/queue.md +0 -51
  352. package/docs/core/components/functional/router/router.html +0 -154
  353. package/docs/core/components/functional/router/router.md +0 -93
  354. package/docs/core/components/functional/sdui/sdui-extension-points.md +0 -94
  355. package/docs/core/components/functional/sdui/sdui.html +0 -397
  356. package/docs/core/components/functional/sdui/sdui.md +0 -307
  357. package/docs/core/components/functional/states/states.html +0 -141
  358. package/docs/core/components/functional/states/states.md +0 -112
  359. package/docs/core/components/functional/submit/submit.html +0 -178
  360. package/docs/core/components/functional/submit/submit.md +0 -106
  361. package/docs/core/components/functional/subscriber/subscriber.md +0 -91
  362. package/docs/core/components/functional/translation/translation.html +0 -60
  363. package/docs/core/components/functional/translation/translation.md +0 -38
  364. package/docs/core/components/functional/value/value.html +0 -81
  365. package/docs/core/components/functional/value/value.md +0 -47
  366. package/docs/core/components/ui/alert/alert.md +0 -186
  367. package/docs/core/components/ui/alert-messages/alert-messages.md +0 -85
  368. package/docs/core/components/ui/badge/badge.md +0 -181
  369. package/docs/core/components/ui/button/button.html +0 -309
  370. package/docs/core/components/ui/button/button.md +0 -216
  371. package/docs/core/components/ui/captcha/captcha.html +0 -80
  372. package/docs/core/components/ui/captcha/captcha.md +0 -56
  373. package/docs/core/components/ui/card/card.md +0 -215
  374. package/docs/core/components/ui/divider/divider.md +0 -126
  375. package/docs/core/components/ui/form/checkbox/checkbox.html +0 -200
  376. package/docs/core/components/ui/form/checkbox/checkbox.md +0 -125
  377. package/docs/core/components/ui/form/fieldset/fieldset.html +0 -238
  378. package/docs/core/components/ui/form/fieldset/fieldset.md +0 -161
  379. package/docs/core/components/ui/form/form-actions/form-actions.md +0 -98
  380. package/docs/core/components/ui/form/form-layout/form-layout.html +0 -115
  381. package/docs/core/components/ui/form/form-layout/form-layout.md +0 -109
  382. package/docs/core/components/ui/form/input/input.html +0 -235
  383. package/docs/core/components/ui/form/input/input.md +0 -142
  384. package/docs/core/components/ui/form/radio/radio.html +0 -144
  385. package/docs/core/components/ui/form/radio/radio.md +0 -78
  386. package/docs/core/components/ui/form/select/select.html +0 -178
  387. package/docs/core/components/ui/form/select/select.md +0 -86
  388. package/docs/core/components/ui/form/switch/switch.html +0 -146
  389. package/docs/core/components/ui/form/switch/switch.md +0 -80
  390. package/docs/core/components/ui/form/textarea/textarea.html +0 -162
  391. package/docs/core/components/ui/form/textarea/textarea.md +0 -82
  392. package/docs/core/components/ui/group/group.html +0 -113
  393. package/docs/core/components/ui/group/group.md +0 -77
  394. package/docs/core/components/ui/icon/icon.md +0 -214
  395. package/docs/core/components/ui/image/image.html +0 -194
  396. package/docs/core/components/ui/image/image.md +0 -167
  397. package/docs/core/components/ui/link/link.md +0 -81
  398. package/docs/core/components/ui/loader/loader.html +0 -114
  399. package/docs/core/components/ui/loader/loader.md +0 -87
  400. package/docs/core/components/ui/menu/menu.md +0 -370
  401. package/docs/core/components/ui/modal/modal.html +0 -324
  402. package/docs/core/components/ui/modal/modal.md +0 -211
  403. package/docs/core/components/ui/pop/pop.html +0 -250
  404. package/docs/core/components/ui/pop/pop.md +0 -216
  405. package/docs/core/components/ui/progress/progress.md +0 -109
  406. package/docs/core/components/ui/table/table.html +0 -333
  407. package/docs/core/components/ui/table/table.md +0 -267
  408. package/docs/core/components/ui/theme/theme.html +0 -116
  409. package/docs/core/components/ui/theme/theme.md +0 -97
  410. package/docs/core/components/ui/toast/toast.html +0 -185
  411. package/docs/core/components/ui/toast/toast.md +0 -147
  412. package/docs/core/components/ui/tooltip/tooltip.html +0 -112
  413. package/docs/core/components/ui/tooltip/tooltip.md +0 -89
  414. package/docs/docs/decorators/ancestor-attribute.html +0 -71
  415. package/docs/docs/decorators/ancestor-attribute.md +0 -59
  416. package/docs/docs/decorators/auto-subscribe.html +0 -61
  417. package/docs/docs/decorators/auto-subscribe.md +0 -40
  418. package/docs/docs/decorators/bind.html +0 -86
  419. package/docs/docs/decorators/bind.md +0 -77
  420. package/docs/docs/decorators/get.html +0 -166
  421. package/docs/docs/decorators/get.md +0 -160
  422. package/docs/docs/decorators/handle.html +0 -139
  423. package/docs/docs/decorators/handle.md +0 -119
  424. package/docs/docs/decorators/on-assign.html +0 -72
  425. package/docs/docs/decorators/on-assign.md +0 -63
  426. package/docs/docs/decorators/patch.html +0 -76
  427. package/docs/docs/decorators/patch.md +0 -44
  428. package/docs/docs/decorators/post.html +0 -150
  429. package/docs/docs/decorators/post.md +0 -134
  430. package/docs/docs/decorators/publish.html +0 -74
  431. package/docs/docs/decorators/publish.md +0 -56
  432. package/docs/docs/decorators/put.html +0 -83
  433. package/docs/docs/decorators/put.md +0 -51
  434. package/docs/docs/decorators/subscribe.html +0 -91
  435. package/docs/docs/decorators/subscribe.md +0 -87
  436. package/docs/docs/decorators/wait-for-ancestors.html +0 -82
  437. package/docs/docs/decorators/wait-for-ancestors.md +0 -76
  438. package/docs/docs/directives/sub.html +0 -79
  439. package/docs/docs/directives/sub.md +0 -75
  440. package/docs/docs/directives/t.html +0 -91
  441. package/docs/docs/directives/t.md +0 -73
  442. package/docs/docs/getting-started/ai-agents.md +0 -76
  443. package/docs/docs/getting-started/components.html +0 -27
  444. package/docs/docs/getting-started/components.md +0 -5
  445. package/docs/docs/getting-started/installation.html +0 -69
  446. package/docs/docs/getting-started/installation.md +0 -36
  447. package/docs/docs/getting-started/my-first-component.md +0 -227
  448. package/docs/docs/getting-started/start.html +0 -47
  449. package/docs/docs/getting-started/start.md +0 -35
  450. package/docs/docs/getting-started/theming.md +0 -253
  451. package/docs/docs/index.html +0 -99
  452. package/docs/docs/misc/api-configuration.md +0 -79
  453. package/docs/docs/misc/dataProviderKey.md +0 -168
  454. package/docs/hubs/decorators.html +0 -443
  455. package/docs/hubs/form-components.html +0 -404
  456. package/docs/hubs/remote-data.html +0 -371
  457. package/docs/img/archive/concorde-001-2cv.webp +0 -0
  458. package/docs/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
  459. package/docs/img/archive/concorde-red-arrows-2002.webm +0 -0
  460. package/docs/img/archive/credits.json +0 -28
  461. package/docs/index.md +0 -22
  462. package/docs/src/core/components/functional/translation/translation.md +0 -38
  463. package/docs/src/docs/decorators/ancestor-attribute.md +0 -59
  464. package/docs/src/docs/decorators/auto-subscribe.md +0 -40
  465. package/docs/src/docs/decorators/bind.md +0 -77
  466. package/docs/src/docs/decorators/get.md +0 -160
  467. package/docs/src/docs/decorators/handle.md +0 -119
  468. package/docs/src/docs/decorators/on-assign.md +0 -63
  469. package/docs/src/docs/decorators/patch.md +0 -44
  470. package/docs/src/docs/decorators/post.md +0 -134
  471. package/docs/src/docs/decorators/publish.md +0 -56
  472. package/docs/src/docs/decorators/put.md +0 -51
  473. package/docs/src/docs/decorators/subscribe.md +0 -87
  474. package/docs/src/docs/decorators/wait-for-ancestors.md +0 -76
  475. package/docs/src/docs/directives/sub.md +0 -75
  476. package/docs/src/docs/directives/t.md +0 -73
  477. package/docs/src/docs/getting-started/components.md +0 -5
  478. package/docs/src/docs/getting-started/create-a-component.md +0 -136
  479. package/docs/src/docs/getting-started/dataFlow.md +0 -87
  480. package/docs/src/docs/getting-started/installation.md +0 -36
  481. package/docs/src/docs/misc/docs-mock-api.md +0 -62
  482. package/docs/src/docs/misc/dynamic-path.md +0 -71
  483. package/docs/src/docs/misc/endpoint.md +0 -45
  484. package/docs/src/docs/misc/html-integration.md +0 -14
  485. /package/{docs → dist}/img/concorde/plane_01.jpg +0 -0
  486. /package/{docs → dist}/img/concorde/plane_02.jpg +0 -0
  487. /package/{docs → dist}/img/concorde/plane_03.jpg +0 -0
  488. /package/{docs → dist}/img/concorde/plane_04.jpg +0 -0
  489. /package/{docs → dist}/img/concorde/plane_05.jpg +0 -0
  490. /package/{docs → dist}/img/concorde/plane_06.jpg +0 -0
  491. /package/{docs → dist}/img/concorde/plane_07.jpg +0 -0
  492. /package/{docs → dist}/img/concorde/plane_08.jpg +0 -0
  493. /package/{docs → dist}/img/concorde/plane_09.jpg +0 -0
  494. /package/{docs → dist}/img/concorde/plane_10.jpg +0 -0
  495. /package/{docs → dist}/img/concorde/plane_11.jpg +0 -0
  496. /package/{docs → dist}/img/concorde/plane_12.jpg +0 -0
  497. /package/{docs → dist}/img/concorde/plane_13.jpg +0 -0
@@ -0,0 +1,122 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import {
4
+ buildManifest,
5
+ collectLitProperties,
6
+ collectLiteralUnions,
7
+ expandType,
8
+ } from "./generate-cem.mjs";
9
+
10
+ test("collectLiteralUnions keeps string-literal aliases only", () => {
11
+ const unions = collectLiteralUnions([
12
+ `export type Size = "sm" | "md";\nexport type Route = string | URL;`,
13
+ `export type Shape =\n | "default"\n | "circle";`,
14
+ ]);
15
+ assert.equal(unions.get("Size"), `"sm" | "md"`);
16
+ assert.equal(unions.get("Shape"), `"default" | "circle"`);
17
+ assert.equal(unions.has("Route"), false);
18
+ });
19
+
20
+ test("collectLiteralUnions drops names defined twice with different values", () => {
21
+ const unions = collectLiteralUnions([`export type Mode = "a" | "b";`, `export type Mode = "c" | "d";`]);
22
+ assert.equal(unions.has("Mode"), false);
23
+ });
24
+
25
+ test("expandType replaces aliases and normalizes whitespace", () => {
26
+ const unions = new Map([["Size", `"sm" | "md"`]]);
27
+ assert.equal(expandType("Size | undefined", unions), `"sm" | "md" | undefined`);
28
+ assert.equal(expandType(`| "a"\n | "b"`, unions), `"a" | "b"`);
29
+ assert.equal(expandType("Route | string", unions), "Route | string");
30
+ });
31
+
32
+ test("collectLitProperties finds fields and accessors, with comments in between", () => {
33
+ const names = collectLitProperties(`
34
+ @property({ type: String }) label = "";
35
+ @property({
36
+ type: Function,
37
+ attribute: false,
38
+ }) /** doc */
39
+ get items() { return this._items; }
40
+ @state() open = false;
41
+ `);
42
+ assert.deepEqual([...names].sort(), ["items", "label"]);
43
+ });
44
+
45
+ const raw = {
46
+ schemaVersion: "1.0.0",
47
+ modules: [
48
+ {
49
+ path: "src/core/mixins/FormElement.ts",
50
+ declarations: [
51
+ {
52
+ kind: "mixin",
53
+ name: "Form",
54
+ attributes: [{ name: "name", type: { text: "string" }, fieldName: "name" }],
55
+ members: [{ kind: "field", name: "name", attribute: "name" }],
56
+ },
57
+ ],
58
+ },
59
+ {
60
+ path: "src/core/components/ui/button/button.ts",
61
+ declarations: [
62
+ {
63
+ kind: "class",
64
+ name: "Button",
65
+ customElement: true,
66
+ mixins: [{ name: "FormElement", package: "@supersoniks/concorde/core/mixins/FormElement" }],
67
+ attributes: [{ name: "size", type: { text: "Size" }, fieldName: "size" }],
68
+ members: [
69
+ { kind: "field", name: "size", attribute: "size", type: { text: "Size" } },
70
+ { kind: "field", name: "items", type: { text: "ListItems" } },
71
+ { kind: "field", name: "pointerDownTime", type: { text: "number" } },
72
+ { kind: "field", name: "_internal" },
73
+ { kind: "method", name: "render" },
74
+ { kind: "method", name: "handleClick" },
75
+ { kind: "method", name: "show", description: "Opens it." },
76
+ ],
77
+ },
78
+ ],
79
+ exports: [{ kind: "custom-element-definition", declaration: { name: "Button" } }],
80
+ },
81
+ {
82
+ path: "src/core/components/functional/example/example.ts",
83
+ declarations: [{ kind: "class", name: "Example", customElement: true }],
84
+ exports: [{ kind: "custom-element-definition", declaration: { name: "Example" } }],
85
+ },
86
+ ],
87
+ };
88
+
89
+ function build() {
90
+ return buildManifest(raw, {
91
+ unions: new Map([["Size", `"sm" | "md"`]]),
92
+ resolveTagName: (p) => (p.includes("button") ? "sonic-button" : "sonic-example"),
93
+ litProperties: (p) => (p.includes("button") ? new Set(["size", "items"]) : new Set()),
94
+ exclude: (p) => p.includes("/functional/example/"),
95
+ });
96
+ }
97
+
98
+ test("buildManifest keeps elements with their tag name and definition export", () => {
99
+ const manifest = build();
100
+ assert.equal(manifest.modules.length, 1);
101
+ const [mod] = manifest.modules;
102
+ const [el] = mod.declarations;
103
+ assert.equal(el.tagName, "sonic-button");
104
+ assert.deepEqual(
105
+ mod.exports.find((e) => e.kind === "custom-element-definition"),
106
+ { kind: "custom-element-definition", name: "sonic-button", declaration: { name: "Button", module: mod.path } },
107
+ );
108
+ assert.equal(el.attributes.find((a) => a.name === "size").type.text, `"sm" | "md"`);
109
+ });
110
+
111
+ test("buildManifest keeps the public API only and merges mixins", () => {
112
+ const [el] = build().modules[0].declarations;
113
+ assert.deepEqual(
114
+ el.members.map((m) => m.name),
115
+ ["size", "items", "show", "name"],
116
+ );
117
+ const inherited = el.attributes.find((a) => a.name === "name");
118
+ assert.deepEqual(inherited.inheritedFrom, {
119
+ name: "FormElement",
120
+ module: "src/core/mixins/FormElement.ts",
121
+ });
122
+ });
@@ -14,6 +14,7 @@ import { fileURLToPath } from "url";
14
14
  import { marked } from "marked";
15
15
  import { gfmHeadingId } from "marked-gfm-heading-id";
16
16
  import { toPublicPath } from "./docs-public-url.mjs";
17
+ import { STATIC_PAGES, renderSitePage } from "./site-pages.mjs";
17
18
 
18
19
  const SITE_ORIGIN = "https://concorde.supersoniks.org";
19
20
  const SRC_DIR = path.resolve("src");
@@ -297,7 +298,7 @@ function writeFileEnsuringDir(filePath, content) {
297
298
  fs.writeFileSync(filePath, content);
298
299
  }
299
300
 
300
- function generateLlmsTxt(pages, hubs = []) {
301
+ export function generateLlmsTxt(pages, hubs = []) {
301
302
  const lines = [
302
303
  "# Concorde by Supersoniks",
303
304
  "",
@@ -314,8 +315,10 @@ function generateLlmsTxt(pages, hubs = []) {
314
315
  `- [Sitemap](${SITE_ORIGIN}/sitemap.xml)`,
315
316
  `- [npm package @supersoniks/concorde](https://www.npmjs.com/package/@supersoniks/concorde)`,
316
317
  `- [Getting started](${SITE_ORIGIN}/docs/getting-started/start)`,
317
- `- [AI agents (skills)](${SITE_ORIGIN}/docs/getting-started/ai-agents)`,
318
+ `- [AI agents (skill)](${SITE_ORIGIN}/docs/getting-started/ai-agents)`,
318
319
  `- [Components index](${SITE_ORIGIN}/docs/getting-started/components)`,
320
+ `- [custom-elements.json](${SITE_ORIGIN}/custom-elements.json) — Custom Elements Manifest: attributes, properties, events and slots of every \`sonic-*\` element`,
321
+ `- [About](${SITE_ORIGIN}/about) · [Privacy](${SITE_ORIGIN}/privacy)`,
319
322
  "",
320
323
  "Doc pages use the same pathnames as the interactive site (`/docs/…`, `/core/…`).",
321
324
  "Markdown: same URL with `.md` (e.g. `/docs/getting-started/start.md`), or `Accept: text/markdown` on the pathname.",
@@ -495,13 +498,16 @@ function generateTopicHubs(pages) {
495
498
  return hubs;
496
499
  }
497
500
 
498
- function generateSitemap(pages, hubs = []) {
501
+ export function generateSitemap(pages, hubs = []) {
499
502
  const homeUrl = ` <url>\n <loc>${SITE_ORIGIN}/</loc>\n </url>`;
500
503
  const homeMdUrl = ` <url>\n <loc>${SITE_ORIGIN}/index.md</loc>\n </url>`;
501
504
  const indexUrl = ` <url>\n <loc>${SITE_ORIGIN}/docs/index.html</loc>\n </url>`;
502
505
  const hubUrls = hubs
503
506
  .map((h) => ` <url>\n <loc>${SITE_ORIGIN}/${h.hubPath}</loc>\n </url>`)
504
507
  .join("\n");
508
+ const staticUrls = STATIC_PAGES.map(
509
+ (p) => ` <url>\n <loc>${SITE_ORIGIN}/${p.slug}</loc>\n </url>`,
510
+ ).join("\n");
505
511
  const urls = pages
506
512
  .map((p) => ` <url>\n <loc>${SITE_ORIGIN}${p.pagePath}</loc>\n </url>`)
507
513
  .join("\n");
@@ -511,6 +517,7 @@ function generateSitemap(pages, hubs = []) {
511
517
  ${homeUrl}
512
518
  ${homeMdUrl}
513
519
  ${indexUrl}
520
+ ${staticUrls}
514
521
  ${hubUrls}
515
522
  ${urls}
516
523
  </urlset>
@@ -533,14 +540,14 @@ Install the npm package [\`@supersoniks/concorde\`](https://www.npmjs.com/packag
533
540
  - Docs index: ${SITE_ORIGIN}/docs/index.html
534
541
  - Sitemap: ${SITE_ORIGIN}/sitemap.xml
535
542
  - Getting started: ${SITE_ORIGIN}/docs/getting-started/start
536
- - AI agents (skills): ${SITE_ORIGIN}/docs/getting-started/ai-agents
543
+ - AI agents (skill): ${SITE_ORIGIN}/docs/getting-started/ai-agents
537
544
  - Components: ${SITE_ORIGIN}/docs/getting-started/components
538
545
 
539
546
  Doc pages share pathnames with the interactive site (\`/docs/…\`, \`/core/…\`). Markdown is at the same path with a \`.md\` suffix (e.g. \`/docs/getting-started/start.md\`), or via \`Accept: text/markdown\` on the pathname (\`Content-Type: text/markdown\`, \`Vary: Accept\`).
540
547
 
541
548
  ## What Concorde includes
542
549
 
543
- Custom elements (\`sonic-*\`) for buttons, forms, lists, queues, SDUI trees and more. Decorators such as \`@get\`, \`@post\`, \`@subscribe\` and \`@bind\` wire components to a shared DataProvider without framework lock-in. Concorde is MIT-licensed and maintained by Supersoniks.
550
+ Custom elements (\`sonic-*\`) for buttons, forms, lists, queues, SDUI trees and more. Decorators such as \`@get\`, \`@post\`, \`@subscribe\` and \`@bind\` wire components to a shared DataProvider without framework lock-in. Concorde is MIT-licensed and maintained by Supersoniks ([about](${SITE_ORIGIN}/about), [privacy](${SITE_ORIGIN}/privacy)).
544
551
  `;
545
552
  }
546
553
 
@@ -581,11 +588,28 @@ export function generateHtaccess() {
581
588
  return fs.readFileSync(htaccessPath, "utf8");
582
589
  }
583
590
 
591
+ /** SPA shell for site pages: the built docs/index.html, else the source one. */
592
+ function readSpaShell(docsOut) {
593
+ const built = path.join(docsOut, "index.html");
594
+ return fs.readFileSync(
595
+ fs.existsSync(built) ? built : path.resolve("index.html"),
596
+ "utf8",
597
+ );
598
+ }
599
+
584
600
  export function writeAgentSiteArtifacts(docsOut = DOCS_OUT) {
585
601
  fs.writeFileSync(path.join(docsOut, "index.md"), generateHomepageMarkdown());
586
602
  fs.writeFileSync(path.join(docsOut, "404.md"), generateNotFoundMarkdown());
587
603
  fs.writeFileSync(path.join(docsOut, "404.html"), generateNotFoundHtml());
588
604
  fs.writeFileSync(path.join(docsOut, ".htaccess"), generateHtaccess());
605
+ const shell = readSpaShell(docsOut);
606
+ for (const page of STATIC_PAGES) {
607
+ fs.writeFileSync(path.join(docsOut, `${page.slug}.md`), page.markdown);
608
+ fs.writeFileSync(
609
+ path.join(docsOut, `${page.slug}.html`),
610
+ renderSitePage(page, marked.parse(page.markdown), shell),
611
+ );
612
+ }
589
613
  }
590
614
 
591
615
  function removeLegacyCrawlDir() {
@@ -14,7 +14,7 @@ import { fileURLToPath } from "url";
14
14
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
15
  const ROOT = path.resolve(__dirname, "..");
16
16
  const CEM_DIR = path.join(ROOT, ".tmp-cem");
17
- const CEM_PATH = path.join(CEM_DIR, "custom-elements.json");
17
+ export const CEM_PATH = path.join(CEM_DIR, "custom-elements.json");
18
18
  const OUT_CATALOG = path.join(
19
19
  ROOT,
20
20
  "src/core/components/functional/sdui/component-catalog.json"
@@ -24,7 +24,7 @@ const OUT_GAPS = path.join(
24
24
  "src/core/components/functional/sdui/component-catalog.gaps.json"
25
25
  );
26
26
 
27
- function extractTagNameFromSource(filePath) {
27
+ export function extractTagNameFromSource(filePath) {
28
28
  if (!fs.existsSync(filePath)) return undefined;
29
29
  const src = fs.readFileSync(filePath, "utf8");
30
30
  const literal = src.match(/@customElement\(\s*["'`]([^"'`]+)["'`]\s*\)/);
@@ -176,8 +176,12 @@ export function cemToCatalog(cem, { resolveTagName } = {}) {
176
176
  };
177
177
  }
178
178
 
179
- function runCem() {
179
+ export function runCem(
180
+ configPath = path.join(ROOT, "custom-elements-manifest.config.mjs"),
181
+ ) {
180
182
  fs.mkdirSync(CEM_DIR, { recursive: true });
183
+ const pkgPath = path.join(ROOT, "package.json");
184
+ const pkgBefore = fs.readFileSync(pkgPath, "utf8");
181
185
  const cemBin = path.join(
182
186
  ROOT,
183
187
  "node_modules/@custom-elements-manifest/analyzer/cem.js"
@@ -188,16 +192,13 @@ function runCem() {
188
192
  cemBin,
189
193
  "analyze",
190
194
  "--config",
191
- path.join(ROOT, "custom-elements-manifest.config.mjs"),
195
+ configPath,
192
196
  ],
193
197
  { cwd: ROOT, stdio: ["ignore", "pipe", "pipe"] }
194
198
  );
195
- // Ne pas laisser cem écrire customElements dans package.json
196
- const pkgPath = path.join(ROOT, "package.json");
197
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
198
- if (pkg.customElements) {
199
- delete pkg.customElements;
200
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
199
+ // cem may rewrite package.json (customElements): keep it as it was
200
+ if (fs.readFileSync(pkgPath, "utf8") !== pkgBefore) {
201
+ fs.writeFileSync(pkgPath, pkgBefore);
201
202
  }
202
203
  }
203
204
 
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Prépare une arborescence « lib publique » pour GitHub :
4
+ * - sans site doc (src/docs, index.html, …)
5
+ * - sans sonic-captcha (altcha.supersoniks.org)
6
+ * - sans scripts / jobs GitLab internes
7
+ *
8
+ * Usage :
9
+ * node scripts/github-export.mjs [répertoire_cible]
10
+ *
11
+ * Par défaut : ../concorde-github-export
12
+ */
13
+ import fs from "fs";
14
+ import path from "path";
15
+ import { fileURLToPath } from "url";
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+ const ROOT = path.resolve(__dirname, "..");
19
+ const IGNORE_FILE = path.join(ROOT, ".github-export-ignore");
20
+ const DEFAULT_OUT = path.resolve(ROOT, "../concorde-github-export");
21
+
22
+ const EXPORT_FILTER_KEY =
23
+ /(?:^|\/)(?:docs|mock-api|undefined)(?:\/|$)|captcha|\.demo\.|\.stories\.|TestUtils|\/prism\/|\/search\/|\/tailwind\/|\/header\/|\/navigation\/|\/layout\.ts$|\/code\.ts$|^code$|^docs$|^layout$/;
24
+
25
+ function readIgnorePatterns() {
26
+ if (!fs.existsSync(IGNORE_FILE)) return [];
27
+ return fs
28
+ .readFileSync(IGNORE_FILE, "utf8")
29
+ .split("\n")
30
+ .map((l) => l.trim())
31
+ .filter((l) => l && !l.startsWith("#"));
32
+ }
33
+
34
+ function globToRegExp(pattern) {
35
+ const escaped = pattern
36
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
37
+ .replace(/\*\*/g, "{{GLOBSTAR}}")
38
+ .replace(/\*/g, "[^/]*")
39
+ .replace(/\{\{GLOBSTAR\}\}/g, ".*");
40
+ return new RegExp(`^${escaped}$`);
41
+ }
42
+
43
+ function shouldExclude(relativePath, patterns) {
44
+ const normalized = relativePath.replace(/\\/g, "/");
45
+ for (const pattern of patterns) {
46
+ const re = globToRegExp(pattern);
47
+ if (re.test(normalized)) return true;
48
+ if (normalized.startsWith(pattern.endsWith("/") ? pattern : `${pattern}/`))
49
+ return true;
50
+ if (normalized === pattern) return true;
51
+ }
52
+ return false;
53
+ }
54
+
55
+ function listAllFiles(dir, base = dir) {
56
+ const out = [];
57
+ for (const name of fs.readdirSync(dir, { withFileTypes: true })) {
58
+ if (name.name === ".git" || name.name === "node_modules") continue;
59
+ const full = path.join(dir, name.name);
60
+ const rel = path.relative(base, full).replace(/\\/g, "/");
61
+ if (name.isDirectory()) {
62
+ if (shouldExclude(rel, ignorePatterns)) continue;
63
+ out.push(...listAllFiles(full, base));
64
+ } else {
65
+ if (!shouldExclude(rel, ignorePatterns)) out.push(rel);
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+
71
+ function copyFile(rel, destRoot) {
72
+ const src = path.join(ROOT, rel);
73
+ const dest = path.join(destRoot, rel);
74
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
75
+ fs.copyFileSync(src, dest);
76
+ }
77
+
78
+ function patchUiTs(destRoot) {
79
+ const uiPath = path.join(
80
+ destRoot,
81
+ "src/core/components/ui/ui.ts",
82
+ );
83
+ if (!fs.existsSync(uiPath)) return;
84
+ const content = fs.readFileSync(uiPath, "utf8");
85
+ const patched = content.replace(
86
+ /import "\.\/captcha\/captcha";\n?/,
87
+ "",
88
+ );
89
+ fs.writeFileSync(uiPath, patched);
90
+ }
91
+
92
+ function exportHaystack(value) {
93
+ if (typeof value === "string") return value;
94
+ if (value && typeof value === "object") {
95
+ return `${value.types ?? ""}${value.default ?? ""}`;
96
+ }
97
+ return String(value);
98
+ }
99
+
100
+ function filterPackageJson(destRoot) {
101
+ const pkgPath = path.join(destRoot, "package.json");
102
+ if (!fs.existsSync(pkgPath)) return;
103
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
104
+ if (pkg.exports && typeof pkg.exports === "object") {
105
+ const next = {};
106
+ for (const [key, value] of Object.entries(pkg.exports)) {
107
+ const hay = `${key}:${exportHaystack(value)}`;
108
+ if (EXPORT_FILTER_KEY.test(hay)) continue;
109
+ if (exportHaystack(value).includes("/captcha/")) continue;
110
+ if (exportHaystack(value).includes("/docs/")) continue;
111
+ if (exportHaystack(value).includes(".demo.")) continue;
112
+ if (exportHaystack(value).includes(".stories.")) continue;
113
+ next[key] = value;
114
+ }
115
+ pkg.exports = next;
116
+ }
117
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
118
+ }
119
+
120
+ function patchReadme(destRoot) {
121
+ const readmePath = path.join(destRoot, "README.md");
122
+ if (!fs.existsSync(readmePath)) return;
123
+ let text = fs.readFileSync(readmePath, "utf8");
124
+ text = text.replace(
125
+ /Le dépôt GitHub est un \*\*miroir\*\* synchronisé depuis GitLab \(voir \[OPEN_SOURCE_CHECKPOINT\.md\]\(OPEN_SOURCE_CHECKPOINT\.md\)\)\./,
126
+ "Le dépôt GitHub est un **export filtré** depuis GitLab (librairie uniquement, sans site doc ni composant captcha — voir [OPEN_SOURCE_CHECKPOINT.md](OPEN_SOURCE_CHECKPOINT.md)).",
127
+ );
128
+ fs.writeFileSync(readmePath, text);
129
+ }
130
+
131
+ const ignorePatterns = readIgnorePatterns();
132
+ const outDir = path.resolve(process.argv[2] || DEFAULT_OUT);
133
+
134
+ if (fs.existsSync(outDir)) {
135
+ fs.rmSync(outDir, { recursive: true, force: true });
136
+ }
137
+ fs.mkdirSync(outDir, { recursive: true });
138
+
139
+ const files = listAllFiles(ROOT);
140
+ for (const rel of files) {
141
+ copyFile(rel, outDir);
142
+ }
143
+
144
+ patchUiTs(outDir);
145
+ filterPackageJson(outDir);
146
+ patchReadme(outDir);
147
+
148
+ console.log(`✅ Export GitHub : ${files.length} fichiers → ${outDir}`);
149
+ console.log(" Exclusions : .github-export-ignore");
150
+ console.log(" Patches : ui.ts (sans captcha), package.json exports");
@@ -1,6 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import { generateCrawlDocs } from "./generate-crawl-docs.mjs";
4
+ import { generateCem } from "./generate-cem.mjs";
4
5
 
5
6
  const src = path.resolve("src");
6
7
  const docs = path.resolve("docs");
@@ -52,6 +53,8 @@ function copyDocs() {
52
53
  }
53
54
 
54
55
  copyDocs();
56
+ // Custom Elements Manifest, served at /custom-elements.json
57
+ fs.copyFileSync(generateCem(), path.join(docs, "custom-elements.json"));
55
58
  generateCrawlDocs();
56
59
 
57
60
  function copyToConcordeDoc() {
File without changes
@@ -4,8 +4,9 @@ import fs from "fs";
4
4
  const requiredFiles = [
5
5
  'concorde-core.bundle.js',
6
6
  'concorde-core.es.js',
7
- 'ai/AGENTS.md',
7
+ 'ai/skills/concorde/SKILL.md',
8
8
  'scripts/ai-init.mjs',
9
+ 'custom-elements.json',
9
10
  ];
10
11
 
11
12
  let allFilesExist = true;
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Homepage JSON-LD and the root site pages (/about, /privacy).
3
+ *
4
+ * Page content lives in site-pages/*.md: the SPA renders it at /about, and
5
+ * the build publishes `slug.md` + `slug.html` (SPA shell with the page
6
+ * inlined for crawlers and link previews).
7
+ */
8
+ import fs from "fs";
9
+ import { fileURLToPath } from "url";
10
+
11
+ export const SITE_ORIGIN = "https://concorde.supersoniks.org";
12
+ export const NPM_URL = "https://www.npmjs.com/package/@supersoniks/concorde";
13
+
14
+ /** Publisher details, from https://supersoniks.com/mentions-legales */
15
+ export const ORGANIZATION = {
16
+ name: "Supersoniks",
17
+ legalName: "SUPERSONIKS",
18
+ url: "https://supersoniks.com/",
19
+ contactUrl: "https://supersoniks.com/un-projet",
20
+ telephone: "+33 2 47 68 93 25",
21
+ streetAddress: "22 rue du Docteur Bretonneau",
22
+ postalCode: "37000",
23
+ addressLocality: "Tours",
24
+ addressCountry: "FR",
25
+ sameAs: [
26
+ "https://www.linkedin.com/company/supersoniks/",
27
+ "https://www.facebook.com/supersoniks",
28
+ "https://www.instagram.com/agencesupersoniks/",
29
+ ],
30
+ };
31
+
32
+ function escapeHtml(text) {
33
+ return String(text)
34
+ .replace(/&/g, "&amp;")
35
+ .replace(/</g, "&lt;")
36
+ .replace(/>/g, "&gt;")
37
+ .replace(/"/g, "&quot;");
38
+ }
39
+
40
+ /* -------------------------------------------------------------------------- */
41
+ /* JSON-LD */
42
+ /* -------------------------------------------------------------------------- */
43
+
44
+ export function organizationJsonLd() {
45
+ return {
46
+ "@type": "Organization",
47
+ "@id": `${ORGANIZATION.url}#organization`,
48
+ name: ORGANIZATION.name,
49
+ legalName: ORGANIZATION.legalName,
50
+ url: ORGANIZATION.url,
51
+ telephone: ORGANIZATION.telephone,
52
+ address: {
53
+ "@type": "PostalAddress",
54
+ streetAddress: ORGANIZATION.streetAddress,
55
+ postalCode: ORGANIZATION.postalCode,
56
+ addressLocality: ORGANIZATION.addressLocality,
57
+ addressCountry: ORGANIZATION.addressCountry,
58
+ },
59
+ contactPoint: {
60
+ "@type": "ContactPoint",
61
+ contactType: "customer service",
62
+ telephone: ORGANIZATION.telephone,
63
+ url: ORGANIZATION.contactUrl,
64
+ availableLanguage: ["fr", "en"],
65
+ },
66
+ sameAs: ORGANIZATION.sameAs,
67
+ };
68
+ }
69
+
70
+ /** Homepage graph: WebSite + SoftwareApplication + Organization. */
71
+ export function homepageJsonLd() {
72
+ const org = { "@id": `${ORGANIZATION.url}#organization` };
73
+ return {
74
+ "@context": "https://schema.org",
75
+ "@graph": [
76
+ {
77
+ "@type": "WebSite",
78
+ "@id": `${SITE_ORIGIN}/#website`,
79
+ name: "Concorde",
80
+ alternateName: "Concorde by Supersoniks",
81
+ url: `${SITE_ORIGIN}/`,
82
+ inLanguage: "en",
83
+ publisher: org,
84
+ },
85
+ {
86
+ "@type": "SoftwareApplication",
87
+ "@id": `${SITE_ORIGIN}/#software`,
88
+ name: "Concorde",
89
+ alternateName: "@supersoniks/concorde",
90
+ description:
91
+ "Concorde is an open-source web components framework built on Lit: UI components, data binding, forms, routing helpers and theming that work in React, Vue, PHP or plain HTML.",
92
+ url: `${SITE_ORIGIN}/`,
93
+ applicationCategory: "DeveloperApplication",
94
+ applicationSubCategory: "Web components framework",
95
+ operatingSystem: "Any (web browser)",
96
+ programmingLanguage: "TypeScript",
97
+ license: "https://opensource.org/licenses/MIT",
98
+ downloadUrl: NPM_URL,
99
+ softwareHelp: `${SITE_ORIGIN}/docs/getting-started/start`,
100
+ image: `${SITE_ORIGIN}/img/og-concorde.jpg`,
101
+ offers: { "@type": "Offer", price: "0", priceCurrency: "EUR" },
102
+ author: org,
103
+ publisher: org,
104
+ sameAs: [NPM_URL],
105
+ },
106
+ organizationJsonLd(),
107
+ ],
108
+ };
109
+ }
110
+
111
+ /* -------------------------------------------------------------------------- */
112
+ /* Site pages: /about, /privacy */
113
+ /* -------------------------------------------------------------------------- */
114
+
115
+ const SITE_PAGES_DIR = fileURLToPath(new URL("../site-pages/", import.meta.url));
116
+
117
+ export const STATIC_PAGES = [
118
+ {
119
+ slug: "about",
120
+ title: "About Concorde — web components framework by Supersoniks",
121
+ description:
122
+ "Concorde is an open-source Lit web components framework designed and maintained by Supersoniks, Tours, France.",
123
+ },
124
+ {
125
+ slug: "privacy",
126
+ title: "Privacy notice — Concorde by Supersoniks",
127
+ description:
128
+ "Privacy notice of the Concorde documentation site: no cookies, no analytics, third-party hosts and your GDPR rights.",
129
+ },
130
+ ].map((page) => ({
131
+ ...page,
132
+ markdown: fs.readFileSync(`${SITE_PAGES_DIR}${page.slug}.md`, "utf8"),
133
+ }));
134
+
135
+ function pageJsonLd(page) {
136
+ return {
137
+ "@context": "https://schema.org",
138
+ "@type": page.slug === "about" ? "AboutPage" : "WebPage",
139
+ name: page.title,
140
+ description: page.description,
141
+ url: `${SITE_ORIGIN}/${page.slug}`,
142
+ isPartOf: { "@type": "WebSite", name: "Concorde", url: `${SITE_ORIGIN}/` },
143
+ publisher: organizationJsonLd(),
144
+ };
145
+ }
146
+
147
+ function replaceOnce(html, re, replacement, what) {
148
+ if (!re.test(html)) throw new Error(`site page shell: ${what} not found`);
149
+ return html.replace(re, () => replacement);
150
+ }
151
+
152
+ /**
153
+ * `slug.html`: the SPA shell (built docs/index.html) with the page's
154
+ * metadata and its rendered content in the no-JS section. Browsers boot the
155
+ * SPA, which renders the same Markdown; crawlers read the inline copy.
156
+ */
157
+ export function renderSitePage(page, bodyHtml, shellHtml) {
158
+ const url = `${SITE_ORIGIN}/${page.slug}`;
159
+ const title = escapeHtml(page.title);
160
+ const description = escapeHtml(page.description);
161
+ let html = shellHtml;
162
+ html = replaceOnce(html, /<title>[\s\S]*?<\/title>/, `<title>${title}</title>`, "title");
163
+ html = replaceOnce(
164
+ html,
165
+ /<meta\s+name="description"\s+content="[^"]*"\s*\/?>/,
166
+ `<meta name="description" content="${description}" />`,
167
+ "description",
168
+ );
169
+ html = replaceOnce(
170
+ html,
171
+ /<link rel="canonical" href="[^"]*"\s*\/?>/,
172
+ `<link rel="canonical" href="${url}" />`,
173
+ "canonical",
174
+ );
175
+ html = replaceOnce(
176
+ html,
177
+ /<link rel="alternate" type="text\/markdown" href="[^"]*"/,
178
+ `<link rel="alternate" type="text/markdown" href="/${page.slug}.md"`,
179
+ "markdown alternate",
180
+ );
181
+ html = replaceOnce(
182
+ html,
183
+ /<meta property="og:title" content="[^"]*"/,
184
+ `<meta property="og:title" content="${title}"`,
185
+ "og:title",
186
+ );
187
+ html = replaceOnce(
188
+ html,
189
+ /<meta property="og:description" content="[^"]*"/,
190
+ `<meta property="og:description" content="${description}"`,
191
+ "og:description",
192
+ );
193
+ html = replaceOnce(
194
+ html,
195
+ /<meta property="og:url" content="[^"]*"/,
196
+ `<meta property="og:url" content="${url}"`,
197
+ "og:url",
198
+ );
199
+ html = replaceOnce(
200
+ html,
201
+ /<script type="application\/ld\+json">[\s\S]*?<\/script>/,
202
+ `<script type="application/ld+json">${JSON.stringify(pageJsonLd(page))}</script>`,
203
+ "JSON-LD",
204
+ );
205
+ html = replaceOnce(
206
+ html,
207
+ /<section id="docs-agent-content"([^>]*)>[\s\S]*?<\/section>/,
208
+ `<section id="docs-agent-content" aria-hidden="true">\n${bodyHtml}\n </section>`,
209
+ "page section",
210
+ );
211
+ return html;
212
+ }