@blokkli/editor 1.4.0-alpha.0 → 2.0.0-alpha.1

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 (447) hide show
  1. package/dist/module.d.mts +12 -125
  2. package/dist/module.json +4 -4
  3. package/dist/module.mjs +1853 -1135
  4. package/dist/modules/drupal/adapter/index.d.mts +6 -0
  5. package/dist/modules/drupal/adapter/index.mjs +762 -0
  6. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliEditState.graphql +44 -0
  7. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliMutatedField.graphql +11 -0
  8. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliMutationItem.graphql +9 -0
  9. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliMutationResult.graphql +7 -0
  10. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliViolation.graphql +7 -0
  11. package/dist/modules/drupal/graphql/base/query.pbConfig.graphql +96 -0
  12. package/dist/modules/drupal/graphql/base/query.pbEditState.graphql +15 -0
  13. package/dist/modules/drupal/graphql/features/conversions.graphql +44 -0
  14. package/dist/modules/drupal/graphql/features/import-existing.graphql +34 -0
  15. package/dist/{runtime/adapter/drupal/graphql → modules/drupal/graphql/features}/library.graphql +17 -0
  16. package/dist/modules/drupal/graphql/features/media-library.graphql +28 -0
  17. package/dist/modules/drupal/graphql/features/preview-grant.graphql +13 -0
  18. package/dist/modules/drupal/graphql/features/publish.graphql +15 -0
  19. package/dist/modules/drupal/graphql/features/publishNew.graphql +59 -0
  20. package/dist/modules/drupal/graphql/mutations/add.graphql +25 -0
  21. package/dist/modules/drupal/graphql/mutations/add_clipboard_text.graphql +25 -0
  22. package/dist/modules/drupal/graphql/mutations/add_entity_reference.graphql +31 -0
  23. package/dist/modules/drupal/graphql/mutations/add_entity_reference_multiple.graphql +25 -0
  24. package/dist/modules/drupal/graphql/mutations/add_file.graphql +27 -0
  25. package/dist/modules/drupal/graphql/mutations/add_image.graphql +27 -0
  26. package/dist/modules/drupal/graphql/mutations/add_video_remote.graphql +25 -0
  27. package/dist/modules/drupal/graphql/mutations/bulk_update_behavior_settings.graphql +15 -0
  28. package/dist/modules/drupal/graphql/mutations/duplicate.graphql +33 -0
  29. package/dist/modules/drupal/graphql/mutations/move.graphql +25 -0
  30. package/dist/modules/drupal/graphql/mutations/move_multiple.graphql +25 -0
  31. package/dist/modules/drupal/graphql/mutations/redo.graphql +14 -0
  32. package/dist/modules/drupal/graphql/mutations/remove.graphql +15 -0
  33. package/dist/modules/drupal/graphql/mutations/remove_multiple.graphql +15 -0
  34. package/dist/modules/drupal/graphql/mutations/replace_host_entity_media.graphql +20 -0
  35. package/dist/modules/drupal/graphql/mutations/replace_media.graphql +22 -0
  36. package/dist/modules/drupal/graphql/mutations/revertAllChanges.graphql +14 -0
  37. package/dist/modules/drupal/graphql/mutations/setHistoryIndex.graphql +15 -0
  38. package/dist/modules/drupal/graphql/mutations/setMutationStatus.graphql +16 -0
  39. package/dist/modules/drupal/graphql/mutations/takeOwnership.graphql +14 -0
  40. package/dist/modules/drupal/graphql/mutations/undo.graphql +14 -0
  41. package/dist/modules/drupal/graphql/mutations/update_behavior_setting.graphql +23 -0
  42. package/dist/modules/drupal/graphql/mutations/update_field_value.graphql +22 -0
  43. package/dist/modules/drupal/graphql/mutations/update_host_entity_field_value.graphql +20 -0
  44. package/dist/modules/drupal/index.d.mts +10 -0
  45. package/dist/modules/drupal/index.mjs +151 -0
  46. package/dist/runtime/adapter/index.d.ts +30 -4
  47. package/dist/runtime/blokkliPlugins/AddAction/index.vue +39 -54
  48. package/dist/runtime/blokkliPlugins/AddAction/index.vue.d.ts +26 -0
  49. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +38 -64
  50. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue.d.ts +12 -0
  51. package/dist/runtime/blokkliPlugins/ContextMenu/index.vue +19 -30
  52. package/dist/runtime/blokkliPlugins/ContextMenu/index.vue.d.ts +37 -0
  53. package/dist/runtime/blokkliPlugins/DebugOverlay/index.vue +15 -23
  54. package/dist/runtime/blokkliPlugins/DebugOverlay/index.vue.d.ts +21 -0
  55. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue +27 -44
  56. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue.d.ts +41 -0
  57. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +39 -85
  58. package/dist/runtime/blokkliPlugins/ItemAction/index.vue.d.ts +83 -0
  59. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue +22 -26
  60. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue.d.ts +17 -0
  61. package/dist/runtime/blokkliPlugins/MenuButton/index.vue +30 -38
  62. package/dist/runtime/blokkliPlugins/MenuButton/index.vue.d.ts +32 -0
  63. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +146 -211
  64. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue.d.ts +91 -0
  65. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +95 -139
  66. package/dist/runtime/blokkliPlugins/Sidebar/index.vue.d.ts +85 -0
  67. package/dist/runtime/blokkliPlugins/ToolbarButton/index.vue +38 -57
  68. package/dist/runtime/blokkliPlugins/ToolbarButton/index.vue.d.ts +48 -0
  69. package/dist/runtime/blokkliPlugins/TourItem/index.vue +20 -29
  70. package/dist/runtime/blokkliPlugins/TourItem/index.vue.d.ts +20 -0
  71. package/dist/runtime/blokkliPlugins/ViewOption/index.vue +45 -59
  72. package/dist/runtime/blokkliPlugins/ViewOption/index.vue.d.ts +39 -0
  73. package/dist/runtime/components/Blocks/Fragment/index.vue +13 -17
  74. package/dist/runtime/components/Blocks/Fragment/index.vue.d.ts +6 -0
  75. package/dist/runtime/components/Blocks/FromLibrary/index.vue +23 -30
  76. package/dist/runtime/components/Blocks/FromLibrary/index.vue.d.ts +6 -0
  77. package/dist/runtime/components/BlokkliEditable.vue +29 -49
  78. package/dist/runtime/components/BlokkliEditable.vue.d.ts +34 -0
  79. package/dist/runtime/components/BlokkliField.vue +100 -159
  80. package/dist/runtime/components/BlokkliField.vue.d.ts +133 -0
  81. package/dist/runtime/components/BlokkliItem.vue +43 -66
  82. package/dist/runtime/components/BlokkliItem.vue.d.ts +26 -0
  83. package/dist/runtime/components/BlokkliProvider.vue +50 -87
  84. package/dist/runtime/components/BlokkliProvider.vue.d.ts +51 -0
  85. package/dist/runtime/components/Edit/Actions/index.vue +116 -164
  86. package/dist/runtime/components/Edit/Actions/index.vue.d.ts +2 -0
  87. package/dist/runtime/components/Edit/AddListItem/index.vue +45 -66
  88. package/dist/runtime/components/Edit/AddListItem/index.vue.d.ts +28 -0
  89. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +52 -88
  90. package/dist/runtime/components/Edit/AnimationCanvas/index.vue.d.ts +2 -0
  91. package/dist/runtime/components/Edit/AppMenu/index.vue +12 -15
  92. package/dist/runtime/components/Edit/AppMenu/index.vue.d.ts +2 -0
  93. package/dist/runtime/components/Edit/BlockProxy/index.vue +48 -84
  94. package/dist/runtime/components/Edit/BlockProxy/index.vue.d.ts +10 -0
  95. package/dist/runtime/components/Edit/BlokkliErrorBoundary.vue +16 -20
  96. package/dist/runtime/components/Edit/BlokkliErrorBoundary.vue.d.ts +23 -0
  97. package/dist/runtime/components/Edit/Dialog/index.vue +67 -103
  98. package/dist/runtime/components/Edit/Dialog/index.vue.d.ts +44 -0
  99. package/dist/runtime/components/Edit/DragInteractions/index.vue +219 -333
  100. package/dist/runtime/components/Edit/DragInteractions/index.vue.d.ts +2 -0
  101. package/dist/runtime/components/Edit/DraggableList.vue +82 -125
  102. package/dist/runtime/components/Edit/DraggableList.vue.d.ts +27 -0
  103. package/dist/runtime/components/Edit/EditIndicator.vue +34 -46
  104. package/dist/runtime/components/Edit/EditIndicator.vue.d.ts +11 -0
  105. package/dist/runtime/components/Edit/EditProvider.vue +144 -142
  106. package/dist/runtime/components/Edit/EditProvider.vue.d.ts +26 -0
  107. package/dist/runtime/components/Edit/Features/AddList/index.vue +90 -117
  108. package/dist/runtime/components/Edit/Features/AddList/index.vue.d.ts +2 -0
  109. package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +43 -63
  110. package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue.d.ts +6 -0
  111. package/dist/runtime/components/Edit/Features/Artboard/Scrollbar/index.vue +18 -23
  112. package/dist/runtime/components/Edit/Features/Artboard/Scrollbar/index.vue.d.ts +7 -0
  113. package/dist/runtime/components/Edit/Features/Artboard/index.vue +175 -223
  114. package/dist/runtime/components/Edit/Features/Artboard/index.vue.d.ts +2 -0
  115. package/dist/runtime/components/Edit/Features/Assistant/Overlay/ResultMarkup/index.vue +7 -7
  116. package/dist/runtime/components/Edit/Features/Assistant/Overlay/ResultMarkup/index.vue.d.ts +6 -0
  117. package/dist/runtime/components/Edit/Features/Assistant/Overlay/index.vue +39 -52
  118. package/dist/runtime/components/Edit/Features/Assistant/Overlay/index.vue.d.ts +8 -0
  119. package/dist/runtime/components/Edit/Features/Assistant/index.vue +31 -40
  120. package/dist/runtime/components/Edit/Features/Assistant/index.vue.d.ts +2 -0
  121. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +225 -326
  122. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue.d.ts +2 -0
  123. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/File.vue +36 -44
  124. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/File.vue.d.ts +3 -0
  125. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/Video.vue +33 -35
  126. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/Video.vue.d.ts +3 -0
  127. package/dist/runtime/components/Edit/Features/Clipboard/List/index.vue +13 -21
  128. package/dist/runtime/components/Edit/Features/Clipboard/List/index.vue.d.ts +10 -0
  129. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +226 -297
  130. package/dist/runtime/components/Edit/Features/Clipboard/index.vue.d.ts +2 -0
  131. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +24 -34
  132. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue.d.ts +22 -0
  133. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +146 -195
  134. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue.d.ts +6 -0
  135. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +21 -26
  136. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue.d.ts +2 -0
  137. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue +9 -12
  138. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue.d.ts +8 -0
  139. package/dist/runtime/components/Edit/Features/Comments/Comment/index.vue +20 -28
  140. package/dist/runtime/components/Edit/Features/Comments/Comment/index.vue.d.ts +23 -0
  141. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue +30 -42
  142. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue.d.ts +19 -0
  143. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue +70 -100
  144. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue.d.ts +18 -0
  145. package/dist/runtime/components/Edit/Features/Comments/index.vue +37 -48
  146. package/dist/runtime/components/Edit/Features/Comments/index.vue.d.ts +2 -0
  147. package/dist/runtime/components/Edit/Features/Conversions/index.vue +40 -56
  148. package/dist/runtime/components/Edit/Features/Conversions/index.vue.d.ts +2 -0
  149. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +37 -50
  150. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue.d.ts +2 -0
  151. package/dist/runtime/components/Edit/Features/Debug/Viewport/index.vue +35 -44
  152. package/dist/runtime/components/Edit/Features/Debug/Viewport/index.vue.d.ts +2 -0
  153. package/dist/runtime/components/Edit/Features/Debug/index.vue +43 -57
  154. package/dist/runtime/components/Edit/Features/Debug/index.vue.d.ts +2 -0
  155. package/dist/runtime/components/Edit/Features/Delete/index.vue +31 -52
  156. package/dist/runtime/components/Edit/Features/Delete/index.vue.d.ts +2 -0
  157. package/dist/runtime/components/Edit/Features/Diff/DiffView/index.vue +68 -107
  158. package/dist/runtime/components/Edit/Features/Diff/DiffView/index.vue.d.ts +2 -0
  159. package/dist/runtime/components/Edit/Features/Diff/index.vue +17 -19
  160. package/dist/runtime/components/Edit/Features/Diff/index.vue.d.ts +2 -0
  161. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +193 -337
  162. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue.d.ts +27 -0
  163. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +1 -1
  164. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +391 -644
  165. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue.d.ts +156 -0
  166. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +197 -323
  167. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue.d.ts +2 -0
  168. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +49 -71
  169. package/dist/runtime/components/Edit/Features/Duplicate/index.vue.d.ts +2 -0
  170. package/dist/runtime/components/Edit/Features/Edit/index.vue +41 -71
  171. package/dist/runtime/components/Edit/Features/Edit/index.vue.d.ts +2 -0
  172. package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue +35 -51
  173. package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue.d.ts +11 -0
  174. package/dist/runtime/components/Edit/Features/EditForm/index.vue +104 -140
  175. package/dist/runtime/components/Edit/Features/EditForm/index.vue.d.ts +2 -0
  176. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Contenteditable/index.vue +18 -25
  177. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Contenteditable/index.vue.d.ts +12 -0
  178. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +34 -50
  179. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue.d.ts +16 -0
  180. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue +40 -51
  181. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue.d.ts +16 -0
  182. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +145 -207
  183. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue.d.ts +15 -0
  184. package/dist/runtime/components/Edit/Features/EditableField/index.vue +90 -143
  185. package/dist/runtime/components/Edit/Features/EditableField/index.vue.d.ts +2 -0
  186. package/dist/runtime/components/Edit/Features/EditableMask/index.vue +28 -36
  187. package/dist/runtime/components/Edit/Features/EditableMask/index.vue.d.ts +2 -0
  188. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +49 -58
  189. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue.d.ts +2 -0
  190. package/dist/runtime/components/Edit/Features/Exit/index.vue +16 -20
  191. package/dist/runtime/components/Edit/Features/Exit/index.vue.d.ts +2 -0
  192. package/dist/runtime/components/Edit/Features/FieldAreas/Overlay/index.vue +4 -15
  193. package/dist/runtime/components/Edit/Features/FieldAreas/Overlay/index.vue.d.ts +2 -0
  194. package/dist/runtime/components/Edit/Features/FieldAreas/index.vue +19 -21
  195. package/dist/runtime/components/Edit/Features/FieldAreas/index.vue.d.ts +2 -0
  196. package/dist/runtime/components/Edit/Features/Fragments/Dialog/Item/index.vue +29 -36
  197. package/dist/runtime/components/Edit/Features/Fragments/Dialog/Item/index.vue.d.ts +8 -0
  198. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue +82 -99
  199. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue.d.ts +12 -0
  200. package/dist/runtime/components/Edit/Features/Fragments/index.vue +41 -51
  201. package/dist/runtime/components/Edit/Features/Fragments/index.vue.d.ts +2 -0
  202. package/dist/runtime/components/Edit/Features/Grid/index.vue +17 -20
  203. package/dist/runtime/components/Edit/Features/Grid/index.vue.d.ts +2 -0
  204. package/dist/runtime/components/Edit/Features/Help/Shortcuts/index.vue +24 -35
  205. package/dist/runtime/components/Edit/Features/Help/Shortcuts/index.vue.d.ts +2 -0
  206. package/dist/runtime/components/Edit/Features/Help/index.vue +17 -21
  207. package/dist/runtime/components/Edit/Features/Help/index.vue.d.ts +2 -0
  208. package/dist/runtime/components/Edit/Features/History/List/index.vue +46 -67
  209. package/dist/runtime/components/Edit/Features/History/List/index.vue.d.ts +5 -0
  210. package/dist/runtime/components/Edit/Features/History/index.vue +54 -69
  211. package/dist/runtime/components/Edit/Features/History/index.vue.d.ts +2 -0
  212. package/dist/runtime/components/Edit/Features/ImportExisting/Dialog/index.vue +48 -66
  213. package/dist/runtime/components/Edit/Features/ImportExisting/Dialog/index.vue.d.ts +14 -0
  214. package/dist/runtime/components/Edit/Features/ImportExisting/index.vue +38 -54
  215. package/dist/runtime/components/Edit/Features/ImportExisting/index.vue.d.ts +2 -0
  216. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +88 -126
  217. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue.d.ts +13 -0
  218. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/Item/index.vue +33 -35
  219. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/Item/index.vue.d.ts +9 -0
  220. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +119 -146
  221. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue.d.ts +12 -0
  222. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +37 -47
  223. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue.d.ts +12 -0
  224. package/dist/runtime/components/Edit/Features/Library/index.vue +85 -117
  225. package/dist/runtime/components/Edit/Features/Library/index.vue.d.ts +2 -0
  226. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/Item.vue +13 -19
  227. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/Item.vue.d.ts +19 -0
  228. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +76 -120
  229. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue.d.ts +6 -0
  230. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +107 -140
  231. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue.d.ts +2 -0
  232. package/dist/runtime/components/Edit/Features/MediaLibrary/types.d.ts +1 -1
  233. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +128 -188
  234. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue.d.ts +12 -0
  235. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +42 -57
  236. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue.d.ts +2 -0
  237. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue +27 -34
  238. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue.d.ts +14 -0
  239. package/dist/runtime/components/Edit/Features/Options/Form/Checkboxes/index.vue +55 -75
  240. package/dist/runtime/components/Edit/Features/Options/Form/Checkboxes/index.vue.d.ts +24 -0
  241. package/dist/runtime/components/Edit/Features/Options/Form/Color/index.vue +18 -21
  242. package/dist/runtime/components/Edit/Features/Options/Form/Color/index.vue.d.ts +12 -0
  243. package/dist/runtime/components/Edit/Features/Options/Form/DateTimeLocal/index.vue +36 -0
  244. package/dist/runtime/components/Edit/Features/Options/Form/DateTimeLocal/index.vue.d.ts +20 -0
  245. package/dist/runtime/components/Edit/Features/Options/Form/Group.vue +7 -9
  246. package/dist/runtime/components/Edit/Features/Options/Form/Group.vue.d.ts +29 -0
  247. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +87 -93
  248. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue.d.ts +14 -0
  249. package/dist/runtime/components/Edit/Features/Options/Form/Number/index.vue +31 -45
  250. package/dist/runtime/components/Edit/Features/Options/Form/Number/index.vue.d.ts +21 -0
  251. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue +54 -78
  252. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue.d.ts +30 -0
  253. package/dist/runtime/components/Edit/Features/Options/Form/Range/index.vue +23 -33
  254. package/dist/runtime/components/Edit/Features/Options/Form/Range/index.vue.d.ts +18 -0
  255. package/dist/runtime/components/Edit/Features/Options/Form/Text/index.vue +17 -26
  256. package/dist/runtime/components/Edit/Features/Options/Form/Text/index.vue.d.ts +17 -0
  257. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +183 -252
  258. package/dist/runtime/components/Edit/Features/Options/Form/index.vue.d.ts +9 -0
  259. package/dist/runtime/components/Edit/Features/Options/index.vue +38 -66
  260. package/dist/runtime/components/Edit/Features/Options/index.vue.d.ts +2 -0
  261. package/dist/runtime/components/Edit/Features/Ownership/index.vue +26 -33
  262. package/dist/runtime/components/Edit/Features/Ownership/index.vue.d.ts +2 -0
  263. package/dist/runtime/components/Edit/Features/Preview/index.vue +22 -27
  264. package/dist/runtime/components/Edit/Features/Preview/index.vue.d.ts +2 -0
  265. package/dist/runtime/components/Edit/Features/PreviewGrant/QrCode/index.vue +11 -15
  266. package/dist/runtime/components/Edit/Features/PreviewGrant/QrCode/index.vue.d.ts +5 -0
  267. package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue +31 -36
  268. package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue.d.ts +2 -0
  269. package/dist/runtime/components/Edit/Features/ProxyView/index.vue +18 -20
  270. package/dist/runtime/components/Edit/Features/ProxyView/index.vue.d.ts +2 -0
  271. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue +118 -0
  272. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue.d.ts +18 -0
  273. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +251 -0
  274. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue.d.ts +19 -0
  275. package/dist/runtime/components/Edit/Features/Publish/Dialog/types.d.ts +7 -0
  276. package/dist/runtime/components/Edit/Features/Publish/index.vue +70 -74
  277. package/dist/runtime/components/Edit/Features/Publish/index.vue.d.ts +2 -0
  278. package/dist/runtime/components/Edit/Features/ResponsivePreview/Frame/index.vue +48 -54
  279. package/dist/runtime/components/Edit/Features/ResponsivePreview/Frame/index.vue.d.ts +27 -0
  280. package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue +77 -103
  281. package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue.d.ts +2 -0
  282. package/dist/runtime/components/Edit/Features/Revert/index.vue +27 -32
  283. package/dist/runtime/components/Edit/Features/Revert/index.vue.d.ts +2 -0
  284. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue +66 -87
  285. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue.d.ts +17 -0
  286. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue +89 -139
  287. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue.d.ts +18 -0
  288. package/dist/runtime/components/Edit/Features/Search/Overlay/index.vue +79 -108
  289. package/dist/runtime/components/Edit/Features/Search/Overlay/index.vue.d.ts +12 -0
  290. package/dist/runtime/components/Edit/Features/Search/index.vue +30 -37
  291. package/dist/runtime/components/Edit/Features/Search/index.vue.d.ts +2 -0
  292. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +67 -103
  293. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue.d.ts +9 -0
  294. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +28 -36
  295. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue.d.ts +5 -0
  296. package/dist/runtime/components/Edit/Features/Selection/index.vue +131 -217
  297. package/dist/runtime/components/Edit/Features/Selection/index.vue.d.ts +2 -0
  298. package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue +50 -81
  299. package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue.d.ts +9 -0
  300. package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +73 -117
  301. package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue.d.ts +6 -0
  302. package/dist/runtime/components/Edit/Features/Settings/index.vue +41 -53
  303. package/dist/runtime/components/Edit/Features/Settings/index.vue.d.ts +2 -0
  304. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +65 -101
  305. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue.d.ts +15 -0
  306. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue +71 -99
  307. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue.d.ts +12 -0
  308. package/dist/runtime/components/Edit/Features/Structure/List/index.vue +17 -26
  309. package/dist/runtime/components/Edit/Features/Structure/List/index.vue.d.ts +12 -0
  310. package/dist/runtime/components/Edit/Features/Structure/index.vue +31 -40
  311. package/dist/runtime/components/Edit/Features/Structure/index.vue.d.ts +2 -0
  312. package/dist/runtime/components/Edit/Features/Theme/Color/index.vue +32 -53
  313. package/dist/runtime/components/Edit/Features/Theme/Color/index.vue.d.ts +7 -0
  314. package/dist/runtime/components/Edit/Features/Theme/GeneratedCode/index.vue +7 -10
  315. package/dist/runtime/components/Edit/Features/Theme/GeneratedCode/index.vue.d.ts +2 -0
  316. package/dist/runtime/components/Edit/Features/Theme/index.vue +49 -63
  317. package/dist/runtime/components/Edit/Features/Theme/index.vue.d.ts +2 -0
  318. package/dist/runtime/components/Edit/Features/TouchActionBar/Bar/index.vue +9 -10
  319. package/dist/runtime/components/Edit/Features/TouchActionBar/Bar/index.vue.d.ts +12 -0
  320. package/dist/runtime/components/Edit/Features/TouchActionBar/index.vue +16 -19
  321. package/dist/runtime/components/Edit/Features/TouchActionBar/index.vue.d.ts +2 -0
  322. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue +117 -172
  323. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue.d.ts +6 -0
  324. package/dist/runtime/components/Edit/Features/Tour/Popup/index.vue +8 -10
  325. package/dist/runtime/components/Edit/Features/Tour/Popup/index.vue.d.ts +8 -0
  326. package/dist/runtime/components/Edit/Features/Tour/index.vue +21 -25
  327. package/dist/runtime/components/Edit/Features/Tour/index.vue.d.ts +2 -0
  328. package/dist/runtime/components/Edit/Features/Transform/index.vue +80 -120
  329. package/dist/runtime/components/Edit/Features/Transform/index.vue.d.ts +2 -0
  330. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue +20 -28
  331. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue.d.ts +6 -0
  332. package/dist/runtime/components/Edit/Features/Translations/index.vue +96 -139
  333. package/dist/runtime/components/Edit/Features/Translations/index.vue.d.ts +2 -0
  334. package/dist/runtime/components/Edit/Features/Validations/Overlay/Item.vue +21 -35
  335. package/dist/runtime/components/Edit/Features/Validations/Overlay/Item.vue.d.ts +6 -0
  336. package/dist/runtime/components/Edit/Features/Validations/Overlay/index.vue +30 -39
  337. package/dist/runtime/components/Edit/Features/Validations/Overlay/index.vue.d.ts +6 -0
  338. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue +20 -28
  339. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue.d.ts +9 -0
  340. package/dist/runtime/components/Edit/Features/Validations/index.vue +26 -32
  341. package/dist/runtime/components/Edit/Features/Validations/index.vue.d.ts +2 -0
  342. package/dist/runtime/components/Edit/Features/index.vue +33 -52
  343. package/dist/runtime/components/Edit/Features/index.vue.d.ts +6 -0
  344. package/dist/runtime/components/Edit/Form/Group/index.vue +23 -0
  345. package/dist/runtime/components/Edit/Form/Group/index.vue.d.ts +20 -0
  346. package/dist/runtime/components/Edit/Form/Item/index.vue +5 -0
  347. package/dist/runtime/components/Edit/Form/Item/index.vue.d.ts +14 -0
  348. package/dist/runtime/components/Edit/Form/Textarea/index.vue +27 -0
  349. package/dist/runtime/components/Edit/Form/Textarea/index.vue.d.ts +16 -0
  350. package/dist/runtime/components/Edit/Form/Toggle/index.vue +21 -0
  351. package/dist/runtime/components/Edit/Form/Toggle/index.vue.d.ts +14 -0
  352. package/dist/runtime/components/Edit/FormOverlay/Header/index.vue +11 -22
  353. package/dist/runtime/components/Edit/FormOverlay/Header/index.vue.d.ts +18 -0
  354. package/dist/runtime/components/Edit/FormOverlay/index.vue +15 -21
  355. package/dist/runtime/components/Edit/FormOverlay/index.vue.d.ts +25 -0
  356. package/dist/runtime/components/Edit/Highlight/index.vue +31 -70
  357. package/dist/runtime/components/Edit/Highlight/index.vue.d.ts +20 -0
  358. package/dist/runtime/components/Edit/Icon/index.vue +11 -14
  359. package/dist/runtime/components/Edit/Icon/index.vue.d.ts +7 -0
  360. package/dist/runtime/components/Edit/InfoBox/index.vue +5 -6
  361. package/dist/runtime/components/Edit/InfoBox/index.vue.d.ts +5 -0
  362. package/dist/runtime/components/Edit/ItemIcon/index.vue +13 -13
  363. package/dist/runtime/components/Edit/ItemIcon/index.vue.d.ts +6 -0
  364. package/dist/runtime/components/Edit/Loading/index.vue +8 -9
  365. package/dist/runtime/components/Edit/Loading/index.vue.d.ts +6 -0
  366. package/dist/runtime/components/Edit/Messages/Item/index.vue +30 -41
  367. package/dist/runtime/components/Edit/Messages/Item/index.vue.d.ts +11 -0
  368. package/dist/runtime/components/Edit/Messages/index.vue +13 -17
  369. package/dist/runtime/components/Edit/Messages/index.vue.d.ts +2 -0
  370. package/dist/runtime/components/Edit/Pagination/index.vue +19 -0
  371. package/dist/runtime/components/Edit/Pagination/index.vue.d.ts +12 -0
  372. package/dist/runtime/components/Edit/PreviewProvider.vue +123 -177
  373. package/dist/runtime/components/Edit/PreviewProvider.vue.d.ts +24 -0
  374. package/dist/runtime/components/Edit/RelativeTime/index.vue +19 -25
  375. package/dist/runtime/components/Edit/RelativeTime/index.vue.d.ts +15 -0
  376. package/dist/runtime/components/Edit/Resizable/index.vue +45 -55
  377. package/dist/runtime/components/Edit/Resizable/index.vue.d.ts +13 -0
  378. package/dist/runtime/components/Edit/ScaleToFit/index.vue +49 -36
  379. package/dist/runtime/components/Edit/ScaleToFit/index.vue.d.ts +15 -0
  380. package/dist/runtime/components/Edit/ScrollBoundary/index.vue +11 -27
  381. package/dist/runtime/components/Edit/ScrollBoundary/index.vue.d.ts +23 -0
  382. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +47 -59
  383. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue.d.ts +20 -0
  384. package/dist/runtime/components/Edit/Sortli/index.vue +45 -59
  385. package/dist/runtime/components/Edit/Sortli/index.vue.d.ts +14 -0
  386. package/dist/runtime/components/Edit/SystemRequirements/index.vue +29 -43
  387. package/dist/runtime/components/Edit/SystemRequirements/index.vue.d.ts +2 -0
  388. package/dist/runtime/components/Edit/Toolbar/index.vue +26 -41
  389. package/dist/runtime/components/Edit/Toolbar/index.vue.d.ts +6 -0
  390. package/dist/runtime/components/Edit/ViewportBlockingRect/index.vue +29 -51
  391. package/dist/runtime/components/Edit/ViewportBlockingRect/index.vue.d.ts +20 -0
  392. package/dist/runtime/components/Edit/index.d.ts +6 -1
  393. package/dist/runtime/components/Edit/index.js +11 -1
  394. package/dist/runtime/composables/defineBlokkli.d.ts +3 -3
  395. package/dist/runtime/composables/defineBlokkli.js +40 -27
  396. package/dist/runtime/composables/defineBlokkliFeature.d.ts +1 -1
  397. package/dist/runtime/composables/defineBlokkliFeature.js +1 -1
  398. package/dist/runtime/composables/defineBlokkliFragment.d.ts +2 -2
  399. package/dist/runtime/composables/defineBlokkliFragment.js +16 -24
  400. package/dist/runtime/css/output.css +1 -1
  401. package/dist/runtime/helpers/definitionProvider.d.ts +18 -0
  402. package/dist/runtime/helpers/definitionProvider.js +96 -0
  403. package/dist/runtime/helpers/domProvider.d.ts +2 -1
  404. package/dist/runtime/helpers/domProvider.js +6 -3
  405. package/dist/runtime/helpers/editComponents/index.d.ts +2 -0
  406. package/dist/runtime/helpers/editComponents/index.js +10 -0
  407. package/dist/runtime/helpers/featuresProvider.d.ts +3 -2
  408. package/dist/runtime/helpers/featuresProvider.js +20 -11
  409. package/dist/runtime/helpers/frameEventBus.d.ts +1 -1
  410. package/dist/runtime/helpers/imports/index.d.ts +1 -0
  411. package/dist/runtime/helpers/imports/index.js +44 -0
  412. package/dist/runtime/helpers/index.d.ts +1 -0
  413. package/dist/runtime/helpers/index.js +11 -8
  414. package/dist/runtime/helpers/runtimeHelpers/index.d.ts +28 -2
  415. package/dist/runtime/helpers/runtimeHelpers/index.js +96 -10
  416. package/dist/runtime/helpers/stateProvider.d.ts +1 -1
  417. package/dist/runtime/helpers/storageProvider.js +1 -1
  418. package/dist/runtime/helpers/textProvider.d.ts +1 -1
  419. package/dist/runtime/helpers/textProvider.js +2 -2
  420. package/dist/runtime/helpers/themeProvider.js +5 -2
  421. package/dist/runtime/helpers/transform.d.ts +1 -1
  422. package/dist/runtime/helpers/typesProvider.d.ts +2 -2
  423. package/dist/runtime/helpers/uiProvider.js +4 -5
  424. package/dist/runtime/helpers/webgl/index.js +1 -1
  425. package/dist/runtime/icons/arrow-right-thin.svg +3 -0
  426. package/dist/runtime/public/_blokkli-assets/check.svg +6 -0
  427. package/dist/runtime/public/_blokkli-assets/loader.svg +1 -0
  428. package/dist/runtime/types/blokkOptions.d.ts +11 -2
  429. package/dist/runtime/types/index.d.ts +38 -15
  430. package/dist/shared/editor.gz_ac6uT.d.mts +431 -0
  431. package/dist/types.d.mts +1 -1
  432. package/package.json +26 -18
  433. package/dist/module.cjs +0 -5
  434. package/dist/module.d.ts +0 -129
  435. package/dist/runtime/adapter/drupal/graphql/base.graphql +0 -944
  436. package/dist/runtime/adapter/drupal/graphqlMiddleware.d.ts +0 -2
  437. package/dist/runtime/adapter/drupal/graphqlMiddleware.js +0 -680
  438. package/dist/runtime/helpers/options.d.ts +0 -2
  439. package/dist/runtime/helpers/options.js +0 -21
  440. package/dist/runtime/types/generatedModuleTypes.d.ts +0 -49
  441. package/dist/types.d.ts +0 -1
  442. /package/dist/{runtime/adapter/drupal/graphql → modules/drupal/graphql/features}/comments.graphql +0 -0
  443. /package/dist/{runtime/adapter/drupal/graphql → modules/drupal/graphql/features}/fragments.graphql +0 -0
  444. /package/dist/{runtime/adapter/drupal/graphql → modules/drupal/graphql/features}/search.graphql +0 -0
  445. /package/dist/{runtime/adapter/drupal/graphql → modules/drupal/graphql/features}/transform.graphql +0 -0
  446. /package/dist/runtime/{types/generatedModuleTypes.js → components/Edit/Features/Publish/Dialog/types.js} +0 -0
  447. /package/dist/runtime/public/{Inter.var.woff2 → _blokkli-assets/Inter.var.woff2} +0 -0
package/dist/module.mjs CHANGED
@@ -1,13 +1,19 @@
1
- import path, { basename, extname } from 'node:path';
2
- import fs, { promises, existsSync } from 'node:fs';
3
- import { defineNuxtModule, createResolver, resolveFiles, addTemplate, addComponent, addBuildPlugin, addImports, addPlugin, updateTemplates } from '@nuxt/kit';
4
- import { defu, createDefu } from 'defu';
1
+ import { resolveFiles, createResolver, addComponent, addImports, addTemplate, addTypeTemplate, resolveAlias, defineNuxtModule, addPlugin, addBuildPlugin } from '@nuxt/kit';
5
2
  import { createUnplugin } from 'unplugin';
6
3
  import MagicString from 'magic-string';
7
4
  import { walk } from 'estree-walker-ts';
5
+ import { pathToFileURL } from 'node:url';
6
+ import { parseURL, parseQuery } from 'ufo';
7
+ import * as ts from 'typescript';
8
+ import path, { basename } from 'node:path';
9
+ import { dirname, relative } from 'pathe';
10
+ import micromatch from 'micromatch';
11
+ import { hash } from 'ohash';
8
12
  import { BK_VISIBLE_LANGUAGES, BK_HIDDEN_GLOBALLY } from '../dist/runtime/helpers/symbols.js';
13
+ import fs from 'node:fs';
14
+ import { defu, createDefu } from 'defu';
9
15
 
10
- const version = "1.4.0-alpha.0";
16
+ const version = "2.0.0-alpha.1";
11
17
 
12
18
  function sortObjectKeys(obj) {
13
19
  if (Array.isArray(obj)) {
@@ -22,728 +28,915 @@ function sortObjectKeys(obj) {
22
28
  }
23
29
  return obj;
24
30
  }
25
-
31
+ function toValidVariableName(input) {
32
+ let result = input.replace(/\W/g, "_");
33
+ if (/^\d/.test(result)) {
34
+ result = "_" + result;
35
+ }
36
+ if (result === "") {
37
+ result = "_empty";
38
+ }
39
+ return result;
40
+ }
41
+ function parseTsObject(tsObjectStr) {
42
+ const source = `(${tsObjectStr})`;
43
+ const result = ts.transpileModule(source, {
44
+ compilerOptions: {
45
+ target: ts.ScriptTarget.ESNext,
46
+ module: ts.ModuleKind.None,
47
+ removeComments: true
48
+ }
49
+ });
50
+ const jsCode = result.outputText.trim();
51
+ const createObj = new Function(`return ${jsCode}`);
52
+ const object = createObj();
53
+ return { object, source: jsCode };
54
+ }
55
+ function extractObjectLiteral(fileContents, composables) {
56
+ const composablesMatch = composables.join("|");
57
+ const pattern = `(${composablesMatch})\\(\\s*(\\{[\\s\\S]+?\\})\\s*\\)`;
58
+ const rgx = new RegExp(pattern);
59
+ const matches = rgx.exec(fileContents);
60
+ if (!matches) {
61
+ return;
62
+ }
63
+ return matches?.at(2);
64
+ }
26
65
  function falsy(value) {
27
66
  return value !== null && value !== void 0;
28
67
  }
29
- const fileRegex = /\.vue$/;
30
- function estreeToObject(expression) {
31
- return Object.fromEntries(
32
- expression.properties.map((prop) => {
33
- if (prop.type === "Property" && "name" in prop.key) {
34
- if (prop.value.type === "Literal") {
35
- return [prop.key.name, prop.value.value];
36
- } else if (prop.value.type === "ObjectExpression") {
37
- return [prop.key.name, estreeToObject(prop.value)];
38
- } else if (prop.value.type === "ArrayExpression") {
39
- return [
40
- prop.key.name,
41
- prop.value.elements.map((v) => {
42
- if (v && "value" in v) {
43
- return v.value;
44
- }
45
- }).filter(falsy)
46
- ];
47
- }
48
- }
49
- return null;
50
- }).filter(falsy)
51
- );
52
- }
53
- function buildRuntimeDefinition(definition) {
54
- const runtimeDefinition = {
55
- bundle: definition.bundle
56
- };
57
- if (definition.options) {
58
- runtimeDefinition.options = {};
59
- Object.entries(definition.options).forEach(
60
- ([optionKey, optionDefinition]) => {
61
- runtimeDefinition.options[optionKey] = {
62
- type: optionDefinition.type,
63
- default: optionDefinition.default
64
- };
65
- }
66
- );
68
+
69
+ class CollectedFile {
70
+ constructor(filePath, fileContents) {
71
+ this.filePath = filePath;
72
+ this.fileContents = fileContents;
67
73
  }
68
- if (definition.globalOptions) {
69
- runtimeDefinition.globalOptions = definition.globalOptions;
74
+ async handleChange(_helper) {
75
+ return Promise.resolve(true);
70
76
  }
71
- return runtimeDefinition;
72
77
  }
73
- const DefinitionPlugin = (nuxt, composableName = "defineBlokkli") => createUnplugin(() => {
74
- return {
75
- name: "transform-file",
76
- enforce: "post",
77
- transform(source, id) {
78
- if (!fileRegex.test(id)) {
79
- return;
80
- }
81
- if (!source.includes(composableName)) {
82
- return;
83
- }
84
- const s = new MagicString(source);
85
- const parsed = this.parse(source, {
86
- sourceType: "module",
87
- ecmaVersion: "latest"
88
- });
89
- walk(parsed, {
90
- enter: (node) => {
91
- if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
92
- return;
93
- }
94
- const callNode = node;
95
- const name = "name" in callNode.callee && callNode.callee.name;
96
- if (name === composableName) {
97
- const arg = callNode.arguments[0];
98
- const meta = callNode.arguments[0];
99
- if (arg.type === "ObjectExpression") {
100
- const definition = estreeToObject(arg);
101
- const runtimeDefinition = buildRuntimeDefinition(definition);
102
- const start = meta.start;
103
- const end = meta.end;
104
- s.overwrite(start, end, JSON.stringify(runtimeDefinition));
105
- }
106
- }
107
- },
108
- leave: () => {
109
- }
110
- });
111
- if (s.hasChanged()) {
112
- return {
113
- code: s.toString(),
114
- map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : null
115
- };
116
- }
117
- return source;
78
+ class Collector {
79
+ constructor(helper) {
80
+ this.helper = helper;
81
+ this.files = /* @__PURE__ */ new Map();
82
+ }
83
+ files;
84
+ needsFileContents = true;
85
+ async addFile(filePath) {
86
+ if (this.needsFileContents) {
87
+ const contents = await this.helper.fileCache.read(filePath);
88
+ const file = this.createCollectedFile(filePath, contents.toString());
89
+ await file.handleChange(this.helper);
90
+ this.files.set(filePath, file);
91
+ } else {
92
+ const file = this.createCollectedFile(filePath);
93
+ await file.handleChange(this.helper);
94
+ this.files.set(filePath, file);
118
95
  }
119
- };
120
- });
121
-
122
- class BlockExtractor {
123
- definitions = {};
124
- fragmentDefinitions = {};
125
- isBuild = false;
126
- composableName;
127
- fragmentComposableName;
128
- constructor(isBuild = false) {
129
- this.isBuild = isBuild;
130
- this.composableName = "defineBlokkli";
131
- this.fragmentComposableName = "defineBlokkliFragment";
132
96
  }
133
- /**
134
- * Add files by path.
135
- */
136
- addFiles(files) {
137
- return Promise.all(files.map((v) => this.handleFile(v)));
97
+ async handleAdd(filePath) {
98
+ const applies = await this.applies(filePath);
99
+ if (applies) {
100
+ await this.addFile(filePath);
101
+ return true;
102
+ }
103
+ return false;
138
104
  }
139
- async getIcon(componentPath) {
140
- const folder = path.dirname(componentPath);
141
- const iconPath = path.join(folder, "/icon.svg");
142
- try {
143
- await fs.promises.access(iconPath, fs.constants.F_OK);
144
- const data = await fs.promises.readFile(iconPath);
145
- return data.toString();
146
- } catch {
105
+ async handleChange(filePath) {
106
+ const applies = await this.applies(filePath);
107
+ if (!applies) {
108
+ return this.handleUnlink(filePath);
147
109
  }
110
+ const file = this.files.get(filePath);
111
+ if (!file) {
112
+ return false;
113
+ }
114
+ if (this.needsFileContents) {
115
+ const contents = await this.helper.fileCache.read(filePath);
116
+ file.fileContents = contents.toString();
117
+ return await file.handleChange(this.helper);
118
+ }
119
+ return true;
148
120
  }
149
- async getContextComponent(baseComponentPath, name) {
150
- const folder = path.dirname(baseComponentPath);
151
- const componentPath = path.join(folder, `/${name}.vue`);
152
- try {
153
- await fs.promises.access(componentPath, fs.constants.F_OK);
154
- return componentPath;
155
- } catch {
121
+ handleUnlink(filePath) {
122
+ if (this.files.has(filePath)) {
123
+ this.files.delete(filePath);
124
+ return true;
156
125
  }
126
+ return false;
157
127
  }
158
- /**
159
- * Read the file and extract the blokkli component definitions.
160
- *
161
- * Returns a promise containing a boolean that indicated if the given file
162
- * should trigger a rebuild of the query.
163
- */
164
- async handleFile(filePath2) {
165
- const fileSource = await this.readFile(filePath2);
166
- const extracted = this.extractSingle(fileSource, filePath2);
167
- if (!extracted) {
168
- if (this.definitions[filePath2]) {
169
- this.definitions[filePath2] = void 0;
170
- return true;
128
+ handleAddDir() {
129
+ return false;
130
+ }
131
+ handleUnlinkDir(folderPath) {
132
+ const allKeys = [...this.files.keys()];
133
+ const toRemove = allKeys.filter((filePath) => filePath.includes(folderPath));
134
+ if (toRemove.length) {
135
+ toRemove.forEach((key) => this.files.delete(key));
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+ async handleWatchEvent(event, filePath) {
141
+ let hasChanged = false;
142
+ if (event === "add") {
143
+ hasChanged = await this.handleAdd(filePath);
144
+ } else if (event === "change") {
145
+ hasChanged = await this.handleChange(filePath);
146
+ } else if (event === "unlink") {
147
+ hasChanged = await this.handleUnlink(filePath);
148
+ } else if (event === "addDir") {
149
+ hasChanged = this.handleAddDir();
150
+ } else if (event === "unlinkDir") {
151
+ hasChanged = this.handleUnlinkDir(filePath);
152
+ }
153
+ return { hasChanged };
154
+ }
155
+ }
156
+
157
+ const DEFINE_BLOKKLI = "defineBlokkli";
158
+ const DEFINE_BLOKKLI_FRAGMENT = "defineBlokkliFragment";
159
+ function isEditComponent(filePath) {
160
+ return filePath.endsWith("/diff.vue") || filePath.endsWith("/proxy.vue");
161
+ }
162
+ function isBlock(definition) {
163
+ return "bundle" in definition;
164
+ }
165
+ function getVariations(definition) {
166
+ if (!definition) {
167
+ return [];
168
+ }
169
+ if (isBlock(definition)) {
170
+ const bundle = definition.bundle;
171
+ if (!definition.renderFor) {
172
+ return ["block:" + bundle];
173
+ }
174
+ const renderFor = Array.isArray(definition.renderFor) ? definition.renderFor : [definition.renderFor];
175
+ return renderFor.map((v) => {
176
+ if ("parentBundle" in v) {
177
+ return `block:${bundle}__p:${v.parentBundle}`;
178
+ } else if ("fieldList" in v) {
179
+ return `block:${bundle}__f:${v.fieldList}`;
180
+ } else {
181
+ return `block:${bundle}__f:${v.fieldListType}`;
171
182
  }
172
- if (this.fragmentDefinitions[filePath2]) {
173
- this.fragmentDefinitions[filePath2] = void 0;
174
- return true;
183
+ }).sort();
184
+ }
185
+ return [`fragment:${definition.name}`];
186
+ }
187
+ function getIdentifier(definition) {
188
+ const type = isBlock(definition) ? "b" : "f";
189
+ const name = isBlock(definition) ? definition.bundle : definition.name;
190
+ return toValidVariableName(
191
+ type + "_" + hash(name + getVariations(definition).join("__"))
192
+ );
193
+ }
194
+ class CollectedBlockFile extends CollectedFile {
195
+ folder = "";
196
+ iconPath = null;
197
+ iconContents = null;
198
+ diffComponentPath = null;
199
+ proxyComponentPath = null;
200
+ type = null;
201
+ definition = null;
202
+ definitionSource = null;
203
+ hasBlokkliField = false;
204
+ identifier = "";
205
+ chunkName = "global";
206
+ variations = [];
207
+ objectLiteralString = "";
208
+ hasSiblingFile(name, helper) {
209
+ const siblingFilePath = path.join(this.folder, "/" + name);
210
+ if (helper.fileCache.fileExists(siblingFilePath)) {
211
+ return siblingFilePath;
212
+ }
213
+ return null;
214
+ }
215
+ async handleChange(helper) {
216
+ this.folder = dirname(this.filePath);
217
+ const diffComponentPath = this.hasSiblingFile("diff.vue", helper);
218
+ const proxyComponentPath = this.hasSiblingFile("proxy.vue", helper);
219
+ const objectLiteralString = extractObjectLiteral(this.fileContents, [
220
+ DEFINE_BLOKKLI,
221
+ DEFINE_BLOKKLI_FRAGMENT
222
+ ]);
223
+ if (objectLiteralString === this.objectLiteralString && diffComponentPath === this.diffComponentPath && proxyComponentPath === this.proxyComponentPath) {
224
+ return false;
225
+ }
226
+ this.objectLiteralString = objectLiteralString || "";
227
+ this.diffComponentPath = diffComponentPath;
228
+ this.proxyComponentPath = proxyComponentPath;
229
+ try {
230
+ if (this.objectLiteralString) {
231
+ const result = parseTsObject(
232
+ this.objectLiteralString
233
+ );
234
+ this.definition = result.object;
235
+ this.definitionSource = result.source;
175
236
  }
237
+ } catch (e) {
238
+ console.error(
239
+ `Failed to parse component "${this.filePath}": The composabe does not contain a valid object literal. No variables and methods are allowed inside the composable.`,
240
+ e
241
+ );
176
242
  return false;
177
243
  }
178
- if ("bundle" in extracted.definition) {
179
- const icon = await this.getIcon(filePath2);
180
- const proxyComponent = await this.getContextComponent(filePath2, "proxy");
181
- const diffComponent = await this.getContextComponent(filePath2, "diff");
182
- if (this.definitions[filePath2] && this.definitions[filePath2]?.source === extracted.source) {
183
- return false;
244
+ this.hasBlokkliField = this.fileContents.includes("<BlokkliField") || this.fileContents.includes("<blokkli-field") || this.fileContents.includes(':is="BlokkliField"');
245
+ this.chunkName = this.definition?.chunkName || "global";
246
+ this.identifier = this.definition ? getIdentifier(this.definition) : "";
247
+ if (!this.definition) {
248
+ this.type = null;
249
+ } else if (isBlock(this.definition)) {
250
+ if (this.definition.renderFor) {
251
+ this.type = "context";
252
+ } else {
253
+ this.type = "main";
184
254
  }
185
- const extension = path.extname(filePath2);
186
- const componentFileName = path.basename(filePath2, extension);
187
- this.definitions[filePath2] = {
188
- filePath: filePath2,
189
- definition: extracted.definition,
190
- icon,
191
- proxyComponent,
192
- diffComponent,
193
- chunkName: this.isBuild ? extracted.definition.chunkName || "global" : "global",
194
- componentName: "BlokkliComponent_" + extracted.definition.bundle + "_" + componentFileName,
195
- source: extracted.source,
196
- fileSource,
197
- hasBlokkliField: fileSource.includes("<BlokkliField") || fileSource.includes("<blokkli-field") || fileSource.includes(':is="BlokkliField"')
198
- };
199
- } else if ("name" in extracted.definition) {
200
- if (this.fragmentDefinitions[filePath2] && this.fragmentDefinitions[filePath2]?.source === extracted.source) {
201
- return false;
255
+ } else {
256
+ this.type = "fragment";
257
+ }
258
+ if (this.type === "main") {
259
+ this.iconPath = this.hasSiblingFile("icon.svg", helper);
260
+ if (this.iconPath) {
261
+ this.iconContents = await helper.fileCache.read(this.iconPath);
202
262
  }
203
- this.fragmentDefinitions[filePath2] = {
204
- filePath: filePath2,
205
- definition: extracted.definition,
206
- chunkName: this.isBuild ? extracted.definition.chunkName || "global" : "global",
207
- componentName: "BlokkliFragmentComponent_" + extracted.definition.name,
208
- source: extracted.source,
209
- fileSource
210
- };
263
+ } else {
264
+ this.iconPath = null;
265
+ this.iconContents = null;
211
266
  }
267
+ this.variations = getVariations(this.definition);
212
268
  return true;
213
269
  }
214
- /**
215
- * Extract the single text method calls.
216
- */
217
- extractSingle(code, filePath) {
218
- const pattern = `(${this.composableName}|${this.fragmentComposableName})\\((\\{.+?\\})\\)`;
219
- const rgx = new RegExp(pattern, "gms");
220
- const source = rgx.exec(code)?.[2];
221
- if (source) {
222
- try {
223
- const definition = eval(`(${source})`);
224
- return { definition, source };
225
- } catch (e) {
226
- console.error(
227
- `Failed to parse component "${filePath}": ${this.composableName} does not contain a valid object literal. No variables and methods are allowed inside ${this.composableName}().`,
228
- e
229
- );
270
+ }
271
+ class BlockCollector extends Collector {
272
+ patterns;
273
+ constructor(helper) {
274
+ super(helper);
275
+ this.patterns = (helper.options.pattern || []).map((pattern) => {
276
+ if (pattern.startsWith("/")) {
277
+ return pattern;
278
+ }
279
+ return helper.resolvers.src.resolve(pattern);
280
+ });
281
+ }
282
+ async init() {
283
+ const files = await resolveFiles(
284
+ this.helper.nuxt.options.srcDir,
285
+ this.patterns
286
+ );
287
+ const promises = [];
288
+ for (const filePath of files) {
289
+ const applies = await this.applies(filePath);
290
+ if (applies) {
291
+ promises.push(this.addFile(filePath));
230
292
  }
231
293
  }
294
+ await Promise.all(promises);
232
295
  }
233
- /**
234
- * Read the given file and return its contents.
235
- */
236
- readFile(filePath2) {
237
- return fs.promises.readFile(filePath2).then((v) => {
238
- return v.toString();
296
+ runHooks() {
297
+ return this.helper.nuxt.hooks.callHook("blokkli:alter-blocks", {
298
+ blocks: [...this.files.values()]
239
299
  });
240
300
  }
241
- /**
242
- * Generate the template.
243
- */
244
- generateDefinitionTemplate(globalOptions = {}) {
245
- const definitionDeclarations = Object.values(this.definitions).filter(falsy).map((v) => {
246
- return `const ${v.componentName}: DefinitionItem = ${v.source}`;
247
- }, {});
248
- const allDefinitions = Object.values(this.definitions).filter(falsy).reduce((acc, v) => {
249
- const bundle = v.definition.bundle;
250
- const renderFor = v.definition.renderFor;
251
- if (renderFor) {
252
- const renderForList = Array.isArray(renderFor) ? renderFor : [renderFor];
253
- renderForList.forEach((entry) => {
254
- if ("parentBundle" in entry) {
255
- acc.push(
256
- `${bundle}__parent_block_${entry.parentBundle}: ${v.componentName}`
257
- );
258
- } else if ("fieldList" in entry) {
259
- acc.push(
260
- `${bundle}__field_list_type_${entry.fieldList}: ${v.componentName}`
261
- );
262
- } else if ("fieldListType" in entry) {
263
- acc.push(
264
- `${bundle}__field_list_type_${entry.fieldListType}: ${v.componentName}`
265
- );
266
- }
267
- });
268
- } else {
269
- acc.push(`${bundle}: ${v.componentName}`);
301
+ createCollectedFile(filePath, fileContents = "") {
302
+ return new CollectedBlockFile(filePath, fileContents);
303
+ }
304
+ findBlockForFolderFile(iconPath) {
305
+ for (const file of this.files.values()) {
306
+ if (file.iconPath === iconPath || file.proxyComponentPath === iconPath || file.diffComponentPath === iconPath) {
307
+ return file.filePath;
270
308
  }
271
- return acc;
272
- }, []);
273
- const allFragmentDefinitions = Object.values(this.fragmentDefinitions).filter(falsy).map((v) => {
274
- return `${v.definition.name}: ${v.source}`;
275
- });
276
- const icons = Object.values(this.definitions).filter(falsy).reduce((acc, v) => {
277
- if (v.icon) {
278
- acc[v.definition.bundle] = v.icon;
309
+ }
310
+ return null;
311
+ }
312
+ async handleAdd(filePath) {
313
+ if (isEditComponent(filePath)) {
314
+ const folder = dirname(filePath);
315
+ for (const file of this.files.values()) {
316
+ if (file.folder === folder) {
317
+ return super.handleChange(file.filePath);
318
+ }
279
319
  }
280
- return acc;
281
- }, {});
282
- const buildContextComponents = (name) => {
283
- const proxyComponents = Object.values(this.definitions).reduce((acc, v) => {
284
- if (v?.[name]) {
285
- acc[v.definition.bundle] = v[name];
320
+ }
321
+ return super.handleAdd(filePath);
322
+ }
323
+ async handleUnlink(filePath) {
324
+ if (isEditComponent(filePath)) {
325
+ const folder = dirname(filePath);
326
+ for (const file of this.files.values()) {
327
+ if (file.folder === folder) {
328
+ return super.handleChange(file.filePath);
286
329
  }
287
- return acc;
288
- }, {});
289
- const imports = Object.entries(proxyComponents).map(([bundle, proxyComponentPath]) => {
290
- return `import ${name}_${bundle} from '${proxyComponentPath}'`;
291
- }).join("\n");
292
- const maps = Object.keys(proxyComponents).map((bundle) => {
293
- return `'${bundle}': ${name}_${bundle}`;
294
- }).join(", \n");
295
- return {
296
- imports,
297
- maps
298
- };
299
- };
300
- const proxy = buildContextComponents("proxyComponent");
301
- const diff = buildContextComponents("diffComponent");
302
- const allFragmentNames = Object.values(this.fragmentDefinitions).filter(falsy).map((v) => `'${v.definition.name}'`).join(" | ");
303
- return `import type { GlobalOptionsKey, ValidFieldListTypes, BlockBundleWithNested } from './generated-types'
304
- import type { BlockDefinitionInput, BlockDefinitionOptionsInput, FragmentDefinitionInput } from '#blokkli/types'
305
- export const globalOptions = ${JSON.stringify(globalOptions, null, 2)} as const
306
- ${proxy.imports}
307
- ${diff.imports}
308
-
309
- type DefinitionItem = BlockDefinitionInput<BlockDefinitionOptionsInput, GlobalOptionsKey[]>
310
-
311
- ${definitionDeclarations.join("\n")}
312
-
313
- const PROXY_COMPONENTS: Record<string, any> = {
314
- ${proxy.maps}
315
- }
316
-
317
- const DIFF_COMPONENTS: Record<string, any> = {
318
- ${diff.maps}
319
- }
320
-
321
- export const icons: Record<string, string> = ${JSON.stringify(icons)}
322
-
323
- export const definitionsMap: Record<string, DefinitionItem> = {
324
- ${allDefinitions.join(",\n")}
325
- }
326
-
327
- export const fragmentDefinitionsMap: Record<string, FragmentDefinitionInput<BlockDefinitionOptionsInput, GlobalOptionsKey[]>> = {
328
- ${allFragmentDefinitions.join(",\n")}
329
- }
330
-
331
- export type BlokkliFragmentName = ${allFragmentNames || "never"}
332
-
333
- export const definitions: BlockDefinitionInput<any, GlobalOptionsKey[]>[] = Object.values(definitionsMap)
334
- export const fragmentDefinitions: FragmentDefinitionInput<any, GlobalOptionsKey[]>[] = Object.values(fragmentDefinitionsMap)
335
-
336
- /**
337
- * Get the block definition for the given field and parent context.
338
- */
339
- export function getDefinition(bundle: string, fieldListType: ValidFieldListTypes, parentBundle?: BlockBundleWithNested): BlockDefinitionInput<Record<string, any>, GlobalOptionsKey[]>|undefined {
340
- const forFieldListType = bundle + '__field_list_type_' + fieldListType
341
- if (definitionsMap[forFieldListType]) {
342
- return definitionsMap[forFieldListType]
330
+ }
331
+ }
332
+ return super.handleUnlink(filePath);
343
333
  }
344
- if (parentBundle) {
345
- const forParentBundle = bundle + '__parent_block_' + parentBundle
346
- if (definitionsMap[forParentBundle]) {
347
- return definitionsMap[forParentBundle]
334
+ async handleChange(filePath) {
335
+ if (filePath.includes("icon.svg")) {
336
+ const matchingBlockFilePath = this.findBlockForFolderFile(filePath);
337
+ if (matchingBlockFilePath) {
338
+ return this.handleChange(matchingBlockFilePath);
339
+ }
340
+ return false;
348
341
  }
342
+ return super.handleChange(filePath);
343
+ }
344
+ async applies(filePath) {
345
+ if (!filePath.endsWith(".vue")) {
346
+ return false;
347
+ }
348
+ if (!micromatch.isMatch(filePath, this.patterns)) {
349
+ return false;
350
+ }
351
+ if (isEditComponent(filePath)) {
352
+ return true;
353
+ }
354
+ const content = await this.helper.fileCache.read(filePath);
355
+ return content.includes(DEFINE_BLOKKLI) || content.includes(DEFINE_BLOKKLI_FRAGMENT);
356
+ }
357
+ getDependencyTypes() {
358
+ return ["block-content", "block-path"];
349
359
  }
350
-
351
- return definitionsMap[bundle]
352
360
  }
353
361
 
354
- export function getBlokkliItemProxyComponent(bundle: string): any {
355
- return PROXY_COMPONENTS[bundle]
362
+ function isVue(id, opts = {}) {
363
+ const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
364
+ if (id.endsWith(".vue") && !search) {
365
+ return true;
366
+ }
367
+ if (!search) {
368
+ return false;
369
+ }
370
+ const query = parseQuery(search);
371
+ if (query.nuxt_component) {
372
+ return false;
373
+ }
374
+ if (query.macro && (search === "?macro=true" || !opts.type || opts.type.includes("script"))) {
375
+ return true;
376
+ }
377
+ const type = "setup" in query ? "script" : query.type;
378
+ if (!("vue" in query) || opts.type && !opts.type.includes(type)) {
379
+ return false;
380
+ }
381
+ return true;
356
382
  }
357
-
358
- export function getBlokkliItemDiffComponent(bundle: string): any {
359
- return DIFF_COMPONENTS[bundle]
383
+ function generateRuntimeArg(definition) {
384
+ const name = isBlock(definition) ? definition.bundle : definition.name;
385
+ return `${name}::${getIdentifier(definition)}`;
360
386
  }
387
+ const RuntimeDefinitionPlugin = (nuxt, composableName) => {
388
+ const cache = /* @__PURE__ */ new Map();
389
+ function extract(source) {
390
+ const fromCache = cache.get(source);
391
+ if (fromCache) {
392
+ return fromCache;
393
+ }
394
+ const definition = parseTsObject(source);
395
+ if (definition.object) {
396
+ cache.set(source, definition.object);
397
+ return definition.object;
398
+ }
399
+ return null;
400
+ }
401
+ return createUnplugin(() => {
402
+ return {
403
+ name: "blokkli:runtime-definition",
404
+ enforce: "post",
405
+ transformInclude(id) {
406
+ return isVue(id);
407
+ },
408
+ transform(source) {
409
+ if (!source.includes(composableName)) {
410
+ return;
411
+ }
412
+ const s = new MagicString(source);
413
+ const parsed = this.parse(source, {
414
+ sourceType: "module",
415
+ ecmaVersion: "latest"
416
+ });
417
+ walk(parsed, {
418
+ enter: (node) => {
419
+ if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
420
+ return;
421
+ }
422
+ const callNode = node;
423
+ const name = "name" in callNode.callee && callNode.callee.name;
424
+ if (name === composableName) {
425
+ const arg = callNode.arguments[0];
426
+ if (!arg) {
427
+ return;
428
+ }
429
+ const meta = callNode.arguments[0];
430
+ if (arg.type === "ObjectExpression") {
431
+ const start = meta.start;
432
+ const end = meta.end;
433
+ const objectSource = s.slice(start, end);
434
+ const object = extract(objectSource);
435
+ if (object) {
436
+ const arg2 = generateRuntimeArg(object);
437
+ s.overwrite(start, end, `"${arg2}"`);
438
+ }
439
+ }
440
+ }
441
+ },
442
+ leave: () => {
443
+ }
444
+ });
445
+ if (s.hasChanged()) {
446
+ return {
447
+ code: s.toString(),
448
+ map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : null
449
+ };
450
+ }
451
+ }
452
+ };
453
+ });
454
+ };
361
455
 
362
- /**
363
- * Get the definition of the default block component.
364
- */
365
- export function getDefaultDefinition(bundle: string): BlockDefinitionInput<Record<string, any>, GlobalOptionsKey[]>|undefined {
366
- return definitionsMap[bundle]
456
+ class IconCollector extends Collector {
457
+ needsFileContents = false;
458
+ srcFromModule;
459
+ constructor(helper) {
460
+ super(helper);
461
+ this.srcFromModule = helper.resolvers.module.resolve("./runtime/icons");
462
+ }
463
+ async init() {
464
+ const srcFromModule = this.helper.resolvers.module.resolve("./runtime/icons");
465
+ const filesModule = await resolveFiles(srcFromModule, "*.svg");
466
+ const filesApp = await resolveFiles(
467
+ this.helper.paths.srcDir,
468
+ "**/icon-blokkli-*.svg"
469
+ );
470
+ const allFiles = [...filesModule, ...filesApp];
471
+ await Promise.all(allFiles.map((filePath) => this.addFile(filePath)));
472
+ }
473
+ runHooks() {
474
+ return this.helper.nuxt.hooks.callHook("blokkli:alter-icons", {
475
+ icons: [...this.files.values()]
476
+ });
477
+ }
478
+ applies(filePath) {
479
+ return Promise.resolve(
480
+ filePath.startsWith(this.srcFromModule) || micromatch.isMatch(filePath, "icon-blokkli-*.svg")
481
+ );
482
+ }
483
+ getDependencyTypes() {
484
+ return ["icons"];
485
+ }
486
+ createCollectedFile(filePath, fileContents = "") {
487
+ return new CollectedFile(filePath, fileContents);
488
+ }
367
489
  }
368
- export const getFragmentDefinition = (name: string): FragmentDefinitionInput<Record<string, any>, GlobalOptionsKey[]>|undefined => fragmentDefinitionsMap[name]
369
- `;
490
+
491
+ class FileCache {
492
+ cache = /* @__PURE__ */ new Map();
493
+ existingFiles = /* @__PURE__ */ new Set();
494
+ /**
495
+ * Read a file from disk.
496
+ */
497
+ async read(filePath) {
498
+ const existing = this.cache.get(filePath);
499
+ if (existing) {
500
+ return existing;
501
+ }
502
+ const buffer = await fs.promises.readFile(filePath);
503
+ const content = buffer.toString();
504
+ this.cache.set(filePath, content);
505
+ return content;
370
506
  }
371
507
  /**
372
- * Generate the options schema.
508
+ * Delete a file.
373
509
  */
374
- generateOptionsSchema(globalOptions = {}) {
375
- const schema = Object.values(this.definitions).filter(falsy).reduce((acc, v) => {
376
- const existing = acc[v.definition.bundle] || {};
377
- acc[v.definition.bundle] = defu(existing, v.definition.options || {});
378
- const globalOptionKeys = v.definition.globalOptions || [];
379
- globalOptionKeys.forEach((name) => {
380
- if (globalOptions[name]) {
381
- acc[v.definition.bundle][name] = globalOptions[name];
382
- }
383
- });
384
- return acc;
385
- }, {});
386
- const sorted = sortObjectKeys(schema);
387
- return JSON.stringify(sorted, null, 2);
510
+ delete(filePath) {
511
+ this.cache.delete(filePath);
388
512
  }
389
- getBundlesWithGlobalOptions(key) {
390
- return Object.values(this.definitions).map((definition2) => {
391
- if (definition2?.definition.globalOptions?.includes(key)) {
392
- return definition2.definition.bundle;
393
- }
394
- }).filter(falsy);
513
+ /**
514
+ * Check if a file exists.
515
+ */
516
+ fileExists(filePath) {
517
+ if (this.existingFiles.has(filePath)) {
518
+ return true;
519
+ }
520
+ const exists = fs.existsSync(filePath);
521
+ if (exists) {
522
+ this.existingFiles.add(filePath);
523
+ }
524
+ return exists;
395
525
  }
396
526
  /**
397
- * Generate the default global options values template.
527
+ * Handles the builder watch event.
398
528
  */
399
- generateDefaultGlobalOptions(globalOptions = {}) {
400
- const defaults = Object.entries(globalOptions).reduce(
401
- (acc, [key, option]) => {
402
- if (option.default !== void 0 && option.default !== null) {
403
- acc[key] = {
404
- default: option.default,
405
- type: option.type
406
- };
529
+ async handleWatchEvent(event, filePath) {
530
+ if (event === "add") {
531
+ this.existingFiles.add(filePath);
532
+ this.cache.delete(filePath);
533
+ } else if (event === "change") {
534
+ this.existingFiles.add(filePath);
535
+ this.cache.delete(filePath);
536
+ } else if (event === "unlink") {
537
+ this.existingFiles.delete(filePath);
538
+ this.cache.delete(filePath);
539
+ } else if (event === "unlinkDir") {
540
+ const filePaths = [...this.existingFiles.keys()];
541
+ filePaths.forEach((v) => {
542
+ if (v.startsWith(filePath)) {
543
+ this.existingFiles.delete(v);
544
+ this.cache.delete(v);
407
545
  }
408
- return acc;
409
- },
410
- {}
411
- );
412
- return `import type { BlockOptionDefinition } from '#blokkli/types/blokkOptions'
413
-
414
- type GlobalOptionsDefaults = {
415
- type: BlockOptionDefinition['type']
416
- default: any
546
+ });
547
+ }
548
+ }
417
549
  }
418
550
 
419
- export const bundlesWithVisibleLanguage: string[] = ${JSON.stringify(this.getBundlesWithGlobalOptions(BK_VISIBLE_LANGUAGES))}
420
- export const bundlesWithHiddenGlobally: string[] = ${JSON.stringify(this.getBundlesWithGlobalOptions(BK_HIDDEN_GLOBALLY))}
421
-
422
- export const globalOptionsDefaults: Record<string, GlobalOptionsDefaults> = ${JSON.stringify(
423
- defaults,
424
- null,
425
- 2
426
- )} as const`;
427
- }
428
- generateTypesTemplate(globalOptions, chunkNames, fieldListTypes) {
429
- const allDefintions = Object.values(
430
- this.definitions
431
- ).map((v) => v?.definition).filter(falsy);
432
- const validChunkNames = chunkNames.map((v) => {
433
- return `'${v}'`;
434
- }).join(" | ");
435
- const validFieldListTypes = fieldListTypes.map((v) => {
436
- return `'${v}'`;
437
- }).join(" | ");
438
- const validGlobalOptions = Object.keys(globalOptions).map((v) => {
439
- return `'${v}'`;
440
- }).join(" | ");
441
- const blockBundlesWithNested = Object.values(this.definitions).filter(falsy).filter((v) => v.hasBlokkliField).map((v) => {
442
- return `'${v.definition.bundle}'`;
443
- }).join(" | ");
444
- const validBlockBundles = allDefintions.filter((v) => v.bundle !== "from_library").map((v) => {
445
- return `'${v.bundle}'`;
446
- }).join(" | ");
447
- const possibleOptionTypes = Object.values(this.definitions).filter(falsy).filter((v) => v.definition.bundle !== "from_library").reduce((acc, v) => {
448
- if (!acc[v.definition.bundle]) {
449
- acc[v.definition.bundle] = [];
450
- }
451
- const definedOptions = v.definition.options;
452
- const blockGlobalOptions = v.globalOptions || [];
453
- blockGlobalOptions.forEach((key) => {
454
- if (globalOptions[key]) {
455
- definedOptions[key] = globalOptions[key];
456
- }
457
- });
458
- const options = Object.entries(definedOptions || {}).map(([key, option]) => {
459
- if (option.type === "text") {
460
- return `${key}: string | undefined`;
461
- } else if (option.type === "checkbox") {
462
- return `${key}: '1' | '0' | undefined`;
463
- } else if (option.type === "radios" || option.type === "checkboxes") {
464
- const possibleValues = Object.keys(option.options).map((v2) => `'${v2}'`).join(" | ");
465
- return `${key}: ${possibleValues} | undefined`;
466
- }
467
- }).join("\n ");
468
- acc[v.definition.bundle].push(
469
- `{
470
- ${options}
471
- }`
472
- );
473
- return acc;
474
- }, {});
475
- const typedFieldListItems = Object.entries(possibleOptionTypes).map(
476
- ([bundle, options]) => {
477
- const typeName = `FieldListItem_${bundle}`;
478
- const typeDefinition = `
479
- type ${typeName} = {
480
- bundle: '${bundle}'
481
- options: ${options.join(" | ")}
482
- }`;
483
- return {
484
- typeName,
485
- typeDefinition
486
- };
487
- }
551
+ function onlyUnique(value, index, self) {
552
+ return self.indexOf(value) === index;
553
+ }
554
+ class ModuleHelper {
555
+ constructor(nuxt, moduleUrl, providedOptions) {
556
+ this.nuxt = nuxt;
557
+ this.isDev = nuxt.options.dev;
558
+ this.isModuleBuild = false;
559
+ this.fileCache = new FileCache();
560
+ this.resolvers = {
561
+ module: createResolver(moduleUrl),
562
+ build: createResolver(nuxt.options.buildDir),
563
+ src: createResolver(nuxt.options.srcDir),
564
+ app: createResolver(nuxt.options.dir.app)
565
+ };
566
+ this.paths = {
567
+ blokkliBuildDir: this.resolvers.build.resolve("blokkli"),
568
+ srcDir: nuxt.options.srcDir,
569
+ editAdapter: this.findEditAdapterPath()
570
+ };
571
+ this.relativePaths = {
572
+ TYPES: relative(
573
+ this.paths.blokkliBuildDir,
574
+ this.resolvers.module.resolve("./runtime/types/index.ts")
575
+ ),
576
+ CONSTANTS: relative(
577
+ this.paths.blokkliBuildDir,
578
+ this.resolvers.module.resolve("./runtime/constants/index.ts")
579
+ ),
580
+ ADAPTER: relative(
581
+ this.paths.blokkliBuildDir,
582
+ this.resolvers.module.resolve("./runtime/adapter/index.ts")
583
+ ),
584
+ TYPES_THEME: relative(
585
+ this.paths.blokkliBuildDir,
586
+ this.resolvers.module.resolve("./runtime/types/theme.ts")
587
+ ),
588
+ TYPES_BLOKK_OPTIONS: relative(
589
+ this.paths.blokkliBuildDir,
590
+ this.resolvers.module.resolve("./runtime/types/blokkOptions.ts")
591
+ )
592
+ };
593
+ const pattern = providedOptions.pattern || [];
594
+ pattern.push(
595
+ this.resolvers.module.resolve(
596
+ "./runtime/components/Blocks/FromLibrary/*.vue"
597
+ )
488
598
  );
489
- return `
490
- import type { FieldListItem } from "#blokkli/types"
491
-
492
- export type ValidFieldListTypes = ${validFieldListTypes}
493
-
494
- export type BlockBundle = ${validBlockBundles || `''`}
495
-
496
- export type BlockBundleWithNested = ${blockBundlesWithNested || `''`}
497
-
498
- export type ValidChunkNames = ${validChunkNames}
499
-
500
- export type GlobalOptionsKey = ${validGlobalOptions || "never"}
501
-
502
- export type ValidGlobalConfigKeys = Array<GlobalOptionsKey>
503
-
504
- ${typedFieldListItems.map((v) => v.typeDefinition).join("\n\n")}
505
-
506
- export type FieldListItemTyped = FieldListItem & (${typedFieldListItems.map((v) => v.typeName).join(" | ")})
507
- export type FieldListItemTypedArray = Array<FieldListItemTyped>
508
- `;
509
- }
510
- generateChunkGroupTemplate(chunkName) {
511
- return this.generateChunkGroup(
512
- chunkName,
513
- chunkName,
514
- { ...this.definitions, ...this.fragmentDefinitions },
515
- true
599
+ pattern.push(
600
+ this.resolvers.module.resolve(
601
+ "./runtime/components/Blocks/Fragment/*.vue"
602
+ )
516
603
  );
604
+ const fieldListTypes = providedOptions.fieldListTypes || [];
605
+ if (!fieldListTypes.includes("default")) {
606
+ fieldListTypes.push("default");
607
+ }
608
+ const chunkNames = providedOptions.chunkNames || [];
609
+ if (!chunkNames.includes("global")) {
610
+ chunkNames.push("global");
611
+ }
612
+ this.options = {
613
+ ...providedOptions,
614
+ pattern,
615
+ fieldListTypes: fieldListTypes.filter(onlyUnique),
616
+ chunkNames: chunkNames.filter(onlyUnique)
617
+ };
517
618
  }
619
+ relativePaths;
620
+ paths;
621
+ resolvers;
622
+ fileCache;
623
+ options;
624
+ isDev;
625
+ isModuleBuild;
518
626
  /**
519
- * Generate the template.
627
+ * Transform the path relative to the module's build directory.
628
+ *
629
+ * @param path - The absolute path.
630
+ *
631
+ * @returns The path relative to the module's build directory.
520
632
  */
521
- generateImportsTemplate(chunkNames) {
522
- const chunkImports = chunkNames.filter((v) => v !== "global").map((chunkName) => {
523
- return `${chunkName}: () => import('#blokkli/chunk-${chunkName}')`;
524
- });
525
- const nonGlobalChunkMapping = Object.values(this.definitions).reduce((acc, v) => {
526
- if (v && v.chunkName !== "global") {
527
- acc["block_" + v.definition.bundle] = v.chunkName;
528
- }
529
- return acc;
530
- }, {});
531
- const nonGlobalFragmentChunkMapping = Object.values(
532
- this.fragmentDefinitions
533
- ).reduce((acc, v) => {
534
- if (v && v.chunkName !== "global") {
535
- acc["fragment_" + v.definition.name] = v.chunkName;
536
- }
537
- return acc;
538
- }, {});
539
- return `
540
- import { defineAsyncComponent } from '#imports'
541
- ${this.generateChunkGroup("global", "global", this.definitions)}
542
- ${this.generateChunkGroup(
543
- "global",
544
- "globalFragments",
545
- this.fragmentDefinitions
546
- )}
547
-
548
- const chunks: Record<string, () => Promise<any>> = {
549
- ${chunkImports.join(",\n ")}
550
- }
551
-
552
- const chunkMapping: Record<string, string> = ${JSON.stringify(
553
- nonGlobalChunkMapping,
554
- null,
555
- 2
556
- )}
557
-
558
- const fragmentChunkMapping: Record<string, string> = ${JSON.stringify(
559
- nonGlobalFragmentChunkMapping,
560
- null,
561
- 2
562
- )}
563
-
564
- function componentOrFunction(component: any) {
565
- if (typeof component === 'object') {
566
- return component
633
+ toModuleBuildRelative(path) {
634
+ return relative(this.paths.blokkliBuildDir, path);
567
635
  }
568
-
569
- return defineAsyncComponent(() => component())
570
- }
571
-
572
- export function getBlokkliItemComponent(bundle: string, fieldListType?: string, parentBundle?: string): any {
573
- const forFieldListType = 'block_' + bundle + '__field_list_type_' + fieldListType
574
- if (global[forFieldListType]) {
575
- return componentOrFunction(global[forFieldListType])
576
- }
577
- if (parentBundle) {
578
- const forParentBundle = 'block_' + bundle + '__parent_block_' + parentBundle
579
- if (global[forParentBundle]) {
580
- return componentOrFunction(global[forParentBundle])
636
+ findEditAdapterPath() {
637
+ const filePath = this.resolvers.app.resolve("blokkli.editAdapter.ts");
638
+ if (this.fileCache.fileExists(filePath)) {
639
+ return filePath;
581
640
  }
641
+ if (this.options.editAdapterPath && this.fileCache.fileExists(this.options.editAdapterPath)) {
642
+ return this.options.editAdapterPath;
643
+ }
644
+ throw new Error(`Missing bl\xF6kkli edit adapter at "${filePath}"`);
582
645
  }
583
- const key = 'block_' + bundle
584
- if (global[key]) {
585
- return componentOrFunction(global[key])
646
+ getChunkNames() {
647
+ return this.options.chunkNames || ["global"];
586
648
  }
587
- const chunkName = chunkMapping[key]
588
- if (chunkName) {
589
- return defineAsyncComponent(() => chunks[chunkName]().then(chunk => {
590
- return chunk.default[key]
591
- }))
649
+ addComponent(name) {
650
+ addComponent({
651
+ filePath: this.resolvers.module.resolve("./runtime/components/" + name),
652
+ name,
653
+ global: true
654
+ });
655
+ }
656
+ addComposable(name) {
657
+ addImports({
658
+ name,
659
+ from: this.resolvers.module.resolve("./runtime/composables/" + name)
660
+ });
661
+ }
662
+ addAlias(name, path) {
663
+ this.nuxt.options.alias[name] = path;
664
+ this.nuxt.options.nitro.typescript ||= {};
665
+ this.nuxt.options.nitro.typescript.tsConfig ||= {};
666
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions ||= {};
667
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths ||= {};
668
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths[name] = [
669
+ path
670
+ ];
671
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths[name + "/*"] = [path + "/*"];
672
+ this.nuxt.options.typescript.tsConfig ||= {};
673
+ this.nuxt.options.typescript.tsConfig.compilerOptions ||= {};
674
+ this.nuxt.options.typescript.tsConfig.compilerOptions.paths ||= {};
675
+ this.nuxt.options.typescript.tsConfig.compilerOptions.paths[name] = [path];
676
+ this.nuxt.options.typescript.tsConfig.compilerOptions.paths[name + "/*"] = [
677
+ path + "/*"
678
+ ];
592
679
  }
593
680
  }
594
681
 
595
- export function getBlokkliFragmentComponent(name: string): any {
596
- const key = 'fragment_' + name
597
- if (globalFragments[key]) {
598
- return componentOrFunction(globalFragments[key])
682
+ const WRITE = false;
683
+ class ModuleContext {
684
+ constructor(helper, icons, features, blocks, theme) {
685
+ this.helper = helper;
686
+ this.icons = icons;
687
+ this.features = features;
688
+ this.blocks = blocks;
689
+ this.theme = theme;
599
690
  }
600
- const chunkName = fragmentChunkMapping[key]
601
- if (chunkName) {
602
- return defineAsyncComponent(() => chunks[chunkName]().then(chunk => {
603
- return chunk.default[key]
604
- }))
691
+ templates = [];
692
+ templateContents = /* @__PURE__ */ new Map();
693
+ getTemplateContents(type, name) {
694
+ const contents = this.templateContents.get(type + name);
695
+ if (contents === void 0) {
696
+ throw new Error(
697
+ `Failed to get contents for template "${name}" of type ${type}`
698
+ );
699
+ }
700
+ return contents;
605
701
  }
606
- }
607
- `;
702
+ setTemplateContents(type, name, contents) {
703
+ this.templateContents.set(type + name, contents.trim());
608
704
  }
609
- /**
610
- * Generate the template.
611
- */
612
- generateChunkGroup(chunkName, exportName, inputDefinitions, addExport) {
613
- const definitions = Object.values(inputDefinitions).filter((v) => {
614
- return v?.chunkName === chunkName;
615
- }).filter(falsy);
616
- const imports = definitions.map((v) => {
617
- if (this.isBuild) {
618
- return `import ${v.componentName} from '${v.filePath}'`;
705
+ async generateTemplates(dependencies) {
706
+ for (const template of this.templates) {
707
+ if (dependencies?.length) {
708
+ const shouldUpdate = dependencies.some(
709
+ (v) => template.options.dependencies.includes(v)
710
+ );
711
+ if (!shouldUpdate) {
712
+ continue;
713
+ }
714
+ }
715
+ if (template.type === "code") {
716
+ this.setTemplateContents(
717
+ "code",
718
+ template.name,
719
+ await template.buildCode(this)
720
+ );
721
+ this.setTemplateContents(
722
+ "types",
723
+ template.name,
724
+ await template.buildTypes(this)
725
+ );
619
726
  } else {
620
- return `const ${v.componentName} = () => import('${v.filePath}')`;
727
+ this.setTemplateContents(
728
+ "file",
729
+ template.fileName,
730
+ await template.build(this)
731
+ );
621
732
  }
622
- });
623
- const map = definitions.reduce((acc, v) => {
624
- if ("bundle" in v.definition) {
625
- const bundle = v.definition.bundle;
626
- const renderFor = v.definition.renderFor;
627
- if (!renderFor) {
628
- acc.push(`block_${v.definition.bundle}: ${v.componentName}`);
629
- } else {
630
- const renderForList = Array.isArray(renderFor) ? renderFor : [renderFor];
631
- renderForList.forEach((entry) => {
632
- if ("parentBundle" in entry) {
633
- acc.push(
634
- `block_${bundle}__parent_block_${entry.parentBundle}: ${v.componentName}`
635
- );
636
- } else if ("fieldList" in entry) {
637
- acc.push(
638
- `block_${bundle}__field_list_type_${entry.fieldList}: ${v.componentName}`
639
- );
640
- } else if ("fieldListType" in entry) {
641
- acc.push(
642
- `block_${bundle}__field_list_type_${entry.fieldListType}: ${v.componentName}`
643
- );
733
+ }
734
+ }
735
+ addTemplate(template) {
736
+ this.templates.push(template);
737
+ if (template.type === "code") {
738
+ addTemplate({
739
+ filename: `blokkli/${template.name}.js`,
740
+ write: template.options.write || WRITE,
741
+ getContents: () => this.getTemplateContents("code", template.name)
742
+ });
743
+ addTypeTemplate({
744
+ filename: `blokkli/${template.name}.d.ts`,
745
+ write: true,
746
+ // Type files are always written.
747
+ getContents: () => {
748
+ const lines = this.getTemplateContents("types", template.name).trim().split("\n");
749
+ const imports = [];
750
+ const declarations = [];
751
+ for (const line of lines) {
752
+ if (line.startsWith("import ") && line.includes(" from ")) {
753
+ imports.push(line);
754
+ } else {
755
+ declarations.push(line);
644
756
  }
645
- });
757
+ }
758
+ return `${imports.join("\n")}
759
+
760
+ declare module '#blokkli-build/${template.name}' {
761
+ ${declarations.join("\n ")}
762
+ }`;
646
763
  }
764
+ });
765
+ } else {
766
+ const filename = template.fileName.startsWith("/") ? template.fileName : `blokkli/${template.fileName}`;
767
+ if (filename.endsWith(".d.ts")) {
768
+ addTypeTemplate({
769
+ filename,
770
+ write: true,
771
+ getContents: () => this.getTemplateContents("file", template.fileName)
772
+ });
647
773
  } else {
648
- acc.push(`fragment_${v.definition.name}: ${v.componentName}`);
774
+ addTemplate({
775
+ filename,
776
+ write: true,
777
+ getContents: () => this.getTemplateContents("file", template.fileName)
778
+ });
649
779
  }
650
- return acc;
651
- }, []);
652
- let content = `
653
- ${imports.join("\n")}
654
-
655
- const ${exportName}: Record<string, any> = {
656
- ${map.join(",\n ")}
657
- }
658
- `;
659
- if (addExport) {
660
- content += `export default ${exportName}`;
661
780
  }
662
- return content;
663
781
  }
664
782
  }
665
783
 
666
- class Extractor {
667
- definitions = {};
668
- isBuild = false;
669
- composableName;
670
- constructor(isBuild = false) {
671
- this.isBuild = isBuild;
672
- this.composableName = "defineBlokkliFeature";
673
- }
674
- /**
675
- * Add files by path.
676
- */
677
- addFiles(files) {
678
- return Promise.all(files.map((v) => this.handleFile(v)));
679
- }
680
- /**
681
- * Read the file and extract the blokkli component definitions.
682
- *
683
- * Returns a promise containing a boolean that indicated if the given file
684
- * should trigger a rebuild of the query.
685
- */
686
- async handleFile(filePath2) {
687
- const fileSource = await this.readFile(filePath2);
688
- const extracted = this.extractSingle(fileSource, filePath2);
689
- if (!extracted) {
690
- if (this.definitions[filePath2]) {
691
- this.definitions[filePath2] = void 0;
692
- return true;
693
- }
694
- return false;
695
- }
696
- const { definition: definition2, source: source2 } = extracted;
697
- if (!this.definitions[filePath2]) {
698
- const regex = /\/Features\/([^/]+)\//;
699
- const componentName = filePath2.match(regex)?.[1] || "";
700
- this.definitions[filePath2] = {
701
- id: definition2.id,
702
- componentName,
703
- componentPath: filePath2,
704
- filePath: filePath2,
705
- definition: definition2,
706
- source: source2
707
- };
708
- return true;
784
+ function defineCodeTemplate(name, buildCode, buildTypes, options) {
785
+ return {
786
+ type: "code",
787
+ name,
788
+ buildCode,
789
+ buildTypes,
790
+ options: {
791
+ dependencies: options?.dependencies || [],
792
+ write: !!options?.write
709
793
  }
710
- if (this.definitions[filePath2]?.definition === definition2) {
711
- return false;
794
+ };
795
+ }
796
+ function defineFileTemplate(fileName, build) {
797
+ return {
798
+ type: "file",
799
+ fileName,
800
+ build,
801
+ options: {
802
+ dependencies: [],
803
+ write: true
712
804
  }
713
- this.definitions[filePath2].definition = definition2;
714
- return true;
805
+ };
806
+ }
807
+ function withHelper(cb) {
808
+ return cb;
809
+ }
810
+
811
+ function toObject(name, map, noExport) {
812
+ const lines = [...map.entries()].map(([key, value]) => {
813
+ return `'${key}': ${value}`;
814
+ }).sort().join(",\n ");
815
+ if (noExport) {
816
+ return `
817
+ const ${name} = {
818
+ ${lines}
819
+ }
820
+ `;
715
821
  }
716
- /**
717
- * Extract the single text method calls.
718
- */
719
- extractSingle(code, filePath) {
720
- const pattern = this.composableName + "\\((\\{.+?\\})\\)";
721
- const rgx = new RegExp(pattern, "gms");
722
- const source = rgx.exec(code)?.[1];
723
- if (source) {
724
- try {
725
- const definition = eval(`(${source})`);
726
- return { definition, source };
727
- } catch (e) {
728
- console.error(
729
- `Failed to parse component "${filePath}": ${this.composableName} does not contain a valid object literal. No variables and methods are allowed inside ${this.composableName}().`,
730
- e
731
- );
732
- }
822
+ return `
823
+ export const ${name} = {
824
+ ${lines}
825
+ }
826
+ `;
827
+ }
828
+ function toImports(map) {
829
+ return [...map.entries()].map(([key, path]) => {
830
+ return `import ${key} from '${path}'`;
831
+ }).sort().join("\n");
832
+ }
833
+
834
+ const icons = defineCodeTemplate(
835
+ "icons",
836
+ (ctx) => {
837
+ const imports = /* @__PURE__ */ new Map();
838
+ const icons = /* @__PURE__ */ new Map();
839
+ const files = ctx.icons.files.values();
840
+ for (const file of files) {
841
+ const name = basename(file.filePath, ".svg").toLowerCase();
842
+ const importName = "icon_" + toValidVariableName(name);
843
+ imports.set(importName, `${file.filePath}?raw`);
844
+ icons.set(name, importName);
733
845
  }
846
+ return `${toImports(imports)}
847
+
848
+ ${toObject("icons", icons)}
849
+ `;
850
+ },
851
+ (ctx) => {
852
+ const allIconNames = [...ctx.icons.files.values()].map((file) => {
853
+ return basename(file.filePath, ".svg").toLowerCase();
854
+ }).sort().map((name) => `"${name}"`).join("\n | ");
855
+ return `
856
+ export type BlokkliIcon =
857
+ | ${allIconNames}
858
+ export const icons: Record<BlokkliIcon, string>
859
+ `;
860
+ },
861
+ {
862
+ dependencies: ["icons"]
734
863
  }
735
- /**
736
- * Read the given file and return its contents.
737
- */
738
- readFile(filePath2) {
739
- return fs.promises.readFile(filePath2).then((v) => {
740
- return v.toString();
741
- });
742
- }
743
- getFeatures() {
744
- return Object.values(this.definitions).filter(falsy);
864
+ );
865
+
866
+ const features = defineCodeTemplate(
867
+ "features",
868
+ (ctx) => {
869
+ const features = ctx.features.getEnabledFeatures().sort((a, b) => b.id.localeCompare(a.id));
870
+ const featuresComponents = /* @__PURE__ */ new Map();
871
+ const definitions = [];
872
+ const declarations = [];
873
+ const imports = /* @__PURE__ */ new Map();
874
+ for (const feature of features) {
875
+ const componentVarName = toValidVariableName(`component_${feature.id}`);
876
+ const declarationVarName = toValidVariableName(`feature_${feature.id}`);
877
+ declarations.push(
878
+ `const ${declarationVarName} = ${feature.definitionSource}`
879
+ );
880
+ definitions.push(declarationVarName);
881
+ imports.set(componentVarName, feature.componentPath);
882
+ featuresComponents.set(feature.id, componentVarName);
883
+ }
884
+ const availableFeaturesAtBuild = features.map((v) => v.id);
885
+ return `${toImports(imports)}
886
+
887
+ export const availableFeaturesAtBuild = ${JSON.stringify(
888
+ availableFeaturesAtBuild.sort()
889
+ )}
890
+
891
+ ${toObject("featureComponents", featuresComponents)}
892
+
893
+ ${declarations.join("\n\n")}
894
+
895
+ export const featureDefinitions = [
896
+ ${definitions.join(",\n ")}
897
+ ]
898
+ `;
899
+ },
900
+ (ctx) => {
901
+ const features = ctx.features.getEnabledFeatures().map((v) => v.id);
902
+ const availableFeaturesAtBuild = features;
903
+ return `
904
+ import type { BlokkliAdapter } from '${ctx.helper.relativePaths.ADAPTER}'
905
+ import type { Viewport } from '${ctx.helper.relativePaths.CONSTANTS}'
906
+ import type { Component } from 'vue'
907
+
908
+ type AdapterMethods = keyof BlokkliAdapter<any>
909
+
910
+ export type ValidFeatureKey = ${availableFeaturesAtBuild.map((v) => '"' + v + '"').join(" | ")}
911
+
912
+ export declare const featureComponents: Record<ValidFeatureKey, Component>
913
+ export declare const featureDefinitions: FeatureDefinition[]
914
+ export declare const availableFeaturesAtBuild: ValidFeatureKey[]
915
+ `;
916
+ },
917
+ {
918
+ dependencies: ["features"]
745
919
  }
746
- }
920
+ );
921
+
922
+ const featuresJson = defineFileTemplate("features-data.json", async (ctx) => {
923
+ const features = [...ctx.features.files.values()];
924
+ const featuresData = await Promise.all(
925
+ features.map(async (v) => {
926
+ const docsPath = v.filePath.replace("index.vue", "docs.md");
927
+ let docs = "";
928
+ if (ctx.helper.fileCache.fileExists(docsPath)) {
929
+ docs = await ctx.helper.fileCache.read(docsPath);
930
+ }
931
+ return {
932
+ ...v,
933
+ repoRelativePath: v.filePath.replace(/.*\/src/, "/src"),
934
+ docs
935
+ };
936
+ })
937
+ );
938
+ return JSON.stringify(featuresData, null, 2);
939
+ });
747
940
 
748
941
  const addCommentToItem$2 = {
749
942
  source: "Comment",
@@ -6103,11 +6296,65 @@ const it = {
6103
6296
  validationsTourText: validationsTourText
6104
6297
  };
6105
6298
 
6106
- const translations = {
6107
- de,
6108
- fr,
6109
- it
6110
- };
6299
+ const translations$1 = {
6300
+ de,
6301
+ fr,
6302
+ it
6303
+ };
6304
+
6305
+ const translations = defineCodeTemplate(
6306
+ "translations",
6307
+ (ctx) => {
6308
+ const translations = {};
6309
+ Object.keys(translations$1).forEach((language) => {
6310
+ translations[language] = {};
6311
+ Object.keys(translations$1[language]).forEach((key) => {
6312
+ translations[language][key] = translations$1[language][key].translation;
6313
+ });
6314
+ });
6315
+ const merged = defu(ctx.helper.options.translations, translations);
6316
+ return `export const translations = ${JSON.stringify(merged, null, 2)}`;
6317
+ },
6318
+ () => {
6319
+ return `
6320
+ export declare const translations: Record<string, Record<string, string>>
6321
+ `;
6322
+ }
6323
+ );
6324
+
6325
+ const editAdapter = defineCodeTemplate(
6326
+ "edit-adapter",
6327
+ (ctx) => {
6328
+ const pathRelative = ctx.helper.toModuleBuildRelative(
6329
+ ctx.helper.paths.editAdapter
6330
+ );
6331
+ return `
6332
+ import adapter from '${pathRelative}'
6333
+
6334
+ export default adapter
6335
+ `;
6336
+ },
6337
+ (ctx) => {
6338
+ return `
6339
+ import type { BlokkliAdapterFactory } from '${ctx.helper.relativePaths.ADAPTER}'
6340
+
6341
+ declare const adapter: BlokkliAdapterFactory<any>
6342
+
6343
+ export default adapter
6344
+ `;
6345
+ }
6346
+ );
6347
+
6348
+ const styles = defineFileTemplate("styles.css", (ctx) => {
6349
+ const cssFilePath = ctx.helper.resolvers.module.resolve(
6350
+ "./runtime/css/output.css"
6351
+ );
6352
+ return `
6353
+ @import url("${relative(ctx.helper.paths.blokkliBuildDir, cssFilePath)}");
6354
+
6355
+ ${ctx.theme.css}
6356
+ `;
6357
+ });
6111
6358
 
6112
6359
  const accent$3 = {
6113
6360
  "50": [
@@ -6873,27 +7120,871 @@ const nuxt = {
6873
7120
  lime: lime
6874
7121
  };
6875
7122
 
6876
- const themes = {
6877
- fire,
6878
- arctic,
6879
- gruvbox,
6880
- nuxt
6881
- };
6882
- const getTheme = (v) => {
6883
- if (typeof v === "string") {
6884
- if (v === "arctic") {
6885
- return themes.arctic;
6886
- } else if (v === "gruvbox") {
6887
- return themes.gruvbox;
6888
- } else if (v === "fire") {
6889
- return themes.fire;
6890
- } else if (v === "nuxt") {
6891
- return themes.nuxt;
7123
+ const themes = {
7124
+ fire,
7125
+ arctic,
7126
+ gruvbox,
7127
+ nuxt
7128
+ };
7129
+ const getTheme = (v) => {
7130
+ if (typeof v === "string") {
7131
+ if (v === "arctic") {
7132
+ return themes.arctic;
7133
+ } else if (v === "gruvbox") {
7134
+ return themes.gruvbox;
7135
+ } else if (v === "fire") {
7136
+ return themes.fire;
7137
+ } else if (v === "nuxt") {
7138
+ return themes.nuxt;
7139
+ }
7140
+ throw new Error(`Invalid theme name: ${v}`);
7141
+ }
7142
+ return v || {};
7143
+ };
7144
+
7145
+ const config = defineCodeTemplate(
7146
+ "config",
7147
+ (ctx) => {
7148
+ const settingsOverride = ctx.helper.options.settingsOverride || {};
7149
+ return `
7150
+ export const hasCustomTheme = ${JSON.stringify(ctx.theme.hasCustomTheme)}
7151
+
7152
+ export const themes = ${JSON.stringify(themes, null, 2)}
7153
+
7154
+ export const theme = ${JSON.stringify(ctx.theme.fullTheme, null, 2)}
7155
+
7156
+ export const settingsOverride = ${JSON.stringify(settingsOverride)}
7157
+
7158
+ export const blokkliVersion = ${JSON.stringify(version)}
7159
+
7160
+ export const storageDefaults = ${JSON.stringify(
7161
+ ctx.helper.options.storageDefaults || {}
7162
+ )}
7163
+ export const defaultLanguage = ${JSON.stringify(
7164
+ ctx.helper.options.defaultLanguage || "en"
7165
+ )}
7166
+ export const forceDefaultLanguage = ${JSON.stringify(
7167
+ !!ctx.helper.options.forceDefaultLanguage
7168
+ )}
7169
+ `;
7170
+ },
7171
+ (ctx) => {
7172
+ return `
7173
+ import type { Theme } from '${ctx.helper.relativePaths.TYPES_THEME}'
7174
+ import type { ModuleOptionsSettings } from '#blokkli-build/module-types'
7175
+
7176
+ /**
7177
+ * Whether the app uses a custom theme.
7178
+ */
7179
+ export declare const hasCustomTheme: boolean
7180
+
7181
+ /**
7182
+ * All available themes.
7183
+ */
7184
+ export declare const themes: Record<string, Theme>
7185
+
7186
+ /**
7187
+ * The default theme.
7188
+ */
7189
+ export declare const theme: Theme
7190
+
7191
+ /**
7192
+ * Overrides for settings.
7193
+ */
7194
+ export declare const settingsOverride: ModuleOptionsSettings
7195
+
7196
+ /**
7197
+ * The version of the @blokkli/editor package.
7198
+ */
7199
+ export declare const blokkliVersion: string
7200
+
7201
+ /**
7202
+ * Default storage settings.
7203
+ */
7204
+ export declare const storageDefaults: Record<string, string|boolean|string[]>
7205
+
7206
+ /**
7207
+ * The default/fallback language.
7208
+ */
7209
+ export declare const defaultLanguage: string
7210
+
7211
+ /**
7212
+ * Whether to always force the default language, even on translation pages.
7213
+ */
7214
+ export declare const forceDefaultLanguage: boolean
7215
+ `;
7216
+ }
7217
+ );
7218
+
7219
+ const definitions = defineCodeTemplate(
7220
+ "definitions",
7221
+ (ctx) => {
7222
+ const blocks = [];
7223
+ const fragments = [];
7224
+ const icons = /* @__PURE__ */ new Map();
7225
+ const definitions = [];
7226
+ const files = [...ctx.blocks.files.values()].sort(
7227
+ (a, b) => b.identifier.localeCompare(a.identifier)
7228
+ );
7229
+ let key = "";
7230
+ files.forEach((file) => {
7231
+ if (!file.definition || !file.definitionSource) {
7232
+ return;
7233
+ }
7234
+ const identifier = file.identifier;
7235
+ key += identifier;
7236
+ if (isBlock(file.definition)) {
7237
+ definitions.push(`const ${identifier} = ${file.definitionSource}`);
7238
+ blocks.push(identifier);
7239
+ if (file.iconContents) {
7240
+ icons.set(file.definition.bundle, JSON.stringify(file.iconContents));
7241
+ }
7242
+ } else {
7243
+ definitions.push(`const ${identifier} = ${file.definitionSource}`);
7244
+ fragments.push(identifier);
7245
+ }
7246
+ });
7247
+ const renderKey = hash(key);
7248
+ return `
7249
+ ${definitions.join("\n\n")}
7250
+
7251
+ const blocks = [
7252
+ ${blocks.join(",\n ")}
7253
+ ]
7254
+
7255
+ const fragments = [
7256
+ ${fragments.join(",\n ")}
7257
+ ]
7258
+
7259
+ ${toObject("icons", icons, true)}
7260
+
7261
+
7262
+ const globalOptions = ${JSON.stringify(ctx.helper.options.globalOptions || {})}
7263
+
7264
+ const renderKey = "${renderKey}"
7265
+
7266
+ const definitions = {
7267
+ blocks,
7268
+ fragments,
7269
+ icons,
7270
+ globalOptions,
7271
+ renderKey
7272
+ }
7273
+
7274
+ export default definitions
7275
+ `;
7276
+ },
7277
+ (ctx) => {
7278
+ const fragmentNames = [];
7279
+ for (const file of ctx.blocks.files.values()) {
7280
+ if (!file.definition) {
7281
+ continue;
7282
+ }
7283
+ if (isBlock(file.definition)) {
7284
+ continue;
7285
+ }
7286
+ fragmentNames.push(`'${file.definition.name}'`);
7287
+ }
7288
+ return `
7289
+ import type { GlobalOptionsKey, ValidFieldListTypes, BlockBundleWithNested, ValidGlobalConfigKeys } from '#blokkli-build/generated-types'
7290
+ import type { BlockDefinitionInput, BlockDefinitionOptionsInput, FragmentDefinitionInput } from '${ctx.helper.relativePaths.TYPES}'
7291
+
7292
+ export type BlockDefinition = BlockDefinitionInput<BlockDefinitionOptionsInput, GlobalOptionsKey[]>
7293
+ export type FragmentDefinition = FragmentDefinitionInput<Record<string, any>, GlobalOptionsKey[]>
7294
+
7295
+ export type BlokkliFragmentName = ${fragmentNames.join(" | ") || "never"}
7296
+
7297
+ const globalOptions = ${JSON.stringify(ctx.helper.options.globalOptions || {})} as const
7298
+
7299
+ export type GlobalOptionsType = typeof globalOptions
7300
+
7301
+ export type Definitions = {
7302
+ blocks: BlockDefinition[]
7303
+ fragments: FragmentDefinition[]
7304
+ icons: Record<string, string>
7305
+ globalOptions: BlockDefinitionOptionsInput
7306
+ renderKey: string
7307
+ }
7308
+
7309
+ const definitions: Definitions
7310
+
7311
+ export default definitions
7312
+ `;
7313
+ },
7314
+ {
7315
+ dependencies: ["block-content", "block-path"]
7316
+ }
7317
+ );
7318
+
7319
+ const moduleTypes = defineCodeTemplate(
7320
+ "module-types",
7321
+ () => {
7322
+ return `export {}`;
7323
+ },
7324
+ (ctx) => {
7325
+ const features = ctx.features.getEnabledFeatures();
7326
+ const settings = [];
7327
+ features.forEach((feature) => {
7328
+ if (feature.definition.settings) {
7329
+ Object.entries(feature.definition.settings).sort((a, b) => a[0].localeCompare(b[0])).forEach(([key, setting]) => {
7330
+ const settingsKey = `feature:${feature.id}:${key}`;
7331
+ settings.push(`/** ${setting.label} */`);
7332
+ if (setting.type === "radios") {
7333
+ const type = Object.keys(setting.options).map((v) => `'${v}'`).join(" | ");
7334
+ settings.push(
7335
+ `'${settingsKey}'?: { disable?: boolean, default?: ${type} }
7336
+ `
7337
+ );
7338
+ } else if (setting.type === "checkbox") {
7339
+ settings.push(
7340
+ `'${settingsKey}'?: { disable?: boolean, default?: boolean }
7341
+ `
7342
+ );
7343
+ } else if (setting.type === "slider") {
7344
+ settings.push(
7345
+ `'${settingsKey}'?: { disable?: boolean, default?: number }
7346
+ `
7347
+ );
7348
+ } else {
7349
+ settings.push(`'${settingsKey}'?: { disable?: boolean }
7350
+ `);
7351
+ }
7352
+ });
7353
+ }
7354
+ });
7355
+ return `
7356
+ export type ModuleOptionsSettings = {
7357
+ ${settings.join("\n ")}
7358
+ }
7359
+ `;
7360
+ },
7361
+ {
7362
+ dependencies: ["features"]
7363
+ }
7364
+ );
7365
+
7366
+ const runtimeOptions = defineCodeTemplate(
7367
+ "runtime-options",
7368
+ (ctx) => {
7369
+ const globalOptions = ctx.helper.options.globalOptions || {};
7370
+ const files = [...ctx.blocks.files.values()];
7371
+ const items = files.map((v) => {
7372
+ if (v.definition && v.identifier) {
7373
+ if (isBlock(v.definition)) {
7374
+ return {
7375
+ varName: v.identifier,
7376
+ definition: v.definition,
7377
+ variations: v.variations
7378
+ };
7379
+ }
7380
+ return {
7381
+ varName: v.identifier,
7382
+ definition: v.definition,
7383
+ variations: v.variations
7384
+ };
7385
+ }
7386
+ return null;
7387
+ }).filter(falsy);
7388
+ const declarations = [];
7389
+ const OPTIONS = /* @__PURE__ */ new Map();
7390
+ for (const item of items) {
7391
+ const optionDefinitions = Object.entries(item.definition.options || {});
7392
+ const options = {};
7393
+ if (item.definition.globalOptions) {
7394
+ item.definition.globalOptions.forEach((name) => {
7395
+ const option = globalOptions[name];
7396
+ if (option) {
7397
+ options[name] = [option.type, option.default];
7398
+ }
7399
+ });
7400
+ }
7401
+ optionDefinitions.forEach(([name, option]) => {
7402
+ options[name] = [option.type, option.default];
7403
+ });
7404
+ const hasOptions = Object.keys(options).length > 0;
7405
+ if (hasOptions) {
7406
+ declarations.push(`const ${item.varName} = ${JSON.stringify(options)}`);
7407
+ OPTIONS.set(item.varName, item.varName);
7408
+ }
7409
+ item.variations.forEach((variation) => {
7410
+ if (hasOptions) {
7411
+ OPTIONS.set(variation, item.varName);
7412
+ }
7413
+ });
7414
+ }
7415
+ return `
7416
+ ${declarations.join("\n")}
7417
+
7418
+ ${toObject("OPTIONS", OPTIONS)}
7419
+ `;
7420
+ },
7421
+ (ctx) => {
7422
+ const globalOptions = ctx.helper.options.globalOptions || {};
7423
+ const blocks = [...ctx.blocks.files.values()].map((v) => {
7424
+ if (v.definition && isBlock(v.definition)) {
7425
+ return v.definition;
7426
+ }
7427
+ return null;
7428
+ }).filter(falsy);
7429
+ function getOptionTypes(definition) {
7430
+ const definedOptions = definition.options || {};
7431
+ const blockGlobalOptions = definition.globalOptions || [];
7432
+ blockGlobalOptions.forEach((key) => {
7433
+ if (globalOptions[key]) {
7434
+ definedOptions[key] = globalOptions[key];
7435
+ }
7436
+ });
7437
+ return Object.entries(definedOptions || {}).map(([key, option]) => {
7438
+ if (option.type === "text" || option.type === "datetime-local") {
7439
+ return `${key}: string`;
7440
+ } else if (option.type === "checkbox") {
7441
+ return `${key}: boolean`;
7442
+ } else if (option.type === "checkboxes") {
7443
+ const possibleValues = Object.keys(option.options).map((v) => `'${v}'`).join(" | ") || "string";
7444
+ return `${key}: Array<${possibleValues}>`;
7445
+ } else if (option.type === "radios") {
7446
+ const possibleValues = Object.keys(option.options).map((v) => `'${v}'`).join(" | ") || "string";
7447
+ return `${key}: ${possibleValues}`;
7448
+ } else if (option.type === "color") {
7449
+ return key + ": `#${string}`";
7450
+ } else if (option.type === "range" || option.type === "number") {
7451
+ return `${key}: number`;
7452
+ }
7453
+ });
7454
+ }
7455
+ const runtimeMappedOptionTypes = blocks.map((definition) => {
7456
+ if (definition.renderFor) {
7457
+ return null;
7458
+ }
7459
+ const bundle = definition.bundle;
7460
+ const options = getOptionTypes(definition).join("\n ");
7461
+ if (!options) {
7462
+ return ` ${bundle}: {}`;
7463
+ }
7464
+ return ` ${bundle}: {
7465
+ ${options}
7466
+ }`;
7467
+ }).filter(falsy).join(",\n");
7468
+ return `
7469
+ import type { BlockOptionDefinition } from '${ctx.helper.relativePaths.TYPES_BLOKK_OPTIONS}'
7470
+
7471
+ export type RuntimeBlockOptionArray = {
7472
+ [T in BlockOptionDefinition as T['type']]: [T['type'], T['default']]
7473
+ }[BlockOptionDefinition['type']]
7474
+
7475
+ export type RuntimeBlockOptions = {
7476
+ ${runtimeMappedOptionTypes}
7477
+ }
7478
+
7479
+ export declare const OPTIONS: Record<string, Record<string, RuntimeBlockOptionArray>>
7480
+ `;
7481
+ },
7482
+ {
7483
+ dependencies: ["block-content", "block-path"]
7484
+ }
7485
+ );
7486
+
7487
+ const editComponents = defineCodeTemplate(
7488
+ "edit-components",
7489
+ (ctx) => {
7490
+ const imports = {};
7491
+ const proxyComponents = /* @__PURE__ */ new Map();
7492
+ const diffComponents = /* @__PURE__ */ new Map();
7493
+ for (const file of ctx.blocks.files.values()) {
7494
+ if (!file.definition || !isBlock(file.definition)) {
7495
+ continue;
7496
+ }
7497
+ const { bundle } = file.definition;
7498
+ if (file.proxyComponentPath) {
7499
+ const importName = "proxy_" + bundle;
7500
+ imports[importName] = file.proxyComponentPath;
7501
+ proxyComponents.set(bundle, importName);
7502
+ } else if (file.diffComponentPath) {
7503
+ const importName = "diff_" + file.definition.bundle;
7504
+ imports[importName] = file.diffComponentPath;
7505
+ diffComponents.set(bundle, importName);
7506
+ }
7507
+ }
7508
+ const importLines = Object.entries(imports).map(([variableName, path]) => {
7509
+ return `import ${variableName} from '${path}'`;
7510
+ }).join("\n");
7511
+ return `
7512
+ ${importLines}
7513
+
7514
+ ${toObject("PROXY_COMPONENTS", proxyComponents)}
7515
+
7516
+ ${toObject("DIFF_COMPONENTS", diffComponents)}
7517
+ `;
7518
+ },
7519
+ () => {
7520
+ return `
7521
+ export declare const PROXY_COMPONENTS: Record<string, any>
7522
+ export declare const DIFF_COMPONENTS: Record<string, any>
7523
+ `;
7524
+ },
7525
+ {
7526
+ dependencies: ["block-path"]
7527
+ }
7528
+ );
7529
+
7530
+ function toStringUnion(strings) {
7531
+ return strings.sort().map((v) => `'${v}'`).join(" | ") || "never";
7532
+ }
7533
+ function getOptionTypes(definition, globalOptions) {
7534
+ const definedOptions = { ...definition.options || {} };
7535
+ const blockGlobalOptions = definition.globalOptions || [];
7536
+ blockGlobalOptions.forEach((key) => {
7537
+ if (globalOptions[key]) {
7538
+ definedOptions[key] = globalOptions[key];
7539
+ }
7540
+ });
7541
+ const options = Object.entries(definedOptions || {}).map(([key, option]) => {
7542
+ if (option.type === "checkbox") {
7543
+ return `${key}: '1' | '0' | undefined`;
7544
+ } else if (option.type === "text" || option.type === "radios" || option.type === "checkboxes" || option.type === "color" || option.type === "datetime-local") {
7545
+ return `${key}: string | undefined`;
7546
+ } else if (option.type === "range" || option.type === "number") {
7547
+ return `${key}: number | string | undefined`;
7548
+ }
7549
+ }).join("\n ");
7550
+ return `{
7551
+ ${options}
7552
+ }`;
7553
+ }
7554
+ const generatedTypes = defineCodeTemplate(
7555
+ "generated-types",
7556
+ () => {
7557
+ return `export {}`;
7558
+ },
7559
+ (ctx) => {
7560
+ const mappedGetBundlePropsType = (bundle, file) => {
7561
+ if (bundle === "from_library" || bundle === "blokkli_fragment") {
7562
+ return {
7563
+ typeName: "Props",
7564
+ from: file.filePath
7565
+ };
7566
+ } else if (ctx.helper.options.getBundlePropsType) {
7567
+ return ctx.helper.options.getBundlePropsType(bundle, file);
7568
+ }
7569
+ return null;
7570
+ };
7571
+ const chunkNames = ctx.helper.options.chunkNames || ["global"];
7572
+ const fieldListTypes = ctx.helper.options.fieldListTypes || ["default"];
7573
+ const globalOptions = ctx.helper.options.globalOptions || {};
7574
+ const validGlobalOptions = Object.keys(globalOptions);
7575
+ const blockBundlesWithNested = [];
7576
+ const validBlockBundles = [];
7577
+ const propTypeImports = {};
7578
+ const propTypes = {};
7579
+ const typedFieldListItems = [];
7580
+ for (const file of ctx.blocks.files.values()) {
7581
+ if (!file.definition || !isBlock(file.definition)) {
7582
+ continue;
7583
+ }
7584
+ if (file.hasBlokkliField) {
7585
+ blockBundlesWithNested.push(file.definition.bundle);
7586
+ }
7587
+ if (file.definition.bundle !== "from_library") {
7588
+ validBlockBundles.push(file.definition.bundle);
7589
+ }
7590
+ if (!file.definition.renderFor) {
7591
+ const bundle = file.definition.bundle;
7592
+ const options = getOptionTypes(file.definition, globalOptions);
7593
+ const generatedTypeName = `FieldListItem_${bundle}`;
7594
+ const lines = [` bundle: '${bundle}'`, `options: ${options}`];
7595
+ const bundlePropsType = mappedGetBundlePropsType(bundle, file);
7596
+ if (bundlePropsType) {
7597
+ const { typeName, from } = bundlePropsType;
7598
+ if (!propTypeImports[from]) {
7599
+ propTypeImports[from] = [];
7600
+ }
7601
+ propTypeImports[from].push({ bundle, typeName });
7602
+ const tsTypeName = `Bundle_${bundle}_Props`;
7603
+ lines.push(`props: ${tsTypeName}`);
7604
+ propTypes[bundle] = tsTypeName;
7605
+ }
7606
+ const typeDefinition = `
7607
+ type ${generatedTypeName} = {
7608
+ ${lines.join("\n ")}
7609
+ }`;
7610
+ typedFieldListItems.push({
7611
+ typeName: generatedTypeName,
7612
+ typeDefinition
7613
+ });
7614
+ }
7615
+ }
7616
+ const propTypeImportStatements = Object.entries(propTypeImports).map(([from, items]) => {
7617
+ const imports = items.map((v) => {
7618
+ return `${v.typeName} as Bundle_${v.bundle}_Props`;
7619
+ }).join(", ");
7620
+ const importPath = relative(ctx.helper.paths.blokkliBuildDir, from);
7621
+ return `import type { ${imports} } from '${importPath}'`;
7622
+ }).join("\n");
7623
+ const BundleProps = Object.entries(propTypes).map(([key, type]) => {
7624
+ return `'${key}': ${type}`;
7625
+ }).join("\n ");
7626
+ return `
7627
+ ${propTypeImportStatements}
7628
+ import type { FieldListItem } from "${ctx.helper.relativePaths.TYPES}"
7629
+
7630
+ export type ValidFieldListTypes = ${toStringUnion(fieldListTypes)}
7631
+
7632
+ export type BlockBundle = ${toStringUnion(validBlockBundles)}
7633
+
7634
+ export type BlockBundleWithNested = ${toStringUnion(blockBundlesWithNested)}
7635
+
7636
+ export type ValidChunkNames = ${toStringUnion(chunkNames)}
7637
+
7638
+ export type BundleProps = {
7639
+ ${BundleProps}
7640
+ }
7641
+
7642
+ export type GlobalOptionsKey = ${toStringUnion(validGlobalOptions)}
7643
+
7644
+ export type ValidGlobalConfigKeys = Array<GlobalOptionsKey>
7645
+
7646
+ ${typedFieldListItems.map((v) => v.typeDefinition).join("\n\n")}
7647
+
7648
+ export type FieldListItemTyped = Omit<FieldListItem, 'props'> & (${typedFieldListItems.map((v) => v.typeName).sort().join(" | ")})
7649
+ export type FieldListItemTypedArray = Array<FieldListItemTyped>
7650
+ `;
7651
+ },
7652
+ {
7653
+ dependencies: ["block-path"]
7654
+ }
7655
+ );
7656
+
7657
+ const defaultGlobalOptions = defineCodeTemplate(
7658
+ "default-global-options",
7659
+ (ctx) => {
7660
+ const globalOptions = ctx.helper.options.globalOptions || {};
7661
+ const defaults = Object.entries(globalOptions).reduce(
7662
+ (acc, [key, option]) => {
7663
+ if (option.default !== void 0 && option.default !== null) {
7664
+ acc[key] = {
7665
+ default: option.default,
7666
+ type: option.type
7667
+ };
7668
+ }
7669
+ return acc;
7670
+ },
7671
+ {}
7672
+ );
7673
+ const bundlesWithVisibleLanguage = [];
7674
+ const bundlesWithHiddenGlobally = [];
7675
+ for (const file of ctx.blocks.files.values()) {
7676
+ if (!file.definition || !isBlock(file.definition)) {
7677
+ continue;
7678
+ }
7679
+ const usedGlobalOptions = file.definition.globalOptions || [];
7680
+ if (usedGlobalOptions.includes(BK_VISIBLE_LANGUAGES)) {
7681
+ bundlesWithVisibleLanguage.push(file.definition.bundle);
7682
+ }
7683
+ if (usedGlobalOptions.includes(BK_HIDDEN_GLOBALLY)) {
7684
+ bundlesWithHiddenGlobally.push(file.definition.bundle);
7685
+ }
7686
+ }
7687
+ return `
7688
+ export const bundlesWithVisibleLanguage = ${JSON.stringify(bundlesWithVisibleLanguage.sort())}
7689
+ export const bundlesWithHiddenGlobally = ${JSON.stringify(bundlesWithHiddenGlobally.sort())}
7690
+
7691
+ export const globalOptionsDefaults = ${JSON.stringify(defaults, null, 2)}`;
7692
+ },
7693
+ (ctx) => {
7694
+ return `
7695
+ import type { BlockOptionDefinition } from '${ctx.helper.relativePaths.TYPES_BLOKK_OPTIONS}'
7696
+
7697
+ type GlobalOptionsDefaults = {
7698
+ type: BlockOptionDefinition['type']
7699
+ default: any
7700
+ }
7701
+
7702
+ export declare const bundlesWithVisibleLanguage: string[]
7703
+ export declare const bundlesWithHiddenGlobally: string[]
7704
+
7705
+ export declare const globalOptionsDefaults: Record<string, GlobalOptionsDefaults>
7706
+ `;
7707
+ },
7708
+ {
7709
+ dependencies: ["block-path"]
7710
+ }
7711
+ );
7712
+
7713
+ const imports = defineCodeTemplate(
7714
+ "imports",
7715
+ (ctx) => {
7716
+ const chunkMapping = {};
7717
+ for (const file of ctx.blocks.files.values()) {
7718
+ if (!file.definition) {
7719
+ continue;
7720
+ }
7721
+ file.variations.forEach((variation) => {
7722
+ chunkMapping[variation] = file.chunkName;
7723
+ });
6892
7724
  }
6893
- throw new Error(`Invalid theme name: ${v}`);
7725
+ const lines = Object.entries(chunkMapping).map(
7726
+ ([variation, importName]) => {
7727
+ return `'${variation}': '${importName}'`;
7728
+ }
7729
+ );
7730
+ const chunks = ctx.helper.getChunkNames().map((chunkName) => {
7731
+ if (chunkName === "global") {
7732
+ return null;
7733
+ }
7734
+ return `${chunkName}: () => import('#blokkli-build/chunk-${chunkName}.js').then(v => v['${chunkName}'])`;
7735
+ }).filter(falsy).sort().join(",\n ");
7736
+ return `
7737
+ import { global } from '#blokkli-build/chunk-global.js'
7738
+
7739
+ export const chunks = {
7740
+ global,
7741
+ ${chunks}
7742
+ }
7743
+
7744
+ export const chunkMapping = {
7745
+ ${lines.sort().join(",\n ")}
7746
+ }
7747
+ `;
7748
+ },
7749
+ () => {
7750
+ return `
7751
+ import type { Component } from 'vue'
7752
+
7753
+ export type ChunkGroup = Record<string, Component | { loadComponent: () => Promise<Component> } >
7754
+ export type ChunkGroupEntry = ChunkGroup | (() => Promise<ChunkGroup>)
7755
+
7756
+ /**
7757
+ * Mapping of block/fragment variation ID to a chunk group.
7758
+ *
7759
+ * The variation is only present if its chunkName is not 'global'.
7760
+ */
7761
+ export declare const chunkMapping: Record<string, string>
7762
+
7763
+ /**
7764
+ * All available chunks.
7765
+ */
7766
+ export declare const chunks: Record<string, ChunkGroupEntry>
7767
+ `;
7768
+ },
7769
+ {
7770
+ dependencies: ["block-path", "block-content"]
6894
7771
  }
6895
- return v || {};
6896
- };
7772
+ );
7773
+
7774
+ const optionsSchema = withHelper((helper) => {
7775
+ let fileName = "options-schema.json";
7776
+ const outputPath = helper.options.schemaOptionsPath;
7777
+ if (outputPath) {
7778
+ const resolved = resolveAlias(outputPath);
7779
+ fileName = helper.resolvers.src.resolve(resolved);
7780
+ }
7781
+ return defineFileTemplate(fileName, (ctx) => {
7782
+ const globalOptions = ctx.helper.options.globalOptions || {};
7783
+ const blocks = [...ctx.blocks.files.values()];
7784
+ const schema = blocks.reduce((acc, v) => {
7785
+ if (v.definition && isBlock(v.definition)) {
7786
+ const bundle = v.definition.bundle;
7787
+ const existing = acc[v.definition.bundle] || {};
7788
+ acc[v.definition.bundle] = defu(existing, v.definition.options || {});
7789
+ const globalOptionKeys = v.definition.globalOptions || [];
7790
+ globalOptionKeys.forEach((name) => {
7791
+ if (globalOptions[name]) {
7792
+ acc[bundle][name] = globalOptions[name];
7793
+ }
7794
+ });
7795
+ }
7796
+ return acc;
7797
+ }, {});
7798
+ const sorted = sortObjectKeys(schema);
7799
+ return JSON.stringify(sorted, null, 2);
7800
+ });
7801
+ });
7802
+
7803
+ const chunkGroup = withHelper((helper) => {
7804
+ return helper.getChunkNames().map((chunkName) => {
7805
+ return defineCodeTemplate(
7806
+ "chunk-" + chunkName,
7807
+ (ctx) => {
7808
+ const imports = [];
7809
+ const map = {};
7810
+ for (const file of ctx.blocks.files.values()) {
7811
+ if (!file.definition) {
7812
+ continue;
7813
+ }
7814
+ if (!fs.existsSync(file.filePath)) {
7815
+ continue;
7816
+ }
7817
+ if (file.chunkName !== chunkName) {
7818
+ continue;
7819
+ }
7820
+ if (helper.isDev) {
7821
+ imports.push(
7822
+ `const ${file.identifier} = () => import('${file.filePath}').then(v => v.default)`
7823
+ );
7824
+ file.variations.forEach((variation) => {
7825
+ map[variation] = `{ loadComponent: ${file.identifier} }`;
7826
+ });
7827
+ } else {
7828
+ imports.push(`import ${file.identifier} from '${file.filePath}'`);
7829
+ file.variations.forEach((variation) => {
7830
+ map[variation] = file.identifier;
7831
+ });
7832
+ }
7833
+ }
7834
+ const lines = Object.entries(map).map(([variation, importName]) => {
7835
+ return `'${variation}': ${importName}`;
7836
+ });
7837
+ return `
7838
+ ${imports.sort().join("\n")}
7839
+
7840
+ export const ${chunkName} = {
7841
+ ${lines.sort().join(",\n ")}
7842
+ }
7843
+ `;
7844
+ },
7845
+ () => {
7846
+ return `
7847
+ import type { Component } from 'vue'
7848
+ export declare const ${chunkName}: Record<string, { loadComponent: () => Promise<Component> } | Component>
7849
+ `;
7850
+ },
7851
+ {
7852
+ dependencies: ["block-path", "block-content"]
7853
+ }
7854
+ );
7855
+ });
7856
+ });
7857
+
7858
+ const TEMPLATES = [
7859
+ icons,
7860
+ features,
7861
+ featuresJson,
7862
+ translations,
7863
+ editAdapter,
7864
+ styles,
7865
+ config,
7866
+ definitions,
7867
+ moduleTypes,
7868
+ runtimeOptions,
7869
+ editComponents,
7870
+ generatedTypes,
7871
+ defaultGlobalOptions,
7872
+ imports,
7873
+ optionsSchema,
7874
+ chunkGroup
7875
+ ];
7876
+
7877
+ class CollectedFeatureFile extends CollectedFile {
7878
+ definition = null;
7879
+ composableName = "defineBlokkliFeature";
7880
+ enabled = true;
7881
+ objectLiteral = void 0;
7882
+ getDefinition() {
7883
+ return this.definition;
7884
+ }
7885
+ async handleChange() {
7886
+ const objectLiteral = extractObjectLiteral(this.fileContents, [
7887
+ this.composableName
7888
+ ]);
7889
+ if (this.objectLiteral === objectLiteral) {
7890
+ return false;
7891
+ }
7892
+ this.objectLiteral = objectLiteral;
7893
+ if (!this.objectLiteral) {
7894
+ return false;
7895
+ }
7896
+ try {
7897
+ const { object: definition, source } = parseTsObject(
7898
+ this.objectLiteral
7899
+ );
7900
+ const regex = /\/Features\/([^/]+)\//;
7901
+ const componentName = this.filePath.match(regex)?.[1] || "";
7902
+ this.definition = {
7903
+ id: definition.id,
7904
+ componentName,
7905
+ componentPath: this.filePath,
7906
+ definition,
7907
+ definitionSource: source
7908
+ };
7909
+ } catch (e) {
7910
+ console.error(
7911
+ `Failed to parse component "${this.filePath}": ${this.composableName} does not contain a valid object literal. No variables and methods are allowed inside ${this.composableName}().`,
7912
+ e
7913
+ );
7914
+ }
7915
+ return Promise.resolve(true);
7916
+ }
7917
+ isEnabled() {
7918
+ return this.enabled;
7919
+ }
7920
+ /**
7921
+ * Disable the feature.
7922
+ */
7923
+ disable() {
7924
+ this.enabled = false;
7925
+ }
7926
+ }
7927
+ class FeatureCollector extends Collector {
7928
+ needsFileContents = true;
7929
+ disabledFeatures = /* @__PURE__ */ new Set();
7930
+ srcFromModule;
7931
+ constructor(helper) {
7932
+ super(helper);
7933
+ this.srcFromModule = helper.resolvers.module.resolve(
7934
+ "./runtime/components/Edit/Features"
7935
+ );
7936
+ }
7937
+ getEnabledFeatures() {
7938
+ return [...this.files.values()].filter((v) => v.isEnabled()).map((v) => v.getDefinition()).filter(falsy).filter((v) => !this.disabledFeatures.has(v.id));
7939
+ }
7940
+ async init() {
7941
+ const builtinFeatures = await resolveFiles(
7942
+ this.srcFromModule,
7943
+ ["*/index.vue"],
7944
+ {
7945
+ followSymbolicLinks: false
7946
+ }
7947
+ );
7948
+ const customFeatures = this.helper.options.featureImports ? await resolveFiles(
7949
+ this.helper.paths.srcDir,
7950
+ this.helper.options.featureImports,
7951
+ {
7952
+ followSymbolicLinks: false
7953
+ }
7954
+ ) : [];
7955
+ await Promise.all(
7956
+ [...builtinFeatures, ...customFeatures].map((v) => this.addFile(v))
7957
+ );
7958
+ const features = [...this.files.values()];
7959
+ if (!this.helper.options.enableThemeEditor) {
7960
+ const themeFeature = features.find(
7961
+ (v) => v.getDefinition()?.id === "theme"
7962
+ );
7963
+ if (themeFeature) {
7964
+ themeFeature.disable();
7965
+ }
7966
+ }
7967
+ }
7968
+ runHooks() {
7969
+ return this.helper.nuxt.hooks.callHook("blokkli:alter-features", {
7970
+ features: [...this.files.values()]
7971
+ });
7972
+ }
7973
+ createCollectedFile(filePath, fileContents = "") {
7974
+ return new CollectedFeatureFile(filePath, fileContents);
7975
+ }
7976
+ applies(filePath) {
7977
+ return Promise.resolve(
7978
+ filePath.startsWith(this.srcFromModule) || micromatch.isMatch(filePath, "icon-blokkli-*.svg")
7979
+ );
7980
+ }
7981
+ getDependencyTypes() {
7982
+ return ["features"];
7983
+ }
7984
+ disableFeature(id) {
7985
+ this.disabledFeatures.add(id);
7986
+ }
7987
+ }
6897
7988
 
6898
7989
  function hexToRgb(hex) {
6899
7990
  if (hex.startsWith("#")) {
@@ -6907,21 +7998,6 @@ function hexToRgb(hex) {
6907
7998
  const b = Number.parseInt(hex.slice(4, 6), 16);
6908
7999
  return [r, g, b];
6909
8000
  }
6910
- function onlyUnique(value, index, self) {
6911
- return self.indexOf(value) === index;
6912
- }
6913
- const fileExists = (path, extensions = ["js", "ts"]) => {
6914
- if (!path) {
6915
- return null;
6916
- } else if (existsSync(path)) {
6917
- return path;
6918
- }
6919
- const extension = extensions.find(
6920
- (extension2) => existsSync(`${path}.${extension2}`)
6921
- );
6922
- return extension ? `${path}.${extension}` : null;
6923
- };
6924
- const POSSIBLE_EXTENSIONS = [".js", ".ts", ".vue", ".mjs"];
6925
8001
  const buildThemeData = (themeOption) => {
6926
8002
  const hasCustomTheme = !!themeOption;
6927
8003
  const mergeTheme = createDefu((obj, key, value) => {
@@ -6958,17 +8034,29 @@ const buildThemeData = (themeOption) => {
6958
8034
  );
6959
8035
  return { themeCss, fullTheme, hasCustomTheme };
6960
8036
  };
8037
+ class ThemeData {
8038
+ css;
8039
+ fullTheme;
8040
+ hasCustomTheme;
8041
+ constructor(helper) {
8042
+ const data = buildThemeData(helper.options.theme);
8043
+ this.css = data.themeCss;
8044
+ this.fullTheme = data.fullTheme;
8045
+ this.hasCustomTheme = data.hasCustomTheme;
8046
+ }
8047
+ }
8048
+
6961
8049
  const module = defineNuxtModule({
6962
8050
  meta: {
6963
8051
  name: "blokkli",
6964
8052
  configKey: "blokkli",
6965
8053
  version,
6966
8054
  compatibility: {
6967
- nuxt: "^3.12.0"
8055
+ nuxt: "^3.15.0"
6968
8056
  }
6969
8057
  },
6970
8058
  defaults: {
6971
- pattern: ["components/Blokkli/**/*.{js,ts,vue}"],
8059
+ pattern: ["components/Blokkli/**/*.vue"],
6972
8060
  globalOptions: {
6973
8061
  [BK_VISIBLE_LANGUAGES]: {
6974
8062
  type: "checkboxes",
@@ -6986,432 +8074,83 @@ const module = defineNuxtModule({
6986
8074
  itemEntityType: "block"
6987
8075
  },
6988
8076
  async setup(moduleOptions, nuxt) {
6989
- const srcDir = nuxt.options.srcDir;
6990
- const srcResolver = createResolver(srcDir);
6991
- const moduleDir = import.meta.url;
6992
- const resolver = createResolver(moduleDir);
6993
- const featureFolder = resolver.resolve("./runtime/components/Edit/Features");
6994
- const featureExtractor = new Extractor(!nuxt.options.dev);
6995
- const builtinFeatures = await resolveFiles(featureFolder, ["*/index.vue"], {
6996
- followSymbolicLinks: false
6997
- });
6998
- const customFeatures = moduleOptions.featureImports ? await resolveFiles(srcDir, moduleOptions.featureImports, {
6999
- followSymbolicLinks: false
7000
- }) : [];
7001
- await featureExtractor.addFiles([...builtinFeatures, ...customFeatures]);
7002
- const extractedFeatures = featureExtractor.getFeatures();
7003
- const features = extractedFeatures.filter((v) => {
7004
- return v.id !== "theme" || moduleOptions.enableThemeEditor;
7005
- });
7006
- const featuresContext = {
7007
- features
7008
- };
7009
- if (moduleOptions.alterFeatures) {
7010
- featuresContext.features = await Promise.resolve(
7011
- moduleOptions.alterFeatures(featuresContext)
7012
- );
7013
- }
7014
- const allFeatureIds = [
7015
- ...extractedFeatures.map((v) => v.id),
7016
- ...featuresContext.features.map((v) => v.id)
7017
- ].filter(onlyUnique);
7018
- const featureComponents = addTemplate({
7019
- write: true,
7020
- filename: "blokkli/features.ts",
7021
- getContents: () => {
7022
- const features2 = featuresContext.features.map((v) => {
7023
- const importName = `Feature_${v.componentName}`;
7024
- return {
7025
- id: v.id,
7026
- componentName: v.componentPath,
7027
- importName,
7028
- importStatement: `import ${importName} from '${v.componentPath}'`,
7029
- definition: v.definition
7030
- };
7031
- });
7032
- const imports = features2.map((v) => {
7033
- return v.importStatement;
7034
- }).join("\n");
7035
- const availableFeaturesAtBuild = featuresContext.features.map(
7036
- (v) => v.id
7037
- );
7038
- const featuresArray = features2.map((v) => {
7039
- return `{
7040
- id: "${v.id}",
7041
- dependencies: ${JSON.stringify(v.definition.dependencies || [])},
7042
- viewports: ${JSON.stringify(v.definition.viewports || [])},
7043
- component: ${v.importName},
7044
- requiredAdapterMethods: ${JSON.stringify(
7045
- v.definition.requiredAdapterMethods || []
7046
- )},
7047
- label: ${JSON.stringify(v.definition.label || "")},
7048
- beta: ${JSON.stringify(!!v.definition.beta)},
7049
- description: "${v.definition.description || ""}"
7050
- }`;
7051
- }).join(",\n");
7052
- return `${imports}
7053
- import type { BlokkliAdapter } from '#blokkli/adapter'
7054
- import type { Viewport } from '#blokkli/constants'
7055
- type AdapterMethods = keyof BlokkliAdapter<any>
7056
-
7057
- export const availableFeaturesAtBuild = ${JSON.stringify(
7058
- availableFeaturesAtBuild
7059
- )} as const
7060
-
7061
- export type ValidFeatureKey = ${allFeatureIds.map((v) => '"' + v + '"').join(" | ")}
7062
-
7063
- type FeatureComponent = {
7064
- id: ValidFeatureKey
7065
- component: any
7066
- requiredAdapterMethods: AdapterMethods[]
7067
- dependencies: ValidFeatureKey[]
7068
- description: string
7069
- label: string
7070
- beta: boolean
7071
- viewports: Viewport[]
7072
- }
7073
-
7074
- export const featureComponents: FeatureComponent[] = [
7075
- ${featuresArray}
7076
- ]
7077
- `;
7078
- },
7079
- options: {
7080
- blokkli: true
7081
- }
7082
- });
7083
- nuxt.options.alias["#blokkli-runtime/features"] = featureComponents.dst;
7084
- addTemplate({
7085
- write: true,
7086
- filename: "blokkli/features.json",
7087
- getContents: async () => {
7088
- const featuresData = await Promise.all(
7089
- featuresContext.features.map(async (v) => {
7090
- const docsPath = v.filePath.replace("index.vue", "docs.md");
7091
- let docs = "";
7092
- if (fileExists(docsPath)) {
7093
- docs = await promises.readFile(docsPath).then((v2) => v2.toString());
7094
- }
7095
- return {
7096
- ...v,
7097
- repoRelativePath: v.filePath.replace(/.*\/src/, "/src"),
7098
- docs
7099
- };
7100
- })
7101
- );
7102
- return JSON.stringify(featuresData, null, 2);
7103
- },
7104
- options: {
7105
- blokkli: true
7106
- }
7107
- });
7108
- function getChunkNames() {
7109
- const chunkNames = [...moduleOptions.chunkNames || []];
7110
- if (!chunkNames.includes("global")) {
7111
- chunkNames.push("global");
7112
- }
7113
- return chunkNames.filter(onlyUnique);
7114
- }
7115
- function getFieldListTypes() {
7116
- const types = [...moduleOptions.fieldListTypes || []];
7117
- if (!types.includes("default")) {
7118
- types.push("default");
8077
+ const blokkliModules = moduleOptions.modules || [];
8078
+ for (const module of blokkliModules) {
8079
+ if (module.init.alterOptions) {
8080
+ module.init.alterOptions(moduleOptions);
7119
8081
  }
7120
- return types.filter(onlyUnique);
7121
- }
7122
- const importPattern = moduleOptions.pattern || [];
7123
- const featureIsEnabled = (id) => featuresContext.features.some((v) => v.id === id);
7124
- if (featureIsEnabled("library")) {
7125
- importPattern.push(
7126
- resolver.resolve("./runtime/components/Blocks/FromLibrary/*.vue")
7127
- );
7128
8082
  }
7129
- if (featureIsEnabled("fragments")) {
7130
- importPattern.push(
7131
- resolver.resolve("./runtime/components/Blocks/Fragment/*.vue")
7132
- );
8083
+ const helper = new ModuleHelper(nuxt, import.meta.url, moduleOptions);
8084
+ const theme = new ThemeData(helper);
8085
+ const iconCollector = new IconCollector(helper);
8086
+ const featureCollector = new FeatureCollector(helper);
8087
+ const blockCollector = new BlockCollector(helper);
8088
+ const collectors = [
8089
+ iconCollector,
8090
+ featureCollector,
8091
+ blockCollector
8092
+ ];
8093
+ await Promise.all(collectors.map((v) => v.init()));
8094
+ await Promise.all(collectors.map((v) => v.runHooks()));
8095
+ const context = new ModuleContext(
8096
+ helper,
8097
+ iconCollector,
8098
+ featureCollector,
8099
+ blockCollector,
8100
+ theme
8101
+ );
8102
+ const app = {
8103
+ helper,
8104
+ context
8105
+ };
8106
+ for (const module of blokkliModules) {
8107
+ await module.init.setup(app, module.options);
7133
8108
  }
7134
- const files = await resolveFiles(srcDir, importPattern, {
7135
- followSymbolicLinks: false
7136
- });
7137
- const blockExtractor = new BlockExtractor(!nuxt.options.dev);
7138
- await blockExtractor.addFiles(files);
7139
- const templateDefinitions = addTemplate({
7140
- write: true,
7141
- filename: "blokkli/definitions.ts",
7142
- getContents: () => {
7143
- return blockExtractor.generateDefinitionTemplate(
7144
- moduleOptions.globalOptions
7145
- );
7146
- },
7147
- options: {
7148
- blokkli: true
7149
- }
7150
- });
7151
- nuxt.options.alias["#blokkli/definitions"] = templateDefinitions.dst;
7152
- const templateTranslations = addTemplate({
7153
- write: true,
7154
- filename: "blokkli/translations.ts",
7155
- getContents: () => {
7156
- const translations$1 = {};
7157
- Object.keys(translations).forEach((language) => {
7158
- translations$1[language] = {};
7159
- Object.keys(translations[language]).forEach((key) => {
7160
- translations$1[language][key] = translations[language][key].translation;
7161
- });
8109
+ TEMPLATES.forEach((v) => {
8110
+ if (typeof v === "function") {
8111
+ const result = v(helper);
8112
+ const templates = Array.isArray(result) ? result : [result];
8113
+ templates.forEach((template) => {
8114
+ context.addTemplate(template);
7162
8115
  });
7163
- const merged = defu(moduleOptions.translations, translations$1);
7164
- return `export const translations = ${JSON.stringify(merged, null, 2)}`;
7165
- },
7166
- options: {
7167
- blokkli: true
8116
+ } else {
8117
+ context.addTemplate(v);
7168
8118
  }
7169
8119
  });
7170
- nuxt.options.alias["#blokkli/translations"] = templateTranslations.dst;
8120
+ await context.generateTemplates();
8121
+ helper.addAlias("#blokkli-build", helper.paths.blokkliBuildDir);
8122
+ const moduleDir = import.meta.url;
8123
+ const resolver = createResolver(moduleDir);
7171
8124
  nuxt.options.runtimeConfig.public.blokkli = {
7172
8125
  itemEntityType: moduleOptions.itemEntityType || "",
7173
8126
  defaultLanguage: moduleOptions.defaultLanguage || "en"
7174
8127
  };
7175
- const resolvedPath = "~/app/blokkli.editAdapter".replace(/^(~~|@@)/, nuxt.options.rootDir).replace(/^(~|@)/, nuxt.options.srcDir);
7176
- const adapterTemplate = (() => {
7177
- const resolvedFilename = `blokkli.editAdapter.ts`;
7178
- const maybeUserFile = fileExists(resolvedPath, ["ts"]);
7179
- if (!maybeUserFile) {
7180
- throw new Error(
7181
- "Missing blokkli adapter file in ~/app/blokkli.editAdapter.ts"
7182
- );
7183
- }
7184
- return addTemplate({
7185
- filename: resolvedFilename,
7186
- write: true,
7187
- getContents: () => `
7188
- import type { BlokkliAdapterFactory } from '#blokkli/adapter'
7189
- import adapter from '${resolvedPath}'
7190
-
7191
- export default adapter as BlokkliAdapterFactory<any>
7192
- `
7193
- });
7194
- })();
7195
- nuxt.options.alias["#blokkli/compiled-edit-adapter"] = adapterTemplate.dst;
7196
8128
  nuxt.options.build.transpile.push(resolver.resolve("runtime"));
7197
- addComponent({
7198
- filePath: resolver.resolve("./runtime/components/BlokkliField"),
7199
- name: "BlokkliField",
7200
- global: true
7201
- });
7202
- addComponent({
7203
- filePath: resolver.resolve("./runtime/components/BlokkliEditable"),
7204
- name: "BlokkliEditable",
7205
- global: true
7206
- });
7207
- addComponent({
7208
- filePath: resolver.resolve("./runtime/components/BlokkliProvider"),
7209
- name: "BlokkliProvider",
7210
- global: true
7211
- });
7212
- addComponent({
7213
- filePath: resolver.resolve("./runtime/components/BlokkliItem"),
7214
- name: "BlokkliItem",
7215
- global: true
7216
- });
7217
- addBuildPlugin(DefinitionPlugin(nuxt));
7218
- addImports({
7219
- name: "defineBlokkli",
7220
- from: resolver.resolve("./runtime/composables/defineBlokkli"),
7221
- as: "defineBlokkli"
7222
- });
7223
- addImports({
7224
- name: "defineBlokkliFragment",
7225
- from: resolver.resolve("./runtime/composables/defineBlokkliFragment"),
7226
- as: "defineBlokkliFragment"
7227
- });
7228
- addImports({
7229
- name: "defineBlokkliFeature",
7230
- from: resolver.resolve("./runtime/composables/defineBlokkliFeature"),
7231
- as: "defineBlokkliFeature"
7232
- });
7233
- addImports({
7234
- name: "useBlokkli",
7235
- from: resolver.resolve("./runtime/composables/useBlokkli"),
7236
- as: "useBlokkli"
7237
- });
7238
- nuxt.options.alias["#blokkli/styles"] = resolver.resolve(
7239
- "./runtime/css/output.css"
7240
- );
7241
- const templateGeneratedTypes = addTemplate({
7242
- write: true,
7243
- filename: "blokkli/generated-types.ts",
7244
- getContents: () => {
7245
- return blockExtractor.generateTypesTemplate(
7246
- moduleOptions.globalOptions || {},
7247
- getChunkNames(),
7248
- getFieldListTypes()
7249
- );
7250
- },
7251
- options: {
7252
- blokkli: true
7253
- }
7254
- });
7255
- nuxt.options.alias["#blokkli/generated-types"] = templateGeneratedTypes.dst;
7256
- const { themeCss, fullTheme, hasCustomTheme } = buildThemeData(
7257
- moduleOptions.theme
8129
+ helper.addComponent("BlokkliField");
8130
+ helper.addComponent("BlokkliEditable");
8131
+ helper.addComponent("BlokkliProvider");
8132
+ helper.addComponent("BlokkliItem");
8133
+ helper.addComposable("defineBlokkli");
8134
+ helper.addComposable("defineBlokkliFragment");
8135
+ helper.addComposable("defineBlokkliFeature");
8136
+ helper.addComposable("useBlokkli");
8137
+ helper.addAlias("#blokkli-build", helper.paths.blokkliBuildDir);
8138
+ helper.addAlias("#blokkli/types", resolver.resolve("runtime/types"));
8139
+ helper.addAlias("#blokkli/constants", resolver.resolve("runtime/constants"));
8140
+ helper.addAlias(
8141
+ "#blokkli/plugins",
8142
+ resolver.resolve("runtime/blokkliPlugins")
7258
8143
  );
7259
- const templateThemeCss = addTemplate({
7260
- write: true,
7261
- filename: "blokkli/theme.css",
7262
- getContents: () => {
7263
- return themeCss;
7264
- },
7265
- options: {
7266
- blokkli: true
7267
- }
7268
- });
7269
- nuxt.options.alias["#blokkli/theme"] = templateThemeCss.dst;
7270
- const templateConfig = addTemplate({
7271
- write: true,
7272
- filename: "blokkli/config.ts",
7273
- getContents: () => {
7274
- const settingsOverride = moduleOptions.settingsOverride || {};
7275
- return `import type { Theme } from '#blokkli/types/theme'
7276
- import type { ModuleOptionsSettings } from '#blokkli/types/generatedModuleTypes'
7277
-
7278
- export const hasCustomTheme = ${JSON.stringify(hasCustomTheme)}
7279
- export const themes: Record<string, Theme> = ${JSON.stringify(themes, null, 2)}
7280
- export const theme: Theme = ${JSON.stringify(fullTheme, null, 2)}
7281
-
7282
- export const settingsOverride: ModuleOptionsSettings = ${JSON.stringify(
7283
- settingsOverride
7284
- )}
7285
-
7286
- export const blokkliVersion = ${JSON.stringify(version)}
7287
-
7288
- export const storageDefaults: Record<string, string|boolean|string[]> = ${JSON.stringify(
7289
- moduleOptions.storageDefaults || {}
7290
- )}
7291
- export const defaultLanguage: string = ${JSON.stringify(
7292
- moduleOptions.defaultLanguage || "en"
7293
- )}
7294
- export const forceDefaultLanguage: boolean = ${JSON.stringify(
7295
- !!moduleOptions.forceDefaultLanguage
7296
- )}
7297
- `;
7298
- },
7299
- options: {
7300
- blokkli: true
7301
- }
7302
- });
7303
- nuxt.options.alias["#blokkli/config"] = templateConfig.dst;
7304
- const templateDefaultGlobalOptions = addTemplate({
7305
- write: true,
7306
- filename: "blokkli/default-global-options.ts",
7307
- getContents: () => {
7308
- return blockExtractor.generateDefaultGlobalOptions(
7309
- moduleOptions.globalOptions || {}
7310
- );
7311
- },
7312
- options: {
7313
- blokkli: true
7314
- }
7315
- });
7316
- nuxt.options.alias["#blokkli/default-global-options"] = templateDefaultGlobalOptions.dst;
7317
- let optionsSchemaTemplate = null;
7318
- const generateOptionsSchema = async () => {
7319
- const outputPath = moduleOptions.schemaOptionsPath;
7320
- if (outputPath) {
7321
- const resolvedPath2 = await srcResolver.resolvePath(outputPath);
7322
- const content = blockExtractor.generateOptionsSchema(
7323
- moduleOptions.globalOptions || {}
7324
- );
7325
- return promises.writeFile(resolvedPath2, content);
7326
- }
7327
- if (optionsSchemaTemplate) {
7328
- return;
7329
- }
7330
- optionsSchemaTemplate = addTemplate({
7331
- write: true,
7332
- filename: "blokkli/options-schema.json",
7333
- getContents: () => {
7334
- return blockExtractor.generateOptionsSchema(
7335
- moduleOptions.globalOptions || {}
7336
- );
7337
- },
7338
- options: {
7339
- blokkli: true
7340
- }
7341
- });
7342
- };
7343
- await generateOptionsSchema();
7344
- getChunkNames().forEach((chunkName) => {
7345
- if (chunkName !== "global" && !nuxt.options.dev) {
7346
- const template = addTemplate({
7347
- write: true,
7348
- filename: `blokkli/chunk-${chunkName}.ts`,
7349
- getContents: () => {
7350
- return blockExtractor.generateChunkGroupTemplate(chunkName);
7351
- },
7352
- options: {
7353
- blokkli: true
7354
- }
7355
- });
7356
- nuxt.options.alias["#blokkli/chunk-" + chunkName] = template.dst;
7357
- }
7358
- });
7359
- const templateImports = addTemplate({
7360
- write: true,
7361
- filename: "blokkli/imports.ts",
7362
- getContents: () => {
7363
- return blockExtractor.generateImportsTemplate(
7364
- nuxt.options.dev ? ["global"] : getChunkNames()
7365
- );
7366
- },
7367
- options: {
7368
- blokkli: true
7369
- }
7370
- });
7371
- const templateIcons = addTemplate({
7372
- write: true,
7373
- filename: "blokkli/icons.ts",
7374
- getContents: async () => {
7375
- const pathModule = resolver.resolve("./runtime/icons");
7376
- const filesModule = await resolveFiles(pathModule, "*.svg");
7377
- const filesApp = await resolveFiles(
7378
- srcDir,
7379
- "components/**/icon-blokkli-*.svg"
7380
- );
7381
- const icons = await Promise.all(
7382
- [...filesModule, ...filesApp].map((filePath) => {
7383
- return promises.readFile(filePath).then((data) => {
7384
- const name = basename(filePath, ".svg").toLowerCase();
7385
- return {
7386
- markup: data.toString(),
7387
- name
7388
- };
7389
- });
7390
- })
7391
- );
7392
- const iconMap = icons.reduce((acc, v) => {
7393
- acc[v.name] = v.markup;
7394
- return acc;
7395
- }, {});
7396
- return `export const icons = ${JSON.stringify(iconMap)} as const
7397
- export type BlokkliIcon = keyof typeof icons`;
7398
- },
7399
- options: {
7400
- blokkli: true
7401
- }
7402
- });
7403
- nuxt.options.alias["#blokkli/icons"] = templateIcons.dst;
7404
- nuxt.options.alias["#blokkli/imports"] = templateImports.dst;
7405
- nuxt.options.alias["#blokkli/types"] = resolver.resolve("runtime/types");
7406
- nuxt.options.alias["#blokkli/constants"] = resolver.resolve("runtime/constants");
7407
- nuxt.options.alias["#blokkli/plugins"] = resolver.resolve(
7408
- "runtime/blokkliPlugins"
8144
+ helper.addAlias(
8145
+ "#blokkli/components",
8146
+ resolver.resolve("runtime/components/Edit")
7409
8147
  );
7410
- nuxt.options.alias["#blokkli/components"] = resolver.resolve(
7411
- "runtime/components/Edit"
8148
+ helper.addAlias("#blokkli/helpers", resolver.resolve("runtime/helpers"));
8149
+ helper.addAlias("#blokkli/adapter", resolver.resolve("runtime/adapter"));
8150
+ helper.addAlias(
8151
+ "#blokkli/runtime-helpers",
8152
+ resolver.resolve("runtime/helpers/runtimeHelpers")
7412
8153
  );
7413
- nuxt.options.alias["#blokkli/helpers"] = resolver.resolve("runtime/helpers");
7414
- nuxt.options.alias["#blokkli/adapter"] = resolver.resolve("runtime/adapter");
7415
8154
  nuxt.hook("nitro:config", (nitroConfig) => {
7416
8155
  nitroConfig.publicAssets ||= [];
7417
8156
  nitroConfig.publicAssets.push({
@@ -7423,43 +8162,22 @@ export type BlokkliIcon = keyof typeof icons`;
7423
8162
  addPlugin({
7424
8163
  src: resolver.resolve("runtime/plugins/blokkliEditable")
7425
8164
  });
7426
- const applies = (path) => {
7427
- const filePath = srcResolver.resolve(path);
7428
- if (!POSSIBLE_EXTENSIONS.includes(extname(filePath))) {
7429
- return Promise.resolve(void 0);
7430
- }
7431
- return resolveFiles(srcDir, importPattern, {
7432
- followSymbolicLinks: false
7433
- }).then((files2) => {
7434
- return files2.find((v) => v === filePath);
7435
- });
7436
- };
8165
+ addBuildPlugin(RuntimeDefinitionPlugin(nuxt, "defineBlokkli"));
8166
+ addBuildPlugin(RuntimeDefinitionPlugin(nuxt, "defineBlokkliFragment"));
7437
8167
  if (nuxt.options.dev) {
7438
- nuxt.hook("vite:serverCreated", (viteServer) => {
7439
- nuxt.hook("builder:watch", async (_event, path) => {
7440
- const filePath = await applies(path);
7441
- if (!filePath) {
7442
- return;
7443
- }
7444
- const hasChanged = await blockExtractor.handleFile(filePath);
7445
- if (!hasChanged) {
7446
- return;
7447
- }
7448
- await updateTemplates({
7449
- filter: (template) => {
7450
- return template.options && template.options.blokkli;
7451
- }
7452
- });
7453
- await generateOptionsSchema();
7454
- const modules = viteServer.moduleGraph.getModulesByFile(
7455
- templateDefinitions.dst
7456
- );
7457
- if (modules) {
7458
- modules.forEach((v) => {
7459
- viteServer.reloadModule(v);
7460
- });
8168
+ nuxt.hook("builder:watch", async (event, providedFilePath) => {
8169
+ const filePath = providedFilePath.startsWith("/") ? providedFilePath : helper.resolvers.src.resolve(providedFilePath);
8170
+ helper.fileCache.handleWatchEvent(event, filePath);
8171
+ const dependenciesToUpdate = [];
8172
+ for (const collector of collectors) {
8173
+ const result = await collector.handleWatchEvent(event, filePath);
8174
+ if (result.hasChanged) {
8175
+ dependenciesToUpdate.push(...collector.getDependencyTypes());
7461
8176
  }
7462
- });
8177
+ }
8178
+ if (dependenciesToUpdate.length) {
8179
+ await context.generateTemplates(dependenciesToUpdate);
8180
+ }
7463
8181
  });
7464
8182
  }
7465
8183
  }