@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
@@ -15,12 +15,11 @@
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 { cmdAddSymbol } from '@silexlabs/grapesjs-symbols'
20
19
 
21
20
  export const cmdPromptAddSymbol = 'symbol-prompt-add'
22
21
 
23
- export default grapesjs.plugins.add(name, (editor, opts) => {
22
+ export default (editor, opts) => {
24
23
  function getNext(prefix) {
25
24
  let idx = 1
26
25
  while(editor.Symbols.find(s => s.get('label') === prefix + idx)) {
@@ -31,8 +30,8 @@ export default grapesjs.plugins.add(name, (editor, opts) => {
31
30
  editor.Commands.add(cmdPromptAddSymbol, {
32
31
  run: (_, sender) => {
33
32
  const label = prompt('Label', getNext('Symbol '))
34
- const icon = prompt('Icon', 'fa-list')
33
+ const icon = 'fa-gem'
35
34
  editor.runCommand(cmdAddSymbol, { label, icon })
36
35
  }
37
36
  })
38
- })
37
+ }
@@ -13,26 +13,30 @@
13
13
  *
14
14
  * You should have received a copy of the GNU Affero General Public License
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ *
16
17
  */
17
18
 
18
- import express from 'express'
19
- import { Directus } from '@directus/sdk'
19
+ const pasteBtnClass = 'fa fa-fw fa-paste silex-button'
20
+ const disabledClass = ' disabled'
21
+
22
+ export default function(editor) {
23
+ // Add copy/paste buttons in the top bar
24
+ const [copyBtn, pasteBtn] = editor.Panels.addButton('options', [{
25
+ id: 'copy',
26
+ className: 'fa fa-fw fa-copy',
27
+ command: 'core:copy',
28
+ attributes: { title: 'Copy (Ctrl+C)' },
29
+ }, {
30
+ id: 'paste',
31
+ className: pasteBtnClass + disabledClass,
32
+ command: 'core:paste',
33
+ attributes: { title: 'Paste (Ctrl+V)' },
34
+ active: false,
35
+ }])
20
36
 
21
- export default async function(config, opts = {}) {
22
- // config.on('silex:startup:start', ({app}) => {
23
- // const router = express.Router()
24
- // router.post(['/publish', '/website', '/assets'], async function(req, res, next) {
25
- // try {
26
- // const token = req.body.token || opts.directusToken
27
- // const directus = new Directus(opts.directusUrl)
28
- // directus.storage.auth_token = token
29
- // const me = await directus.users.me.read()
30
- // next()
31
- // } catch(err) {
32
- // console.error('Publish failed in auth module. Did you provide a directus token?', err.message)
33
- // res.status(403).json({ message: err.message })
34
- // }
35
- // })
36
- // app.use(router)
37
- // })
37
+ // Disable paste button if clipboard is empty
38
+ editor.EditorModel.on('change:clipboard', (model, value) => {
39
+ const hasClipboard = value && value.length > 0
40
+ pasteBtn.set('className', pasteBtnClass + (hasClipboard ? '' : disabledClass))
41
+ })
38
42
  }
@@ -21,18 +21,28 @@
21
21
  *
22
22
  */
23
23
 
24
+ import { DEV_MESSAGE } from '../constants'
24
25
  import { ClientConfig } from './config'
25
26
  import { ClientEvent } from './events'
26
27
  import { initEditor, getEditor } from './grapesjs/index'
28
+ import { cmdPauseAutoSave } from './grapesjs/storage'
27
29
 
28
30
  // Expose API to calling app as window.silex
29
31
  export * from './expose'
30
32
 
33
+ /**
34
+ * Expose the config object
35
+ */
36
+ export let config: ClientConfig
37
+
31
38
  /**
32
39
  * Start Silex, called from host HTML page with window.silex.start()
33
40
  */
34
- export async function start(options = {}) {
35
- const config = new ClientConfig()
41
+ export async function start(options = {}): Promise<void> {
42
+ // Log Silex version for devs - it is also displayed in te settings
43
+ console.info(DEV_MESSAGE)
44
+ // Create the config object
45
+ config = new ClientConfig()
36
46
  Object.assign(config, options)
37
47
 
38
48
  // Config file in root folder which may be generated by the server
@@ -50,6 +60,8 @@ export async function start(options = {}) {
50
60
  config.initGrapesConfig()
51
61
 
52
62
  // Start grapesjs
63
+ // Here you can change the config before passing it to grapesjs
64
+ config.emit(ClientEvent.GRAPESJS_START)
53
65
  try{
54
66
  await initEditor(config.grapesJsConfig)
55
67
  } catch(e) {
@@ -57,18 +69,25 @@ export async function start(options = {}) {
57
69
  throw e
58
70
  }
59
71
 
60
- config.emit(ClientEvent.GRAPESJS_START)
61
72
  const editor = getEditor()
73
+
74
+ // Store the config in the editor
75
+ editor.getModel().set('config', config)
76
+
77
+ // Notify plugins
62
78
  config.emit(ClientEvent.GRAPESJS_END, { editor })
63
79
 
64
80
  // Init internationalization module
65
81
  editor.I18n.setLocale(config.lang)
66
82
 
83
+ // Add default plugins
84
+ await config.addDefaultPlugins()
85
+
67
86
  // Load the site
68
- editor.StorageManager.setAutosave(false)
69
- console.log('before load')
70
87
  try {
88
+ editor.runCommand(cmdPauseAutoSave)
71
89
  await editor.load(null)
90
+ editor.once('canvas:frame:load', () => editor.stopCommand(cmdPauseAutoSave))
72
91
  } catch(e) {
73
92
  if(e.httpStatusCode === 401) {
74
93
  // Unauthorized, will try to login
@@ -76,16 +95,16 @@ export async function start(options = {}) {
76
95
  // Will display an error message, see in storage.ts
77
96
  }
78
97
  } finally {
79
- console.log('after load')
80
- setTimeout(() => {
81
- // This needs time for grapesjs
82
- editor.editor.set('changesCount', 0)
83
- editor.StorageManager.setAutosave(true)
84
-
85
- // This needs time for the loader to be hidden
86
- document.querySelector('.silex-loader').classList.add('silex-dialog-hide')
87
- document.querySelector('#gjs').classList.remove('silex-dialog-hide')
88
- config.emit(ClientEvent.STARTUP_END, { editor, config })
89
- }, 100)
98
+ if(editor.getModel().getCurrentFrame().loaded) {
99
+ loaded(editor)
100
+ } else {
101
+ editor.once('canvas:frame:load', () => loaded(editor))
102
+ }
90
103
  }
91
104
  }
105
+
106
+ function loaded(editor) {
107
+ document.querySelector('.silex-loader').classList.add('silex-dialog-hide')
108
+ document.querySelector('#gjs').classList.remove('silex-dialog-hide')
109
+ config.emit(ClientEvent.STARTUP_END, { editor, config })
110
+ }
@@ -0,0 +1,207 @@
1
+ import { jest, expect, describe, it, beforeEach } from '@jest/globals'
2
+ import { Mock } from 'jest-mock'
3
+ import {
4
+ renderComponents,
5
+ renderCssRules,
6
+ resetRenderComponents,
7
+ resetRenderCssRules,
8
+ PublicationTransformer,
9
+ transformFiles,
10
+ transformBgImage
11
+ } from './publication-transformers'
12
+ import { ClientConfig } from './config'
13
+ import grapesjs, { Component, Editor, StyleProps, Page } from 'grapesjs'
14
+ import { ClientSideFile, ClientSideFileType, PublicationData } from '../types'
15
+
16
+ describe('publication-transformers', () => {
17
+ let mockConfig: ClientConfig
18
+ let mockFile: ClientSideFile
19
+ let mockData: PublicationData
20
+ let transformer: PublicationTransformer
21
+
22
+ let editor: Editor
23
+
24
+ beforeEach(() => {
25
+ // Initialize your mocks here
26
+ /* @ts-ignore */
27
+ editor = grapesjs.init({
28
+ headless: true,
29
+ storageManager: { autoload: false },
30
+ })
31
+ expect(editor).not.toBeUndefined()
32
+ editor.addComponents(`
33
+ <nav class="parent">
34
+ <div class="child">Hello world</div>
35
+ <nav>
36
+ `)
37
+ editor.addStyle(`
38
+ .parent {
39
+ color: red;
40
+ }
41
+ .child {
42
+ color: blue;
43
+ }
44
+ `)
45
+ mockFile = {
46
+ path: 'test path',
47
+ content: 'test content',
48
+ } as ClientSideFile
49
+ mockData = {
50
+ files: [mockFile],
51
+ pages: [{} as Page],
52
+ } as any as PublicationData
53
+ transformer = {
54
+ renderComponent: jest.fn(),
55
+ renderCssRule: jest.fn(),
56
+ transformFile: jest.fn(),
57
+ transformPermalink: jest.fn(),
58
+ transformPath: jest.fn(),
59
+ } as PublicationTransformer
60
+ mockConfig = { getEditor: jest.fn(() => editor), publicationTransformers: [transformer] } as unknown as ClientConfig
61
+ editor.getModel().set('config', mockConfig)
62
+ })
63
+
64
+ it('should transform components', () => {
65
+ const renderComponent = transformer.renderComponent as Mock
66
+ renderComponent.mockReturnValue('mockHtml')
67
+ renderComponents(editor)
68
+ const html = editor.getHtml()
69
+ expect(renderComponent).toBeCalledTimes(6)
70
+ const results = renderComponent.mock.calls.map(call => call[0] as Component)
71
+ const parent = results.find(c => c.getClasses()[0] === 'parent')
72
+ expect(parent).not.toBeUndefined()
73
+ const child = results.find(c => c.getClasses()[0] === 'child')
74
+ expect(child).not.toBeUndefined()
75
+ })
76
+
77
+ it('should reset transformed pages', () => {
78
+ const renderComponent = transformer.renderComponent as Mock
79
+ renderComponent.mockReturnValue('mockHtml')
80
+ renderComponents(editor)
81
+ resetRenderComponents(editor)
82
+ const html = editor.getHtml()
83
+ expect(renderComponent).toBeCalledTimes(0)
84
+ expect(html).toContain('Hello world')
85
+ })
86
+
87
+ it('should transform styles', () => {
88
+ const transformCssRule = transformer.renderCssRule as Mock
89
+ transformCssRule.mockImplementation((rule: any) => {
90
+ return { color: 'test'+rule.color } as StyleProps
91
+ })
92
+ renderCssRules(editor)
93
+ const css = editor.getCss()
94
+ expect(transformCssRule).toBeCalledTimes(2)
95
+ const results = transformCssRule.mock.results.map(r => r.value as StyleProps)
96
+ const parent = results.find(c => c.color === 'testred')
97
+ expect(parent).not.toBeUndefined()
98
+ const child = results.find(c => c.color === 'testblue')
99
+ expect(child).not.toBeUndefined()
100
+ expect(css).toContain('color:test')
101
+ expect(css).not.toContain('color:blue')
102
+ })
103
+
104
+ it('should reset transformed styles', () => {
105
+ const renderCssRule = transformer.renderCssRule as Mock
106
+ const returned = {color: 'test'} as StyleProps
107
+ renderCssRule.mockReturnValue(returned)
108
+ renderCssRules(editor)
109
+ resetRenderCssRules(editor)
110
+ const css = editor.getCss()
111
+ expect(renderCssRule).toBeCalledTimes(0)
112
+ expect(css).toContain('color:blue')
113
+ })
114
+
115
+ it('should transform files', () => {
116
+ const transformFile = transformer.transformFile as Mock
117
+ const returned = {path: 'test path changed', content: 'test content changed'} as ClientSideFile
118
+ transformFile.mockReturnValue(returned)
119
+ expect(mockData.files?.length).toBe(1)
120
+ if (mockData.files?.length) { // To avoid ! operator on mockData.files and make the lint happy
121
+ expect(mockData.files[0]).toBe(mockFile)
122
+ transformFiles(editor, mockData)
123
+ expect(transformFile).toBeCalledTimes(1)
124
+ expect(mockData.files[0]).toBe(returned)
125
+ }
126
+ })
127
+ it('should transform permalinks of images src', () => {
128
+ editor.addComponents(`
129
+ <img src="test.png">
130
+ `)
131
+ const transformPermalink = transformer.transformPermalink as Mock
132
+ const transformedSrc = 'transformed.png'
133
+ transformPermalink.mockReturnValue(transformedSrc)
134
+ renderComponents(editor)
135
+ const html = editor.getHtml()
136
+ expect(transformPermalink).toBeCalledTimes(2) // 2x because of c.attributes.src and c.attributes.attributes.src
137
+ expect(transformPermalink.mock.calls[0][0]).toBe('test.png')
138
+ expect(transformPermalink.mock.calls[0][1]).toBe('asset')
139
+ })
140
+
141
+ it('should transform a style rule with background image', () => {
142
+ expect(transformBgImage(editor, { 'background-image': 'url(test.png)' })).toEqual({ 'background-image': 'url(test.png)' })
143
+ const transformPermalink = transformer.transformPermalink as Mock
144
+ const transformedSrc = 'transformed.png'
145
+ const transformedSrc2 = 'transformed2.png'
146
+ transformPermalink.mockImplementation((url, type) => (url as string).replace('test.png', transformedSrc).replace('test2.png', transformedSrc2))
147
+ expect(transformBgImage(editor, { 'background-image': 'url(test.png)' })).toEqual({ 'background-image': `url(${transformedSrc})` })
148
+ expect(transformBgImage(editor, { 'background-image': 'url("test.png")' })).toEqual({ 'background-image': `url(${transformedSrc})` })
149
+ expect(transformBgImage(editor, {
150
+ 'background-image': 'linear-gradient(to right, rgb(30 75 115 / 100%), url(test.png), linear-gradient(to left, rgb(30 75 115 / 10%), url(test2.png), rgb(255 255 255 / 0%));',
151
+ })).toEqual({
152
+ 'background-image': `linear-gradient(to right, rgb(30 75 115 / 100%), url(${transformedSrc}), linear-gradient(to left, rgb(30 75 115 / 10%), url(${transformedSrc2}), rgb(255 255 255 / 0%));`,
153
+ })
154
+ })
155
+
156
+ it('should transform permalinks of background images in inline css', () => {
157
+ const el = document.createElement('div')
158
+ const [comp] = editor.addComponents(el)
159
+ comp.setStyle({ 'background-image': 'url(test.png)' })
160
+ //editor.addComponents(`
161
+ // <div style="color: black; background-image: url(test.png);"></div>
162
+ //`)
163
+ const transformPermalink = transformer.transformPermalink as Mock
164
+ const transformedSrc = 'transformed.png'
165
+ transformPermalink.mockReturnValue(transformedSrc)
166
+ renderComponents(editor)
167
+ const css = editor.getCss()
168
+ expect(transformPermalink).toBeCalledTimes(1)
169
+ expect(transformPermalink.mock.calls[0][0]).toBe('test.png')
170
+ expect(transformPermalink.mock.calls[0][1]).toBe('asset')
171
+ expect(css).toContain('url(test.png)')
172
+ })
173
+ it('should transform permalinks of background images in styles', () => {
174
+ editor.addComponents(`
175
+ <div class="test"></div>
176
+ `)
177
+ editor.addStyle(`
178
+ .test {
179
+ background-image: url(test.png);
180
+ }
181
+ `)
182
+ const transformPermalink = transformer.transformPermalink as Mock
183
+ const transformedSrc = 'transformed.png'
184
+ transformPermalink.mockReturnValue(transformedSrc)
185
+ renderCssRules(editor)
186
+ const css = editor.getCss()
187
+ expect(transformPermalink).toBeCalledTimes(1)
188
+ expect(transformPermalink.mock.calls[0][0]).toBe('test.png')
189
+ expect(transformPermalink.mock.calls[0][1]).toBe('asset')
190
+ expect(css).toContain(`url(${transformedSrc})`)
191
+ })
192
+ it('should transform links to pages to match permalinks ', () => {
193
+ editor.addComponents(`
194
+ <a href="./index.html">test</a>
195
+ `)
196
+ const transformPermalink = transformer.transformPermalink as Mock
197
+ const transformedPermalink = './transformed-page.html'
198
+ transformPermalink.mockReturnValue(transformedPermalink)
199
+ renderComponents(editor)
200
+ const html = editor.getHtml()
201
+ expect(transformPermalink).toBeCalledTimes(1)
202
+ expect((transformPermalink.mock.calls[0][0])).toBe('./index.html')
203
+ expect((transformPermalink.mock.calls[0][1])).toBe(ClientSideFileType.HTML)
204
+ expect(html).not.toContain('href="./index.html"')
205
+ expect(html).toContain(`href="${transformedPermalink}"`)
206
+ })
207
+ })
@@ -0,0 +1,280 @@
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 { Component, CssRule, StyleProps, Editor } from 'grapesjs'
19
+ import { ClientSideFile, ClientSideFileType, Initiator, PublicationData } from '../types'
20
+ import { onAll } from './utils'
21
+
22
+ /**
23
+ * @fileoverview Silex publication transformers are used to control how the site is rendered and published
24
+ * Here we call path the path on the connector (either storage or hosting)
25
+ * We call permalink the path at which the resource is served
26
+ * This is where pages and assets paths and permalinks are set
27
+ * Here we also update background images urls, assets url and links to match the new permalinks
28
+ */
29
+
30
+ // Properties names used to store the original methods on the components and styles
31
+ const ATTRIBUTE_METHOD_STORE_HTML = 'tmp-pre-publication-transformer-tohtml'
32
+ const ATTRIBUTE_METHOD_STORE_SRC = 'tmp-pre-publication-transformer-src'
33
+ const ATTRIBUTE_METHOD_STORE_ATTRIBUTES_SRC = 'tmp-pre-publication-transformer-attributes-src'
34
+ const ATTRIBUTE_METHOD_STORE_INLINE_CSS = 'tmp-pre-publication-transformer-inline-css'
35
+ const ATTRIBUTE_METHOD_STORE_HREF = 'tmp-pre-publication-transformer-href'
36
+ const ATTRIBUTE_METHOD_STORE_CSS = 'tmp-pre-publication-transformer-tocss'
37
+
38
+ /**
39
+ * Interface for publication transformers
40
+ * They are added to the config object with config.addPublicationTransformer()
41
+ */
42
+ export interface PublicationTransformer {
43
+ // Temporarily override how components render at publication by grapesjs
44
+ renderComponent?(component: Component, toHtml: () => string): string | undefined
45
+ // Temporarily override how styles render at publication by grapesjs
46
+ renderCssRule?(rule: CssRule, initialRule: () => StyleProps): StyleProps | undefined
47
+ // Transform files after they are rendered and before they are published
48
+ transformFile?(file: ClientSideFile): ClientSideFile
49
+ // Define files URLs
50
+ transformPermalink?(link: string, type: ClientSideFileType, initiator: Initiator): string
51
+ // Define where files are published
52
+ transformPath?(path: string, type: ClientSideFileType): string
53
+ }
54
+
55
+ export const publicationTransformerDefault: PublicationTransformer = {
56
+ // Override how components render at publication by grapesjs
57
+ renderComponent(component: Component, toHtml: () => string): string | undefined {
58
+ return toHtml()
59
+ },
60
+ // Override how styles render at publication by grapesjs
61
+ renderCssRule(rule: CssRule, initialRule: () => StyleProps): StyleProps | undefined {
62
+ return initialRule()
63
+ },
64
+ // Define where files are published
65
+ transformPath(path: string, type: ClientSideFileType): string {
66
+ return path
67
+ },
68
+ // Define files URLs
69
+ transformPermalink(link: string, type: ClientSideFileType, initiator: Initiator): string {
70
+ switch(initiator) {
71
+ case Initiator.HTML:
72
+ return link
73
+ case Initiator.CSS:
74
+ // In case of a link from a CSS file, we need to go up one level
75
+ return `../${link.replace(/^\//, '')}`
76
+ default:
77
+ throw new Error(`Unknown initiator ${initiator}`)
78
+ }
79
+ },
80
+ // Define how files are named
81
+ transformFile(file: ClientSideFile): ClientSideFile {
82
+ return file
83
+ }
84
+ }
85
+
86
+ export function validatePublicationTransformer(transformer: PublicationTransformer): void {
87
+ // List all the properties
88
+ const allowedProperties = [
89
+ 'renderComponent',
90
+ 'renderCssRule',
91
+ 'transformFile',
92
+ 'transformPermalink',
93
+ 'transformPath',
94
+ ]
95
+
96
+ // Check that there are no unknown properties
97
+ Object.keys(transformer).forEach(key => {
98
+ if(!allowedProperties.includes(key)) {
99
+ throw new Error(`Publication transformer: unknown property ${key}`)
100
+ }
101
+ })
102
+
103
+ // Check that the methods are functions
104
+ allowedProperties.forEach(key => {
105
+ if(typeof transformer[key] !== 'function' && transformer[key] !== undefined) {
106
+ throw new Error(`Publication transformer: ${key} must be a function`)
107
+ }
108
+ })
109
+ }
110
+
111
+ /**
112
+ * Alter the components rendering
113
+ * Exported for unit tests
114
+ */
115
+ export function renderComponents(editor: Editor) {
116
+ const config = editor.getModel().get('config')
117
+ onAll(editor, (c: Component) => {
118
+ if (c.get(ATTRIBUTE_METHOD_STORE_HTML)) {
119
+ console.warn('Publication transformer: HTML transform already altered', c)
120
+ } else {
121
+ const initialToHTML = c.toHTML.bind(c)
122
+ c[ATTRIBUTE_METHOD_STORE_HTML] = c.toHTML
123
+ const initialGetStyle = c.getStyle.bind(c)
124
+ c[ATTRIBUTE_METHOD_STORE_INLINE_CSS] = c.getStyle
125
+ const href = c.get('attributes').href as string | undefined
126
+ if(href?.startsWith('./')) {
127
+ c[ATTRIBUTE_METHOD_STORE_HREF] = href
128
+ c.set('attributes', {
129
+ ...c.get('attributes'),
130
+ href: transformPermalink(editor, href, ClientSideFileType.HTML, Initiator.HTML),
131
+ })
132
+ }
133
+ // Handle both c.attributes.src and c.attributes.attributes.src
134
+ // For some reason we need both
135
+ // Especially when the component is not on the current page, we need c.attributes.attributes.src
136
+ if(c.get('attributes').src) {
137
+ c[ATTRIBUTE_METHOD_STORE_SRC] = c.get('attributes').src
138
+ const src = transformPermalink(editor, c.get('attributes').src, ClientSideFileType.ASSET, Initiator.HTML)
139
+ c.set('attributes', {
140
+ ...c.get('attributes'),
141
+ src,
142
+ })
143
+ }
144
+ if(c.get('src')) {
145
+ c[ATTRIBUTE_METHOD_STORE_ATTRIBUTES_SRC] = c.get('src')
146
+ const src = transformPermalink(editor, c.get('src'), ClientSideFileType.ASSET, Initiator.HTML)
147
+ c.set('src', src)
148
+ }
149
+ c.toHTML = () => {
150
+ return config.publicationTransformers.reduce((html: string, transformer: PublicationTransformer) => {
151
+ return transformer.renderComponent ? transformer.renderComponent(c, () => html) ?? html : html
152
+ }, initialToHTML())
153
+ }
154
+ c.getStyle = () => transformBgImage(editor, initialGetStyle())
155
+ }
156
+ })
157
+ }
158
+
159
+ /**
160
+ * Alter the styles rendering
161
+ * Exported for unit tests
162
+ */
163
+ export function renderCssRules(editor: Editor) {
164
+ const config = editor.getModel().get('config')
165
+ editor.Css.getAll().forEach((style: CssRule) => {
166
+ if (style[ATTRIBUTE_METHOD_STORE_CSS]) {
167
+ console.warn('Publication transformer: CSS transform already altered', style)
168
+ } else {
169
+ const initialGetStyle = style.getStyle.bind(style)
170
+ style[ATTRIBUTE_METHOD_STORE_CSS] = style.getStyle
171
+ style.getStyle = () => {
172
+ const initialStyle = transformBgImage(editor, initialGetStyle())
173
+ const result = config.publicationTransformers.reduce((s: CssRule, transformer: PublicationTransformer) => {
174
+ return {
175
+ ...transformer.renderCssRule ? transformer.renderCssRule(s, () => initialStyle) ?? s : s,
176
+ }
177
+ }, initialStyle)
178
+ return result
179
+ }
180
+ }
181
+ })
182
+ }
183
+
184
+ function doTransformPermalink(editor: Editor, cssValue: string): string {
185
+ return cssValue.replace(/url\(([^)]+)\)/g, (match, url) => {
186
+ // Support URLs with or without quotes
187
+ const cleanUrl = url.replace(/['"]/g, '')
188
+ // Transform URLs
189
+ const newUrl = transformPermalink(editor, cleanUrl, ClientSideFileType.ASSET, Initiator.CSS)
190
+ // Return the new URL with url keyword
191
+ return `url(${newUrl})`
192
+ })
193
+ }
194
+
195
+ /**
196
+ * Transform background image url according to the transformed path of assets
197
+ */
198
+ export function transformBgImage(editor: Editor, style: StyleProps): StyleProps {
199
+ const cssValue = style['background-image']
200
+ if (cssValue) {
201
+ const newCssValue = typeof cssValue === 'string' ? doTransformPermalink(editor, cssValue) : cssValue.map(value => doTransformPermalink(editor, value))
202
+ return {
203
+ ...style,
204
+ 'background-image': newCssValue,
205
+ }
206
+ }
207
+ return style
208
+ }
209
+
210
+ /**
211
+ * Transform files
212
+ * Exported for unit tests
213
+ */
214
+ export function transformFiles(editor: Editor, data: PublicationData) {
215
+ const config = editor.getModel().get('config')
216
+ data.files = config.publicationTransformers.reduce((files: ClientSideFile[], transformer: PublicationTransformer) => {
217
+ return files.map((file, idx) => {
218
+ const page = data.pages[idx] ?? null
219
+ return transformer.transformFile ? transformer.transformFile(file) as ClientSideFile ?? file : file
220
+ })
221
+ }, data.files)
222
+ }
223
+
224
+ /**
225
+ * Transform files paths
226
+ * Exported for unit tests
227
+ */
228
+ export function transformPermalink(editor: Editor, path: string, type: ClientSideFileType, initiator: Initiator): string {
229
+ const config = editor.getModel().get('config')
230
+ return config.publicationTransformers.reduce((result: string, transformer: PublicationTransformer) => {
231
+ return transformer.transformPermalink ? transformer.transformPermalink(result, type, initiator) ?? result : result
232
+ }, path)
233
+ }
234
+
235
+ export function transformPath(editor: Editor, path: string, type: ClientSideFileType): string {
236
+ const config = editor.getModel().get('config')
237
+ return config.publicationTransformers.reduce((result: string, transformer: PublicationTransformer) => {
238
+ return transformer.transformPath ? transformer.transformPath(result, type) ?? result : result
239
+ }, path)
240
+ }
241
+
242
+ export function resetRenderComponents(editor: Editor) {
243
+ onAll(editor, (c: Component) => {
244
+ if (c[ATTRIBUTE_METHOD_STORE_HTML]) {
245
+ c.toHTML = c[ATTRIBUTE_METHOD_STORE_HTML]
246
+ delete c[ATTRIBUTE_METHOD_STORE_HTML]
247
+ }
248
+ if (c[ATTRIBUTE_METHOD_STORE_INLINE_CSS]) {
249
+ c.getStyle = c[ATTRIBUTE_METHOD_STORE_INLINE_CSS]
250
+ delete c[ATTRIBUTE_METHOD_STORE_INLINE_CSS]
251
+ }
252
+ if(c[ATTRIBUTE_METHOD_STORE_SRC]) {
253
+ c.set('attributes', {
254
+ ...c.get('attributes'),
255
+ src: c[ATTRIBUTE_METHOD_STORE_SRC],
256
+ })
257
+ delete c[ATTRIBUTE_METHOD_STORE_SRC]
258
+ }
259
+ if(c[ATTRIBUTE_METHOD_STORE_ATTRIBUTES_SRC]) {
260
+ c.set('src', c[ATTRIBUTE_METHOD_STORE_ATTRIBUTES_SRC])
261
+ delete c[ATTRIBUTE_METHOD_STORE_ATTRIBUTES_SRC]
262
+ }
263
+ if(c[ATTRIBUTE_METHOD_STORE_HREF]) {
264
+ c.set('attributes', {
265
+ ...c.get('attributes'),
266
+ href: c[ATTRIBUTE_METHOD_STORE_HREF],
267
+ })
268
+ delete c[ATTRIBUTE_METHOD_STORE_HREF]
269
+ }
270
+ })
271
+ }
272
+
273
+ export function resetRenderCssRules(editor: Editor) {
274
+ editor.Css.getAll().forEach(c => {
275
+ if (c[ATTRIBUTE_METHOD_STORE_CSS]) {
276
+ c.getStyle = c[ATTRIBUTE_METHOD_STORE_CSS]
277
+ delete c[ATTRIBUTE_METHOD_STORE_CSS]
278
+ }
279
+ })
280
+ }
@@ -14,12 +14,18 @@
14
14
  * You should have received a copy of the GNU Affero General Public License
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  */
17
- // Browse all elements of all pages
18
- export function onAll(editor, cbk) {
19
- editor.Pages.getAll()
20
- .forEach(page => {
21
- page.getMainComponent()
22
- .onAll(c => cbk(c));
23
- });
17
+
18
+ /**
19
+ * @fileoverview Make sure custom script blocks include script tags when published
20
+ */
21
+
22
+ export default async function (config) {
23
+ config.addPublicationTransformers({
24
+ renderComponent(component, toHtml) {
25
+ if (component.get('type') === 'custom-code' && component.get('custom-code-plugin__code')) {
26
+ return component.get('custom-code-plugin__code')
27
+ }
28
+ return toHtml()
29
+ },
30
+ })
24
31
  }
25
- //# sourceMappingURL=utils.js.map