@silexlabs/silex 3.0.1-alpha.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.
- package/.env.default +20 -0
- package/.silex.js +67 -8
- package/LICENSE +661 -203
- package/README.md +37 -35
- package/dist/client/client/api.d.ts +90 -0
- package/dist/client/client/assetUrl.d.ts +54 -0
- package/dist/client/client/config.d.ts +102 -0
- package/dist/client/client/events.d.ts +23 -0
- package/dist/client/client/expose.d.ts +8 -0
- package/dist/client/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/client/client/grapesjs/PublicationManager.d.ts +73 -0
- package/dist/client/client/grapesjs/PublicationUi.d.ts +59 -0
- package/dist/client/client/grapesjs/blocks.d.ts +1 -0
- package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/client/grapesjs/img.d.ts +6 -0
- package/dist/client/client/grapesjs/index.d.ts +9 -0
- package/dist/client/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/client/client/grapesjs/openImport.d.ts +9 -0
- package/dist/client/client/grapesjs/page-panel.d.ts +9 -0
- package/dist/client/client/grapesjs/project-bar.d.ts +21 -0
- package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/client/grapesjs/rich-text.d.ts +4 -0
- package/dist/client/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/client/grapesjs/settings.d.ts +4 -0
- package/dist/client/client/grapesjs/storage.d.ts +2 -0
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/client/index.d.ts +10 -0
- package/dist/client/client/publication-transformers.d.ts +42 -0
- package/dist/client/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/client/publish-fonts.d.ts +4 -0
- package/dist/client/client/utils.d.ts +22 -0
- package/dist/client/constants.d.ts +32 -0
- package/dist/client/css/admin.css +1114 -328
- package/dist/client/css/admin.css.map +1 -0
- package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
- package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
- package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
- package/dist/client/index.html +3 -2
- package/dist/client/js/main.js +356 -131
- package/dist/client/js/main.js.LICENSE.txt +15 -1
- package/dist/client/page.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
- package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
- package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
- package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
- package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
- package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
- package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
- package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
- package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
- package/dist/client/types.d.ts +339 -0
- package/dist/plugins/client/client/events.d.ts +23 -0
- package/dist/plugins/client/client/events.js +43 -0
- package/dist/plugins/client/client/events.js.map +1 -0
- package/dist/plugins/client/plugins/client/template.d.ts +2 -0
- package/dist/plugins/client/plugins/client/template.js +234 -0
- package/dist/plugins/client/plugins/client/template.js.map +1 -0
- package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
- package/dist/plugins/client/plugins/client/website-info.js +72 -0
- package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
- package/dist/plugins/client/types.d.ts +339 -0
- package/dist/plugins/client/types.js +80 -0
- package/dist/plugins/client/types.js.map +1 -0
- package/dist/plugins/server/constants.d.ts +32 -0
- package/dist/plugins/server/constants.js +76 -0
- package/dist/plugins/server/constants.js.map +1 -0
- package/dist/plugins/server/plugins/server/Cache.d.ts +2 -0
- package/dist/plugins/server/plugins/server/Cache.js +36 -0
- package/dist/plugins/server/plugins/server/Cache.js.map +1 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/FtpConnector.d.ts +86 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js +536 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +135 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +649 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.d.ts +0 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.js +14 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.js.map +1 -0
- package/dist/plugins/server/plugins/server/SslPlugin.d.ts +1 -0
- package/dist/plugins/server/plugins/server/SslPlugin.js +86 -0
- package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js +45 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -0
- package/dist/plugins/server/server/config.d.ts +59 -0
- package/dist/plugins/server/server/config.js +181 -0
- package/dist/plugins/server/server/config.js.map +1 -0
- package/dist/plugins/server/server/connectors/FsHosting.d.ts +14 -0
- package/dist/plugins/server/server/connectors/FsHosting.js +66 -0
- package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -0
- package/dist/plugins/server/server/connectors/FsStorage.d.ts +44 -0
- package/dist/plugins/server/server/connectors/FsStorage.js +261 -0
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -0
- package/dist/plugins/server/server/connectors/connectors.d.ts +86 -0
- package/dist/plugins/server/server/connectors/connectors.js +126 -0
- package/dist/plugins/server/server/connectors/connectors.js.map +1 -0
- package/dist/plugins/server/server/events.d.ts +26 -0
- package/dist/plugins/server/server/events.js +31 -0
- package/dist/plugins/server/server/events.js.map +1 -0
- package/dist/plugins/server/server/jobs.d.ts +12 -0
- package/dist/plugins/server/server/jobs.js +79 -0
- package/dist/plugins/server/server/jobs.js.map +1 -0
- package/dist/plugins/server/server/utils/validation.d.ts +7 -0
- package/dist/plugins/server/server/utils/validation.js +37 -0
- package/dist/plugins/server/server/utils/validation.js.map +1 -0
- package/dist/plugins/server/types.d.ts +339 -0
- package/dist/plugins/server/types.js +84 -0
- package/dist/plugins/server/types.js.map +1 -0
- package/dist/server/constants.js +55 -0
- package/dist/server/plugins/server/Cache.js +19 -0
- package/dist/server/server/api/api.js +20 -0
- package/dist/server/server/api/connectorApi.js +334 -0
- package/dist/server/server/api/publicationApi.js +106 -0
- package/dist/server/server/api/websiteApi.js +315 -0
- package/dist/server/server/cli.js +71 -0
- package/dist/server/server/config.js +120 -0
- package/dist/server/server/connectors/FsHosting.js +47 -0
- package/dist/server/server/connectors/FsStorage.js +228 -0
- package/dist/server/server/connectors/connectors.js +88 -0
- package/dist/server/server/events.js +14 -0
- package/dist/server/server/expose.js +27 -0
- package/dist/server/server/express.js +46 -0
- package/dist/server/server/index.js +94 -0
- package/dist/server/server/jobs.js +50 -0
- package/dist/server/server/utils/validation.js +14 -0
- package/dist/server/types.js +40 -0
- package/package.json +99 -49
- package/public/assets/download.png +0 -0
- package/public/assets/favicon.ico +0 -0
- package/public/assets/favicon.png +0 -0
- package/public/assets/ftp.png +0 -0
- package/public/assets/gitlab.png +0 -0
- package/public/assets/gitlab2.png +0 -0
- package/public/assets/laptop.png +0 -0
- package/public/assets/logo-silex-small.png +0 -0
- package/public/silex.js +22 -23
- package/src/css/_variables.scss +24 -20
- package/src/css/dialog.scss +35 -2
- package/src/css/fonts.scss +31 -0
- package/src/css/footer.scss +12 -0
- package/src/css/grapesjs-light.scss +180 -0
- package/src/css/grapesjs-plugins.scss +227 -0
- package/src/css/grapesjs.scss +159 -1
- package/src/css/index.scss +12 -1
- package/src/css/light.scss +7 -0
- package/src/css/loader.scss +2 -0
- package/src/css/project-bar.scss +32 -16
- package/src/css/silex.scss +79 -5
- package/src/css/website-info.scss +14 -0
- package/src/html/index.pug +3 -3
- package/src/html/templates/includes.pug +0 -1
- package/src/ts/client/api.ts +156 -0
- package/src/ts/client/assetUrl.test.ts +164 -0
- package/src/ts/client/assetUrl.ts +254 -0
- package/src/ts/client/config.ts +175 -13
- package/src/ts/client/events.ts +43 -0
- package/src/ts/client/expose.ts +27 -1
- package/src/ts/client/grapesjs/LoginDialog.ts +204 -0
- package/src/ts/client/grapesjs/PublicationManager.ts +433 -0
- package/src/ts/client/grapesjs/PublicationUi.ts +366 -0
- package/src/ts/client/grapesjs/blocks.ts +17 -0
- package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
- package/src/ts/client/grapesjs/css-props.ts +910 -0
- package/src/ts/client/grapesjs/eleventy.ts +30 -7
- package/src/ts/client/grapesjs/footer.ts +42 -0
- package/src/ts/client/grapesjs/img.ts +147 -0
- package/src/ts/client/grapesjs/index.ts +311 -122
- package/src/ts/client/grapesjs/internal-links.test.ts +19 -1
- package/src/ts/client/grapesjs/internal-links.ts +31 -7
- package/src/ts/client/grapesjs/keymaps.ts +207 -0
- package/src/ts/client/grapesjs/new-page-dialog.ts +19 -3
- package/src/ts/client/grapesjs/openImport.ts +22 -0
- package/src/ts/client/grapesjs/page-panel.ts +109 -7
- package/src/ts/client/grapesjs/project-bar.ts +133 -72
- package/src/ts/client/grapesjs/resize-panel.ts +20 -0
- package/src/ts/client/grapesjs/rich-text.ts +38 -13
- package/src/ts/client/grapesjs/semantic.ts +20 -3
- package/src/ts/client/grapesjs/settings-sections.ts +117 -0
- package/src/ts/client/grapesjs/settings.ts +191 -96
- package/src/ts/client/grapesjs/storage.ts +187 -0
- package/src/ts/client/grapesjs/symbolDialogs.ts +21 -5
- package/src/ts/client/grapesjs/view-buttons.ts +42 -0
- package/src/ts/client/index.ts +80 -21
- package/src/ts/client/publication-transformers.test.ts +207 -0
- package/src/ts/client/publication-transformers.ts +280 -0
- package/src/ts/client/publish-custom-code-block.ts +31 -0
- package/src/ts/client/publish-fonts.ts +36 -0
- package/src/ts/client/utils.ts +70 -1
- package/src/ts/constants.ts +78 -0
- package/src/ts/externs.ts +17 -0
- package/src/ts/page.ts +20 -3
- package/src/ts/plugins/client/template.ts +246 -0
- package/src/ts/plugins/client/website-info.ts +84 -0
- package/src/ts/plugins/server/Cache.ts +32 -0
- package/src/ts/plugins/server/DownloadConnector.ts +146 -0
- package/src/ts/plugins/server/FtpConnector.test.ts +82 -0
- package/src/ts/plugins/server/FtpConnector.ts +621 -0
- package/src/ts/plugins/server/GitlabConnector.ts +749 -0
- package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
- package/src/ts/plugins/server/PublicationOptimizer.ts +14 -0
- package/src/ts/plugins/server/SslPlugin.ts +84 -0
- package/src/ts/plugins/server/StaticPlugin.ts +45 -0
- package/src/ts/server/api/api.ts +19 -0
- package/src/ts/server/api/connectorApi.ts +464 -0
- package/src/ts/server/api/publicationApi.ts +159 -0
- package/src/ts/server/api/websiteApi.ts +462 -0
- package/src/ts/server/cli.ts +48 -14
- package/src/ts/server/config.ts +158 -60
- package/src/ts/server/connectors/FsHosting.ts +66 -0
- package/src/ts/server/connectors/FsStorage.test.ts +51 -0
- package/src/ts/server/connectors/FsStorage.ts +290 -0
- package/src/ts/server/connectors/connectors.ts +203 -0
- package/src/ts/server/events.ts +37 -0
- package/src/ts/server/expose.ts +19 -0
- package/src/ts/server/express.ts +57 -5
- package/src/ts/server/index.ts +79 -16
- package/src/ts/server/jobs.test.ts +75 -0
- package/src/ts/server/jobs.ts +89 -0
- package/src/ts/server/utils/BackwardCompat.ts +546 -528
- package/src/ts/server/utils/validation.ts +34 -0
- package/src/ts/types.ts +295 -85
- package/.dockerignore +0 -5
- package/.editorconfig +0 -14
- package/.eslintrc.json +0 -43
- package/.github/FUNDING.yml +0 -13
- package/.github/workflows/docker-hub-publish.yml +0 -36
- package/.github/workflows/npm-publish.yml +0 -19
- package/.github/workflows/test.yml +0 -26
- package/.nvmrc +0 -1
- package/.silex/default/.silex.data.json +0 -1
- package/CODE_OF_CONDUCT.md +0 -128
- package/CONTRIBUTING.md +0 -131
- package/Dockerfile +0 -15
- package/directus.silex.js +0 -7
- package/dist/constants.js +0 -4
- package/dist/events.js +0 -5
- package/dist/page.js +0 -15
- package/dist/server/cli.js +0 -43
- package/dist/server/config.js +0 -70
- package/dist/server/express.js +0 -18
- package/dist/server/index.js +0 -58
- package/dist/types.js +0 -34
- package/jest.config.js +0 -10
- package/logos/logo_by_ceubri/silex-icon-2018@200px.png +0 -0
- package/logos/logo_by_ceubri/silex-icon-2018@4x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white-transp.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@0.5x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@0.75x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@4x.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@4x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.ai +5 -2521
- package/logos/logo_by_ceubri/silex-logo-2018.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@0.5x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@0.75x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@4x.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@4x.png +0 -0
- package/logos/silexlabs.png +0 -0
- package/src/example-client-config.js +0 -47
- package/src/plugins/AuthPlugin.js +0 -21
- package/src/plugins/Cache.js +0 -11
- package/src/plugins/DefaultBackend.js +0 -149
- package/src/plugins/ExpressPlugin.js +0 -39
- package/src/plugins/HooksPlugin.js +0 -58
- package/src/plugins/PublishPlugin.js +0 -69
- package/src/plugins/SslPlugin.js +0 -66
- package/src/plugins/StaticPlugin.js +0 -48
- package/src/plugins/WebsitePlugin.js +0 -207
- package/src/ts/client/grapesjs/publish.ts +0 -386
- package/src/ts/client/grapesjs/template.ts +0 -166
- package/src/ts/events.ts +0 -2
- package/tsconfig-server-debug.json +0 -19
- package/tsconfig-server-release.json +0 -19
- package/tsconfig.jest.json +0 -9
- package/tsconfig.json +0 -26
- package/webpack.config.js +0 -28
- package/webpack.debug.config.js +0 -8
package/src/ts/client/index.ts
CHANGED
|
@@ -1,25 +1,51 @@
|
|
|
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
|
+
|
|
1
18
|
/**
|
|
2
19
|
* @fileoverview
|
|
3
20
|
* Defines the entry point of Silex client side application
|
|
4
21
|
*
|
|
5
22
|
*/
|
|
6
23
|
|
|
7
|
-
import {
|
|
24
|
+
import { DEV_MESSAGE } from '../constants'
|
|
25
|
+
import { ClientConfig } from './config'
|
|
26
|
+
import { ClientEvent } from './events'
|
|
8
27
|
import { initEditor, getEditor } from './grapesjs/index'
|
|
9
|
-
import {
|
|
28
|
+
import { cmdPauseAutoSave } from './grapesjs/storage'
|
|
29
|
+
|
|
30
|
+
// Expose API to calling app as window.silex
|
|
31
|
+
export * from './expose'
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Expose the config object
|
|
35
|
+
*/
|
|
36
|
+
export let config: ClientConfig
|
|
10
37
|
|
|
11
38
|
/**
|
|
12
39
|
* Start Silex, called from host HTML page with window.silex.start()
|
|
13
40
|
*/
|
|
14
|
-
export async function start(options = {}) {
|
|
15
|
-
|
|
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()
|
|
16
46
|
Object.assign(config, options)
|
|
17
47
|
|
|
18
|
-
// Config file in root folder which
|
|
19
|
-
console.log('Loading config', config.clientConfigUrl)
|
|
20
|
-
//import(/* webpackIgnore: true */ config.clientConfigUrl)
|
|
21
|
-
//.then((configFile) => console.log('Config loaded', configFile))
|
|
22
|
-
//.catch((e) => console.error('Config error', config.clientConfigUrl, e))
|
|
48
|
+
// Config file in root folder which may be generated by the server
|
|
23
49
|
await config.addPlugin(config.clientConfigUrl, {})
|
|
24
50
|
|
|
25
51
|
// Debug mode
|
|
@@ -28,24 +54,57 @@ export async function start(options = {}) {
|
|
|
28
54
|
}
|
|
29
55
|
|
|
30
56
|
// Notify plugins that loading is over and Silex is starting
|
|
31
|
-
config.emit(
|
|
57
|
+
config.emit(ClientEvent.STARTUP_START)
|
|
58
|
+
|
|
59
|
+
// Init GrapesJS config which depend on the config file properties
|
|
60
|
+
config.initGrapesConfig()
|
|
32
61
|
|
|
33
62
|
// Start grapesjs
|
|
34
|
-
|
|
63
|
+
// Here you can change the config before passing it to grapesjs
|
|
64
|
+
config.emit(ClientEvent.GRAPESJS_START)
|
|
35
65
|
try{
|
|
36
|
-
initEditor(config.
|
|
66
|
+
await initEditor(config.grapesJsConfig)
|
|
37
67
|
} catch(e) {
|
|
38
68
|
console.error('Error starting Silex', e)
|
|
69
|
+
throw e
|
|
39
70
|
}
|
|
40
71
|
|
|
72
|
+
const editor = getEditor()
|
|
73
|
+
|
|
74
|
+
// Store the config in the editor
|
|
75
|
+
editor.getModel().set('config', config)
|
|
76
|
+
|
|
77
|
+
// Notify plugins
|
|
78
|
+
config.emit(ClientEvent.GRAPESJS_END, { editor })
|
|
79
|
+
|
|
41
80
|
// Init internationalization module
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
81
|
+
editor.I18n.setLocale(config.lang)
|
|
82
|
+
|
|
83
|
+
// Add default plugins
|
|
84
|
+
await config.addDefaultPlugins()
|
|
85
|
+
|
|
86
|
+
// Load the site
|
|
87
|
+
try {
|
|
88
|
+
editor.runCommand(cmdPauseAutoSave)
|
|
89
|
+
await editor.load(null)
|
|
90
|
+
editor.once('canvas:frame:load', () => editor.stopCommand(cmdPauseAutoSave))
|
|
91
|
+
} catch(e) {
|
|
92
|
+
if(e.httpStatusCode === 401) {
|
|
93
|
+
// Unauthorized, will try to login
|
|
94
|
+
} else {
|
|
95
|
+
// Will display an error message, see in storage.ts
|
|
96
|
+
}
|
|
97
|
+
} finally {
|
|
98
|
+
if(editor.getModel().getCurrentFrame().loaded) {
|
|
99
|
+
loaded(editor)
|
|
100
|
+
} else {
|
|
101
|
+
editor.once('canvas:frame:load', () => loaded(editor))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
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 })
|
|
51
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
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
/**
|
|
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
|
+
})
|
|
31
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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 { ClientSideFile, ClientSideFileType, ClientSideFileWithContent } from '../types'
|
|
19
|
+
import { cmdGetHtml } from '@silexlabs/grapesjs-fonts/src/commands'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @fileoverview Make sure custom script blocks include script tags when published
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export default async function (config) {
|
|
26
|
+
config.addPublicationTransformers({
|
|
27
|
+
transformFile(file: ClientSideFile): ClientSideFile {
|
|
28
|
+
const fileWithContent = file as ClientSideFileWithContent
|
|
29
|
+
if(fileWithContent.type === ClientSideFileType.HTML && fileWithContent.content) {
|
|
30
|
+
const htmlLinks = config.getEditor().runCommand(cmdGetHtml)
|
|
31
|
+
fileWithContent.content = fileWithContent.content.replace(/<\/head>/, `${htmlLinks}</head>`)
|
|
32
|
+
}
|
|
33
|
+
return file
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
}
|