@silexlabs/silex 3.0.0-alpha.96 → 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 +26 -7
  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 +35 -31
  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 +145 -42
  88. package/src/ts/client/assetUrl.ts +29 -10
  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 +51 -17
  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
@@ -20,8 +20,15 @@ import { getEditor, getEditorConfig } from './grapesjs'
20
20
  import { CLIENT_CONFIG_FILE_NAME, DEFAULT_LANGUAGE, DEFAULT_WEBSITE_ID } from '../constants'
21
21
  import { ConnectorId, WebsiteId } from '../types'
22
22
  import { Editor, EditorConfig, Page } from 'grapesjs'
23
- import { PublicationTransformer, validatePublicationTransformer } from './publication-transformers'
23
+ import { PublicationTransformer, publicationTransformerDefault, validatePublicationTransformer } from './publication-transformers'
24
24
  import * as api from './api'
25
+ import { assetsPublicationTransformer } from './assetUrl'
26
+ import { SettingsSection } from './grapesjs/settings-sections'
27
+ import { addSection, removeSection } from './grapesjs/settings'
28
+
29
+ // Plugins
30
+ import publishCustomCodeBlock from './publish-custom-code-block'
31
+ import publishFonts from './publish-fonts'
25
32
 
26
33
  /**
27
34
  * @fileoverview Silex client side config
@@ -57,10 +64,38 @@ export class ClientConfig extends Config {
57
64
  */
58
65
  debug = false
59
66
 
67
+ /**
68
+ * Add hash in the file name of CSS at the time of publication
69
+ * If true, CSS files of generated pages will look like `page-name.123456.css` instead of `page-name.css`
70
+ * This is useful to avoid caching issues
71
+ * @default true
72
+ */
73
+ addHashInCssFileName = true
74
+
75
+ /**
76
+ * Replaced elements
77
+ * This is a list of elements which support the object-fit and object-position CSS properties
78
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element
79
+ * When selected, Silex will show the object-fit and object-position properties in the style panel
80
+ */
81
+ replacedElements = [
82
+ 'img',
83
+ 'video',
84
+ 'iframe',
85
+ 'embed',
86
+ 'object',
87
+ 'audio',
88
+ 'canvas',
89
+ // 'option',
90
+ ]
91
+
60
92
  /**
61
93
  * Grapesjs config
62
94
  */
63
- grapesJsConfig: EditorConfig
95
+ grapesJsConfig: EditorConfig = {
96
+ plugins: [],
97
+ pluginsOpts: {},
98
+ }
64
99
 
65
100
  /**
66
101
  * Client config url
@@ -72,7 +107,22 @@ export class ClientConfig extends Config {
72
107
  * Init GrapesJS config which depend on the config file properties
73
108
  */
74
109
  initGrapesConfig() {
75
- this.grapesJsConfig = getEditorConfig(this.websiteId, this.storageId, this.rootUrl)
110
+ // Get the initial config
111
+ const config = getEditorConfig(this)
112
+
113
+ // Merge with the config modified by plugins
114
+ this.grapesJsConfig = {
115
+ ...this.grapesJsConfig,
116
+ ...config,
117
+ plugins: [
118
+ ...this.grapesJsConfig.plugins,
119
+ ...config.plugins,
120
+ ],
121
+ pluginsOpts: {
122
+ ...this.grapesJsConfig.pluginsOpts,
123
+ ...config.pluginsOpts,
124
+ },
125
+ }
76
126
  }
77
127
 
78
128
  /**
@@ -85,7 +135,14 @@ export class ClientConfig extends Config {
85
135
  /**
86
136
  * Publication transformers let plugins change files before they are published
87
137
  */
88
- publicationTransformers: Array<PublicationTransformer> = []
138
+ publicationTransformers: Array<PublicationTransformer> = [assetsPublicationTransformer, publicationTransformerDefault]
139
+
140
+ /**
141
+ * Reset publication transformers
142
+ */
143
+ resetPublicationTransformers() {
144
+ this.publicationTransformers = [assetsPublicationTransformer]
145
+ }
89
146
 
90
147
  /**
91
148
  * Add a publication transformer(s)
@@ -102,4 +159,28 @@ export class ClientConfig extends Config {
102
159
  // Add to the list
103
160
  this.publicationTransformers = this.publicationTransformers.concat(transformers)
104
161
  }
162
+
163
+ /**
164
+ * Add a section to the settings dialog
165
+ */
166
+ addSettings(section: SettingsSection, siteOrPage: 'site' | 'page', position: 'first' | 'last' | number = 'last') {
167
+ addSection(section, siteOrPage, position)
168
+ }
169
+
170
+ /**
171
+ * Remove a section from the settings dialog
172
+ */
173
+ removeSettings(id: string, siteOrPage: 'site' | 'page') {
174
+ removeSection(id, siteOrPage)
175
+ }
176
+
177
+ /**
178
+ * Add default plugins
179
+ */
180
+ async addDefaultPlugins() {
181
+ await this.addPlugin([
182
+ publishCustomCodeBlock,
183
+ publishFonts,
184
+ ], {})
185
+ }
105
186
  }
@@ -17,18 +17,24 @@
17
17
 
18
18
  export enum ClientEvent {
19
19
  // Sent on the config object
20
- STARTUP_START = 'silex:startup:start',
21
- STARTUP_END = 'silex:startup:end',
22
- GRAPESJS_START = 'silex:grapesjs:start',
23
- GRAPESJS_END = 'silex:grapesjs:end',
20
+ STARTUP_START = 'silex:startup:start', /* Loading is over and Silex is starting */
21
+ STARTUP_END = 'silex:startup:end', /* Silex is ready to be used */
22
+ GRAPESJS_START = 'silex:grapesjs:start', /* GrapesJS is about to be initialized, it is time to edit config.grapesJsConfig */
23
+ GRAPESJS_END = 'silex:grapesjs:end', /* GrapesJS is ready to be used, `editor` is passed as an argument */
24
24
 
25
- // Sent on the editor object
26
- PUBLISH_START = 'silex:publish:start',
27
- PUBLISH_DATA = 'silex:publish:data',
28
- PUBLISH_END = 'silex:publish:end',
29
- PUBLISH_ERROR = 'silex:publish:error',
25
+ // Sent on GrapesJs editor object (returned by silex.getEditor())
26
+ PUBLISH_START = 'silex:publish:start', /* Publication starts, you can read+write {projectData, siteSettings} */
27
+ PUBLISH_PAGE = 'silex:publish:page', /* Publication of a page, read+write { siteSettings, pageSettings, page } */
28
+ PUBLISH_DATA = 'silex:publish:data', /* Just before we send the published data to the server, read+write all publication data, check PublicationData type in types.ts */
29
+ PUBLISH_END = 'silex:publish:end', /* Publication is over, the argument is the publication result with {success: boolean, message: string} */
30
+ PUBLISH_ERROR = 'silex:publish:error', /* Publication failed, the argument is the publication result with {success: boolean, message: string} */
30
31
  PUBLISH_LOGIN_START = 'silex:publish:login:start',
31
32
  PUBLISH_LOGIN_END = 'silex:publish:login:end',
32
33
  ASSET_WRITE_END = 'silex:asset:write:end',
33
34
  WRITE_END = 'silex:write:end',
35
+ SETTINGS_OPEN = 'silex:settings:open', /* The settings dialog is opened */
36
+ SETTINGS_CLOSE = 'silex:settings:close', /* The settings dialog is closed */
37
+ SETTINGS_SAVE_START = 'silex:settings:save:start', /* The settings dialog is closed and the settings are about to be saved */
38
+ SETTINGS_SAVE_END = 'silex:settings:save:end', /* The settings dialog is closed and the settings are saved */
39
+ SETTINGS_SECTION_CHANGE = 'silex:settings:section-change', /* The user clicked on a section in the settings dialog */
34
40
  }
@@ -16,13 +16,15 @@
16
16
  */
17
17
 
18
18
  import { getPageSlug } from '../../page'
19
- import { ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiPublicationPublishBody, ClientSideFile, ClientSideFileType, ConnectorData, ConnectorType, ConnectorUser, JobStatus, PublicationData, PublicationJobData, PublicationSettings, WebsiteData, WebsiteFile, WebsiteId, WebsiteSettings } from '../../types'
19
+ import { ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiPublicationPublishBody, ClientSideFile, ClientSideFileType, ConnectorData, ConnectorType, ConnectorUser, JobStatus, Initiator, PublicationData, PublicationJobData, PublicationSettings, WebsiteData, WebsiteFile, WebsiteId, WebsiteSettings } from '../../types'
20
20
  import { Editor } from 'grapesjs'
21
21
  import { PublicationUi } from './PublicationUi'
22
22
  import { getUser, logout, publicationStatus, publish } from '../api'
23
23
  import { API_CONNECTOR_LOGIN, API_CONNECTOR_PATH, API_PATH } from '../../constants'
24
24
  import { ClientEvent } from '../events'
25
25
  import { resetRenderComponents, resetRenderCssRules, transformPermalink, transformFiles, transformPath, renderComponents, renderCssRules } from '../publication-transformers'
26
+ import { displayedToStored } from '../assetUrl'
27
+ import { hashString } from '../utils'
26
28
 
27
29
  /**
28
30
  * @fileoverview Publication manager for Silex
@@ -210,27 +212,10 @@ export class PublicationManager {
210
212
  }
211
213
  }
212
214
 
213
- /**
214
- * Start the publication process
215
- * This is the command "publish"
216
- */
217
- async startPublication() {
218
- if (this.status === PublicationStatus.STATUS_PENDING) throw new Error('Publication is already in progress')
219
- this.status = PublicationStatus.STATUS_PENDING
220
- this.job = null
221
- this.dialog && this.dialog.displayPending(this.job, this.status)
222
- this.editor.trigger(ClientEvent.PUBLISH_START)
223
- // User and where to publish
224
- const storageUser = this.editor.getModel().get('user') as ConnectorUser
225
- if(!storageUser) throw new Error('User not logged in to a storage connector')
226
- if(!this.settings.connector?.connectorId) throw new Error('User not logged in to a hosting connector')
227
- const websiteId = this.options.websiteId
228
- const storageId = storageUser.storage.connectorId
215
+ async getPublicationData(projectData, siteSettings): Promise<PublicationData> {
229
216
  // Data to publish
230
217
  // See assetUrl.ts which is a default transformer, always present
231
218
  this.setPublicationTransformers()
232
- const projectData = this.editor.getProjectData() as WebsiteData
233
- const siteSettings = this.editor.getModel().get('settings') as WebsiteSettings
234
219
  // Build the files structure
235
220
  const files: ClientSideFile[] = (await this.getHtmlFiles(siteSettings))
236
221
  .flatMap(file => ([{
@@ -250,7 +235,13 @@ export class PublicationManager {
250
235
  // .replace(/^\/assets/, '')
251
236
  // Transform the file paths with the transformers
252
237
  const path = transformPath(this.editor, asset.src, ClientSideFileType.ASSET)
253
- const src = transformPermalink(this.editor, asset.src, ClientSideFileType.ASSET)
238
+ //const src = transformPermalink(this.editor, asset.src, ClientSideFileType.ASSET)
239
+ // This is done in transformPermalink and transformPath but other transformers may change it
240
+ // So we do this only using displayedToStored for the path
241
+ // As path is used to download the asset
242
+ const src = displayedToStored(asset.src)
243
+ // Remove the /asset prefix to keep only the file name
244
+ .replace(/^\/assets\//, '')
254
245
  return {
255
246
  ...asset,
256
247
  path,
@@ -261,14 +252,45 @@ export class PublicationManager {
261
252
  // Create the data to send to the server
262
253
  const data: PublicationData = {
263
254
  ...projectData,
255
+ assets: projectData.assets.map(asset => ({
256
+ ...asset,
257
+ src: displayedToStored(asset.src),
258
+ })),
264
259
  settings: siteSettings,
265
260
  publication: this.settings,
266
261
  files,
267
262
  }
268
263
  this.resetPublicationTransformers()
264
+ // Let plugins transform the data
269
265
  transformFiles(this.editor, data)
270
266
  this.editor.trigger(ClientEvent.PUBLISH_DATA, data)
267
+ // Return the data
268
+ return data
269
+ }
270
+
271
+ /**
272
+ * Start the publication process
273
+ * This is the command "publish"
274
+ */
275
+ async startPublication() {
271
276
  try {
277
+ if (this.status === PublicationStatus.STATUS_PENDING) throw new Error('Publication is already in progress')
278
+ this.status = PublicationStatus.STATUS_PENDING
279
+ this.job = null
280
+ this.dialog && this.dialog.displayPending(this.job, this.status)
281
+ // Get the data to publish, clone the objects because plugins can change it
282
+ const projectData = { ...this.editor.getProjectData() as WebsiteData }
283
+ const siteSettings = { ...this.editor.getModel().get('settings') as WebsiteSettings }
284
+ this.editor.trigger(ClientEvent.PUBLISH_START, {projectData, siteSettings})
285
+ // User and where to publish
286
+ const storageUser = this.editor.getModel().get('user') as ConnectorUser
287
+ if(!storageUser) throw new Error('User not logged in to a storage connector')
288
+ if(!this.settings.connector?.connectorId) throw new Error('User not logged in to a hosting connector')
289
+ const websiteId = this.options.websiteId
290
+ const storageId = storageUser.storage.connectorId
291
+ // Get the data to publish
292
+ const data = await this.getPublicationData(projectData, siteSettings)
293
+ // Use the publication API
272
294
  const [url, job] = await publish({
273
295
  websiteId,
274
296
  hostingId: this.settings.connector.connectorId,
@@ -278,12 +300,6 @@ export class PublicationManager {
278
300
  })
279
301
  this.job = job
280
302
  this.status = jobStatusToPublicationStatus(this.job.status)
281
- // Save the publication settings
282
- // Useless because the url is useful after publish only
283
- //if(this.settings.url !== url) {
284
- // this.settings.url = url
285
- // await this.editor.store(null)
286
- //}
287
303
  this.trackProgress()
288
304
  } catch (e) {
289
305
  console.error('publish error', e)
@@ -302,41 +318,58 @@ export class PublicationManager {
302
318
  }
303
319
 
304
320
  async getHtmlFiles(siteSettings: WebsiteSettings): Promise<WebsiteFile[]> {
305
- return this.editor.Pages.getAll().map(page => {
306
- const pageSettings = page.get('settings') as WebsiteSettings
321
+ return Promise.all(this.editor.Pages.getAll().map(async page => {
322
+ // Clone the settings because plugins can change them
323
+ siteSettings = { ...siteSettings }
324
+ const pageSettings = { ...page.get('settings') as WebsiteSettings }
325
+ // Utility function to get a setting from the page or the site settings
307
326
  function getSetting(name) {
308
327
  return (pageSettings || {})[name] || (siteSettings || [])[name] || ''
309
328
  }
310
- const component = page.getMainComponent()
329
+
330
+ // Get the content from GrapesJS
331
+ const body = page.getMainComponent()
332
+ const cssContent = this.editor.getCss({ component: body })
333
+ const htmlContent = this.editor.getHtml({ component: body })
334
+
311
335
  // Transform the file paths
312
336
  const slug = getPageSlug(page.get('name'))
313
- const cssInitialPath = `/css/${slug}.css`
337
+ const cssInitialPath = `/css/${slug}-${await hashString(cssContent)}.css`
314
338
  const htmlInitialPath = `/${slug}.html`
315
- const cssPermalink = transformPermalink(this.editor, cssInitialPath, ClientSideFileType.CSS)
339
+ const cssPermalink = transformPermalink(this.editor, cssInitialPath, ClientSideFileType.CSS, Initiator.HTML)
316
340
  const cssPath = transformPath(this.editor, cssInitialPath, ClientSideFileType.CSS)
317
341
  const htmlPath = transformPath(this.editor, htmlInitialPath, ClientSideFileType.HTML)
318
- const body = this.editor.getHtml({ component })
342
+
343
+ // Let plugins transform the data
344
+ this.editor.trigger(ClientEvent.PUBLISH_PAGE, { page, siteSettings, pageSettings })
345
+
346
+ // Useful data for HTML result
347
+ const title = getSetting('title')
348
+ const favicon = getSetting('favicon')
349
+ // Return the HTML file
319
350
  return {
320
351
  html: `<!DOCTYPE html>
321
352
  <html lang="${getSetting('lang')}">
322
353
  <head>
354
+ <meta charset="UTF-8">
323
355
  <link rel="stylesheet" href="${cssPermalink}" />
324
356
  ${siteSettings?.head || ''}
325
357
  ${pageSettings?.head || ''}
326
- <title>${getSetting('title')}</title>
327
- <link rel="icon" href="${getSetting('favicon')}" />
358
+ ${ title ? `<title>${ title }</title>` : '' }
359
+ ${ favicon ? `<link rel="icon" href="${favicon}" />` : '' }
328
360
  ${['description', 'og:title', 'og:description', 'og:image']
329
- .map(prop => `<meta property="${prop}" content="${getSetting(prop)}"/>`)
361
+ .filter(prop => !!getSetting(prop))
362
+ .map(prop => `<meta name="${prop}" property="${prop}" content="${getSetting(prop)}"/>`)
330
363
  .join('\n')
331
364
  }
332
365
  </head>
333
- ${body}
366
+ ${htmlContent}
334
367
  </html>`,
335
- css: this.editor.getCss({ component }),
368
+ css: cssContent,
336
369
  cssPath,
337
370
  htmlPath,
338
371
  }
339
- })
372
+ }))
340
373
  }
341
374
 
342
375
  async trackProgress() {
@@ -125,13 +125,16 @@ export class PublicationUi {
125
125
  el.id = 'publish-dialog'
126
126
  el.className = 'silex-dialog-inline silex-dialog gjs-two-color'
127
127
  document.body.append(el)
128
- // Create the publish button
129
- this.editor.Panels.addButton(this.options.appendTo, {
130
- id: 'publish-button',
131
- className: 'silex-button--size publish-button',
132
- command: cmdPublish,
133
- attributes: { title: 'Publish' },
134
- label: '<span class="fa-solid fa-upload"></span><span class="silex-button--small">Publish</span>',
128
+ // Let the other buttons be added, we want to be last
129
+ setTimeout(() => {
130
+ // Create the publish button
131
+ this.editor.Panels.addButton(this.options.appendTo, {
132
+ id: 'publish-button',
133
+ className: 'silex-button--size publish-button',
134
+ command: cmdPublish,
135
+ attributes: { title: 'Publish' },
136
+ label: '<span class="fa-solid fa-upload"></span><span class="silex-button--small">Publish</span>',
137
+ })
135
138
  })
136
139
  return el
137
140
  }
@@ -158,6 +161,9 @@ export class PublicationUi {
158
161
  }
159
162
  async renderOpenDialog(job: PublicationJobData, status: PublicationStatus): Promise<TemplateResult> {
160
163
  return html`
164
+ <header>
165
+ <h3>Publication</h3>
166
+ </header>
161
167
  <main>
162
168
  ${this.isPending(status) ? html`
163
169
  <p>Publication in progress</p>
@@ -188,8 +194,6 @@ export class PublicationUi {
188
194
  <summary>Logs</summary>
189
195
  <pre style="
190
196
  max-width: 100%;
191
- max-height: 50vh;
192
- overflow: auto;
193
197
  font-size: x-small;
194
198
  " >${unsafeHTML(cleanupLogEntry(job.logs))}
195
199
  </pre>
@@ -200,8 +204,6 @@ export class PublicationUi {
200
204
  <summary>Errors</summary>
201
205
  <pre style="
202
206
  max-width: 100%;
203
- max-height: 50vh;
204
- overflow: auto;
205
207
  font-size: x-small;
206
208
  "
207
209
  >${unsafeHTML(cleanupLogEntry(job.errors))}