@silexlabs/silex 3.0.0-alpha.97 → 3.0.0

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 (206) hide show
  1. package/.env.default +2 -1
  2. package/README.md +31 -9
  3. package/dist/client/client/api.d.ts +5 -0
  4. package/dist/client/client/assetUrl.d.ts +3 -0
  5. package/dist/client/client/config.d.ts +31 -0
  6. package/dist/client/client/events.d.ts +7 -1
  7. package/dist/client/client/grapesjs/PublicationManager.d.ts +2 -1
  8. package/dist/client/client/grapesjs/css-props.d.ts +6 -0
  9. package/dist/client/client/grapesjs/img.d.ts +6 -0
  10. package/dist/client/client/grapesjs/index.d.ts +2 -2
  11. package/dist/client/client/grapesjs/new-page-dialog.d.ts +1 -1
  12. package/dist/client/client/grapesjs/page-panel.d.ts +1 -1
  13. package/dist/client/client/grapesjs/project-bar.d.ts +16 -0
  14. package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
  15. package/dist/client/client/grapesjs/rich-text.d.ts +4 -1
  16. package/dist/client/client/grapesjs/semantic.d.ts +1 -1
  17. package/dist/client/client/grapesjs/settings-sections.d.ts +15 -0
  18. package/dist/client/client/grapesjs/settings.d.ts +3 -1
  19. package/dist/client/client/grapesjs/symbolDialogs.d.ts +1 -1
  20. package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
  21. package/dist/client/client/index.d.ts +10 -0
  22. package/dist/client/client/publication-transformers.d.ts +4 -3
  23. package/dist/client/client/publish-custom-code-block.d.ts +4 -0
  24. package/dist/client/client/publish-fonts.d.ts +4 -0
  25. package/dist/client/client/utils.d.ts +4 -0
  26. package/dist/client/constants.d.ts +1 -0
  27. package/dist/client/css/admin.css +273 -32
  28. package/dist/client/index.html +2 -1
  29. package/dist/client/js/main.js +164 -123
  30. package/dist/client/js/main.js.LICENSE.txt +15 -1
  31. package/dist/client/types.d.ts +12 -7
  32. package/dist/plugins/client/client/events.d.ts +7 -1
  33. package/dist/plugins/client/client/events.js +7 -1
  34. package/dist/plugins/client/client/events.js.map +1 -1
  35. package/dist/plugins/client/plugins/client/template.js +108 -58
  36. package/dist/plugins/client/plugins/client/template.js.map +1 -1
  37. package/dist/plugins/client/types.d.ts +12 -7
  38. package/dist/plugins/client/types.js +6 -0
  39. package/dist/plugins/client/types.js.map +1 -1
  40. package/dist/plugins/server/constants.d.ts +1 -0
  41. package/dist/plugins/server/constants.js +2 -1
  42. package/dist/plugins/server/constants.js.map +1 -1
  43. package/dist/plugins/server/plugins/server/FtpConnector.d.ts +1 -0
  44. package/dist/plugins/server/plugins/server/FtpConnector.js +12 -1
  45. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
  46. package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +3 -0
  47. package/dist/plugins/server/plugins/server/GitlabConnector.js +72 -35
  48. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
  49. package/dist/plugins/server/server/config.js +3 -3
  50. package/dist/plugins/server/server/config.js.map +1 -1
  51. package/dist/plugins/server/server/connectors/FsHosting.d.ts +1 -0
  52. package/dist/plugins/server/server/connectors/FsHosting.js +13 -1
  53. package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -1
  54. package/dist/plugins/server/server/connectors/FsStorage.d.ts +2 -1
  55. package/dist/plugins/server/server/connectors/FsStorage.js +29 -25
  56. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
  57. package/dist/plugins/server/server/connectors/connectors.d.ts +1 -0
  58. package/dist/plugins/server/server/jobs.js +4 -2
  59. package/dist/plugins/server/server/jobs.js.map +1 -1
  60. package/dist/plugins/server/types.d.ts +12 -7
  61. package/dist/plugins/server/types.js +7 -1
  62. package/dist/plugins/server/types.js.map +1 -1
  63. package/dist/server/constants.js +2 -1
  64. package/dist/server/server/api/publicationApi.js +3 -5
  65. package/dist/server/server/api/websiteApi.js +22 -3
  66. package/dist/server/server/cli.js +9 -6
  67. package/dist/server/server/config.js +3 -3
  68. package/dist/server/server/connectors/FsHosting.js +13 -1
  69. package/dist/server/server/connectors/FsStorage.js +28 -25
  70. package/dist/server/server/jobs.js +4 -2
  71. package/dist/server/types.js +7 -1
  72. package/package.json +34 -30
  73. package/public/assets/favicon.ico +0 -0
  74. package/public/assets/favicon.png +0 -0
  75. package/public/assets/logo-silex-small.png +0 -0
  76. package/src/css/_variables.scss +5 -3
  77. package/src/css/dialog.scss +22 -1
  78. package/src/css/fonts.scss +31 -0
  79. package/src/css/footer.scss +1 -1
  80. package/src/css/grapesjs-plugins.scss +34 -0
  81. package/src/css/grapesjs.scss +26 -11
  82. package/src/css/index.scss +1 -0
  83. package/src/css/project-bar.scss +11 -7
  84. package/src/css/silex.scss +58 -5
  85. package/src/html/index.pug +2 -2
  86. package/src/ts/client/api.ts +14 -9
  87. package/src/ts/client/assetUrl.test.ts +39 -0
  88. package/src/ts/client/assetUrl.ts +24 -5
  89. package/src/ts/client/config.ts +85 -4
  90. package/src/ts/client/events.ts +15 -9
  91. package/src/ts/client/grapesjs/PublicationManager.ts +71 -38
  92. package/src/ts/client/grapesjs/PublicationUi.ts +13 -11
  93. package/src/ts/client/grapesjs/css-props.ts +544 -0
  94. package/src/ts/client/grapesjs/eleventy.ts +2 -5
  95. package/src/ts/client/grapesjs/footer.ts +24 -9
  96. package/src/ts/client/grapesjs/img.ts +147 -0
  97. package/src/ts/client/grapesjs/index.ts +63 -25
  98. package/src/ts/client/grapesjs/internal-links.test.ts +2 -1
  99. package/src/ts/client/grapesjs/internal-links.ts +0 -1
  100. package/src/ts/client/grapesjs/new-page-dialog.ts +2 -3
  101. package/src/ts/client/grapesjs/page-panel.ts +28 -3
  102. package/src/ts/client/grapesjs/project-bar.ts +83 -64
  103. package/src/ts/client/grapesjs/resize-panel.ts +20 -0
  104. package/src/ts/client/grapesjs/rich-text.ts +21 -13
  105. package/src/ts/client/grapesjs/semantic.ts +3 -3
  106. package/src/ts/client/grapesjs/settings-sections.ts +117 -0
  107. package/src/ts/client/grapesjs/settings.ts +120 -77
  108. package/src/ts/client/grapesjs/symbolDialogs.ts +2 -3
  109. package/src/ts/client/grapesjs/view-buttons.ts +42 -0
  110. package/src/ts/client/index.ts +13 -6
  111. package/src/ts/client/publication-transformers.test.ts +13 -5
  112. package/src/ts/client/publication-transformers.ts +60 -47
  113. package/{dist/plugins/client/client/utils.js → src/ts/client/publish-custom-code-block.ts} +14 -8
  114. package/{dist/plugins/client/page.js → src/ts/client/publish-fonts.ts} +19 -14
  115. package/src/ts/client/utils.ts +18 -0
  116. package/src/ts/constants.ts +1 -0
  117. package/src/ts/plugins/client/template.ts +112 -60
  118. package/src/ts/plugins/server/FtpConnector.ts +14 -2
  119. package/src/ts/plugins/server/GitlabConnector.ts +71 -32
  120. package/src/ts/server/api/publicationApi.ts +5 -5
  121. package/src/ts/server/api/websiteApi.ts +39 -9
  122. package/src/ts/server/cli.ts +7 -5
  123. package/src/ts/server/config.ts +4 -4
  124. package/src/ts/server/connectors/FsHosting.ts +11 -5
  125. package/src/ts/server/connectors/FsStorage.ts +33 -4
  126. package/src/ts/server/connectors/connectors.ts +1 -1
  127. package/src/ts/server/jobs.ts +4 -2
  128. package/src/ts/types.ts +10 -7
  129. package/dist/plugins/client/client/api.d.ts +0 -85
  130. package/dist/plugins/client/client/api.js +0 -114
  131. package/dist/plugins/client/client/api.js.map +0 -1
  132. package/dist/plugins/client/client/assetUrl.d.ts +0 -51
  133. package/dist/plugins/client/client/assetUrl.js +0 -224
  134. package/dist/plugins/client/client/assetUrl.js.map +0 -1
  135. package/dist/plugins/client/client/config.d.ts +0 -58
  136. package/dist/plugins/client/client/config.js +0 -90
  137. package/dist/plugins/client/client/config.js.map +0 -1
  138. package/dist/plugins/client/client/grapesjs/LoginDialog.d.ts +0 -15
  139. package/dist/plugins/client/client/grapesjs/LoginDialog.js +0 -195
  140. package/dist/plugins/client/client/grapesjs/LoginDialog.js.map +0 -1
  141. package/dist/plugins/client/client/grapesjs/PublicationManager.d.ts +0 -72
  142. package/dist/plugins/client/client/grapesjs/PublicationManager.js +0 -356
  143. package/dist/plugins/client/client/grapesjs/PublicationManager.js.map +0 -1
  144. package/dist/plugins/client/client/grapesjs/PublicationUi.d.ts +0 -62
  145. package/dist/plugins/client/client/grapesjs/PublicationUi.js +0 -336
  146. package/dist/plugins/client/client/grapesjs/PublicationUi.js.map +0 -1
  147. package/dist/plugins/client/client/grapesjs/blocks.d.ts +0 -1
  148. package/dist/plugins/client/client/grapesjs/blocks.js +0 -37
  149. package/dist/plugins/client/client/grapesjs/blocks.js.map +0 -1
  150. package/dist/plugins/client/client/grapesjs/breadcrumbs.d.ts +0 -1
  151. package/dist/plugins/client/client/grapesjs/breadcrumbs.js +0 -75
  152. package/dist/plugins/client/client/grapesjs/breadcrumbs.js.map +0 -1
  153. package/dist/plugins/client/client/grapesjs/footer.d.ts +0 -2
  154. package/dist/plugins/client/client/grapesjs/footer.js +0 -28
  155. package/dist/plugins/client/client/grapesjs/footer.js.map +0 -1
  156. package/dist/plugins/client/client/grapesjs/index.d.ts +0 -5
  157. package/dist/plugins/client/client/grapesjs/index.js +0 -313
  158. package/dist/plugins/client/client/grapesjs/index.js.map +0 -1
  159. package/dist/plugins/client/client/grapesjs/internal-links.d.ts +0 -1
  160. package/dist/plugins/client/client/grapesjs/internal-links.js +0 -219
  161. package/dist/plugins/client/client/grapesjs/internal-links.js.map +0 -1
  162. package/dist/plugins/client/client/grapesjs/new-page-dialog.d.ts +0 -2
  163. package/dist/plugins/client/client/grapesjs/new-page-dialog.js +0 -83
  164. package/dist/plugins/client/client/grapesjs/new-page-dialog.js.map +0 -1
  165. package/dist/plugins/client/client/grapesjs/openImport.d.ts +0 -9
  166. package/dist/plugins/client/client/grapesjs/openImport.js +0 -74
  167. package/dist/plugins/client/client/grapesjs/openImport.js.map +0 -1
  168. package/dist/plugins/client/client/grapesjs/page-panel.d.ts +0 -3
  169. package/dist/plugins/client/client/grapesjs/page-panel.js +0 -113
  170. package/dist/plugins/client/client/grapesjs/page-panel.js.map +0 -1
  171. package/dist/plugins/client/client/grapesjs/project-bar.d.ts +0 -1
  172. package/dist/plugins/client/client/grapesjs/project-bar.js +0 -104
  173. package/dist/plugins/client/client/grapesjs/project-bar.js.map +0 -1
  174. package/dist/plugins/client/client/grapesjs/rich-text.d.ts +0 -1
  175. package/dist/plugins/client/client/grapesjs/rich-text.js +0 -31
  176. package/dist/plugins/client/client/grapesjs/rich-text.js.map +0 -1
  177. package/dist/plugins/client/client/grapesjs/semantic.d.ts +0 -1
  178. package/dist/plugins/client/client/grapesjs/semantic.js +0 -110
  179. package/dist/plugins/client/client/grapesjs/semantic.js.map +0 -1
  180. package/dist/plugins/client/client/grapesjs/settings.d.ts +0 -2
  181. package/dist/plugins/client/client/grapesjs/settings.js +0 -198
  182. package/dist/plugins/client/client/grapesjs/settings.js.map +0 -1
  183. package/dist/plugins/client/client/grapesjs/storage.d.ts +0 -1
  184. package/dist/plugins/client/client/grapesjs/storage.js +0 -126
  185. package/dist/plugins/client/client/grapesjs/storage.js.map +0 -1
  186. package/dist/plugins/client/client/grapesjs/symbolDialogs.d.ts +0 -3
  187. package/dist/plugins/client/client/grapesjs/symbolDialogs.js +0 -36
  188. package/dist/plugins/client/client/grapesjs/symbolDialogs.js.map +0 -1
  189. package/dist/plugins/client/client/publication-transformers.d.ts +0 -41
  190. package/dist/plugins/client/client/publication-transformers.js +0 -238
  191. package/dist/plugins/client/client/publication-transformers.js.map +0 -1
  192. package/dist/plugins/client/client/utils.d.ts +0 -2
  193. package/dist/plugins/client/client/utils.js.map +0 -1
  194. package/dist/plugins/client/constants.d.ts +0 -29
  195. package/dist/plugins/client/constants.js +0 -46
  196. package/dist/plugins/client/constants.js.map +0 -1
  197. package/dist/plugins/client/page.d.ts +0 -2
  198. package/dist/plugins/client/page.js.map +0 -1
  199. package/dist/plugins/client/plugins/client/11ty.d.ts +0 -17
  200. package/dist/plugins/client/plugins/client/11ty.js +0 -86
  201. package/dist/plugins/client/plugins/client/11ty.js.map +0 -1
  202. package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +0 -2
  203. package/dist/plugins/client/plugins/client/publicationRenderer.js +0 -170
  204. package/dist/plugins/client/plugins/client/publicationRenderer.js.map +0 -1
  205. package/src/ts/plugins/client/11ty.ts +0 -104
  206. package/src/ts/plugins/client/publicationRenderer.ts +0 -174
@@ -0,0 +1,147 @@
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 { Editor } from 'grapesjs'
19
+
20
+ /**
21
+ * @fileoverview This plugin adds CSS properties object-fit and object-position to the image component.
22
+ */
23
+
24
+ export default (editor: Editor, opts) => {
25
+ opts = {
26
+ // Default options
27
+ labelSrc: 'Image URL',
28
+ placeholderSrc: 'https://example.com/image.jpg',
29
+ // These default values will never be used,
30
+ // as there is default values in config
31
+ replacedElements: ['img'],
32
+ // Override with provided config
33
+ ...opts,
34
+ }
35
+ // Add src trait in the properties
36
+ editor.TraitManager.addType('src', {
37
+ events: {
38
+ 'change': 'onChange',
39
+ },
40
+ templateInput() {
41
+ return `
42
+ <div class="gjs-field gjs-field-trad">
43
+ <label class="gjs-label">${opts.labelSrc}</label>
44
+ <input type="text" class="gjs-field" placeholder="${opts.placeholderSrc}" />
45
+ </div>
46
+ `
47
+ },
48
+ getInputEl() {
49
+ if (!this.inputEl) {
50
+ this.inputEl = this.templateInput()
51
+ }
52
+ return this.inputEl
53
+ },
54
+ onValueChange() {
55
+ this.setValue(this.getInputEl().value)
56
+ },
57
+ setValue(value) {
58
+ this.getInputEl().value = value
59
+ },
60
+ getValue() {
61
+ return this.getInputEl().value
62
+ },
63
+ })
64
+
65
+ // Add the trait to the image component
66
+ editor.DomComponents.addType('image', {
67
+ model: {
68
+ defaults: {
69
+ ...editor.DomComponents.getType('image').model.prototype.defaults,
70
+ traits: [
71
+ ...editor.DomComponents.getType('image').model.prototype.defaults.traits
72
+ // Remove href and tagName trait becase images have to keep the img tag, not become links
73
+ // Remove tag-name trait which is added by the semantic plugin
74
+ // Also remove src trait in case it exists already
75
+ .filter((trait) => !['href', 'tag-name', 'src'].includes(trait.name)),
76
+ 'src',
77
+ ],
78
+ },
79
+ },
80
+ })
81
+
82
+ // Wait for the editor to be ready
83
+ editor.on('load', () => {
84
+ // Add a sector to the style manager
85
+ const sector = editor.StyleManager.addSector('object', {
86
+ name: 'Object',
87
+ open: false,
88
+ properties: [{
89
+ label: 'object-fit',
90
+ property: 'object-fit',
91
+ type: 'select',
92
+ default: '',
93
+ /* @ts-ignore */
94
+ options: [
95
+ { id: '', label: '' },
96
+ { id: 'fill', label: 'fill' },
97
+ { id: 'contain', label: 'contain' },
98
+ { id: 'cover', label: 'cover' },
99
+ { id: 'none', label: 'none' },
100
+ { id: 'scale-down', label: 'scale-down' },
101
+ { id: 'initial', label: 'initial' },
102
+ { id: 'inherit', label: 'inherit' },
103
+ { id: 'auto', label: 'auto' },
104
+ ],
105
+ }, {
106
+ label: 'object-position',
107
+ property: 'object-position',
108
+ type: 'select',
109
+ default: '',
110
+ /* @ts-ignore */
111
+ options: [
112
+ { id: '', label: '' },
113
+ { id: 'left top', label: 'left top' },
114
+ { id: 'left center', label: 'left center' },
115
+ { id: 'left bottom', label: 'left bottom' },
116
+ { id: 'right top', label: 'right top' },
117
+ { id: 'right center', label: 'right center' },
118
+ { id: 'right bottom', label: 'right bottom' },
119
+ { id: 'center top', label: 'center top' },
120
+ { id: 'center center', label: 'center center' },
121
+ { id: 'center bottom', label: 'center bottom' },
122
+ { id: 'initial', label: 'initial' },
123
+ { id: 'inherit', label: 'inherit' },
124
+ { id: 'unset', label: 'unset' },
125
+ ],
126
+ }],
127
+ }, {
128
+ at: 1,
129
+ })
130
+ let showSector = false
131
+ // It shows up when the selection is an image
132
+ editor.on('component:selected', (model) => {
133
+ if (model && opts.replacedElements.includes(model.get('tagName')?.toLowerCase())) {
134
+ // Not necessary, grapesjs does it automatically
135
+ // sector.set('visible', true);
136
+ showSector = true
137
+ } else {
138
+ showSector = false
139
+ sector.set('visible', false)
140
+ }
141
+ })
142
+ // Watch automatic changes and revert them if needed
143
+ sector.on('change:visible', (model, open) => {
144
+ if(sector.get('visible') !== showSector) sector.set('visible', showSector)
145
+ })
146
+ })
147
+ }
@@ -31,6 +31,7 @@ import styleFilterPlugin from 'grapesjs-style-filter'
31
31
  import formPlugin from 'grapesjs-plugin-forms'
32
32
  import codePlugin from 'grapesjs-custom-code'
33
33
  import uiSuggestClasses from '@silexlabs/grapesjs-ui-suggest-classes'
34
+ import filterStyles from '@silexlabs/grapesjs-filter-styles'
34
35
  import symbolsPlugin from '@silexlabs/grapesjs-symbols'
35
36
  import loadingPlugin from '@silexlabs/grapesjs-loading'
36
37
  import fontsDialogPlugin, { cmdOpenFonts } from '@silexlabs/grapesjs-fonts'
@@ -38,7 +39,12 @@ import symbolDialogsPlugin, { cmdPromptAddSymbol } from './symbolDialogs'
38
39
  import loginDialogPlugin, { LoginDialogOptions, cmdLogout } from './LoginDialog'
39
40
  import footerPlugin from './footer'
40
41
  import breadcrumbsPlugin from './breadcrumbs'
42
+ import imgPlugin from './img'
43
+ import cssPropsPlugin from './css-props'
41
44
  import rateLimitPlugin from '@silexlabs/grapesjs-storage-rate-limit'
45
+ import borderPugin from 'grapesjs-style-border'
46
+ import backgroundPlugin from 'grapesjs-style-bg'
47
+ import resizePanelPlugin from './resize-panel'
42
48
 
43
49
  import { pagePanelPlugin, cmdTogglePages, cmdAddPage } from './page-panel'
44
50
  import { newPageDialog, cmdOpenNewPageDialog } from './new-page-dialog'
@@ -46,21 +52,24 @@ import { projectBarPlugin } from './project-bar'
46
52
  import { settingsDialog, cmdOpenSettings } from './settings'
47
53
  import { blocksPlugin } from './blocks'
48
54
  import { semanticPlugin } from './semantic'
49
- import { richTextPlugin } from './rich-text'
55
+ import { orderedList, richTextPlugin, unorderedList } from './rich-text'
50
56
  import { internalLinksPlugin } from './internal-links'
51
57
  import publicationManagerPlugin, { PublicationManagerOptions } from './PublicationManager'
58
+ import ViewButtons from './view-buttons'
52
59
  import { storagePlugin } from './storage'
53
- import { ConnectorId, WebsiteId } from '../../types'
54
60
  import { API_PATH, API_WEBSITE_ASSETS_WRITE, API_WEBSITE_PATH } from '../../constants'
61
+ import { ClientConfig } from '../config'
55
62
 
56
63
  const plugins = [
57
64
  {name: './project-bar', value: projectBarPlugin}, // has to be before panels and dialogs
65
+ {name: 'grapesjs-style-bg', value: backgroundPlugin},
58
66
  {name: './settings', value: settingsDialog},
59
67
  {name: '@silexlabs/grapesjs-fonts', value: fontsDialogPlugin},
60
68
  {name: './new-page-dialog', value: newPageDialog},
61
69
  {name: './page-panel', value: pagePanelPlugin},
62
70
  {name: 'grapesjs-blocks-basic', value: blocksBasicPlugin},
63
71
  {name: './blocks', value: blocksPlugin},
72
+ {name: './view-buttons', value: ViewButtons},
64
73
  {name: './semantic', value: semanticPlugin},
65
74
  {name: './rich-text', value: richTextPlugin},
66
75
  {name: 'grapesjs-style-filter', value: styleFilterPlugin},
@@ -68,6 +77,7 @@ const plugins = [
68
77
  {name: 'grapesjs-custom-code', value: codePlugin},
69
78
  {name: './internal-links', value: internalLinksPlugin},
70
79
  {name: '@silexlabs/grapesjs-ui-suggest-classes', value: uiSuggestClasses},
80
+ {name: '@silexlabs/grapesjs-filter-styles', value: filterStyles},
71
81
  {name: './symbolDialogs', value: symbolDialogsPlugin},
72
82
  {name: '@silexlabs/grapesjs-symbols', value: symbolsPlugin},
73
83
  {name: './PublicationManager', value: publicationManagerPlugin},
@@ -75,8 +85,12 @@ const plugins = [
75
85
  {name: './LoginDialog', value: loginDialogPlugin},
76
86
  {name: '@silexlabs/grapesjs-loading', value: loadingPlugin},
77
87
  {name: './breadcrumbs', value: breadcrumbsPlugin},
88
+ {name: './img', value: imgPlugin},
89
+ {name: './css-props', value: cssPropsPlugin},
78
90
  {name: './footer', value: footerPlugin},
79
91
  {name: '@silexlabs/grapesjs-storage-rate-limit', value: rateLimitPlugin},
92
+ {name: 'grapesjs-style-border', value: borderPugin},
93
+ {name: './resize-panel', value: resizePanelPlugin}
80
94
  ]
81
95
  // Check that all plugins are loaded correctly
82
96
  plugins
@@ -99,7 +113,8 @@ const LIGHTER_PRIMARY_COLOR = '#575757'
99
113
  const catBasic = 'Containers'
100
114
  const catComponents = 'Components'
101
115
 
102
- export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl: string): EditorConfig {
116
+ export function getEditorConfig(config: ClientConfig): EditorConfig {
117
+ const { websiteId, storageId, rootUrl } = config
103
118
  return {
104
119
  container: '#gjs',
105
120
  height: '100%',
@@ -117,7 +132,7 @@ export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl
117
132
  },
118
133
 
119
134
  assetManager: {
120
- upload: `${rootUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSETS_WRITE}/?websiteId=${id}${ connectorId ? `&connectorId=${connectorId}` : ''}`,
135
+ upload: `${rootUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSETS_WRITE}/?websiteId=${websiteId}${ storageId ? `&connectorId=${storageId}` : ''}`,
121
136
  },
122
137
 
123
138
  storageManager: {
@@ -125,8 +140,8 @@ export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl
125
140
  type: 'connector',
126
141
  options: {
127
142
  connector: {
128
- id,
129
- connectorId,
143
+ id: websiteId,
144
+ connectorId: storageId,
130
145
  },
131
146
  },
132
147
  },
@@ -150,15 +165,21 @@ export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl
150
165
  }
151
166
  `,
152
167
 
168
+ richTextEditor: {
169
+ // @ts-ignore
170
+ actions: ['bold', 'italic', 'underline', 'strikethrough', 'link', 'wrap', orderedList, unorderedList],
171
+ },
172
+
173
+
153
174
  plugins: plugins.map(p => p.value),
154
175
 
155
176
  pluginsOpts: {
156
- [blocksBasicPlugin as any]: {
177
+ [blocksBasicPlugin.toString()]: {
157
178
  blocks: ['text', 'image', 'video', 'map'],
158
179
  category: catBasic,
159
180
  //flexGrid: true,
160
181
  },
161
- [projectBarPlugin as any]: {
182
+ [projectBarPlugin.toString()]: {
162
183
  panels: [
163
184
  {
164
185
  id: 'dash',
@@ -238,45 +259,54 @@ export function getEditorConfig(id: WebsiteId, connectorId: ConnectorId, rootUrl
238
259
  },
239
260
  ],
240
261
  },
241
- [publicationManagerPlugin as any]: {
262
+ [publicationManagerPlugin.toString()]: {
242
263
  appendTo: 'options',
243
- websiteId: id,
264
+ websiteId,
244
265
  } as PublicationManagerOptions,
245
- [pagePanelPlugin as any]: {
266
+ [pagePanelPlugin.toString()]: {
246
267
  cmdOpenNewPageDialog,
247
268
  cmdOpenSettings,
248
269
  appendTo: '.page-panel-container',
249
270
  },
250
- [uiSuggestClasses as any]: {
271
+ [uiSuggestClasses.toString()]: {
251
272
  enableCount: false,
252
273
  enablePerformance: false,
253
274
  },
254
- [internalLinksPlugin as any]: {
275
+ [filterStyles]: {
276
+ appendBefore: '.gjs-sm-sectors',
277
+ },
278
+ [internalLinksPlugin.toString()]: {
255
279
  // FIXME: warn the user about links in error
256
280
  onError: (errors) => console.warn('Links errors:', errors),
257
281
  },
258
- [codePlugin as any]: {
282
+ [codePlugin.toString()]: {
259
283
  blockLabel: 'HTML',
260
284
  blockCustomCode: {
261
285
  category: catComponents,
262
- }
286
+ },
287
+ codeViewOptions: {
288
+ autoFormat: false,
289
+ },
263
290
  },
264
- [symbolsPlugin as any]: {
291
+ [symbolsPlugin.toString()]: {
265
292
  appendTo: '.symbols-list-container',
266
293
  emptyText: 'No symbol yet.',
267
294
  primaryColor: PRIMARY_COLOR,
268
295
  secondaryColor: SECONDARY_COLOR,
269
296
  highlightColor: TERTIARY_COLOR,
270
297
  },
271
- [fontsDialogPlugin as any]: {
298
+ [fontsDialogPlugin.toString()]: {
272
299
  api_key: 'AIzaSyAdJTYSLPlKz4w5Iqyy-JAF2o8uQKd1FKc',
273
300
  },
274
- [loginDialogPlugin as any]: {
275
- id,
301
+ [loginDialogPlugin.toString()]: {
302
+ id: websiteId,
276
303
  } as LoginDialogOptions,
277
- [rateLimitPlugin as any]: {
304
+ [rateLimitPlugin.toString()]: {
278
305
  time: 5000,
279
306
  },
307
+ [imgPlugin.toString()]: {
308
+ replacedElements: config.replacedElements,
309
+ },
280
310
  },
281
311
  }
282
312
  }
@@ -290,6 +320,7 @@ export async function initEditor(config: EditorConfig) {
290
320
  if(editor) throw new Error('Grapesjs editor already created')
291
321
  return new Promise<Editor>((resolve, reject) => {
292
322
  try {
323
+ /* @ts-ignore */
293
324
  editor = grapesjs.init(config)
294
325
  } catch(e) {
295
326
  console.error('Error initializing GrapesJs with plugins:', plugins, e)
@@ -312,17 +343,24 @@ export async function initEditor(config: EditorConfig) {
312
343
  modalImportTitle: 'Import from website',
313
344
  }))
314
345
 
346
+ // Adjustments to do when the editor is ready
315
347
  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
348
+ const views = editor.Panels.getPanel('views')
349
+
350
+ // Remove blocks and layers buttons from the properties
351
+ // This is because in Silex they are on the left
352
+ views.buttons.remove('open-blocks')
353
+ views.buttons.remove('open-layers')
354
+
355
+ // Remove useless buttons
320
356
  editor.Panels.getPanel('options').buttons.remove('export-template')
357
+ editor.Panels.getPanel('options').buttons.remove('fullscreen')
321
358
 
359
+ // Render the block manager, otherwise it is empty
322
360
  editor.BlockManager.render(null)
323
361
 
324
362
  // use the style filter plugin
325
- editor.StyleManager.addProperty('extra',{ extend: 'filter' })
363
+ editor.StyleManager.addProperty('extra', { extend: 'filter' })
326
364
 
327
365
  // GrapesJs editor is ready
328
366
  resolve(editor)
@@ -65,6 +65,7 @@ const page2 = {
65
65
  },
66
66
  }
67
67
  beforeEach(() => {
68
+ /* @ts-ignore */
68
69
  editor = grapesjs.init({
69
70
  headless: true,
70
71
  storageManager: { autoload: false },
@@ -81,7 +82,7 @@ test('init', () => {
81
82
  test('rename page and rewrite links in current page', () => {
82
83
  const page = editor.Pages.getSelected()
83
84
  expect(page.id).toBe(pageMain.id)
84
- expect(page.getName()).toBeUndefined()
85
+ expect(page.getName()).toBe('')
85
86
  const newName = 'Home page'
86
87
  const newPath = './home-page.html'
87
88
  // Do not work: page.setName(newName)
@@ -56,7 +56,6 @@ export const internalLinksPlugin = (editor, opts) => {
56
56
  // mark all links as issues
57
57
  const issues = []
58
58
  onAll(component => {
59
- console.log(component.getAttributes().href, getPageLink(page.previous('name')), page.previous('name'))
60
59
  if(component.getAttributes().href === getPageLink(page.previous('name'))) {
61
60
  issues.push(component)
62
61
  }
@@ -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,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
 
21
20
  const pluginName = 'page-panel'
@@ -29,16 +28,41 @@ function selectPage(editor, page) {
29
28
  }
30
29
  function addPage(editor, config) {
31
30
  const pages = editor.Pages.getAll()
31
+ // Get a name
32
32
  let idx = 1
33
33
  const newPageName = config.newPageName || 'New page'
34
34
  let pageName = newPageName
35
35
  while(pages.find(p => p.getName() === pageName)) {
36
36
  pageName = `${newPageName} ${idx++}`
37
37
  }
38
+ // Add page
38
39
  const page = editor.Pages.add({ name: pageName })
40
+ // Select the new page
41
+ editor.Pages.select(page)
42
+ // Open page settings to edit the name
39
43
  editor.runCommand(config.cmdOpenNewPageDialog, {page})
40
44
  }
41
45
 
46
+ function clonePage(editor, page) {
47
+ const pages = editor.Pages.getAll()
48
+ // Get a name
49
+ let idx = 1
50
+ const newPageName = (page.getName() || 'main') + ' copy'
51
+ let pageName = newPageName
52
+ while(pages.find(p => p.getName() === pageName)) {
53
+ pageName = `${newPageName} ${idx++}`
54
+ }
55
+ // Clone components
56
+ const body = page.getMainComponent().clone()
57
+ // Add page
58
+ const newPage = editor.Pages.add({
59
+ name: pageName,
60
+ component: body,
61
+ })
62
+ // Select the new page
63
+ editor.Pages.select(newPage)
64
+ }
65
+
42
66
  function removePage(editor, page) {
43
67
  if(editor.Pages.getAll().length === 1) {
44
68
  console.error('can not delete the only page')
@@ -76,6 +100,7 @@ function renderPages(editor, config) {
76
100
  ${ name }
77
101
  </div>
78
102
  <i class="pages__icon pages__remove-btn fa fa-trash" @click=${e => removePage(editor, getPageFromEvent(e))}></i>
103
+ <i class="pages__icon pages__clone-btn fa fa-clone" @click=${e => clonePage(editor, getPageFromEvent(e))}></i>
79
104
  <i class="pages__icon fa fa-cog" @click=${e => settingsPage(editor, config, getPageFromEvent(e))}></i>
80
105
  </div>
81
106
  </div>
@@ -89,7 +114,7 @@ function renderPages(editor, config) {
89
114
  </main></section>`
90
115
  }
91
116
 
92
- export const pagePanelPlugin = grapesjs.plugins.add(pluginName, (editor, opts) => {
117
+ export const pagePanelPlugin = (editor, opts) => {
93
118
  // create wrapper
94
119
  const el = document.createElement('div')
95
120
  el.classList.add('pages__wrapper')
@@ -114,5 +139,5 @@ export const pagePanelPlugin = grapesjs.plugins.add(pluginName, (editor, opts) =
114
139
  // add command to add pages
115
140
  editor.Commands.add(cmdAddPage, () => addPage(editor, opts))
116
141
  })
117
- })
142
+ }
118
143
 
@@ -15,11 +15,27 @@
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
21
  const panelId = 'project-bar-panel'
21
22
  const containerPanelId = 'project-bar-container'
22
23
 
24
+ export interface PanelObject {
25
+ command: string | ((editor: Editor) => void)
26
+ text: string
27
+ className: string
28
+ attributes: {
29
+ title?: string
30
+ containerClassName?: string
31
+ }
32
+ buttons?: {
33
+ command: string
34
+ text: string
35
+ className: string
36
+ }[]
37
+ }
38
+
23
39
  export const projectBarPlugin = (editor, opts) => {
24
40
  // create the panels container for all panels in grapesjs
25
41
  const containerPanel = editor.Panels.addPanel({
@@ -32,76 +48,79 @@ export const projectBarPlugin = (editor, opts) => {
32
48
  buttons: opts.panels,
33
49
  visible : true,
34
50
  })
35
- const panelsEl = opts.panels.map(panel => {
36
- const el = document.createElement('div')
51
+ // add the panels to the container
52
+ opts.panels.map(panel => addButton(editor, panel))
37
53
 
38
- // create container for panel
39
- if(panel.attributes.containerClassName) {
40
- el.classList.add('project-bar__panel', panel.attributes.containerClassName, 'gjs-hidden')
54
+ // Handle the preview mode which behaves oddly
55
+ editor.on('stop:preview', () => {
56
+ containerPanel.set('visible', false)
57
+ updateSqueez(editor)
58
+ })
41
59
 
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
- }
60
+ // All other events where the canvas is resized
61
+ editor.on('load device:select page', () => {
62
+ updateSqueez(editor)
63
+ })
64
+ }
58
65
 
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)
66
+ function updateSqueez(editor: Editor) {
67
+ const containerPanel = editor.Panels.getPanel(containerPanelId)
68
+ // make sure the squeez corresponds to the state (reset when change page)
69
+ if(containerPanel.get('visible')) document.body.classList.add('silex-squeeze-left')
70
+ else document.body.classList.remove('silex-squeeze-left')
71
+ editor.refresh()
72
+ }
62
73
 
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
- })
74
+ export function addButton(editor: Editor, panel: PanelObject) {
75
+ const containerPanel = editor.Panels.getPanel(containerPanelId)
76
+ const el = document.createElement('div')
77
+ // create container for panel
78
+ if(panel.attributes.containerClassName) {
79
+ el.classList.add('project-bar__panel', panel.attributes.containerClassName, 'gjs-hidden')
80
+ // add header
81
+ if(panel.attributes.title) {
82
+ render(html`
83
+ <header class="project-bar__panel-header">
84
+ <h3 class="project-bar__panel-header-title">${ panel.attributes.title }</h3>
85
+ ${ panel.buttons?.map(button => {
86
+ return html`
87
+ <div
88
+ class="project-bar__panel-header-button ${ button.className }"
89
+ @click=${e => editor.runCommand(button.command)}
90
+ ><span>${ button.text }</span></div>
91
+ `
92
+ }) }
93
+ </header>
94
+ `, el)
69
95
  }
70
-
71
- // commands for show / hide panels
72
- // handle the case where command is a normal command, then let the Panel handle it
73
- typeof panel.command === 'string' && editor.Commands.add(panel.command, {
74
- run() {
75
- if(panel.attributes.containerClassName) {
76
- containerPanel.set('visible', true)
77
- el.classList.remove('gjs-hidden')
78
- editor.Canvas.getFrameEl().classList.add('silex-squeeze-left')
79
- }
80
- },
81
- stop() {
82
- if(panel.attributes.containerClassName) {
83
- containerPanel.set('visible', false)
84
- el.classList.add('gjs-hidden')
85
- editor.Canvas.getFrameEl().classList.remove('silex-squeeze-left')
86
- }
87
- },
96
+ // temporarily attach it to the body
97
+ // this lets the block manager and other plugins attach to their container
98
+ document.body.appendChild(el)
99
+ // on load attach the panels to the main container
100
+ // this is when the main containerPanel has an element
101
+ editor.on('load', () => {
102
+ const containerPanelEl = containerPanel.view.el
103
+ containerPanelEl.appendChild(el)
88
104
  })
89
- })
90
- function updateSqueez() {
91
- const containerPanelEl = containerPanel.view.el
92
- const iframe = editor.Canvas.getFrameEl()
93
- iframe.classList.remove('enable-squeeze')
94
- setTimeout(() => {
95
- const left = iframe.getClientRects()[0]?.left
96
- const right = containerPanelEl.getClientRects()[0]?.right
97
- if(left < right || !right) iframe.classList.add('enable-squeeze')
98
- else iframe.classList.remove('enable-squeeze')
99
- }, 400) // More than the transition duration
100
- // make sure the squeez corresponds to the state (reset when change page)
101
- if(containerPanel.get('visible')) iframe.classList.add('silex-squeeze-left')
102
- else iframe.classList.remove('silex-squeeze-left')
103
105
  }
104
- editor.on('load device:select page', () => {
105
- updateSqueez()
106
+ // commands for show / hide panels
107
+ // handle the case where command is a normal command, then let the Panel handle it
108
+ typeof panel.command === 'string' && editor.Commands.add(panel.command, {
109
+ run() {
110
+ if(panel.attributes.containerClassName) {
111
+ containerPanel.set('visible', true)
112
+ el.classList.remove('gjs-hidden')
113
+ document.body.classList.add('silex-squeeze-left')
114
+ editor.refresh()
115
+ }
116
+ },
117
+ stop() {
118
+ if(panel.attributes.containerClassName) {
119
+ containerPanel.set('visible', false)
120
+ el.classList.add('gjs-hidden')
121
+ document.body.classList.remove('silex-squeeze-left')
122
+ editor.refresh()
123
+ }
124
+ },
106
125
  })
107
126
  }