@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,207 @@
1
+ import {Editor, PluginOptions} from 'grapesjs'
2
+ import {isTextOrInputField, selectBody} from '../utils'
3
+ import {PublishableEditor} from './PublicationManager'
4
+
5
+ // Utility functions
6
+
7
+ function setButton(editor: Editor, panel_id: string, btn_id: string, active?: boolean): void {
8
+ const button = editor.Panels.getButton(panel_id, btn_id)
9
+ button.set('active', active ?? !button.get('active'))
10
+ }
11
+
12
+ /**
13
+ * Opens the Publish dialog and publishes the website.
14
+ * @param editor The editor.
15
+ */
16
+ function publish(editor: Editor): void {
17
+ setButton(editor, 'options', 'publish-button', true)
18
+ editor.runCommand('publish')
19
+ }
20
+
21
+ /**
22
+ * Closes any open left panel.
23
+ * @param editor The editor.
24
+ */
25
+ function resetPanel(editor: Editor): void {
26
+ const projectBarBtns = editor.Panels.getPanels().get('project-bar-panel').buttons
27
+ projectBarBtns.forEach(button => button.set('active', false))
28
+ }
29
+
30
+ /**
31
+ * Escapes the current context in this order : modal, Publish dialog, left panel.
32
+ * If none of these are open, it selects the body.
33
+ * @param editor The editor.
34
+ */
35
+ function escapeContext(editor: Editor): void {
36
+ const publishDialog = (editor as PublishableEditor).PublicationManager.dialog
37
+ const projectBarPanel = editor.Panels.getPanel('project-bar-panel')
38
+
39
+ if (editor.Modal.isOpen()) {
40
+ editor.Modal.close()
41
+ } else if (publishDialog && publishDialog.isOpen) {
42
+ publishDialog.closeDialog()
43
+ } else if (projectBarPanel.buttons.some(b => b.get('active'))) {
44
+ resetPanel(editor)
45
+ } else {
46
+ selectBody(editor)
47
+ }
48
+ }
49
+
50
+ function whenNoFocus(editor: Editor, cbk: () => void): void {
51
+ if(editor.getEditing()) return
52
+ if(editor.Modal.isOpen()) return
53
+ const target = document.activeElement as HTMLElement | null
54
+ if (target && target.tagName === 'INPUT' && target.getAttribute('type') === 'submit') return
55
+ if (target && isTextOrInputField(target)) return
56
+ cbk()
57
+ }
58
+
59
+ // Constants
60
+
61
+ export const cmdSelectBody = 'select-body'
62
+ export let prefixKey = 'shift'
63
+
64
+ export const defaultKms = {
65
+ kmOpenSettings: {
66
+ id: 'general:open-settings',
67
+ keys: 'alt+s',
68
+ handler: editor => setButton(editor, 'project-bar-panel', 'settings-dialog-btn')
69
+ },
70
+ kmOpenPublish: {
71
+ id: 'general:open-publish',
72
+ keys: 'alt+p',
73
+ handler: editor => setButton(editor, 'options', 'publish-button')
74
+ },
75
+ kmOpenFonts: {
76
+ id: 'general:open-fonts',
77
+ keys: 'alt+f',
78
+ handler: editor => setButton(editor, 'project-bar-panel', 'font-dialog-btn')
79
+ },
80
+ kmPreviewMode: {
81
+ id: 'general:preview-mode',
82
+ keys: 'tab',
83
+ handler: editor => whenNoFocus(editor, () => setButton(editor, 'options', 'preview'))
84
+ },
85
+ kmLayers: {
86
+ id: 'panels:layers',
87
+ keys: prefixKey + '+l',
88
+ handler: editor => setButton(editor, 'project-bar-panel', 'layer-manager-btn')
89
+ },
90
+ kmBlocks: {
91
+ id: 'panels:blocks',
92
+ keys: prefixKey + '+a',
93
+ handler: editor => setButton(editor, 'project-bar-panel', 'block-manager-btn')
94
+ },
95
+ kmNotifications: {
96
+ id: 'panels:notifications',
97
+ keys: prefixKey + '+n',
98
+ handler: editor => setButton(editor, 'project-bar-panel', 'notifications-btn')
99
+ },
100
+ kmPages: {
101
+ id: 'panels:pages',
102
+ keys: prefixKey + '+p',
103
+ handler: editor => setButton(editor, 'project-bar-panel', 'page-panel-btn')
104
+ },
105
+ kmSymbols: {
106
+ id: 'panels:symbols',
107
+ keys: prefixKey + '+s',
108
+ handler: editor => setButton(editor, 'project-bar-panel', 'symbols-btn')
109
+ },
110
+ kmStyleManager: {
111
+ id: 'panels:style-manager',
112
+ keys: 'r',
113
+ handler: editor => setButton(editor, 'views', 'open-sm', true)
114
+ },
115
+ kmTraitsManager: {
116
+ id: 'panels:traits',
117
+ keys: 't',
118
+ handler: editor => setButton(editor, 'views', 'open-tm', true)
119
+ },
120
+ kmClosePanel: {
121
+ id: 'panels:close-panel',
122
+ keys: 'escape',
123
+ handler: escapeContext
124
+ },
125
+ kmSelectBody: {
126
+ id: 'workflow:select-body',
127
+ keys: prefixKey + '+b',
128
+ handler: cmdSelectBody
129
+ },
130
+ kmDuplicateSelection: {
131
+ id: 'workflow:duplicate-selection',
132
+ keys: 'ctrl+d',
133
+ handler: 'tlb-clone',
134
+ },
135
+ kmPublish: {
136
+ id: 'workflow:publish',
137
+ keys: 'ctrl+alt+p',
138
+ handler: publish
139
+ },
140
+ kmAddPage: {
141
+ id: 'pages:add-page',
142
+ keys: 'ctrl+alt+n',
143
+ handler: 'pages:add'
144
+ },
145
+ kmRemovePage: {
146
+ id: 'pages:remove-page',
147
+ keys: 'ctrl+alt+backspace',
148
+ handler: 'pages:remove'
149
+ },
150
+ kmClonePage: {
151
+ id: 'pages:clone-page',
152
+ keys: 'ctrl+alt+d',
153
+ handler: 'pages:clone'
154
+ },
155
+ kmSelectNextPage: {
156
+ id: 'pages:select-next',
157
+ keys: 'ctrl+alt+j',
158
+ handler: 'pages:select-next'
159
+ },
160
+ kmSelectPrevPage: {
161
+ id: 'pages:select-previous',
162
+ keys: 'ctrl+alt+k',
163
+ handler: 'pages:select-prev'
164
+ },
165
+ kmSelectFirstPage: {
166
+ id: 'pages:select-first',
167
+ keys: 'ctrl+alt+h',
168
+ handler: 'pages:select-first'
169
+ }
170
+ }
171
+
172
+ // Main part
173
+
174
+ export function keymapsPlugin(editor: Editor, opts: PluginOptions): void {
175
+ // Commands
176
+ editor.Commands.add(cmdSelectBody, selectBody)
177
+
178
+ if (opts.disableKeymaps) return
179
+ if (opts.prefixKey) prefixKey = opts.prefixKey
180
+
181
+ const km = editor.Keymaps
182
+
183
+ // Default keymaps
184
+ for (const keymap in defaultKms) {
185
+ km.add(defaultKms[keymap].id, defaultKms[keymap].keys, defaultKms[keymap].handler, {
186
+ prevent: true,
187
+ ...defaultKms[keymap].options
188
+ })
189
+ }
190
+
191
+ // Handling the Escape keymap during text edition
192
+ document.addEventListener('keydown', event => {
193
+ if (event.key.toLowerCase() === defaultKms.kmClosePanel.keys) {
194
+ const target = event.target as HTMLElement | null
195
+ if(editor.getEditing()) return // Close the rich text edition
196
+ if(editor.Modal.isOpen()) {
197
+ editor.Modal.close()
198
+ } else if (target) { // If target exists...
199
+ if (target.tagName === 'INPUT' && target.getAttribute('type') === 'submit') { // If it's a submit button...
200
+ escapeContext(editor)
201
+ } else if (isTextOrInputField(target)) { // If it's a text field...
202
+ target.blur()
203
+ }
204
+ }
205
+ }
206
+ })
207
+ }
@@ -15,7 +15,6 @@
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import * as grapesjs from 'grapesjs/dist/grapes.min.js'
19
18
  import {html, render} from 'lit-html'
20
19
  import {live} from 'lit-html/directives/live.js'
21
20
 
@@ -26,7 +25,7 @@ let modal
26
25
 
27
26
  export const cmdOpenNewPageDialog = 'new-page-dialog'
28
27
 
29
- export const newPageDialog = grapesjs.plugins.add(name, (editor, opts) => {
28
+ export const newPageDialog = (editor, opts) => {
30
29
  editor.Commands.add(cmdOpenNewPageDialog, {
31
30
  run: (_, sender, {page}) => {
32
31
  modal = editor.Modal.open({
@@ -53,7 +52,7 @@ export const newPageDialog = grapesjs.plugins.add(name, (editor, opts) => {
53
52
  // el.innerHTML = ''
54
53
  },
55
54
  })
56
- })
55
+ }
57
56
 
58
57
  function onImport(editor, page) {
59
58
  editor.Pages.select(page)
@@ -15,30 +15,61 @@
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import * as grapesjs from 'grapesjs/dist/grapes.min.js'
18
+ import { Editor } from 'grapesjs'
19
19
  import {html, render} from 'lit-html'
20
+ import {ref} from 'lit-html/directives/ref.js'
20
21
 
21
22
  const pluginName = 'page-panel'
22
23
  let open
23
24
 
24
25
  export const cmdTogglePages = 'pages:open-panel'
25
26
  export const cmdAddPage = 'pages:add'
27
+ export const cmdRemovePage = 'pages:remove'
28
+ export const cmdClonePage = 'pages:clone'
29
+ export const cmdSelectNextPage = 'pages:select-next'
30
+ export const cmdSelectPrevPage = 'pages:select-prev'
31
+ export const cmdSelectFirstPage = 'pages:select-first'
26
32
 
27
33
  function selectPage(editor, page) {
28
34
  editor.Pages.select(page)
29
35
  }
30
36
  function addPage(editor, config) {
31
37
  const pages = editor.Pages.getAll()
38
+ // Get a name
32
39
  let idx = 1
33
40
  const newPageName = config.newPageName || 'New page'
34
41
  let pageName = newPageName
35
42
  while(pages.find(p => p.getName() === pageName)) {
36
43
  pageName = `${newPageName} ${idx++}`
37
44
  }
45
+ // Add page
38
46
  const page = editor.Pages.add({ name: pageName })
47
+ // Select the new page
48
+ editor.Pages.select(page)
49
+ // Open page settings to edit the name
39
50
  editor.runCommand(config.cmdOpenNewPageDialog, {page})
40
51
  }
41
52
 
53
+ function clonePage(editor, page) {
54
+ const pages = editor.Pages.getAll()
55
+ // Get a name
56
+ let idx = 1
57
+ const newPageName = (page.getName() || 'main') + ' copy'
58
+ let pageName = newPageName
59
+ while(pages.find(p => p.getName() === pageName)) {
60
+ pageName = `${newPageName} ${idx++}`
61
+ }
62
+ // Clone components
63
+ const body = page.getMainComponent().clone()
64
+ // Add page
65
+ const newPage = editor.Pages.add({
66
+ name: pageName,
67
+ component: body,
68
+ })
69
+ // Select the new page
70
+ editor.Pages.select(newPage)
71
+ }
72
+
42
73
  function removePage(editor, page) {
43
74
  if(editor.Pages.getAll().length === 1) {
44
75
  console.error('can not delete the only page')
@@ -52,6 +83,54 @@ function removePage(editor, page) {
52
83
  }
53
84
  }
54
85
 
86
+ function removePageWithConfirm(editor, page) {
87
+ const content = document.createElement('div')
88
+ const modal = editor.Modal.open({
89
+ title: 'Are you sure?',
90
+ content,
91
+ })
92
+ render(html`
93
+ <p>Do you really want to remove this page?</p>
94
+ <footer>
95
+ <button
96
+ ${ref((el: HTMLButtonElement) => {
97
+ console.log('focus', el)
98
+ setTimeout(() => el.focus())
99
+ })}
100
+ @click=${() => {
101
+ removePage(editor, page)
102
+ modal.close()
103
+ }}
104
+ class="silex-button silex-button--primary">Delete page</button>
105
+ <button
106
+ @click=${() => modal.close()}
107
+ class="silex-button silex-button--secondary">Cancel</button
108
+ </footer>
109
+ `, content)
110
+ }
111
+
112
+ function selectNextPage(editor) {
113
+ const pages = editor.Pages.getAll()
114
+ const selected = editor.Pages.getSelected()
115
+ const idx = pages.indexOf(selected)
116
+ if(idx < pages.length - 1) {
117
+ selectPage(editor, pages[idx + 1])
118
+ } else {
119
+ selectPage(editor, pages[0])
120
+ }
121
+ }
122
+
123
+ function selectPrevPage(editor) {
124
+ const pages = editor.Pages.getAll()
125
+ const selected = editor.Pages.getSelected()
126
+ const idx = pages.indexOf(selected)
127
+ if(idx > 0) {
128
+ selectPage(editor, pages[idx - 1])
129
+ } else {
130
+ selectPage(editor, pages[pages.length - 1])
131
+ }
132
+ }
133
+
55
134
  function settingsPage(editor, config, page) {
56
135
  editor.runCommand(config.cmdOpenSettings, {page})
57
136
  }
@@ -76,6 +155,7 @@ function renderPages(editor, config) {
76
155
  ${ name }
77
156
  </div>
78
157
  <i class="pages__icon pages__remove-btn fa fa-trash" @click=${e => removePage(editor, getPageFromEvent(e))}></i>
158
+ <i class="pages__icon pages__clone-btn fa fa-clone" @click=${e => clonePage(editor, getPageFromEvent(e))}></i>
79
159
  <i class="pages__icon fa fa-cog" @click=${e => settingsPage(editor, config, getPageFromEvent(e))}></i>
80
160
  </div>
81
161
  </div>
@@ -89,7 +169,7 @@ function renderPages(editor, config) {
89
169
  </main></section>`
90
170
  }
91
171
 
92
- export const pagePanelPlugin = grapesjs.plugins.add(pluginName, (editor, opts) => {
172
+ export const pagePanelPlugin = (editor: Editor, opts) => {
93
173
  // create wrapper
94
174
  const el = document.createElement('div')
95
175
  el.classList.add('pages__wrapper')
@@ -100,9 +180,9 @@ export const pagePanelPlugin = grapesjs.plugins.add(pluginName, (editor, opts) =
100
180
  })
101
181
  editor.on('load', () => {
102
182
  open = false
103
- document.querySelector(opts.appendTo)
104
- .appendChild(el)
183
+ document.querySelector(opts.appendTo).appendChild(el)
105
184
  doRender()
185
+
106
186
  // click anywhere close it
107
187
  // const close = (event) => {
108
188
  // if(open) {
@@ -111,8 +191,13 @@ export const pagePanelPlugin = grapesjs.plugins.add(pluginName, (editor, opts) =
111
191
  // }
112
192
  // }
113
193
  // document.addEventListener('mousedown', close)
114
- // add command to add pages
194
+
195
+ // add useful commands
115
196
  editor.Commands.add(cmdAddPage, () => addPage(editor, opts))
197
+ editor.Commands.add(cmdRemovePage, () => removePageWithConfirm(editor, editor.Pages.getSelected()))
198
+ editor.Commands.add(cmdClonePage, () => clonePage(editor, editor.Pages.getSelected()))
199
+ editor.Commands.add(cmdSelectNextPage, () => selectNextPage(editor))
200
+ editor.Commands.add(cmdSelectPrevPage, () => selectPrevPage(editor))
201
+ editor.Commands.add(cmdSelectFirstPage, () => selectPage(editor, editor.Pages.getAll()[0]))
116
202
  })
117
- })
118
-
203
+ }
@@ -15,95 +15,139 @@
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
+ import { Editor, Panel } from 'grapesjs'
18
19
  import {html, render} from 'lit-html'
19
20
 
20
- const panelId = 'project-bar-panel'
21
- const containerPanelId = 'project-bar-container'
21
+ export const PROJECT_BAR_PANEL_ID = 'project-bar-panel'
22
+ export const containerPanelId = 'project-bar-container'
23
+
24
+ export interface PanelObject {
25
+ command: string | ((editor: Editor) => void)
26
+ text: string
27
+ className: string
28
+ name?: string
29
+ attributes: {
30
+ title?: string
31
+ containerClassName?: string
32
+ }
33
+ buttons?: {
34
+ command: string
35
+ text: string
36
+ className: string
37
+ }[]
38
+ onClick?: (editor: Editor) => void
39
+ }
22
40
 
23
41
  export const projectBarPlugin = (editor, opts) => {
24
42
  // create the panels container for all panels in grapesjs
25
43
  const containerPanel = editor.Panels.addPanel({
26
44
  id: containerPanelId,
27
- visible : false,
45
+ visible: false,
46
+ // resize project panel button
47
+ buttons: [{
48
+ id: 'resizeBlocks',
49
+ className: 'viewsOptionsProjectPanel__size-btn',
50
+ command: 'resize-ProjectPanel',
51
+ attributes: { title: 'Resize Project Panel' },
52
+ }],
53
+ })
54
+ // resize project panel command
55
+ editor.Commands.add('resize-ProjectPanel', {
56
+ run: (editor, sender) => {
57
+ document.documentElement.style.setProperty('--viewsProjectPanelWidth', '26%')
58
+ },
59
+ stop: (editor, sender) => {
60
+ document.documentElement.style.setProperty('--viewsProjectPanelWidth', '13%')
61
+ },
28
62
  })
29
63
  // create the project bar panel in grapesjs
30
- const projectBarPanel = editor.Panels.addPanel({
31
- id: panelId,
64
+ editor.Panels.addPanel({
65
+ id: PROJECT_BAR_PANEL_ID,
32
66
  buttons: opts.panels,
33
- visible : true,
67
+ visible: true,
34
68
  })
35
- const panelsEl = opts.panels.map(panel => {
36
- const el = document.createElement('div')
69
+ // add the panels to the container
70
+ opts.panels.map(panel => addButton(editor, panel))
37
71
 
38
- // create container for panel
39
- if(panel.attributes.containerClassName) {
40
- el.classList.add('project-bar__panel', panel.attributes.containerClassName, 'gjs-hidden')
72
+ // Handle the preview mode which behaves oddly
73
+ editor.on('stop:preview', () => {
74
+ containerPanel.set('visible', false)
75
+ updateSqueez(editor)
76
+ })
41
77
 
42
- // add header
43
- if(panel.attributes.title) {
44
- render(html`
45
- <header class="project-bar__panel-header">
46
- <h3 class="project-bar__panel-header-title">${ panel.attributes.title }</h3>
47
- ${ panel.buttons?.map(button => {
48
- return html`
49
- <div
50
- class="project-bar__panel-header-button ${ button.className }"
51
- @click=${e => editor.runCommand(button.command)}
52
- ><span>${ button.text }</span></div>
53
- `
54
- }) }
55
- </header>
56
- `, el)
57
- }
78
+ // All other events where the canvas is resized
79
+ editor.on('load device:select page', () => {
80
+ updateSqueez(editor)
81
+ })
82
+ }
58
83
 
59
- // temporarily attach it to the body
60
- // this lets the block manager and other plugins attach to their container
61
- document.body.appendChild(el)
84
+ function updateSqueez(editor: Editor) {
85
+ const containerPanel = editor.Panels.getPanel(containerPanelId)
86
+ // make sure the squeez corresponds to the state (reset when change page)
87
+ if(containerPanel.get('visible')) document.body.classList.add('silex-squeeze-left')
88
+ else document.body.classList.remove('silex-squeeze-left')
89
+ editor.refresh()
90
+ }
62
91
 
63
- // on load attach the panels to the main container
64
- // this is when the main containerPanel has an element
65
- editor.on('load', () => {
66
- const containerPanelEl = containerPanel.view.el
67
- containerPanelEl.appendChild(el)
68
- })
92
+ export function addButton(editor: Editor, panel: PanelObject) {
93
+ const containerPanel = editor.Panels.getPanel(containerPanelId)
94
+ const el = document.createElement('div')
95
+ // create container for panel
96
+ if(panel.attributes.containerClassName) {
97
+ el.classList.add('project-bar__panel', panel.attributes.containerClassName, 'gjs-hidden')
98
+ // add header
99
+ const title = panel.name ?? panel.attributes.title
100
+ if(title) {
101
+ render(html`
102
+ <header class="project-bar__panel-header">
103
+ <h3 class="project-bar__panel-header-title">${ title }</h3>
104
+ ${ panel.buttons?.map(button => {
105
+ return html`
106
+ <div
107
+ class="project-bar__panel-header-button ${ button.className }"
108
+ @click=${e => editor.runCommand(button.command)}
109
+ ><span>${ button.text }</span></div>
110
+ `
111
+ }) }
112
+ </header>
113
+ `, el)
69
114
  }
70
-
71
- // commands for show / hide panels
72
- editor.Commands.add(panel.command, {
73
- run() {
74
- if(panel.link) {
75
- window.open(panel.link)
76
- }
77
- if(panel.attributes.containerClassName) {
78
- containerPanel.set('visible', true)
79
- el.classList.remove('gjs-hidden')
80
- editor.Canvas.getFrameEl().classList.add('silex-squeeze-left')
81
- }
82
- },
83
- stop() {
84
- if(panel.attributes.containerClassName) {
85
- containerPanel.set('visible', false)
86
- el.classList.add('gjs-hidden')
87
- editor.Canvas.getFrameEl().classList.remove('silex-squeeze-left')
88
- }
89
- },
115
+ // temporarily attach it to the body
116
+ // this lets the block manager and other plugins attach to their container
117
+ document.body.appendChild(el)
118
+ // on load attach the panels to the main container
119
+ // this is when the main containerPanel has an element
120
+ editor.on('load', () => {
121
+ const containerPanelEl = containerPanel.view.el
122
+ containerPanelEl.appendChild(el)
90
123
  })
91
- })
92
- function updateSqueez() {
93
- const containerPanelEl = containerPanel.view.el
94
- const iframe = editor.Canvas.getFrameEl()
95
- iframe.classList.remove('enable-squeeze')
96
- setTimeout(() => {
97
- const left = iframe.getClientRects()[0]?.left
98
- const right = containerPanelEl.getClientRects()[0]?.right
99
- if(left < right || !right) iframe.classList.add('enable-squeeze')
100
- else iframe.classList.remove('enable-squeeze')
101
- }, 400) // More than the transition duration
102
- // make sure the squeez corresponds to the state (reset when change page)
103
- if(containerPanel.get('visible')) iframe.classList.add('silex-squeeze-left')
104
- else iframe.classList.remove('silex-squeeze-left')
105
124
  }
106
- editor.on('load device:select page', () => {
107
- updateSqueez()
125
+ // commands for show / hide panels
126
+ // handle the case where command is a normal command, then let the Panel handle it
127
+ typeof panel.command === 'string' && editor.Commands.add(panel.command, {
128
+ run() {
129
+ if(panel.attributes.containerClassName) {
130
+ containerPanel.set('visible', true)
131
+ el.classList.remove('gjs-hidden')
132
+ document.body.classList.add('silex-squeeze-left')
133
+ editor.refresh()
134
+ }
135
+ // Call the onClick function if it exists
136
+ if(panel.onClick) panel.onClick(editor)
137
+ // Remove the dirty flag
138
+ el.classList.remove('project-bar__dirty')
139
+ },
140
+ stop() {
141
+ if(panel.attributes.containerClassName) {
142
+ containerPanel.set('visible', false)
143
+ el.classList.add('gjs-hidden')
144
+ document.body.classList.remove('silex-squeeze-left')
145
+ editor.refresh()
146
+ }
147
+ // Call the onClick function if it exists
148
+ if(panel.onClick) panel.onClick(editor)
149
+ // Remove the dirty flag
150
+ el.classList.remove('project-bar__dirty')
151
+ },
108
152
  })
109
153
  }
@@ -0,0 +1,20 @@
1
+ export default function(editor) {
2
+ editor.Panels.addPanel({
3
+ id: 'viewsOptions',
4
+ buttons: [{
5
+ id: 'resize',
6
+ // icon for arrow left
7
+ className: 'viewsOptions__size-btn',
8
+ command: 'resize-panel',
9
+ attributes: { title: 'Resize panel' },
10
+ }],
11
+ })
12
+ editor.Commands.add('resize-panel', {
13
+ run: (editor, sender) => {
14
+ document.documentElement.style.setProperty('--viewsPanelWidth', '40%')
15
+ },
16
+ stop: (editor, sender) => {
17
+ document.documentElement.style.setProperty('--viewsPanelWidth', '20%')
18
+ },
19
+ })
20
+ }
@@ -15,19 +15,27 @@
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import * as grapesjs from 'grapesjs/dist/grapes.min.js'
18
+ import { RichTextEditorAction } from 'grapesjs'
19
19
 
20
20
  const pluginName = 'richText'
21
21
 
22
- export const richTextPlugin = grapesjs.plugins.add(pluginName, (editor, opts) => {
23
- editor.RichTextEditor.add('orderedList', {
24
- icon: '1.',
25
- attributes: {title: 'Ordered List'},
26
- result: rte => rte.exec('insertOrderedList'),
27
- })
28
- editor.RichTextEditor.add('unorderedList', {
29
- icon: '<i class="fa fa-list-ul"></i>',
30
- attributes: {title: 'Unordered List'},
31
- result: rte => rte.exec('insertUnorderedList'),
32
- })
33
- })
22
+ export const orderedList: RichTextEditorAction = {
23
+ name: 'orderedList',
24
+ icon: '1.',
25
+ attributes: { title: 'Ordered List' },
26
+ result: rte => rte.exec('insertOrderedList'),
27
+ }
28
+
29
+ export const unorderedList: RichTextEditorAction = {
30
+ name: 'unorderedList',
31
+ icon: '•',
32
+ //icon: '<i class="fa fa-list-ul"></i>',
33
+ attributes: { title: 'Unordered List' },
34
+ result: rte => rte.exec('insertUnorderedList'),
35
+ }
36
+
37
+ export const richTextPlugin = (editor, opts) => {
38
+ // This doesn't work, it is now added in the editor config
39
+ //editor.RichTextEditor.add('orderedList', orderedList)
40
+ //editor.RichTextEditor.add('unorderedList', unorderedList)
41
+ }