@aglyn/plugins-ai 1.0.0-beta.230 → 1.0.0-beta.232

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 (305) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.js +8 -4
  3. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  4. package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
  5. package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
  6. package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
  7. package/src/lib/components/ai-assist-provider.component.js +9 -10
  8. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  9. package/src/lib/components/ai-job-follow.component.js +1 -0
  10. package/src/lib/components/ai-job-follow.component.js.map +1 -1
  11. package/src/lib/components/ai-job-links.js +13 -0
  12. package/src/lib/components/ai-job-links.js.map +1 -1
  13. package/src/lib/components/ai-job-plan.component.js +3 -1
  14. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  15. package/src/lib/components/ai-jobs-list-page.component.js +1 -0
  16. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  17. package/src/lib/components/ai-media-create.component.d.ts +20 -7
  18. package/src/lib/components/ai-media-create.component.js +107 -55
  19. package/src/lib/components/ai-media-create.component.js.map +1 -1
  20. package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
  21. package/src/lib/components/ai-permissions-on-host.component.js +5 -53
  22. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  23. package/src/lib/components/ai-seo-fields-card.component.js +1 -0
  24. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  25. package/src/lib/components/ai-site-build-page.component.js +20 -8
  26. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  27. package/src/lib/components/ai-site-memory-card.component.d.ts +32 -0
  28. package/src/lib/components/ai-site-memory-card.component.js +187 -0
  29. package/src/lib/components/ai-site-memory-card.component.js.map +1 -0
  30. package/src/lib/components/ai-site-start-card.component.js +80 -77
  31. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  32. package/src/lib/components/ai-theme-proposal-card.component.js +4 -0
  33. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  34. package/src/lib/components/ai-usage-strip.component.js +1 -0
  35. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  36. package/src/lib/components/assist-panel.component.d.ts +10 -0
  37. package/src/lib/components/assist-panel.component.js +119 -9
  38. package/src/lib/components/assist-panel.component.js.map +1 -1
  39. package/src/lib/components/assist-signals-page.component.js +2 -0
  40. package/src/lib/components/assist-signals-page.component.js.map +1 -1
  41. package/src/lib/components/billing-ai-allotments.component.js +3 -0
  42. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  43. package/src/lib/components/billing-ai-top-users.component.js +1 -0
  44. package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
  45. package/src/lib/components/billing-assist-overage-card.component.js +2 -0
  46. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  47. package/src/lib/components/member-ai-usage-card.component.js +10 -0
  48. package/src/lib/components/member-ai-usage-card.component.js.map +1 -1
  49. package/src/lib/components/staff-org-ai-card.component.js +1 -0
  50. package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
  51. package/src/lib/components/staff-org-ai-conversations.component.d.ts +23 -0
  52. package/src/lib/components/staff-org-ai-conversations.component.js +346 -0
  53. package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -0
  54. package/src/lib/jobs/ai-build-capabilities.d.ts +13 -1
  55. package/src/lib/jobs/ai-build-capabilities.js +101 -7
  56. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  57. package/src/lib/jobs/ai-build-unit-outcome.js +4 -2
  58. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
  59. package/src/lib/jobs/ai-business-profile-prefill.d.ts +29 -0
  60. package/src/lib/jobs/ai-business-profile-prefill.js +85 -0
  61. package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -0
  62. package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
  63. package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
  64. package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
  65. package/src/lib/jobs/ai-job-build-step.js +14 -1
  66. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  67. package/src/lib/jobs/ai-job-edit-step.d.ts +225 -0
  68. package/src/lib/jobs/ai-job-edit-step.js +631 -0
  69. package/src/lib/jobs/ai-job-edit-step.js.map +1 -0
  70. package/src/lib/jobs/ai-job-generation.d.ts +8 -0
  71. package/src/lib/jobs/ai-job-generation.js +13 -2
  72. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  73. package/src/lib/jobs/ai-job-insight-step.js +29 -5
  74. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  75. package/src/lib/jobs/ai-job-layout-language.d.ts +78 -0
  76. package/src/lib/jobs/ai-job-layout-language.js +200 -0
  77. package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
  78. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
  79. package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
  80. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  81. package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
  82. package/src/lib/jobs/ai-job-layout-step.js +107 -6
  83. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  84. package/src/lib/jobs/ai-job-logic-step.d.ts +20 -0
  85. package/src/lib/jobs/ai-job-logic-step.js +87 -6
  86. package/src/lib/jobs/ai-job-logic-step.js.map +1 -1
  87. package/src/lib/jobs/ai-job-page-language.d.ts +194 -0
  88. package/src/lib/jobs/ai-job-page-language.js +418 -0
  89. package/src/lib/jobs/ai-job-page-language.js.map +1 -0
  90. package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
  91. package/src/lib/jobs/ai-job-page-sections.js +93 -11
  92. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  93. package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
  94. package/src/lib/jobs/ai-job-page-step.js +115 -14
  95. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  96. package/src/lib/jobs/ai-job-plan-step.d.ts +20 -6
  97. package/src/lib/jobs/ai-job-plan-step.js +62 -22
  98. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  99. package/src/lib/jobs/ai-job-site-content.d.ts +163 -0
  100. package/src/lib/jobs/ai-job-site-content.js +443 -0
  101. package/src/lib/jobs/ai-job-site-content.js.map +1 -0
  102. package/src/lib/jobs/ai-job-site-look.d.ts +112 -0
  103. package/src/lib/jobs/ai-job-site-look.js +322 -0
  104. package/src/lib/jobs/ai-job-site-look.js.map +1 -0
  105. package/src/lib/jobs/ai-job-site-step.d.ts +30 -5
  106. package/src/lib/jobs/ai-job-site-step.js +183 -27
  107. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  108. package/src/lib/jobs/ai-job-workflow-step.js +2 -2
  109. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  110. package/src/lib/jobs/ai-jobs-notify.d.ts +6 -1
  111. package/src/lib/jobs/ai-jobs-notify.js +15 -3
  112. package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
  113. package/src/lib/jobs/ai-jobs.d.ts +1 -1
  114. package/src/lib/jobs/ai-jobs.js +17 -8
  115. package/src/lib/jobs/ai-jobs.js.map +1 -1
  116. package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
  117. package/src/lib/jobs/ai-layout-full-height.js +82 -0
  118. package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
  119. package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
  120. package/src/lib/jobs/ai-layout-site-facts.js +153 -0
  121. package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
  122. package/src/lib/layout-language/ai-layout-compiler.d.ts +154 -0
  123. package/src/lib/layout-language/ai-layout-compiler.js +1235 -0
  124. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
  125. package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
  126. package/src/lib/layout-language/ai-layout-copy.js +137 -0
  127. package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
  128. package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
  129. package/src/lib/layout-language/ai-layout-frame.js +458 -0
  130. package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
  131. package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
  132. package/src/lib/layout-language/ai-layout-gaps.js +345 -0
  133. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
  134. package/src/lib/layout-language/ai-layout-language.d.ts +168 -0
  135. package/src/lib/layout-language/ai-layout-language.js +529 -0
  136. package/src/lib/layout-language/ai-layout-language.js.map +1 -0
  137. package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
  138. package/src/lib/layout-language/ai-layout-links.js +109 -0
  139. package/src/lib/layout-language/ai-layout-links.js.map +1 -0
  140. package/src/lib/layout-language/ai-layout-pictures.d.ts +144 -0
  141. package/src/lib/layout-language/ai-layout-pictures.js +214 -0
  142. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -0
  143. package/src/lib/layout-language/ai-layout-store.d.ts +41 -0
  144. package/src/lib/layout-language/ai-layout-store.js +75 -0
  145. package/src/lib/layout-language/ai-layout-store.js.map +1 -0
  146. package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
  147. package/src/lib/layout-language/ai-layout-tree.js +84 -0
  148. package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
  149. package/src/lib/lazy-widget.d.ts +45 -0
  150. package/src/lib/lazy-widget.js +53 -0
  151. package/src/lib/lazy-widget.js.map +1 -0
  152. package/src/lib/model/ai-build-job.js +2 -1
  153. package/src/lib/model/ai-build-job.js.map +1 -1
  154. package/src/lib/model/ai-build-progress.d.ts +20 -3
  155. package/src/lib/model/ai-build-progress.js +52 -7
  156. package/src/lib/model/ai-build-progress.js.map +1 -1
  157. package/src/lib/model/ai-edit-job.d.ts +109 -0
  158. package/src/lib/model/ai-edit-job.js +157 -0
  159. package/src/lib/model/ai-edit-job.js.map +1 -0
  160. package/src/lib/model/ai-host-publish-context.d.ts +51 -0
  161. package/src/lib/model/ai-host-publish-context.js +104 -0
  162. package/src/lib/model/ai-host-publish-context.js.map +1 -0
  163. package/src/lib/model/ai-job-activity.d.ts +22 -0
  164. package/src/lib/model/ai-job-activity.js +23 -1
  165. package/src/lib/model/ai-job-activity.js.map +1 -1
  166. package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
  167. package/src/lib/model/ai-job-failure-copy.js +56 -1
  168. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  169. package/src/lib/model/ai-job-notice.d.ts +3 -1
  170. package/src/lib/model/ai-job-notice.js +31 -9
  171. package/src/lib/model/ai-job-notice.js.map +1 -1
  172. package/src/lib/model/ai-jobs.types.d.ts +22 -1
  173. package/src/lib/model/ai-jobs.types.js.map +1 -1
  174. package/src/lib/model/ai-logic-job.d.ts +18 -1
  175. package/src/lib/model/ai-logic-job.js +24 -3
  176. package/src/lib/model/ai-logic-job.js.map +1 -1
  177. package/src/lib/model/ai-media-credits.d.ts +8 -4
  178. package/src/lib/model/ai-media-credits.js +11 -4
  179. package/src/lib/model/ai-media-credits.js.map +1 -1
  180. package/src/lib/model/ai-media-kinds.d.ts +68 -0
  181. package/src/lib/model/ai-media-kinds.js +98 -0
  182. package/src/lib/model/ai-media-kinds.js.map +1 -0
  183. package/src/lib/model/ai-site-build-progress.d.ts +9 -1
  184. package/src/lib/model/ai-site-build-progress.js +54 -14
  185. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  186. package/src/lib/model/ai-site-context.d.ts +111 -0
  187. package/src/lib/model/ai-site-context.js +222 -0
  188. package/src/lib/model/ai-site-context.js.map +1 -0
  189. package/src/lib/model/ai-site-job.d.ts +18 -2
  190. package/src/lib/model/ai-site-job.js +21 -5
  191. package/src/lib/model/ai-site-job.js.map +1 -1
  192. package/src/lib/model/ai-site-kinds.d.ts +164 -0
  193. package/src/lib/model/ai-site-kinds.js +1942 -0
  194. package/src/lib/model/ai-site-kinds.js.map +1 -0
  195. package/src/lib/model/ai-site-look.d.ts +150 -0
  196. package/src/lib/model/ai-site-look.js +1236 -0
  197. package/src/lib/model/ai-site-look.js.map +1 -0
  198. package/src/lib/model/ai-site-memory.d.ts +80 -0
  199. package/src/lib/model/ai-site-memory.js +171 -0
  200. package/src/lib/model/ai-site-memory.js.map +1 -0
  201. package/src/lib/model/ai-site-start-seo.d.ts +1 -1
  202. package/src/lib/model/ai-site-start.d.ts +15 -3
  203. package/src/lib/model/ai-site-start.js +21 -4
  204. package/src/lib/model/ai-site-start.js.map +1 -1
  205. package/src/lib/model/assist-follow-up.d.ts +92 -0
  206. package/src/lib/model/assist-follow-up.js +128 -0
  207. package/src/lib/model/assist-follow-up.js.map +1 -0
  208. package/src/lib/plugin-config.js +2 -0
  209. package/src/lib/plugin-config.js.map +1 -1
  210. package/src/lib/plugin.js +99 -48
  211. package/src/lib/plugin.js.map +1 -1
  212. package/src/lib/providers/anthropic.d.ts +9 -1
  213. package/src/lib/providers/anthropic.js +143 -9
  214. package/src/lib/providers/anthropic.js.map +1 -1
  215. package/src/lib/providers/catalog.d.ts +38 -8
  216. package/src/lib/providers/catalog.js +106 -14
  217. package/src/lib/providers/catalog.js.map +1 -1
  218. package/src/lib/providers/contract.d.ts +29 -0
  219. package/src/lib/providers/contract.js.map +1 -1
  220. package/src/lib/providers/image-contract.d.ts +22 -1
  221. package/src/lib/providers/image-contract.js +40 -1
  222. package/src/lib/providers/image-contract.js.map +1 -1
  223. package/src/lib/providers/image-endpoints.d.ts +24 -0
  224. package/src/lib/providers/image-endpoints.js +28 -0
  225. package/src/lib/providers/image-endpoints.js.map +1 -0
  226. package/src/lib/providers/model-choice.js +23 -2
  227. package/src/lib/providers/model-choice.js.map +1 -1
  228. package/src/lib/providers/routing.js +18 -0
  229. package/src/lib/providers/routing.js.map +1 -1
  230. package/src/lib/providers/vertex-image-endpoint.d.ts +48 -0
  231. package/src/lib/providers/vertex-image-endpoint.js +80 -0
  232. package/src/lib/providers/vertex-image-endpoint.js.map +1 -0
  233. package/src/lib/providers/vertex-image.d.ts +13 -27
  234. package/src/lib/providers/vertex-image.js +15 -42
  235. package/src/lib/providers/vertex-image.js.map +1 -1
  236. package/src/lib/runtime/ai-blog-post-generation.d.ts +62 -0
  237. package/src/lib/runtime/ai-blog-post-generation.js +89 -0
  238. package/src/lib/runtime/ai-blog-post-generation.js.map +1 -0
  239. package/src/lib/runtime/ai-dev-env.d.ts +53 -0
  240. package/src/lib/runtime/ai-dev-env.js +72 -0
  241. package/src/lib/runtime/ai-dev-env.js.map +1 -0
  242. package/src/lib/runtime/ai-dev-replay.d.ts +116 -0
  243. package/src/lib/runtime/ai-dev-replay.js +313 -0
  244. package/src/lib/runtime/ai-dev-replay.js.map +1 -0
  245. package/src/lib/runtime/ai-doctrine-validators.d.ts +82 -0
  246. package/src/lib/runtime/ai-doctrine-validators.js +436 -4
  247. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  248. package/src/lib/runtime/ai-doctrine.js +16 -3
  249. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  250. package/src/lib/runtime/ai-eval-live.js +4 -0
  251. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  252. package/src/lib/runtime/ai-eval.d.ts +13 -1
  253. package/src/lib/runtime/ai-eval.js +84 -1
  254. package/src/lib/runtime/ai-eval.js.map +1 -1
  255. package/src/lib/runtime/ai-icon-library.d.ts +257 -0
  256. package/src/lib/runtime/ai-icon-library.js +254 -0
  257. package/src/lib/runtime/ai-icon-library.js.map +1 -0
  258. package/src/lib/runtime/ai-live-batch.d.ts +45 -0
  259. package/src/lib/runtime/ai-live-batch.js +89 -0
  260. package/src/lib/runtime/ai-live-batch.js.map +1 -0
  261. package/src/lib/runtime/ai-node-tree.d.ts +9 -0
  262. package/src/lib/runtime/ai-node-tree.js +30 -4
  263. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  264. package/src/lib/runtime/ai-palette.d.ts +6 -0
  265. package/src/lib/runtime/ai-palette.generated.js +70 -0
  266. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  267. package/src/lib/runtime/ai-palette.js.map +1 -1
  268. package/src/lib/runtime/ai-runtime.js +46 -2
  269. package/src/lib/runtime/ai-runtime.js.map +1 -1
  270. package/src/lib/runtime/site-context.d.ts +58 -0
  271. package/src/lib/runtime/site-context.js +127 -0
  272. package/src/lib/runtime/site-context.js.map +1 -0
  273. package/src/lib/server/ai-admin-conversations.d.ts +22 -0
  274. package/src/lib/server/ai-admin-conversations.js +197 -0
  275. package/src/lib/server/ai-admin-conversations.js.map +1 -0
  276. package/src/lib/server/ai-media-image.d.ts +5 -5
  277. package/src/lib/server/ai-media-image.js +25 -11
  278. package/src/lib/server/ai-media-image.js.map +1 -1
  279. package/src/lib/server/ai-media-raster-prompt.d.ts +34 -0
  280. package/src/lib/server/ai-media-raster-prompt.js +53 -0
  281. package/src/lib/server/ai-media-raster-prompt.js.map +1 -0
  282. package/src/lib/server/assist-chat.d.ts +11 -0
  283. package/src/lib/server/assist-chat.js +57 -18
  284. package/src/lib/server/assist-chat.js.map +1 -1
  285. package/src/lib/server/assist-edit-applied.js +16 -3
  286. package/src/lib/server/assist-edit-applied.js.map +1 -1
  287. package/src/lib/server/assist-view-context.d.ts +19 -1
  288. package/src/lib/server/assist-view-context.js +38 -1
  289. package/src/lib/server/assist-view-context.js.map +1 -1
  290. package/src/lib/server.js +10 -0
  291. package/src/lib/server.js.map +1 -1
  292. package/src/lib/subprocessors.js +17 -1
  293. package/src/lib/subprocessors.js.map +1 -1
  294. package/src/lib/tools/ai-blog-post-tool.d.ts +60 -0
  295. package/src/lib/tools/ai-blog-post-tool.js +175 -0
  296. package/src/lib/tools/ai-blog-post-tool.js.map +1 -0
  297. package/src/lib/tools/ai-workflow-tool.d.ts +6 -2
  298. package/src/lib/tools/ai-workflow-tool.js +16 -14
  299. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  300. package/src/lib/usage/assist-usage.d.ts +3 -0
  301. package/src/lib/usage/assist-usage.js +4 -2
  302. package/src/lib/usage/assist-usage.js.map +1 -1
  303. package/src/lib/usage/staff-org-ai-conversations.d.ts +103 -0
  304. package/src/lib/usage/staff-org-ai-conversations.js +152 -0
  305. package/src/lib/usage/staff-org-ai-conversations.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-compiler.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { REUSABLE_INSTANCE_COMPONENT_ID } from '@aglyn/aglyn/app-utils/reusable-component-keys'\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport {\n AI_ICON_COMPONENT_ID,\n aiIconOfWord,\n AI_ICON_LIBRARY,\n type AiIconLibraryEntry,\n} from '../runtime/ai-icon-library'\nimport { AI_INSTANCE_REF_PROP } from '../runtime/ai-node-tree'\nimport { aiPageScrollInteraction } from '../runtime/ai-page-links'\nimport {\n aiLayoutFitText,\n aiLayoutQuoteGap,\n aiLayoutWords,\n type AiLayoutTextPlace,\n} from './ai-layout-copy'\nimport {\n AI_LAYOUT_GROUP_KINDS,\n AI_LAYOUT_MAX_ITEMS,\n type AiLayoutBand,\n type AiLayoutBlock,\n type AiLayoutItem,\n type AiLayoutSection,\n type AiLayoutSettlement,\n} from './ai-layout-language'\nimport {\n aiLayoutResolveLink,\n type AiLayoutDestination,\n type AiLayoutLinkScope,\n type AiLayoutTargets,\n} from './ai-layout-links'\nimport {\n AI_LAYOUT_FRAMES,\n AiLayoutTreeBuilder,\n type AiLayoutRawTree,\n} from './ai-layout-tree'\n\n/**\n * The layout language compiler (AGL-3660): a page designed in the language\n * (`ai-layout-language.ts`) becomes the element tree the page stores — built\n * from the palette's elements and the theme's tokens only, so the doctrine's\n * building rules hold by construction rather than by a re-ask.\n *\n * What the compiler decides, so no model has to:\n *\n * - STRUCTURE. A section is a semantic `section` band around a Container at\n * a stock width, its content a Stack on the spacing scale; a row of\n * columns is a Grid container whose items are sized `xs:12 md:N` from the\n * relative widths, full width on a phone; a group of cards is a Grid of\n * sized items, or a Stack where it would be one column.\n * - THE OUTLINE. The first section's first heading is the page's one h1 (the\n * plan's title stands in where it gave none); every other section opens at\n * h2; a card's title is one level under its section's heading.\n * - TOKENS. Colors are palette roles, never values: a `brand` band is\n * `primary.main` with its contrast text, a `dark` band pins the site's dark\n * scheme, a `soft` band is the paper surface. So a band reads in the\n * visitor's light or dark mode alike.\n * - LINKS. A button goes to a real page id, a section of this page through\n * the platform's Scroll to element interaction, or an address the brief\n * gave (`ai-layout-links.ts`); one with nowhere to go is left out.\n * - THE PLAN. A form or a component the plan places in a section is placed\n * there, by its id, whether or not the answer remembered it.\n * - RULE 1. Where the workspace keeps reusable components, a section's\n * repeated items are instances of the component its plan places; with\n * none to place they are drawn in their compact form, a title over its\n * text, which is smaller than a block worth a component. A workspace that\n * keeps none (Free) draws its repeats in full.\n * - RULES 8, 9, 14, 16. Seven items a group at most; every picture carries\n * its description as alt text; copy fitted to its place at a clean\n * boundary, with any phone number or email the brief did not give written\n * as a gap; no wrapper around a lone wrapper, no empty element, and no\n * multi-key inline style repeated across a page.\n */\n\nexport interface AiLayoutPagePlan {\n /** The page's title in its plan: the h1 where the first section names none. */\n title: string\n sections: ReadonlyArray<{\n name: string\n uses: readonly string[]\n items: number\n }>\n}\n\nexport interface AiLayoutCompileOptions {\n /**\n * Whether the workspace keeps reusable components (AGL-3030). Where it does,\n * rule 1 holds: repeated items are instances of a component the plan\n * places, or drawn in their compact form.\n */\n reusableComponents: boolean\n /**\n * The ids the page stores its sections under, in plan order\n * (`aiPageSectionNodeId`): each section root is written under its own, and\n * a link to a section scrolls to it. Absent, `section-<n>`.\n */\n sectionIds?: readonly string[]\n}\n\n/** A section root's id where the caller gives none. */\nfunction sectionIdOf(index: number): string {\n return `section-${index + 1}`\n}\n\nexport interface AiLayoutCompiledPage {\n tree: AiLayoutRawTree\n /** Each plan section's root, by its compiled id, in plan order. */\n sectionRoots: string[]\n /** A button's compiled id → the plan section a click scrolls to. */\n scrollTo: Record<string, number>\n settled: AiLayoutSettlement[]\n /**\n * Each plan section's repeated items — cards, steps, figures, component\n * instances, list lines and questions — by the id of the element that\n * draws each (AGL-3660), so a check can count what a visitor sees after\n * anything later takes words out.\n */\n itemIds: string[][]\n}\n\n/** The most pictures a page carries; each beyond it is one more empty slot to fill. */\nexport const AI_LAYOUT_MAX_IMAGES = 3\n\n/** The most `brand` or `dark` bands a page shows; more and none stands out. */\nexport const AI_LAYOUT_MAX_STRONG_BANDS = 2\n\nconst SECTION_PADDING = { xs: 8, md: 12 } as const\nconst HERO_PADDING = { xs: 10, md: 14 } as const\n\n/** Everything one page's compile shares. */\nexport interface PageScope {\n tree: AiLayoutTreeBuilder\n plan: AiLayoutPagePlan\n targets: AiLayoutTargets\n options: AiLayoutCompileOptions\n settled: AiLayoutSettlement[]\n scrollTo: Record<string, number>\n images: number\n strong: Record<'brand' | 'dark', number>\n /** The section of this page that places the site's form, if one does. */\n formSection: number | null\n /** The icon a picture shows until the owner places one, when its block names none. */\n pageIcon: AiIconLibraryEntry\n /** The forms this page already places, each once. */\n formsPlaced: Set<string>\n /** Each section's repeated items, by the id of the element that draws each (AGL-3660). */\n itemIds: string[][]\n}\n\n/** Everything one section's compile shares. */\nexport interface SectionScope {\n page: PageScope\n index: number\n at: string\n band: AiLayoutBand\n centered: boolean\n /** The level of the section's own heading: 1 on the first section, 2 after. */\n level: number\n /**\n * A section of the site's frame — its footer — whose headings are labels:\n * a layout carries no heading outline of its own, since every page brings\n * its own (rule 11).\n */\n frame?: boolean\n /** Whether the section's own heading has been written. */\n headed: boolean\n link: AiLayoutLinkScope\n /** Like items the section may still show (rule 8), across its groups. */\n itemsLeft: number\n}\n\nconst formIdsOf = (targets: AiLayoutTargets): Set<string> =>\n new Set(targets.forms.map((form) => form.id))\nconst componentOf = (targets: AiLayoutTargets, id: string | undefined) =>\n id\n ? (targets.components.find((component) => component.id === id) ?? null)\n : null\n\n/**\n * The section of this page that places a form: one whose plan places one, or\n * whose design places one by its id.\n */\nfunction formSectionOf(\n sections: readonly AiLayoutSection[],\n plan: AiLayoutPagePlan,\n targets: AiLayoutTargets,\n): number | null {\n const forms = formIdsOf(targets)\n const planned = plan.sections.findIndex((section) =>\n section.uses.some((ref) => forms.has(ref)),\n )\n if (planned !== -1) return planned\n const designed = sections.findIndex((section) =>\n section.blocks.some(\n (block) => block.kind === 'form' && (!block.to || forms.has(block.to)),\n ),\n )\n return designed === -1 ? null : designed\n}\n\n/** Compiles a page designed in the layout language into the tree it stores. */\nexport function aiCompileLayoutPage(\n sections: readonly AiLayoutSection[],\n plan: AiLayoutPagePlan,\n targets: AiLayoutTargets,\n options: AiLayoutCompileOptions,\n): AiLayoutCompiledPage {\n const tree = new AiLayoutTreeBuilder()\n const page: PageScope = {\n tree,\n plan,\n targets,\n options,\n settled: [],\n scrollTo: {},\n images: 0,\n strong: { brand: 0, dark: 0 },\n formSection: formSectionOf(sections, plan, targets),\n pageIcon: pageIconOf(sections),\n formsPlaced: new Set(),\n itemIds: plan.sections.map(() => []),\n }\n const roots = plan.sections.map((_, index) => {\n const section = sections[index] ?? { blocks: [] }\n return compileSection(page, section, index)\n })\n const rootId = tree.add(\n 'div',\n null,\n null,\n roots,\n 'page',\n CANVAS_ROOT_ELEMENT_ID,\n )\n return {\n tree: { rootId, nodes: tree.nodes },\n sectionRoots: roots,\n scrollTo: page.scrollTo,\n settled: page.settled,\n itemIds: page.itemIds,\n }\n}\n\n/** The first icon the design names anywhere, else a sparkle: what an empty picture shows. */\nfunction pageIconOf(sections: readonly AiLayoutSection[]): AiIconLibraryEntry {\n for (const section of sections) {\n for (const block of section.blocks) {\n const own = aiIconOfWord(block.icon)\n if (own) return own\n for (const item of block.items ?? []) {\n const icon = aiIconOfWord(item.icon)\n if (icon) return icon\n }\n }\n }\n return AI_ICON_LIBRARY.sparkle\n}\n\n// ── A section ─────────────────────────────────────────────────────────────\n\nfunction compileSection(\n page: PageScope,\n raw: AiLayoutSection,\n index: number,\n): string {\n const at = `sections[${index}]`\n const band = settleBand(page, raw.band ?? 'plain', at)\n const scope: SectionScope = {\n page,\n index,\n at,\n band,\n centered: raw.align === 'center',\n level: index === 0 ? 1 : 2,\n headed: false,\n itemsLeft: AI_LAYOUT_MAX_ITEMS,\n link: {\n sections: page.plan.sections.map((section) => section.name),\n from: index,\n formSection: page.formSection,\n },\n }\n // A quote is a gap the owner fills, and a published page shows no gap (AGL-3660).\n const blocks = placePlanned(scope, raw).filter((block) => {\n if (block.kind !== 'quotes') return true\n page.settled.push({ at, what: 'a quotes group left out: a published page shows no customer words the brief did not give' })\n return false\n })\n const cols = raw.cols && raw.cols.length >= 2 ? raw.cols : null\n // Above the row, the row's columns, and below it.\n const head: AiLayoutBlock[] = []\n const tail: AiLayoutBlock[] = []\n const columns: AiLayoutBlock[][] = cols ? cols.map(() => []) : []\n let placed = false\n for (const block of blocks) {\n if (cols && block.col !== undefined) {\n columns[Math.min(block.col, cols.length - 1)].push(block)\n placed = true\n } else if (placed) {\n tail.push(block)\n } else {\n head.push(block)\n }\n }\n let filled = columns\n .map((column, position) => ({ column, weight: cols?.[position] ?? 1 }))\n .filter((entry) => entry.column.length)\n // A row whose columns each place the same component, one instance a\n // column or more, is that component's group of cards: the compiler lays\n // its instances out once, rather than one like Grid a column (rule 1).\n // Row by row, as the columns showed them: the first of each column, then the second.\n const deepest = Math.max(0, ...filled.map((entry) => entry.column.length))\n const placedHere = Array.from({ length: deepest }, (_, row) =>\n filled.flatMap((entry) => (entry.column[row] ? [entry.column[row]] : [])),\n ).flat()\n const repeated = placedHere[0]?.kind === 'component' ? componentOf(page.targets, placedHere[0].to) : null\n if (\n filled.length >= 2 &&\n repeated &&\n placedHere.every((block) => block.kind === 'component' && block.to === repeated.id)\n ) {\n head.push({ kind: 'cards', to: repeated.id, items: placedHere.map((block) => componentItem(block, repeated.props)) })\n page.settled.push({ at, what: `${placedHere.length} ${repeated.name} instances in ${filled.length} columns drawn as one group` })\n filled = []\n }\n // A row whose columns each hold only one kind of group — a card a column —\n // is that group, laid out by the compiler rather than column by column.\n const groups = filled.flatMap((entry) => entry.column)\n if (\n filled.length >= 2 &&\n groups.every(\n (block) => isItemGroup(block) && block.kind === groups[0].kind && block.to === groups[0].to,\n )\n ) {\n head.push({ ...groups[0], col: undefined, items: groups.flatMap((block) => block.items ?? []) })\n page.settled.push({ at, what: `a ${groups[0].kind} group split over ${filled.length} columns drawn as one` })\n filled = []\n }\n // A row whose columns all say the same kind of thing, three or more across,\n // is a group of cards: one design, the words the columns gave.\n if (filled.length >= 3 && sameShape(filled.map((entry) => entry.column))) {\n head.push(columnsAsCards(filled.map((entry) => entry.column)))\n page.settled.push({\n at,\n what: `${filled.length} like columns drawn as cards`,\n })\n filled = []\n }\n if (filled.length === 1) {\n // One column with anything in it is no row.\n head.push(...filled[0].column)\n filled = []\n }\n // The section's heading leads its outline: a heading with no words is no\n // heading, the first section always carries the page's one h1, and a\n // heading written after a group whose titles sit under it moves above it.\n const inOrder = () =>\n head.concat(\n filled.flatMap((entry) => entry.column),\n tail,\n )\n const speaks = (block: AiLayoutBlock) =>\n block.kind === 'heading' &&\n !!aiLayoutWords(block.text, 'heading', page.targets.facts)\n for (const list of [head, tail, ...filled.map((entry) => entry.column)]) {\n for (let at = list.length - 1; at >= 0; at -= 1)\n if (list[at].kind === 'heading' && !speaks(list[at])) list.splice(at, 1)\n }\n if (index === 0 && !inOrder().some(speaks)) {\n head.unshift({ kind: 'heading', text: page.plan.title })\n page.settled.push({\n at,\n what: \"no heading; the page's title written as its h1\",\n })\n }\n const order = inOrder()\n const first = order.findIndex(speaks)\n if (\n first > 0 &&\n order\n .slice(0, first)\n .some(\n (block) =>\n block.kind === 'cards' ||\n block.kind === 'steps' ||\n block.kind === 'component',\n )\n ) {\n const lead = order[first]\n for (const list of [head, tail, ...filled.map((entry) => entry.column)]) {\n const at = list.indexOf(lead)\n if (at !== -1) list.splice(at, 1)\n }\n head.unshift({ ...lead, col: undefined })\n page.settled.push({\n at,\n what: 'the heading moved above the group it heads',\n })\n }\n filled = filled.filter((entry) => entry.column.length)\n if (filled.length === 1) {\n head.push(...filled[0].column)\n filled = []\n }\n const wide =\n filled.length > 0 || [...head, ...tail].some((block) => isWideGroup(block))\n const parts: string[] = []\n const headId = compileFlow(scope, head, 'full')\n if (headId) parts.push(centered(scope, headId, wide))\n if (filled.length) parts.push(compileRow(scope, filled))\n const tailId = compileFlow(scope, tail, 'full')\n if (tailId) parts.push(centered(scope, tailId, wide))\n // A frame whose content came to nothing is taken out, leaves first.\n for (let at = parts.length - 1; at >= 0; at -= 1) {\n page.tree.prune(parts[at])\n const part = page.tree.nodes[parts[at]]\n if (AI_LAYOUT_FRAMES.has(part.componentId) && !part.nodes?.length) {\n delete page.tree.nodes[parts[at]]\n parts.splice(at, 1)\n }\n }\n if (!parts.length) {\n // Nothing the design gave this section could be shown: it keeps its\n // place on the page under the name its plan gives it.\n const fallback = compileFlow(\n scope,\n [\n {\n kind: 'heading',\n text: page.plan.sections[index]?.name || page.plan.title,\n },\n ],\n 'full',\n )\n if (fallback) parts.push(fallback)\n page.settled.push({\n at,\n what: 'nothing to show; the section named by its plan',\n })\n }\n const tree = page.tree\n const content =\n parts.length === 1\n ? parts[0]\n : // Gap, not margins: a stack's margin spacing resets its children's\n // margins, which un-centers a reading-width head (AGL-3660).\n tree.add('muiStack', { spacing: '6', useFlexGap: true }, null, parts, 'content')\n const container = tree.add(\n 'muiContainer',\n { maxWidth: wide ? 'lg' : 'md' },\n { py: index === 0 ? { ...HERO_PADDING } : { ...SECTION_PADDING } },\n [content],\n 'container',\n )\n const name = page.plan.sections[index]?.name?.trim() || `Section ${index + 1}`\n return tree.add(\n 'section',\n {\n element: 'section',\n ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`,\n ...(band === 'dark' ? { colorScheme: 'dark' } : {}),\n },\n bandSx(band),\n [container],\n 'section',\n page.options.sectionIds?.[index] ?? sectionIdOf(index),\n )\n}\n\n/**\n * A component block's prop values as a card item: its title-like prop as the\n * title and its text-like prop as the text, which `instanceValues` writes\n * back into the same props.\n */\nfunction componentItem(block: AiLayoutBlock, props: Record<string, string>): AiLayoutItem {\n // An item that names no prop is the card itself, written as a cards item.\n const own = (block.items ?? []).find((item) => !(item.title in props) && (item.title.trim() || item.text.trim()))\n if (own && !(block.items ?? []).some((item) => item.title in props)) return { title: own.title, text: own.text }\n const value = (pattern: RegExp) =>\n (block.items ?? []).find((item) => item.title in props && pattern.test(item.title) && item.text.trim())?.text ?? ''\n const title = value(/title|name|heading|label|question|figure|value/i) || block.text || ''\n const text = value(/text|description|body|summary|copy|answer|detail|caption/i)\n return { title, text }\n}\n\n/** A band the page has room for: past two brand or two dark bands, a soft one instead. */\nfunction settleBand(\n page: PageScope,\n band: AiLayoutBand,\n at: string,\n): AiLayoutBand {\n if (band !== 'brand' && band !== 'dark') return band\n if (page.strong[band] >= AI_LAYOUT_MAX_STRONG_BANDS) {\n page.settled.push({\n at: `${at}.band`,\n what: `a third ${band} band drawn soft`,\n })\n return 'soft'\n }\n page.strong[band] += 1\n return band\n}\n\n/** A band's own colors, as palette roles: the dark band pins the scheme instead. */\nexport function bandSx(band: AiLayoutBand): Record<string, unknown> | null {\n if (band === 'soft') return { bgcolor: 'background.paper' }\n if (band === 'brand')\n return { bgcolor: 'primary.main', color: 'primary.contrastText' }\n return null\n}\n\n/** A group whose items sit side by side. */\nfunction isItemGroup(block: AiLayoutBlock): boolean {\n return block.kind === 'cards' || block.kind === 'steps' || block.kind === 'stats' || block.kind === 'quotes'\n}\n\n/** Whether a block spans more than a reading column: a row of several items. */\nfunction isWideGroup(block: AiLayoutBlock): boolean {\n return (\n (block.kind === 'cards' ||\n block.kind === 'steps' ||\n block.kind === 'stats' ||\n block.kind === 'quotes') &&\n (block.items?.length ?? 0) >= 2\n )\n}\n\n/** A full-width flow centered on a wide section is held to a reading width. */\nfunction centered(scope: SectionScope, flowId: string, wide: boolean): string {\n const flow = scope.page.tree.nodes[flowId]\n const holdsGroup = (flow.nodes ?? []).some(\n (id) => scope.page.tree.nodes[id]?.componentId === 'muiGrid',\n )\n if (!wide || !scope.centered || holdsGroup) return flowId\n return scope.page.tree.add(\n 'muiContainer',\n { maxWidth: 'md', disableGutters: true },\n null,\n [flowId],\n 'measure',\n )\n}\n\n/**\n * The section's blocks with what its plan places in it: a form or a\n * component the plan line names and the design left out is added where the\n * section ends, and a `form` or `component` block naming nothing takes the\n * one the plan line names.\n */\nfunction placePlanned(\n scope: SectionScope,\n raw: AiLayoutSection,\n): AiLayoutBlock[] {\n const { page, index, at } = scope\n const forms = formIdsOf(page.targets)\n const uses = page.plan.sections[index]?.uses ?? []\n const plannedForms = uses.filter((ref) => forms.has(ref))\n const plannedComponents = uses.filter((ref) => componentOf(page.targets, ref))\n const blocks = raw.blocks.map((block) => ({\n ...block,\n ...(block.items ? { items: [...block.items] } : {}),\n }))\n const lastCol =\n raw.cols && raw.cols.length >= 2 ? raw.cols.length - 1 : undefined\n for (const block of blocks) {\n if (block.kind === 'form' && !(block.to && forms.has(block.to))) {\n const only =\n page.targets.forms.length === 1 ? page.targets.forms[0].id : undefined\n block.to = plannedForms[0] ?? only\n }\n if (\n (block.kind === 'component' || block.kind === 'cards') &&\n block.to &&\n !componentOf(page.targets, block.to)\n ) {\n if (block.kind === 'component') block.to = plannedComponents[0]\n else delete block.to\n }\n if (block.kind === 'component' && !block.to) block.to = plannedComponents[0]\n // A group whose every item names the same component is that component's\n // placements (AGL-3660): the design put the id on its items, not the block.\n if (AI_LAYOUT_GROUP_KINDS.has(block.kind) && !block.to && block.items?.length) {\n const named = block.items[0]?.to\n if (named && componentOf(page.targets, named) && block.items.every((item) => item.to === named)) {\n block.to = named\n block.items = block.items.map(({ to: _to, ...item }) => item)\n }\n }\n }\n for (const form of plannedForms) {\n if (!blocks.some((block) => block.kind === 'form' && block.to === form)) {\n blocks.push({\n kind: 'form',\n to: form,\n ...(lastCol !== undefined ? { col: lastCol } : {}),\n })\n page.settled.push({ at, what: `the planned form ${form} placed` })\n }\n }\n for (const component of plannedComponents) {\n if (\n blocks.some(\n (block) =>\n (block.kind === 'component' || block.kind === 'cards') &&\n block.to === component,\n )\n )\n continue\n // A group the design drew where the plan places a component is that component's placements.\n const group = blocks.find(\n (block) =>\n AI_LAYOUT_GROUP_KINDS.has(block.kind) &&\n block.kind !== 'faq' &&\n block.kind !== 'list' &&\n !block.to,\n )\n if (group) {\n // Every group of that kind the design split over the row's columns, so\n // each item of the row is drawn alike (AGL-3660), never the first alone.\n for (const like of blocks) {\n if (like.kind === group.kind && !like.to) like.to = component\n }\n continue\n }\n blocks.push({\n kind: 'component',\n to: component,\n ...(lastCol !== undefined ? { col: lastCol } : {}),\n })\n page.settled.push({ at, what: `the planned component ${component} placed` })\n }\n return blocks.filter((block) => {\n if ((block.kind === 'form' || block.kind === 'component') && !block.to) {\n page.settled.push({\n at,\n what: `a ${block.kind} with nothing to place; left out`,\n })\n return false\n }\n // A form is placed once a page: a second copy of the same form asks a\n // visitor the same thing twice.\n if (block.kind === 'form' && block.to) {\n if (page.formsPlaced.has(block.to)) {\n page.settled.push({ at, what: `the form ${block.to} again; left out` })\n return false\n }\n page.formsPlaced.add(block.to)\n }\n return true\n })\n}\n\n/** The block kinds a column holds, as a column's shape is compared. */\nfunction shapeOf(column: readonly AiLayoutBlock[]): string {\n return column.map((block) => block.kind).join(',')\n}\n\nfunction sameShape(columns: readonly AiLayoutBlock[][]): boolean {\n const first = shapeOf(columns[0])\n return (\n columns.every((column) => shapeOf(column) === first) &&\n columns[0].some((block) => block.kind === 'heading') &&\n columns[0].every((block) =>\n ['heading', 'text', 'lede', 'eyebrow', 'image', 'note'].includes(\n block.kind,\n ),\n )\n )\n}\n\n/** Like columns as one group of cards: each column's heading its title, its words its text. */\nfunction columnsAsCards(columns: readonly AiLayoutBlock[][]): AiLayoutBlock {\n return {\n kind: 'cards',\n items: columns.map((column) => {\n const title = column.find((block) => block.kind === 'heading')?.text ?? ''\n const words = column\n .filter(\n (block) =>\n block.kind === 'text' ||\n block.kind === 'lede' ||\n block.kind === 'note',\n )\n .map((block) => block.text ?? '')\n .join(' ')\n const icon = column.find((block) => block.icon)?.icon\n return { title, text: words, ...(icon ? { icon } : {}) }\n }),\n }\n}\n\n// ── A row of columns ──────────────────────────────────────────────────────\n\n/** Spans out of twelve for relative widths: each at least three, summing to twelve. */\nexport function aiLayoutSpans(weights: readonly number[]): number[] {\n const total = weights.reduce((sum, weight) => sum + weight, 0)\n const spans = weights.map((weight) =>\n Math.max(3, Math.round((weight / total) * 12)),\n )\n let over = spans.reduce((sum, span) => sum + span, 0) - 12\n while (over !== 0) {\n // Take from (or give to) the widest column that can spare it.\n const order = spans\n .map((span, position) => ({ span, position }))\n .sort((a, b) => (over > 0 ? b.span - a.span : a.span - b.span))\n const pick = order.find((entry) => (over > 0 ? entry.span > 3 : true))\n if (!pick) break\n spans[pick.position] += over > 0 ? -1 : 1\n over += over > 0 ? -1 : 1\n }\n return spans\n}\n\nexport function compileRow(\n scope: SectionScope,\n columns: Array<{ column: AiLayoutBlock[]; weight: number }>,\n): string {\n const tree = scope.page.tree\n const spans = aiLayoutSpans(columns.map((entry) => entry.weight))\n const items = columns.map((entry, position) => {\n const span = spans[position]\n const flow = compileFlow(\n scope,\n entry.column,\n span >= 8 ? 'full' : span >= 5 ? 'half' : 'narrow',\n )\n const size =\n columns.length >= 4 ? `xs:12 sm:6 md:${span}` : `xs:12 md:${span}`\n return tree.add('muiGrid', { size }, null, [flow], 'column')\n })\n return tree.add(\n 'muiGrid',\n { container: true, spacing: columns.length >= 3 ? '4' : '6' },\n { alignItems: 'center' },\n items,\n 'row',\n )\n}\n\n// ── A flow of blocks ─────────────────────────────────────────────────────\n\nexport type Room = 'full' | 'half' | 'narrow'\n\n/** A column of blocks, top to bottom, with buttons side by side; `null` when nothing in it compiles. */\nexport function compileFlow(\n scope: SectionScope,\n blocks: readonly AiLayoutBlock[],\n room: Room,\n): string | null {\n const tree = scope.page.tree\n const children: string[] = []\n let buttons: string[] = []\n const flushButtons = () => {\n if (!buttons.length) return\n children.push(\n buttons.length === 1\n ? buttons[0]\n : tree.add(\n 'muiStack',\n {\n direction: 'row',\n spacing: '2',\n useFlexGap: true,\n flexWrap: 'wrap',\n ...(scope.centered ? { justifyContent: 'center' } : {}),\n },\n null,\n buttons,\n 'actions',\n ),\n )\n buttons = []\n }\n for (const block of blocks) {\n if (block.kind === 'button') {\n const id = compileButton(scope, block)\n if (id) buttons.push(id)\n continue\n }\n flushButtons()\n const id = compileBlock(scope, block, room)\n if (id) children.push(id)\n }\n flushButtons()\n if (!children.length) return null\n // One block needs no flow around it.\n if (children.length === 1) return children[0]\n const align = scope.centered && room === 'full'\n // A flow whose words open with a label, a heading and a lede reads as one\n // block at a tighter spacing than the groups under it.\n return tree.add(\n 'muiStack',\n {\n spacing: hasGroup(tree, children) ? '4' : '2.5',\n ...(align ? { alignItems: 'center' } : {}),\n },\n null,\n children,\n 'flow',\n )\n}\n\nfunction hasGroup(tree: AiLayoutTreeBuilder, ids: readonly string[]): boolean {\n return ids.some((id) =>\n ['muiGrid', 'muiList'].includes(tree.nodes[id]?.componentId ?? ''),\n )\n}\n\nfunction compileBlock(\n scope: SectionScope,\n block: AiLayoutBlock,\n room: Room,\n): string | null {\n switch (block.kind) {\n case 'eyebrow':\n return words(\n scope,\n block,\n 'eyebrow',\n 'overline',\n { component: 'p' },\n accent(scope),\n )\n case 'heading':\n return heading(scope, block)\n case 'lede':\n return words(scope, block, 'lede', 'lede', {}, muted(scope))\n case 'text':\n return words(scope, block, 'text', 'body1', {}, muted(scope))\n case 'note':\n return words(scope, block, 'note', 'body2', {}, muted(scope))\n case 'image':\n return image(scope, block, room)\n case 'form':\n return form(scope, block)\n case 'component':\n return component(scope, block)\n case 'list':\n return list(scope, block)\n case 'faq':\n return faq(scope, block)\n case 'cards':\n case 'steps':\n case 'stats':\n case 'quotes':\n return group(scope, block, room)\n default:\n return null\n }\n}\n\n/** Secondary words' color: muted text, or the band's own on a brand band. */\nfunction muted(scope: SectionScope): Record<string, unknown> | null {\n return scope.band === 'brand' ? null : { color: 'text.secondary' }\n}\n\n/** An accent's color: the brand's, or the band's own on a brand band. */\nfunction accent(scope: SectionScope): Record<string, unknown> | null {\n return scope.band === 'brand' ? null : { color: 'primary.main' }\n}\n\nfunction align(scope: SectionScope): Record<string, unknown> {\n return scope.centered ? { align: 'center' } : {}\n}\n\nfunction words(\n scope: SectionScope,\n block: AiLayoutBlock,\n place: AiLayoutTextPlace,\n variant: string,\n props: Record<string, unknown>,\n sx: Record<string, unknown> | null,\n): string | null {\n const text = aiLayoutWords(block.text, place, scope.page.targets.facts)\n if (!text) return null\n return scope.page.tree.add(\n 'muiTypography',\n { children: text, variant, ...props, ...align(scope) },\n sx,\n null,\n place,\n )\n}\n\n/** A heading at its place in the outline: the section's own, or one under it. */\nfunction heading(scope: SectionScope, block: AiLayoutBlock): string | null {\n if (scope.frame) {\n const label = aiLayoutWords(\n block.text,\n 'itemTitle',\n scope.page.targets.facts,\n )\n return label\n ? scope.page.tree.add(\n 'muiTypography',\n {\n children: label,\n variant: 'subtitle1',\n component: 'p',\n ...align(scope),\n },\n null,\n null,\n 'label',\n )\n : null\n }\n const own = !scope.headed\n const level = own ? scope.level : scope.level + 1\n const place: AiLayoutTextPlace =\n level === 1 ? 'title' : own ? 'heading' : 'itemTitle'\n const text = aiLayoutWords(block.text, place, scope.page.targets.facts)\n if (!text) return null\n scope.headed = scope.headed || own\n const variant =\n level === 1\n ? block.style === 'large'\n ? 'displayXl'\n : 'h1'\n : own\n ? 'h2'\n : 'h4'\n return scope.page.tree.add(\n 'muiTypography',\n { children: text, variant, component: `h${level}`, ...align(scope) },\n null,\n null,\n 'heading',\n )\n}\n\n/** The level an item's title takes: one under the section's heading, or h2 in a section with none yet. */\nfunction itemLevel(scope: SectionScope): number {\n return scope.headed ? scope.level + 1 : Math.max(2, scope.level)\n}\n\n/** The element an item's title renders as: a heading on a page, a label in the frame. */\nfunction itemElement(scope: SectionScope): string {\n return scope.frame ? 'p' : `h${itemLevel(scope)}`\n}\n\nfunction compileButton(\n scope: SectionScope,\n block: AiLayoutBlock,\n): string | null {\n const label = aiLayoutFitText(block.text, 'label')\n if (!label) return null\n const destination = aiLayoutResolveLink(\n block.to,\n label,\n scope.link,\n scope.page.targets,\n )\n if (!destination) {\n scope.page.settled.push({\n at: scope.at,\n what: `the button \"${label}\" has nowhere to go; left out`,\n })\n return null\n }\n const style = block.style ?? 'primary'\n const onBrand = scope.band === 'brand'\n const look =\n style === 'quiet'\n ? { variant: 'text', color: onBrand ? 'inherit' : 'primary' }\n : style === 'secondary'\n ? { variant: 'outlined', color: onBrand ? 'inherit' : 'primary' }\n : { variant: 'contained', color: onBrand ? 'secondary' : 'primary' }\n const id = scope.page.tree.add(\n 'muiButton',\n {\n children: label,\n ...look,\n size: scope.index === 0 || block.style === 'large' ? 'large' : 'medium',\n ...destinationProps(destination),\n },\n // Sized to its words, never stretched across the column a Stack would\n // stretch it over (AGL-3660), and aligned with its section.\n { alignSelf: scope.centered ? 'center' : 'flex-start' },\n null,\n 'button',\n )\n linkTo(scope, id, destination)\n return id\n}\n\n/**\n * A link to a section of this page carries the platform's Scroll to element\n * interaction to that section's root (AGL-3097), by the id the page stores it\n * under.\n */\nfunction linkTo(\n scope: SectionScope,\n id: string,\n destination: AiLayoutDestination,\n): void {\n if (destination.kind !== 'section') return\n const { page } = scope\n page.scrollTo[id] = destination.index\n const target =\n page.options.sectionIds?.[destination.index] ??\n sectionIdOf(destination.index)\n const name =\n page.plan.sections[destination.index]?.name ??\n `section ${destination.index + 1}`\n page.tree.nodes[id].interactions = [aiPageScrollInteraction(target, name)]\n}\n\nexport function destinationProps(\n destination: AiLayoutDestination,\n): Record<string, unknown> {\n if (destination.kind === 'page') return { screenId: destination.screenId }\n if (destination.kind === 'href')\n return { href: destination.href, target: '_blank' }\n return {}\n}\n\n/**\n * A picture slot: a soft frame at a stock shape showing an icon until the\n * owner places the picture, which then fills it. Its description is its alt\n * text (rule 9), and no source is set here: the compiler stays pure, and\n * `ai-layout-pictures.ts` fills the slot with a photo the site serves itself\n * once the page is checked.\n */\nfunction image(\n scope: SectionScope,\n block: AiLayoutBlock,\n room: Room,\n): string | null {\n const { page } = scope\n const alt = aiLayoutFitText(block.text, 'alt')\n if (!alt) return null\n if (page.images >= maxImages(page)) {\n page.settled.push({\n at: scope.at,\n what: `a picture past the page's ${AI_LAYOUT_MAX_IMAGES}; left out`,\n })\n return null\n }\n page.images += 1\n const icon = aiIconOfWord(block.icon) ?? page.pageIcon\n const tree = page.tree\n const mark = tree.add(\n AI_ICON_COMPONENT_ID,\n { iconId: icon.id, size: '64' },\n { color: 'primary.main' },\n null,\n 'imageIcon',\n )\n const picture = tree.add(\n 'image',\n { alt, objectFit: 'cover' },\n { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' },\n null,\n 'image',\n )\n return tree.add(\n 'muiBox',\n null,\n {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n // In multiples of the theme's corner radius, so a sharp site's frames are sharp.\n borderRadius: 2,\n bgcolor: 'action.hover',\n // The frame's shape follows its room, so no two slots of a page share one style.\n aspectRatio:\n room === 'full'\n ? page.images === 1\n ? '16 / 9'\n : '21 / 9'\n : room === 'half'\n ? '4 / 3'\n : page.images === 1\n ? '1 / 1'\n : '3 / 4',\n },\n [mark, picture],\n 'frame',\n )\n}\n\n/** A saved form, framed as a card so it reads as the section's one task. */\nfunction form(scope: SectionScope, block: AiLayoutBlock): string | null {\n const tree = scope.page.tree\n const placed = tree.add('form', { formId: block.to }, null, null, 'form')\n const content = tree.add(\n 'muiCardContent',\n null,\n { p: { xs: 3, md: 4 } },\n [placed],\n 'formContent',\n )\n // The card style is the site theme's (AGL-3660), as a card dropped from the\n // drawer takes it; it takes the flow's width, so a centered section never\n // shrinks a form to its button.\n return tree.add('muiCard', null, { alignSelf: 'stretch' }, [content], 'formCard')\n}\n\n/** A reusable component placed by its id, its props filled from the block's items. */\nfunction component(scope: SectionScope, block: AiLayoutBlock): string | null {\n const declared = componentOf(scope.page.targets, block.to)\n if (!declared) return null\n const values: Record<string, unknown> = {}\n for (const item of block.items ?? []) {\n const name = item.title.trim()\n if (name in declared.props && item.text.trim())\n values[name] = aiLayoutWords(item.text, 'text', scope.page.targets.facts)\n }\n // An instance fills at least one prop (rule 1): the block's words, else the\n // name its section has in the plan, rather than the component's placeholder.\n if (!Object.values(values).some(Boolean)) {\n const first = textProps(declared.props)[0]\n const words =\n aiLayoutWords(block.text, 'text', scope.page.targets.facts) ||\n aiLayoutWords(\n scope.page.plan.sections[scope.index]?.name,\n 'itemTitle',\n scope.page.targets.facts,\n )\n if (first && words) values[first] = words\n }\n for (const [name, value] of Object.entries(values))\n if (!value) delete values[name]\n return scope.page.tree.add(\n REUSABLE_INSTANCE_COMPONENT_ID,\n {\n [AI_INSTANCE_REF_PROP]: declared.id,\n ...(Object.keys(values).length ? { propValues: values } : {}),\n },\n null,\n null,\n 'instance',\n )\n}\n\nfunction textProps(props: Record<string, string>): string[] {\n return Object.entries(props)\n .filter(([, type]) => type === 'text' || type === 'richText')\n .map(([name]) => name)\n}\n\n/** An item's words as the props of the component that draws it. */\nfunction instanceValues(\n props: Record<string, string>,\n item: AiLayoutItem,\n facts: string,\n): Record<string, unknown> {\n const texts = textProps(props)\n const titleProp =\n texts.find((name) =>\n /title|name|heading|label|question|figure|value/i.test(name),\n ) ?? texts[0]\n const textProp =\n texts.find(\n (name) =>\n name !== titleProp &&\n /text|description|body|summary|copy|answer|detail|caption/i.test(name),\n ) ?? texts.find((name) => name !== titleProp)\n const values: Record<string, unknown> = {}\n if (titleProp && item.title.trim())\n values[titleProp] = aiLayoutWords(item.title, 'itemTitle', facts)\n if (textProp && item.text.trim())\n values[textProp] = aiLayoutWords(item.text, 'itemText', facts)\n const first = titleProp ?? textProp\n if (!Object.values(values).some(Boolean) && first)\n values[first] = aiLayoutWords(item.title || item.text, 'itemTitle', facts)\n return values\n}\n\n// ── Groups ────────────────────────────────────────────────────────────────\n\n/** Records the elements that draw a section's repeated items, and hands them back. */\nfunction noted<T extends readonly string[]>(scope: SectionScope, ids: T): T {\n if (!scope.frame) scope.page.itemIds[scope.index]?.push(...ids)\n return ids\n}\n\n/** How many items sit side by side in a room. */\nfunction across(\n count: number,\n room: Room,\n kind: AiLayoutBlock['kind'],\n): number {\n if (room === 'narrow') return 1\n if (room === 'half') return count >= 2 && kind === 'stats' ? 2 : 1\n if (count <= 3) return count\n if (count === 4) return 4\n if (count === 7) return 4\n return 3\n}\n\nfunction itemSize(perRow: number): string {\n if (perRow === 2) return 'xs:12 sm:6'\n if (perRow === 3) return 'xs:12 md:4'\n return 'xs:12 sm:6 md:3'\n}\n\n/** Items laid out side by side as a Grid of sized items, or stacked where they sit one to a row. */\nfunction layOut(\n scope: SectionScope,\n items: readonly string[],\n perRow: number,\n spacing: string,\n role: string,\n): string {\n const tree = scope.page.tree\n if (items.length === 1) return items[0]\n if (perRow <= 1) {\n return tree.add('muiStack', { spacing }, null, items, role)\n }\n const size = itemSize(perRow)\n const cells = items.map((id) =>\n tree.add('muiGrid', { size }, null, [id], 'cell'),\n )\n return tree.add('muiGrid', { container: true, spacing }, null, cells, role)\n}\n\n/**\n * Whether repeats must be components here (rule 1): the workspace keeps\n * them. Rule 1 counts like blocks across the whole page, so where it holds\n * every group the plan places no component for is drawn compact, however\n * few its items — two sections of two cards are four like cards.\n */\nfunction rule1(scope: SectionScope): boolean {\n return scope.page.options.reusableComponents\n}\n\n/** The most pictures this page carries: two where rule 1 counts three like frames as a repeat. */\nfunction maxImages(page: PageScope): number {\n return page.options.reusableComponents ? 2 : AI_LAYOUT_MAX_IMAGES\n}\n\n/**\n * The items a group may still show in its section (rule 8): seven like items\n * a section, across all its groups, since eight are a list typed by hand.\n */\n/** Whether an item has words left once they are cleaned and fitted: an item with none is no item. */\nfunction speaks(scope: SectionScope, item: AiLayoutItem): boolean {\n const facts = scope.page.targets.facts\n return !!(\n aiLayoutWords(item.title, 'itemTitle', facts) ||\n aiLayoutWords(item.text, 'itemText', facts)\n )\n}\n\n/** A group's items with every part that has no words left once cleaned emptied, and wordless items left out. */\n/** A title that only names the kind of thing it is: \"Card\", \"Item 2\", \"Title\". */\nconst AI_LAYOUT_PLACEHOLDER_TITLE = /^(?:card|item|title|heading|placeholder|tile|box|feature|service|post|article|entry)\\s*\\d*$/i\n\nfunction cleanItems(\n scope: SectionScope,\n items: readonly AiLayoutItem[],\n): AiLayoutItem[] {\n const facts = scope.page.targets.facts\n // A title that is only the name or id of what places it — a \"Card\" item of\n // the Card component (AGL-3660) — is no words a visitor reads.\n const references = new Set(\n scope.page.targets.components.flatMap((component) => [component.name, component.id]).map((name) => name.trim().toLowerCase()),\n )\n return items\n .map((item) => ({\n ...item,\n title:\n aiLayoutWords(item.title, 'itemTitle', facts) &&\n !references.has(item.title.trim().toLowerCase()) &&\n !AI_LAYOUT_PLACEHOLDER_TITLE.test(item.title.trim())\n ? item.title\n : '',\n text: aiLayoutWords(item.text, 'itemText', facts) ? item.text : '',\n }))\n .filter((item) => speaks(scope, item))\n}\n\nfunction takeItems<T>(scope: SectionScope, items: readonly T[]): T[] {\n const kept = items.slice(0, Math.max(0, scope.itemsLeft))\n if (kept.length < items.length) {\n scope.page.settled.push({\n at: scope.at,\n what: `${items.length - kept.length} items past the section's ${AI_LAYOUT_MAX_ITEMS}; left out`,\n })\n }\n scope.itemsLeft -= kept.length\n return kept\n}\n\n/** `takeItems` on a list it shortens where it stands. */\nfunction takeItemsInPlace<T>(scope: SectionScope, items: T[]): void {\n const kept = takeItems(scope, items)\n items.length = kept.length\n}\n\nfunction group(\n scope: SectionScope,\n block: AiLayoutBlock,\n room: Room,\n): string | null {\n const items = takeItems(scope, cleanItems(scope, block.items ?? []))\n if (!items.length) return null\n const perRow = across(items.length, room, block.kind)\n const placed = componentOf(scope.page.targets, block.to)\n if (placed) return instances(scope, placed, items, perRow)\n if (rule1(scope)) return compactGroup(scope, block, items, perRow)\n switch (block.kind) {\n case 'steps':\n return layOut(\n scope,\n noted(scope, items.map((item, position) => step(scope, item, position))),\n perRow,\n '4',\n 'steps',\n )\n case 'stats':\n return layOut(\n scope,\n noted(scope, items.map((item) => stat(scope, item))),\n perRow,\n '4',\n 'stats',\n )\n case 'quotes':\n return layOut(\n scope,\n noted(scope, items.map((item) => quote(scope, item))),\n perRow,\n '3',\n 'quotes',\n )\n default:\n return layOut(\n scope,\n noted(scope, items.map((item) => card(scope, block, item))),\n perRow,\n '3',\n 'cards',\n )\n }\n}\n\nfunction instances(\n scope: SectionScope,\n placed: { id: string; props: Record<string, string> },\n items: readonly AiLayoutItem[],\n perRow: number,\n): string {\n const tree = scope.page.tree\n const ids = items.map((item) => {\n const values = instanceValues(placed.props, item, scope.page.targets.facts)\n return tree.add(\n REUSABLE_INSTANCE_COMPONENT_ID,\n {\n [AI_INSTANCE_REF_PROP]: placed.id,\n ...(Object.keys(values).length ? { propValues: values } : {}),\n },\n null,\n null,\n 'instance',\n )\n })\n return layOut(scope, noted(scope, ids), perRow, '3', 'instances')\n}\n\n/**\n * A group in its compact form, a title over its text: two elements an item,\n * under the three a block must have before rule 1 asks for a component.\n */\nfunction compactGroup(\n scope: SectionScope,\n block: AiLayoutBlock,\n items: readonly AiLayoutItem[],\n perRow: number,\n): string {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n const pairs = items.map((item, position) => {\n const title =\n block.kind === 'quotes'\n ? aiLayoutQuoteGap(item.text || item.title)\n : block.kind === 'stats'\n ? aiLayoutWords(item.title, 'stat', facts)\n : `${block.kind === 'steps' ? `${position + 1}. ` : ''}${aiLayoutWords(item.title, 'itemTitle', facts)}`\n const text =\n block.kind === 'quotes'\n ? '[Customer name]'\n : aiLayoutWords(\n item.text,\n block.kind === 'stats' ? 'statLabel' : 'itemText',\n facts,\n )\n return tree.add(\n 'muiListItemText',\n { primary: title, ...(text ? { secondary: text } : {}) },\n null,\n null,\n 'pair',\n )\n })\n return layOut(scope, noted(scope, pairs), perRow, '3', 'compact')\n}\n\n/** A card: an optional icon, its title one level under the section's heading, and its words. */\nfunction card(\n scope: SectionScope,\n block: AiLayoutBlock,\n item: AiLayoutItem,\n): string {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n const icon = aiIconOfWord(item.icon) ?? aiIconOfWord(block.icon)\n const children = [\n icon\n ? tree.add(\n AI_ICON_COMPONENT_ID,\n { iconId: icon.id, size: '32' },\n { color: 'primary.main' },\n null,\n 'icon',\n )\n : null,\n item.title.trim()\n ? tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.title, 'itemTitle', facts),\n variant: 'h5',\n component: itemElement(scope),\n },\n null,\n null,\n 'title',\n )\n : null,\n item.text.trim()\n ? tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.text, 'itemText', facts),\n variant: 'body1',\n },\n { color: 'text.secondary' },\n null,\n 'text',\n )\n : null,\n ]\n const stack = tree.add(\n 'muiStack',\n { spacing: '1.5' },\n null,\n children,\n 'cardStack',\n )\n if (block.style === 'quiet') return stack\n const content = tree.add(\n 'muiCardContent',\n null,\n { p: 3 },\n [stack],\n 'cardContent',\n )\n // Flat, outlined, raised, tinted or ruled is the site theme's card style\n // (AGL-3660), never a choice stamped on this card.\n return tree.add('muiCard', null, { height: '100%' }, [content], 'card')\n}\n\n/** A numbered step: its number in the brand color, its title and its words. */\nfunction step(\n scope: SectionScope,\n item: AiLayoutItem,\n position: number,\n): string {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n return tree.add(\n 'muiStack',\n { spacing: '1' },\n null,\n [\n tree.add(\n 'muiTypography',\n {\n children: String(position + 1).padStart(2, '0'),\n variant: 'h3',\n component: 'p',\n },\n accent(scope),\n null,\n 'number',\n ),\n item.title.trim()\n ? tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.title, 'itemTitle', facts),\n variant: 'h5',\n component: itemElement(scope),\n },\n null,\n null,\n 'title',\n )\n : null,\n item.text.trim()\n ? tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.text, 'itemText', facts),\n variant: 'body1',\n },\n muted(scope),\n null,\n 'text',\n )\n : null,\n ],\n 'step',\n )\n}\n\n/** A figure and its label. A figure the brief did not give is the model's bracketed gap. */\nfunction stat(scope: SectionScope, item: AiLayoutItem): string {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n return tree.add(\n 'muiStack',\n { spacing: '0.5', ...(scope.centered ? { alignItems: 'center' } : {}) },\n null,\n [\n tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.title, 'stat', facts) || '[figure]',\n variant: 'h2',\n component: 'p',\n ...align(scope),\n },\n accent(scope),\n null,\n 'figure',\n ),\n item.text.trim()\n ? tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.text, 'statLabel', facts),\n variant: 'body2',\n ...align(scope),\n },\n muted(scope),\n null,\n 'label',\n )\n : null,\n ],\n 'stat',\n )\n}\n\n/** A quote slot: what a customer should be quoted saying, as the gap the owner fills. */\nfunction quote(scope: SectionScope, item: AiLayoutItem): string {\n const tree = scope.page.tree\n const words = aiLayoutQuoteGap(item.text || item.title)\n const who =\n item.text && item.title ? aiLayoutFitText(item.title, 'statLabel') : ''\n const stack = tree.add(\n 'muiStack',\n { spacing: '2' },\n null,\n [\n tree.add(\n AI_ICON_COMPONENT_ID,\n { iconId: AI_ICON_LIBRARY.quote.id, size: '32' },\n { color: 'primary.main' },\n null,\n 'quoteMark',\n ),\n tree.add(\n 'muiTypography',\n { children: words, variant: 'body1' },\n null,\n null,\n 'quote',\n ),\n tree.add(\n 'muiTypography',\n {\n children:\n aiLayoutFitText(\n who ? `[Customer name], ${who.replace(/^\\[|\\]$/g, '')}` : '',\n 'note',\n ) || '[Customer name]',\n variant: 'subtitle2',\n component: 'p',\n },\n null,\n null,\n 'attribution',\n ),\n ],\n 'quoteStack',\n )\n const content = tree.add(\n 'muiCardContent',\n null,\n { p: 3 },\n [stack],\n 'quoteContent',\n )\n return tree.add('muiCard', null, { height: '100%' }, [content], 'quoteCard')\n}\n\n/** A list: check-marked lines, or plain lines where rule 1 holds and the list is long. */\nfunction list(scope: SectionScope, block: AiLayoutBlock): string | null {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n // A list whose lines go somewhere is a list of links: each line that\n // resolves is a Page Link, and one that does not is left out (rule 10).\n if ((block.items ?? []).some((item) => item.to)) {\n const links = (block.items ?? []).flatMap((item) => {\n const label = aiLayoutFitText(item.title || item.text, 'label')\n const destination = label\n ? aiLayoutResolveLink(item.to, label, scope.link, scope.page.targets)\n : null\n if (!destination) return []\n const id = tree.add(\n 'muiScreenLink',\n {\n children: label,\n renderAs: 'link',\n color: 'inherit',\n ...destinationProps(destination),\n },\n null,\n null,\n 'link',\n )\n linkTo(scope, id, destination)\n return [id]\n })\n return links.length\n ? tree.add('muiStack', { spacing: '1' }, null, noted(scope, links), 'links')\n : null\n }\n const lines = cleanItems(scope, block.items ?? [])\n .map((item) =>\n aiLayoutWords(\n [item.title, item.text].filter((part) => part.trim()).join(' — '),\n 'listItem',\n facts,\n ),\n )\n .filter(Boolean)\n takeItemsInPlace(scope, lines)\n if (!lines.length) return null\n if (rule1(scope)) {\n const rows = lines.map((line) =>\n tree.add(\n 'muiListItem',\n { disableGutters: true },\n null,\n [tree.add('muiListItemText', { primary: line }, null, null, 'line')],\n 'row',\n ),\n )\n return tree.add('muiList', { disablePadding: true }, null, noted(scope, rows), 'list')\n }\n const check = aiIconOfWord(block.icon) ?? AI_ICON_LIBRARY.check\n const rows = lines.map((line) =>\n tree.add(\n 'muiStack',\n { direction: 'row', spacing: '1.5', alignItems: 'flex-start' },\n null,\n [\n tree.add(\n AI_ICON_COMPONENT_ID,\n { iconId: check.id, size: '22' },\n accent(scope),\n null,\n 'check',\n ),\n tree.add(\n 'muiTypography',\n { children: line, variant: 'body1' },\n null,\n null,\n 'line',\n ),\n ],\n 'row',\n ),\n )\n return tree.add('muiStack', { spacing: '1.5' }, null, noted(scope, rows), 'list')\n}\n\n/** Questions and answers: an accordion each, or question-over-answer pairs where rule 1 holds. */\nfunction faq(scope: SectionScope, block: AiLayoutBlock): string | null {\n const tree = scope.page.tree\n const facts = scope.page.targets.facts\n const items = takeItems(\n scope,\n cleanItems(scope, block.items ?? []).filter(\n (item) => !!aiLayoutWords(item.title, 'question', facts),\n ),\n )\n if (!items.length) return null\n if (rule1(scope)) {\n const rows = items.map((item) =>\n tree.add(\n 'muiListItem',\n { disableGutters: true, divider: true },\n null,\n [\n tree.add(\n 'muiListItemText',\n {\n primary: aiLayoutWords(item.title, 'question', facts),\n ...(item.text.trim()\n ? { secondary: aiLayoutWords(item.text, 'answer', facts) }\n : {}),\n },\n null,\n null,\n 'qa',\n ),\n ],\n 'row',\n ),\n )\n return tree.add('muiList', { disablePadding: true }, null, noted(scope, rows), 'faq')\n }\n const panels = items.map((item, position) =>\n tree.add(\n 'muiAccordion',\n {\n disableGutters: true,\n ...(position === 0 ? { defaultExpanded: true } : {}),\n },\n null,\n [\n tree.add(\n 'muiAccordionSummary',\n { children: aiLayoutWords(item.title, 'question', facts) },\n null,\n null,\n 'question',\n ),\n item.text.trim()\n ? tree.add(\n 'muiAccordionDetails',\n null,\n null,\n [\n tree.add(\n 'muiTypography',\n {\n children: aiLayoutWords(item.text, 'answer', facts),\n variant: 'body1',\n },\n { color: 'text.secondary' },\n null,\n 'answer',\n ),\n ],\n 'details',\n )\n : null,\n ],\n 'panel',\n ),\n )\n return tree.add('muiStack', { spacing: '1.5' }, null, noted(scope, panels), 'faq')\n}\n\n/** The id the compiled page's root is stored under. */\nexport const AI_LAYOUT_PAGE_ROOT_ID = CANVAS_ROOT_ELEMENT_ID\n"],"names":["REUSABLE_INSTANCE_COMPONENT_ID","CANVAS_ROOT_ELEMENT_ID","AI_ICON_COMPONENT_ID","aiIconOfWord","AI_ICON_LIBRARY","AI_INSTANCE_REF_PROP","aiPageScrollInteraction","aiLayoutFitText","aiLayoutQuoteGap","aiLayoutWords","AI_LAYOUT_GROUP_KINDS","AI_LAYOUT_MAX_ITEMS","aiLayoutResolveLink","AI_LAYOUT_FRAMES","AiLayoutTreeBuilder","sectionIdOf","index","AI_LAYOUT_MAX_IMAGES","AI_LAYOUT_MAX_STRONG_BANDS","SECTION_PADDING","xs","md","HERO_PADDING","formIdsOf","targets","Set","forms","map","form","id","componentOf","components","find","component","formSectionOf","sections","plan","planned","findIndex","section","uses","some","ref","has","designed","blocks","block","kind","to","aiCompileLayoutPage","options","tree","page","settled","scrollTo","images","strong","brand","dark","formSection","pageIcon","pageIconOf","formsPlaced","itemIds","roots","_","compileSection","rootId","add","nodes","sectionRoots","own","icon","item","items","sparkle","raw","placedHere","at","band","settleBand","scope","centered","align","level","headed","itemsLeft","link","name","from","placePlanned","filter","push","what","cols","length","head","tail","columns","placed","col","undefined","Math","min","filled","column","position","weight","entry","deepest","max","Array","row","flatMap","flat","repeated","every","componentItem","props","groups","isItemGroup","sameShape","columnsAsCards","inOrder","concat","speaks","text","facts","list","splice","unshift","title","order","first","slice","lead","indexOf","wide","isWideGroup","parts","headId","compileFlow","compileRow","tailId","part","prune","componentId","fallback","content","spacing","useFlexGap","container","maxWidth","py","trim","element","ariaLabel","colorScheme","bandSx","sectionIds","value","pattern","test","bgcolor","color","flowId","flow","holdsGroup","disableGutters","plannedForms","plannedComponents","lastCol","only","named","_to","group","like","shapeOf","join","includes","words","aiLayoutSpans","weights","total","reduce","sum","spans","round","over","span","sort","a","b","pick","size","alignItems","room","children","buttons","flushButtons","direction","flexWrap","justifyContent","compileButton","compileBlock","hasGroup","ids","accent","heading","muted","image","faq","place","variant","sx","frame","label","style","itemLevel","itemElement","destination","onBrand","look","destinationProps","alignSelf","linkTo","target","interactions","screenId","href","alt","maxImages","mark","iconId","picture","objectFit","top","left","width","height","display","overflow","borderRadius","aspectRatio","formId","p","declared","values","Object","Boolean","textProps","entries","keys","propValues","type","instanceValues","texts","titleProp","textProp","noted","across","count","itemSize","perRow","layOut","role","cells","rule1","reusableComponents","AI_LAYOUT_PLACEHOLDER_TITLE","cleanItems","references","toLowerCase","takeItems","kept","takeItemsInPlace","instances","compactGroup","step","stat","quote","card","pairs","primary","secondary","stack","String","padStart","who","replace","links","renderAs","lines","rows","line","disablePadding","check","divider","panels","defaultExpanded","AI_LAYOUT_PAGE_ROOT_ID"],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * The words of a layout language document, made to fit where they are shown
19
+ * (AGL-3660). Every word is the model's; the compiler only cleans and fits
20
+ * them: markup a person would see is taken out, a line too long for its place
21
+ * ends at a clean boundary instead of mid-word, a line that would end on a
22
+ * dangling word ("…for you and") loses it, and a phone number or an email
23
+ * address the brief never gave is written as the bracketed gap the doctrine
24
+ * asks for (rule 14) rather than shown as a fact.
25
+ */
26
+ /** Characters each place holds before its line is ended. */
27
+ export declare const AI_LAYOUT_TEXT_LIMITS: {
28
+ /** A page's h1. */
29
+ readonly title: 70;
30
+ /** A section's heading. */
31
+ readonly heading: 80;
32
+ /** A card's, a step's or a sub-heading's title. */
33
+ readonly itemTitle: 60;
34
+ readonly eyebrow: 40;
35
+ /** A button's label; the palette holds a label to 40. */
36
+ readonly label: 28;
37
+ readonly lede: 240;
38
+ readonly text: 420;
39
+ readonly itemText: 240;
40
+ readonly listItem: 140;
41
+ readonly stat: 14;
42
+ readonly statLabel: 60;
43
+ readonly question: 120;
44
+ readonly answer: 420;
45
+ readonly quote: 240;
46
+ readonly note: 200;
47
+ /** An image's description, which is its alt text. */
48
+ readonly alt: 160;
49
+ };
50
+ export type AiLayoutTextPlace = keyof typeof AI_LAYOUT_TEXT_LIMITS;
51
+ /** Collapses whitespace and takes out markup a page would print. */
52
+ export declare function aiLayoutCleanText(value: unknown): string;
53
+ /**
54
+ * The line with every phone number and email address the brief did not give
55
+ * written as the gap (rule 14): a site's contact details are facts, and a
56
+ * model that writes one the brief lacks is inventing it. `facts` is every
57
+ * word the job was given — the brief, the site's answers and its profile.
58
+ */
59
+ export declare function aiLayoutGuardContacts(line: string, facts: string): string;
60
+ /** A line fitted to its place with invented contact details written as gaps. */
61
+ export declare function aiLayoutWords(value: unknown, place: AiLayoutTextPlace, facts: string): string;
62
+ /**
63
+ * A line held to the characters its place holds (see `fitText`), and none at
64
+ * all where what is left is filler.
65
+ */
66
+ export declare function aiLayoutFitText(value: unknown, place: AiLayoutTextPlace): string;
67
+ /**
68
+ * Whether a line is filler rule 14 refuses ("lorem ipsum", "your text here"):
69
+ * such a line is no copy, and the compiler leaves it out rather than ship it.
70
+ */
71
+ export declare function aiLayoutIsFiller(text: string): boolean;
72
+ /** A quote that cannot be a real customer's, written as the gap the owner fills with one (rule 14). */
73
+ export declare function aiLayoutQuoteGap(value: unknown): string;
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { aiDanglingWord, detectOffVoiceCopy } from "../runtime/ai-doctrine-validators.js";
17
+ /**
18
+ * The words of a layout language document, made to fit where they are shown
19
+ * (AGL-3660). Every word is the model's; the compiler only cleans and fits
20
+ * them: markup a person would see is taken out, a line too long for its place
21
+ * ends at a clean boundary instead of mid-word, a line that would end on a
22
+ * dangling word ("…for you and") loses it, and a phone number or an email
23
+ * address the brief never gave is written as the bracketed gap the doctrine
24
+ * asks for (rule 14) rather than shown as a fact.
25
+ */ /** Characters each place holds before its line is ended. */ export const AI_LAYOUT_TEXT_LIMITS = {
26
+ /** A page's h1. */ title: 70,
27
+ /** A section's heading. */ heading: 80,
28
+ /** A card's, a step's or a sub-heading's title. */ itemTitle: 60,
29
+ eyebrow: 40,
30
+ /** A button's label; the palette holds a label to 40. */ label: 28,
31
+ lede: 240,
32
+ text: 420,
33
+ itemText: 240,
34
+ listItem: 140,
35
+ stat: 14,
36
+ statLabel: 60,
37
+ question: 120,
38
+ answer: 420,
39
+ quote: 240,
40
+ note: 200,
41
+ /** An image's description, which is its alt text. */ alt: 160
42
+ };
43
+ /** Inline markup a model writes out of habit, which a page would print literally. */ const MARKUP = /(\*\*|__|`|~~|^#{1,6}\s+|^\s*[-*•]\s+)/gm;
44
+ /** A sentence's end inside a line. */ const SENTENCE_END = /[.!?…](?=["'”’)\]]?\s)/g;
45
+ /** A clause boundary inside a line: a comma, a semicolon, a colon or a dash, with what follows. */ const CLAUSE_END = /\s*(?:[,;:]|\s[—–-])\s/g;
46
+ /** Punctuation that may not end a line it was cut back to. */ const TRAILING_JOINERS = /[\s,;:—–-]+$/;
47
+ /** Collapses whitespace and takes out markup a page would print. */ export function aiLayoutCleanText(value) {
48
+ if (typeof value !== 'string') return '';
49
+ return value.replace(MARKUP, '')// A JSON escape a model wrote out as text ("\\u2014") is the character it names.
50
+ .replace(/\\u([0-9a-fA-F]{4})/g, (_, hex)=>String.fromCharCode(parseInt(hex, 16))).replace(/\s+/g, ' ').trim();
51
+ }
52
+ /** The line with every trailing dangling word taken off, as rule 14 reads one. */ function withoutDanglingTail(line) {
53
+ let text = line.replace(TRAILING_JOINERS, '').trim();
54
+ for(let guard = 0; guard < 6; guard += 1){
55
+ const word = aiDanglingWord(text);
56
+ if (!word) break;
57
+ text = text.slice(0, text.length - word.length).replace(TRAILING_JOINERS, '').trim();
58
+ }
59
+ return text;
60
+ }
61
+ /**
62
+ * A line held to the characters its place holds, ended where a reader expects
63
+ * a line to end: at the last sentence's end that leaves at least half the
64
+ * room, else the last clause boundary that does, else the last whole word. A
65
+ * line that fits is returned clean, with any dangling tail taken off.
66
+ */ function fitText(value, place) {
67
+ const text = aiLayoutCleanText(value);
68
+ const limit = AI_LAYOUT_TEXT_LIMITS[place];
69
+ if (text.length <= limit) return withoutDanglingTail(text);
70
+ const room = text.slice(0, limit + 1);
71
+ const half = Math.floor(limit * 0.4);
72
+ const lastMatch = (pattern)=>{
73
+ let at = -1;
74
+ for (const match of room.matchAll(pattern)){
75
+ var _match_index;
76
+ const end = ((_match_index = match.index) != null ? _match_index : 0) + (pattern === SENTENCE_END ? 1 : 0);
77
+ if (end <= limit && end >= half) at = end;
78
+ }
79
+ return at;
80
+ };
81
+ const sentence = lastMatch(SENTENCE_END);
82
+ if (sentence > 0) return withoutDanglingTail(room.slice(0, sentence));
83
+ const clause = lastMatch(CLAUSE_END);
84
+ if (clause > 0) return withoutDanglingTail(room.slice(0, clause));
85
+ const space = room.lastIndexOf(' ', limit);
86
+ return withoutDanglingTail(space > half ? room.slice(0, space) : room.slice(0, limit));
87
+ }
88
+ /** A phone number as people write one: seven or more digits with the usual separators. */ const PHONE = /\(?\+?\d[\d\s().-]{6,}\d/g;
89
+ const EMAIL = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
90
+ /** The digits of a phone number, which is what two spellings of one number share. */ function digitsOf(value) {
91
+ return value.replace(/\D/g, '');
92
+ }
93
+ /**
94
+ * The line with every phone number and email address the brief did not give
95
+ * written as the gap (rule 14): a site's contact details are facts, and a
96
+ * model that writes one the brief lacks is inventing it. `facts` is every
97
+ * word the job was given — the brief, the site's answers and its profile.
98
+ */ export function aiLayoutGuardContacts(line, facts) {
99
+ var _facts_match;
100
+ const known = facts.toLowerCase();
101
+ const knownDigits = new Set(((_facts_match = facts.match(PHONE)) != null ? _facts_match : []).map(digitsOf));
102
+ return line.replace(EMAIL, (email)=>known.includes(email.toLowerCase()) ? email : '[email address]').replace(PHONE, (phone)=>{
103
+ const digits = digitsOf(phone);
104
+ // A year, a price or a count is not a phone number.
105
+ if (digits.length < 7) return phone;
106
+ return knownDigits.has(digits) ? phone : '[phone number]';
107
+ });
108
+ }
109
+ /** A line fitted to its place with invented contact details written as gaps. */ export function aiLayoutWords(value, place, facts) {
110
+ return aiLayoutFitText(aiLayoutGuardContacts(aiLayoutCleanText(value), facts), place);
111
+ }
112
+ /**
113
+ * A line held to the characters its place holds (see `fitText`), and none at
114
+ * all where what is left is filler.
115
+ */ export function aiLayoutFitText(value, place) {
116
+ const text = fitText(value, place);
117
+ return aiLayoutIsFiller(text) ? '' : text;
118
+ }
119
+ /**
120
+ * Whether a line is filler rule 14 refuses ("lorem ipsum", "your text here"):
121
+ * such a line is no copy, and the compiler leaves it out rather than ship it.
122
+ */ export function aiLayoutIsFiller(text) {
123
+ return detectOffVoiceCopy([
124
+ {
125
+ at: 'line',
126
+ text
127
+ }
128
+ ]).length > 0;
129
+ }
130
+ /** A quote that cannot be a real customer's, written as the gap the owner fills with one (rule 14). */ export function aiLayoutQuoteGap(value) {
131
+ const text = aiLayoutFitText(value, 'quote').replace(/^["“'‘]+|["”'’]+$/g, '').trim();
132
+ if (!text) return '';
133
+ if (/^\[.*\]$/.test(text)) return text;
134
+ return `[${text.replace(/^\[|\]$/g, '')}]`;
135
+ }
136
+
137
+ //# sourceMappingURL=ai-layout-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-copy.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n aiDanglingWord,\n detectOffVoiceCopy,\n} from '../runtime/ai-doctrine-validators'\n\n/**\n * The words of a layout language document, made to fit where they are shown\n * (AGL-3660). Every word is the model's; the compiler only cleans and fits\n * them: markup a person would see is taken out, a line too long for its place\n * ends at a clean boundary instead of mid-word, a line that would end on a\n * dangling word (\"…for you and\") loses it, and a phone number or an email\n * address the brief never gave is written as the bracketed gap the doctrine\n * asks for (rule 14) rather than shown as a fact.\n */\n\n/** Characters each place holds before its line is ended. */\nexport const AI_LAYOUT_TEXT_LIMITS = {\n /** A page's h1. */\n title: 70,\n /** A section's heading. */\n heading: 80,\n /** A card's, a step's or a sub-heading's title. */\n itemTitle: 60,\n eyebrow: 40,\n /** A button's label; the palette holds a label to 40. */\n label: 28,\n lede: 240,\n text: 420,\n itemText: 240,\n listItem: 140,\n stat: 14,\n statLabel: 60,\n question: 120,\n answer: 420,\n quote: 240,\n note: 200,\n /** An image's description, which is its alt text. */\n alt: 160,\n} as const\n\nexport type AiLayoutTextPlace = keyof typeof AI_LAYOUT_TEXT_LIMITS\n\n/** Inline markup a model writes out of habit, which a page would print literally. */\nconst MARKUP = /(\\*\\*|__|`|~~|^#{1,6}\\s+|^\\s*[-*•]\\s+)/gm\n\n/** A sentence's end inside a line. */\nconst SENTENCE_END = /[.!?…](?=[\"'”’)\\]]?\\s)/g\n\n/** A clause boundary inside a line: a comma, a semicolon, a colon or a dash, with what follows. */\nconst CLAUSE_END = /\\s*(?:[,;:]|\\s[—–-])\\s/g\n\n/** Punctuation that may not end a line it was cut back to. */\nconst TRAILING_JOINERS = /[\\s,;:—–-]+$/\n\n/** Collapses whitespace and takes out markup a page would print. */\nexport function aiLayoutCleanText(value: unknown): string {\n if (typeof value !== 'string') return ''\n return value\n .replace(MARKUP, '')\n // A JSON escape a model wrote out as text (\"\\\\u2014\") is the character it names.\n .replace(/\\\\u([0-9a-fA-F]{4})/g, (_, hex: string) => String.fromCharCode(parseInt(hex, 16)))\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** The line with every trailing dangling word taken off, as rule 14 reads one. */\nfunction withoutDanglingTail(line: string): string {\n let text = line.replace(TRAILING_JOINERS, '').trim()\n for (let guard = 0; guard < 6; guard += 1) {\n const word = aiDanglingWord(text)\n if (!word) break\n text = text\n .slice(0, text.length - word.length)\n .replace(TRAILING_JOINERS, '')\n .trim()\n }\n return text\n}\n\n/**\n * A line held to the characters its place holds, ended where a reader expects\n * a line to end: at the last sentence's end that leaves at least half the\n * room, else the last clause boundary that does, else the last whole word. A\n * line that fits is returned clean, with any dangling tail taken off.\n */\nfunction fitText(value: unknown, place: AiLayoutTextPlace): string {\n const text = aiLayoutCleanText(value)\n const limit = AI_LAYOUT_TEXT_LIMITS[place]\n if (text.length <= limit) return withoutDanglingTail(text)\n const room = text.slice(0, limit + 1)\n const half = Math.floor(limit * 0.4)\n const lastMatch = (pattern: RegExp): number => {\n let at = -1\n for (const match of room.matchAll(pattern)) {\n const end = (match.index ?? 0) + (pattern === SENTENCE_END ? 1 : 0)\n if (end <= limit && end >= half) at = end\n }\n return at\n }\n const sentence = lastMatch(SENTENCE_END)\n if (sentence > 0) return withoutDanglingTail(room.slice(0, sentence))\n const clause = lastMatch(CLAUSE_END)\n if (clause > 0) return withoutDanglingTail(room.slice(0, clause))\n const space = room.lastIndexOf(' ', limit)\n return withoutDanglingTail(\n space > half ? room.slice(0, space) : room.slice(0, limit),\n )\n}\n\n/** A phone number as people write one: seven or more digits with the usual separators. */\nconst PHONE = /\\(?\\+?\\d[\\d\\s().-]{6,}\\d/g\nconst EMAIL = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}/g\n\n/** The digits of a phone number, which is what two spellings of one number share. */\nfunction digitsOf(value: string): string {\n return value.replace(/\\D/g, '')\n}\n\n/**\n * The line with every phone number and email address the brief did not give\n * written as the gap (rule 14): a site's contact details are facts, and a\n * model that writes one the brief lacks is inventing it. `facts` is every\n * word the job was given — the brief, the site's answers and its profile.\n */\nexport function aiLayoutGuardContacts(line: string, facts: string): string {\n const known = facts.toLowerCase()\n const knownDigits = new Set((facts.match(PHONE) ?? []).map(digitsOf))\n return line\n .replace(EMAIL, (email) =>\n known.includes(email.toLowerCase()) ? email : '[email address]',\n )\n .replace(PHONE, (phone) => {\n const digits = digitsOf(phone)\n // A year, a price or a count is not a phone number.\n if (digits.length < 7) return phone\n return knownDigits.has(digits) ? phone : '[phone number]'\n })\n}\n\n/** A line fitted to its place with invented contact details written as gaps. */\nexport function aiLayoutWords(\n value: unknown,\n place: AiLayoutTextPlace,\n facts: string,\n): string {\n return aiLayoutFitText(\n aiLayoutGuardContacts(aiLayoutCleanText(value), facts),\n place,\n )\n}\n\n/**\n * A line held to the characters its place holds (see `fitText`), and none at\n * all where what is left is filler.\n */\nexport function aiLayoutFitText(\n value: unknown,\n place: AiLayoutTextPlace,\n): string {\n const text = fitText(value, place)\n return aiLayoutIsFiller(text) ? '' : text\n}\n\n/**\n * Whether a line is filler rule 14 refuses (\"lorem ipsum\", \"your text here\"):\n * such a line is no copy, and the compiler leaves it out rather than ship it.\n */\nexport function aiLayoutIsFiller(text: string): boolean {\n return detectOffVoiceCopy([{ at: 'line', text }]).length > 0\n}\n\n/** A quote that cannot be a real customer's, written as the gap the owner fills with one (rule 14). */\nexport function aiLayoutQuoteGap(value: unknown): string {\n const text = aiLayoutFitText(value, 'quote')\n .replace(/^[\"“'‘]+|[\"”'’]+$/g, '')\n .trim()\n if (!text) return ''\n if (/^\\[.*\\]$/.test(text)) return text\n return `[${text.replace(/^\\[|\\]$/g, '')}]`\n}\n"],"names":["aiDanglingWord","detectOffVoiceCopy","AI_LAYOUT_TEXT_LIMITS","title","heading","itemTitle","eyebrow","label","lede","text","itemText","listItem","stat","statLabel","question","answer","quote","note","alt","MARKUP","SENTENCE_END","CLAUSE_END","TRAILING_JOINERS","aiLayoutCleanText","value","replace","_","hex","String","fromCharCode","parseInt","trim","withoutDanglingTail","line","guard","word","slice","length","fitText","place","limit","room","half","Math","floor","lastMatch","pattern","at","match","matchAll","end","index","sentence","clause","space","lastIndexOf","PHONE","EMAIL","digitsOf","aiLayoutGuardContacts","facts","known","toLowerCase","knownDigits","Set","map","email","includes","phone","digits","has","aiLayoutWords","aiLayoutFitText","aiLayoutIsFiller","aiLayoutQuoteGap","test"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type AiLayoutSection, type AiLayoutSettlement } from './ai-layout-language';
18
+ import { type AiLayoutPage, type AiLayoutTargets } from './ai-layout-links';
19
+ import { type AiLayoutRawTree } from './ai-layout-tree';
20
+ /**
21
+ * A site's frame — the header and the footer every page renders between —
22
+ * compiled from the layout language (AGL-3660), the same language a page is
23
+ * designed in.
24
+ *
25
+ * The design is the model's: the header's band and alignment and its one
26
+ * call to action, and the footer's columns and every word in them. What a
27
+ * frame owes the site is the platform's, written here, so it is never wrong
28
+ * and never invented: the site's name as the brand, linking home; its pages
29
+ * as the navigation, a row on a wide screen and the platform's Drawer behind
30
+ * its Menu Button on a phone; the Layout Slot, the page's one main landmark,
31
+ * held tall enough that the footer sits at the bottom of a short page; and
32
+ * the site's pages and name in the footer, where the design gave neither.
33
+ */
34
+ export interface AiLayoutFramePlan {
35
+ /** The site's name, which the header and the footer carry as its brand. */
36
+ siteName: string;
37
+ /** The site's home page, which the brand links; none where the site has none yet. */
38
+ homeId: string | null;
39
+ /** The pages the navigation links, in order. */
40
+ navPages: readonly AiLayoutPage[];
41
+ }
42
+ export interface AiLayoutCompiledFrame {
43
+ tree: AiLayoutRawTree;
44
+ settled: AiLayoutSettlement[];
45
+ }
46
+ /** A line that reads as a copyright notice: "© 2026 …", "Copyright …", "All rights reserved." */
47
+ export declare function aiLayoutIsCopyright(text: unknown): boolean;
48
+ /** Compiles a site's header and footer, designed in the layout language, into its layout. */
49
+ export declare function aiCompileLayoutFrame(frame: {
50
+ header: AiLayoutSection | null;
51
+ footer: AiLayoutSection | null;
52
+ }, plan: AiLayoutFramePlan, targets: AiLayoutTargets): AiLayoutCompiledFrame;