@silexlabs/silex 3.0.0-alpha.100

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 (282) hide show
  1. package/.env.default +19 -0
  2. package/.silex.js +37 -0
  3. package/LICENSE +661 -0
  4. package/README.md +96 -0
  5. package/dist/client/client/api.d.ts +85 -0
  6. package/dist/client/client/assetUrl.d.ts +51 -0
  7. package/dist/client/client/config.d.ts +58 -0
  8. package/dist/client/client/events.d.ts +14 -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 +72 -0
  12. package/dist/client/client/grapesjs/PublicationUi.d.ts +62 -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/footer.d.ts +2 -0
  16. package/dist/client/client/grapesjs/index.d.ts +5 -0
  17. package/dist/client/client/grapesjs/internal-links.d.ts +1 -0
  18. package/dist/client/client/grapesjs/new-page-dialog.d.ts +2 -0
  19. package/dist/client/client/grapesjs/openImport.d.ts +9 -0
  20. package/dist/client/client/grapesjs/page-panel.d.ts +3 -0
  21. package/dist/client/client/grapesjs/project-bar.d.ts +1 -0
  22. package/dist/client/client/grapesjs/rich-text.d.ts +1 -0
  23. package/dist/client/client/grapesjs/semantic.d.ts +1 -0
  24. package/dist/client/client/grapesjs/settings.d.ts +2 -0
  25. package/dist/client/client/grapesjs/storage.d.ts +1 -0
  26. package/dist/client/client/grapesjs/symbolDialogs.d.ts +3 -0
  27. package/dist/client/client/index.d.ts +5 -0
  28. package/dist/client/client/publication-transformers.d.ts +41 -0
  29. package/dist/client/client/utils.d.ts +2 -0
  30. package/dist/client/constants.d.ts +29 -0
  31. package/dist/client/css/admin.css +4491 -0
  32. package/dist/client/index.html +9 -0
  33. package/dist/client/js/main.js +321 -0
  34. package/dist/client/js/main.js.LICENSE.txt +24 -0
  35. package/dist/client/page.d.ts +2 -0
  36. package/dist/client/types.d.ts +334 -0
  37. package/dist/plugins/client/client/api.d.ts +85 -0
  38. package/dist/plugins/client/client/api.js +114 -0
  39. package/dist/plugins/client/client/api.js.map +1 -0
  40. package/dist/plugins/client/client/assetUrl.d.ts +51 -0
  41. package/dist/plugins/client/client/assetUrl.js +224 -0
  42. package/dist/plugins/client/client/assetUrl.js.map +1 -0
  43. package/dist/plugins/client/client/config.d.ts +58 -0
  44. package/dist/plugins/client/client/config.js +90 -0
  45. package/dist/plugins/client/client/config.js.map +1 -0
  46. package/dist/plugins/client/client/events.d.ts +14 -0
  47. package/dist/plugins/client/client/events.js +34 -0
  48. package/dist/plugins/client/client/events.js.map +1 -0
  49. package/dist/plugins/client/client/grapesjs/LoginDialog.d.ts +15 -0
  50. package/dist/plugins/client/client/grapesjs/LoginDialog.js +195 -0
  51. package/dist/plugins/client/client/grapesjs/LoginDialog.js.map +1 -0
  52. package/dist/plugins/client/client/grapesjs/PublicationManager.d.ts +72 -0
  53. package/dist/plugins/client/client/grapesjs/PublicationManager.js +356 -0
  54. package/dist/plugins/client/client/grapesjs/PublicationManager.js.map +1 -0
  55. package/dist/plugins/client/client/grapesjs/PublicationUi.d.ts +62 -0
  56. package/dist/plugins/client/client/grapesjs/PublicationUi.js +336 -0
  57. package/dist/plugins/client/client/grapesjs/PublicationUi.js.map +1 -0
  58. package/dist/plugins/client/client/grapesjs/blocks.d.ts +1 -0
  59. package/dist/plugins/client/client/grapesjs/blocks.js +37 -0
  60. package/dist/plugins/client/client/grapesjs/blocks.js.map +1 -0
  61. package/dist/plugins/client/client/grapesjs/breadcrumbs.d.ts +1 -0
  62. package/dist/plugins/client/client/grapesjs/breadcrumbs.js +75 -0
  63. package/dist/plugins/client/client/grapesjs/breadcrumbs.js.map +1 -0
  64. package/dist/plugins/client/client/grapesjs/footer.d.ts +2 -0
  65. package/dist/plugins/client/client/grapesjs/footer.js +28 -0
  66. package/dist/plugins/client/client/grapesjs/footer.js.map +1 -0
  67. package/dist/plugins/client/client/grapesjs/index.d.ts +5 -0
  68. package/dist/plugins/client/client/grapesjs/index.js +313 -0
  69. package/dist/plugins/client/client/grapesjs/index.js.map +1 -0
  70. package/dist/plugins/client/client/grapesjs/internal-links.d.ts +1 -0
  71. package/dist/plugins/client/client/grapesjs/internal-links.js +219 -0
  72. package/dist/plugins/client/client/grapesjs/internal-links.js.map +1 -0
  73. package/dist/plugins/client/client/grapesjs/new-page-dialog.d.ts +2 -0
  74. package/dist/plugins/client/client/grapesjs/new-page-dialog.js +83 -0
  75. package/dist/plugins/client/client/grapesjs/new-page-dialog.js.map +1 -0
  76. package/dist/plugins/client/client/grapesjs/openImport.d.ts +9 -0
  77. package/dist/plugins/client/client/grapesjs/openImport.js +74 -0
  78. package/dist/plugins/client/client/grapesjs/openImport.js.map +1 -0
  79. package/dist/plugins/client/client/grapesjs/page-panel.d.ts +3 -0
  80. package/dist/plugins/client/client/grapesjs/page-panel.js +113 -0
  81. package/dist/plugins/client/client/grapesjs/page-panel.js.map +1 -0
  82. package/dist/plugins/client/client/grapesjs/project-bar.d.ts +1 -0
  83. package/dist/plugins/client/client/grapesjs/project-bar.js +104 -0
  84. package/dist/plugins/client/client/grapesjs/project-bar.js.map +1 -0
  85. package/dist/plugins/client/client/grapesjs/rich-text.d.ts +1 -0
  86. package/dist/plugins/client/client/grapesjs/rich-text.js +31 -0
  87. package/dist/plugins/client/client/grapesjs/rich-text.js.map +1 -0
  88. package/dist/plugins/client/client/grapesjs/semantic.d.ts +1 -0
  89. package/dist/plugins/client/client/grapesjs/semantic.js +110 -0
  90. package/dist/plugins/client/client/grapesjs/semantic.js.map +1 -0
  91. package/dist/plugins/client/client/grapesjs/settings.d.ts +2 -0
  92. package/dist/plugins/client/client/grapesjs/settings.js +198 -0
  93. package/dist/plugins/client/client/grapesjs/settings.js.map +1 -0
  94. package/dist/plugins/client/client/grapesjs/storage.d.ts +1 -0
  95. package/dist/plugins/client/client/grapesjs/storage.js +126 -0
  96. package/dist/plugins/client/client/grapesjs/storage.js.map +1 -0
  97. package/dist/plugins/client/client/grapesjs/symbolDialogs.d.ts +3 -0
  98. package/dist/plugins/client/client/grapesjs/symbolDialogs.js +36 -0
  99. package/dist/plugins/client/client/grapesjs/symbolDialogs.js.map +1 -0
  100. package/dist/plugins/client/client/publication-transformers.d.ts +41 -0
  101. package/dist/plugins/client/client/publication-transformers.js +238 -0
  102. package/dist/plugins/client/client/publication-transformers.js.map +1 -0
  103. package/dist/plugins/client/client/utils.d.ts +2 -0
  104. package/dist/plugins/client/client/utils.js +25 -0
  105. package/dist/plugins/client/client/utils.js.map +1 -0
  106. package/dist/plugins/client/constants.d.ts +29 -0
  107. package/dist/plugins/client/constants.js +46 -0
  108. package/dist/plugins/client/constants.js.map +1 -0
  109. package/dist/plugins/client/page.d.ts +2 -0
  110. package/dist/plugins/client/page.js +31 -0
  111. package/dist/plugins/client/page.js.map +1 -0
  112. package/dist/plugins/client/plugins/client/11ty.d.ts +17 -0
  113. package/dist/plugins/client/plugins/client/11ty.js +86 -0
  114. package/dist/plugins/client/plugins/client/11ty.js.map +1 -0
  115. package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +2 -0
  116. package/dist/plugins/client/plugins/client/publicationRenderer.js +170 -0
  117. package/dist/plugins/client/plugins/client/publicationRenderer.js.map +1 -0
  118. package/dist/plugins/client/plugins/client/template.d.ts +2 -0
  119. package/dist/plugins/client/plugins/client/template.js +183 -0
  120. package/dist/plugins/client/plugins/client/template.js.map +1 -0
  121. package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
  122. package/dist/plugins/client/plugins/client/website-info.js +72 -0
  123. package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
  124. package/dist/plugins/client/types.d.ts +334 -0
  125. package/dist/plugins/client/types.js +74 -0
  126. package/dist/plugins/client/types.js.map +1 -0
  127. package/dist/plugins/server/constants.d.ts +29 -0
  128. package/dist/plugins/server/constants.js +49 -0
  129. package/dist/plugins/server/constants.js.map +1 -0
  130. package/dist/plugins/server/plugins/server/AuthPlugin.d.ts +1 -0
  131. package/dist/plugins/server/plugins/server/AuthPlugin.js +40 -0
  132. package/dist/plugins/server/plugins/server/AuthPlugin.js.map +1 -0
  133. package/dist/plugins/server/plugins/server/Cache.d.ts +2 -0
  134. package/dist/plugins/server/plugins/server/Cache.js +32 -0
  135. package/dist/plugins/server/plugins/server/Cache.js.map +1 -0
  136. package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
  137. package/dist/plugins/server/plugins/server/DownloadConnector.js +129 -0
  138. package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
  139. package/dist/plugins/server/plugins/server/FtpConnector.d.ts +86 -0
  140. package/dist/plugins/server/plugins/server/FtpConnector.js +526 -0
  141. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -0
  142. package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +87 -0
  143. package/dist/plugins/server/plugins/server/GitlabConnector.js +564 -0
  144. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -0
  145. package/dist/plugins/server/plugins/server/PublicationOptimizer.d.ts +0 -0
  146. package/dist/plugins/server/plugins/server/PublicationOptimizer.js +14 -0
  147. package/dist/plugins/server/plugins/server/PublicationOptimizer.js.map +1 -0
  148. package/dist/plugins/server/plugins/server/SslPlugin.d.ts +1 -0
  149. package/dist/plugins/server/plugins/server/SslPlugin.js +86 -0
  150. package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -0
  151. package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +1 -0
  152. package/dist/plugins/server/plugins/server/StaticPlugin.js +78 -0
  153. package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -0
  154. package/dist/plugins/server/server/config.d.ts +59 -0
  155. package/dist/plugins/server/server/config.js +181 -0
  156. package/dist/plugins/server/server/config.js.map +1 -0
  157. package/dist/plugins/server/server/connectors/FsHosting.d.ts +13 -0
  158. package/dist/plugins/server/server/connectors/FsHosting.js +54 -0
  159. package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -0
  160. package/dist/plugins/server/server/connectors/FsStorage.d.ts +43 -0
  161. package/dist/plugins/server/server/connectors/FsStorage.js +257 -0
  162. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -0
  163. package/dist/plugins/server/server/connectors/connectors.d.ts +87 -0
  164. package/dist/plugins/server/server/connectors/connectors.js +127 -0
  165. package/dist/plugins/server/server/connectors/connectors.js.map +1 -0
  166. package/dist/plugins/server/server/events.d.ts +26 -0
  167. package/dist/plugins/server/server/events.js +31 -0
  168. package/dist/plugins/server/server/events.js.map +1 -0
  169. package/dist/plugins/server/server/jobs.d.ts +12 -0
  170. package/dist/plugins/server/server/jobs.js +77 -0
  171. package/dist/plugins/server/server/jobs.js.map +1 -0
  172. package/dist/plugins/server/server/utils/validation.d.ts +7 -0
  173. package/dist/plugins/server/server/utils/validation.js +38 -0
  174. package/dist/plugins/server/server/utils/validation.js.map +1 -0
  175. package/dist/plugins/server/types.d.ts +334 -0
  176. package/dist/plugins/server/types.js +78 -0
  177. package/dist/plugins/server/types.js.map +1 -0
  178. package/dist/server/constants.js +29 -0
  179. package/dist/server/plugins/server/Cache.js +15 -0
  180. package/dist/server/server/api/api.js +20 -0
  181. package/dist/server/server/api/connectorApi.js +216 -0
  182. package/dist/server/server/api/publicationApi.js +108 -0
  183. package/dist/server/server/api/websiteApi.js +296 -0
  184. package/dist/server/server/cli.js +68 -0
  185. package/dist/server/server/config.js +120 -0
  186. package/dist/server/server/connectors/FsHosting.js +35 -0
  187. package/dist/server/server/connectors/FsStorage.js +225 -0
  188. package/dist/server/server/connectors/connectors.js +89 -0
  189. package/dist/server/server/events.js +14 -0
  190. package/dist/server/server/expose.js +27 -0
  191. package/dist/server/server/express.js +47 -0
  192. package/dist/server/server/index.js +90 -0
  193. package/dist/server/server/jobs.js +48 -0
  194. package/dist/server/server/utils/validation.js +15 -0
  195. package/dist/server/types.js +34 -0
  196. package/package.json +209 -0
  197. package/public/assets/container.png +0 -0
  198. package/public/assets/favicon.png +0 -0
  199. package/public/assets/logo-silex-small.png +0 -0
  200. package/public/robots.txt +2 -0
  201. package/public/silex.js +24 -0
  202. package/src/css/_mixins.scss +8 -0
  203. package/src/css/_variables.scss +33 -0
  204. package/src/css/dialog.scss +41 -0
  205. package/src/css/footer.scss +12 -0
  206. package/src/css/grapesjs-light.scss +180 -0
  207. package/src/css/grapesjs.scss +152 -0
  208. package/src/css/index.scss +32 -0
  209. package/src/css/light.scss +7 -0
  210. package/src/css/loader.scss +12 -0
  211. package/src/css/page-panel.scss +65 -0
  212. package/src/css/project-bar.scss +102 -0
  213. package/src/css/silex.scss +189 -0
  214. package/src/css/website-info.scss +14 -0
  215. package/src/html/debug.pug +8 -0
  216. package/src/html/index.pug +39 -0
  217. package/src/html/templates/includes.pug +1 -0
  218. package/src/html/templates/workspace.pug +2 -0
  219. package/src/ts/client/api.ts +144 -0
  220. package/src/ts/client/assetUrl.test.ts +125 -0
  221. package/src/ts/client/assetUrl.ts +235 -0
  222. package/src/ts/client/config.ts +105 -0
  223. package/src/ts/client/events.ts +34 -0
  224. package/src/ts/client/expose.ts +30 -0
  225. package/src/ts/client/grapesjs/LoginDialog.ts +204 -0
  226. package/src/ts/client/grapesjs/PublicationManager.ts +370 -0
  227. package/src/ts/client/grapesjs/PublicationUi.ts +342 -0
  228. package/src/ts/client/grapesjs/blocks.ts +37 -0
  229. package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
  230. package/src/ts/client/grapesjs/eleventy.ts +47 -0
  231. package/src/ts/client/grapesjs/footer.ts +27 -0
  232. package/src/ts/client/grapesjs/index.ts +335 -0
  233. package/src/ts/client/grapesjs/internal-links.test.ts +105 -0
  234. package/src/ts/client/grapesjs/internal-links.ts +225 -0
  235. package/src/ts/client/grapesjs/new-page-dialog.ts +90 -0
  236. package/src/ts/client/grapesjs/openImport.ts +81 -0
  237. package/src/ts/client/grapesjs/page-panel.ts +118 -0
  238. package/src/ts/client/grapesjs/project-bar.ts +107 -0
  239. package/src/ts/client/grapesjs/rich-text.ts +33 -0
  240. package/src/ts/client/grapesjs/semantic.ts +114 -0
  241. package/src/ts/client/grapesjs/settings.ts +208 -0
  242. package/src/ts/client/grapesjs/storage.ts +121 -0
  243. package/src/ts/client/grapesjs/symbolDialogs.ts +38 -0
  244. package/src/ts/client/index.ts +98 -0
  245. package/src/ts/client/publication-transformers.test.ts +199 -0
  246. package/src/ts/client/publication-transformers.ts +263 -0
  247. package/src/ts/client/utils.ts +28 -0
  248. package/src/ts/constants.ts +52 -0
  249. package/src/ts/externs.ts +18 -0
  250. package/src/ts/page.ts +31 -0
  251. package/src/ts/plugins/client/11ty.ts +104 -0
  252. package/src/ts/plugins/client/publicationRenderer.ts +174 -0
  253. package/src/ts/plugins/client/template.ts +192 -0
  254. package/src/ts/plugins/client/website-info.ts +84 -0
  255. package/src/ts/plugins/server/AuthPlugin.ts +38 -0
  256. package/src/ts/plugins/server/Cache.ts +28 -0
  257. package/src/ts/plugins/server/DownloadConnector.ts +148 -0
  258. package/src/ts/plugins/server/FtpConnector.test.ts +82 -0
  259. package/src/ts/plugins/server/FtpConnector.ts +609 -0
  260. package/src/ts/plugins/server/GitlabConnector.ts +644 -0
  261. package/src/ts/plugins/server/PublicationOptimizer.ts +14 -0
  262. package/src/ts/plugins/server/SslPlugin.ts +84 -0
  263. package/src/ts/plugins/server/StaticPlugin.ts +79 -0
  264. package/src/ts/server/api/api.ts +19 -0
  265. package/src/ts/server/api/connectorApi.ts +345 -0
  266. package/src/ts/server/api/publicationApi.ts +159 -0
  267. package/src/ts/server/api/websiteApi.ts +432 -0
  268. package/src/ts/server/cli.ts +65 -0
  269. package/src/ts/server/config.ts +189 -0
  270. package/src/ts/server/connectors/FsHosting.ts +60 -0
  271. package/src/ts/server/connectors/FsStorage.test.ts +51 -0
  272. package/src/ts/server/connectors/FsStorage.ts +261 -0
  273. package/src/ts/server/connectors/connectors.ts +203 -0
  274. package/src/ts/server/events.ts +37 -0
  275. package/src/ts/server/expose.ts +19 -0
  276. package/src/ts/server/express.ts +70 -0
  277. package/src/ts/server/index.ts +100 -0
  278. package/src/ts/server/jobs.test.ts +75 -0
  279. package/src/ts/server/jobs.ts +87 -0
  280. package/src/ts/server/utils/BackwardCompat.ts +552 -0
  281. package/src/ts/server/utils/validation.ts +34 -0
  282. package/src/ts/types.ts +339 -0
@@ -0,0 +1,335 @@
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 grapesjs, { Editor, EditorConfig } from 'grapesjs'
19
+ import openImport from './openImport'
20
+
21
+ /**
22
+ * @fileoverview This is where grapes config gets created
23
+ * Handle plugins, options and initialization of the editor
24
+ */
25
+
26
+ // ////////////////////
27
+ // Plugins
28
+ // ////////////////////
29
+ import blocksBasicPlugin from 'grapesjs-blocks-basic'
30
+ import styleFilterPlugin from 'grapesjs-style-filter'
31
+ import formPlugin from 'grapesjs-plugin-forms'
32
+ import codePlugin from 'grapesjs-custom-code'
33
+ import uiSuggestClasses from '@silexlabs/grapesjs-ui-suggest-classes'
34
+ import symbolsPlugin from '@silexlabs/grapesjs-symbols'
35
+ import loadingPlugin from '@silexlabs/grapesjs-loading'
36
+ import fontsDialogPlugin, { cmdOpenFonts } from '@silexlabs/grapesjs-fonts'
37
+ import symbolDialogsPlugin, { cmdPromptAddSymbol } from './symbolDialogs'
38
+ import loginDialogPlugin, { LoginDialogOptions, cmdLogout } from './LoginDialog'
39
+ import footerPlugin from './footer'
40
+ import breadcrumbsPlugin from './breadcrumbs'
41
+ import rateLimitPlugin from '@silexlabs/grapesjs-storage-rate-limit'
42
+
43
+ import { pagePanelPlugin, cmdTogglePages, cmdAddPage } from './page-panel'
44
+ import { newPageDialog, cmdOpenNewPageDialog } from './new-page-dialog'
45
+ import { projectBarPlugin } from './project-bar'
46
+ import { settingsDialog, cmdOpenSettings } from './settings'
47
+ import { blocksPlugin } from './blocks'
48
+ import { semanticPlugin } from './semantic'
49
+ import { richTextPlugin } from './rich-text'
50
+ import { internalLinksPlugin } from './internal-links'
51
+ import publicationManagerPlugin, { PublicationManagerOptions } from './PublicationManager'
52
+ import { storagePlugin } from './storage'
53
+ import { ConnectorId, WebsiteId } from '../../types'
54
+ import { API_PATH, API_WEBSITE_ASSETS_WRITE, API_WEBSITE_PATH } from '../../constants'
55
+
56
+ const plugins = [
57
+ {name: './project-bar', value: projectBarPlugin}, // has to be before panels and dialogs
58
+ {name: './settings', value: settingsDialog},
59
+ {name: '@silexlabs/grapesjs-fonts', value: fontsDialogPlugin},
60
+ {name: './new-page-dialog', value: newPageDialog},
61
+ {name: './page-panel', value: pagePanelPlugin},
62
+ {name: 'grapesjs-blocks-basic', value: blocksBasicPlugin},
63
+ {name: './blocks', value: blocksPlugin},
64
+ {name: './semantic', value: semanticPlugin},
65
+ {name: './rich-text', value: richTextPlugin},
66
+ {name: 'grapesjs-style-filter', value: styleFilterPlugin},
67
+ {name: 'grapesjs-plugin-forms', value: formPlugin},
68
+ {name: 'grapesjs-custom-code', value: codePlugin},
69
+ {name: './internal-links', value: internalLinksPlugin},
70
+ {name: '@silexlabs/grapesjs-ui-suggest-classes', value: uiSuggestClasses},
71
+ {name: './symbolDialogs', value: symbolDialogsPlugin},
72
+ {name: '@silexlabs/grapesjs-symbols', value: symbolsPlugin},
73
+ {name: './PublicationManager', value: publicationManagerPlugin},
74
+ {name: './storage', value: storagePlugin},
75
+ {name: './LoginDialog', value: loginDialogPlugin},
76
+ {name: '@silexlabs/grapesjs-loading', value: loadingPlugin},
77
+ {name: './breadcrumbs', value: breadcrumbsPlugin},
78
+ {name: './footer', value: footerPlugin},
79
+ {name: '@silexlabs/grapesjs-storage-rate-limit', value: rateLimitPlugin},
80
+ ]
81
+ // Check that all plugins are loaded correctly
82
+ plugins
83
+ .filter(p => typeof p.value !== 'function')
84
+ .forEach(p => {
85
+ throw new Error(`Plugin ${p.name} could not be loaded correctly (${p.value})`)
86
+ })
87
+
88
+ // Constants
89
+ const PRIMARY_COLOR = '#333333'
90
+ const SECONDARY_COLOR = '#ddd'
91
+ const TERTIARY_COLOR = '#8873FE'
92
+ const QUATERNARY_COLOR = '#A291FF'
93
+ const DARKER_PRIMARY_COLOR = '#363636'
94
+ const LIGHTER_PRIMARY_COLOR = '#575757'
95
+
96
+ // ////////////////////
97
+ // Config
98
+ // ////////////////////
99
+ const catBasic = 'Containers'
100
+ const catComponents = 'Components'
101
+
102
+ export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl: string): EditorConfig {
103
+ return {
104
+ container: '#gjs',
105
+ height: '100%',
106
+ showOffsets: true,
107
+ showDevices: true,
108
+
109
+ //pageManager: {},
110
+
111
+ layerManager: {
112
+ appendTo: '.layer-manager-container',
113
+ },
114
+
115
+ blockManager: {
116
+ appendTo: '.block-manager-container',
117
+ },
118
+
119
+ assetManager: {
120
+ upload: `${rootUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSETS_WRITE}/?websiteId=${id}${ connectorId ? `&connectorId=${connectorId}` : ''}`,
121
+ },
122
+
123
+ storageManager: {
124
+ autoload: false,
125
+ type: 'connector',
126
+ options: {
127
+ connector: {
128
+ id,
129
+ connectorId,
130
+ },
131
+ },
132
+ },
133
+
134
+ cssIcons: './css/all.min.css',
135
+ canvasCss: `
136
+ :root {
137
+ --primaryColor: ${PRIMARY_COLOR};
138
+ --secondaryColor: ${SECONDARY_COLOR};
139
+ --tertiaryColor: ${TERTIARY_COLOR};
140
+ --quaternaryColor: ${QUATERNARY_COLOR};
141
+ --darkerPrimaryColor: ${DARKER_PRIMARY_COLOR};
142
+ --lighterPrimaryColor: ${LIGHTER_PRIMARY_COLOR};
143
+ }
144
+ .gjs-frame-selected {
145
+ box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5) !important; // Change to red border
146
+ }
147
+ .gjs-selected {
148
+ outline: 2px solid var(--tertiaryColor) !important;
149
+ outline-offset: -2px;
150
+ }
151
+ `,
152
+
153
+ plugins: plugins.map(p => p.value),
154
+
155
+ pluginsOpts: {
156
+ [blocksBasicPlugin as any]: {
157
+ blocks: ['text', 'image', 'video', 'map'],
158
+ category: catBasic,
159
+ //flexGrid: true,
160
+ },
161
+ [projectBarPlugin as any]: {
162
+ panels: [
163
+ {
164
+ id: 'dash',
165
+ className: 'logo',
166
+ attributes: { title: 'Dashboard' },
167
+ command: () => {
168
+ window.location.href = '/'
169
+ },
170
+ }, {
171
+ id: 'block-manager-btn',
172
+ className: 'block-manager-btn fa fa-fw fa-plus',
173
+ attributes: { title: 'Blocks', containerClassName: 'block-manager-container', },
174
+ command: 'open-blocks',
175
+ }, {
176
+ id: 'symbols-btn',
177
+ className: 'symbols-btn fa-regular fa-gem',
178
+ attributes: { title: 'Symbols', containerClassName: 'symbols-list-container', },
179
+ command: 'open-symbols',
180
+ buttons: [
181
+ {
182
+ id: 'symbol-create-button',
183
+ className: 'pages__add-page fa-solid fa-plus',
184
+ label: 'Create symbol from selection',
185
+ command: cmdPromptAddSymbol,
186
+ },
187
+ ],
188
+ }, {
189
+ id: 'page-panel-btn',
190
+ className: 'page-panel-btn fa fa-fw fa-file',
191
+ attributes: { title: 'Pages', containerClassName: 'page-panel-container', },
192
+ command: cmdTogglePages,
193
+ buttons: [{
194
+ className: 'pages__add-page fa fa-file',
195
+ command: cmdAddPage,
196
+ text: '+',
197
+ }],
198
+ }, {
199
+ id: 'layer-manager-btn',
200
+ className: 'layer-manager-btn fa-solid fa-layer-group',
201
+ attributes: { title: 'Layers', containerClassName: 'layer-manager-container', },
202
+ command: 'open-layers',
203
+ }, {
204
+ id: 'font-dialog-btn',
205
+ className: 'font-manager-btn fa-solid fa-font',
206
+ attributes: { title: 'Fonts' },
207
+ command: () => {
208
+ editor.runCommand(cmdOpenFonts)
209
+ },
210
+ }, {
211
+ id: 'settings-dialog-btn',
212
+ className: 'page-panel-btn fa-solid fa-gears',
213
+ attributes: { title: 'Settings' },
214
+ command: cmdOpenSettings,
215
+ }, {
216
+ id: 'spacer',
217
+ attributes: {},
218
+ className: 'project-bar-spacer',
219
+ }, {
220
+ id: 'dash2',
221
+ className: 'fa-solid fa-house',
222
+ attributes: { title: 'Dashboard' },
223
+ command: () => {
224
+ window.location.href = '/'
225
+ },
226
+ }, {
227
+ id: 'help',
228
+ className: 'fa fa-fw fa-question-circle',
229
+ attributes: { title: 'Documentation' },
230
+ command: () => {
231
+ window.open('https://docs.silex.me/', '_blank')
232
+ },
233
+ }, {
234
+ id: 'logout-button',
235
+ className: 'page-panel-btn fa fa-fw fa-sign-out',
236
+ attributes: { title: 'Sign out' },
237
+ command: cmdLogout,
238
+ },
239
+ ],
240
+ },
241
+ [publicationManagerPlugin as any]: {
242
+ appendTo: 'options',
243
+ websiteId: id,
244
+ } as PublicationManagerOptions,
245
+ [pagePanelPlugin as any]: {
246
+ cmdOpenNewPageDialog,
247
+ cmdOpenSettings,
248
+ appendTo: '.page-panel-container',
249
+ },
250
+ [uiSuggestClasses as any]: {
251
+ enableCount: false,
252
+ enablePerformance: false,
253
+ },
254
+ [internalLinksPlugin as any]: {
255
+ // FIXME: warn the user about links in error
256
+ onError: (errors) => console.warn('Links errors:', errors),
257
+ },
258
+ [codePlugin as any]: {
259
+ blockLabel: 'HTML',
260
+ blockCustomCode: {
261
+ category: catComponents,
262
+ }
263
+ },
264
+ [symbolsPlugin as any]: {
265
+ appendTo: '.symbols-list-container',
266
+ emptyText: 'No symbol yet.',
267
+ primaryColor: PRIMARY_COLOR,
268
+ secondaryColor: SECONDARY_COLOR,
269
+ highlightColor: TERTIARY_COLOR,
270
+ },
271
+ [fontsDialogPlugin as any]: {
272
+ api_key: 'AIzaSyAdJTYSLPlKz4w5Iqyy-JAF2o8uQKd1FKc',
273
+ },
274
+ [loginDialogPlugin as any]: {
275
+ id,
276
+ } as LoginDialogOptions,
277
+ [rateLimitPlugin as any]: {
278
+ time: 5000,
279
+ },
280
+ },
281
+ }
282
+ }
283
+
284
+ // ////////////////////
285
+ // Initialize editor
286
+ // ////////////////////
287
+ // Keep a ref to the editor singleton
288
+ let editor: Editor
289
+ export async function initEditor(config: EditorConfig) {
290
+ if(editor) throw new Error('Grapesjs editor already created')
291
+ return new Promise<Editor>((resolve, reject) => {
292
+ try {
293
+ editor = grapesjs.init(config)
294
+ } catch(e) {
295
+ console.error('Error initializing GrapesJs with plugins:', plugins, e)
296
+ reject(e)
297
+ }
298
+
299
+ // customize the editor
300
+ ['text']
301
+ .forEach(id => editor.Blocks.get(id)?.set('category', 'Basics'))
302
+ ;['image', 'video']
303
+ .forEach(id => editor.Blocks.get(id)?.set('category', 'Media'))
304
+ ;['map']
305
+ .forEach(id => editor.Blocks.get(id)?.set('category', 'Components'))
306
+ editor.Blocks.render([])
307
+
308
+ editor.Commands.add('gjs-open-import-webpage', openImport(editor, {
309
+ modalImportLabel: '',
310
+ modalImportContent: 'Paste a web page HTML code here.',
311
+ modalImportButton: 'Import',
312
+ modalImportTitle: 'Import from website',
313
+ }))
314
+
315
+ editor.on('load', () => {
316
+ // remove blocks and layers buttons from the properties
317
+ editor.Panels.getPanel('views').buttons.remove('open-blocks')
318
+ editor.Panels.getPanel('views').buttons.remove('open-layers')
319
+ editor.Panels.getPanel('views').view.el.firstChild.style.justifyContent = 'initial' // align left
320
+ editor.Panels.getPanel('options').buttons.remove('export-template')
321
+
322
+ editor.BlockManager.render(null)
323
+
324
+ // use the style filter plugin
325
+ editor.StyleManager.addProperty('extra',{ extend: 'filter' })
326
+
327
+ // GrapesJs editor is ready
328
+ resolve(editor)
329
+ })
330
+ })
331
+ }
332
+
333
+ export function getEditor() {
334
+ return editor
335
+ }
@@ -0,0 +1,105 @@
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 { internalLinksPlugin } from './internal-links'
19
+ import { expect, test, beforeEach } from '@jest/globals'
20
+ import grapesjs from 'grapesjs'
21
+
22
+ let editor
23
+ let nextId = 1
24
+ function getNewId() {
25
+ return (nextId++).toString()
26
+ }
27
+ const comp1 = {
28
+ tagName: 'a',
29
+ content: 'link to main',
30
+ attributes: { href: './index.html' },
31
+ }
32
+ const comp2 = {
33
+ tagName: 'a',
34
+ content: 'link to page 1',
35
+ attributes: { href: './page-1.html' },
36
+ }
37
+ const comp3 = {
38
+ tagName: 'a',
39
+ content: 'link to page 2',
40
+ attributes: { href: './page-2.html' },
41
+ }
42
+
43
+ const pageMain = {
44
+ id: getNewId(),
45
+ type: 'main',
46
+ component: {
47
+ tagName: 'div',
48
+ components: [comp1, comp2],
49
+ },
50
+ }
51
+ const page1 = {
52
+ id: getNewId(),
53
+ name: 'Page 1',
54
+ component: {
55
+ tagName: 'div',
56
+ components: [comp3],
57
+ },
58
+ }
59
+ const page2 = {
60
+ id: getNewId(),
61
+ name: 'Page 2',
62
+ component: {
63
+ tagName: 'div',
64
+ components: [comp1, comp2, comp3],
65
+ },
66
+ }
67
+ beforeEach(() => {
68
+ editor = grapesjs.init({
69
+ headless: true,
70
+ storageManager: { autoload: false },
71
+ pageManager: {
72
+ pages: [pageMain, page1, page2],
73
+ },
74
+ plugins: [internalLinksPlugin],
75
+ })
76
+ expect(editor).not.toBeUndefined()
77
+ })
78
+ test('init', () => {
79
+ expect(editor.getComponents()).toHaveLength(pageMain.component.components.length)
80
+ })
81
+ test('rename page and rewrite links in current page', () => {
82
+ const page = editor.Pages.getSelected()
83
+ expect(page.id).toBe(pageMain.id)
84
+ expect(page.getName()).toBeUndefined()
85
+ const newName = 'Home page'
86
+ const newPath = './home-page.html'
87
+ // Do not work: page.setName(newName)
88
+ page.set('name', newName)
89
+ expect(page.getName()).toBe(newName)
90
+ const comp1Model = page.getMainComponent().components().find(c => c.attributes.content === comp1.content)
91
+ expect(comp1Model).toBeTruthy()
92
+ expect(comp1Model.attributes.attributes.href).toBe(newPath)
93
+ })
94
+ test('rename page and rewrite links in another page', () => {
95
+ const page = editor.Pages.get(page2.id)
96
+ expect(page.get('name')).toBe(page2.name)
97
+ const newName = 'Page 2 new-name'
98
+ const newPath = './page-2-new-name.html'
99
+ // Do not work: page.setName(newName)
100
+ page.set('name', newName)
101
+ expect(page.get('name')).toBe(newName)
102
+ const comp1Model = page.getMainComponent().components().find(c => c.attributes.content === comp3.content)
103
+ expect(comp1Model).toBeTruthy()
104
+ expect(comp1Model.attributes.attributes.href).toBe(newPath)
105
+ })
@@ -0,0 +1,225 @@
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 {html, render} from 'lit-html'
19
+ import {map} from 'lit-html/directives/map.js'
20
+ import grapesjs from 'grapesjs/dist/grapes.min.js'
21
+ import { getPageLink } from '../../page'
22
+
23
+ // constants
24
+ const pluginName = 'internal-links'
25
+ const options: grapesjs.SelectOption = [
26
+ { id: '', name: '-' },
27
+ { id: 'url', name: 'URL' },
28
+ { id: 'email', name: 'Email' },
29
+ { id: 'page', name: 'Page' },
30
+ ]
31
+
32
+ // plugin code
33
+ export const internalLinksPlugin = (editor, opts) => {
34
+ // update links when a page link changes
35
+ function onAll(cbk) {
36
+ editor.Pages.getAll()
37
+ .forEach(page => {
38
+ page.getMainComponent()
39
+ .onAll(cbk)
40
+ })
41
+ }
42
+ editor.on('page', ({ event, page }) => {
43
+ if(!page) return // fixes UT
44
+ switch (event) {
45
+ case 'change:name':
46
+ // update all links to this page
47
+ onAll(component => {
48
+ if(component.getAttributes().href === getPageLink(page.previous('name'))) {
49
+ component.setAttributes({
50
+ href: getPageLink(page.get('name')),
51
+ })
52
+ }
53
+ })
54
+ break
55
+ case 'remove':
56
+ // mark all links as issues
57
+ const issues = []
58
+ onAll(component => {
59
+ console.log(component.getAttributes().href, getPageLink(page.previous('name')), page.previous('name'))
60
+ if(component.getAttributes().href === getPageLink(page.previous('name'))) {
61
+ issues.push(component)
62
+ }
63
+ })
64
+ opts?.onError(issues)
65
+ break
66
+ }
67
+ })
68
+ // utility functions to render the UI
69
+ function getUi(type, href) {
70
+ switch (type) {
71
+ case 'email':
72
+ const mailTo = href.replace('mailto:', '').split('?')
73
+ const email = mailTo[0]
74
+ const params = (mailTo[1] || '').split('&').reduce((acc, item) => {
75
+ const items = item.split('=')
76
+ acc[items[0]] = items[1]
77
+ return acc
78
+ }, {})
79
+ return html`<div class="href-next__email-inputs">
80
+ <label for="href-next__email" class="gjs-one-bg silex-label">Email address</label>
81
+ <input class="href-next__email" placeholder="Insert email" type="email" value=${email || ''}/>
82
+ <label for="href-next__email-subject" class="gjs-one-bg silex-label">Subject</label>
83
+ <input class="href-next__email-subject" placeholder="Insert subject" value=${ params.subject || '' }/>
84
+ </div>`
85
+ case 'page':
86
+ return html`<div class="href-next__page-inputs">
87
+ <label for="href-next__page" class="gjs-one-bg silex-label">Page name</label>
88
+ <select id="href-next__page" class="href-next__page">
89
+ ${
90
+ map<grapesjs.Page>(editor.Pages.getAll(), page => html`<option
91
+ ?selected=${getPageLink(page.getName()) === href}
92
+ value=${getPageLink(page.getName())}>
93
+ ${page.getName() || 'Main'}
94
+ </option>`)
95
+ }
96
+ </select>
97
+ </div>`
98
+ case 'url':
99
+ return html`<div class="href-next__url-inputs">
100
+ <label for="href-next__url" class="gjs-one-bg silex-label">URL</label>
101
+ <input class="href-next__url" placeholder="Insert URL" type="url" value=${ href }/>
102
+ </div>`
103
+ default:
104
+ return ''
105
+ }
106
+ }
107
+ function getDefaultHref(type) {
108
+ switch(type) {
109
+ case 'email': return 'mailto:'
110
+ case 'page': return getPageLink(null)
111
+ case 'url': return 'https://'
112
+ }
113
+ }
114
+ function doRender(el: HTMLElement, href = '') {
115
+ const type = getType(href)
116
+ const ui = getUi(type, href)
117
+
118
+ render(html`
119
+ <label for="href-next__type" class="gjs-one-bg silex-label">Type</label>
120
+ <select id="href-next__type" class="href-next__type" @change=${event => doRender(el, getDefaultHref(event.target.value))}>
121
+ ${map<grapesjs.SelectOption>(options, opt => html`
122
+ <option value="${opt.id}" ?selected=${type === opt.id}>${opt.name}</option>
123
+ `)}
124
+ </select>
125
+ ${ ui }
126
+ `, el)
127
+ }
128
+ function getType(href: string) {
129
+ if (href.indexOf('mailto:') === 0) {
130
+ return 'email'
131
+ } else if(href.indexOf('./') === 0){
132
+ return 'page'
133
+ } else if(href){
134
+ return 'url'
135
+ }
136
+ return ''
137
+ }
138
+ function doRenderCurrent(el) {
139
+ doRender(el, editor.getSelected()?.getAttributes().href || '')
140
+ }
141
+
142
+ // Add the new trait to all component types
143
+ editor.DomComponents.getTypes().map(type => {
144
+ editor.DomComponents.addType(type.id, {
145
+ model: {
146
+ defaults: {
147
+ traits: [
148
+ // Keep the type original traits
149
+ ...editor.DomComponents.getType(type.id).model.prototype.defaults.traits
150
+ // Filter original href trait
151
+ .filter(trait => trait.name ? trait.name !== 'href' : trait !== 'href'),
152
+ // Add the new trait
153
+ {
154
+ label: 'Link',
155
+ type: 'href-next',
156
+ name: 'href',
157
+ },
158
+ ]
159
+ }
160
+ }
161
+ })
162
+ })
163
+
164
+ editor.TraitManager.addType('href-next', {
165
+ createInput({ trait }) {
166
+ // Create a new element container and add some content
167
+ const el = document.createElement('div')
168
+ // update the UI when a page is added/renamed/removed
169
+ editor.on('page', () => doRenderCurrent(el))
170
+ doRenderCurrent(el)
171
+ // this will be the element passed to onEvent and onUpdate
172
+ return el
173
+ },
174
+ // Update the component based on UI changes
175
+ // `elInput` is the result HTMLElement you get from `createInput`
176
+ onEvent({ elInput, component, event }) {
177
+ const inputType = elInput.querySelector('.href-next__type')
178
+ let href = ''
179
+ // Compute the new HREF value
180
+ switch (inputType.value) {
181
+ case 'page':
182
+ const valPage = elInput.querySelector('.href-next__page')?.value
183
+ href = valPage || getDefaultHref('page')
184
+ break
185
+ case 'url':
186
+ const valUrl = elInput.querySelector('.href-next__url')?.value
187
+ href = valUrl || getDefaultHref('url')
188
+ break
189
+ case 'email':
190
+ const valEmail = elInput.querySelector('.href-next__email')?.value
191
+ const valSubj = elInput.querySelector('.href-next__email-subject')?.value
192
+ href = valEmail ? `mailto:${valEmail}${valSubj ? `?subject=${valSubj}` : ''}` : getDefaultHref('email')
193
+ break
194
+ default:
195
+ href = ''
196
+ }
197
+
198
+ // Store the new HREF value
199
+ component.addAttributes({ href })
200
+
201
+ // Handle the tag name
202
+ if(href === '') {
203
+ // Not a link
204
+ if(component.get('tagName').toUpperCase() === 'A'){
205
+ // Retrieve the original stored value
206
+ const original = component.get('originalTagName') ?? 'DIV'
207
+ // Case of the inline A tags inserted by the text bar
208
+ const value = original.toUpperCase() === 'A' ? 'SPAN' : original
209
+ component.set('tagName', value)
210
+ }
211
+ } else {
212
+ // Link
213
+ if(component.get('tagName').toUpperCase() !== 'A') {
214
+ component.set('originalTagName', component.get('tagName'))
215
+ component.set('tagName', 'A')
216
+ }
217
+ }
218
+ },
219
+ // Update UI on the component change
220
+ onUpdate({ elInput, component }) {
221
+ const href = component.getAttributes().href || ''
222
+ doRender(elInput, href)
223
+ },
224
+ })
225
+ }