@silexlabs/silex 3.0.0-alpha.100
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 +19 -0
- package/.silex.js +37 -0
- package/LICENSE +661 -0
- package/README.md +96 -0
- package/dist/client/client/api.d.ts +85 -0
- package/dist/client/client/assetUrl.d.ts +51 -0
- package/dist/client/client/config.d.ts +58 -0
- package/dist/client/client/events.d.ts +14 -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 +72 -0
- package/dist/client/client/grapesjs/PublicationUi.d.ts +62 -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/footer.d.ts +2 -0
- package/dist/client/client/grapesjs/index.d.ts +5 -0
- package/dist/client/client/grapesjs/internal-links.d.ts +1 -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 +3 -0
- package/dist/client/client/grapesjs/project-bar.d.ts +1 -0
- package/dist/client/client/grapesjs/rich-text.d.ts +1 -0
- package/dist/client/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/client/grapesjs/settings.d.ts +2 -0
- package/dist/client/client/grapesjs/storage.d.ts +1 -0
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/client/index.d.ts +5 -0
- package/dist/client/client/publication-transformers.d.ts +41 -0
- package/dist/client/client/utils.d.ts +2 -0
- package/dist/client/constants.d.ts +29 -0
- package/dist/client/css/admin.css +4491 -0
- package/dist/client/index.html +9 -0
- package/dist/client/js/main.js +321 -0
- package/dist/client/js/main.js.LICENSE.txt +24 -0
- package/dist/client/page.d.ts +2 -0
- package/dist/client/types.d.ts +334 -0
- package/dist/plugins/client/client/api.d.ts +85 -0
- package/dist/plugins/client/client/api.js +114 -0
- package/dist/plugins/client/client/api.js.map +1 -0
- package/dist/plugins/client/client/assetUrl.d.ts +51 -0
- package/dist/plugins/client/client/assetUrl.js +224 -0
- package/dist/plugins/client/client/assetUrl.js.map +1 -0
- package/dist/plugins/client/client/config.d.ts +58 -0
- package/dist/plugins/client/client/config.js +90 -0
- package/dist/plugins/client/client/config.js.map +1 -0
- package/dist/plugins/client/client/events.d.ts +14 -0
- package/dist/plugins/client/client/events.js +34 -0
- package/dist/plugins/client/client/events.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/plugins/client/client/grapesjs/LoginDialog.js +195 -0
- package/dist/plugins/client/client/grapesjs/LoginDialog.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/PublicationManager.d.ts +72 -0
- package/dist/plugins/client/client/grapesjs/PublicationManager.js +356 -0
- package/dist/plugins/client/client/grapesjs/PublicationManager.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/PublicationUi.d.ts +62 -0
- package/dist/plugins/client/client/grapesjs/PublicationUi.js +336 -0
- package/dist/plugins/client/client/grapesjs/PublicationUi.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/blocks.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/blocks.js +37 -0
- package/dist/plugins/client/client/grapesjs/blocks.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/breadcrumbs.js +75 -0
- package/dist/plugins/client/client/grapesjs/breadcrumbs.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/footer.d.ts +2 -0
- package/dist/plugins/client/client/grapesjs/footer.js +28 -0
- package/dist/plugins/client/client/grapesjs/footer.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/index.d.ts +5 -0
- package/dist/plugins/client/client/grapesjs/index.js +313 -0
- package/dist/plugins/client/client/grapesjs/index.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/internal-links.js +219 -0
- package/dist/plugins/client/client/grapesjs/internal-links.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/plugins/client/client/grapesjs/new-page-dialog.js +83 -0
- package/dist/plugins/client/client/grapesjs/new-page-dialog.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/openImport.d.ts +9 -0
- package/dist/plugins/client/client/grapesjs/openImport.js +74 -0
- package/dist/plugins/client/client/grapesjs/openImport.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/page-panel.d.ts +3 -0
- package/dist/plugins/client/client/grapesjs/page-panel.js +113 -0
- package/dist/plugins/client/client/grapesjs/page-panel.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/project-bar.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/project-bar.js +104 -0
- package/dist/plugins/client/client/grapesjs/project-bar.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/rich-text.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/rich-text.js +31 -0
- package/dist/plugins/client/client/grapesjs/rich-text.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/semantic.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/semantic.js +110 -0
- package/dist/plugins/client/client/grapesjs/semantic.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/settings.d.ts +2 -0
- package/dist/plugins/client/client/grapesjs/settings.js +198 -0
- package/dist/plugins/client/client/grapesjs/settings.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/storage.d.ts +1 -0
- package/dist/plugins/client/client/grapesjs/storage.js +126 -0
- package/dist/plugins/client/client/grapesjs/storage.js.map +1 -0
- package/dist/plugins/client/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/plugins/client/client/grapesjs/symbolDialogs.js +36 -0
- package/dist/plugins/client/client/grapesjs/symbolDialogs.js.map +1 -0
- package/dist/plugins/client/client/publication-transformers.d.ts +41 -0
- package/dist/plugins/client/client/publication-transformers.js +238 -0
- package/dist/plugins/client/client/publication-transformers.js.map +1 -0
- package/dist/plugins/client/client/utils.d.ts +2 -0
- package/dist/plugins/client/client/utils.js +25 -0
- package/dist/plugins/client/client/utils.js.map +1 -0
- package/dist/plugins/client/constants.d.ts +29 -0
- package/dist/plugins/client/constants.js +46 -0
- package/dist/plugins/client/constants.js.map +1 -0
- package/dist/plugins/client/page.d.ts +2 -0
- package/dist/plugins/client/page.js +31 -0
- package/dist/plugins/client/page.js.map +1 -0
- package/dist/plugins/client/plugins/client/11ty.d.ts +17 -0
- package/dist/plugins/client/plugins/client/11ty.js +86 -0
- package/dist/plugins/client/plugins/client/11ty.js.map +1 -0
- package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +2 -0
- package/dist/plugins/client/plugins/client/publicationRenderer.js +170 -0
- package/dist/plugins/client/plugins/client/publicationRenderer.js.map +1 -0
- package/dist/plugins/client/plugins/client/template.d.ts +2 -0
- package/dist/plugins/client/plugins/client/template.js +183 -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 +334 -0
- package/dist/plugins/client/types.js +74 -0
- package/dist/plugins/client/types.js.map +1 -0
- package/dist/plugins/server/constants.d.ts +29 -0
- package/dist/plugins/server/constants.js +49 -0
- package/dist/plugins/server/constants.js.map +1 -0
- package/dist/plugins/server/plugins/server/AuthPlugin.d.ts +1 -0
- package/dist/plugins/server/plugins/server/AuthPlugin.js +40 -0
- package/dist/plugins/server/plugins/server/AuthPlugin.js.map +1 -0
- package/dist/plugins/server/plugins/server/Cache.d.ts +2 -0
- package/dist/plugins/server/plugins/server/Cache.js +32 -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 +129 -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 +526 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +87 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +564 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.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 +1 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js +78 -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 +13 -0
- package/dist/plugins/server/server/connectors/FsHosting.js +54 -0
- package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -0
- package/dist/plugins/server/server/connectors/FsStorage.d.ts +43 -0
- package/dist/plugins/server/server/connectors/FsStorage.js +257 -0
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -0
- package/dist/plugins/server/server/connectors/connectors.d.ts +87 -0
- package/dist/plugins/server/server/connectors/connectors.js +127 -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 +77 -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 +38 -0
- package/dist/plugins/server/server/utils/validation.js.map +1 -0
- package/dist/plugins/server/types.d.ts +334 -0
- package/dist/plugins/server/types.js +78 -0
- package/dist/plugins/server/types.js.map +1 -0
- package/dist/server/constants.js +29 -0
- package/dist/server/plugins/server/Cache.js +15 -0
- package/dist/server/server/api/api.js +20 -0
- package/dist/server/server/api/connectorApi.js +216 -0
- package/dist/server/server/api/publicationApi.js +108 -0
- package/dist/server/server/api/websiteApi.js +296 -0
- package/dist/server/server/cli.js +68 -0
- package/dist/server/server/config.js +120 -0
- package/dist/server/server/connectors/FsHosting.js +35 -0
- package/dist/server/server/connectors/FsStorage.js +225 -0
- package/dist/server/server/connectors/connectors.js +89 -0
- package/dist/server/server/events.js +14 -0
- package/dist/server/server/expose.js +27 -0
- package/dist/server/server/express.js +47 -0
- package/dist/server/server/index.js +90 -0
- package/dist/server/server/jobs.js +48 -0
- package/dist/server/server/utils/validation.js +15 -0
- package/dist/server/types.js +34 -0
- package/package.json +209 -0
- package/public/assets/container.png +0 -0
- package/public/assets/favicon.png +0 -0
- package/public/assets/logo-silex-small.png +0 -0
- package/public/robots.txt +2 -0
- package/public/silex.js +24 -0
- package/src/css/_mixins.scss +8 -0
- package/src/css/_variables.scss +33 -0
- package/src/css/dialog.scss +41 -0
- package/src/css/footer.scss +12 -0
- package/src/css/grapesjs-light.scss +180 -0
- package/src/css/grapesjs.scss +152 -0
- package/src/css/index.scss +32 -0
- package/src/css/light.scss +7 -0
- package/src/css/loader.scss +12 -0
- package/src/css/page-panel.scss +65 -0
- package/src/css/project-bar.scss +102 -0
- package/src/css/silex.scss +189 -0
- package/src/css/website-info.scss +14 -0
- package/src/html/debug.pug +8 -0
- package/src/html/index.pug +39 -0
- package/src/html/templates/includes.pug +1 -0
- package/src/html/templates/workspace.pug +2 -0
- package/src/ts/client/api.ts +144 -0
- package/src/ts/client/assetUrl.test.ts +125 -0
- package/src/ts/client/assetUrl.ts +235 -0
- package/src/ts/client/config.ts +105 -0
- package/src/ts/client/events.ts +34 -0
- package/src/ts/client/expose.ts +30 -0
- package/src/ts/client/grapesjs/LoginDialog.ts +204 -0
- package/src/ts/client/grapesjs/PublicationManager.ts +370 -0
- package/src/ts/client/grapesjs/PublicationUi.ts +342 -0
- package/src/ts/client/grapesjs/blocks.ts +37 -0
- package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
- package/src/ts/client/grapesjs/eleventy.ts +47 -0
- package/src/ts/client/grapesjs/footer.ts +27 -0
- package/src/ts/client/grapesjs/index.ts +335 -0
- package/src/ts/client/grapesjs/internal-links.test.ts +105 -0
- package/src/ts/client/grapesjs/internal-links.ts +225 -0
- package/src/ts/client/grapesjs/new-page-dialog.ts +90 -0
- package/src/ts/client/grapesjs/openImport.ts +81 -0
- package/src/ts/client/grapesjs/page-panel.ts +118 -0
- package/src/ts/client/grapesjs/project-bar.ts +107 -0
- package/src/ts/client/grapesjs/rich-text.ts +33 -0
- package/src/ts/client/grapesjs/semantic.ts +114 -0
- package/src/ts/client/grapesjs/settings.ts +208 -0
- package/src/ts/client/grapesjs/storage.ts +121 -0
- package/src/ts/client/grapesjs/symbolDialogs.ts +38 -0
- package/src/ts/client/index.ts +98 -0
- package/src/ts/client/publication-transformers.test.ts +199 -0
- package/src/ts/client/publication-transformers.ts +263 -0
- package/src/ts/client/utils.ts +28 -0
- package/src/ts/constants.ts +52 -0
- package/src/ts/externs.ts +18 -0
- package/src/ts/page.ts +31 -0
- package/src/ts/plugins/client/11ty.ts +104 -0
- package/src/ts/plugins/client/publicationRenderer.ts +174 -0
- package/src/ts/plugins/client/template.ts +192 -0
- package/src/ts/plugins/client/website-info.ts +84 -0
- package/src/ts/plugins/server/AuthPlugin.ts +38 -0
- package/src/ts/plugins/server/Cache.ts +28 -0
- package/src/ts/plugins/server/DownloadConnector.ts +148 -0
- package/src/ts/plugins/server/FtpConnector.test.ts +82 -0
- package/src/ts/plugins/server/FtpConnector.ts +609 -0
- package/src/ts/plugins/server/GitlabConnector.ts +644 -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 +79 -0
- package/src/ts/server/api/api.ts +19 -0
- package/src/ts/server/api/connectorApi.ts +345 -0
- package/src/ts/server/api/publicationApi.ts +159 -0
- package/src/ts/server/api/websiteApi.ts +432 -0
- package/src/ts/server/cli.ts +65 -0
- package/src/ts/server/config.ts +189 -0
- package/src/ts/server/connectors/FsHosting.ts +60 -0
- package/src/ts/server/connectors/FsStorage.test.ts +51 -0
- package/src/ts/server/connectors/FsStorage.ts +261 -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 +70 -0
- package/src/ts/server/index.ts +100 -0
- package/src/ts/server/jobs.test.ts +75 -0
- package/src/ts/server/jobs.ts +87 -0
- package/src/ts/server/utils/BackwardCompat.ts +552 -0
- package/src/ts/server/utils/validation.ts +34 -0
- package/src/ts/types.ts +339 -0
|
@@ -0,0 +1,192 @@
|
|
|
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
|
+
// Silex serves /clients
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
import { onAll } from '../client/utils.js'
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
import { ClientEvent } from '../client/events.js'
|
|
23
|
+
|
|
24
|
+
// You need to serve lit-html at /js/lit-html/
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
import {html, render} from '../js/lit-html/lit-html.js'
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
import {styleMap} from '../js/lit-html/directives/style-map.js'
|
|
29
|
+
|
|
30
|
+
const silex = window['silex']
|
|
31
|
+
|
|
32
|
+
const pluginName = 'template'
|
|
33
|
+
const templateType = 'templateType'
|
|
34
|
+
const templateKey = 'template'
|
|
35
|
+
|
|
36
|
+
export default async (config, opts: any = {}) => {
|
|
37
|
+
config.on(ClientEvent.GRAPESJS_END, () => {
|
|
38
|
+
const editor = silex.getEditor()
|
|
39
|
+
// Add the new trait to all component types
|
|
40
|
+
editor.DomComponents.getTypes().map(type => {
|
|
41
|
+
const originalType = editor.DomComponents.getType(type.id)
|
|
42
|
+
editor.DomComponents.addType(type.id, {
|
|
43
|
+
model: {
|
|
44
|
+
defaults: {
|
|
45
|
+
traits: [
|
|
46
|
+
// Keep the type original traits
|
|
47
|
+
...originalType.model.prototype.defaults.traits,
|
|
48
|
+
// Add the new trait
|
|
49
|
+
{
|
|
50
|
+
label: false,
|
|
51
|
+
type: templateType,
|
|
52
|
+
name: pluginName,
|
|
53
|
+
},
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
function doRender(el) {
|
|
61
|
+
const template = editor.getSelected()?.get(templateKey) || {}
|
|
62
|
+
const taStyle = opts.styles?.textarea ?? styleMap({
|
|
63
|
+
backgroundColor: 'var(--darkerPrimaryColor)',
|
|
64
|
+
})
|
|
65
|
+
const sepStyle = opts.styles?.sep ?? styleMap({ height: '10px' })
|
|
66
|
+
const labels = {
|
|
67
|
+
before: html`<strong>Before</strong> the element`,
|
|
68
|
+
replace: html`<strong>Replace</strong> the element's children`,
|
|
69
|
+
after: html`<strong>After</strong> the element`,
|
|
70
|
+
attributes: html`HTML attributes`,
|
|
71
|
+
classname: html`CSS classes`,
|
|
72
|
+
style: html`CSS styles`,
|
|
73
|
+
}
|
|
74
|
+
render(html`
|
|
75
|
+
<div>
|
|
76
|
+
<h3>Template</h3>
|
|
77
|
+
<p>This will be inserted in the published version</p>
|
|
78
|
+
</div>
|
|
79
|
+
${['classname', 'attributes', 'style'].map(id => html`
|
|
80
|
+
<label>
|
|
81
|
+
${labels[id]}
|
|
82
|
+
<input
|
|
83
|
+
id="template-${id}"
|
|
84
|
+
.value=${template[id] || ''}
|
|
85
|
+
style=${taStyle}
|
|
86
|
+
/>
|
|
87
|
+
</label>
|
|
88
|
+
`)}
|
|
89
|
+
${['before', 'replace', 'after'].map(id => html`
|
|
90
|
+
<label
|
|
91
|
+
for="template-${id}"
|
|
92
|
+
>${labels[id]}</label>
|
|
93
|
+
<textarea
|
|
94
|
+
id="template-${id}"
|
|
95
|
+
style=${taStyle}
|
|
96
|
+
.value=${template[id] || ''}
|
|
97
|
+
></textarea>
|
|
98
|
+
`)}
|
|
99
|
+
`, el)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
editor.TraitManager.addType(templateType, {
|
|
103
|
+
createInput({ trait }) {
|
|
104
|
+
// Create a new element container and add some content
|
|
105
|
+
const el = document.createElement('div')
|
|
106
|
+
el.classList.add('gjs-one-bg')
|
|
107
|
+
// update the UI when a page is added/renamed/removed
|
|
108
|
+
editor.on('page', () => doRender(el))
|
|
109
|
+
doRender(el)
|
|
110
|
+
// this will be the element passed to onEvent and onUpdate
|
|
111
|
+
return el
|
|
112
|
+
},
|
|
113
|
+
// Update the component based on UI changes
|
|
114
|
+
// `elInput` is the result HTMLElement you get from `createInput`
|
|
115
|
+
onEvent({ elInput, component, event }) {
|
|
116
|
+
const template = {
|
|
117
|
+
before: elInput.querySelector('#template-before').value,
|
|
118
|
+
replace: elInput.querySelector('#template-replace').value,
|
|
119
|
+
after: elInput.querySelector('#template-after').value,
|
|
120
|
+
attributes: elInput.querySelector('#template-attributes').value,
|
|
121
|
+
classname: elInput.querySelector('#template-classname').value,
|
|
122
|
+
style: elInput.querySelector('#template-style').value,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Store the new template
|
|
126
|
+
if (Object.values(template).filter(val => !!val && !!cleanup(val)).length > 0) {
|
|
127
|
+
component.set(templateKey, template)
|
|
128
|
+
} else {
|
|
129
|
+
component.set(templateKey)
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
// Update UI on the component change
|
|
133
|
+
onUpdate({ elInput, component }) {
|
|
134
|
+
doRender(elInput)
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
// Make html attribute
|
|
139
|
+
// Quote strings, no values for boolean
|
|
140
|
+
function makeAttribute(key, value) {
|
|
141
|
+
switch (typeof value) {
|
|
142
|
+
case 'boolean': return value ? key : ''
|
|
143
|
+
default: return `${key}="${value}"`
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Remove empty lines in templates
|
|
147
|
+
function cleanup(template) {
|
|
148
|
+
return template
|
|
149
|
+
// split in lines
|
|
150
|
+
.split('\n')
|
|
151
|
+
// remove lines with only spaces
|
|
152
|
+
.map(line => line.trim())
|
|
153
|
+
.filter(line => !!line)
|
|
154
|
+
// put back together
|
|
155
|
+
.join('\n')
|
|
156
|
+
}
|
|
157
|
+
editor.on(ClientEvent.PUBLISH_START, () => {
|
|
158
|
+
// Insert templates
|
|
159
|
+
onAll(editor, c => {
|
|
160
|
+
const template = c.get(templateKey)
|
|
161
|
+
const toHTML = c.toHTML
|
|
162
|
+
const classes = c.getClasses()
|
|
163
|
+
const before = cleanup(template?.before || '')
|
|
164
|
+
const replace = cleanup(template?.replace || '')
|
|
165
|
+
const after = cleanup(template?.after || '')
|
|
166
|
+
const classname = cleanup(template?.classname || '')
|
|
167
|
+
const style = cleanup(template?.style || '')
|
|
168
|
+
const attributes = cleanup(template?.attributes || '')
|
|
169
|
+
// Store the initial method
|
|
170
|
+
if (!c.has('tmpHtml')) c.set('tmpHtml', toHTML)
|
|
171
|
+
// Override the method
|
|
172
|
+
c.toHTML = () => {
|
|
173
|
+
return `${before
|
|
174
|
+
}${c.get('tagName') ? `<${c.get('tagName')}
|
|
175
|
+
${Object.entries(c.get('attributes') as object).map(([key, value]) => makeAttribute(key, value)).join(' ')}
|
|
176
|
+
${classes.length || classname ? `class="${classes.join(' ')} ${classname}"` : ''}
|
|
177
|
+
${attributes}
|
|
178
|
+
${style ? `style="${style}"` : ''}
|
|
179
|
+
>` : ''}${replace || c.getInnerHTML()
|
|
180
|
+
}${c.get('tagName') ? `</${c.get('tagName')}>` : ''}${after
|
|
181
|
+
}`
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
editor.on(ClientEvent.PUBLISH_END, () => {
|
|
186
|
+
onAll(editor, c => {
|
|
187
|
+
// Restore the original method
|
|
188
|
+
c.toHTML = c.get('tmpHtml')
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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 { ClientEvent } from '../../client/events.js'
|
|
19
|
+
import { WebsiteMeta } from '../../types.js'
|
|
20
|
+
|
|
21
|
+
interface WebsiteInfoOptions {
|
|
22
|
+
websiteId: string
|
|
23
|
+
connectorId: string
|
|
24
|
+
appendTo: 'commands' | 'options' | 'views' | 'project-bar-container' | 'project-bar-panel' | 'views-container'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Silex plugin
|
|
28
|
+
export default async function(config) {
|
|
29
|
+
let websiteMeta: WebsiteMeta | null = null
|
|
30
|
+
config.on(ClientEvent.GRAPESJS_START, async () => {
|
|
31
|
+
// GrapesJs plugin
|
|
32
|
+
const grapesPlugin = (editor, opts: Partial<WebsiteInfoOptions>) => {
|
|
33
|
+
const options = {
|
|
34
|
+
appendTo: 'commands',
|
|
35
|
+
...opts,
|
|
36
|
+
} as WebsiteInfoOptions
|
|
37
|
+
editor.on('storage:end:load', async () => {
|
|
38
|
+
// Get website meta data
|
|
39
|
+
const { websiteId, connectorId } = options
|
|
40
|
+
// Get the website meta data
|
|
41
|
+
websiteMeta = await config.api.websiteMetaRead({ websiteId, connectorId })
|
|
42
|
+
displayWebsiteMeta()
|
|
43
|
+
})
|
|
44
|
+
return {}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add the plugin to the GrapeJS
|
|
48
|
+
config.grapesJsConfig.plugins.push(grapesPlugin)
|
|
49
|
+
config.grapesJsConfig.pluginsOpts[grapesPlugin.toString()] = {
|
|
50
|
+
websiteId: config.websiteId,
|
|
51
|
+
connectorId: config.storageId,
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
config.on(ClientEvent.GRAPESJS_END, async ({editor}) => {
|
|
56
|
+
// Detect when the page changes
|
|
57
|
+
editor.on('page:select', async () => {
|
|
58
|
+
displayWebsiteMeta()
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
// Display the website meta data
|
|
64
|
+
function displayWebsiteMeta() {
|
|
65
|
+
// Get or create the container
|
|
66
|
+
const container = document.querySelector('#gjs-website-meta') ?? (function() {
|
|
67
|
+
const c = document.createElement('div')
|
|
68
|
+
c.id = 'gjs-website-meta'
|
|
69
|
+
c.classList.add('gjs-website-meta')
|
|
70
|
+
// Add the container to the UI
|
|
71
|
+
// Add the name of the website in the top bar
|
|
72
|
+
const topBar = document.querySelector('.gjs-pn-devices-c')
|
|
73
|
+
topBar?.appendChild(c)
|
|
74
|
+
return c
|
|
75
|
+
})()
|
|
76
|
+
// Get the current page
|
|
77
|
+
const currentPage = config.getEditor().Pages?.getSelected()
|
|
78
|
+
// Display the website meta data
|
|
79
|
+
container.innerHTML = `
|
|
80
|
+
${websiteMeta?.imageUrl ? `<div class="gjs-website-meta-image" style="background: url(${websiteMeta?.imageUrl});"></div>` : ''}
|
|
81
|
+
<div class="gjs-website-meta-name">${websiteMeta?.name ?? 'Unknown'} | ${currentPage.get('name') ?? currentPage.get('type')}</div>
|
|
82
|
+
`
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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 express from 'express'
|
|
19
|
+
// import { Directus } from '@directus/sdk'
|
|
20
|
+
|
|
21
|
+
export default async function(config, opts = {}) {
|
|
22
|
+
// config.on('silex:startup:start', ({app}) => {
|
|
23
|
+
// const router = express.Router()
|
|
24
|
+
// router.post(['/publish', '/website', '/assets'], async function(req, res, next) {
|
|
25
|
+
// try {
|
|
26
|
+
// const token = req.body.token || opts.directusToken
|
|
27
|
+
// const directus = new Directus(opts.directusUrl)
|
|
28
|
+
// directus.storage.auth_token = token
|
|
29
|
+
// const me = await directus.users.me.read()
|
|
30
|
+
// next()
|
|
31
|
+
// } catch(err) {
|
|
32
|
+
// console.error('Publish failed in auth module. Did you provide a directus token?', err.message)
|
|
33
|
+
// res.status(403).json({ message: err.message })
|
|
34
|
+
// }
|
|
35
|
+
// })
|
|
36
|
+
// app.use(router)
|
|
37
|
+
// })
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
export function noCache (req, res, next) {
|
|
19
|
+
res.header('Cache-Control', 'private,no-cache,no-store,must-revalidate,proxy-revalidate')
|
|
20
|
+
res.header('Expires', '-1')
|
|
21
|
+
res.header('Pragma', 'no-cache')
|
|
22
|
+
next()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function withCache(req, res, next) {
|
|
26
|
+
res.header('Cache-Control', 'public,max-age=86400,immutable') // 24h
|
|
27
|
+
next()
|
|
28
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { createWriteStream } from 'fs'
|
|
2
|
+
import archiver from 'archiver'
|
|
3
|
+
import { ConnectorOptions, ConnectorType, ConnectorUser, JobData, JobStatus, PublicationJobData, WebsiteId } from '../../types'
|
|
4
|
+
import { ConnectorFile, ConnectorSession, HostingConnector } from '../../server/connectors/connectors'
|
|
5
|
+
import { tmpdir } from 'os'
|
|
6
|
+
import { JobManager } from '../../server/jobs'
|
|
7
|
+
import { ServerConfig } from '../../server/config'
|
|
8
|
+
import { ServerEvent } from '../../server/events'
|
|
9
|
+
|
|
10
|
+
import { Request, Response } from 'express'
|
|
11
|
+
|
|
12
|
+
type DownloadConnectorSession = ConnectorSession;
|
|
13
|
+
|
|
14
|
+
type DownloadConnectorOptions = object
|
|
15
|
+
|
|
16
|
+
const svg = '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 464c-8.8 0-16-7.2-16-16V64c0-8.8 7.2-16 16-16h48c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16h48v80c0 17.7 14.3 32 32 32h80V448c0 8.8-7.2 16-16 16H64zM64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V154.5c0-17-6.7-33.3-18.7-45.3L274.7 18.7C262.7 6.7 246.5 0 229.5 0H64zm48 112c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16s-7.2-16-16-16H128c-8.8 0-16 7.2-16 16zm0 64c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16s-7.2-16-16-16H128c-8.8 0-16 7.2-16 16zm-6.3 71.8L82.1 335.9c-1.4 5.4-2.1 10.9-2.1 16.4c0 35.2 28.8 63.7 64 63.7s64-28.5 64-63.7c0-5.5-.7-11.1-2.1-16.4l-23.5-88.2c-3.7-14-16.4-23.8-30.9-23.8H136.6c-14.5 0-27.2 9.7-30.9 23.8zM128 336h32c8.8 0 16 7.2 16 16s-7.2 16-16 16H128c-8.8 0-16-7.2-16-16s7.2-16 16-16z"/></svg>'
|
|
17
|
+
const encodedSvg = encodeURIComponent(svg)
|
|
18
|
+
const ZIP_ICON = `data:image/svg+xml,${encodedSvg}`
|
|
19
|
+
|
|
20
|
+
export default class implements HostingConnector<DownloadConnectorSession> {
|
|
21
|
+
connectorId = 'download-connector'
|
|
22
|
+
displayName = 'Download zip file'
|
|
23
|
+
icon = ZIP_ICON
|
|
24
|
+
disableLogout = false
|
|
25
|
+
options: DownloadConnectorOptions
|
|
26
|
+
connectorType = ConnectorType.HOSTING
|
|
27
|
+
color = '#ffffff'
|
|
28
|
+
background = '#006400'
|
|
29
|
+
|
|
30
|
+
constructor(config: ServerConfig) {
|
|
31
|
+
// Add a route to serve the zip file
|
|
32
|
+
config.on(ServerEvent.STARTUP_END, ({app}) => {
|
|
33
|
+
app.get('/download/:tmpZipFile', async (req: Request, res: Response) => {
|
|
34
|
+
const path = `${tmpdir()}/${req.params.tmpZipFile}`
|
|
35
|
+
res.sendFile(path, {}, (err) => {
|
|
36
|
+
if (err) {
|
|
37
|
+
console.error('[DownloadConnector] Error while sending file', err)
|
|
38
|
+
res.status(500).send(`
|
|
39
|
+
<h1>Error</h1>
|
|
40
|
+
<p>There was an error while getting the zip file of your website</p>
|
|
41
|
+
<p>${err.message}</p>
|
|
42
|
+
`)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getOptions(formData: object): ConnectorOptions {
|
|
50
|
+
return {}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getOAuthUrl(session: DownloadConnectorSession): Promise<null> { return null }
|
|
54
|
+
|
|
55
|
+
async getLoginForm(session: DownloadConnectorSession, redirectTo: string): Promise<string | null> {
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
async getSettingsForm(session: DownloadConnectorSession, redirectTo: string): Promise<string | null> {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async isLoggedIn(session: DownloadConnectorSession): Promise<boolean> {
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async setToken(session: DownloadConnectorSession, query: object): Promise<void> {}
|
|
67
|
+
|
|
68
|
+
async logout(session: DownloadConnectorSession): Promise<void> {}
|
|
69
|
+
|
|
70
|
+
async getUser(session: DownloadConnectorSession): Promise<ConnectorUser | null> {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async publish(session: DownloadConnectorSession, websiteId: WebsiteId, files: ConnectorFile[], jobManager: JobManager): Promise<JobData> {
|
|
75
|
+
const job = jobManager.startJob(`Publishing to ${this.displayName}`) as PublicationJobData
|
|
76
|
+
this.startPublishingInBackground(session, websiteId, files, job)
|
|
77
|
+
return job
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async startPublishingInBackground(session: DownloadConnectorSession, websiteId: WebsiteId, files: ConnectorFile[], job: PublicationJobData): Promise<void> {
|
|
81
|
+
const fileName = `${websiteId}-${Date.now()}-${Math.random().toString(36).substring(7)}.zip`
|
|
82
|
+
return new Promise<string>((resolve, reject) => {
|
|
83
|
+
let resolved = false
|
|
84
|
+
try {
|
|
85
|
+
// Generate a temporary path for the zip file, in the OS tmp folder, with the website id, the date and random string
|
|
86
|
+
const path = `${tmpdir()}/${fileName}`
|
|
87
|
+
// create a file to stream archive data to.
|
|
88
|
+
const output = createWriteStream(path)
|
|
89
|
+
const archive = archiver('zip', {
|
|
90
|
+
zlib: { level: 9 } // Sets the compression level.
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
// Listen to archive events
|
|
94
|
+
// listen for all archive data to be written
|
|
95
|
+
// 'close' event is fired only when a file descriptor is involved
|
|
96
|
+
output.on('close', function () {
|
|
97
|
+
!resolved && resolve(path)
|
|
98
|
+
resolved = true
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
|
102
|
+
archive.on('warning', function (err) {
|
|
103
|
+
if (err.code === 'ENOENT') {
|
|
104
|
+
// log warning
|
|
105
|
+
} else {
|
|
106
|
+
!resolved && reject(err)
|
|
107
|
+
resolved = true
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// good practice to catch this error explicitly
|
|
112
|
+
archive.on('error', function (err) {
|
|
113
|
+
!resolved && reject(err)
|
|
114
|
+
resolved = true
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// pipe archive data to the filey
|
|
118
|
+
archive.pipe(output)
|
|
119
|
+
|
|
120
|
+
// append files
|
|
121
|
+
for (const file of files) {
|
|
122
|
+
job.message = `Adding ${file.path} to the zip file`
|
|
123
|
+
// Handle content as string, buffer or readable
|
|
124
|
+
archive.append(file.content, { name: file.path })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// finalize the archive (ie we are done appending files but streams have to finish yet)
|
|
128
|
+
job.message = 'Finalizing the zip file'
|
|
129
|
+
return archive.finalize()
|
|
130
|
+
.then(() => path)
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.error('Error while creating the zip file', err)
|
|
133
|
+
job.message = `Error while creating the zip file: ${err.message}`
|
|
134
|
+
job.status = JobStatus.ERROR
|
|
135
|
+
!resolved && reject(err)
|
|
136
|
+
resolved = true
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
.then(path => {
|
|
140
|
+
job.message = `Zip file created, <a href="/download/${fileName}" target="_blank">download it now</a>`
|
|
141
|
+
job.status = JobStatus.SUCCESS
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getUrl(session: DownloadConnectorSession, websiteId: WebsiteId): Promise<string> {
|
|
146
|
+
return ''
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ServerConfig } from '../../server/config'
|
|
2
|
+
import { expect, jest, beforeEach, afterEach, it, describe } from '@jest/globals'
|
|
3
|
+
import { ConnectorType, WebsiteData, WebsiteId } from '../../types'
|
|
4
|
+
import { Readable } from 'stream'
|
|
5
|
+
|
|
6
|
+
const mocks = {
|
|
7
|
+
access: jest.fn(),
|
|
8
|
+
close: jest.fn(),
|
|
9
|
+
trackProgress: jest.fn(),
|
|
10
|
+
uploadFrom: jest.fn(),
|
|
11
|
+
}
|
|
12
|
+
function mockClient() {
|
|
13
|
+
jest.mock('basic-ftp', () => ({
|
|
14
|
+
Client: jest.fn().mockImplementation(() => mocks),
|
|
15
|
+
}))
|
|
16
|
+
}
|
|
17
|
+
mockClient()
|
|
18
|
+
|
|
19
|
+
const FtpConnector = (await import('./FtpConnector')).default
|
|
20
|
+
|
|
21
|
+
let connector
|
|
22
|
+
const storageRootPath = 'dummy storageRootPath'
|
|
23
|
+
const assetsFolder = 'dummy assetsFolder'
|
|
24
|
+
const dummySession = {
|
|
25
|
+
[`ftp-${ConnectorType.STORAGE}`]: {
|
|
26
|
+
host: 'dummy host',
|
|
27
|
+
user: 'dummy user',
|
|
28
|
+
pass: 'dummy pass',
|
|
29
|
+
port: 1234,
|
|
30
|
+
secure: false,
|
|
31
|
+
storageRootPath,
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
const dummyId: WebsiteId = 'dummy id'
|
|
35
|
+
const dummyWebsite: WebsiteData = {
|
|
36
|
+
pages: [],
|
|
37
|
+
assets: [],
|
|
38
|
+
styles: [],
|
|
39
|
+
settings: {},
|
|
40
|
+
fonts: [],
|
|
41
|
+
symbols: [],
|
|
42
|
+
publication: {},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
mockClient()
|
|
47
|
+
connector = new FtpConnector({} as ServerConfig, {
|
|
48
|
+
type: ConnectorType.STORAGE,
|
|
49
|
+
assetsFolder,
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
afterEach(async () => {
|
|
54
|
+
// FIXME: This removes the mock of Client
|
|
55
|
+
//await jest.resetAllMocks()
|
|
56
|
+
// Reset each mock
|
|
57
|
+
Object.keys(mocks).forEach(key => {
|
|
58
|
+
mocks[key].mockClear()
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
describe('FtpConnector website', () => {
|
|
63
|
+
it('should write to FTP', async () => {
|
|
64
|
+
await connector.updateWebsite(dummySession, dummyId, dummyWebsite)
|
|
65
|
+
expect(mocks.uploadFrom).toHaveBeenCalledTimes(1)
|
|
66
|
+
expect(mocks.uploadFrom.mock.calls[0][0]).toBeInstanceOf(Readable)
|
|
67
|
+
expect(mocks.uploadFrom.mock.calls[0][1]).toBe(`${storageRootPath}/${dummyId}/website.json`)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('FtpConnector assets', () => {
|
|
72
|
+
it('should write an asset to FTP', async () => {
|
|
73
|
+
const assets = [{
|
|
74
|
+
path: 'dummy path',
|
|
75
|
+
content: 'dummy content',
|
|
76
|
+
}]
|
|
77
|
+
await connector.writeAssets(dummySession, dummyId, assets)
|
|
78
|
+
expect(mocks.uploadFrom).toHaveBeenCalledTimes(1)
|
|
79
|
+
expect(mocks.uploadFrom.mock.calls[0][0]).toBeInstanceOf(Readable)
|
|
80
|
+
expect(mocks.uploadFrom.mock.calls[0][1]).toBe(`${storageRootPath}/${dummyId}/${assetsFolder}/${assets[0].path}`)
|
|
81
|
+
})
|
|
82
|
+
})
|