@plone/volto 18.0.0-alpha.46 → 18.0.0-alpha.48
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/.eslintrc +0 -1
- package/CHANGELOG.md +64 -0
- package/locales/ca/LC_MESSAGES/volto.po +82 -15
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +87 -20
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +82 -15
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +82 -15
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +82 -15
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +82 -15
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +82 -15
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +82 -15
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +82 -15
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +82 -15
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +82 -15
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +82 -15
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +82 -15
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +82 -15
- package/locales/ro.json +1 -1
- package/locales/volto.pot +83 -16
- package/locales/zh_CN/LC_MESSAGES/volto.po +82 -15
- package/locales/zh_CN.json +1 -1
- package/package.json +11 -9
- package/razzle.config.js +8 -5
- package/src/actions/aliases/aliases.js +27 -7
- package/src/actions/aliases/aliases.test.js +1 -1
- package/src/components/manage/Blocks/Block/Edit.jsx +1 -2
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +5 -2
- package/src/components/manage/Blocks/Block/StyleWrapper.jsx +1 -1
- package/src/components/manage/Blocks/Listing/getAsyncData.js +8 -0
- package/src/components/manage/Blocks/ToC/View.jsx +18 -7
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +2 -20
- package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +2 -19
- package/src/components/manage/Controlpanels/Aliases.jsx +499 -412
- package/src/components/manage/Controlpanels/Aliases.test.jsx +7 -0
- package/src/components/manage/Edit/Edit.jsx +7 -3
- package/src/components/manage/Form/ModalForm.jsx +3 -1
- package/src/components/manage/Toolbar/PersonalTools.jsx +7 -7
- package/src/components/manage/Toolbar/PersonalTools.test.jsx +71 -0
- package/src/components/manage/Widgets/IdWidget.jsx +6 -7
- package/src/components/theme/App/App.jsx +2 -0
- package/src/components/theme/App/App.test.jsx +4 -3
- package/src/components/theme/Login/Login.jsx +1 -2
- package/src/components/theme/RouteAnnouncer/RouteAnnouncer.jsx +64 -0
- package/src/constants/ActionTypes.js +1 -0
- package/src/express-middleware/static.js +2 -2
- package/src/helpers/Api/Api.js +12 -1
- package/src/helpers/Blocks/Blocks.js +73 -33
- package/src/helpers/Blocks/Blocks.test.js +204 -27
- package/src/middleware/api.js +3 -0
- package/src/reducers/content/content.js +12 -0
- package/src/start-server.js +2 -5
- package/types/actions/aliases/aliases.d.ts +8 -1
- package/types/components/manage/Blocks/ToC/View.d.ts +1 -4
- package/types/components/manage/Blocks/ToC/variations/DefaultTocRenderer.d.ts +10 -5
- package/types/components/manage/Blocks/ToC/variations/HorizontalMenu.d.ts +10 -5
- package/types/components/manage/Blocks/ToC/variations/index.d.ts +16 -4
- package/types/components/manage/Contents/__mocks__/index.d.ts +0 -1
- package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
- package/types/components/manage/Controlpanels/index.d.ts +0 -1
- package/types/components/manage/Form/__mocks__/index.d.ts +0 -1
- package/types/components/manage/Form/index.d.ts +0 -1
- package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
- package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
- package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/__mocks__/index.d.ts +0 -1
- package/types/components/manage/Widgets/index.d.ts +2 -3
- package/types/components/theme/RouteAnnouncer/RouteAnnouncer.d.ts +2 -0
- package/types/config/slots.d.ts +1 -1
- package/types/constants/ActionTypes.d.ts +1 -0
- package/types/helpers/Blocks/Blocks.d.ts +10 -1
- package/types/helpers/Helmet/Helmet.d.ts +1 -1
|
@@ -346,11 +346,15 @@ class Edit extends Component {
|
|
|
346
346
|
<>
|
|
347
347
|
<Helmet
|
|
348
348
|
title={
|
|
349
|
-
this.props?.
|
|
349
|
+
this.props?.content?.title
|
|
350
350
|
? this.props.intl.formatMessage(messages.edit, {
|
|
351
|
-
title: this.props
|
|
351
|
+
title: this.props?.content?.title,
|
|
352
352
|
})
|
|
353
|
-
:
|
|
353
|
+
: this.props?.schema?.title
|
|
354
|
+
? this.props.intl.formatMessage(messages.edit, {
|
|
355
|
+
title: this.props.schema.title,
|
|
356
|
+
})
|
|
357
|
+
: null
|
|
354
358
|
}
|
|
355
359
|
>
|
|
356
360
|
{this.props.content?.language && (
|
|
@@ -70,6 +70,7 @@ class ModalForm extends Component {
|
|
|
70
70
|
required: PropTypes.arrayOf(PropTypes.string),
|
|
71
71
|
}).isRequired,
|
|
72
72
|
title: PropTypes.string.isRequired,
|
|
73
|
+
description: PropTypes.objectOf(PropTypes.any),
|
|
73
74
|
formData: PropTypes.objectOf(PropTypes.any),
|
|
74
75
|
submitError: PropTypes.string,
|
|
75
76
|
onSubmit: PropTypes.func.isRequired,
|
|
@@ -211,7 +212,7 @@ class ModalForm extends Component {
|
|
|
211
212
|
* @returns {string} Markup for the component.
|
|
212
213
|
*/
|
|
213
214
|
render() {
|
|
214
|
-
const { schema, onCancel } = this.props;
|
|
215
|
+
const { schema, onCancel, description } = this.props;
|
|
215
216
|
const currentFieldset = schema.fieldsets[this.state.currentTab];
|
|
216
217
|
|
|
217
218
|
const fields = map(currentFieldset.fields, (field) => ({
|
|
@@ -245,6 +246,7 @@ class ModalForm extends Component {
|
|
|
245
246
|
onSubmit={this.onSubmit}
|
|
246
247
|
error={state_errors || Boolean(this.props.submitError)}
|
|
247
248
|
>
|
|
249
|
+
{description}
|
|
248
250
|
<Message error>
|
|
249
251
|
{state_errors ? (
|
|
250
252
|
<FormattedMessage
|
|
@@ -9,11 +9,7 @@ import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
|
|
|
9
9
|
import { Icon } from '@plone/volto/components';
|
|
10
10
|
import { getUser } from '@plone/volto/actions';
|
|
11
11
|
import { Pluggable } from '@plone/volto/components/manage/Pluggable';
|
|
12
|
-
import {
|
|
13
|
-
expandToBackendURL,
|
|
14
|
-
getBaseUrl,
|
|
15
|
-
userHasRoles,
|
|
16
|
-
} from '@plone/volto/helpers';
|
|
12
|
+
import { expandToBackendURL, getBaseUrl } from '@plone/volto/helpers';
|
|
17
13
|
import logoutSVG from '@plone/volto/icons/log-out.svg';
|
|
18
14
|
import rightArrowSVG from '@plone/volto/icons/right-key.svg';
|
|
19
15
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
@@ -50,7 +46,11 @@ const PersonalTools = (props) => {
|
|
|
50
46
|
const token = useSelector((state) => state.userSession.token, shallowEqual);
|
|
51
47
|
const user = useSelector((state) => state.users.user);
|
|
52
48
|
const userId = token ? jwtDecode(token).sub : '';
|
|
53
|
-
|
|
49
|
+
const siteSetupAction = useSelector((state) =>
|
|
50
|
+
state.actions?.actions?.user?.find(
|
|
51
|
+
(action) => action?.id === 'plone_setup',
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
54
|
useEffect(() => {
|
|
55
55
|
dispatch(getUser(userId));
|
|
56
56
|
}, [dispatch, userId]);
|
|
@@ -127,7 +127,7 @@ const PersonalTools = (props) => {
|
|
|
127
127
|
</button>
|
|
128
128
|
</li>
|
|
129
129
|
|
|
130
|
-
{
|
|
130
|
+
{siteSetupAction && (
|
|
131
131
|
<li>
|
|
132
132
|
<Link to="/controlpanel">
|
|
133
133
|
<FormattedMessage id="Site Setup" defaultMessage="Site Setup" />
|
|
@@ -29,6 +29,16 @@ describe('Toolbar Personal Tools component', () => {
|
|
|
29
29
|
is_folderish: true,
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
|
+
actions: {
|
|
33
|
+
actions: {
|
|
34
|
+
user: [
|
|
35
|
+
{
|
|
36
|
+
id: 'plone_setup',
|
|
37
|
+
title: 'Site Setup',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
32
42
|
intl: {
|
|
33
43
|
locale: 'en',
|
|
34
44
|
messages: {},
|
|
@@ -70,6 +80,16 @@ describe('Toolbar Personal Tools component', () => {
|
|
|
70
80
|
is_folderish: true,
|
|
71
81
|
},
|
|
72
82
|
},
|
|
83
|
+
actions: {
|
|
84
|
+
actions: {
|
|
85
|
+
user: [
|
|
86
|
+
{
|
|
87
|
+
id: 'plone_setup',
|
|
88
|
+
title: 'Site Setup',
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
73
93
|
intl: {
|
|
74
94
|
locale: 'en',
|
|
75
95
|
messages: {},
|
|
@@ -112,6 +132,57 @@ describe('Toolbar Personal Tools component', () => {
|
|
|
112
132
|
is_folderish: true,
|
|
113
133
|
},
|
|
114
134
|
},
|
|
135
|
+
actions: {
|
|
136
|
+
actions: {
|
|
137
|
+
user: [
|
|
138
|
+
{
|
|
139
|
+
id: 'plone_setup',
|
|
140
|
+
title: 'Site Setup',
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
intl: {
|
|
146
|
+
locale: 'en',
|
|
147
|
+
messages: {},
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
const component = renderer.create(
|
|
151
|
+
<Provider store={store}>
|
|
152
|
+
<PluggablesProvider>
|
|
153
|
+
<MemoryRouter>
|
|
154
|
+
<PersonalTools
|
|
155
|
+
loadComponent={() => {}}
|
|
156
|
+
theToolbar={{
|
|
157
|
+
current: { getBoundingClientRect: () => ({ width: '320' }) },
|
|
158
|
+
}}
|
|
159
|
+
/>
|
|
160
|
+
</MemoryRouter>
|
|
161
|
+
</PluggablesProvider>
|
|
162
|
+
</Provider>,
|
|
163
|
+
);
|
|
164
|
+
const json = component.toJSON();
|
|
165
|
+
expect(json).toMatchSnapshot();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('renders an Toolbar Personal Tools component without Site Setup access', () => {
|
|
169
|
+
const store = mockStore({
|
|
170
|
+
users: {
|
|
171
|
+
user: {
|
|
172
|
+
fullname: 'regular_user',
|
|
173
|
+
email: 'user@plone.org',
|
|
174
|
+
roles: ['Member'],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
userSession: {
|
|
178
|
+
token: jwt.sign({ sub: 'regular_user' }, 'secret'),
|
|
179
|
+
},
|
|
180
|
+
content: {
|
|
181
|
+
data: {
|
|
182
|
+
'@type': 'Folder',
|
|
183
|
+
is_folderish: true,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
115
186
|
intl: {
|
|
116
187
|
locale: 'en',
|
|
117
188
|
messages: {},
|
|
@@ -7,7 +7,7 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { useSelector, useDispatch } from 'react-redux';
|
|
9
9
|
import { Input } from 'semantic-ui-react';
|
|
10
|
-
import { compact, concat,
|
|
10
|
+
import { compact, concat, map, union, uniq } from 'lodash';
|
|
11
11
|
|
|
12
12
|
import { defineMessages, useIntl } from 'react-intl';
|
|
13
13
|
import { Icon } from '@plone/volto/components';
|
|
@@ -46,8 +46,7 @@ const IdWidget = (props) => {
|
|
|
46
46
|
const intl = useIntl();
|
|
47
47
|
const dispatch = useDispatch();
|
|
48
48
|
const ref = useRef();
|
|
49
|
-
|
|
50
|
-
const indexes = useSelector((state) => keys(state.querystring.indexes));
|
|
49
|
+
const indexes = useSelector((state) => state.querystring.indexes);
|
|
51
50
|
|
|
52
51
|
const [errors, setError] = useState([]);
|
|
53
52
|
const [reservedIds] = useState(
|
|
@@ -62,11 +61,11 @@ const IdWidget = (props) => {
|
|
|
62
61
|
),
|
|
63
62
|
),
|
|
64
63
|
);
|
|
65
|
-
const fieldValidation = (
|
|
64
|
+
const fieldValidation = (value) => {
|
|
66
65
|
const error = [];
|
|
67
66
|
|
|
68
67
|
// Check reserved id's
|
|
69
|
-
if (reservedIds.indexOf(
|
|
68
|
+
if (reservedIds.indexOf(value) !== -1) {
|
|
70
69
|
error.push(intl.formatMessage(messages.reservedId));
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -74,14 +73,14 @@ const IdWidget = (props) => {
|
|
|
74
73
|
if (
|
|
75
74
|
// eslint-disable-next-line no-control-regex
|
|
76
75
|
!/^(?!.*\\)(?!\+\+)(?!@@)(?!.*request)(?!.*contributors)(?!aq_)(?!.*__)(?!_)(?!((^|\/)\.\.?($|\/)|^"\s*"$))(?!.*[A-Z])(?:(?![\r\n<>/?&#\x00-\x1F\x7F])['\x00-\x7F\u0080-\uFFFF. _])*$/.test(
|
|
77
|
-
|
|
76
|
+
value,
|
|
78
77
|
)
|
|
79
78
|
) {
|
|
80
79
|
error.push(intl.formatMessage(messages.invalidCharacters));
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
// Check indexes
|
|
84
|
-
if (
|
|
83
|
+
if (value in indexes) {
|
|
85
84
|
error.push(intl.formatMessage(messages.reservedId));
|
|
86
85
|
}
|
|
87
86
|
|
|
@@ -51,6 +51,7 @@ import clearSVG from '@plone/volto/icons/clear.svg';
|
|
|
51
51
|
import MultilingualRedirector from '@plone/volto/components/theme/MultilingualRedirector/MultilingualRedirector';
|
|
52
52
|
import WorkingCopyToastsFactory from '@plone/volto/components/manage/WorkingCopyToastsFactory/WorkingCopyToastsFactory';
|
|
53
53
|
import LockingToastsFactory from '@plone/volto/components/manage/LockingToastsFactory/LockingToastsFactory';
|
|
54
|
+
import RouteAnnouncer from '@plone/volto/components/theme/RouteAnnouncer/RouteAnnouncer';
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
57
|
* @export
|
|
@@ -191,6 +192,7 @@ export class App extends Component {
|
|
|
191
192
|
</main>
|
|
192
193
|
</Segment>
|
|
193
194
|
</MultilingualRedirector>
|
|
195
|
+
<RouteAnnouncer />
|
|
194
196
|
<Footer />
|
|
195
197
|
<LockingToastsFactory
|
|
196
198
|
content={this.props.content}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import config from '@plone/volto/registry';
|
|
1
2
|
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import configureStore from 'redux-mock-store';
|
|
4
3
|
import { Provider } from 'react-intl-redux';
|
|
5
4
|
import { MemoryRouter } from 'react-router-dom';
|
|
6
|
-
import
|
|
5
|
+
import renderer from 'react-test-renderer';
|
|
6
|
+
import configureStore from 'redux-mock-store';
|
|
7
7
|
|
|
8
8
|
import { __test__ as App } from './App';
|
|
9
9
|
|
|
@@ -64,5 +64,6 @@ describe('App', () => {
|
|
|
64
64
|
);
|
|
65
65
|
const json = component.toJSON();
|
|
66
66
|
expect(json).toMatchSnapshot();
|
|
67
|
+
component.unmount();
|
|
67
68
|
});
|
|
68
69
|
});
|
|
@@ -80,9 +80,8 @@ const Login = (props) => {
|
|
|
80
80
|
const loading = useSelector((state) => state.userSession.login.loading);
|
|
81
81
|
const returnUrl =
|
|
82
82
|
qs.parse(props.location?.search ?? location.search).return_url ||
|
|
83
|
-
location.pathname.replace(/\/
|
|
83
|
+
location.pathname.replace(/\/[^/]*\/?$/, '') ||
|
|
84
84
|
'/';
|
|
85
|
-
|
|
86
85
|
const previousToken = usePrevious(token);
|
|
87
86
|
|
|
88
87
|
useEffect(() => {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
function RouteAnnouncer() {
|
|
4
|
+
const [pageTitle, setPageTitle] = useState('');
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
function updatePage(title) {
|
|
8
|
+
setPageTitle(title);
|
|
9
|
+
document.activeElement.blur();
|
|
10
|
+
}
|
|
11
|
+
function handlePop(event) {
|
|
12
|
+
const pageTitle = event.target.document.title;
|
|
13
|
+
updatePage(pageTitle);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const observer = new MutationObserver((mutationList) => {
|
|
17
|
+
for (const mutation of mutationList) {
|
|
18
|
+
if (mutation.type === 'childList') {
|
|
19
|
+
for (const node of mutation.addedNodes) {
|
|
20
|
+
if (node.nodeType === Node.TEXT_NODE && node.textContent) {
|
|
21
|
+
updatePage(node.textContent);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
observer.observe(document.querySelector('title'), {
|
|
28
|
+
characterData: true,
|
|
29
|
+
attributes: true,
|
|
30
|
+
childList: true,
|
|
31
|
+
subtree: true,
|
|
32
|
+
});
|
|
33
|
+
window.addEventListener('popstate', handlePop);
|
|
34
|
+
|
|
35
|
+
return () => {
|
|
36
|
+
observer.disconnect();
|
|
37
|
+
window.removeEventListener('popstate', handlePop);
|
|
38
|
+
};
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<p
|
|
43
|
+
id="route-announcer"
|
|
44
|
+
role="alert"
|
|
45
|
+
// Off-screen element with 'best' browser support
|
|
46
|
+
style={{
|
|
47
|
+
border: 0,
|
|
48
|
+
clip: 'rect(1px 1px 1px 1px)', // IE-style CSS for compatibility
|
|
49
|
+
height: '1px',
|
|
50
|
+
margin: '-1px',
|
|
51
|
+
overflow: 'hidden',
|
|
52
|
+
padding: 0,
|
|
53
|
+
position: 'absolute',
|
|
54
|
+
width: '1px',
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
wordWrap: 'normal',
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
{pageTitle}
|
|
60
|
+
</p>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default RouteAnnouncer;
|
|
@@ -138,6 +138,7 @@ export const MOVE_CONTENT_RULE = 'MOVE_CONTENT_RULE';
|
|
|
138
138
|
export const GET_ALIASES = 'GET_ALIASES';
|
|
139
139
|
export const ADD_ALIASES = 'ADD_ALIASES';
|
|
140
140
|
export const REMOVE_ALIASES = 'REMOVE_ALIASES';
|
|
141
|
+
export const UPLOAD_ALIASES = 'UPLOAD_ALIASES';
|
|
141
142
|
export const GET_USERSCHEMA = 'GET_USERSCHEMA';
|
|
142
143
|
export const GET_UPGRADE = 'GET_UPGRADE';
|
|
143
144
|
export const POST_UPGRADE = 'POST_UPGRADE';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import
|
|
3
|
+
import { AddonRegistry } from '@plone/registry/addon-registry';
|
|
4
4
|
import config from '@plone/volto/registry';
|
|
5
5
|
|
|
6
6
|
const projectRootPath = path.resolve('.');
|
|
7
|
-
const registry =
|
|
7
|
+
const { registry } = AddonRegistry.init(projectRootPath);
|
|
8
8
|
|
|
9
9
|
const staticDirectory = () => {
|
|
10
10
|
if (process.env.BUILD_DIR) {
|
package/src/helpers/Api/Api.js
CHANGED
|
@@ -50,7 +50,14 @@ class Api {
|
|
|
50
50
|
methods.forEach((method) => {
|
|
51
51
|
this[method] = (
|
|
52
52
|
path,
|
|
53
|
-
{
|
|
53
|
+
{
|
|
54
|
+
params,
|
|
55
|
+
data,
|
|
56
|
+
type,
|
|
57
|
+
headers = {},
|
|
58
|
+
checkUrl = false,
|
|
59
|
+
attach = [],
|
|
60
|
+
} = {},
|
|
54
61
|
) => {
|
|
55
62
|
let request;
|
|
56
63
|
let promise = new Promise((resolve, reject) => {
|
|
@@ -88,6 +95,10 @@ class Api {
|
|
|
88
95
|
request.send(data);
|
|
89
96
|
}
|
|
90
97
|
|
|
98
|
+
attach.forEach((attachment) => {
|
|
99
|
+
request.attach.apply(request, attachment);
|
|
100
|
+
});
|
|
101
|
+
|
|
91
102
|
request.end((err, response) => {
|
|
92
103
|
if (
|
|
93
104
|
checkUrl &&
|
|
@@ -629,11 +629,11 @@ export const styleDataToStyleObject = (key, value, prefix = '') => {
|
|
|
629
629
|
* Generate styles object from data
|
|
630
630
|
*
|
|
631
631
|
* @function buildStyleObjectFromData
|
|
632
|
-
* @param {Object}
|
|
632
|
+
* @param {Object} data A block data object
|
|
633
633
|
* @param {string} prefix The prefix (could be dragged from a recursive call, initially empty)
|
|
634
634
|
* @return {Object} The style object ready to be passed as prop
|
|
635
635
|
*/
|
|
636
|
-
export const buildStyleObjectFromData = (
|
|
636
|
+
export const buildStyleObjectFromData = (data = {}, prefix = '') => {
|
|
637
637
|
// style wrapper object has the form:
|
|
638
638
|
// const styles = {
|
|
639
639
|
// color: 'red',
|
|
@@ -641,39 +641,79 @@ export const buildStyleObjectFromData = (obj = {}, prefix = '') => {
|
|
|
641
641
|
// }
|
|
642
642
|
// Returns: {'--background-color: '#AABBCC'}
|
|
643
643
|
|
|
644
|
-
|
|
645
|
-
Object.
|
|
646
|
-
.
|
|
647
|
-
|
|
648
|
-
(
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
644
|
+
function recursiveBuildStyleObjectFromData(obj, prefix) {
|
|
645
|
+
return Object.fromEntries(
|
|
646
|
+
Object.entries(obj)
|
|
647
|
+
.filter(([k, v]) => k.startsWith('--') || isObject(v))
|
|
648
|
+
.reduce(
|
|
649
|
+
(acc, [k, v]) => [
|
|
650
|
+
...acc,
|
|
651
|
+
// Kept for easy debugging
|
|
652
|
+
// ...(() => {
|
|
653
|
+
// if (isObject(v)) {
|
|
654
|
+
// return Object.entries(
|
|
655
|
+
// buildStyleObjectFromData(
|
|
656
|
+
// v,
|
|
657
|
+
// `${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`,
|
|
658
|
+
// ),
|
|
659
|
+
// );
|
|
660
|
+
// }
|
|
661
|
+
// return [styleDataToStyleObject(k, v, prefix)];
|
|
662
|
+
// })(),
|
|
663
|
+
...(isObject(v)
|
|
664
|
+
? Object.entries(
|
|
665
|
+
recursiveBuildStyleObjectFromData(
|
|
666
|
+
v,
|
|
667
|
+
`${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`, // We don't add a prefix if the key ends with the marker suffix
|
|
668
|
+
),
|
|
669
|
+
)
|
|
670
|
+
: [styleDataToStyleObject(k, v, prefix)]),
|
|
671
|
+
],
|
|
672
|
+
[],
|
|
673
|
+
)
|
|
674
|
+
.filter((v) => !!v),
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// If the block has a `@type`, it's a full data block object
|
|
679
|
+
// Then apply the style enhancers
|
|
680
|
+
if (data['@type']) {
|
|
681
|
+
const styleObj = data.styles || {};
|
|
682
|
+
const stylesFromCSSproperties = recursiveBuildStyleObjectFromData(
|
|
683
|
+
styleObj,
|
|
684
|
+
prefix,
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
let stylesFromObjectStyleEnhancers = {};
|
|
688
|
+
const enhancers = config.getUtilities({
|
|
689
|
+
type: 'styleWrapperStyleObjectEnhancer',
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
enhancers.forEach(({ method }) => {
|
|
693
|
+
stylesFromObjectStyleEnhancers = {
|
|
694
|
+
...stylesFromObjectStyleEnhancers,
|
|
695
|
+
...method(data),
|
|
696
|
+
};
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
return { ...stylesFromCSSproperties, ...stylesFromObjectStyleEnhancers };
|
|
700
|
+
} else {
|
|
701
|
+
return recursiveBuildStyleObjectFromData(data, prefix);
|
|
702
|
+
}
|
|
675
703
|
};
|
|
676
704
|
|
|
705
|
+
/**
|
|
706
|
+
* Find a matching style by name given a style definition
|
|
707
|
+
*
|
|
708
|
+
* @function findStyleByName
|
|
709
|
+
* @param {Object} styleDefinitions An object with the style definitions
|
|
710
|
+
* @param {string} name The name of the style to find
|
|
711
|
+
* @return {Object} The style object of the matching name
|
|
712
|
+
*/
|
|
713
|
+
export function findStyleByName(styleDefinitions, name) {
|
|
714
|
+
return styleDefinitions.find((color) => color.name === name)?.style;
|
|
715
|
+
}
|
|
716
|
+
|
|
677
717
|
/**
|
|
678
718
|
* Return previous/next blocks given the content object and the current block id
|
|
679
719
|
*
|