@silexlabs/silex 3.0.1-alpha.0 → 3.0.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 (323) hide show
  1. package/.env.default +20 -0
  2. package/.silex.js +67 -8
  3. package/LICENSE +661 -203
  4. package/README.md +37 -35
  5. package/dist/client/client/api.d.ts +90 -0
  6. package/dist/client/client/assetUrl.d.ts +54 -0
  7. package/dist/client/client/config.d.ts +102 -0
  8. package/dist/client/client/events.d.ts +23 -0
  9. package/dist/client/client/expose.d.ts +8 -0
  10. package/dist/client/client/grapesjs/LoginDialog.d.ts +15 -0
  11. package/dist/client/client/grapesjs/PublicationManager.d.ts +73 -0
  12. package/dist/client/client/grapesjs/PublicationUi.d.ts +59 -0
  13. package/dist/client/client/grapesjs/blocks.d.ts +1 -0
  14. package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
  15. package/dist/client/client/grapesjs/css-props.d.ts +6 -0
  16. package/dist/client/client/grapesjs/footer.d.ts +2 -0
  17. package/dist/client/client/grapesjs/img.d.ts +6 -0
  18. package/dist/client/client/grapesjs/index.d.ts +9 -0
  19. package/dist/client/client/grapesjs/internal-links.d.ts +1 -0
  20. package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
  21. package/dist/client/client/grapesjs/new-page-dialog.d.ts +2 -0
  22. package/dist/client/client/grapesjs/openImport.d.ts +9 -0
  23. package/dist/client/client/grapesjs/page-panel.d.ts +9 -0
  24. package/dist/client/client/grapesjs/project-bar.d.ts +21 -0
  25. package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
  26. package/dist/client/client/grapesjs/rich-text.d.ts +4 -0
  27. package/dist/client/client/grapesjs/semantic.d.ts +1 -0
  28. package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
  29. package/dist/client/client/grapesjs/settings.d.ts +4 -0
  30. package/dist/client/client/grapesjs/storage.d.ts +2 -0
  31. package/dist/client/client/grapesjs/symbolDialogs.d.ts +3 -0
  32. package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
  33. package/dist/client/client/index.d.ts +10 -0
  34. package/dist/client/client/publication-transformers.d.ts +42 -0
  35. package/dist/client/client/publish-custom-code-block.d.ts +4 -0
  36. package/dist/client/client/publish-fonts.d.ts +4 -0
  37. package/dist/client/client/utils.d.ts +22 -0
  38. package/dist/client/constants.d.ts +32 -0
  39. package/dist/client/css/admin.css +1114 -328
  40. package/dist/client/css/admin.css.map +1 -0
  41. package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
  42. package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
  43. package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
  44. package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
  45. package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
  46. package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
  47. package/dist/client/index.html +3 -2
  48. package/dist/client/js/main.js +356 -131
  49. package/dist/client/js/main.js.LICENSE.txt +15 -1
  50. package/dist/client/page.d.ts +2 -0
  51. package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
  52. package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
  53. package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
  54. package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
  55. package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
  56. package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
  57. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
  58. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
  59. package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
  60. package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
  61. package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
  62. package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
  63. package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
  64. package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
  65. package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
  66. package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
  67. package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
  68. package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
  69. package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
  70. package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
  71. package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
  72. package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
  73. package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
  74. package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
  75. package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
  76. package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
  77. package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
  78. package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
  79. package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
  80. package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
  81. package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
  82. package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
  83. package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
  84. package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
  85. package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
  86. package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
  87. package/dist/client/types.d.ts +339 -0
  88. package/dist/plugins/client/client/events.d.ts +23 -0
  89. package/dist/plugins/client/client/events.js +43 -0
  90. package/dist/plugins/client/client/events.js.map +1 -0
  91. package/dist/plugins/client/plugins/client/template.d.ts +2 -0
  92. package/dist/plugins/client/plugins/client/template.js +234 -0
  93. package/dist/plugins/client/plugins/client/template.js.map +1 -0
  94. package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
  95. package/dist/plugins/client/plugins/client/website-info.js +72 -0
  96. package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
  97. package/dist/plugins/client/types.d.ts +339 -0
  98. package/dist/plugins/client/types.js +80 -0
  99. package/dist/plugins/client/types.js.map +1 -0
  100. package/dist/plugins/server/constants.d.ts +32 -0
  101. package/dist/plugins/server/constants.js +76 -0
  102. package/dist/plugins/server/constants.js.map +1 -0
  103. package/dist/plugins/server/plugins/server/Cache.d.ts +2 -0
  104. package/dist/plugins/server/plugins/server/Cache.js +36 -0
  105. package/dist/plugins/server/plugins/server/Cache.js.map +1 -0
  106. package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
  107. package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
  108. package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
  109. package/dist/plugins/server/plugins/server/FtpConnector.d.ts +86 -0
  110. package/dist/plugins/server/plugins/server/FtpConnector.js +536 -0
  111. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -0
  112. package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +135 -0
  113. package/dist/plugins/server/plugins/server/GitlabConnector.js +649 -0
  114. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -0
  115. package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
  116. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
  117. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
  118. package/dist/plugins/server/plugins/server/PublicationOptimizer.d.ts +0 -0
  119. package/dist/plugins/server/plugins/server/PublicationOptimizer.js +14 -0
  120. package/dist/plugins/server/plugins/server/PublicationOptimizer.js.map +1 -0
  121. package/dist/plugins/server/plugins/server/SslPlugin.d.ts +1 -0
  122. package/dist/plugins/server/plugins/server/SslPlugin.js +86 -0
  123. package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -0
  124. package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -0
  125. package/dist/plugins/server/plugins/server/StaticPlugin.js +45 -0
  126. package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -0
  127. package/dist/plugins/server/server/config.d.ts +59 -0
  128. package/dist/plugins/server/server/config.js +181 -0
  129. package/dist/plugins/server/server/config.js.map +1 -0
  130. package/dist/plugins/server/server/connectors/FsHosting.d.ts +14 -0
  131. package/dist/plugins/server/server/connectors/FsHosting.js +66 -0
  132. package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -0
  133. package/dist/plugins/server/server/connectors/FsStorage.d.ts +44 -0
  134. package/dist/plugins/server/server/connectors/FsStorage.js +261 -0
  135. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -0
  136. package/dist/plugins/server/server/connectors/connectors.d.ts +86 -0
  137. package/dist/plugins/server/server/connectors/connectors.js +126 -0
  138. package/dist/plugins/server/server/connectors/connectors.js.map +1 -0
  139. package/dist/plugins/server/server/events.d.ts +26 -0
  140. package/dist/plugins/server/server/events.js +31 -0
  141. package/dist/plugins/server/server/events.js.map +1 -0
  142. package/dist/plugins/server/server/jobs.d.ts +12 -0
  143. package/dist/plugins/server/server/jobs.js +79 -0
  144. package/dist/plugins/server/server/jobs.js.map +1 -0
  145. package/dist/plugins/server/server/utils/validation.d.ts +7 -0
  146. package/dist/plugins/server/server/utils/validation.js +37 -0
  147. package/dist/plugins/server/server/utils/validation.js.map +1 -0
  148. package/dist/plugins/server/types.d.ts +339 -0
  149. package/dist/plugins/server/types.js +84 -0
  150. package/dist/plugins/server/types.js.map +1 -0
  151. package/dist/server/constants.js +55 -0
  152. package/dist/server/plugins/server/Cache.js +19 -0
  153. package/dist/server/server/api/api.js +20 -0
  154. package/dist/server/server/api/connectorApi.js +334 -0
  155. package/dist/server/server/api/publicationApi.js +106 -0
  156. package/dist/server/server/api/websiteApi.js +315 -0
  157. package/dist/server/server/cli.js +71 -0
  158. package/dist/server/server/config.js +120 -0
  159. package/dist/server/server/connectors/FsHosting.js +47 -0
  160. package/dist/server/server/connectors/FsStorage.js +228 -0
  161. package/dist/server/server/connectors/connectors.js +88 -0
  162. package/dist/server/server/events.js +14 -0
  163. package/dist/server/server/expose.js +27 -0
  164. package/dist/server/server/express.js +46 -0
  165. package/dist/server/server/index.js +94 -0
  166. package/dist/server/server/jobs.js +50 -0
  167. package/dist/server/server/utils/validation.js +14 -0
  168. package/dist/server/types.js +40 -0
  169. package/package.json +99 -49
  170. package/public/assets/download.png +0 -0
  171. package/public/assets/favicon.ico +0 -0
  172. package/public/assets/favicon.png +0 -0
  173. package/public/assets/ftp.png +0 -0
  174. package/public/assets/gitlab.png +0 -0
  175. package/public/assets/gitlab2.png +0 -0
  176. package/public/assets/laptop.png +0 -0
  177. package/public/assets/logo-silex-small.png +0 -0
  178. package/public/silex.js +22 -23
  179. package/src/css/_variables.scss +24 -20
  180. package/src/css/dialog.scss +35 -2
  181. package/src/css/fonts.scss +31 -0
  182. package/src/css/footer.scss +12 -0
  183. package/src/css/grapesjs-light.scss +180 -0
  184. package/src/css/grapesjs-plugins.scss +227 -0
  185. package/src/css/grapesjs.scss +159 -1
  186. package/src/css/index.scss +12 -1
  187. package/src/css/light.scss +7 -0
  188. package/src/css/loader.scss +2 -0
  189. package/src/css/project-bar.scss +32 -16
  190. package/src/css/silex.scss +79 -5
  191. package/src/css/website-info.scss +14 -0
  192. package/src/html/index.pug +3 -3
  193. package/src/html/templates/includes.pug +0 -1
  194. package/src/ts/client/api.ts +156 -0
  195. package/src/ts/client/assetUrl.test.ts +164 -0
  196. package/src/ts/client/assetUrl.ts +254 -0
  197. package/src/ts/client/config.ts +175 -13
  198. package/src/ts/client/events.ts +43 -0
  199. package/src/ts/client/expose.ts +27 -1
  200. package/src/ts/client/grapesjs/LoginDialog.ts +204 -0
  201. package/src/ts/client/grapesjs/PublicationManager.ts +433 -0
  202. package/src/ts/client/grapesjs/PublicationUi.ts +366 -0
  203. package/src/ts/client/grapesjs/blocks.ts +17 -0
  204. package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
  205. package/src/ts/client/grapesjs/css-props.ts +910 -0
  206. package/src/ts/client/grapesjs/eleventy.ts +30 -7
  207. package/src/ts/client/grapesjs/footer.ts +42 -0
  208. package/src/ts/client/grapesjs/img.ts +147 -0
  209. package/src/ts/client/grapesjs/index.ts +311 -122
  210. package/src/ts/client/grapesjs/internal-links.test.ts +19 -1
  211. package/src/ts/client/grapesjs/internal-links.ts +31 -7
  212. package/src/ts/client/grapesjs/keymaps.ts +207 -0
  213. package/src/ts/client/grapesjs/new-page-dialog.ts +19 -3
  214. package/src/ts/client/grapesjs/openImport.ts +22 -0
  215. package/src/ts/client/grapesjs/page-panel.ts +109 -7
  216. package/src/ts/client/grapesjs/project-bar.ts +133 -72
  217. package/src/ts/client/grapesjs/resize-panel.ts +20 -0
  218. package/src/ts/client/grapesjs/rich-text.ts +38 -13
  219. package/src/ts/client/grapesjs/semantic.ts +20 -3
  220. package/src/ts/client/grapesjs/settings-sections.ts +117 -0
  221. package/src/ts/client/grapesjs/settings.ts +191 -96
  222. package/src/ts/client/grapesjs/storage.ts +187 -0
  223. package/src/ts/client/grapesjs/symbolDialogs.ts +21 -5
  224. package/src/ts/client/grapesjs/view-buttons.ts +42 -0
  225. package/src/ts/client/index.ts +80 -21
  226. package/src/ts/client/publication-transformers.test.ts +207 -0
  227. package/src/ts/client/publication-transformers.ts +280 -0
  228. package/src/ts/client/publish-custom-code-block.ts +31 -0
  229. package/src/ts/client/publish-fonts.ts +36 -0
  230. package/src/ts/client/utils.ts +70 -1
  231. package/src/ts/constants.ts +78 -0
  232. package/src/ts/externs.ts +17 -0
  233. package/src/ts/page.ts +20 -3
  234. package/src/ts/plugins/client/template.ts +246 -0
  235. package/src/ts/plugins/client/website-info.ts +84 -0
  236. package/src/ts/plugins/server/Cache.ts +32 -0
  237. package/src/ts/plugins/server/DownloadConnector.ts +146 -0
  238. package/src/ts/plugins/server/FtpConnector.test.ts +82 -0
  239. package/src/ts/plugins/server/FtpConnector.ts +621 -0
  240. package/src/ts/plugins/server/GitlabConnector.ts +749 -0
  241. package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
  242. package/src/ts/plugins/server/PublicationOptimizer.ts +14 -0
  243. package/src/ts/plugins/server/SslPlugin.ts +84 -0
  244. package/src/ts/plugins/server/StaticPlugin.ts +45 -0
  245. package/src/ts/server/api/api.ts +19 -0
  246. package/src/ts/server/api/connectorApi.ts +464 -0
  247. package/src/ts/server/api/publicationApi.ts +159 -0
  248. package/src/ts/server/api/websiteApi.ts +462 -0
  249. package/src/ts/server/cli.ts +48 -14
  250. package/src/ts/server/config.ts +158 -60
  251. package/src/ts/server/connectors/FsHosting.ts +66 -0
  252. package/src/ts/server/connectors/FsStorage.test.ts +51 -0
  253. package/src/ts/server/connectors/FsStorage.ts +290 -0
  254. package/src/ts/server/connectors/connectors.ts +203 -0
  255. package/src/ts/server/events.ts +37 -0
  256. package/src/ts/server/expose.ts +19 -0
  257. package/src/ts/server/express.ts +57 -5
  258. package/src/ts/server/index.ts +79 -16
  259. package/src/ts/server/jobs.test.ts +75 -0
  260. package/src/ts/server/jobs.ts +89 -0
  261. package/src/ts/server/utils/BackwardCompat.ts +546 -528
  262. package/src/ts/server/utils/validation.ts +34 -0
  263. package/src/ts/types.ts +295 -85
  264. package/.dockerignore +0 -5
  265. package/.editorconfig +0 -14
  266. package/.eslintrc.json +0 -43
  267. package/.github/FUNDING.yml +0 -13
  268. package/.github/workflows/docker-hub-publish.yml +0 -36
  269. package/.github/workflows/npm-publish.yml +0 -19
  270. package/.github/workflows/test.yml +0 -26
  271. package/.nvmrc +0 -1
  272. package/.silex/default/.silex.data.json +0 -1
  273. package/CODE_OF_CONDUCT.md +0 -128
  274. package/CONTRIBUTING.md +0 -131
  275. package/Dockerfile +0 -15
  276. package/directus.silex.js +0 -7
  277. package/dist/constants.js +0 -4
  278. package/dist/events.js +0 -5
  279. package/dist/page.js +0 -15
  280. package/dist/server/cli.js +0 -43
  281. package/dist/server/config.js +0 -70
  282. package/dist/server/express.js +0 -18
  283. package/dist/server/index.js +0 -58
  284. package/dist/types.js +0 -34
  285. package/jest.config.js +0 -10
  286. package/logos/logo_by_ceubri/silex-icon-2018@200px.png +0 -0
  287. package/logos/logo_by_ceubri/silex-icon-2018@4x.png +0 -0
  288. package/logos/logo_by_ceubri/silex-logo-2018-white-transp.pdf +0 -0
  289. package/logos/logo_by_ceubri/silex-logo-2018-white.jpg +0 -0
  290. package/logos/logo_by_ceubri/silex-logo-2018-white.pdf +0 -0
  291. package/logos/logo_by_ceubri/silex-logo-2018-white.png +0 -0
  292. package/logos/logo_by_ceubri/silex-logo-2018-white@0.5x.png +0 -0
  293. package/logos/logo_by_ceubri/silex-logo-2018-white@0.75x.png +0 -0
  294. package/logos/logo_by_ceubri/silex-logo-2018-white@4x.jpg +0 -0
  295. package/logos/logo_by_ceubri/silex-logo-2018-white@4x.png +0 -0
  296. package/logos/logo_by_ceubri/silex-logo-2018.ai +5 -2521
  297. package/logos/logo_by_ceubri/silex-logo-2018.jpg +0 -0
  298. package/logos/logo_by_ceubri/silex-logo-2018.pdf +0 -0
  299. package/logos/logo_by_ceubri/silex-logo-2018.png +0 -0
  300. package/logos/logo_by_ceubri/silex-logo-2018@0.5x.png +0 -0
  301. package/logos/logo_by_ceubri/silex-logo-2018@0.75x.png +0 -0
  302. package/logos/logo_by_ceubri/silex-logo-2018@4x.jpg +0 -0
  303. package/logos/logo_by_ceubri/silex-logo-2018@4x.png +0 -0
  304. package/logos/silexlabs.png +0 -0
  305. package/src/example-client-config.js +0 -47
  306. package/src/plugins/AuthPlugin.js +0 -21
  307. package/src/plugins/Cache.js +0 -11
  308. package/src/plugins/DefaultBackend.js +0 -149
  309. package/src/plugins/ExpressPlugin.js +0 -39
  310. package/src/plugins/HooksPlugin.js +0 -58
  311. package/src/plugins/PublishPlugin.js +0 -69
  312. package/src/plugins/SslPlugin.js +0 -66
  313. package/src/plugins/StaticPlugin.js +0 -48
  314. package/src/plugins/WebsitePlugin.js +0 -207
  315. package/src/ts/client/grapesjs/publish.ts +0 -386
  316. package/src/ts/client/grapesjs/template.ts +0 -166
  317. package/src/ts/events.ts +0 -2
  318. package/tsconfig-server-debug.json +0 -19
  319. package/tsconfig-server-release.json +0 -19
  320. package/tsconfig.jest.json +0 -9
  321. package/tsconfig.json +0 -26
  322. package/webpack.config.js +0 -28
  323. package/webpack.debug.config.js +0 -8
@@ -0,0 +1,433 @@
1
+ /*
2
+ * Silex website builder, free/libre no-code tool for makers.
3
+ * Copyright (c) 2023 lexoyo and Silex Labs foundation
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import { getPageSlug } from '../../page'
19
+ import { ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiPublicationPublishBody, ClientSideFile, ClientSideFileType, ConnectorData, ConnectorType, ConnectorUser, JobStatus, Initiator, PublicationData, PublicationJobData, PublicationSettings, WebsiteData, WebsiteFile, WebsiteId, WebsiteSettings } from '../../types'
20
+ import { Editor } from 'grapesjs'
21
+ import { PublicationUi } from './PublicationUi'
22
+ import { getUser, logout, publicationStatus, publish } from '../api'
23
+ import { API_CONNECTOR_LOGIN, API_CONNECTOR_PATH, API_PATH } from '../../constants'
24
+ import { ClientEvent } from '../events'
25
+ import { resetRenderComponents, resetRenderCssRules, transformPermalink, transformFiles, transformPath, renderComponents, renderCssRules } from '../publication-transformers'
26
+ import { displayedToStored } from '../assetUrl'
27
+ import { hashString } from '../utils'
28
+
29
+ /**
30
+ * @fileoverview Publication manager for Silex
31
+ * This plugin adds a publication feature to Silex
32
+ * It lets the user publish the website to a hosting service
33
+ * It can optionally display a button and a dialog
34
+ * Useful commands:
35
+ * - publish: starts the publication process and optionally open the dialog
36
+ * - publish-login: open the login dialog
37
+ * - publish-logout: logout from the hosting service and let the user choose a hosting service again
38
+ */
39
+
40
+ // Constants
41
+ export const cmdPublicationStart = 'publish'
42
+ export const cmdPublicationLogin = 'publish-login'
43
+ export const cmdPublicationLogout = 'publish-logout'
44
+
45
+ // Types
46
+ export type PublishableEditor = Editor & {
47
+ PublicationManager: PublicationManager
48
+ }
49
+
50
+ export enum PublicationStatus {
51
+ STATUS_NONE = 'STATUS_NONE',
52
+ STATUS_PENDING = 'STATUS_PENDING',
53
+ STATUS_ERROR = 'STATUS_ERROR',
54
+ STATUS_SUCCESS = 'STATUS_SUCCESS',
55
+ STATUS_LOGGED_OUT = 'STATUS_AUTH_ERROR',
56
+ }
57
+
58
+ export type PublicationManagerOptions = {
59
+ appendTo?: string // If not provided, no button nor dialog will be created
60
+ websiteId: WebsiteId
61
+ }
62
+
63
+ // plugin init cod
64
+ export default function publishPlugin(editor, opts) {
65
+ (editor as PublishableEditor).PublicationManager = new PublicationManager(editor, opts)
66
+ }
67
+
68
+ function jobStatusToPublicationStatus(status: JobStatus): PublicationStatus {
69
+ switch (status) {
70
+ case JobStatus.IN_PROGRESS:
71
+ return PublicationStatus.STATUS_PENDING
72
+ case JobStatus.ERROR:
73
+ return PublicationStatus.STATUS_ERROR
74
+ case JobStatus.SUCCESS:
75
+ return PublicationStatus.STATUS_SUCCESS
76
+ }
77
+ throw new Error(`Unknown job status ${status}`)
78
+ }
79
+
80
+ // Orging and path, should we use config.rootUrl?
81
+ const SERVER_URL = window.location.origin + window.location.pathname.replace(/\/$/, '')
82
+
83
+ // The publication manager class
84
+ // This class is responsible for the publication dialog and for the publication process
85
+ // It is added to the editor instance as editor.PublicationManager
86
+ export class PublicationManager {
87
+ /**
88
+ * Publication dialog
89
+ * This class is responsible for the UI
90
+ */
91
+ dialog?: PublicationUi
92
+ /**
93
+ * Publication settings
94
+ * This is the data which is stored in the website settings
95
+ */
96
+ _settings: PublicationSettings
97
+ get settings(): PublicationSettings {
98
+ return this._settings
99
+ }
100
+ set settings(newSettings: PublicationSettings) {
101
+ this._settings = newSettings
102
+ this.dialog && (this.dialog.settings = newSettings)
103
+ }
104
+ /**
105
+ * Plugin options
106
+ * This is the data which is passed to the plugin by grapesjs
107
+ */
108
+ options: PublicationManagerOptions
109
+ /**
110
+ * Publication job during the publication process
111
+ */
112
+ job: PublicationJobData | null = null
113
+ /**
114
+ * Publication state
115
+ * This is the state of the publication process
116
+ */
117
+ status: PublicationStatus = PublicationStatus.STATUS_NONE
118
+
119
+ constructor(private editor: PublishableEditor, opts: PublicationManagerOptions) {
120
+ this.options = {
121
+ appendTo: 'options',
122
+ ...opts,
123
+ } as PublicationManagerOptions
124
+ // Save the publication settings in the website settings
125
+ editor.on('storage:start:store', (data) => {
126
+ data.publication = this.settings
127
+ })
128
+ // load publication settings from the website
129
+ editor.on('storage:end:load', (data) => {
130
+ this.settings = data.publication ?? {}
131
+ // Check if the user is logged in
132
+ getUser({ type: ConnectorType.HOSTING, connectorId: this.settings.connector?.connectorId })
133
+ .then((user) => {})
134
+ .catch((err) => {
135
+ this.status = PublicationStatus.STATUS_LOGGED_OUT
136
+ this.settings = {}
137
+ this.dialog && this.dialog.displayError('Please login', this.job, this.status)
138
+ })
139
+ })
140
+ // Add the publish command to the editor
141
+ editor.Commands.add(cmdPublicationStart, () => this.startPublication())
142
+ editor.Commands.add(cmdPublicationLogin, (editor: PublishableEditor, sender: any, connector: ConnectorData) => this.goLogin(connector))
143
+ editor.Commands.add(cmdPublicationLogout, () => this.goLogout())
144
+ // Add the publication dialog to the editor
145
+ if (this.options.appendTo) {
146
+ this.dialog = new PublicationUi(editor, {
147
+ appendTo: this.options.appendTo,
148
+ })
149
+ } else {
150
+ console.info('PublicationUi is disabled because no appendTo option is set')
151
+ }
152
+ }
153
+
154
+ async goLogin(connector: ConnectorData) {
155
+ let preventDefault = false
156
+ this.editor.trigger(ClientEvent.PUBLISH_LOGIN_START, { connector, publicationManager: this, preventDefault: () => preventDefault = true })
157
+ if(preventDefault) {
158
+ this.status = PublicationStatus.STATUS_NONE
159
+ this.dialog && this.dialog.displayPending(this.job, this.status)
160
+ return
161
+ }
162
+ // Check if the user is already logged in
163
+ if(connector.isLoggedIn) {
164
+ this.settings = {
165
+ ...this.settings, // In case there are options
166
+ connector,
167
+ }
168
+ this.status = PublicationStatus.STATUS_NONE
169
+ // Save the website with the new settings
170
+ // WIP: prevent saving during publication
171
+ // await this.editor.store(null)
172
+ // Display the dialog
173
+ this.dialog && this.dialog.displayPending(this.job, this.status)
174
+ return
175
+ }
176
+ this.settings = {}
177
+ this.status = PublicationStatus.STATUS_LOGGED_OUT
178
+ this.dialog && this.dialog.displayPending(this.job, this.status)
179
+ const params: ApiConnectorLoginQuery = {
180
+ connectorId: connector.connectorId,
181
+ type: connector.type,
182
+ }
183
+ window.open(connector.oauthUrl || `${SERVER_URL}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN}?connectorId=${params.connectorId}&type=${params.type}`, '_blank')
184
+ return new Promise<void>((resolve, reject) => {
185
+ const onMessage = async (event) => {
186
+ const data = event.data as ApiConnectorLoggedInPostMessage
187
+ if (data?.type === 'login') {
188
+ window.removeEventListener('message', onMessage)
189
+ if (data.error) {
190
+ this.status = PublicationStatus.STATUS_LOGGED_OUT
191
+ this.settings = {}
192
+ this.dialog && this.dialog.displayError(data.message, this.job, this.status)
193
+ reject(new Error(data.message))
194
+ } else {
195
+ this.editor.trigger(ClientEvent.PUBLISH_LOGIN_END)
196
+ //const uesr = await getUser({type: connector.type, connectorId: data.connectorId})
197
+ this.settings.connector = connector
198
+ this.settings.options = data.options
199
+ this.status = PublicationStatus.STATUS_NONE
200
+ // Save the website with the new settings
201
+ // WIP: prevent saving during publication
202
+ // await this.editor.store(null)
203
+ // Display the dialog
204
+ this.dialog && this.dialog.displayPending(this.job, this.status)
205
+ //await this.startPublication()
206
+ resolve()
207
+ }
208
+ }
209
+ }
210
+ window.addEventListener('message', onMessage, false)
211
+ })
212
+ }
213
+
214
+ async goLogout() {
215
+ try {
216
+ await logout({type: ConnectorType.HOSTING, connectorId: this.settings.connector.connectorId})
217
+ this.settings = {}
218
+ this.dialog && this.dialog.displayPending(this.job, this.status)
219
+ } catch (e) {
220
+ console.error('logout error', e)
221
+ this.status = PublicationStatus.STATUS_ERROR
222
+ this.dialog && this.dialog.displayError(e.message, this.job, this.status)
223
+ }
224
+ }
225
+
226
+ async getPublicationData(projectData, siteSettings, preventDefault: () => void): Promise<PublicationData> {
227
+ // Data to publish
228
+ // See assetUrl.ts which is a default transformer, always present
229
+ this.setPublicationTransformers()
230
+ // Build the files structure
231
+ const files: ClientSideFile[] = (await this.getHtmlFiles(siteSettings, preventDefault))
232
+ .flatMap(file => ([{
233
+ path: file.htmlPath, // Already "transformed" in getHtmlFiles
234
+ content: file.html,
235
+ type: ClientSideFileType.HTML,
236
+ } as ClientSideFile, {
237
+ path: file.cssPath, // Already "transformed" in getHtmlFiles
238
+ content: file.css,
239
+ type: ClientSideFileType.CSS,
240
+ } as ClientSideFile]))
241
+ .concat(projectData.assets
242
+ .map(asset => {
243
+ // TODO: is this needed?
244
+ // // Remove /assets that is added by grapesjs
245
+ // const initialPath = asset.src
246
+ // .replace(/^\/assets/, '')
247
+ // Transform the file paths with the transformers
248
+ const path = transformPath(this.editor, asset.src, ClientSideFileType.ASSET)
249
+ //const src = transformPermalink(this.editor, asset.src, ClientSideFileType.ASSET)
250
+ // This is done in transformPermalink and transformPath but other transformers may change it
251
+ // So we do this only using displayedToStored for the path
252
+ // As path is used to download the asset
253
+ const src = displayedToStored(asset.src)
254
+ // Remove the /asset prefix to keep only the file name
255
+ .replace(/^\/assets\//, '')
256
+ return {
257
+ ...asset,
258
+ path,
259
+ src,
260
+ type: ClientSideFileType.ASSET, // Replaces grapesjs's 'image' type
261
+ } as ClientSideFile
262
+ }))
263
+ // Create the data to send to the server
264
+ const data: PublicationData = {
265
+ ...projectData,
266
+ assets: projectData.assets.map(asset => ({
267
+ ...asset,
268
+ src: displayedToStored(asset.src),
269
+ })),
270
+ settings: siteSettings,
271
+ publication: this.settings,
272
+ files,
273
+ }
274
+ this.resetPublicationTransformers()
275
+ // Let plugins transform the data
276
+ transformFiles(this.editor, data)
277
+ this.editor.trigger(ClientEvent.PUBLISH_DATA, { data, preventDefault, publicationManager: this })
278
+ // Return the data
279
+ return data
280
+ }
281
+
282
+ /**
283
+ * Start the publication process
284
+ * This is the command "publish"
285
+ */
286
+ async startPublication() {
287
+ try {
288
+ if (this.status === PublicationStatus.STATUS_PENDING) throw new Error('Publication is already in progress')
289
+ this.status = PublicationStatus.STATUS_PENDING
290
+ this.job = null
291
+ this.dialog && this.dialog.displayPending(this.job, this.status)
292
+ // Get the data to publish, clone the objects because plugins can change it
293
+ const projectData = { ...this.editor.getProjectData() as WebsiteData }
294
+ const siteSettings = { ...this.editor.getModel().get('settings') as WebsiteSettings }
295
+ let preventDefaultStart = false
296
+ this.editor.trigger(ClientEvent.PUBLISH_START, {projectData, siteSettings, preventDefault: () => preventDefaultStart = true, publicationManager: this })
297
+ if(preventDefaultStart) {
298
+ this.status = PublicationStatus.STATUS_NONE
299
+ this.dialog && this.dialog.displayPending(this.job, this.status)
300
+ return
301
+ }
302
+ // Get the data to publish
303
+ let preventDefaultData = false
304
+ const data = await this.getPublicationData(projectData, siteSettings, () => preventDefaultData = true)
305
+ if(preventDefaultData) {
306
+ this.status = PublicationStatus.STATUS_NONE
307
+ this.dialog && this.dialog.displayPending(this.job, this.status)
308
+ return
309
+ }
310
+ // User and where to publish
311
+ const storageUser = this.editor.getModel().get('user') as ConnectorUser
312
+ if(!storageUser) throw new Error('User not logged in to a storage connector')
313
+ if(!this.settings.connector?.connectorId) throw new Error('User not logged in to a hosting connector')
314
+ const websiteId = this.options.websiteId
315
+ const storageId = storageUser.storage.connectorId
316
+ // Use the publication API
317
+ const [url, job] = await publish({
318
+ websiteId,
319
+ hostingId: this.settings.connector.connectorId,
320
+ storageId,
321
+ data: data as ApiPublicationPublishBody,
322
+ options: this.settings.options,
323
+ })
324
+
325
+ // in gitlab pages situation, getUrl from gitlabHostingConnector gives publication url obtained with Gitlab API pages
326
+ console.info('Gitlab url: ', url)
327
+ // could be used in an future UI
328
+
329
+ this.job = job
330
+ this.status = jobStatusToPublicationStatus(this.job.status)
331
+ this.trackProgress()
332
+ } catch (e) {
333
+ console.error('publish error', e)
334
+ if(e.code === 401 || e.httpStatusCode === 401) {
335
+ this.status = PublicationStatus.STATUS_LOGGED_OUT
336
+ this.settings = {}
337
+ this.dialog && this.dialog.displayError('Please login.', this.job, this.status)
338
+ } else {
339
+ this.status = PublicationStatus.STATUS_ERROR
340
+ this.dialog && this.dialog.displayError(`An error occured, your site is not published. ${e.message}`, this.job, this.status)
341
+ }
342
+ this.editor.trigger(ClientEvent.PUBLISH_ERROR, { success: false, message: e.message })
343
+ this.editor.trigger(ClientEvent.PUBLISH_END, { success: false, message: e.message })
344
+ return
345
+ }
346
+ }
347
+
348
+ async getHtmlFiles(siteSettings: WebsiteSettings, preventDefault): Promise<WebsiteFile[]> {
349
+ return Promise.all(this.editor.Pages.getAll().map(async page => {
350
+ // Clone the settings because plugins can change them
351
+ siteSettings = { ...siteSettings }
352
+ const pageSettings = { ...page.get('settings') as WebsiteSettings }
353
+ // Utility function to get a setting from the page or the site settings
354
+ function getSetting(name) {
355
+ return (pageSettings || {})[name] || (siteSettings || [])[name] || ''
356
+ }
357
+
358
+ // Get the content from GrapesJS
359
+ const body = page.getMainComponent()
360
+ const cssContent = this.editor.getCss({ component: body })
361
+ console.time(`getHtml ${page.getId()} ${page.get('name')}`)
362
+ const htmlContent = this.editor.getHtml({ component: body })
363
+ console.timeEnd(`getHtml ${page.getId()} ${page.get('name')}`)
364
+
365
+ // Transform the file paths
366
+ const slug = getPageSlug(page.get('name'))
367
+ const cssInitialPath = `/css/${slug}-${await hashString(cssContent)}.css`
368
+ const htmlInitialPath = `/${slug}.html`
369
+ const cssPermalink = transformPermalink(this.editor, cssInitialPath, ClientSideFileType.CSS, Initiator.HTML)
370
+ const cssPath = transformPath(this.editor, cssInitialPath, ClientSideFileType.CSS)
371
+ const htmlPath = transformPath(this.editor, htmlInitialPath, ClientSideFileType.HTML)
372
+
373
+ // Let plugins transform the data
374
+ this.editor.trigger(ClientEvent.PUBLISH_PAGE, { page, siteSettings, pageSettings, preventDefault, publicationManager: this })
375
+
376
+ // Useful data for HTML result
377
+ const title = getSetting('title')
378
+ const favicon = getSetting('favicon')
379
+ // Return the HTML file
380
+ return {
381
+ html: `<!DOCTYPE html>
382
+ <html lang="${getSetting('lang')}">
383
+ <head>
384
+ <meta charset="UTF-8">
385
+ <link rel="stylesheet" href="${cssPermalink}" />
386
+ ${siteSettings?.head || ''}
387
+ ${pageSettings?.head || ''}
388
+ ${ title ? `<title>${ title }</title>` : '' }
389
+ ${ favicon ? `<link rel="icon" href="${favicon}" />` : '' }
390
+ ${['description', 'og:title', 'og:description', 'og:image']
391
+ .filter(prop => !!getSetting(prop))
392
+ .map(prop => `<meta name="${prop}" property="${prop}" content="${getSetting(prop)}"/>`)
393
+ .join('\n')
394
+ }
395
+ </head>
396
+ ${htmlContent}
397
+ </html>`,
398
+ css: cssContent,
399
+ cssPath,
400
+ htmlPath,
401
+ }
402
+ }))
403
+ }
404
+
405
+ async trackProgress() {
406
+ try {
407
+ this.job = await publicationStatus({jobId: this.job.jobId})
408
+ this.status = jobStatusToPublicationStatus(this.job.status)
409
+ } catch (e) {
410
+ this.status = PublicationStatus.STATUS_ERROR
411
+ this.dialog && this.dialog.displayError(`An error occured, your site is not published. ${e.message}`, this.job, this.status)
412
+ this.editor.trigger(ClientEvent.PUBLISH_END, { success: false, message: e.message })
413
+ this.editor.trigger(ClientEvent.PUBLISH_ERROR, { success: false, message: e.message })
414
+ return
415
+ }
416
+ if (this.job.status === JobStatus.IN_PROGRESS) {
417
+ setTimeout(() => this.trackProgress(), 2000)
418
+ } else {
419
+ this.editor.trigger(ClientEvent.PUBLISH_END, { success: this.job.status === JobStatus.SUCCESS, message: this.job.message })
420
+ }
421
+ this.dialog && this.dialog.displayPending(this.job, this.status)
422
+ }
423
+
424
+ private setPublicationTransformers() {
425
+ renderComponents(this.editor)
426
+ renderCssRules(this.editor)
427
+ }
428
+
429
+ private resetPublicationTransformers() {
430
+ resetRenderComponents(this.editor)
431
+ resetRenderCssRules(this.editor)
432
+ }
433
+ }