@silexlabs/silex 3.0.1-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 (250) hide show
  1. package/.env.default +3 -2
  2. package/.silex.js +39 -1
  3. package/README.md +37 -35
  4. package/dist/client/client/api.d.ts +8 -1
  5. package/dist/client/client/assetUrl.d.ts +54 -0
  6. package/dist/client/client/config.d.ts +60 -1
  7. package/dist/client/client/events.d.ts +19 -10
  8. package/dist/client/client/grapesjs/PublicationManager.d.ts +6 -8
  9. package/dist/client/client/grapesjs/PublicationUi.d.ts +8 -10
  10. package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
  11. package/dist/client/client/grapesjs/css-props.d.ts +6 -0
  12. package/dist/client/client/grapesjs/footer.d.ts +2 -0
  13. package/dist/client/client/grapesjs/img.d.ts +6 -0
  14. package/dist/client/client/grapesjs/index.d.ts +6 -2
  15. package/dist/client/client/grapesjs/internal-links.d.ts +1 -1
  16. package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
  17. package/dist/client/client/grapesjs/new-page-dialog.d.ts +1 -1
  18. package/dist/client/client/grapesjs/page-panel.d.ts +7 -1
  19. package/dist/client/client/grapesjs/project-bar.d.ts +20 -0
  20. package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
  21. package/dist/client/client/grapesjs/rich-text.d.ts +4 -1
  22. package/dist/client/client/grapesjs/semantic.d.ts +1 -1
  23. package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
  24. package/dist/client/client/grapesjs/settings.d.ts +3 -1
  25. package/dist/client/client/grapesjs/storage.d.ts +1 -0
  26. package/dist/client/client/grapesjs/symbolDialogs.d.ts +1 -1
  27. package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
  28. package/dist/client/client/index.d.ts +5 -0
  29. package/dist/client/client/publication-transformers.d.ts +42 -0
  30. package/dist/client/client/publish-custom-code-block.d.ts +4 -0
  31. package/dist/client/client/publish-fonts.d.ts +4 -0
  32. package/dist/client/client/utils.d.ts +22 -1
  33. package/dist/client/constants.d.ts +3 -0
  34. package/dist/client/css/admin.css +1107 -411
  35. package/dist/client/css/admin.css.map +1 -0
  36. package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
  37. package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
  38. package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
  39. package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
  40. package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
  41. package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
  42. package/dist/client/index.html +3 -2
  43. package/dist/client/js/main.js +305 -170
  44. package/dist/client/js/main.js.LICENSE.txt +21 -1
  45. package/dist/client/page.d.ts +1 -1
  46. package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
  47. package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
  48. package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
  49. package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
  50. package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
  51. package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
  52. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
  53. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
  54. package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
  55. package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
  56. package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
  57. package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
  58. package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
  59. package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
  60. package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
  61. package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
  62. package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
  63. package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
  64. package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
  65. package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
  66. package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
  67. package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
  68. package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
  69. package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
  70. package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
  71. package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
  72. package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
  73. package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
  74. package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
  75. package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
  76. package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
  77. package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
  78. package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
  79. package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
  80. package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
  81. package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
  82. package/dist/client/types.d.ts +59 -35
  83. package/dist/plugins/client/client/events.d.ts +19 -10
  84. package/dist/plugins/client/client/events.js +11 -0
  85. package/dist/plugins/client/client/events.js.map +1 -1
  86. package/dist/plugins/client/plugins/client/template.js +119 -71
  87. package/dist/plugins/client/plugins/client/template.js.map +1 -1
  88. package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
  89. package/dist/plugins/client/plugins/client/website-info.js +72 -0
  90. package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
  91. package/dist/plugins/client/types.d.ts +59 -35
  92. package/dist/plugins/client/types.js +23 -0
  93. package/dist/plugins/client/types.js.map +1 -1
  94. package/dist/plugins/server/constants.d.ts +3 -0
  95. package/dist/plugins/server/constants.js +28 -1
  96. package/dist/plugins/server/constants.js.map +1 -1
  97. package/dist/plugins/server/plugins/server/Cache.js +9 -5
  98. package/dist/plugins/server/plugins/server/Cache.js.map +1 -1
  99. package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
  100. package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
  101. package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
  102. package/dist/plugins/server/plugins/server/FtpConnector.d.ts +5 -2
  103. package/dist/plugins/server/plugins/server/FtpConnector.js +38 -23
  104. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
  105. package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +63 -9
  106. package/dist/plugins/server/plugins/server/GitlabConnector.js +367 -91
  107. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
  108. package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
  109. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
  110. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
  111. package/dist/plugins/server/plugins/server/SslPlugin.js +6 -6
  112. package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -1
  113. package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -1
  114. package/dist/plugins/server/plugins/server/StaticPlugin.js +5 -31
  115. package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -1
  116. package/dist/plugins/server/server/config.js +8 -9
  117. package/dist/plugins/server/server/config.js.map +1 -1
  118. package/dist/plugins/server/server/connectors/FsHosting.d.ts +3 -2
  119. package/dist/plugins/server/server/connectors/FsHosting.js +18 -7
  120. package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -1
  121. package/dist/plugins/server/server/connectors/FsStorage.d.ts +3 -1
  122. package/dist/plugins/server/server/connectors/FsStorage.js +35 -28
  123. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
  124. package/dist/plugins/server/server/connectors/connectors.d.ts +7 -7
  125. package/dist/plugins/server/server/connectors/connectors.js +6 -7
  126. package/dist/plugins/server/server/connectors/connectors.js.map +1 -1
  127. package/dist/plugins/server/server/events.js +16 -0
  128. package/dist/plugins/server/server/events.js.map +1 -1
  129. package/dist/plugins/server/server/jobs.d.ts +6 -0
  130. package/dist/plugins/server/server/jobs.js +12 -8
  131. package/dist/plugins/server/server/jobs.js.map +1 -1
  132. package/dist/plugins/server/server/utils/validation.js +1 -2
  133. package/dist/plugins/server/server/utils/validation.js.map +1 -1
  134. package/dist/plugins/server/types.d.ts +59 -35
  135. package/dist/plugins/server/types.js +24 -1
  136. package/dist/plugins/server/types.js.map +1 -1
  137. package/dist/server/constants.js +27 -1
  138. package/dist/server/plugins/server/Cache.js +9 -5
  139. package/dist/server/server/api/api.js +1 -1
  140. package/dist/server/server/api/connectorApi.js +154 -25
  141. package/dist/server/server/api/publicationApi.js +17 -25
  142. package/dist/server/server/api/websiteApi.js +30 -8
  143. package/dist/server/server/cli.js +9 -6
  144. package/dist/server/server/config.js +8 -9
  145. package/dist/server/server/connectors/FsHosting.js +17 -7
  146. package/dist/server/server/connectors/FsStorage.js +34 -28
  147. package/dist/server/server/connectors/connectors.js +6 -7
  148. package/dist/server/server/express.js +4 -5
  149. package/dist/server/server/index.js +5 -1
  150. package/dist/server/server/jobs.js +11 -8
  151. package/dist/server/server/utils/validation.js +1 -2
  152. package/dist/server/types.js +13 -1
  153. package/package.json +56 -42
  154. package/public/assets/download.png +0 -0
  155. package/public/assets/favicon.ico +0 -0
  156. package/public/assets/favicon.png +0 -0
  157. package/public/assets/ftp.png +0 -0
  158. package/public/assets/gitlab.png +0 -0
  159. package/public/assets/gitlab2.png +0 -0
  160. package/public/assets/laptop.png +0 -0
  161. package/public/assets/logo-silex-small.png +0 -0
  162. package/public/silex.js +5 -23
  163. package/src/css/_variables.scss +23 -20
  164. package/src/css/dialog.scss +27 -1
  165. package/src/css/fonts.scss +31 -0
  166. package/src/css/footer.scss +12 -0
  167. package/src/css/grapesjs-light.scss +180 -0
  168. package/src/css/grapesjs-plugins.scss +227 -0
  169. package/src/css/grapesjs.scss +84 -10
  170. package/src/css/index.scss +12 -1
  171. package/src/css/light.scss +7 -0
  172. package/src/css/project-bar.scss +32 -16
  173. package/src/css/silex.scss +79 -5
  174. package/src/css/website-info.scss +14 -0
  175. package/src/html/index.pug +3 -3
  176. package/src/ts/client/api.ts +38 -14
  177. package/src/ts/client/assetUrl.test.ts +164 -0
  178. package/src/ts/client/assetUrl.ts +254 -0
  179. package/src/ts/client/config.ts +133 -5
  180. package/src/ts/client/events.ts +21 -9
  181. package/src/ts/client/grapesjs/LoginDialog.ts +4 -2
  182. package/src/ts/client/grapesjs/PublicationManager.ts +180 -54
  183. package/src/ts/client/grapesjs/PublicationUi.ts +122 -86
  184. package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
  185. package/src/ts/client/grapesjs/css-props.ts +910 -0
  186. package/src/ts/client/grapesjs/eleventy.ts +11 -8
  187. package/{dist/plugins/client/page.js → src/ts/client/grapesjs/footer.ts} +24 -13
  188. package/src/ts/client/grapesjs/img.ts +147 -0
  189. package/src/ts/client/grapesjs/index.ts +234 -52
  190. package/src/ts/client/grapesjs/internal-links.test.ts +2 -1
  191. package/src/ts/client/grapesjs/internal-links.ts +14 -7
  192. package/src/ts/client/grapesjs/keymaps.ts +207 -0
  193. package/src/ts/client/grapesjs/new-page-dialog.ts +2 -3
  194. package/src/ts/client/grapesjs/page-panel.ts +92 -7
  195. package/src/ts/client/grapesjs/project-bar.ts +116 -72
  196. package/src/ts/client/grapesjs/resize-panel.ts +20 -0
  197. package/src/ts/client/grapesjs/rich-text.ts +21 -13
  198. package/src/ts/client/grapesjs/semantic.ts +3 -3
  199. package/src/ts/client/grapesjs/settings-sections.ts +117 -0
  200. package/src/ts/client/grapesjs/settings.ts +174 -96
  201. package/src/ts/client/grapesjs/storage.ts +98 -33
  202. package/src/ts/client/grapesjs/symbolDialogs.ts +3 -4
  203. package/src/ts/{plugins/server/AuthPlugin.ts → client/grapesjs/view-buttons.ts} +23 -19
  204. package/src/ts/client/index.ts +35 -16
  205. package/src/ts/client/publication-transformers.test.ts +207 -0
  206. package/src/ts/client/publication-transformers.ts +280 -0
  207. package/{dist/plugins/client/client/utils.js → src/ts/client/publish-custom-code-block.ts} +14 -8
  208. package/src/ts/client/publish-fonts.ts +36 -0
  209. package/src/ts/client/utils.ts +53 -1
  210. package/src/ts/constants.ts +31 -0
  211. package/src/ts/page.ts +2 -2
  212. package/src/ts/plugins/client/template.ts +125 -75
  213. package/src/ts/plugins/client/website-info.ts +84 -0
  214. package/src/ts/plugins/server/Cache.ts +6 -2
  215. package/src/ts/plugins/server/DownloadConnector.ts +146 -0
  216. package/src/ts/plugins/server/FtpConnector.ts +47 -21
  217. package/src/ts/plugins/server/GitlabConnector.ts +423 -108
  218. package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
  219. package/src/ts/plugins/server/SslPlugin.ts +5 -5
  220. package/src/ts/plugins/server/StaticPlugin.ts +3 -30
  221. package/src/ts/server/api/connectorApi.ts +165 -28
  222. package/src/ts/server/api/publicationApi.ts +17 -24
  223. package/src/ts/server/api/websiteApi.ts +57 -14
  224. package/src/ts/server/cli.ts +7 -5
  225. package/src/ts/server/config.ts +9 -10
  226. package/src/ts/server/connectors/FsHosting.ts +14 -8
  227. package/src/ts/server/connectors/FsStorage.ts +40 -7
  228. package/src/ts/server/connectors/connectors.ts +8 -6
  229. package/src/ts/server/events.ts +17 -0
  230. package/src/ts/server/express.ts +2 -2
  231. package/src/ts/server/index.ts +6 -0
  232. package/src/ts/server/jobs.ts +14 -2
  233. package/src/ts/server/utils/BackwardCompat.ts +530 -529
  234. package/src/ts/types.ts +78 -34
  235. package/dist/plugins/client/client/utils.d.ts +0 -1
  236. package/dist/plugins/client/client/utils.js.map +0 -1
  237. package/dist/plugins/client/page.d.ts +0 -2
  238. package/dist/plugins/client/page.js.map +0 -1
  239. package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +0 -2
  240. package/dist/plugins/client/plugins/client/publicationRenderer.js +0 -128
  241. package/dist/plugins/client/plugins/client/publicationRenderer.js.map +0 -1
  242. package/dist/plugins/server/plugins/server/AuthPlugin.d.ts +0 -1
  243. package/dist/plugins/server/plugins/server/AuthPlugin.js +0 -38
  244. package/dist/plugins/server/plugins/server/AuthPlugin.js.map +0 -1
  245. package/dist/plugins/server/plugins/server/HooksPlugin.d.ts +0 -7
  246. package/dist/plugins/server/plugins/server/HooksPlugin.js +0 -74
  247. package/dist/plugins/server/plugins/server/HooksPlugin.js.map +0 -1
  248. package/src/example-client-config.js +0 -64
  249. package/src/ts/plugins/client/publicationRenderer.ts +0 -128
  250. package/src/ts/plugins/server/HooksPlugin.ts +0 -76
@@ -0,0 +1,254 @@
1
+ import { API_PATH, API_WEBSITE_ASSET_READ, API_WEBSITE_PATH } from '../constants'
2
+ import { Asset, ClientSideFileType, Component, ConnectorId, Page, Style, WebsiteId } from '../types'
3
+
4
+ /**
5
+ * @fileoverview Helpers to manage assets URL
6
+ * Assets URLs are stored on storage in their "stored version": `/assets/image.webp`
7
+ * But the client side uses the "display version": `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
8
+ * After loading the site data we convert all URLs to the client side version
9
+ * Before saving the site data we convert all URLs to the storage version
10
+ * During publicationn we convert all URLs to the storage version and back
11
+ */
12
+
13
+ // Get the base URL where Silex is served
14
+ const baseUrl = window.location.pathname.replace(/\/$/, '')
15
+
16
+ // Orging and path, should we use config.rootUrl?
17
+ const SERVER_URL = window.location.origin
18
+
19
+ /**
20
+ * Function to convert a path from it stored version to the displayed version
21
+ * Stored version is like `/assets/image.webp`
22
+ * Grapesjs version is like `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
23
+ * Exported for unit tests
24
+ */
25
+ export function storedToDisplayed(path: string, websiteId: WebsiteId, storageId: ConnectorId): string {
26
+ // Check the path is a stored path
27
+ if (path.startsWith('/assets')) {
28
+ // Make an absolute URL
29
+ const url = new URL(path, SERVER_URL)
30
+ // Remove the assets folder as it is part of the saved path
31
+ url.pathname = url.pathname.replace(/^\/assets/, '')
32
+ // Add the API path and the connectorId and websiteId
33
+ url.pathname = `${baseUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSET_READ}${url.pathname}`
34
+ // Add the GET params
35
+ url.searchParams.set('websiteId', websiteId)
36
+ url.searchParams.set('connectorId', storageId)
37
+ // Back to a relative URL, keep the path but not the origin
38
+ return `${decodeURIComponent(url.pathname)}${url.search}`
39
+ //const encodedPath = '/' + url.toString() // add a leading slash
40
+ // .replace(new RegExp(`^${SERVER_URL}`), '')
41
+ // .replace(/^\//, '') // remove the first slash if it exists
42
+ //return decodeURIComponent(encodedPath)
43
+ } else {
44
+ if(path.startsWith('<svg') || path.startsWith('data:image')) {
45
+ // SVG or data URL
46
+ return path
47
+ }
48
+ // Not a stored path, is there a problem?
49
+ console.warn('storedToDisplayed: path is not a stored path', path)
50
+ return path
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Function to convert a path from the one we give to grapesjs to the stored version
56
+ * Grapesjs version is like `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
57
+ * Stored version is like `/assets/image.webp`
58
+ * @param path the path to convert
59
+ * @returns the converted path
60
+ * Exported for unit tests
61
+ */
62
+ export function displayedToStored(path: string): string {
63
+ // The path to the assets API
64
+ const apiPath = `${baseUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSET_READ}`
65
+ // Check the path is a displayed path
66
+ if (path.startsWith(apiPath)) {
67
+ const url = new URL(path, SERVER_URL)
68
+ url.pathname = url.pathname.replace(new RegExp(`^${apiPath}`), '')
69
+ url.pathname = `${baseUrl}/assets${url.pathname}`
70
+ url.searchParams.delete('websiteId')
71
+ url.searchParams.delete('connectorId')
72
+ const encodedPath = '/' + url.toString() // add a leading slash
73
+ .replace(new RegExp(`^${SERVER_URL}${baseUrl}`), '')
74
+ .replace(/^\//, '') // remove the first slash if it exists
75
+ return decodeURIComponent(encodedPath)
76
+ } else {
77
+ if(path.startsWith('<svg') || path.startsWith('data:image')) {
78
+ // SVG or data URL
79
+ return path
80
+ }
81
+ console.warn('displayedToStored: path is not a displayed path', path)
82
+ return path
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Publication transformer to convert the asset URL during publication
88
+ */
89
+ export const assetsPublicationTransformer = {
90
+ transformPath(path: string, type: ClientSideFileType): string {
91
+ if(type === ClientSideFileType.ASSET) {
92
+ const result = displayedToStored(path)
93
+ return result
94
+ }
95
+ return undefined
96
+ },
97
+ transformPermalink(path: string, type: ClientSideFileType): string {
98
+ if(type === ClientSideFileType.ASSET) {
99
+ const result = displayedToStored(path)
100
+ return result
101
+ }
102
+ return undefined
103
+ },
104
+ }
105
+
106
+ /**
107
+ * Update asset URL to use the current storage connector and website ID
108
+ * Assets URLs are stored in the project data in the form `/assets/image.webp`
109
+ * This function adds the API path and the connectorId and websiteId like so: `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
110
+ */
111
+ export function addTempDataToAssetUrl(assets: Asset[], websiteId: WebsiteId, storageId: ConnectorId): Asset[] {
112
+ return assets.map((asset: Asset) => {
113
+ return asset.src ? {
114
+ ...asset,
115
+ src: storedToDisplayed(asset.src, websiteId, storageId),
116
+ } : asset
117
+ })
118
+ }
119
+
120
+ /**
121
+ * Remove the temporary data from the asset URL
122
+ * Remove the API path and the connectorId and websiteId like so: `/assets/image.webp`
123
+ */
124
+ export function removeTempDataFromAssetUrl(assets: Asset[]): Asset[] {
125
+ return assets.map((asset: Asset) => {
126
+ // Return the asset with the new URL
127
+ return asset.src ? {
128
+ ...asset,
129
+ src: displayedToStored(asset.src),
130
+ } : asset
131
+ })
132
+ }
133
+
134
+ /**
135
+ * Reucrsive function to update the asset URL in the components
136
+ */
137
+ function addTempDataToComponents(component: Component, websiteId: WebsiteId, storageId: ConnectorId): Component {
138
+ // Update the asset URL in the component
139
+ const newComponent = component.attributes?.src ? {
140
+ ...component,
141
+ attributes: {
142
+ ...component.attributes,
143
+ src: storedToDisplayed(component.attributes.src, websiteId, storageId),
144
+ },
145
+ } : component
146
+ // Update the asset URL in the children
147
+ if (newComponent.components) {
148
+ newComponent.components = newComponent.components.map((childComponent: Component) => {
149
+ return addTempDataToComponents(childComponent, websiteId, storageId)
150
+ })
151
+ }
152
+ return newComponent
153
+ }
154
+
155
+ /**
156
+ * Reucrsive function to update the asset URL in the components
157
+ */
158
+ function removeTempDataFromComponents(component: Component): Component {
159
+ // Update the asset URL in the component
160
+ const newComponent = component.attributes?.src ? {
161
+ ...component,
162
+ attributes: {
163
+ ...component.attributes,
164
+ src: displayedToStored(component.attributes.src),
165
+ },
166
+ } : component
167
+ // Update the asset URL in the children
168
+ if (newComponent.components) {
169
+ newComponent.components = newComponent.components.map((childComponent: Component) => {
170
+ return removeTempDataFromComponents(childComponent)
171
+ })
172
+ }
173
+ return newComponent
174
+ }
175
+
176
+ /**
177
+ * Add temp data to pages
178
+ */
179
+ export function addTempDataToPages(pages: Page[], websiteId: WebsiteId, storageId: ConnectorId): Page[] {
180
+ return pages.map((page: Page) => {
181
+ return {
182
+ ...page,
183
+ frames: page.frames.map(frame => ({
184
+ ...frame,
185
+ component: addTempDataToComponents(frame.component, websiteId, storageId),
186
+ }))
187
+ }
188
+ })
189
+ }
190
+
191
+ /**
192
+ * Remove temp data from asset URL in the components
193
+ */
194
+ export function removeTempDataFromPages(pages: Page[]): Page[] {
195
+ return pages.map((page: Page) => {
196
+ return {
197
+ ...page,
198
+ frames: page.frames.map(frame => ({
199
+ ...frame,
200
+ component: removeTempDataFromComponents(frame.component),
201
+ }))
202
+ }
203
+ })
204
+ }
205
+
206
+ /**
207
+ * Add data to stylesheets
208
+ * e.g. linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url('/assets/qIg7JPRc.webp'), linear-gradient(#0ca311 0%, #0ca311 100%)
209
+ */
210
+ export function addTempDataToStyles(styles: Style[], websiteId: WebsiteId, storageId: ConnectorId): Style[] {
211
+ const regex = new RegExp(/(.*)(url\((["']?)([^"']+?)\1\))*(.*)/, 'g')
212
+
213
+ return styles.map((style: Style) => {
214
+ if (style.style && style.style['background-image']) {
215
+ const bgImage = style.style['background-image']
216
+ .replace(/url\((['"]?)([^'"]+)\1\)/g, (match, quote, url) => {
217
+ return `url(${quote}${storedToDisplayed(url, websiteId, storageId)}${quote})`
218
+ })
219
+ return {
220
+ ...style,
221
+ style: {
222
+ ...style.style,
223
+ 'background-image': bgImage,
224
+ },
225
+ }
226
+ }
227
+ return style
228
+ })
229
+ }
230
+
231
+ /**
232
+ * Remove temp data from stylesheets
233
+ * The property `background-image` contains the URLs of the assets and other values,
234
+ * e.g. `linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url('/api/website/assets/qIg7JPRc.webp?websiteId=default&connectorId=fs-storage'), linear-gradient(#0ca311 0%, #0ca311 100%)`
235
+ */
236
+ export function removeTempDataFromStyles(styles: Style[]): Style[] {
237
+ const pattern = /url\((["']?)([^"']+?)\1\)/g
238
+ return styles.map((style: Style) => {
239
+ if (style.style && style.style['background-image']) {
240
+ const bgImage = style.style['background-image']
241
+ .replace(/url\((['"]?)([^'"]+)\1\)/g, (match, quote, url) => {
242
+ return `url(${quote}${displayedToStored(url)}${quote})`
243
+ })
244
+ return {
245
+ ...style,
246
+ style: {
247
+ ...style.style,
248
+ 'background-image': bgImage,
249
+ },
250
+ }
251
+ }
252
+ return style
253
+ })
254
+ }
@@ -16,16 +16,27 @@
16
16
  */
17
17
 
18
18
  import { Config } from '@silexlabs/silex-plugins'
19
- import { getEditorConfig } from './grapesjs'
19
+ import { getEditor, getEditorConfig } from './grapesjs'
20
20
  import { CLIENT_CONFIG_FILE_NAME, DEFAULT_LANGUAGE, DEFAULT_WEBSITE_ID } from '../constants'
21
21
  import { ConnectorId, WebsiteId } from '../types'
22
- import { EditorConfig } from 'grapesjs'
22
+ import { Editor, EditorConfig, Page } from 'grapesjs'
23
+ import { PublicationTransformer, publicationTransformerDefault, validatePublicationTransformer } from './publication-transformers'
24
+ import * as api from './api'
25
+ import { assetsPublicationTransformer } from './assetUrl'
26
+ import { SettingsSection } from './grapesjs/settings-sections'
27
+ import { addSection, removeSection } from './grapesjs/settings'
28
+
29
+ // Plugins
30
+ import publishCustomCodeBlock from './publish-custom-code-block'
31
+ import publishFonts from './publish-fonts'
23
32
 
24
33
  /**
25
34
  * @fileoverview Silex client side config
26
35
  */
27
36
 
28
37
  export class ClientConfig extends Config {
38
+ api = api
39
+
29
40
  /**
30
41
  * The website to load
31
42
  * This is the id of the website in the storage connector
@@ -46,17 +57,45 @@ export class ClientConfig extends Config {
46
57
  /**
47
58
  * root url of Silex app
48
59
  */
49
- rootUrl = window.location.origin
60
+ rootUrl = window.location.origin + window.location.pathname.replace(/\/$/, '')
50
61
 
51
62
  /**
52
63
  * debug mode
53
64
  */
54
65
  debug = false
55
66
 
67
+ /**
68
+ * Add hash in the file name of CSS at the time of publication
69
+ * If true, CSS files of generated pages will look like `page-name.123456.css` instead of `page-name.css`
70
+ * This is useful to avoid caching issues
71
+ * @default true
72
+ */
73
+ addHashInCssFileName = true
74
+
75
+ /**
76
+ * Replaced elements
77
+ * This is a list of elements which support the object-fit and object-position CSS properties
78
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element
79
+ * When selected, Silex will show the object-fit and object-position properties in the style panel
80
+ */
81
+ replacedElements = [
82
+ 'img',
83
+ 'video',
84
+ 'iframe',
85
+ 'embed',
86
+ 'object',
87
+ 'audio',
88
+ 'canvas',
89
+ // 'option',
90
+ ]
91
+
56
92
  /**
57
93
  * Grapesjs config
58
94
  */
59
- grapesJsConfig: EditorConfig
95
+ grapesJsConfig: EditorConfig = {
96
+ plugins: [],
97
+ pluginsOpts: {},
98
+ }
60
99
 
61
100
  /**
62
101
  * Client config url
@@ -64,10 +103,99 @@ export class ClientConfig extends Config {
64
103
  */
65
104
  clientConfigUrl = `${this.rootUrl}/${CLIENT_CONFIG_FILE_NAME}`
66
105
 
106
+ /**
107
+ * Google fonts API key, see this doc to get an API key: https://developers.google.com/fonts/docs/developer_api#APIKey
108
+ * @default Test key for local dev
109
+ */
110
+ fontsApiKey = 'AIzaSyAdJTYSLPlKz4w5Iqyy-JAF2o8uQKd1FKc'
111
+
112
+ /**
113
+ * Google fonts server or a free privacy-friendly drop-in replacement for Google Fonts or a proxy server to speed up the load and protect privacy
114
+ * @see https://github.com/coollabsio/fonts
115
+ * @see https://fontlay.com/
116
+ * @default Google Fonts
117
+ */
118
+ fontsServerUrl = 'https://fonts.googleapis.com'
119
+ fontsApiUrl = 'https://www.googleapis.com'
120
+
67
121
  /**
68
122
  * Init GrapesJS config which depend on the config file properties
69
123
  */
70
124
  initGrapesConfig() {
71
- this.grapesJsConfig = getEditorConfig(this.websiteId, this.storageId, this.rootUrl)
125
+ // Get the initial config
126
+ const config = getEditorConfig(this)
127
+
128
+ // Merge with the config modified by plugins
129
+ this.grapesJsConfig = {
130
+ ...this.grapesJsConfig,
131
+ ...config,
132
+ plugins: [
133
+ ...this.grapesJsConfig.plugins,
134
+ ...config.plugins,
135
+ ],
136
+ pluginsOpts: {
137
+ ...this.grapesJsConfig.pluginsOpts,
138
+ ...config.pluginsOpts,
139
+ },
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Get grapesjs editor
145
+ */
146
+ getEditor(): Editor {
147
+ return getEditor()
148
+ }
149
+
150
+ /**
151
+ * Publication transformers let plugins change files before they are published
152
+ */
153
+ publicationTransformers: Array<PublicationTransformer> = [assetsPublicationTransformer, publicationTransformerDefault]
154
+
155
+ /**
156
+ * Reset publication transformers
157
+ */
158
+ resetPublicationTransformers() {
159
+ this.publicationTransformers = [assetsPublicationTransformer]
160
+ }
161
+
162
+ /**
163
+ * Add a publication transformer(s)
164
+ */
165
+ addPublicationTransformers(transformers: PublicationTransformer | PublicationTransformer[]) {
166
+ // Make sure it is an array
167
+ if (!Array.isArray(transformers)) {
168
+ transformers = [transformers]
169
+ }
170
+ // Validate
171
+ transformers.forEach(transformer => {
172
+ validatePublicationTransformer(transformer)
173
+ })
174
+ // Add to the list
175
+ this.publicationTransformers = this.publicationTransformers.concat(transformers)
176
+ }
177
+
178
+ /**
179
+ * Add a section to the settings dialog
180
+ */
181
+ addSettings(section: SettingsSection, siteOrPage: 'site' | 'page', position: 'first' | 'last' | number = 'last') {
182
+ addSection(section, siteOrPage, position)
183
+ }
184
+
185
+ /**
186
+ * Remove a section from the settings dialog
187
+ */
188
+ removeSettings(id: string, siteOrPage: 'site' | 'page') {
189
+ removeSection(id, siteOrPage)
190
+ }
191
+
192
+ /**
193
+ * Add default plugins
194
+ */
195
+ async addDefaultPlugins() {
196
+ await this.addPlugin([
197
+ publishCustomCodeBlock,
198
+ publishFonts,
199
+ ], {})
72
200
  }
73
201
  }
@@ -16,16 +16,28 @@
16
16
  */
17
17
 
18
18
  export enum ClientEvent {
19
- STARTUP_START = 'silex:startup:start',
20
- STARTUP_END = 'silex:startup:end',
21
- GRAPESJS_START = 'silex:grapesjs:start',
22
- GRAPESJS_END = 'silex:grapesjs:end',
23
- PUBLISH_START = 'silex:publish:start',
24
- PUBLISH_DATA = 'silex:publish:data',
25
- PUBLISH_END = 'silex:publish:end',
26
- PUBLISH_ERROR = 'silex:publish:error',
27
- PUBLISH_LOGIN_START = 'silex:publish:login:start',
19
+ // Sent on the config object
20
+ STARTUP_START = 'silex:startup:start', /* Loading is over and Silex is starting */
21
+ STARTUP_END = 'silex:startup:end', /* Silex is ready to be used */
22
+ GRAPESJS_START = 'silex:grapesjs:start', /* GrapesJS is about to be initialized, it is time to edit config.grapesJsConfig */
23
+ GRAPESJS_END = 'silex:grapesjs:end', /* GrapesJS is ready to be used, `editor` is passed as an argument */
24
+
25
+ // Sent on GrapesJs editor object (returned by silex.getEditor())
26
+ PUBLICATION_UI_OPEN = 'silex:publication-ui:open', /* The publication UI is opened, you can access it with { publicationUi } */
27
+ PUBLICATION_UI_CLOSE = 'silex:publication-ui:close', /* The publication UI is closed, you can access it with { publicationUi } */
28
+ PUBLISH_BEFORE = 'silex:publish:before', /* Publication is about to start, you can read+write {projectData, siteSettings} */
29
+ PUBLISH_START = 'silex:publish:start', /* Publication starts, you can read+write project data/settings, use publication manager/ui, prevent publication {projectData, siteSettings, publicationManager, prenventDefault} */
30
+ PUBLISH_PAGE = 'silex:publish:page', /* Publication of a page, read+write settings and page data, use publication manager and prevent publication { siteSettings, pageSettings, page, publicationManager, preventDefault } */
31
+ PUBLISH_DATA = 'silex:publish:data', /* Just before we send the published data to the server, read+write all publication data, check PublicationData type in types.ts { data, publicationManager } */
32
+ PUBLISH_END = 'silex:publish:end', /* Publication is over, the argument is the publication result with {success: boolean, message: string} */
33
+ PUBLISH_ERROR = 'silex:publish:error', /* Publication failed, the argument is the publication result with {success: boolean, message: string} */
34
+ PUBLISH_LOGIN_START = 'silex:publish:login:start', /* The user is about to login before publication, you can read+write connector data and use publication manager and prevent publication {connector, publicationManager, preventDefault} */
28
35
  PUBLISH_LOGIN_END = 'silex:publish:login:end',
29
36
  ASSET_WRITE_END = 'silex:asset:write:end',
30
37
  WRITE_END = 'silex:write:end',
38
+ SETTINGS_OPEN = 'silex:settings:open', /* The settings dialog is opened */
39
+ SETTINGS_CLOSE = 'silex:settings:close', /* The settings dialog is closed */
40
+ SETTINGS_SAVE_START = 'silex:settings:save:start', /* The settings dialog is closed and the settings are about to be saved */
41
+ SETTINGS_SAVE_END = 'silex:settings:save:end', /* The settings dialog is closed and the settings are saved */
42
+ SETTINGS_SECTION_CHANGE = 'silex:settings:section-change', /* The user clicked on a section in the settings dialog */
31
43
  }
@@ -21,12 +21,14 @@ export async function getCurrentUser(editor: Editor): Promise<ConnectorUser> {
21
21
  }
22
22
 
23
23
  export async function updateUser(editor: Editor, type: ConnectorType, connectorId?: ConnectorId): Promise<ConnectorUser> {
24
- console.log('updateUser', type, connectorId)
25
24
  const user = await getUser({type, connectorId})
26
25
  editor.getModel().set('user', user)
27
26
  return user
28
27
  }
29
28
 
29
+ // Orging and path, should we use config.rootUrl?
30
+ const SERVER_URL = window.location.origin + window.location.pathname.replace(/\/$/, '')
31
+
30
32
  let open = false
31
33
  let body: HTMLElement | null = null
32
34
  export default function loginDialogPlugin(editor, opts) {
@@ -133,7 +135,7 @@ export default function loginDialogPlugin(editor, opts) {
133
135
  }
134
136
  }
135
137
  async function loginWithConnector(connector: ConnectorData) {
136
- const nonOAuthUrl = `${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN}?connectorId=${connector.connectorId}&type=${connector.type}`
138
+ const nonOAuthUrl = `${SERVER_URL}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN}?connectorId=${connector.connectorId}&type=${connector.type}`
137
139
  window.open(connector.oauthUrl ?? nonOAuthUrl, '_blank')
138
140
  return new Promise(resolve => {
139
141
  render(html`