@silexlabs/silex 3.0.0-alpha.96 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.default +2 -1
- package/README.md +31 -9
- package/dist/client/client/api.d.ts +5 -0
- package/dist/client/client/assetUrl.d.ts +3 -0
- package/dist/client/client/config.d.ts +31 -0
- package/dist/client/client/events.d.ts +7 -1
- package/dist/client/client/grapesjs/PublicationManager.d.ts +2 -1
- package/dist/client/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/client/grapesjs/img.d.ts +6 -0
- package/dist/client/client/grapesjs/index.d.ts +2 -2
- package/dist/client/client/grapesjs/new-page-dialog.d.ts +1 -1
- package/dist/client/client/grapesjs/page-panel.d.ts +1 -1
- package/dist/client/client/grapesjs/project-bar.d.ts +16 -0
- package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/client/grapesjs/rich-text.d.ts +4 -1
- package/dist/client/client/grapesjs/semantic.d.ts +1 -1
- package/dist/client/client/grapesjs/settings-sections.d.ts +15 -0
- package/dist/client/client/grapesjs/settings.d.ts +3 -1
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +1 -1
- 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 +4 -3
- 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 +4 -0
- package/dist/client/constants.d.ts +1 -0
- package/dist/client/css/admin.css +273 -32
- package/dist/client/index.html +2 -1
- package/dist/client/js/main.js +164 -123
- package/dist/client/js/main.js.LICENSE.txt +15 -1
- package/dist/client/types.d.ts +12 -7
- package/dist/plugins/client/client/events.d.ts +7 -1
- package/dist/plugins/client/client/events.js +7 -1
- package/dist/plugins/client/client/events.js.map +1 -1
- package/dist/plugins/client/plugins/client/template.js +108 -58
- package/dist/plugins/client/plugins/client/template.js.map +1 -1
- package/dist/plugins/client/types.d.ts +12 -7
- package/dist/plugins/client/types.js +6 -0
- package/dist/plugins/client/types.js.map +1 -1
- package/dist/plugins/server/constants.d.ts +1 -0
- package/dist/plugins/server/constants.js +2 -1
- package/dist/plugins/server/constants.js.map +1 -1
- package/dist/plugins/server/plugins/server/FtpConnector.d.ts +1 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js +12 -1
- package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
- package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +3 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +72 -35
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
- package/dist/plugins/server/server/config.js +3 -3
- package/dist/plugins/server/server/config.js.map +1 -1
- package/dist/plugins/server/server/connectors/FsHosting.d.ts +1 -0
- package/dist/plugins/server/server/connectors/FsHosting.js +13 -1
- package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -1
- package/dist/plugins/server/server/connectors/FsStorage.d.ts +2 -1
- package/dist/plugins/server/server/connectors/FsStorage.js +29 -25
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
- package/dist/plugins/server/server/connectors/connectors.d.ts +1 -0
- package/dist/plugins/server/server/jobs.js +4 -2
- package/dist/plugins/server/server/jobs.js.map +1 -1
- package/dist/plugins/server/types.d.ts +12 -7
- package/dist/plugins/server/types.js +7 -1
- package/dist/plugins/server/types.js.map +1 -1
- package/dist/server/constants.js +2 -1
- package/dist/server/server/api/publicationApi.js +3 -5
- package/dist/server/server/api/websiteApi.js +26 -7
- package/dist/server/server/cli.js +9 -6
- package/dist/server/server/config.js +3 -3
- package/dist/server/server/connectors/FsHosting.js +13 -1
- package/dist/server/server/connectors/FsStorage.js +28 -25
- package/dist/server/server/jobs.js +4 -2
- package/dist/server/types.js +7 -1
- package/package.json +35 -31
- package/public/assets/favicon.ico +0 -0
- package/public/assets/favicon.png +0 -0
- package/public/assets/logo-silex-small.png +0 -0
- package/src/css/_variables.scss +5 -3
- package/src/css/dialog.scss +22 -1
- package/src/css/fonts.scss +31 -0
- package/src/css/footer.scss +1 -1
- package/src/css/grapesjs-plugins.scss +34 -0
- package/src/css/grapesjs.scss +26 -11
- package/src/css/index.scss +1 -0
- package/src/css/project-bar.scss +11 -7
- package/src/css/silex.scss +58 -5
- package/src/html/index.pug +2 -2
- package/src/ts/client/api.ts +14 -9
- package/src/ts/client/assetUrl.test.ts +145 -42
- package/src/ts/client/assetUrl.ts +29 -10
- package/src/ts/client/config.ts +85 -4
- package/src/ts/client/events.ts +15 -9
- package/src/ts/client/grapesjs/PublicationManager.ts +71 -38
- package/src/ts/client/grapesjs/PublicationUi.ts +13 -11
- package/src/ts/client/grapesjs/css-props.ts +544 -0
- package/src/ts/client/grapesjs/eleventy.ts +2 -5
- package/src/ts/client/grapesjs/footer.ts +24 -9
- package/src/ts/client/grapesjs/img.ts +147 -0
- package/src/ts/client/grapesjs/index.ts +63 -25
- package/src/ts/client/grapesjs/internal-links.test.ts +2 -1
- package/src/ts/client/grapesjs/internal-links.ts +0 -1
- package/src/ts/client/grapesjs/new-page-dialog.ts +2 -3
- package/src/ts/client/grapesjs/page-panel.ts +28 -3
- package/src/ts/client/grapesjs/project-bar.ts +83 -64
- package/src/ts/client/grapesjs/resize-panel.ts +20 -0
- package/src/ts/client/grapesjs/rich-text.ts +21 -13
- package/src/ts/client/grapesjs/semantic.ts +3 -3
- package/src/ts/client/grapesjs/settings-sections.ts +117 -0
- package/src/ts/client/grapesjs/settings.ts +120 -77
- package/src/ts/client/grapesjs/symbolDialogs.ts +2 -3
- package/src/ts/client/grapesjs/view-buttons.ts +42 -0
- package/src/ts/client/index.ts +13 -6
- package/src/ts/client/publication-transformers.test.ts +13 -5
- package/src/ts/client/publication-transformers.ts +60 -47
- package/{dist/plugins/client/client/utils.js → src/ts/client/publish-custom-code-block.ts} +14 -8
- package/{dist/plugins/client/page.js → src/ts/client/publish-fonts.ts} +19 -14
- package/src/ts/client/utils.ts +18 -0
- package/src/ts/constants.ts +1 -0
- package/src/ts/plugins/client/template.ts +112 -60
- package/src/ts/plugins/server/FtpConnector.ts +14 -2
- package/src/ts/plugins/server/GitlabConnector.ts +71 -32
- package/src/ts/server/api/publicationApi.ts +5 -5
- package/src/ts/server/api/websiteApi.ts +51 -17
- package/src/ts/server/cli.ts +7 -5
- package/src/ts/server/config.ts +4 -4
- package/src/ts/server/connectors/FsHosting.ts +11 -5
- package/src/ts/server/connectors/FsStorage.ts +33 -4
- package/src/ts/server/connectors/connectors.ts +1 -1
- package/src/ts/server/jobs.ts +4 -2
- package/src/ts/types.ts +10 -7
- package/dist/plugins/client/client/api.d.ts +0 -85
- package/dist/plugins/client/client/api.js +0 -114
- package/dist/plugins/client/client/api.js.map +0 -1
- package/dist/plugins/client/client/assetUrl.d.ts +0 -51
- package/dist/plugins/client/client/assetUrl.js +0 -224
- package/dist/plugins/client/client/assetUrl.js.map +0 -1
- package/dist/plugins/client/client/config.d.ts +0 -58
- package/dist/plugins/client/client/config.js +0 -90
- package/dist/plugins/client/client/config.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/LoginDialog.d.ts +0 -15
- package/dist/plugins/client/client/grapesjs/LoginDialog.js +0 -195
- package/dist/plugins/client/client/grapesjs/LoginDialog.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/PublicationManager.d.ts +0 -72
- package/dist/plugins/client/client/grapesjs/PublicationManager.js +0 -356
- package/dist/plugins/client/client/grapesjs/PublicationManager.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/PublicationUi.d.ts +0 -62
- package/dist/plugins/client/client/grapesjs/PublicationUi.js +0 -336
- package/dist/plugins/client/client/grapesjs/PublicationUi.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/blocks.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/blocks.js +0 -37
- package/dist/plugins/client/client/grapesjs/blocks.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/breadcrumbs.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/breadcrumbs.js +0 -75
- package/dist/plugins/client/client/grapesjs/breadcrumbs.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/footer.d.ts +0 -2
- package/dist/plugins/client/client/grapesjs/footer.js +0 -28
- package/dist/plugins/client/client/grapesjs/footer.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/index.d.ts +0 -5
- package/dist/plugins/client/client/grapesjs/index.js +0 -313
- package/dist/plugins/client/client/grapesjs/index.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/internal-links.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/internal-links.js +0 -219
- package/dist/plugins/client/client/grapesjs/internal-links.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/new-page-dialog.d.ts +0 -2
- package/dist/plugins/client/client/grapesjs/new-page-dialog.js +0 -83
- package/dist/plugins/client/client/grapesjs/new-page-dialog.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/openImport.d.ts +0 -9
- package/dist/plugins/client/client/grapesjs/openImport.js +0 -74
- package/dist/plugins/client/client/grapesjs/openImport.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/page-panel.d.ts +0 -3
- package/dist/plugins/client/client/grapesjs/page-panel.js +0 -113
- package/dist/plugins/client/client/grapesjs/page-panel.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/project-bar.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/project-bar.js +0 -104
- package/dist/plugins/client/client/grapesjs/project-bar.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/rich-text.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/rich-text.js +0 -31
- package/dist/plugins/client/client/grapesjs/rich-text.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/semantic.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/semantic.js +0 -110
- package/dist/plugins/client/client/grapesjs/semantic.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/settings.d.ts +0 -2
- package/dist/plugins/client/client/grapesjs/settings.js +0 -198
- package/dist/plugins/client/client/grapesjs/settings.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/storage.d.ts +0 -1
- package/dist/plugins/client/client/grapesjs/storage.js +0 -126
- package/dist/plugins/client/client/grapesjs/storage.js.map +0 -1
- package/dist/plugins/client/client/grapesjs/symbolDialogs.d.ts +0 -3
- package/dist/plugins/client/client/grapesjs/symbolDialogs.js +0 -36
- package/dist/plugins/client/client/grapesjs/symbolDialogs.js.map +0 -1
- package/dist/plugins/client/client/publication-transformers.d.ts +0 -41
- package/dist/plugins/client/client/publication-transformers.js +0 -238
- package/dist/plugins/client/client/publication-transformers.js.map +0 -1
- package/dist/plugins/client/client/utils.d.ts +0 -2
- package/dist/plugins/client/client/utils.js.map +0 -1
- package/dist/plugins/client/constants.d.ts +0 -29
- package/dist/plugins/client/constants.js +0 -46
- package/dist/plugins/client/constants.js.map +0 -1
- package/dist/plugins/client/page.d.ts +0 -2
- package/dist/plugins/client/page.js.map +0 -1
- package/dist/plugins/client/plugins/client/11ty.d.ts +0 -17
- package/dist/plugins/client/plugins/client/11ty.js +0 -86
- package/dist/plugins/client/plugins/client/11ty.js.map +0 -1
- package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +0 -2
- package/dist/plugins/client/plugins/client/publicationRenderer.js +0 -170
- package/dist/plugins/client/plugins/client/publicationRenderer.js.map +0 -1
- package/src/ts/plugins/client/11ty.ts +0 -104
- package/src/ts/plugins/client/publicationRenderer.ts +0 -174
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default function(editor) {
|
|
2
|
+
editor.Panels.addPanel({
|
|
3
|
+
id: 'viewsOptions',
|
|
4
|
+
buttons: [{
|
|
5
|
+
id: 'resize',
|
|
6
|
+
// icon for arrow left
|
|
7
|
+
className: 'viewsOptions__size-btn',
|
|
8
|
+
command: 'resize-panel',
|
|
9
|
+
attributes: { title: 'Resize panel' },
|
|
10
|
+
}],
|
|
11
|
+
})
|
|
12
|
+
editor.Commands.add('resize-panel', {
|
|
13
|
+
run: (editor, sender) => {
|
|
14
|
+
document.documentElement.style.setProperty('--viewsPanelWidth', '40%')
|
|
15
|
+
},
|
|
16
|
+
stop: (editor, sender) => {
|
|
17
|
+
document.documentElement.style.setProperty('--viewsPanelWidth', '20%')
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -15,19 +15,27 @@
|
|
|
15
15
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import
|
|
18
|
+
import { RichTextEditorAction } from 'grapesjs'
|
|
19
19
|
|
|
20
20
|
const pluginName = 'richText'
|
|
21
21
|
|
|
22
|
-
export const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
22
|
+
export const orderedList: RichTextEditorAction = {
|
|
23
|
+
name: 'orderedList',
|
|
24
|
+
icon: '1.',
|
|
25
|
+
attributes: { title: 'Ordered List' },
|
|
26
|
+
result: rte => rte.exec('insertOrderedList'),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const unorderedList: RichTextEditorAction = {
|
|
30
|
+
name: 'unorderedList',
|
|
31
|
+
icon: '•',
|
|
32
|
+
//icon: '<i class="fa fa-list-ul"></i>',
|
|
33
|
+
attributes: { title: 'Unordered List' },
|
|
34
|
+
result: rte => rte.exec('insertUnorderedList'),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const richTextPlugin = (editor, opts) => {
|
|
38
|
+
// This doesn't work, it is now added in the editor config
|
|
39
|
+
//editor.RichTextEditor.add('orderedList', orderedList)
|
|
40
|
+
//editor.RichTextEditor.add('unorderedList', unorderedList)
|
|
41
|
+
}
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
import {html, render} from 'lit-html'
|
|
19
19
|
import {map} from 'lit-html/directives/map.js'
|
|
20
|
-
import grapesjs from 'grapesjs/dist/grapes.min.js'
|
|
21
20
|
|
|
22
21
|
// constants
|
|
23
22
|
const pluginName = 'semantic'
|
|
@@ -48,7 +47,7 @@ const tags = [
|
|
|
48
47
|
]
|
|
49
48
|
|
|
50
49
|
// plugin code
|
|
51
|
-
export const semanticPlugin =
|
|
50
|
+
export const semanticPlugin = (editor, opts) => {
|
|
52
51
|
// Add the new trait to all component types
|
|
53
52
|
editor.DomComponents.getTypes().map(type => {
|
|
54
53
|
editor.DomComponents.addType(type.id, {
|
|
@@ -61,6 +60,7 @@ export const semanticPlugin = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
61
60
|
{
|
|
62
61
|
label: 'Tag name',
|
|
63
62
|
type: 'tag-name',
|
|
63
|
+
name: 'tag-name',
|
|
64
64
|
},
|
|
65
65
|
]
|
|
66
66
|
}
|
|
@@ -111,4 +111,4 @@ export const semanticPlugin = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
111
111
|
doRender(elInput, tagName)
|
|
112
112
|
},
|
|
113
113
|
})
|
|
114
|
-
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {live} from 'lit-html/directives/live.js'
|
|
2
|
+
import {html} from 'lit-html'
|
|
3
|
+
import { WebsiteSettings } from '../../types'
|
|
4
|
+
|
|
5
|
+
// ID of the code editor wrapper
|
|
6
|
+
export const idCodeWrapper = 'settings-head-wrapper'
|
|
7
|
+
|
|
8
|
+
// Is the model a site or a page?
|
|
9
|
+
export function isSite(model) { return !!model.getHtml }
|
|
10
|
+
|
|
11
|
+
export interface SettingsSection {
|
|
12
|
+
id: string
|
|
13
|
+
label: string
|
|
14
|
+
render: (settings: WebsiteSettings, model) => any
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This is the settings dialog default sections
|
|
19
|
+
* Each section has an entry in the sidebar
|
|
20
|
+
* Each section render as part of the settings form
|
|
21
|
+
* The form is submitted to save the settings with all FormData
|
|
22
|
+
*/
|
|
23
|
+
export const defaultSections: SettingsSection[] = [{
|
|
24
|
+
id: 'general',
|
|
25
|
+
label: 'General',
|
|
26
|
+
render: (settings, model) => html`
|
|
27
|
+
<div id="settings-general" class="silex-hideable">
|
|
28
|
+
<div class="gjs-sm-sector-title">General</div>
|
|
29
|
+
<div class="silex-form__group col2">
|
|
30
|
+
<label class="silex-form__element">
|
|
31
|
+
<h3>${isSite(model) ? 'Site name' : 'Page name'}</h3>
|
|
32
|
+
<p class="silex-help">${isSite(model) ? 'The project name in the editor, for you to remember what it is about.' : 'Label of the page in the editor, and file name of the published HTML page.'}</p>
|
|
33
|
+
<input type="text" name="name" .value=${live(model.get('name') || '')}/>
|
|
34
|
+
</label>
|
|
35
|
+
<label class="silex-form__element">
|
|
36
|
+
<h3>Website language</h3>
|
|
37
|
+
<p class="silex-help">This is the default language code for this website. Example: en, fr, es...</p>
|
|
38
|
+
<input type="text" name="lang" .value=${live(settings.lang || '')}/>
|
|
39
|
+
</label>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
`,
|
|
43
|
+
}, {
|
|
44
|
+
id: 'seo',
|
|
45
|
+
label: 'SEO',
|
|
46
|
+
render: (settings, model) => html`
|
|
47
|
+
<div id="settings-seo" class="silex-hideable silex-hidden">
|
|
48
|
+
<div class="gjs-sm-sector-title">SEO</div>
|
|
49
|
+
<div class="silex-form__group col2">
|
|
50
|
+
<label class="silex-form__element">
|
|
51
|
+
<h3>Title</h3>
|
|
52
|
+
<p class="silex-help">Title of the browser window, and title in the search engines results. It is used by search engines to find out what your site is talking about. The title should be a maximum of 70 characters long, including spaces.</p>
|
|
53
|
+
<input type="text" name="title" .value=${live(settings.title || '')}/>
|
|
54
|
+
</label>
|
|
55
|
+
<label class="silex-form__element">
|
|
56
|
+
<h3>Description</h3>
|
|
57
|
+
<p class="silex-help">Description displayed by the search engines in search results. It is used by search engines to find out what your site is talking about. It is best to keep meta descriptions between 150 and 160 characters.</p>
|
|
58
|
+
<input type="text" name="description" .value=${live(settings.description || '')}/>
|
|
59
|
+
</label>
|
|
60
|
+
<label class="silex-form__element">
|
|
61
|
+
<h3>Favicon</h3>
|
|
62
|
+
<p class="silex-help">Small image displayed in the browser's address bar and in tabs. The recommended size is 16×16 or 32×32 pixels. This can be a URL or a relative path.</p>
|
|
63
|
+
<input type="text" name="favicon" .value=${live(settings.favicon || '')}/>
|
|
64
|
+
</label>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
`,
|
|
68
|
+
}, {
|
|
69
|
+
id: 'social',
|
|
70
|
+
label: 'Social',
|
|
71
|
+
render: (settings, model) => html`
|
|
72
|
+
<div id="settings-social" class="silex-hideable silex-hidden">
|
|
73
|
+
<div class="gjs-sm-sector-title">Social</div>
|
|
74
|
+
<div class="silex-help">
|
|
75
|
+
<p>Once your website is live, you can use these tools to test sharing: <a target="_blank" href="https://developers.facebook.com/tools/debug/">Facebook</a>,
|
|
76
|
+
<a target="_blank" href="https://cards-dev.twitter.com/validator">Twitter</a>,
|
|
77
|
+
<a target="_blank" href="https://www.linkedin.com/post-inspector/inspect/">Linkedin</a></p>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="silex-form__group col2">
|
|
80
|
+
<label class="silex-form__element">
|
|
81
|
+
<h3>Title</h3>
|
|
82
|
+
<p class="silex-help">The title of your website displayed when a user shares your website on a social network.
|
|
83
|
+
Do not include any branding in this title, just eye-catching phrase, e.g. "Learn everything about fishing".
|
|
84
|
+
Title should be between 60 and 90 characters long.</p>
|
|
85
|
+
<input type="text" name="og:title" .value=${live(settings['og:title'] || '')}/>
|
|
86
|
+
</label>
|
|
87
|
+
<label class="silex-form__element">
|
|
88
|
+
<h3>Description</h3>
|
|
89
|
+
<p class="silex-help">Description displayed when a user shares your website on a social network. Make it catchy, and invite readers to visit your website too, e.g. "Sam's website about fishing, check it out!" Title should be between 60 and 90 characters long.</p>
|
|
90
|
+
<input type="text" name="og:description" .value=${live(settings['og:description'] || '')}/>
|
|
91
|
+
</label>
|
|
92
|
+
<label class="silex-form__element">
|
|
93
|
+
<h3>Image</h3>
|
|
94
|
+
<div class="silex-help">
|
|
95
|
+
<p>Thumbnail image which is displayed when your website is shared on a social network. The optimal size is 1200×627 pixels. At this size, your thumbnail will be big and stand out from the crowd. But do not exceed the 5MB size limit. If you use an image that is smaller than 400 pixels x 209 pixels, it will render as a much smaller thumbnail.</p>
|
|
96
|
+
<p>Please enter the full URL here, e.g. "http://mysite.com/path/to/image.jpg"</p>
|
|
97
|
+
</div>
|
|
98
|
+
<input type="text" name="og:image" .value=${live(settings['og:image'] || '')}/>
|
|
99
|
+
</label>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
`,
|
|
103
|
+
}, {
|
|
104
|
+
id: 'code',
|
|
105
|
+
label: 'Code',
|
|
106
|
+
render: (settings, model) => html`
|
|
107
|
+
<div id="settings-code" class="silex-hideable silex-hidden">
|
|
108
|
+
<div class="gjs-sm-sector-title">Code</div>
|
|
109
|
+
<div class="silex-form__group">
|
|
110
|
+
<label class="silex-form__element" id="${idCodeWrapper}">
|
|
111
|
+
<h3>HTML head</h3>
|
|
112
|
+
<p class="silex-help">HTML code which will be inserted in the HEAD tag.</p>
|
|
113
|
+
</label>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
`,
|
|
117
|
+
}]
|
|
@@ -16,12 +16,18 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import {html, render} from 'lit-html'
|
|
19
|
-
import {
|
|
20
|
-
|
|
19
|
+
import {defaultSections, idCodeWrapper, isSite} from './settings-sections'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @fileoverview This file contains the settings dialog. The config API lets plugins add sections to the settings dialog.
|
|
23
|
+
*/
|
|
21
24
|
|
|
22
25
|
import { WebsiteSettings } from '../../types'
|
|
26
|
+
import { ClientEvent } from '../events'
|
|
27
|
+
|
|
28
|
+
const sectionsSite = [...defaultSections]
|
|
29
|
+
const sectionsPage = [...defaultSections]
|
|
23
30
|
|
|
24
|
-
const pluginName = 'settings-dialog'
|
|
25
31
|
const el = document.createElement('div')
|
|
26
32
|
let modal
|
|
27
33
|
|
|
@@ -31,7 +37,8 @@ declare const VERSION: string
|
|
|
31
37
|
export const cmdOpenSettings = 'open-settings'
|
|
32
38
|
|
|
33
39
|
let version = 'v3'
|
|
34
|
-
|
|
40
|
+
let headEditor = null
|
|
41
|
+
export const settingsDialog = (editor, opts) => {
|
|
35
42
|
// Display Silex version from package.json
|
|
36
43
|
try {
|
|
37
44
|
version = VERSION
|
|
@@ -47,7 +54,7 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
47
54
|
attributes: { class: 'settings-dialog' },
|
|
48
55
|
})
|
|
49
56
|
.onceClose(() => {
|
|
50
|
-
sender.set('active', 0) // Deactivate the button to make it ready to be clicked again
|
|
57
|
+
sender?.set && sender.set('active', 0) // Deactivate the button to make it ready to be clicked again, only in case of a grapesjs button (not in the pages panel)
|
|
51
58
|
editor.stopCommand(cmdOpenSettings) // apparently this is needed to be able to run the command several times
|
|
52
59
|
})
|
|
53
60
|
displaySettings(editor, opts, page)
|
|
@@ -55,14 +62,20 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
55
62
|
const form = el.querySelector('form')
|
|
56
63
|
form.onsubmit = event => {
|
|
57
64
|
event.preventDefault()
|
|
65
|
+
editor.trigger(ClientEvent.SETTINGS_SAVE_START, page)
|
|
58
66
|
saveSettings(editor, opts, page)
|
|
67
|
+
editor.trigger(ClientEvent.SETTINGS_SAVE_END, page)
|
|
59
68
|
editor.stopCommand(cmdOpenSettings)
|
|
60
69
|
}
|
|
61
70
|
form.querySelector('input')?.focus()
|
|
71
|
+
// Notify other plugins
|
|
72
|
+
editor.trigger(ClientEvent.SETTINGS_OPEN, page)
|
|
73
|
+
// Return the dialog
|
|
62
74
|
return modal
|
|
63
75
|
},
|
|
64
76
|
stop: () => {
|
|
65
77
|
modal.close()
|
|
78
|
+
editor.trigger(ClientEvent.SETTINGS_CLOSE)
|
|
66
79
|
},
|
|
67
80
|
})
|
|
68
81
|
// add settings to the website
|
|
@@ -74,93 +87,117 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
74
87
|
const model = editor.getModel()
|
|
75
88
|
model.set('settings', data.settings || {})
|
|
76
89
|
model.set('name', data.name)
|
|
77
|
-
updateDom(editor)
|
|
78
90
|
})
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
// On chrome this is needed to apply the head content to the DOM
|
|
92
|
+
editor.on('storage:end:load', () => {
|
|
93
|
+
setTimeout(() => {
|
|
81
94
|
updateDom(editor)
|
|
82
95
|
})
|
|
83
96
|
})
|
|
84
|
-
|
|
97
|
+
// Normal way to apply the head content to the DOM
|
|
98
|
+
// fix #1559 Custom <head> code must be reapplied
|
|
99
|
+
editor.on('canvas:frame:load', () => {
|
|
100
|
+
updateDom(editor)
|
|
101
|
+
})
|
|
102
|
+
// When the page changes, update the dom
|
|
103
|
+
editor.on('page', (e) => {
|
|
104
|
+
updateDom(editor)
|
|
105
|
+
})
|
|
106
|
+
headEditor = editor.CodeManager.createViewer({
|
|
107
|
+
readOnly: false,
|
|
108
|
+
codeName: 'htmlmixed',
|
|
109
|
+
lineNumbers: true,
|
|
110
|
+
lineWrapping: true,
|
|
111
|
+
autoFormat: false,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function addSection(section, siteOrPage: 'site' | 'page', position: 'first' | 'last' | number) {
|
|
116
|
+
const sections = siteOrPage === 'site' ? sectionsSite : sectionsPage
|
|
117
|
+
if (position === 'first') {
|
|
118
|
+
sections.unshift(section)
|
|
119
|
+
} else if (position === 'last') {
|
|
120
|
+
sections.push(section)
|
|
121
|
+
} else if (typeof position === 'number') {
|
|
122
|
+
sections.splice(position, 0, section)
|
|
123
|
+
} else {
|
|
124
|
+
throw new Error('Invalid position for settings section')
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function removeSection(id, siteOrPage: 'site' | 'page') {
|
|
129
|
+
const sections = siteOrPage === 'site' ? sectionsSite : sectionsPage
|
|
130
|
+
const index = sections.findIndex(section => section.id === id)
|
|
131
|
+
if(index === -1) throw new Error(`Cannot find section with id ${id}`)
|
|
132
|
+
sections.splice(index, 1)
|
|
133
|
+
}
|
|
85
134
|
|
|
86
|
-
// Is the model a site or a page?
|
|
87
|
-
function isSite(model) { return !!model.getHtml }
|
|
88
135
|
|
|
89
136
|
function displaySettings(editor, config, model = editor.getModel()) {
|
|
137
|
+
// Update the model with the current settings
|
|
90
138
|
const settings = model.get('settings') || {} as WebsiteSettings
|
|
91
139
|
model.set('settings', settings)
|
|
140
|
+
// Get the current sections for page or site
|
|
141
|
+
const menuItemsCurrent = isSite(model) ? sectionsSite : sectionsPage
|
|
142
|
+
// Init the current section selection
|
|
143
|
+
let sections = menuItemsCurrent[0]
|
|
92
144
|
render(html`
|
|
93
|
-
<p>The page settings will override site settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
94
145
|
<form class="silex-form">
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<h3>Website language</h3>
|
|
104
|
-
<p>This is the default language code for this website. Example: en, fr, es...</p>
|
|
105
|
-
<input type="text" name="lang" .value=${live(settings.lang || '')}/>
|
|
106
|
-
</label>
|
|
107
|
-
<label class="silex-form__element">
|
|
108
|
-
<h3>Title</h3>
|
|
109
|
-
<p>Title of the browser window, and title in the search engines results. It is used by search engines to find out what your site is talking about. The title should be a maximum of 70 characters long, including spaces.</p>
|
|
110
|
-
<input type="text" name="title" .value=${live(settings.title || '')}/>
|
|
111
|
-
</label>
|
|
112
|
-
<label class="silex-form__element">
|
|
113
|
-
<h3>Description</h3>
|
|
114
|
-
<p>Description displayed by the search engines in search results. It is used by search engines to find out what your site is talking about. It is best to keep meta descriptions between 150 and 160 characters.</p>
|
|
115
|
-
<input type="text" name="description" .value=${live(settings.description || '')}/>
|
|
116
|
-
</label>
|
|
117
|
-
<label class="silex-form__element">
|
|
118
|
-
<h3>Favicon</h3>
|
|
119
|
-
<p>Small image displayed in the browser's address bar and in tabs. The recommended size is 16×16 or 32×32 pixels. This can be a URL or a relative path.</p>
|
|
120
|
-
<input type="text" name="favicon" .value=${live(settings.favicon || '')}/>
|
|
121
|
-
</label>
|
|
122
|
-
</div>
|
|
123
|
-
<h2>Social networks sharing</h2>
|
|
124
|
-
<div>
|
|
125
|
-
<p>Once your website is live, you can use these tools to test sharing: <a target="_blank" href="https://developers.facebook.com/tools/debug/">Facebook</a>,
|
|
126
|
-
<a target="_blank" href="https://cards-dev.twitter.com/validator">Twitter</a>,
|
|
127
|
-
<a target="_blank" href="https://www.linkedin.com/post-inspector/inspect/">Linkedin</a></p>
|
|
128
|
-
</div>
|
|
129
|
-
<div class="silex-form__group col2">
|
|
130
|
-
<label class="silex-form__element">
|
|
131
|
-
<h3>Title</h3>
|
|
132
|
-
<p>The title of your website displayed when a user shares your website on a social network.
|
|
133
|
-
Do not include any branding in this title, just eye-catching phrase, e.g. "Learn everything about fishing".
|
|
134
|
-
Title should be between 60 and 90 characters long.</p>
|
|
135
|
-
<input type="text" name="og:title" .value=${live(settings['og:title'] || '')}/>
|
|
136
|
-
</label>
|
|
137
|
-
<label class="silex-form__element">
|
|
138
|
-
<h3>Description</h3>
|
|
139
|
-
<p>Description displayed when a user shares your website on a social network. Make it catchy, and invite readers to visit your website too, e.g. "Sam's website about fishing, check it out!" Title should be between 60 and 90 characters long.</p>
|
|
140
|
-
<input type="text" name="og:description" .value=${live(settings['og:description'] || '')}/>
|
|
141
|
-
</label>
|
|
142
|
-
<label class="silex-form__element">
|
|
143
|
-
<h3>Image</h3>
|
|
144
|
-
<p>Thumbnail image which is displayed when your website is shared on a social network. The optimal size is 1200×627 pixels. At this size, your thumbnail will be big and stand out from the crowd. But do not exceed the 5MB size limit. If you use an image that is smaller than 400 pixels x 209 pixels, it will render as a much smaller thumbnail.</p>
|
|
145
|
-
<p>Please enter the full URL here, e.g. "http://mysite.com/path/to/image.jpg"</p>
|
|
146
|
-
<input type="text" name="og:image" .value=${live(settings['og:image'] || '')}/>
|
|
147
|
-
</label>
|
|
148
|
-
</div>
|
|
149
|
-
<h2>Code</h2>
|
|
150
|
-
<div class="silex-form__group">
|
|
151
|
-
<label class="silex-form__element">
|
|
152
|
-
<h3>HTML head</h3>
|
|
153
|
-
<p>HTML code which will be inserted in the HEAD tag.</p>
|
|
154
|
-
<textarea name="head" .value=${live(settings.head || '')}></textarea>
|
|
155
|
-
</label>
|
|
146
|
+
<div class="silex-help">
|
|
147
|
+
${isSite(model) ? html`
|
|
148
|
+
<p>Here you can set the name of your website, SEO and social networks sharing data.</p>
|
|
149
|
+
<p>These settings are overriden by the page settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
150
|
+
` : html`
|
|
151
|
+
<p>Here you can set the name of your page, SEO and social networks sharing data.</p>
|
|
152
|
+
<p>These settings override the site settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
153
|
+
`}
|
|
156
154
|
</div>
|
|
155
|
+
<section class="silex-sidebar-dialog">
|
|
156
|
+
<aside class="silex-bar">
|
|
157
|
+
<ul class="silex-list silex-list--menu">
|
|
158
|
+
${menuItemsCurrent.map(item => html`
|
|
159
|
+
<li
|
|
160
|
+
class=${item.id === sections.id ? 'active' : ''}
|
|
161
|
+
@click=${e => {
|
|
162
|
+
e.preventDefault()
|
|
163
|
+
sections = item
|
|
164
|
+
const li = e.target as HTMLElement
|
|
165
|
+
const ul = li.closest('ul')
|
|
166
|
+
const section = li.closest('section')
|
|
167
|
+
const mainItem = section.querySelector(`#settings-${item.id}`)
|
|
168
|
+
// Update active
|
|
169
|
+
Array.from(ul.querySelectorAll('.active')).forEach(el => el.classList.remove('active'))
|
|
170
|
+
li.classList.add('active')
|
|
171
|
+
// Update hidden
|
|
172
|
+
Array.from(section.querySelectorAll('.silex-hideable')).forEach(el => el.classList.add('silex-hidden'))
|
|
173
|
+
mainItem.classList.remove('silex-hidden')
|
|
174
|
+
// This messes up with the save / cancel mechanism
|
|
175
|
+
// displaySettings(editor, config, model)
|
|
176
|
+
// Refresh the code editor just in case it went from hidden to visible
|
|
177
|
+
// This makes it ready to be used when the user clicks on the tab
|
|
178
|
+
headEditor.refresh()
|
|
179
|
+
// Notify other plugins
|
|
180
|
+
editor.trigger(ClientEvent.SETTINGS_SECTION_CHANGE, item.id)
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
183
|
+
${item.label}
|
|
184
|
+
</li>
|
|
185
|
+
`)}
|
|
186
|
+
</ul>
|
|
187
|
+
</aside>
|
|
188
|
+
<main>
|
|
189
|
+
${menuItemsCurrent.map(item => item.render(settings, model))}
|
|
190
|
+
</main>
|
|
191
|
+
</section>
|
|
157
192
|
<footer>
|
|
158
193
|
<p class="silex-version">Silex ${version}</p>
|
|
159
194
|
<input class="silex-button" type="button" @click=${e => editor.stopCommand(cmdOpenSettings)} value="Cancel">
|
|
160
|
-
<input class="silex-button" type="submit" value="
|
|
195
|
+
<input class="silex-button" type="submit" value="Apply">
|
|
161
196
|
</footer>
|
|
162
197
|
</form>
|
|
163
198
|
`, el)
|
|
199
|
+
el.querySelector(`#${idCodeWrapper}`)?.appendChild(headEditor.getElement())
|
|
200
|
+
headEditor.setContent(settings.head || '')
|
|
164
201
|
}
|
|
165
202
|
|
|
166
203
|
function saveSettings(editor, config, model = editor.getModel()) {
|
|
@@ -168,13 +205,19 @@ function saveSettings(editor, config, model = editor.getModel()) {
|
|
|
168
205
|
const formData = new FormData(form)
|
|
169
206
|
const data = Array.from(formData as any)
|
|
170
207
|
.reduce((aggregate, [key, value]) => {
|
|
171
|
-
|
|
208
|
+
// Keep only the values that are set
|
|
209
|
+
if(value !== '') {
|
|
210
|
+
aggregate[key] = value
|
|
211
|
+
}
|
|
172
212
|
return aggregate
|
|
173
213
|
}, {}) as {[key: string]: any}
|
|
174
|
-
|
|
214
|
+
// take the name out to the main model (by design in grapesjs pages)
|
|
175
215
|
const { name, ...settings } = data
|
|
176
216
|
model.set({
|
|
177
|
-
settings
|
|
217
|
+
settings: {
|
|
218
|
+
...data,
|
|
219
|
+
head: headEditor.getContent(),
|
|
220
|
+
},
|
|
178
221
|
name,
|
|
179
222
|
})
|
|
180
223
|
// save if auto save is on
|
|
@@ -15,12 +15,11 @@
|
|
|
15
15
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import * as grapesjs from 'grapesjs/dist/grapes.min.js'
|
|
19
18
|
import { cmdAddSymbol } from '@silexlabs/grapesjs-symbols'
|
|
20
19
|
|
|
21
20
|
export const cmdPromptAddSymbol = 'symbol-prompt-add'
|
|
22
21
|
|
|
23
|
-
export default
|
|
22
|
+
export default (editor, opts) => {
|
|
24
23
|
function getNext(prefix) {
|
|
25
24
|
let idx = 1
|
|
26
25
|
while(editor.Symbols.find(s => s.get('label') === prefix + idx)) {
|
|
@@ -35,4 +34,4 @@ export default grapesjs.plugins.add(name, (editor, opts) => {
|
|
|
35
34
|
editor.runCommand(cmdAddSymbol, { label, icon })
|
|
36
35
|
}
|
|
37
36
|
})
|
|
38
|
-
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
const pasteBtnClass = 'fa fa-fw fa-paste silex-button'
|
|
20
|
+
const disabledClass = ' disabled'
|
|
21
|
+
|
|
22
|
+
export default function(editor) {
|
|
23
|
+
// Add copy/paste buttons in the top bar
|
|
24
|
+
const [copyBtn, pasteBtn] = editor.Panels.addButton('options', [{
|
|
25
|
+
id: 'copy',
|
|
26
|
+
className: 'fa fa-fw fa-copy',
|
|
27
|
+
command: 'core:copy',
|
|
28
|
+
attributes: { title: 'Copy (Ctrl+C)' },
|
|
29
|
+
}, {
|
|
30
|
+
id: 'paste',
|
|
31
|
+
className: pasteBtnClass + disabledClass,
|
|
32
|
+
command: 'core:paste',
|
|
33
|
+
attributes: { title: 'Paste (Ctrl+V)' },
|
|
34
|
+
active: false,
|
|
35
|
+
}])
|
|
36
|
+
|
|
37
|
+
// Disable paste button if clipboard is empty
|
|
38
|
+
editor.EditorModel.on('change:clipboard', (model, value) => {
|
|
39
|
+
const hasClipboard = value && value.length > 0
|
|
40
|
+
pasteBtn.set('className', pasteBtnClass + (hasClipboard ? '' : disabledClass))
|
|
41
|
+
})
|
|
42
|
+
}
|
package/src/ts/client/index.ts
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { assetsPublicationTransformer } from './assetUrl'
|
|
25
24
|
import { ClientConfig } from './config'
|
|
26
25
|
import { ClientEvent } from './events'
|
|
27
26
|
import { initEditor, getEditor } from './grapesjs/index'
|
|
@@ -29,16 +28,18 @@ import { initEditor, getEditor } from './grapesjs/index'
|
|
|
29
28
|
// Expose API to calling app as window.silex
|
|
30
29
|
export * from './expose'
|
|
31
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Expose the config object
|
|
33
|
+
*/
|
|
34
|
+
export let config: ClientConfig
|
|
35
|
+
|
|
32
36
|
/**
|
|
33
37
|
* Start Silex, called from host HTML page with window.silex.start()
|
|
34
38
|
*/
|
|
35
|
-
export async function start(options = {}) {
|
|
36
|
-
|
|
39
|
+
export async function start(options = {}): Promise<void> {
|
|
40
|
+
config = new ClientConfig()
|
|
37
41
|
Object.assign(config, options)
|
|
38
42
|
|
|
39
|
-
// Add the publication transformers which are used to cleanup assets URLs
|
|
40
|
-
config.addPublicationTransformers(assetsPublicationTransformer)
|
|
41
|
-
|
|
42
43
|
// Config file in root folder which may be generated by the server
|
|
43
44
|
await config.addPlugin(config.clientConfigUrl, {})
|
|
44
45
|
|
|
@@ -54,6 +55,7 @@ export async function start(options = {}) {
|
|
|
54
55
|
config.initGrapesConfig()
|
|
55
56
|
|
|
56
57
|
// Start grapesjs
|
|
58
|
+
// Here you can change the config before passing it to grapesjs
|
|
57
59
|
config.emit(ClientEvent.GRAPESJS_START)
|
|
58
60
|
try{
|
|
59
61
|
await initEditor(config.grapesJsConfig)
|
|
@@ -73,6 +75,9 @@ export async function start(options = {}) {
|
|
|
73
75
|
// Init internationalization module
|
|
74
76
|
editor.I18n.setLocale(config.lang)
|
|
75
77
|
|
|
78
|
+
// Add default plugins
|
|
79
|
+
await config.addDefaultPlugins()
|
|
80
|
+
|
|
76
81
|
// Load the site
|
|
77
82
|
editor.StorageManager.setAutosave(false)
|
|
78
83
|
try {
|
|
@@ -94,5 +99,7 @@ export async function start(options = {}) {
|
|
|
94
99
|
document.querySelector('#gjs').classList.remove('silex-dialog-hide')
|
|
95
100
|
config.emit(ClientEvent.STARTUP_END, { editor, config })
|
|
96
101
|
}, 100)
|
|
102
|
+
const um = editor.UndoManager
|
|
103
|
+
um.clear()
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
transformBgImage
|
|
11
11
|
} from './publication-transformers'
|
|
12
12
|
import { ClientConfig } from './config'
|
|
13
|
-
import
|
|
13
|
+
import grapesjs, { Component, Editor, ObjectStrings, Page } from 'grapesjs'
|
|
14
14
|
import { ClientSideFile, ClientSideFileType, PublicationData } from '../types'
|
|
15
15
|
|
|
16
16
|
describe('publication-transformers', () => {
|
|
@@ -23,7 +23,8 @@ describe('publication-transformers', () => {
|
|
|
23
23
|
|
|
24
24
|
beforeEach(() => {
|
|
25
25
|
// Initialize your mocks here
|
|
26
|
-
|
|
26
|
+
/* @ts-ignore */
|
|
27
|
+
editor = grapesjs.init({
|
|
27
28
|
headless: true,
|
|
28
29
|
storageManager: { autoload: false },
|
|
29
30
|
})
|
|
@@ -136,13 +137,20 @@ describe('publication-transformers', () => {
|
|
|
136
137
|
expect(transformPermalink.mock.calls[0][0]).toBe('test.png')
|
|
137
138
|
expect(transformPermalink.mock.calls[0][1]).toBe('asset')
|
|
138
139
|
})
|
|
140
|
+
|
|
139
141
|
it('should transform a style rule with background image', () => {
|
|
140
142
|
expect(transformBgImage(editor, { 'background-image': 'url(test.png)' })).toEqual({ 'background-image': 'url(test.png)' })
|
|
141
143
|
const transformPermalink = transformer.transformPermalink as Mock
|
|
142
144
|
const transformedSrc = 'transformed.png'
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
expect(transformBgImage(editor, { 'background-image': 'url(
|
|
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
|
+
})
|
|
146
154
|
})
|
|
147
155
|
|
|
148
156
|
it('should transform permalinks of background images in inline css', () => {
|