canopycms 0.0.68-int.98 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (688) hide show
  1. package/CHANGELOG.md +2131 -0
  2. package/README.md +47 -63
  3. package/dist/ai/generate.d.ts +5 -0
  4. package/dist/ai/generate.js +244 -115
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/json-to-markdown.d.ts +21 -1
  7. package/dist/ai/json-to-markdown.js +120 -57
  8. package/dist/ai/references.d.ts +72 -0
  9. package/dist/ai/references.js +223 -0
  10. package/dist/ai/resolve-branch.js +9 -2
  11. package/dist/ai/to-plain-text.d.ts +17 -8
  12. package/dist/ai/to-plain-text.js +18 -15
  13. package/dist/ai/types.d.ts +84 -3
  14. package/dist/api/admin-branch-health.d.ts +24 -1
  15. package/dist/api/admin-branch-health.js +52 -20
  16. package/dist/api/admin.d.ts +23 -5
  17. package/dist/api/admin.js +36 -1
  18. package/dist/api/assets.js +88 -78
  19. package/dist/api/branch-create-window.d.ts +12 -0
  20. package/dist/api/branch-create-window.js +13 -0
  21. package/dist/api/branch-merge.d.ts +1 -1
  22. package/dist/api/branch-merge.js +1 -1
  23. package/dist/api/branch-review.d.ts +3 -3
  24. package/dist/api/branch-review.js +16 -7
  25. package/dist/api/branch-status.d.ts +16 -6
  26. package/dist/api/branch-status.js +57 -12
  27. package/dist/api/branch-withdraw.d.ts +2 -2
  28. package/dist/api/branch-withdraw.js +8 -3
  29. package/dist/api/branch.d.ts +25 -12
  30. package/dist/api/branch.js +164 -103
  31. package/dist/api/client.d.ts +78 -58
  32. package/dist/api/client.js +150 -117
  33. package/dist/api/comments.d.ts +12 -3
  34. package/dist/api/comments.js +118 -9
  35. package/dist/api/content.d.ts +9 -9
  36. package/dist/api/content.js +131 -22
  37. package/dist/api/entries-constants.d.ts +14 -3
  38. package/dist/api/entries-constants.js +14 -3
  39. package/dist/api/entries.d.ts +40 -2
  40. package/dist/api/entries.js +102 -6
  41. package/dist/api/github-sync.d.ts +19 -0
  42. package/dist/api/github-sync.js +50 -3
  43. package/dist/api/groups.d.ts +4 -4
  44. package/dist/api/groups.js +2 -1
  45. package/dist/api/guards.js +23 -3
  46. package/dist/api/index.d.ts +3 -1
  47. package/dist/api/index.js +1 -0
  48. package/dist/api/permissions.d.ts +21 -2
  49. package/dist/api/permissions.js +50 -3
  50. package/dist/api/request-deadline.d.ts +59 -0
  51. package/dist/api/request-deadline.js +73 -0
  52. package/dist/api/resolve-references.js +8 -7
  53. package/dist/api/route-builder.d.ts +14 -0
  54. package/dist/api/route-builder.js +14 -1
  55. package/dist/api/schema.d.ts +11 -9
  56. package/dist/api/schema.js +2 -0
  57. package/dist/api/settings-helpers.d.ts +5 -1
  58. package/dist/api/settings-helpers.js +10 -2
  59. package/dist/api/types.d.ts +18 -0
  60. package/dist/api/users-constants.d.ts +6 -0
  61. package/dist/api/users-constants.js +6 -0
  62. package/dist/assets/asset-url.d.ts +28 -16
  63. package/dist/assets/asset-url.js +51 -25
  64. package/dist/assets/finalize.js +3 -0
  65. package/dist/assets/index.d.ts +1 -1
  66. package/dist/assets/materialize.d.ts +153 -0
  67. package/dist/assets/materialize.js +402 -0
  68. package/dist/assets/store-local.d.ts +19 -5
  69. package/dist/assets/store-local.js +69 -10
  70. package/dist/assets/store-s3.d.ts +38 -7
  71. package/dist/assets/store-s3.js +128 -22
  72. package/dist/assets/transform-directives.d.ts +52 -13
  73. package/dist/assets/transform-directives.js +87 -27
  74. package/dist/assets/transform.d.ts +3 -3
  75. package/dist/assets/transform.js +13 -8
  76. package/dist/assets/types.d.ts +31 -4
  77. package/dist/auth/cache.d.ts +1 -1
  78. package/dist/auth/cache.js +1 -1
  79. package/dist/auth/caching-auth-plugin.d.ts +2 -0
  80. package/dist/auth/caching-auth-plugin.js +12 -2
  81. package/dist/auth/file-based-auth-cache.d.ts +8 -0
  82. package/dist/auth/file-based-auth-cache.js +18 -8
  83. package/dist/auth/person-name.d.ts +5 -0
  84. package/dist/auth/person-name.js +8 -0
  85. package/dist/auth/plugin.d.ts +10 -1
  86. package/dist/auth/types.d.ts +2 -0
  87. package/dist/auth/user-metadata-lookup.d.ts +21 -0
  88. package/dist/auth/user-metadata-lookup.js +116 -0
  89. package/dist/authorization/branch.d.ts +1 -1
  90. package/dist/authorization/branch.js +12 -13
  91. package/dist/authorization/groups/schema.d.ts +4 -4
  92. package/dist/authorization/helpers.d.ts +8 -0
  93. package/dist/authorization/helpers.js +8 -0
  94. package/dist/authorization/index.d.ts +1 -1
  95. package/dist/authorization/index.js +1 -1
  96. package/dist/authorization/protected-branch.d.ts +5 -4
  97. package/dist/authorization/protected-branch.js +7 -5
  98. package/dist/branch-health.d.ts +35 -8
  99. package/dist/branch-health.js +54 -18
  100. package/dist/branch-metadata-error.d.ts +27 -0
  101. package/dist/branch-metadata-error.js +23 -0
  102. package/dist/branch-metadata-file.d.ts +205 -24
  103. package/dist/branch-metadata-file.js +126 -25
  104. package/dist/branch-metadata.d.ts +45 -6
  105. package/dist/branch-metadata.js +142 -50
  106. package/dist/branch-provisioning.d.ts +167 -0
  107. package/dist/branch-provisioning.js +501 -0
  108. package/dist/branch-registry.d.ts +8 -0
  109. package/dist/branch-registry.js +61 -9
  110. package/dist/branch-schema-cache.d.ts +29 -12
  111. package/dist/branch-schema-cache.js +64 -21
  112. package/dist/branch-sparse.d.ts +23 -0
  113. package/dist/branch-sparse.js +118 -0
  114. package/dist/branch-workspace.d.ts +42 -3
  115. package/dist/branch-workspace.js +239 -100
  116. package/dist/build/asset-refs.d.ts +94 -0
  117. package/dist/build/asset-refs.js +267 -0
  118. package/dist/build/generate-ai-content.js +5 -0
  119. package/dist/build/inline-flight.d.ts +37 -0
  120. package/dist/build/inline-flight.js +142 -0
  121. package/dist/cli/asset-refs.d.ts +52 -0
  122. package/dist/cli/asset-refs.js +194 -0
  123. package/dist/cli/cli.d.ts +15 -1
  124. package/dist/cli/cli.js +8543 -3193
  125. package/dist/cli/configured-asset-store.d.ts +12 -0
  126. package/dist/cli/configured-asset-store.js +46 -0
  127. package/dist/cli/generate-ai-content.js +4244 -1072
  128. package/dist/cli/init.js +217 -126
  129. package/dist/cli/project-detect.d.ts +2 -0
  130. package/dist/cli/project-detect.js +2 -0
  131. package/dist/cli/template-files/Dockerfile.cms.template +13 -5
  132. package/dist/cli/template-files/cms-stack.ts.template +16 -13
  133. package/dist/client.d.ts +1 -2
  134. package/dist/client.js +1 -2
  135. package/dist/comment-store.d.ts +25 -0
  136. package/dist/comment-store.js +43 -8
  137. package/dist/config/flatten.js +2 -0
  138. package/dist/config/helpers.js +2 -2
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/config/schemas/config.d.ts +12 -29
  141. package/dist/config/schemas/config.js +9 -12
  142. package/dist/config/schemas/field.d.ts +3 -0
  143. package/dist/config/schemas/field.js +58 -4
  144. package/dist/config/schemas/media.d.ts +4 -13
  145. package/dist/config/schemas/media.js +5 -8
  146. package/dist/config/schemas/url.d.ts +2 -20
  147. package/dist/config/schemas/url.js +2 -25
  148. package/dist/config/types.d.ts +116 -22
  149. package/dist/config/types.js +3 -9
  150. package/dist/config/validation.d.ts +25 -4
  151. package/dist/config/validation.js +116 -3
  152. package/dist/content-id-index.js +2 -2
  153. package/dist/content-index-generation.d.ts +1 -1
  154. package/dist/content-index-generation.js +1 -1
  155. package/dist/content-listing.d.ts +10 -1
  156. package/dist/content-listing.js +22 -5
  157. package/dist/content-reader.d.ts +9 -0
  158. package/dist/content-reader.js +16 -11
  159. package/dist/content-store.d.ts +75 -12
  160. package/dist/content-store.js +249 -86
  161. package/dist/content-tree.js +2 -2
  162. package/dist/context.js +5 -2
  163. package/dist/dangling-reference-log.d.ts +17 -0
  164. package/dist/dangling-reference-log.js +29 -0
  165. package/dist/dev-content-watcher.d.ts +1 -1
  166. package/dist/dev-content-watcher.js +1 -1
  167. package/dist/editor/BranchManager.d.ts +23 -7
  168. package/dist/editor/BranchManager.js +119 -54
  169. package/dist/editor/CanopyEditor.d.ts +1 -1
  170. package/dist/editor/CanopyEditor.js +1 -2
  171. package/dist/editor/CommentsPanel.d.ts +14 -0
  172. package/dist/editor/CommentsPanel.js +68 -43
  173. package/dist/editor/Editor.d.ts +11 -5
  174. package/dist/editor/Editor.js +891 -218
  175. package/dist/editor/EditorAuthGate.d.ts +7 -1
  176. package/dist/editor/EditorAuthGate.js +41 -9
  177. package/dist/editor/EntryNavigator.d.ts +22 -0
  178. package/dist/editor/EntryNavigator.js +353 -105
  179. package/dist/editor/FormHeader.d.ts +25 -0
  180. package/dist/editor/FormHeader.js +82 -0
  181. package/dist/editor/FormRenderer.d.ts +27 -3
  182. package/dist/editor/FormRenderer.js +171 -76
  183. package/dist/editor/PreviewFrame.d.ts +40 -0
  184. package/dist/editor/PreviewFrame.js +215 -0
  185. package/dist/editor/PreviewPane.d.ts +47 -0
  186. package/dist/editor/PreviewPane.js +147 -0
  187. package/dist/editor/PreviewToolbarTools.d.ts +22 -0
  188. package/dist/editor/PreviewToolbarTools.js +73 -0
  189. package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
  190. package/dist/editor/admin/SystemHealthPanel.js +163 -33
  191. package/dist/editor/admin/useSystemHealth.d.ts +18 -0
  192. package/dist/editor/admin/useSystemHealth.js +70 -1
  193. package/dist/editor/branch-status.d.ts +17 -0
  194. package/dist/editor/branch-status.js +29 -0
  195. package/dist/editor/canopy-path.d.ts +9 -6
  196. package/dist/editor/canopy-path.js +8 -11
  197. package/dist/editor/client-reference-resolver.d.ts +43 -16
  198. package/dist/editor/client-reference-resolver.js +155 -64
  199. package/dist/editor/comments/BranchComments.d.ts +1 -1
  200. package/dist/editor/comments/BranchComments.js +2 -2
  201. package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
  202. package/dist/editor/comments/CloseRefusedNotice.js +7 -0
  203. package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
  204. package/dist/editor/comments/CommentThreadsPopover.js +274 -0
  205. package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
  206. package/dist/editor/comments/CommentWriteAlert.js +13 -0
  207. package/dist/editor/comments/EntryComments.d.ts +10 -4
  208. package/dist/editor/comments/EntryComments.js +14 -17
  209. package/dist/editor/comments/FieldWrapper.d.ts +18 -4
  210. package/dist/editor/comments/FieldWrapper.js +62 -28
  211. package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
  212. package/dist/editor/comments/InlineCommentThread.js +11 -47
  213. package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
  214. package/dist/editor/comments/ThreadCarousel.js +18 -21
  215. package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
  216. package/dist/editor/comments/ThreadReplyControls.js +92 -0
  217. package/dist/editor/comments/field-comment-context.d.ts +14 -0
  218. package/dist/editor/comments/field-comment-context.js +14 -0
  219. package/dist/editor/comments/form-comments.d.ts +48 -0
  220. package/dist/editor/comments/form-comments.js +178 -0
  221. package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
  222. package/dist/editor/comments/item-anchor-copy.js +6 -0
  223. package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
  224. package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
  225. package/dist/editor/comments/popover-placement.d.ts +18 -0
  226. package/dist/editor/comments/popover-placement.js +58 -0
  227. package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
  228. package/dist/editor/comments/use-tracked-writes.js +53 -0
  229. package/dist/editor/components/BranchAccessList.d.ts +15 -0
  230. package/dist/editor/components/BranchAccessList.js +52 -0
  231. package/dist/editor/components/BranchLockBanner.d.ts +22 -0
  232. package/dist/editor/components/BranchLockBanner.js +39 -0
  233. package/dist/editor/components/BranchPill.d.ts +32 -0
  234. package/dist/editor/components/BranchPill.js +33 -0
  235. package/dist/editor/components/BranchesDrawer.d.ts +11 -0
  236. package/dist/editor/components/BranchesDrawer.js +5 -0
  237. package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
  238. package/dist/editor/components/ConfirmDeleteModal.js +3 -2
  239. package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
  240. package/dist/editor/components/DestructiveMenuItem.js +8 -0
  241. package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
  242. package/dist/editor/components/EditorCrashScreen.js +22 -0
  243. package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
  244. package/dist/editor/components/EditorErrorBoundary.js +40 -0
  245. package/dist/editor/components/EditorHeader.d.ts +56 -106
  246. package/dist/editor/components/EditorHeader.js +130 -131
  247. package/dist/editor/components/EditorRail.d.ts +49 -0
  248. package/dist/editor/components/EditorRail.js +65 -0
  249. package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
  250. package/dist/editor/components/EntryBreadcrumb.js +56 -0
  251. package/dist/editor/components/EntryCreateModal.d.ts +12 -7
  252. package/dist/editor/components/EntryCreateModal.js +51 -57
  253. package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
  254. package/dist/editor/components/NoEditPermissionNotice.js +5 -4
  255. package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
  256. package/dist/editor/components/QuickOpenPalette.js +66 -0
  257. package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
  258. package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
  259. package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
  260. package/dist/editor/components/ReasonedMenuItem.js +15 -0
  261. package/dist/editor/components/ReferencedByList.d.ts +11 -0
  262. package/dist/editor/components/ReferencedByList.js +28 -0
  263. package/dist/editor/components/RelativeTime.d.ts +10 -0
  264. package/dist/editor/components/RelativeTime.js +10 -0
  265. package/dist/editor/components/RenameEntryModal.d.ts +9 -1
  266. package/dist/editor/components/RenameEntryModal.js +19 -31
  267. package/dist/editor/components/RetryToastMessage.d.ts +9 -0
  268. package/dist/editor/components/RetryToastMessage.js +6 -0
  269. package/dist/editor/components/SaveAllResult.d.ts +25 -0
  270. package/dist/editor/components/SaveAllResult.js +86 -0
  271. package/dist/editor/components/SaveSplitButton.d.ts +30 -0
  272. package/dist/editor/components/SaveSplitButton.js +108 -0
  273. package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
  274. package/dist/editor/components/StagedChangesDrawer.js +92 -0
  275. package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
  276. package/dist/editor/components/UnavailableEntryNotice.js +9 -0
  277. package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
  278. package/dist/editor/components/UnavailableTypeMessage.js +9 -0
  279. package/dist/editor/components/UndoToastMessage.d.ts +18 -0
  280. package/dist/editor/components/UndoToastMessage.js +10 -0
  281. package/dist/editor/components/UserBadge.d.ts +2 -5
  282. package/dist/editor/components/UserBadge.js +62 -33
  283. package/dist/editor/components/ValidationSummary.d.ts +14 -0
  284. package/dist/editor/components/ValidationSummary.js +24 -0
  285. package/dist/editor/components/index.d.ts +2 -2
  286. package/dist/editor/components/index.js +2 -2
  287. package/dist/editor/context/ApiClientContext.d.ts +8 -2
  288. package/dist/editor/context/ApiClientContext.js +19 -8
  289. package/dist/editor/context/AssetContext.d.ts +13 -35
  290. package/dist/editor/context/AssetContext.js +12 -31
  291. package/dist/editor/context/EditorStateContext.d.ts +4 -4
  292. package/dist/editor/context/EditorStateContext.js +4 -4
  293. package/dist/editor/context/SWRProvider.d.ts +3 -3
  294. package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
  295. package/dist/editor/context/SiteMdxAllowContext.js +7 -0
  296. package/dist/editor/context/index.d.ts +2 -1
  297. package/dist/editor/context/index.js +2 -1
  298. package/dist/editor/contrast.d.ts +19 -0
  299. package/dist/editor/contrast.js +41 -0
  300. package/dist/editor/copy.d.ts +18 -0
  301. package/dist/editor/copy.js +18 -0
  302. package/dist/editor/editor-config.js +16 -0
  303. package/dist/editor/editor-utils.d.ts +34 -8
  304. package/dist/editor/editor-utils.js +42 -20
  305. package/dist/editor/entry-search.d.ts +20 -0
  306. package/dist/editor/entry-search.js +34 -0
  307. package/dist/editor/field-breadcrumb.d.ts +12 -0
  308. package/dist/editor/field-breadcrumb.js +85 -0
  309. package/dist/editor/field-props.d.ts +86 -0
  310. package/dist/editor/field-props.js +27 -0
  311. package/dist/editor/field-target.d.ts +30 -0
  312. package/dist/editor/field-target.js +77 -0
  313. package/dist/editor/fields/BlockField.d.ts +12 -0
  314. package/dist/editor/fields/BlockField.js +89 -73
  315. package/dist/editor/fields/CodeField.d.ts +2 -0
  316. package/dist/editor/fields/CodeField.js +6 -2
  317. package/dist/editor/fields/DateTimeField.d.ts +4 -29
  318. package/dist/editor/fields/DateTimeField.js +79 -41
  319. package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
  320. package/dist/editor/fields/ExpandAllButton.js +4 -0
  321. package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
  322. package/dist/editor/fields/FieldCrashFallback.js +30 -0
  323. package/dist/editor/fields/FieldLabel.d.ts +37 -0
  324. package/dist/editor/fields/FieldLabel.js +19 -0
  325. package/dist/editor/fields/ImageField.d.ts +4 -0
  326. package/dist/editor/fields/ImageField.js +29 -14
  327. package/dist/editor/fields/InlineGroupField.js +4 -3
  328. package/dist/editor/fields/ItemList.d.ts +42 -0
  329. package/dist/editor/fields/ItemList.js +130 -0
  330. package/dist/editor/fields/MarkdownField.d.ts +32 -0
  331. package/dist/editor/fields/MarkdownField.js +223 -46
  332. package/dist/editor/fields/MdxImageDialog.js +1 -1
  333. package/dist/editor/fields/NumberField.d.ts +2 -0
  334. package/dist/editor/fields/NumberField.js +8 -5
  335. package/dist/editor/fields/NumberListField.d.ts +2 -0
  336. package/dist/editor/fields/NumberListField.js +19 -16
  337. package/dist/editor/fields/ObjectField.d.ts +2 -7
  338. package/dist/editor/fields/ObjectField.js +15 -5
  339. package/dist/editor/fields/ObjectListField.d.ts +29 -0
  340. package/dist/editor/fields/ObjectListField.js +57 -0
  341. package/dist/editor/fields/ReferenceField.d.ts +2 -0
  342. package/dist/editor/fields/ReferenceField.js +34 -9
  343. package/dist/editor/fields/SelectField.d.ts +2 -0
  344. package/dist/editor/fields/SelectField.js +11 -2
  345. package/dist/editor/fields/StringListField.d.ts +4 -1
  346. package/dist/editor/fields/StringListField.js +22 -8
  347. package/dist/editor/fields/TextField.d.ts +2 -0
  348. package/dist/editor/fields/TextField.js +6 -2
  349. package/dist/editor/fields/ToggleField.d.ts +2 -0
  350. package/dist/editor/fields/ToggleField.js +8 -3
  351. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
  352. package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
  353. package/dist/editor/fields/form-expansion.d.ts +9 -0
  354. package/dist/editor/fields/form-expansion.js +2 -0
  355. package/dist/editor/fields/item-expansion.d.ts +15 -0
  356. package/dist/editor/fields/item-expansion.js +60 -0
  357. package/dist/editor/fields/list-item-keys.d.ts +8 -0
  358. package/dist/editor/fields/list-item-keys.js +50 -0
  359. package/dist/editor/fields/list-item-title.d.ts +20 -0
  360. package/dist/editor/fields/list-item-title.js +85 -0
  361. package/dist/editor/fields/markdown-export-options.d.ts +2 -0
  362. package/dist/editor/fields/markdown-export-options.js +8 -0
  363. package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
  364. package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
  365. package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
  366. package/dist/editor/fields/mdx-jsx-support.js +157 -69
  367. package/dist/editor/fields/rich-text-failures.d.ts +5 -0
  368. package/dist/editor/fields/rich-text-failures.js +26 -0
  369. package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
  370. package/dist/editor/fields/toolbar-wrap.js +35 -0
  371. package/dist/editor/form-outline.d.ts +13 -0
  372. package/dist/editor/form-outline.js +70 -0
  373. package/dist/editor/group-manager/GroupCard.d.ts +4 -1
  374. package/dist/editor/group-manager/GroupCard.js +12 -3
  375. package/dist/editor/group-manager/GroupForm.js +1 -1
  376. package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
  377. package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
  378. package/dist/editor/group-manager/MemberList.d.ts +2 -1
  379. package/dist/editor/group-manager/MemberList.js +15 -4
  380. package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
  381. package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
  382. package/dist/editor/group-manager/index.js +34 -5
  383. package/dist/editor/group-manager/types.d.ts +5 -2
  384. package/dist/editor/hooks/create-branch-request.d.ts +20 -0
  385. package/dist/editor/hooks/create-branch-request.js +54 -0
  386. package/dist/editor/hooks/save-all.d.ts +68 -0
  387. package/dist/editor/hooks/save-all.js +61 -0
  388. package/dist/editor/hooks/useBranchActions.d.ts +11 -1
  389. package/dist/editor/hooks/useBranchActions.js +42 -19
  390. package/dist/editor/hooks/useBranchManager.d.ts +21 -0
  391. package/dist/editor/hooks/useBranchManager.js +321 -125
  392. package/dist/editor/hooks/useBranchesData.d.ts +8 -4
  393. package/dist/editor/hooks/useBranchesData.js +9 -5
  394. package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
  395. package/dist/editor/hooks/useCommentSystem.js +79 -55
  396. package/dist/editor/hooks/useCommentsData.d.ts +11 -7
  397. package/dist/editor/hooks/useCommentsData.js +20 -19
  398. package/dist/editor/hooks/useDraftManager.d.ts +77 -3
  399. package/dist/editor/hooks/useDraftManager.js +887 -94
  400. package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
  401. package/dist/editor/hooks/useEditorLayout.js +98 -20
  402. package/dist/editor/hooks/useEntriesData.d.ts +2 -1
  403. package/dist/editor/hooks/useEntriesData.js +18 -4
  404. package/dist/editor/hooks/useEntryManager.d.ts +41 -2
  405. package/dist/editor/hooks/useEntryManager.js +227 -41
  406. package/dist/editor/hooks/useGroupManager.js +13 -16
  407. package/dist/editor/hooks/usePermissionManager.js +14 -6
  408. package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
  409. package/dist/editor/hooks/usePreviewMarks.js +33 -0
  410. package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
  411. package/dist/editor/hooks/useReferenceResolution.js +34 -177
  412. package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
  413. package/dist/editor/hooks/useSchemaManager.js +97 -39
  414. package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
  415. package/dist/editor/hooks/useUserMetadata.js +76 -47
  416. package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
  417. package/dist/editor/hooks/user-metadata-batcher.js +33 -0
  418. package/dist/editor/media/AssetCard.d.ts +6 -7
  419. package/dist/editor/media/AssetCard.js +24 -31
  420. package/dist/editor/media/AssetListRow.d.ts +16 -0
  421. package/dist/editor/media/AssetListRow.js +41 -0
  422. package/dist/editor/media/CropStep.js +6 -1
  423. package/dist/editor/media/MediaLibrary.d.ts +4 -3
  424. package/dist/editor/media/MediaLibrary.js +11 -4
  425. package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
  426. package/dist/editor/media/MediaLibraryBody.js +195 -80
  427. package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
  428. package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
  429. package/dist/editor/media/crop-math.d.ts +3 -4
  430. package/dist/editor/media/crop-math.js +11 -22
  431. package/dist/editor/media/editor-image-src.d.ts +8 -0
  432. package/dist/editor/media/editor-image-src.js +10 -0
  433. package/dist/editor/media/format-bytes.d.ts +2 -0
  434. package/dist/editor/media/format-bytes.js +23 -0
  435. package/dist/editor/media/media-library-prefs.d.ts +23 -0
  436. package/dist/editor/media/media-library-prefs.js +49 -0
  437. package/dist/editor/media/media-library-view.d.ts +34 -0
  438. package/dist/editor/media/media-library-view.js +40 -0
  439. package/dist/editor/media/useAssetLibrary.d.ts +30 -0
  440. package/dist/editor/media/useAssetLibrary.js +126 -0
  441. package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
  442. package/dist/editor/media/useStableAssetOrder.js +37 -0
  443. package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
  444. package/dist/editor/media/useThumbnailFailure.js +16 -0
  445. package/dist/editor/permission-manager/GroupSelector.js +2 -2
  446. package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
  447. package/dist/editor/permission-manager/PermissionEditor.js +15 -4
  448. package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
  449. package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
  450. package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
  451. package/dist/editor/permission-manager/UserSelector.js +3 -3
  452. package/dist/editor/permission-manager/index.js +12 -3
  453. package/dist/editor/permission-manager/types.d.ts +5 -2
  454. package/dist/editor/platform.d.ts +3 -0
  455. package/dist/editor/platform.js +9 -0
  456. package/dist/editor/preview-asset-base.d.ts +9 -0
  457. package/dist/editor/preview-asset-base.js +17 -0
  458. package/dist/editor/preview-bridge.d.ts +51 -27
  459. package/dist/editor/preview-bridge.js +103 -144
  460. package/dist/editor/preview-marks.d.ts +15 -0
  461. package/dist/editor/preview-marks.js +74 -0
  462. package/dist/editor/preview-path.d.ts +12 -0
  463. package/dist/editor/preview-path.js +45 -1
  464. package/dist/editor/preview-scale.d.ts +27 -0
  465. package/dist/editor/preview-scale.js +34 -0
  466. package/dist/editor/raw-asset-base.d.ts +5 -0
  467. package/dist/editor/raw-asset-base.js +14 -0
  468. package/dist/editor/relative-time.d.ts +4 -4
  469. package/dist/editor/relative-time.js +16 -8
  470. package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
  471. package/dist/editor/schema-editor/CollectionEditor.js +361 -62
  472. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
  473. package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
  474. package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
  475. package/dist/editor/schema-editor/collection-draft.js +40 -0
  476. package/dist/editor/schema-editor/index.d.ts +1 -1
  477. package/dist/editor/schema-label.d.ts +10 -0
  478. package/dist/editor/schema-label.js +17 -0
  479. package/dist/editor/settings-conflict.d.ts +5 -0
  480. package/dist/editor/settings-conflict.js +8 -0
  481. package/dist/editor/shell/ActivityRail.d.ts +37 -0
  482. package/dist/editor/shell/ActivityRail.js +91 -0
  483. package/dist/editor/shell/EditorShell.d.ts +17 -0
  484. package/dist/editor/shell/EditorShell.js +31 -0
  485. package/dist/editor/shell/PaneLayout.d.ts +28 -0
  486. package/dist/editor/shell/PaneLayout.js +116 -0
  487. package/dist/editor/shell/SidePanelHost.d.ts +35 -0
  488. package/dist/editor/shell/SidePanelHost.js +184 -0
  489. package/dist/editor/shell/TopBar.d.ts +12 -0
  490. package/dist/editor/shell/TopBar.js +14 -0
  491. package/dist/editor/shell/host-chrome.d.ts +16 -0
  492. package/dist/editor/shell/host-chrome.js +69 -0
  493. package/dist/editor/slug.d.ts +16 -0
  494. package/dist/editor/slug.js +43 -0
  495. package/dist/editor/theme.d.ts +2 -1
  496. package/dist/editor/theme.js +314 -13
  497. package/dist/editor/unanswered.d.ts +17 -0
  498. package/dist/editor/unanswered.js +26 -0
  499. package/dist/editor/unavailable-entry-type.d.ts +20 -0
  500. package/dist/editor/unavailable-entry-type.js +28 -0
  501. package/dist/editor/undo-removal.d.ts +57 -0
  502. package/dist/editor/undo-removal.js +163 -0
  503. package/dist/editor/user-display.d.ts +4 -0
  504. package/dist/editor/user-display.js +5 -0
  505. package/dist/editor/utils/confirm-modal.d.ts +8 -0
  506. package/dist/editor/utils/confirm-modal.js +12 -0
  507. package/dist/editor/utils/editor-errors.d.ts +19 -0
  508. package/dist/editor/utils/editor-errors.js +32 -0
  509. package/dist/editor/utils/focus-return.d.ts +56 -0
  510. package/dist/editor/utils/focus-return.js +106 -0
  511. package/dist/entry-link-resolver.d.ts +11 -1
  512. package/dist/entry-link-resolver.js +65 -5
  513. package/dist/entry-schema-registry.d.ts +3 -3
  514. package/dist/entry-schema-registry.js +7 -4
  515. package/dist/entry-schema.d.ts +49 -3
  516. package/dist/entry-schema.js +18 -0
  517. package/dist/git-manager.d.ts +172 -10
  518. package/dist/git-manager.js +449 -107
  519. package/dist/github-service.d.ts +39 -2
  520. package/dist/github-service.js +101 -7
  521. package/dist/http/handler.js +74 -9
  522. package/dist/http/types.d.ts +2 -0
  523. package/dist/http/worker-not-ready.d.ts +9 -4
  524. package/dist/http/worker-not-ready.js +59 -6
  525. package/dist/index.d.ts +2 -0
  526. package/dist/index.js +3 -0
  527. package/dist/item-keys.d.ts +46 -0
  528. package/dist/item-keys.js +235 -0
  529. package/dist/operating-mode/editor-mode-check.d.ts +15 -0
  530. package/dist/operating-mode/editor-mode-check.js +24 -0
  531. package/dist/operating-mode/mode-env.d.ts +13 -14
  532. package/dist/operating-mode/mode-env.js +13 -14
  533. package/dist/operating-mode/types.d.ts +2 -2
  534. package/dist/paths/branch.d.ts +0 -1
  535. package/dist/paths/branch.js +1 -8
  536. package/dist/paths/index.d.ts +1 -1
  537. package/dist/paths/index.js +1 -1
  538. package/dist/paths/validation.js +0 -2
  539. package/dist/preview.d.ts +8 -0
  540. package/dist/preview.js +7 -0
  541. package/dist/reference-resolver.js +1 -0
  542. package/dist/resolve-canopy-user.d.ts +1 -1
  543. package/dist/resolve-canopy-user.js +1 -1
  544. package/dist/schema/meta-loader.d.ts +18 -8
  545. package/dist/schema/meta-loader.js +42 -9
  546. package/dist/schema/registry-fingerprint.d.ts +14 -0
  547. package/dist/schema/registry-fingerprint.js +63 -0
  548. package/dist/schema/resolver.d.ts +7 -4
  549. package/dist/schema/resolver.js +7 -6
  550. package/dist/schema/schema-store.d.ts +7 -10
  551. package/dist/schema/schema-store.js +13 -11
  552. package/dist/schema/schema-unavailable-error.d.ts +11 -0
  553. package/dist/schema/schema-unavailable-error.js +15 -0
  554. package/dist/schema/types.d.ts +22 -0
  555. package/dist/schema-registry-record.d.ts +35 -0
  556. package/dist/schema-registry-record.js +134 -0
  557. package/dist/server.d.ts +79 -9
  558. package/dist/server.js +62 -8
  559. package/dist/services.d.ts +33 -5
  560. package/dist/services.js +155 -37
  561. package/dist/settings-workspace.d.ts +23 -3
  562. package/dist/settings-workspace.js +159 -45
  563. package/dist/stamp-on-publish.d.ts +36 -0
  564. package/dist/stamp-on-publish.js +71 -0
  565. package/dist/static/index.d.ts +58 -5
  566. package/dist/static/index.js +133 -3
  567. package/dist/static/seo.d.ts +5 -5
  568. package/dist/static/seo.js +5 -5
  569. package/dist/submission-attribution.d.ts +8 -0
  570. package/dist/submission-attribution.js +22 -0
  571. package/dist/system-users.d.ts +12 -0
  572. package/dist/system-users.js +12 -0
  573. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  574. package/dist/task-queue/cms-task-queue.js +1 -1
  575. package/dist/task-queue/index.d.ts +1 -1
  576. package/dist/task-queue/index.js +1 -1
  577. package/dist/task-queue/task-queue.d.ts +6 -0
  578. package/dist/task-queue/task-queue.js +29 -0
  579. package/dist/task-queue/worker-status.d.ts +35 -9
  580. package/dist/task-queue/worker-status.js +84 -17
  581. package/dist/types.d.ts +90 -9
  582. package/dist/url-collision.js +3 -3
  583. package/dist/url-exclusivity-fixtures.d.ts +8 -1
  584. package/dist/url-exclusivity-fixtures.js +11 -1
  585. package/dist/user.js +2 -1
  586. package/dist/utils/atomic-write.js +2 -1
  587. package/dist/utils/base-branch.d.ts +13 -0
  588. package/dist/utils/base-branch.js +23 -0
  589. package/dist/utils/content-serialize.d.ts +15 -7
  590. package/dist/utils/content-serialize.js +353 -51
  591. package/dist/utils/content-write-lock.d.ts +6 -1
  592. package/dist/utils/content-write-lock.js +21 -6
  593. package/dist/utils/debug.d.ts +1 -1
  594. package/dist/utils/debug.js +5 -3
  595. package/dist/utils/error.js +13 -2
  596. package/dist/utils/escape-text.d.ts +7 -0
  597. package/dist/utils/escape-text.js +27 -0
  598. package/dist/utils/fs.d.ts +12 -4
  599. package/dist/utils/fs.js +18 -5
  600. package/dist/utils/git.d.ts +21 -1
  601. package/dist/utils/git.js +63 -8
  602. package/dist/utils/json-source-splice.d.ts +14 -0
  603. package/dist/utils/json-source-splice.js +120 -0
  604. package/dist/utils/markdown-body-splice.d.ts +39 -0
  605. package/dist/utils/markdown-body-splice.js +421 -0
  606. package/dist/utils/occ-json-write.js +18 -12
  607. package/dist/utils/provision-log.d.ts +25 -0
  608. package/dist/utils/provision-log.js +49 -0
  609. package/dist/utils/provisioning-lock.d.ts +32 -1
  610. package/dist/utils/provisioning-lock.js +78 -32
  611. package/dist/utils/sanitize-href.d.ts +9 -23
  612. package/dist/utils/sanitize-href.js +14 -28
  613. package/dist/utils/title-field.d.ts +10 -0
  614. package/dist/utils/title-field.js +47 -0
  615. package/dist/utils/yaml-source-splice.d.ts +58 -0
  616. package/dist/utils/yaml-source-splice.js +515 -0
  617. package/dist/validation/block-structural-keys.d.ts +1 -1
  618. package/dist/validation/block-structural-keys.js +1 -1
  619. package/dist/validation/deletion-checker.d.ts +21 -29
  620. package/dist/validation/deletion-checker.js +41 -117
  621. package/dist/validation/entry-validator.d.ts +6 -10
  622. package/dist/validation/entry-validator.js +19 -26
  623. package/dist/validation/field-traversal.d.ts +22 -0
  624. package/dist/validation/field-traversal.js +39 -8
  625. package/dist/validation/markdown-safety.d.ts +68 -0
  626. package/dist/validation/markdown-safety.js +596 -0
  627. package/dist/validation/mdx-allowlist.d.ts +55 -0
  628. package/dist/validation/mdx-allowlist.js +183 -0
  629. package/dist/validation/reference-validator.d.ts +2 -0
  630. package/dist/validation/reference-validator.js +3 -0
  631. package/dist/version.d.ts +1 -1
  632. package/dist/version.js +1 -1
  633. package/dist/worker/branch-policy.d.ts +124 -0
  634. package/dist/worker/branch-policy.js +243 -0
  635. package/dist/worker/bundle-header.d.ts +117 -0
  636. package/dist/worker/bundle-header.js +253 -0
  637. package/dist/worker/cms-worker.d.ts +236 -142
  638. package/dist/worker/cms-worker.js +772 -285
  639. package/dist/worker/gateway-egress.d.ts +43 -0
  640. package/dist/worker/gateway-egress.js +209 -0
  641. package/dist/worker/gateway-instance.d.ts +42 -0
  642. package/dist/worker/gateway-instance.js +129 -0
  643. package/dist/worker/git-process.d.ts +81 -0
  644. package/dist/worker/git-process.js +234 -0
  645. package/dist/worker/git-sync.d.ts +34 -17
  646. package/dist/worker/git-sync.js +394 -131
  647. package/dist/worker/github-auth.d.ts +9 -9
  648. package/dist/worker/github-auth.js +13 -15
  649. package/dist/worker/github-gateway-http.d.ts +62 -0
  650. package/dist/worker/github-gateway-http.js +977 -0
  651. package/dist/worker/github-gateway-wire.d.ts +590 -0
  652. package/dist/worker/github-gateway-wire.js +488 -0
  653. package/dist/worker/github-gateway.d.ts +238 -0
  654. package/dist/worker/github-gateway.js +726 -0
  655. package/dist/worker/github-mirror-upkeep.d.ts +75 -0
  656. package/dist/worker/github-mirror-upkeep.js +266 -0
  657. package/dist/worker/github-mirror.d.ts +364 -0
  658. package/dist/worker/github-mirror.js +1030 -0
  659. package/dist/worker/github-transfer.d.ts +56 -0
  660. package/dist/worker/github-transfer.js +444 -0
  661. package/dist/worker/history-rewrite.d.ts +4 -5
  662. package/dist/worker/history-rewrite.js +12 -17
  663. package/dist/worker/provisioned-workspace.d.ts +5 -5
  664. package/dist/worker/provisioned-workspace.js +5 -5
  665. package/dist/worker/rebase.d.ts +1 -1
  666. package/dist/worker/rebase.js +58 -54
  667. package/dist/worker/remote-git-maintenance.d.ts +3 -0
  668. package/dist/worker/remote-git-maintenance.js +12 -0
  669. package/dist/worker/schema-gate.d.ts +49 -0
  670. package/dist/worker/schema-gate.js +226 -0
  671. package/dist/worker/self-checks.d.ts +107 -0
  672. package/dist/worker/self-checks.js +358 -0
  673. package/dist/worker/shared-repo-git.d.ts +96 -0
  674. package/dist/worker/shared-repo-git.js +459 -0
  675. package/dist/worker/sparse-cone.d.ts +20 -0
  676. package/dist/worker/sparse-cone.js +136 -0
  677. package/dist/worker/stale-mirror.d.ts +82 -0
  678. package/dist/worker/stale-mirror.js +130 -0
  679. package/dist/worker/task-runner.d.ts +5 -3
  680. package/dist/worker/task-runner.js +287 -186
  681. package/dist/worker/worker-context.d.ts +36 -37
  682. package/package.json +35 -7
  683. package/dist/editor/EditorPanes.d.ts +0 -10
  684. package/dist/editor/EditorPanes.js +0 -98
  685. package/dist/editor/components/EditorFooter.d.ts +0 -11
  686. package/dist/editor/components/EditorFooter.js +0 -9
  687. package/dist/editor/components/EditorSidebar.d.ts +0 -67
  688. package/dist/editor/components/EditorSidebar.js +0 -22
@@ -0,0 +1,596 @@
1
+ /**
2
+ * The save-time policy that keeps code out of `markdown` and `mdx` content.
3
+ *
4
+ * MDX compiles `{expressions}`, `import`/`export` and JSX into JavaScript that runs wherever a
5
+ * body renders: a preview with the viewer's session, a server render, a CI build. A body this
6
+ * policy accepts runs only the site's own components. A field or body `markdownPolicyOf` checks as
7
+ * MDX accepts:
8
+ *
9
+ * - no `import`/`export`, and no `{…}` expression except a comment or a static literal
10
+ * (`{300}`, `{["a", "b"]}`), in text or as an attribute value; no spread attributes;
11
+ * - components by plain name (`<Callout>`, the site's own code) and HTML tags from
12
+ * `SAFE_HTML_TAGS` only, since a tag is a real element whose attributes need no expression to
13
+ * run code (`<script>`, `<iframe srcdoc>`);
14
+ * - on an HTML tag, attributes from `SAFE_HTML_ATTRIBUTES` and `aria-*` only; no event handler
15
+ * (`on…` on a tag, `onX` on a component), `dangerouslySetInnerHTML` or `srcdoc` anywhere;
16
+ * - URLs, in links, images, definitions and URL attributes, that are relative, use a scheme in
17
+ * `SAFE_URL_SCHEMES`, or are raster `data:` images; no `javascript:` or `vbscript:` value in any
18
+ * prop. React 18 renders a `javascript:` href as given.
19
+ *
20
+ * An `mdxAllow` allowlist (`mdx-allowlist.ts`) narrows this further. Other markdown renders braces
21
+ * and imports as text and runs no tag without raw HTML, so only its URLs are checked; a field with
22
+ * `executable: true` is not checked. A body is parsed with and without GFM, so `remark-gfm` cannot
23
+ * hide a construct; an MDX body that does not parse cannot be checked, so is refused.
24
+ *
25
+ * A save keeps code the stored entry already holds (from outside the CMS, or from before this
26
+ * policy) only in a field saved unchanged: code reads what surrounds it (the props beside it, its
27
+ * parent, the markup a script reads), so no smaller unit is safe to keep. Other fields stay
28
+ * editable, and removing the code is always accepted.
29
+ */
30
+ import { fromMarkdown } from 'mdast-util-from-markdown';
31
+ import { gfmFromMarkdown } from 'mdast-util-gfm';
32
+ import { mdxFromMarkdown } from 'mdast-util-mdx';
33
+ import { gfm } from 'micromark-extension-gfm';
34
+ import { mdxjs } from 'micromark-extension-mdxjs';
35
+ import { findBodyFieldName } from '../utils/body-field.js';
36
+ import { flattenGroupFields } from '../utils/flatten-group-fields.js';
37
+ import { getErrorMessage } from '../utils/error.js';
38
+ import { traverseFields } from './field-traversal.js';
39
+ import { FORBIDDEN_ATTRIBUTES, SAFE_HTML_TAGS, isComponentName, allowlistIdentity, isMarkdownField, markdownPolicyOf, resolveMdxAllowlist, } from './mdx-allowlist.js';
40
+ /** `entry:` is CanopyCMS's own link to an entry, which the site resolves to a path. */
41
+ const SAFE_URL_SCHEMES = new Set(['http', 'https', 'mailto', 'tel', 'entry']);
42
+ /** A `data:` URL is accepted only as a raster image, which no browser runs as a document. */
43
+ const SAFE_DATA_URL = /^data:image\/(?:png|gif|jpe?g|webp|avif)[;,]/i;
44
+ /**
45
+ * Attribute names, lower-cased with non-letters removed, that `SAFE_HTML_TAGS` load as a URL or
46
+ * that a component commonly passes on to one. `data` is left out: it is a URL only on `<object>`,
47
+ * which is not a safe tag, and a common component prop.
48
+ */
49
+ const URL_ATTRIBUTES = new Set([
50
+ 'action',
51
+ 'cite',
52
+ 'formaction',
53
+ 'href',
54
+ 'ping',
55
+ 'poster',
56
+ 'src',
57
+ 'srcset',
58
+ 'to',
59
+ 'url',
60
+ 'xlinkhref',
61
+ ]);
62
+ /**
63
+ * Attributes, lower-cased, that `SAFE_HTML_TAGS` may carry, plus any `aria-*`. Anything else is
64
+ * refused on a tag, because a script the site loads can give an attribute meaning: Alpine's
65
+ * `x-init`, htmx's `hx-on:click`, or a `data-*` a page script `eval`s.
66
+ */
67
+ const SAFE_HTML_ATTRIBUTES = new Set([
68
+ 'abbr',
69
+ 'align',
70
+ 'alt',
71
+ 'autoplay',
72
+ 'cite',
73
+ 'class',
74
+ 'classname',
75
+ 'colspan',
76
+ 'controls',
77
+ 'datetime',
78
+ 'decoding',
79
+ 'default',
80
+ 'dir',
81
+ 'download',
82
+ 'headers',
83
+ 'height',
84
+ 'hidden',
85
+ 'href',
86
+ 'hreflang',
87
+ 'id',
88
+ 'kind',
89
+ 'label',
90
+ 'lang',
91
+ 'loading',
92
+ 'loop',
93
+ 'media',
94
+ 'muted',
95
+ 'open',
96
+ 'playsinline',
97
+ 'poster',
98
+ 'preload',
99
+ 'rel',
100
+ 'reversed',
101
+ 'role',
102
+ 'rowspan',
103
+ 'scope',
104
+ 'sizes',
105
+ 'span',
106
+ 'src',
107
+ 'srclang',
108
+ 'srcset',
109
+ 'start',
110
+ 'style',
111
+ 'target',
112
+ 'title',
113
+ 'translate',
114
+ 'type',
115
+ 'valign',
116
+ 'value',
117
+ 'width',
118
+ ]);
119
+ function isRecord(value) {
120
+ return typeof value === 'object' && value !== null;
121
+ }
122
+ /** True when an ESTree expression is literal data: no identifier, call, function or spread. */
123
+ function isStaticValue(node) {
124
+ if (!isRecord(node))
125
+ return false;
126
+ switch (node.type) {
127
+ case 'Literal':
128
+ return true;
129
+ case 'TemplateLiteral':
130
+ return Array.isArray(node.expressions) && node.expressions.length === 0;
131
+ case 'UnaryExpression':
132
+ return ((node.operator === '-' || node.operator === '+') &&
133
+ isRecord(node.argument) &&
134
+ node.argument.type === 'Literal' &&
135
+ typeof node.argument.value === 'number');
136
+ case 'ArrayExpression':
137
+ return (Array.isArray(node.elements) &&
138
+ node.elements.every((element) => element === null || isStaticValue(element)));
139
+ case 'ObjectExpression':
140
+ return (Array.isArray(node.properties) &&
141
+ // A method or accessor's value is a function, so the value check refuses it too.
142
+ node.properties.every((property) => isRecord(property) &&
143
+ property.type === 'Property' &&
144
+ property.computed === false &&
145
+ isStaticValue(property.value)));
146
+ default:
147
+ return false;
148
+ }
149
+ }
150
+ /** The program MDX parsed an expression node's code into, if it did. */
151
+ function estreeOf(node) {
152
+ return isRecord(node.data) ? node.data.estree : undefined;
153
+ }
154
+ /**
155
+ * True when an expression's parsed program holds no code: only comments, or one static value.
156
+ * A missing program (it was not parsed) holds code as far as this check knows.
157
+ */
158
+ function isInertProgram(estree) {
159
+ if (!isRecord(estree) || !Array.isArray(estree.body))
160
+ return false;
161
+ if (estree.body.length === 0)
162
+ return true;
163
+ if (estree.body.length > 1)
164
+ return false;
165
+ const [statement] = estree.body;
166
+ return (isRecord(statement) &&
167
+ statement.type === 'ExpressionStatement' &&
168
+ isStaticValue(statement.expression));
169
+ }
170
+ /** The scheme a browser would read from `url`, lower-cased, or undefined for a relative URL. */
171
+ function urlScheme(url) {
172
+ // Browsers drop ASCII tab and newline anywhere and C0 controls and spaces at the ends;
173
+ // dropping every one of them anywhere can only find a scheme where a browser finds none.
174
+ // eslint-disable-next-line no-control-regex
175
+ const compact = url.replace(/[\u0000-\u0020\u007f]/g, '');
176
+ return /^([a-z][a-z0-9+.-]*):/i.exec(compact)?.[1]?.toLowerCase();
177
+ }
178
+ function unsafeUrlScheme(url) {
179
+ const scheme = urlScheme(url);
180
+ if (scheme === undefined || SAFE_URL_SCHEMES.has(scheme))
181
+ return undefined;
182
+ if (scheme === 'data' && SAFE_DATA_URL.test(url.trim()))
183
+ return undefined;
184
+ return scheme;
185
+ }
186
+ /**
187
+ * The scheme of a value that runs script if it reaches an `href` or `src`, which a component may
188
+ * do with any prop: checked on every string a prop holds. `data:` is left to the URL attributes,
189
+ * since a data document runs in an opaque origin and prose often starts with "Data:".
190
+ */
191
+ function scriptScheme(value) {
192
+ const scheme = urlScheme(value);
193
+ return scheme === 'javascript' || scheme === 'vbscript' ? scheme : undefined;
194
+ }
195
+ /** Every string in a static value: literals, template text, and array and object values. */
196
+ function staticStrings(node) {
197
+ if (!isRecord(node))
198
+ return [];
199
+ switch (node.type) {
200
+ case 'Program':
201
+ return Array.isArray(node.body) ? node.body.flatMap(staticStrings) : [];
202
+ case 'ExpressionStatement':
203
+ return staticStrings(node.expression);
204
+ case 'Literal':
205
+ return typeof node.value === 'string' ? [node.value] : [];
206
+ case 'TemplateLiteral':
207
+ return Array.isArray(node.quasis)
208
+ ? node.quasis.flatMap((quasi) => isRecord(quasi) && isRecord(quasi.value) && typeof quasi.value.cooked === 'string'
209
+ ? [quasi.value.cooked]
210
+ : [])
211
+ : [];
212
+ case 'ArrayExpression':
213
+ return Array.isArray(node.elements) ? node.elements.flatMap(staticStrings) : [];
214
+ case 'ObjectExpression':
215
+ return Array.isArray(node.properties)
216
+ ? node.properties.flatMap((property) => isRecord(property) ? staticStrings(property.value) : [])
217
+ : [];
218
+ default:
219
+ return [];
220
+ }
221
+ }
222
+ /** Each URL a `srcset` names: the first token of every comma-separated candidate. */
223
+ function srcsetUrls(value) {
224
+ return value
225
+ .split(',')
226
+ .map((candidate) => candidate.trim().split(/\s+/)[0] ?? '')
227
+ .filter((url) => url !== '');
228
+ }
229
+ /** Where an issue sits, as the editor shows it. */
230
+ const at = (node) => (node.position ? ` (line ${node.position.start.line})` : '');
231
+ function issue(node, message) {
232
+ return { message: `${message}${at(node)}`, line: node.position?.start.line };
233
+ }
234
+ function urlIssue(node, url, where) {
235
+ const scheme = unsafeUrlScheme(url);
236
+ if (scheme === undefined)
237
+ return undefined;
238
+ return issue(node, `The URL scheme "${scheme}:" is not allowed in ${where}; use http(s), mailto, tel, an entry link or a path on the site`);
239
+ }
240
+ /** The URLs and script schemes in one attribute value, which the base policy refuses. */
241
+ function attributeValueIssues(node, tag, attributeName, value) {
242
+ const lower = attributeName.toLowerCase();
243
+ const isUrl = URL_ATTRIBUTES.has(lower.replace(/[^a-z]/g, ''));
244
+ if (isRecord(value) && (isUrl || !isInertProgram(estreeOf(value)))) {
245
+ return [
246
+ issue(node, isUrl
247
+ ? `${attributeName} on ${tag} must be a plain "string"`
248
+ : `${attributeName} on ${tag} must be a plain value, such as "text" or {300}`),
249
+ ];
250
+ }
251
+ if (isUrl && typeof value === 'string') {
252
+ const urls = lower === 'srcset' ? srcsetUrls(value) : [value];
253
+ return urls.flatMap((url) => urlIssue(node, url, `${attributeName} on ${tag}`) ?? []);
254
+ }
255
+ const strings = typeof value === 'string' ? [value] : isRecord(value) ? staticStrings(estreeOf(value)) : [];
256
+ return strings.flatMap((text) => {
257
+ const scheme = scriptScheme(text);
258
+ return scheme === undefined
259
+ ? []
260
+ : [issue(node, `The URL scheme "${scheme}:" is not allowed in ${attributeName} on ${tag}`)];
261
+ });
262
+ }
263
+ /**
264
+ * The value an allowlist's value list matches: a string, `true` for a bare attribute, or a
265
+ * single literal expression. Undefined for anything else, which no list matches.
266
+ */
267
+ function plainValue(value) {
268
+ if (value === null || value === undefined)
269
+ return true;
270
+ if (typeof value === 'string')
271
+ return value;
272
+ const estree = isRecord(value) ? estreeOf(value) : undefined;
273
+ if (!isRecord(estree) || !Array.isArray(estree.body) || estree.body.length !== 1)
274
+ return undefined;
275
+ const [statement] = estree.body;
276
+ if (!isRecord(statement) || statement.type !== 'ExpressionStatement')
277
+ return undefined;
278
+ const expression = statement.expression;
279
+ if (!isRecord(expression) || expression.type !== 'Literal')
280
+ return undefined;
281
+ const literal = expression.value;
282
+ return typeof literal === 'string' || typeof literal === 'number' || typeof literal === 'boolean'
283
+ ? literal
284
+ : undefined;
285
+ }
286
+ /** How a refusal shows an attribute as written. */
287
+ function showAttribute(attributeName, value) {
288
+ if (value === null || value === undefined)
289
+ return attributeName;
290
+ if (typeof value === 'string')
291
+ return `${attributeName}="${value}"`;
292
+ return `${attributeName}={…}`;
293
+ }
294
+ const listOf = (names) => [...names].sort().join(', ');
295
+ /** A string allowance's `maxLength` (`null`: uncapped), or `undefined` for any other allowance. */
296
+ function stringAllowance(allowed) {
297
+ if (allowed === 'string')
298
+ return { maxLength: null };
299
+ if (isRecord(allowed) && allowed.type === 'string') {
300
+ return { maxLength: allowed.maxLength ?? null };
301
+ }
302
+ return undefined;
303
+ }
304
+ function checkJsxElement(node, allow) {
305
+ const name = node.name;
306
+ // A fragment (`<>…</>`) renders its children and nothing else.
307
+ if (name === null || name === undefined) {
308
+ return allow.fragments ? [] : [issue(node, 'Fragments (<>…</>) are not allowed here')];
309
+ }
310
+ const tag = `<${name}>`;
311
+ const isComponent = isComponentName(name);
312
+ if (!isComponent && !SAFE_HTML_TAGS.has(name)) {
313
+ return [
314
+ issue(node, name.includes('.')
315
+ ? `${tag} is not allowed: use a component by its plain name`
316
+ : `${tag} is not allowed: it is not one of the HTML tags a body may use, so use one of the site's components instead`),
317
+ ];
318
+ }
319
+ if (!isComponent && !allow.htmlTags.has(name)) {
320
+ const allowed = allow.htmlTags.size === 0 ? 'none' : listOf(allow.htmlTags);
321
+ return [issue(node, `${tag} is not allowed here; allowed HTML tags: ${allowed}`)];
322
+ }
323
+ if (isComponent && allow.components !== undefined && !allow.components.has(name)) {
324
+ return [
325
+ issue(node, allow.components.size === 0
326
+ ? `Component ${tag} is not allowed: no components are allowed here`
327
+ : `Component ${tag} is not allowed here; allowed: ${listOf(allow.components.keys())}`),
328
+ ];
329
+ }
330
+ const props = isComponent ? allow.components?.get(name) : undefined;
331
+ const issues = [];
332
+ const attributes = Array.isArray(node.attributes) ? node.attributes : [];
333
+ for (const attribute of attributes) {
334
+ if (!isRecord(attribute) ||
335
+ attribute.type !== 'mdxJsxAttribute' ||
336
+ typeof attribute.name !== 'string') {
337
+ issues.push(issue(node, `{…} spread attributes are not allowed on ${tag}`));
338
+ continue;
339
+ }
340
+ const attributeName = attribute.name;
341
+ const value = attribute.value;
342
+ const lower = attributeName.toLowerCase();
343
+ if (props !== undefined && !props.has(attributeName)) {
344
+ issues.push(issue(node, props.size === 0
345
+ ? `Prop ${attributeName} on ${tag} is not allowed: ${tag} takes no props here`
346
+ : `Prop ${attributeName} on ${tag} is not allowed here; allowed: ${listOf(props.keys())}`));
347
+ continue;
348
+ }
349
+ // A tag's `on…` attribute is a handler in any spelling; a component's prop is one by React's
350
+ // convention, so `online` or `onlyMobile` stays a plain prop.
351
+ if (isComponent ? /^on[A-Z]/.test(attributeName) : /^on/.test(lower)) {
352
+ issues.push(issue(node, `${attributeName} on ${tag} is not allowed: event handlers run code`));
353
+ continue;
354
+ }
355
+ if (FORBIDDEN_ATTRIBUTES.has(lower) ||
356
+ (!isComponent && !SAFE_HTML_ATTRIBUTES.has(lower) && !lower.startsWith('aria-'))) {
357
+ issues.push(issue(node, `${attributeName} on ${tag} is not allowed`));
358
+ continue;
359
+ }
360
+ if (isRecord(value) && !allow.expressions) {
361
+ issues.push(issue(node, `${attributeName} on ${tag} must be a plain "string": {…} values are not allowed here`));
362
+ continue;
363
+ }
364
+ const found = attributeValueIssues(node, tag, attributeName, value);
365
+ if (found.length > 0) {
366
+ issues.push(...found);
367
+ continue;
368
+ }
369
+ const values = props?.get(attributeName);
370
+ const stringOnly = stringAllowance(values);
371
+ if (stringOnly !== undefined) {
372
+ if (typeof value !== 'string') {
373
+ issues.push(issue(node, `Prop ${attributeName} on ${tag} must be a quoted string, e.g. ${attributeName}="…"`));
374
+ }
375
+ else {
376
+ const length = [...value].length;
377
+ if (stringOnly.maxLength !== null && length > stringOnly.maxLength) {
378
+ issues.push(issue(node, `Prop ${attributeName} on ${tag} must be at most ${stringOnly.maxLength} characters; it has ${length}`));
379
+ }
380
+ }
381
+ }
382
+ else if (Array.isArray(values)) {
383
+ const plain = plainValue(value);
384
+ if (plain === undefined || !values.includes(plain)) {
385
+ const allowed = values.map((v) => JSON.stringify(v)).join(', ');
386
+ issues.push(issue(node, `${showAttribute(attributeName, value)} on ${tag} is not allowed here; allowed values: ${allowed}`));
387
+ }
388
+ }
389
+ }
390
+ return issues;
391
+ }
392
+ function checkNode(node, definitions, allow) {
393
+ const issues = [];
394
+ switch (node.type) {
395
+ case 'mdxjsEsm':
396
+ issues.push(issue(node, 'import/export statements are not allowed: they run as code'));
397
+ break;
398
+ case 'mdxFlowExpression':
399
+ case 'mdxTextExpression':
400
+ if (!allow.expressions) {
401
+ issues.push(issue(node, '{…} expressions are not allowed here, not even comments or plain values'));
402
+ }
403
+ else if (!isInertProgram(estreeOf(node))) {
404
+ issues.push(issue(node, '{…} expressions are not allowed: they run as code. A comment {/* … */} or a plain value such as {" "} is fine'));
405
+ }
406
+ break;
407
+ case 'mdxJsxFlowElement':
408
+ case 'mdxJsxTextElement':
409
+ issues.push(...checkJsxElement(node, allow));
410
+ break;
411
+ case 'link':
412
+ case 'image':
413
+ case 'definition': {
414
+ const found = node.url === undefined ? undefined : urlIssue(node, node.url, URL_SITES[node.type] ?? '');
415
+ if (found)
416
+ issues.push(found);
417
+ break;
418
+ }
419
+ // A reference loads its definition's URL.
420
+ case 'linkReference':
421
+ case 'imageReference': {
422
+ const url = node.identifier === undefined ? undefined : definitions.get(node.identifier);
423
+ const found = url === undefined ? undefined : urlIssue(node, url, URL_SITES[node.type] ?? '');
424
+ if (found)
425
+ issues.push(found);
426
+ break;
427
+ }
428
+ }
429
+ for (const child of node.children ?? [])
430
+ issues.push(...checkNode(child, definitions, allow));
431
+ return issues;
432
+ }
433
+ /** How an issue names each node that carries a URL. */
434
+ const URL_SITES = {
435
+ link: 'a link',
436
+ image: 'an image',
437
+ definition: 'a definition',
438
+ linkReference: 'a link reference',
439
+ imageReference: 'an image reference',
440
+ };
441
+ /** Each definition's URL by label. The first definition of a label is the one that applies. */
442
+ function collectDefinitions(node, into = new Map()) {
443
+ if (node.type === 'definition' && node.identifier !== undefined && node.url !== undefined) {
444
+ if (!into.has(node.identifier))
445
+ into.set(node.identifier, node.url);
446
+ }
447
+ for (const child of node.children ?? [])
448
+ collectDefinitions(child, into);
449
+ return into;
450
+ }
451
+ function parse(source, dialect, withGfm) {
452
+ const extensions = [...(withGfm ? [gfm()] : []), ...(dialect === 'mdx' ? [mdxjs()] : [])];
453
+ const mdastExtensions = [
454
+ ...(withGfm ? [gfmFromMarkdown()] : []),
455
+ ...(dialect === 'mdx' ? [mdxFromMarkdown()] : []),
456
+ ];
457
+ return fromMarkdown(source, { extensions, mdastExtensions });
458
+ }
459
+ /**
460
+ * Every construct in `source` that runs code, or loads a URL that does, when it renders.
461
+ * @internal Exported for tests.
462
+ */
463
+ export function findUnsafeMarkdown(source, dialect, allow = resolveMdxAllowlist(undefined, undefined)) {
464
+ // Line endings are not part of what MDX compiles, and a save may turn CRLF into LF.
465
+ const field = source.replace(/\r\n?/g, '\n');
466
+ const parses = [];
467
+ for (const withGfm of [false, true]) {
468
+ let tree;
469
+ try {
470
+ tree = parse(field, dialect, withGfm);
471
+ }
472
+ catch (err) {
473
+ return [
474
+ { message: `This MDX does not parse, so it cannot be checked: ${getErrorMessage(err)}` },
475
+ ];
476
+ }
477
+ let found;
478
+ try {
479
+ found = checkNode(tree, collectDefinitions(tree), allow);
480
+ }
481
+ catch (err) {
482
+ // Nesting deep enough to exhaust the stack.
483
+ return [{ message: `This body is too deeply nested to check: ${getErrorMessage(err)}` }];
484
+ }
485
+ parses.push(found);
486
+ }
487
+ // Both parses report most constructs; each is reported as often as the parse that saw it most.
488
+ const id = (item) => item.message;
489
+ const [plain = [], withGfm = []] = parses;
490
+ const unmatched = new Map();
491
+ for (const item of plain)
492
+ unmatched.set(id(item), (unmatched.get(id(item)) ?? 0) + 1);
493
+ const issues = [...plain];
494
+ for (const item of withGfm) {
495
+ const count = unmatched.get(id(item)) ?? 0;
496
+ if (count > 0)
497
+ unmatched.set(id(item), count - 1);
498
+ else
499
+ issues.push(item);
500
+ }
501
+ // The same text runs differently as markdown and as MDX, and a field may hold only what its own
502
+ // allowlist accepts, so both are part of the key.
503
+ const key = `${dialect}\0${allowlistIdentity(allow)}\0${field}`;
504
+ return issues.map((item) => ({ ...item, key }));
505
+ }
506
+ /** The field's one message: its first issue, and how many more there are. */
507
+ function toFieldError(fieldPath, issues) {
508
+ const [first, ...rest] = issues;
509
+ const more = rest.length === 0 ? '' : ` (and ${rest.length} more)`;
510
+ return { fieldPath, message: `${first?.message ?? ''}${more}` };
511
+ }
512
+ function findInValue(fieldPath, value, { dialect, allow }) {
513
+ const values = Array.isArray(value) ? value : [value];
514
+ const findings = [];
515
+ values.forEach((item, index) => {
516
+ if (typeof item !== 'string' || item === '')
517
+ return;
518
+ const issues = findUnsafeMarkdown(item, dialect, allow);
519
+ if (issues.length === 0)
520
+ return;
521
+ findings.push({
522
+ fieldPath: Array.isArray(value) ? `${fieldPath}[${index}]` : fieldPath,
523
+ issues,
524
+ });
525
+ });
526
+ return findings;
527
+ }
528
+ /**
529
+ * The policy's issues in one entry's on-disk-shaped data, the body merged in under the schema's
530
+ * body field name. The body is checked as `markdownPolicyOf` says for its field and the entry's
531
+ * format, even when the schema declares no body field; it is exempt only when its field is
532
+ * `executable`. `siteAllow` is the config's `mdxAllow`, under each field's own.
533
+ */
534
+ export function findMarkdownSafetyIssues(fields, format, data, siteAllow) {
535
+ const hasBody = format === 'md' || format === 'mdx';
536
+ const bodyName = hasBody ? findBodyFieldName(fields) : undefined;
537
+ const findings = [];
538
+ if (hasBody && bodyName !== undefined) {
539
+ const found = flattenGroupFields(fields).find((field) => field.name === bodyName);
540
+ const bodyField = found !== undefined && isMarkdownField(found) ? found : undefined;
541
+ const policy = markdownPolicyOf(bodyField, siteAllow, format);
542
+ if (policy !== undefined)
543
+ findings.push(...findInValue(bodyName, data[bodyName], policy));
544
+ }
545
+ findings.push(...traverseFields(fields, data, ({ field, value, path }) => {
546
+ if (path === bodyName || !isMarkdownField(field))
547
+ return [];
548
+ const policy = markdownPolicyOf(field, siteAllow);
549
+ return policy === undefined ? [] : findInValue(path, value, policy);
550
+ }));
551
+ return findings;
552
+ }
553
+ /** A field with list and block positions dropped, so reordering items keeps a match. */
554
+ const site = (fieldPath) => fieldPath.replace(/\[\d+\]/g, '');
555
+ /**
556
+ * The field occurrence a finding stands for: its site and key, which every one of its issues
557
+ * carries, or undefined for a finding whose one issue has none, such as a body that does not parse.
558
+ */
559
+ function occurrenceOf(finding) {
560
+ const key = finding.issues[0]?.key;
561
+ return key === undefined ? undefined : `${site(finding.fieldPath)}\0${key}`;
562
+ }
563
+ /**
564
+ * Splits a save's findings into those it adds, which refuse it, and those of a field saved exactly
565
+ * as the stored entry held it, which it keeps. Fields are matched by site and key, one stored field
566
+ * for one saved field, so a second copy of a stored field is refused, as is one moved to a field of
567
+ * another name or allowlist. A finding with an unkeyed issue is never kept.
568
+ */
569
+ export function splitByStored(found, stored) {
570
+ const available = new Map();
571
+ const storedSites = new Set(stored.map((finding) => site(finding.fieldPath)));
572
+ for (const finding of stored) {
573
+ const id = occurrenceOf(finding);
574
+ if (id !== undefined)
575
+ available.set(id, (available.get(id) ?? 0) + 1);
576
+ }
577
+ const refused = [];
578
+ const kept = [];
579
+ for (const finding of found) {
580
+ const id = occurrenceOf(finding);
581
+ const count = id === undefined ? 0 : (available.get(id) ?? 0);
582
+ if (id !== undefined && count > 0) {
583
+ available.set(id, count - 1);
584
+ kept.push(toFieldError(finding.fieldPath, finding.issues));
585
+ continue;
586
+ }
587
+ const error = toFieldError(finding.fieldPath, finding.issues);
588
+ refused.push(storedSites.has(site(finding.fieldPath))
589
+ ? {
590
+ ...error,
591
+ message: `This field already holds content it refuses, so it saves only unchanged or with that content removed. ${error.message}`,
592
+ }
593
+ : error);
594
+ }
595
+ return { refused, kept };
596
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * What an MDX body may hold, as `markdown-safety.ts` enforces it and as config validation and
3
+ * the editor read it. Dependency-free, so config schemas and the client bundle can import it
4
+ * without the MDX parser.
5
+ *
6
+ * An `MdxAllowlist` only narrows the base policy: a tag outside `SAFE_HTML_TAGS`, a name that is
7
+ * not a component, and a prop the base policy refuses are config errors, and every base rule
8
+ * still runs on what the allowlist accepts.
9
+ */
10
+ import type { ContentFormat, FieldConfig, MarkdownFieldConfig, MdxAllowlist, MdxPropAllow } from '../config/types.js';
11
+ /** HTML tags an MDX body may use: content elements whose attributes carry no code. */
12
+ export declare const SAFE_HTML_TAGS: ReadonlySet<string>;
13
+ export declare function isComponentName(name: string): boolean;
14
+ /** Attribute names, lower-cased, that put markup or a document into the page. */
15
+ export declare const FORBIDDEN_ATTRIBUTES: ReadonlySet<string>;
16
+ /**
17
+ * A component prop the base policy always refuses: an event handler by React's convention
18
+ * (`onClick`, while `online` stays a plain prop), or one in `FORBIDDEN_ATTRIBUTES`.
19
+ */
20
+ export declare function isRefusedComponentProp(name: string): boolean;
21
+ /**
22
+ * An allowlist with the defaults filled in. `components` undefined: any component; a component's
23
+ * props undefined: any prop.
24
+ */
25
+ export interface ResolvedMdxAllowlist {
26
+ components: ReadonlyMap<string, ReadonlyMap<string, MdxPropAllow> | undefined> | undefined;
27
+ htmlTags: ReadonlySet<string>;
28
+ expressions: boolean;
29
+ fragments: boolean;
30
+ }
31
+ /**
32
+ * A string two allowlists share only if they accept the same MDX. Two spellings of one allowlist
33
+ * (value order, the full tag set listed out) can differ, which only ever refuses keeping content.
34
+ */
35
+ export declare function allowlistIdentity(allow: ResolvedMdxAllowlist): string;
36
+ /** Each key the field sets replaces the site's; a key neither sets keeps the base policy. */
37
+ export declare function resolveMdxAllowlist(field: MdxAllowlist | undefined, site: MdxAllowlist | undefined): ResolvedMdxAllowlist;
38
+ export declare function isMarkdownField(field: FieldConfig): field is MarkdownFieldConfig;
39
+ /** How a field's content is checked: as markdown or MDX, and what MDX it accepts. */
40
+ export interface MarkdownPolicy {
41
+ dialect: 'md' | 'mdx';
42
+ allow: ResolvedMdxAllowlist;
43
+ }
44
+ /**
45
+ * The policy the server enforces and the editor follows, or undefined for an `executable` field. A
46
+ * field is MDX when typed `mdx` or set `renderAs: 'mdx'`. An entry's body (`bodyFormat` given, its
47
+ * field possibly undeclared) follows the entry instead: MDX in an `mdx` entry, and in an `md` entry
48
+ * only with `renderAs: 'mdx'`, since a site renders an `md` file as markdown.
49
+ */
50
+ export declare function markdownPolicyOf(field: MarkdownFieldConfig | undefined, site: MdxAllowlist | undefined, bodyFormat?: ContentFormat): MarkdownPolicy | undefined;
51
+ /**
52
+ * Why a markdown or mdx field's `renderAs`, `mdxAllow` and `executable` contradict each other, or
53
+ * undefined. An allowlist that cannot apply would look like protection it is not.
54
+ */
55
+ export declare function markdownFieldOptionsError(field: MarkdownFieldConfig): string | undefined;