@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/html/index.pug
CHANGED
|
@@ -12,7 +12,7 @@ html(lang="en", translate="no")
|
|
|
12
12
|
style.
|
|
13
13
|
body {
|
|
14
14
|
background-color: #444444;
|
|
15
|
-
font-family: Helvetica,sans-serif;
|
|
15
|
+
font-family: "Ubuntu", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
16
16
|
}
|
|
17
17
|
.silex-loader {
|
|
18
18
|
display: none;
|
|
@@ -34,6 +34,6 @@ html(lang="en", translate="no")
|
|
|
34
34
|
script(src='js/main.js')
|
|
35
35
|
|
|
36
36
|
block silex-start
|
|
37
|
-
// Here you can use silex.config to hook into silex options before silex starts
|
|
38
37
|
script.
|
|
39
|
-
|
|
38
|
+
silex.start()
|
|
39
|
+
// From here silex.config is available and Silex is getting started
|
|
@@ -0,0 +1,156 @@
|
|
|
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 { API_CONNECTOR_LIST, API_CONNECTOR_USER, API_CONNECTOR_LOGOUT, API_CONNECTOR_PATH, API_PATH, API_PUBLICATION_PATH, API_PUBLICATION_PUBLISH, API_PUBLICATION_STATUS, API_WEBSITE_ASSET_READ, API_WEBSITE_ASSETS_WRITE, API_WEBSITE_DELETE, API_WEBSITE_LIST, API_WEBSITE_PATH, API_WEBSITE_READ, API_WEBSITE_WRITE, API_WEBSITE_META_READ, API_WEBSITE_META_WRITE, API_WEBSITE_CREATE, API_WEBSITE_DUPLICATE } from '../constants'
|
|
19
|
+
import { ApiPublicationPublishBody, ApiPublicationPublishQuery, ApiPublicationPublishResponse, ApiPublicationStatusQuery, ApiPublicationStatusResponse, ConnectorId, JobData, JobId, PublicationJobData, WebsiteId, ApiConnectorListResponse, ApiConnectorListQuery, ConnectorData, ConnectorType, ApiWebsiteReadQuery, ApiWebsiteReadResponse, WebsiteData, ApiWebsiteWriteQuery, ApiWebsiteWriteBody, ApiWebsiteWriteResponse, ApiWebsiteDeleteQuery, ApiWebsiteAssetsReadQuery, ApiWebsiteAssetsReadResponse, ApiWebsiteAssetsWriteQuery, ApiWebsiteAssetsWriteBody, ApiWebsiteAssetsWriteResponse, ClientSideFile, PublicationData, ApiConnectorUserResponse, ConnectorUser, WebsiteMeta, ApiConnectorLogoutQuery, ApiConnectorUserQuery, ApiWebsiteListResponse, ApiWebsiteListQuery, WebsiteMetaFileContent, ApiWebsiteCreateQuery, ApiWebsiteCreateBody, ApiWebsiteCreateResponse, ApiWebsiteMetaWriteQuery, ApiWebsiteMetaWriteBody, ApiWebsiteMetaWriteResponse, ApiWebsiteMetaReadQuery, ApiWebsiteMetaReadResponse, ConnectorOptions, ApiError, ApiWebsiteDuplicateQuery } from '../types'
|
|
20
|
+
|
|
21
|
+
export enum ApiRoute {
|
|
22
|
+
PUBLICATION_PUBLISH = API_PATH + API_PUBLICATION_PATH + API_PUBLICATION_PUBLISH,
|
|
23
|
+
PUBLICATION_STATUS = API_PATH + API_PUBLICATION_PATH + API_PUBLICATION_STATUS,
|
|
24
|
+
CONNECTOR_USER = API_PATH + API_CONNECTOR_PATH + API_CONNECTOR_USER,
|
|
25
|
+
CONNECTOR_LOGOUT = API_PATH + API_CONNECTOR_PATH + API_CONNECTOR_LOGOUT,
|
|
26
|
+
CONNECTOR_LIST = API_PATH + API_CONNECTOR_PATH + API_CONNECTOR_LIST,
|
|
27
|
+
WEBSITE_READ = API_PATH + API_WEBSITE_PATH + API_WEBSITE_READ,
|
|
28
|
+
WEBSITE_WRITE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_WRITE,
|
|
29
|
+
WEBSITE_DELETE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_DELETE,
|
|
30
|
+
WEBSITE_DUPLICATE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_DUPLICATE,
|
|
31
|
+
WEBSITE_CREATE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_CREATE,
|
|
32
|
+
WEBSITE_LIST = API_PATH + API_WEBSITE_PATH + API_WEBSITE_LIST,
|
|
33
|
+
WEBSITE_ASSETS_READ = API_PATH + API_WEBSITE_PATH + API_WEBSITE_ASSET_READ,
|
|
34
|
+
WEBSITE_ASSETS_WRITE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_ASSETS_WRITE,
|
|
35
|
+
WEBSITE_META_READ = API_PATH + API_WEBSITE_PATH + API_WEBSITE_META_READ,
|
|
36
|
+
WEBSITE_META_WRITE = API_PATH + API_WEBSITE_PATH + API_WEBSITE_META_WRITE,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Root URL of Silex server, should we use config.rootUrl ?
|
|
40
|
+
let serverUrl = window.location.origin + window.location.pathname.replace(/\/$/, '')
|
|
41
|
+
export function setServerUrl(url: string): void {
|
|
42
|
+
serverUrl = url
|
|
43
|
+
}
|
|
44
|
+
export function getServerUrl(): string {
|
|
45
|
+
return serverUrl
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function getUser({type, connectorId}: {type: ConnectorType, connectorId?: ConnectorId}): Promise<ConnectorUser> {
|
|
49
|
+
return api<ApiConnectorUserQuery, null, ApiConnectorUserResponse>(ApiRoute.CONNECTOR_USER, 'GET', {
|
|
50
|
+
type,
|
|
51
|
+
connectorId,
|
|
52
|
+
}) as Promise<ConnectorUser>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function logout({type, connectorId}: {type: ConnectorType, connectorId?: ConnectorId}): Promise<void> {
|
|
56
|
+
return api<ApiConnectorLogoutQuery, null, null>(ApiRoute.CONNECTOR_LOGOUT, 'POST', { connectorId, type })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function publish({websiteId, hostingId, storageId, data, options}: {websiteId: WebsiteId, hostingId: ConnectorId, storageId: ConnectorId, data: PublicationData, options: ConnectorOptions}): Promise<[url: string, job: PublicationJobData]> {
|
|
60
|
+
const { url, job } = await api<ApiPublicationPublishQuery, ApiPublicationPublishBody, ApiPublicationPublishResponse>(
|
|
61
|
+
ApiRoute.PUBLICATION_PUBLISH,
|
|
62
|
+
'POST',
|
|
63
|
+
{ websiteId, hostingId, storageId, options },
|
|
64
|
+
data
|
|
65
|
+
) as ApiPublicationPublishResponse
|
|
66
|
+
return [url, job]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function publicationStatus({jobId}: {jobId: JobId}): Promise<PublicationJobData> {
|
|
70
|
+
return api<ApiPublicationStatusQuery, null, ApiPublicationStatusResponse>(
|
|
71
|
+
ApiRoute.PUBLICATION_STATUS,
|
|
72
|
+
'GET',
|
|
73
|
+
{ jobId },
|
|
74
|
+
) as Promise<PublicationJobData>
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function connectorList({type}: {type: ConnectorType}): Promise<ConnectorData[]> {
|
|
78
|
+
const list = await api<ApiConnectorListQuery, null, ApiConnectorListResponse>(ApiRoute.CONNECTOR_LIST, 'GET', { type })
|
|
79
|
+
return list as ConnectorData[]
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function websiteList({connectorId}: {connectorId?: ConnectorId}): Promise<WebsiteMeta[]> {
|
|
83
|
+
return api<ApiWebsiteListQuery, null, ApiWebsiteListResponse>(ApiRoute.WEBSITE_LIST, 'GET', { connectorId }) as Promise<WebsiteMeta[]>
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function websiteLoad({websiteId, connectorId}: {websiteId: WebsiteId, connectorId?: ConnectorId}): Promise<WebsiteData> {
|
|
87
|
+
return api<ApiWebsiteReadQuery, null, ApiWebsiteReadResponse>(ApiRoute.WEBSITE_READ, 'GET', { websiteId, connectorId }) as Promise<WebsiteData>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function websiteSave({websiteId, data, connectorId}: {websiteId: WebsiteId, data: WebsiteData, connectorId?: ConnectorId}): Promise<void> {
|
|
91
|
+
const { message } = await api<ApiWebsiteWriteQuery, ApiWebsiteWriteBody, ApiWebsiteWriteResponse>(ApiRoute.WEBSITE_WRITE, 'POST', { websiteId, connectorId }, data)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function websiteDelete({websiteId, connectorId}: {websiteId: WebsiteId, connectorId?: ConnectorId}): Promise<void> {
|
|
95
|
+
await api<ApiWebsiteDeleteQuery, null, null>(ApiRoute.WEBSITE_DELETE, 'DELETE', { websiteId, connectorId })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function websiteDuplicate({websiteId, connectorId}: {websiteId: WebsiteId, connectorId?: ConnectorId}): Promise<void> {
|
|
99
|
+
await api<ApiWebsiteDuplicateQuery, null, null>(ApiRoute.WEBSITE_DUPLICATE, 'POST', { websiteId, connectorId })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function websiteCreate({websiteId, data, connectorId}: {websiteId: WebsiteId, data: WebsiteMetaFileContent, connectorId?: ConnectorId}): Promise<void> {
|
|
103
|
+
await api<ApiWebsiteCreateQuery, ApiWebsiteCreateBody, ApiWebsiteCreateResponse>(ApiRoute.WEBSITE_CREATE, 'PUT', { connectorId }, data)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function websiteMetaWrite({websiteId, data, connectorId}: {websiteId: WebsiteId, data: WebsiteMetaFileContent, connectorId?: ConnectorId}): Promise<void> {
|
|
107
|
+
await api<ApiWebsiteMetaWriteQuery, ApiWebsiteMetaWriteBody, ApiWebsiteMetaWriteResponse>(ApiRoute.WEBSITE_META_WRITE, 'POST', { websiteId, connectorId }, data)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function websiteMetaRead({websiteId, connectorId}: {websiteId: WebsiteId, connectorId?: ConnectorId}): Promise<WebsiteMeta> {
|
|
111
|
+
return api<ApiWebsiteMetaReadQuery, null, ApiWebsiteMetaReadResponse>(ApiRoute.WEBSITE_META_WRITE, 'GET', { websiteId, connectorId })
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function websiteAssetsLoad({path, websiteId, connectorId}: {path: string, websiteId: WebsiteId, connectorId: ConnectorId}): Promise<string> {
|
|
115
|
+
return api<ApiWebsiteAssetsReadQuery, null, ApiWebsiteAssetsReadResponse>(`${ApiRoute.WEBSITE_ASSETS_READ}/${path}`, 'GET', { websiteId, connectorId })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Not used directly, grapesjs handles the upload
|
|
120
|
+
* @see assetManager in src/ts/client/grapesjs/index.ts
|
|
121
|
+
*/
|
|
122
|
+
export async function websiteAssetsSave({websiteId, connectorId, files}: {websiteId: WebsiteId, connectorId: ConnectorId, files: ClientSideFile[]}): Promise<string[]> {
|
|
123
|
+
const { data } = await api<ApiWebsiteAssetsWriteQuery, ApiWebsiteAssetsWriteBody, ApiWebsiteAssetsWriteResponse>(ApiRoute.WEBSITE_ASSETS_WRITE, 'POST', { websiteId, connectorId }, files)
|
|
124
|
+
return data
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function api<ReqQuery, ReqBody, ResBody>(route: ApiRoute | string, method: string, query?: ReqQuery, payload?: ReqBody): Promise<ResBody> {
|
|
128
|
+
const url = `${serverUrl}${route.toString()}?${
|
|
129
|
+
new URLSearchParams(
|
|
130
|
+
Object.entries(query)
|
|
131
|
+
.filter(([key, value]) => !!value)
|
|
132
|
+
.map(([key, value]) => [key, typeof value === 'string' ? value : JSON.stringify(value)])
|
|
133
|
+
).toString()}`
|
|
134
|
+
const response = await fetch(url, {
|
|
135
|
+
method,
|
|
136
|
+
headers: {
|
|
137
|
+
'Content-Type': 'application/json',
|
|
138
|
+
},
|
|
139
|
+
body: payload && JSON.stringify(payload), // assuming that the payload needs to be stringified
|
|
140
|
+
credentials: 'include', // sends the cookies with the request
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
let json
|
|
145
|
+
try {
|
|
146
|
+
json = await response.json()
|
|
147
|
+
} catch (err) {
|
|
148
|
+
// If the response is not JSON, throw a generic error
|
|
149
|
+
// This is the case when Silex backend has an uncatched error, e.g. expressjs 413 PayloadTooLargeError: request entity too large
|
|
150
|
+
throw new ApiError(response.statusText, response.status)
|
|
151
|
+
}
|
|
152
|
+
throw new ApiError(json.message, response.status)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return response.json()
|
|
156
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { jest, expect, describe, it, beforeEach } from '@jest/globals'
|
|
2
|
+
import { removeTempDataFromStyles } from './assetUrl'
|
|
3
|
+
|
|
4
|
+
describe('assetUrl', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
jest.resetModules()
|
|
7
|
+
Object.defineProperty(window, 'location', {
|
|
8
|
+
value: {
|
|
9
|
+
href: 'http://localhost:6800/',
|
|
10
|
+
pathname: '',
|
|
11
|
+
origin: 'http://localhost:6800',
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
Object.assign(window.location, {
|
|
15
|
+
href: 'http://localhost:6800/',
|
|
16
|
+
pathname: '',
|
|
17
|
+
origin: 'http://localhost:6800',
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('store url to display url', async () => {
|
|
22
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
23
|
+
// Convert a valid URL as stored
|
|
24
|
+
expect(storedToDisplayed('/assets/test.webp', 'test-id', 'test-connector'))
|
|
25
|
+
.toBe('/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
26
|
+
// Convert a URL which is already as displayed
|
|
27
|
+
expect(storedToDisplayed('/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector', 'test-id', 'test-connector'))
|
|
28
|
+
.toBe('/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('display url to store url', async () => {
|
|
32
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
33
|
+
// Convert a valid URL as displayed
|
|
34
|
+
expect(displayedToStored('/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector'))
|
|
35
|
+
.toBe('/assets/test.webp')
|
|
36
|
+
// Convert a URL which is already as stored
|
|
37
|
+
expect(displayedToStored('/assets/test.webp'))
|
|
38
|
+
.toBe('/assets/test.webp')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('store url to display url with a root path', async () => {
|
|
42
|
+
Object.assign(window.location, {
|
|
43
|
+
href: 'http://localhost:6800/silex',
|
|
44
|
+
pathname: '/silex',
|
|
45
|
+
origin: 'http://localhost:6800',
|
|
46
|
+
})
|
|
47
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
48
|
+
// Convert a valid URL as stored
|
|
49
|
+
expect(storedToDisplayed('/assets/test.webp', 'test-id', 'test-connector'))
|
|
50
|
+
.toBe('/silex/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
51
|
+
// Convert a URL which is already as displayed
|
|
52
|
+
expect(storedToDisplayed('/silex/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector', 'test-id', 'test-connector'))
|
|
53
|
+
.toBe('/silex/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('display url to store url with a root path', async () => {
|
|
57
|
+
Object.assign(window.location, {
|
|
58
|
+
href: 'http://localhost:6800/silex',
|
|
59
|
+
pathname: '/silex',
|
|
60
|
+
origin: 'http://localhost:6800',
|
|
61
|
+
})
|
|
62
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
63
|
+
// Convert a valid URL as displayed
|
|
64
|
+
expect(displayedToStored('/silex/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector'))
|
|
65
|
+
.toBe('/assets/test.webp')
|
|
66
|
+
// Convert a URL which is already as stored
|
|
67
|
+
expect(displayedToStored('/assets/test.webp'))
|
|
68
|
+
.toBe('/assets/test.webp')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('store url to display url with escapable chars', async () => {
|
|
72
|
+
Object.assign(window.location, {
|
|
73
|
+
href: 'http://localhost:6800/silex%20with%20spaces',
|
|
74
|
+
pathname: '/silex%20with%20spaces',
|
|
75
|
+
origin: 'http://localhost:6800',
|
|
76
|
+
})
|
|
77
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
78
|
+
// Convert a valid URL as displayed
|
|
79
|
+
expect(displayedToStored('/silex%20with%20spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector'))
|
|
80
|
+
.toBe('/assets/test.webp')
|
|
81
|
+
// Convert a URL which is already as stored
|
|
82
|
+
expect(displayedToStored('/assets/test.webp'))
|
|
83
|
+
.toBe('/assets/test.webp')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('display url to store url with escapable chars', async () => {
|
|
87
|
+
Object.assign(window.location, {
|
|
88
|
+
href: 'http://localhost:6800/silex%20with%20spaces',
|
|
89
|
+
pathname: '/silex%20with%20spaces',
|
|
90
|
+
origin: 'http://localhost:6800',
|
|
91
|
+
})
|
|
92
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
93
|
+
// Convert a valid URL as stored
|
|
94
|
+
expect(storedToDisplayed('/assets/test.webp', 'test-id', 'test-connector'))
|
|
95
|
+
.toBe('/silex with spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
96
|
+
// Convert a URL which is already as displayed
|
|
97
|
+
expect(storedToDisplayed('/silex%20with%20spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector', 'test-id', 'test-connector'))
|
|
98
|
+
.toBe('/silex%20with%20spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
99
|
+
expect(storedToDisplayed('/silex with spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector', 'test-id', 'test-connector'))
|
|
100
|
+
.toBe('/silex with spaces/api/website/assets/test.webp?websiteId=test-id&connectorId=test-connector')
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('store url to display url with escapable website id and connector id', async () => {
|
|
104
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
105
|
+
// Convert a valid URL as displayed
|
|
106
|
+
expect(displayedToStored('/api/website/assets/test.webp?websiteId=test%20id&connectorId=test%20connector'))
|
|
107
|
+
.toBe('/assets/test.webp')
|
|
108
|
+
// Convert a URL which is already as stored
|
|
109
|
+
expect(displayedToStored('/assets/test.webp'))
|
|
110
|
+
.toBe('/assets/test.webp')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('display url to store url with escapable website id and connector id', async () => {
|
|
114
|
+
const { displayedToStored, storedToDisplayed } = await import('./assetUrl')
|
|
115
|
+
const websiteId = 'test id'
|
|
116
|
+
const websiteIdEncoded = 'test+id'
|
|
117
|
+
const connectorId = 'test connector'
|
|
118
|
+
const connectorIdEncoded = 'test+connector'
|
|
119
|
+
// Convert a valid URL as stored
|
|
120
|
+
expect(storedToDisplayed('/assets/test.webp', websiteId, connectorId))
|
|
121
|
+
.toBe(`/api/website/assets/test.webp?websiteId=${websiteIdEncoded}&connectorId=${connectorIdEncoded}`)
|
|
122
|
+
// Convert a URL which is already as displayed
|
|
123
|
+
expect(storedToDisplayed(`/api/website/assets/test.webp?websiteId=${websiteIdEncoded}&connectorId=${connectorIdEncoded}`, websiteId, connectorId))
|
|
124
|
+
.toBe(`/api/website/assets/test.webp?websiteId=${websiteIdEncoded}&connectorId=${connectorIdEncoded}`)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('multiple backgrounds', async () => {
|
|
128
|
+
// // FIXME: this should mock the functions but it doesnt
|
|
129
|
+
// const mocked = {
|
|
130
|
+
// displayedToStored: jest.fn((url: string) => url),
|
|
131
|
+
// storedToDisplayed: jest.fn((url: string) => url),
|
|
132
|
+
// }
|
|
133
|
+
// jest.mock('./assetUrl', () => (mocked))
|
|
134
|
+
//addTempDataToStyles([toStyle(bgImageDisplayed)], websiteId, connectorId)
|
|
135
|
+
//expect(mocked.displayedToStored).toBeCalledTimes(1)
|
|
136
|
+
const { addTempDataToStyles } = await import('./assetUrl')
|
|
137
|
+
|
|
138
|
+
const websiteId = 'test-id'
|
|
139
|
+
const connectorId = 'test-connector'
|
|
140
|
+
const bgImageDisplayed = `linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url('/api/website/assets/qIg7JPRc.webp?websiteId=${websiteId}&connectorId=${connectorId}'), linear-gradient(#0ca311 0%, #0ca311 100%)`
|
|
141
|
+
const bgImageStored = 'linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url(\'/assets/qIg7JPRc.webp\'), linear-gradient(#0ca311 0%, #0ca311 100%)'
|
|
142
|
+
const selectors = ['body']
|
|
143
|
+
function toStyle(bgImage: string) {
|
|
144
|
+
return {
|
|
145
|
+
style: {
|
|
146
|
+
'background-image': bgImage,
|
|
147
|
+
},
|
|
148
|
+
selectors,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// From stored to displayed
|
|
152
|
+
expect(addTempDataToStyles([toStyle(bgImageStored)], websiteId, connectorId))
|
|
153
|
+
.toEqual([toStyle(bgImageDisplayed)])
|
|
154
|
+
// From displayed to displayed (error case)
|
|
155
|
+
expect(addTempDataToStyles([toStyle(bgImageDisplayed)], websiteId, connectorId))
|
|
156
|
+
.toEqual([toStyle(bgImageDisplayed)])
|
|
157
|
+
// From displayed to stored
|
|
158
|
+
expect(removeTempDataFromStyles([toStyle(bgImageDisplayed)]))
|
|
159
|
+
.toEqual([toStyle(bgImageStored)])
|
|
160
|
+
//// From stored to stored (error case)
|
|
161
|
+
expect(removeTempDataFromStyles([toStyle(bgImageStored)]))
|
|
162
|
+
.toEqual([toStyle(bgImageStored)])
|
|
163
|
+
})
|
|
164
|
+
})
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { API_PATH, API_WEBSITE_ASSET_READ, API_WEBSITE_PATH } from '../constants'
|
|
2
|
+
import { Asset, ClientSideFileType, Component, ConnectorId, Page, Style, WebsiteId } from '../types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Helpers to manage assets URL
|
|
6
|
+
* Assets URLs are stored on storage in their "stored version": `/assets/image.webp`
|
|
7
|
+
* But the client side uses the "display version": `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
|
|
8
|
+
* After loading the site data we convert all URLs to the client side version
|
|
9
|
+
* Before saving the site data we convert all URLs to the storage version
|
|
10
|
+
* During publicationn we convert all URLs to the storage version and back
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Get the base URL where Silex is served
|
|
14
|
+
const baseUrl = window.location.pathname.replace(/\/$/, '')
|
|
15
|
+
|
|
16
|
+
// Orging and path, should we use config.rootUrl?
|
|
17
|
+
const SERVER_URL = window.location.origin
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Function to convert a path from it stored version to the displayed version
|
|
21
|
+
* Stored version is like `/assets/image.webp`
|
|
22
|
+
* Grapesjs version is like `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
|
|
23
|
+
* Exported for unit tests
|
|
24
|
+
*/
|
|
25
|
+
export function storedToDisplayed(path: string, websiteId: WebsiteId, storageId: ConnectorId): string {
|
|
26
|
+
// Check the path is a stored path
|
|
27
|
+
if (path.startsWith('/assets')) {
|
|
28
|
+
// Make an absolute URL
|
|
29
|
+
const url = new URL(path, SERVER_URL)
|
|
30
|
+
// Remove the assets folder as it is part of the saved path
|
|
31
|
+
url.pathname = url.pathname.replace(/^\/assets/, '')
|
|
32
|
+
// Add the API path and the connectorId and websiteId
|
|
33
|
+
url.pathname = `${baseUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSET_READ}${url.pathname}`
|
|
34
|
+
// Add the GET params
|
|
35
|
+
url.searchParams.set('websiteId', websiteId)
|
|
36
|
+
url.searchParams.set('connectorId', storageId)
|
|
37
|
+
// Back to a relative URL, keep the path but not the origin
|
|
38
|
+
return `${decodeURIComponent(url.pathname)}${url.search}`
|
|
39
|
+
//const encodedPath = '/' + url.toString() // add a leading slash
|
|
40
|
+
// .replace(new RegExp(`^${SERVER_URL}`), '')
|
|
41
|
+
// .replace(/^\//, '') // remove the first slash if it exists
|
|
42
|
+
//return decodeURIComponent(encodedPath)
|
|
43
|
+
} else {
|
|
44
|
+
if(path.startsWith('<svg') || path.startsWith('data:image')) {
|
|
45
|
+
// SVG or data URL
|
|
46
|
+
return path
|
|
47
|
+
}
|
|
48
|
+
// Not a stored path, is there a problem?
|
|
49
|
+
console.warn('storedToDisplayed: path is not a stored path', path)
|
|
50
|
+
return path
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Function to convert a path from the one we give to grapesjs to the stored version
|
|
56
|
+
* Grapesjs version is like `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
|
|
57
|
+
* Stored version is like `/assets/image.webp`
|
|
58
|
+
* @param path the path to convert
|
|
59
|
+
* @returns the converted path
|
|
60
|
+
* Exported for unit tests
|
|
61
|
+
*/
|
|
62
|
+
export function displayedToStored(path: string): string {
|
|
63
|
+
// The path to the assets API
|
|
64
|
+
const apiPath = `${baseUrl}${API_PATH}${API_WEBSITE_PATH}${API_WEBSITE_ASSET_READ}`
|
|
65
|
+
// Check the path is a displayed path
|
|
66
|
+
if (path.startsWith(apiPath)) {
|
|
67
|
+
const url = new URL(path, SERVER_URL)
|
|
68
|
+
url.pathname = url.pathname.replace(new RegExp(`^${apiPath}`), '')
|
|
69
|
+
url.pathname = `${baseUrl}/assets${url.pathname}`
|
|
70
|
+
url.searchParams.delete('websiteId')
|
|
71
|
+
url.searchParams.delete('connectorId')
|
|
72
|
+
const encodedPath = '/' + url.toString() // add a leading slash
|
|
73
|
+
.replace(new RegExp(`^${SERVER_URL}${baseUrl}`), '')
|
|
74
|
+
.replace(/^\//, '') // remove the first slash if it exists
|
|
75
|
+
return decodeURIComponent(encodedPath)
|
|
76
|
+
} else {
|
|
77
|
+
if(path.startsWith('<svg') || path.startsWith('data:image')) {
|
|
78
|
+
// SVG or data URL
|
|
79
|
+
return path
|
|
80
|
+
}
|
|
81
|
+
console.warn('displayedToStored: path is not a displayed path', path)
|
|
82
|
+
return path
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Publication transformer to convert the asset URL during publication
|
|
88
|
+
*/
|
|
89
|
+
export const assetsPublicationTransformer = {
|
|
90
|
+
transformPath(path: string, type: ClientSideFileType): string {
|
|
91
|
+
if(type === ClientSideFileType.ASSET) {
|
|
92
|
+
const result = displayedToStored(path)
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
return undefined
|
|
96
|
+
},
|
|
97
|
+
transformPermalink(path: string, type: ClientSideFileType): string {
|
|
98
|
+
if(type === ClientSideFileType.ASSET) {
|
|
99
|
+
const result = displayedToStored(path)
|
|
100
|
+
return result
|
|
101
|
+
}
|
|
102
|
+
return undefined
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Update asset URL to use the current storage connector and website ID
|
|
108
|
+
* Assets URLs are stored in the project data in the form `/assets/image.webp`
|
|
109
|
+
* This function adds the API path and the connectorId and websiteId like so: `/api/website/assets/image.webp?websiteId=47868975&connectorId=gitlab`
|
|
110
|
+
*/
|
|
111
|
+
export function addTempDataToAssetUrl(assets: Asset[], websiteId: WebsiteId, storageId: ConnectorId): Asset[] {
|
|
112
|
+
return assets.map((asset: Asset) => {
|
|
113
|
+
return asset.src ? {
|
|
114
|
+
...asset,
|
|
115
|
+
src: storedToDisplayed(asset.src, websiteId, storageId),
|
|
116
|
+
} : asset
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Remove the temporary data from the asset URL
|
|
122
|
+
* Remove the API path and the connectorId and websiteId like so: `/assets/image.webp`
|
|
123
|
+
*/
|
|
124
|
+
export function removeTempDataFromAssetUrl(assets: Asset[]): Asset[] {
|
|
125
|
+
return assets.map((asset: Asset) => {
|
|
126
|
+
// Return the asset with the new URL
|
|
127
|
+
return asset.src ? {
|
|
128
|
+
...asset,
|
|
129
|
+
src: displayedToStored(asset.src),
|
|
130
|
+
} : asset
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Reucrsive function to update the asset URL in the components
|
|
136
|
+
*/
|
|
137
|
+
function addTempDataToComponents(component: Component, websiteId: WebsiteId, storageId: ConnectorId): Component {
|
|
138
|
+
// Update the asset URL in the component
|
|
139
|
+
const newComponent = component.attributes?.src ? {
|
|
140
|
+
...component,
|
|
141
|
+
attributes: {
|
|
142
|
+
...component.attributes,
|
|
143
|
+
src: storedToDisplayed(component.attributes.src, websiteId, storageId),
|
|
144
|
+
},
|
|
145
|
+
} : component
|
|
146
|
+
// Update the asset URL in the children
|
|
147
|
+
if (newComponent.components) {
|
|
148
|
+
newComponent.components = newComponent.components.map((childComponent: Component) => {
|
|
149
|
+
return addTempDataToComponents(childComponent, websiteId, storageId)
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
return newComponent
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Reucrsive function to update the asset URL in the components
|
|
157
|
+
*/
|
|
158
|
+
function removeTempDataFromComponents(component: Component): Component {
|
|
159
|
+
// Update the asset URL in the component
|
|
160
|
+
const newComponent = component.attributes?.src ? {
|
|
161
|
+
...component,
|
|
162
|
+
attributes: {
|
|
163
|
+
...component.attributes,
|
|
164
|
+
src: displayedToStored(component.attributes.src),
|
|
165
|
+
},
|
|
166
|
+
} : component
|
|
167
|
+
// Update the asset URL in the children
|
|
168
|
+
if (newComponent.components) {
|
|
169
|
+
newComponent.components = newComponent.components.map((childComponent: Component) => {
|
|
170
|
+
return removeTempDataFromComponents(childComponent)
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
return newComponent
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Add temp data to pages
|
|
178
|
+
*/
|
|
179
|
+
export function addTempDataToPages(pages: Page[], websiteId: WebsiteId, storageId: ConnectorId): Page[] {
|
|
180
|
+
return pages.map((page: Page) => {
|
|
181
|
+
return {
|
|
182
|
+
...page,
|
|
183
|
+
frames: page.frames.map(frame => ({
|
|
184
|
+
...frame,
|
|
185
|
+
component: addTempDataToComponents(frame.component, websiteId, storageId),
|
|
186
|
+
}))
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Remove temp data from asset URL in the components
|
|
193
|
+
*/
|
|
194
|
+
export function removeTempDataFromPages(pages: Page[]): Page[] {
|
|
195
|
+
return pages.map((page: Page) => {
|
|
196
|
+
return {
|
|
197
|
+
...page,
|
|
198
|
+
frames: page.frames.map(frame => ({
|
|
199
|
+
...frame,
|
|
200
|
+
component: removeTempDataFromComponents(frame.component),
|
|
201
|
+
}))
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Add data to stylesheets
|
|
208
|
+
* e.g. linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url('/assets/qIg7JPRc.webp'), linear-gradient(#0ca311 0%, #0ca311 100%)
|
|
209
|
+
*/
|
|
210
|
+
export function addTempDataToStyles(styles: Style[], websiteId: WebsiteId, storageId: ConnectorId): Style[] {
|
|
211
|
+
const regex = new RegExp(/(.*)(url\((["']?)([^"']+?)\1\))*(.*)/, 'g')
|
|
212
|
+
|
|
213
|
+
return styles.map((style: Style) => {
|
|
214
|
+
if (style.style && style.style['background-image']) {
|
|
215
|
+
const bgImage = style.style['background-image']
|
|
216
|
+
.replace(/url\((['"]?)([^'"]+)\1\)/g, (match, quote, url) => {
|
|
217
|
+
return `url(${quote}${storedToDisplayed(url, websiteId, storageId)}${quote})`
|
|
218
|
+
})
|
|
219
|
+
return {
|
|
220
|
+
...style,
|
|
221
|
+
style: {
|
|
222
|
+
...style.style,
|
|
223
|
+
'background-image': bgImage,
|
|
224
|
+
},
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return style
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Remove temp data from stylesheets
|
|
233
|
+
* The property `background-image` contains the URLs of the assets and other values,
|
|
234
|
+
* e.g. `linear-gradient(to right, #1fb101 0%, #df1313 67%, rgba(234, 97, 97, 255) 78%, white 100%), url('/api/website/assets/qIg7JPRc.webp?websiteId=default&connectorId=fs-storage'), linear-gradient(#0ca311 0%, #0ca311 100%)`
|
|
235
|
+
*/
|
|
236
|
+
export function removeTempDataFromStyles(styles: Style[]): Style[] {
|
|
237
|
+
const pattern = /url\((["']?)([^"']+?)\1\)/g
|
|
238
|
+
return styles.map((style: Style) => {
|
|
239
|
+
if (style.style && style.style['background-image']) {
|
|
240
|
+
const bgImage = style.style['background-image']
|
|
241
|
+
.replace(/url\((['"]?)([^'"]+)\1\)/g, (match, quote, url) => {
|
|
242
|
+
return `url(${quote}${displayedToStored(url)}${quote})`
|
|
243
|
+
})
|
|
244
|
+
return {
|
|
245
|
+
...style,
|
|
246
|
+
style: {
|
|
247
|
+
...style.style,
|
|
248
|
+
'background-image': bgImage,
|
|
249
|
+
},
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return style
|
|
253
|
+
})
|
|
254
|
+
}
|