@eeacms/volto-eea-website-theme 1.26.2 → 1.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,5 +44,13 @@ module.exports = {
44
44
  },
45
45
  },
46
46
  },
47
+ rules: {
48
+ 'react/jsx-no-target-blank': [
49
+ 'error',
50
+ {
51
+ allowReferrer: true,
52
+ },
53
+ ],
54
+ },
47
55
  };
48
56
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [1.27.1](https://github.com/eea/volto-eea-website-theme/compare/1.27.0...1.27.1) - 18 January 2024
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix: remove norefferer for seo purposes - refs #263008 [Gabriel - [`fab8094`](https://github.com/eea/volto-eea-website-theme/commit/fab80944fa3267ee4c584d2c4f77480d2270242c)]
12
+
13
+ ### [1.27.0](https://github.com/eea/volto-eea-website-theme/compare/1.26.2...1.27.0) - 17 January 2024
14
+
15
+ #### :rocket: New Features
16
+
17
+ - feat: Put cloneData function for slate block, in order to change the uuids of fragments - refs #261770 [dobri1408 - [`069bffc`](https://github.com/eea/volto-eea-website-theme/commit/069bffcf114a886690408bbc2c2909c298b5e1aa)]
18
+
19
+ #### :bug: Bug Fixes
20
+
21
+ - fix: noreferrer on links - refs #263008 [ichim-david - [`d8f81e0`](https://github.com/eea/volto-eea-website-theme/commit/d8f81e01d9d2666e834ac92b2f34976f25156ea2)]
22
+ - fix: History diff page overlap - refs #262216 [dobri1408 - [`f580b16`](https://github.com/eea/volto-eea-website-theme/commit/f580b16f24faacb9318402699a1b616814840d63)]
23
+
7
24
  ### [1.26.2](https://github.com/eea/volto-eea-website-theme/compare/1.26.1...1.26.2) - 4 January 2024
8
25
 
9
26
  ### [1.26.1](https://github.com/eea/volto-eea-website-theme/compare/1.26.0...1.26.1) - 14 December 2023
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-theme",
3
- "version": "1.26.2",
3
+ "version": "1.27.1",
4
4
  "description": "@eeacms/volto-eea-website-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -133,7 +133,7 @@ export default {
133
133
  Ex. ri-copyright-line. See{' '}
134
134
  <a
135
135
  target="_blank"
136
- rel="noopener noreferrer"
136
+ rel="noopener"
137
137
  href="https://eea.github.io/volto-eea-design-system/docs/webdev/Guidelines/iconography/#icon-set"
138
138
  >
139
139
  Remix Icon set
@@ -80,7 +80,7 @@ export function ImageSchema({ formData, intl }) {
80
80
  href="https://www.w3.org/WAI/tutorials/images/decision-tree/"
81
81
  title={intl.formatMessage(messages.openLinkInNewTab)}
82
82
  target="_blank"
83
- rel="noopener noreferrer"
83
+ rel="noopener"
84
84
  >
85
85
  {intl.formatMessage(messages.AltTextHintLinkText)}
86
86
  </a>{' '}
@@ -117,7 +117,7 @@ export function ImageSchema({ formData, intl }) {
117
117
  Ex. ri-copyright-line. See{' '}
118
118
  <a
119
119
  target="_blank"
120
- rel="noopener noreferrer"
120
+ rel="noopener"
121
121
  href="https://eea.github.io/volto-eea-design-system/docs/webdev/Guidelines/iconography/#icon-set"
122
122
  >
123
123
  Remix Icon set
@@ -95,7 +95,7 @@ export function LeadImageSchema({ formData, intl }) {
95
95
  Ex. ri-copyright-line. See{' '}
96
96
  <a
97
97
  target="_blank"
98
- rel="noopener noreferrer"
98
+ rel="noopener"
99
99
  href="https://eea.github.io/volto-eea-design-system/docs/webdev/Guidelines/iconography/#icon-set"
100
100
  >
101
101
  Remix Icon set
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Diff field component.
3
+ * @module components/manage/Diff/DiffField
4
+ */
5
+
6
+ import React from 'react';
7
+ // import { diffWords as dWords } from 'diff';
8
+ import { join, map } from 'lodash';
9
+ import PropTypes from 'prop-types';
10
+ import { Grid } from 'semantic-ui-react';
11
+ import ReactDOMServer from 'react-dom/server';
12
+ import { Provider } from 'react-intl-redux';
13
+ import { createBrowserHistory } from 'history';
14
+ import { ConnectedRouter } from 'connected-react-router';
15
+ import { useSelector } from 'react-redux';
16
+
17
+ import { Api } from '@plone/volto/helpers';
18
+ import configureStore from '@plone/volto/store';
19
+ import { DefaultView } from '@plone/volto/components/';
20
+ import { serializeNodes } from '@plone/volto-slate/editor/render';
21
+
22
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
23
+
24
+ /**
25
+ * Enhanced diff words utility
26
+ * @function diffWords
27
+ * @param oneStr Field one
28
+ * @param twoStr Field two
29
+ */
30
+
31
+ /**
32
+ * Diff field component.
33
+ * @function DiffField
34
+ * @param {*} one Field one
35
+ * @param {*} two Field two
36
+ * @param {Object} schema Field schema
37
+ * @returns {string} Markup of the component.
38
+ */
39
+ const DiffField = ({
40
+ one,
41
+ two,
42
+ contentOne,
43
+ contentTwo,
44
+ view,
45
+ schema,
46
+ diffLib,
47
+ }) => {
48
+ const language = useSelector((state) => state.intl.locale);
49
+ const readable_date_format = {
50
+ dateStyle: 'full',
51
+ timeStyle: 'short',
52
+ };
53
+ const splitWords = (str) => {
54
+ if (!str) return [];
55
+ const splitedArray = [];
56
+ let elementCurent = '';
57
+ let insideTag = false;
58
+ for (let i = 0; i < str.length; i++)
59
+ if (str[i] === '<') {
60
+ if (elementCurent) splitedArray.push(elementCurent);
61
+ elementCurent = '<';
62
+ insideTag = true;
63
+ } else if (str[i] === '>') {
64
+ elementCurent += '>';
65
+ splitedArray.push(elementCurent);
66
+ elementCurent = '';
67
+ insideTag = false;
68
+ } else if (str[i] === ' ' && insideTag === false) {
69
+ elementCurent += ' ';
70
+ splitedArray.push(elementCurent);
71
+ elementCurent = '';
72
+ } else elementCurent += str[i];
73
+ if (elementCurent) splitedArray.push(elementCurent);
74
+ return splitedArray;
75
+ };
76
+
77
+ const diffWords = (oneStr, twoStr) => {
78
+ return diffLib.diffArrays(splitWords(oneStr), splitWords(twoStr));
79
+ };
80
+
81
+ let parts, oneArray, twoArray;
82
+ if (schema.widget && schema.title !== 'Data sources and providers') {
83
+ switch (schema.widget) {
84
+ case 'richtext':
85
+ parts = diffWords(one?.data, two?.data);
86
+ break;
87
+ case 'datetime':
88
+ parts = diffWords(
89
+ new Intl.DateTimeFormat(language, readable_date_format)
90
+ .format(new Date(one))
91
+ .replace('\u202F', ' '),
92
+ new Intl.DateTimeFormat(language, readable_date_format)
93
+ .format(new Date(two))
94
+ .replace('\u202F', ' '),
95
+ );
96
+ break;
97
+ case 'json': {
98
+ const api = new Api();
99
+ const history = createBrowserHistory();
100
+ const store = configureStore(window.__data, history, api);
101
+ parts = diffWords(
102
+ ReactDOMServer.renderToStaticMarkup(
103
+ <Provider store={store}>
104
+ <ConnectedRouter history={history}>
105
+ <DefaultView content={contentOne} />
106
+ </ConnectedRouter>
107
+ </Provider>,
108
+ ),
109
+ ReactDOMServer.renderToStaticMarkup(
110
+ <Provider store={store}>
111
+ <ConnectedRouter history={history}>
112
+ <DefaultView content={contentTwo} />
113
+ </ConnectedRouter>
114
+ </Provider>,
115
+ ),
116
+ );
117
+ break;
118
+ }
119
+ case 'slate': {
120
+ const api = new Api();
121
+ const history = createBrowserHistory();
122
+ const store = configureStore(window.__data, history, api);
123
+ parts = diffWords(
124
+ ReactDOMServer.renderToStaticMarkup(
125
+ <Provider store={store}>
126
+ <ConnectedRouter history={history}>
127
+ {serializeNodes(one)}
128
+ </ConnectedRouter>
129
+ </Provider>,
130
+ ),
131
+ ReactDOMServer.renderToStaticMarkup(
132
+ <Provider store={store}>
133
+ <ConnectedRouter history={history}>
134
+ {serializeNodes(two)}
135
+ </ConnectedRouter>
136
+ </Provider>,
137
+ ),
138
+ );
139
+ break;
140
+ }
141
+ case 'temporal': {
142
+ if (one?.temporal?.length > 0 && two.temporal?.length > 0) {
143
+ let firstString = one.temporal.reduce((acc, cur) => {
144
+ return acc + cur?.label + ', ';
145
+ }, '');
146
+ firstString = firstString.substring(0, firstString.length - 2);
147
+ let secondString = two.temporal.reduce((acc, cur) => {
148
+ return acc + cur?.label + ', ';
149
+ }, '');
150
+ secondString = secondString.substring(0, secondString.length - 2);
151
+ parts = diffWords(firstString, secondString);
152
+ }
153
+ break;
154
+ }
155
+ case 'geolocation': {
156
+ if (one?.geolocation?.length > 0 && two.geolocation?.length > 0) {
157
+ let firstString = one.geolocation.reduce((acc, cur) => {
158
+ return acc + cur?.label + ', ';
159
+ }, '');
160
+ firstString = firstString.substring(0, firstString.length - 2);
161
+ let secondString = two.geolocation.reduce((acc, cur) => {
162
+ return acc + cur?.label + ', ';
163
+ }, '');
164
+ secondString = secondString.substring(0, secondString.length - 2);
165
+ parts = diffWords(firstString, secondString);
166
+ }
167
+ break;
168
+ }
169
+ case 'textarea':
170
+ default:
171
+ parts = diffWords(one, two);
172
+ break;
173
+ }
174
+ } else if (schema.title === 'Data sources and providers') {
175
+ if (one?.data?.length > 0 && two.data?.length > 0) {
176
+ let firstString = one.data.reduce((acc, cur) => {
177
+ return acc + cur?.title + ', ' + cur?.organisation + '<br/>';
178
+ }, '');
179
+ firstString = firstString.substring(0, firstString.length - 2);
180
+ let secondString = two.data.reduce((acc, cur) => {
181
+ return acc + cur?.title + ', ' + cur?.organisation + '<br/>';
182
+ }, '');
183
+ secondString = secondString.substring(0, secondString.length - 2);
184
+ parts = diffWords(firstString, secondString);
185
+ }
186
+ } else if (schema.type === 'object') {
187
+ parts = diffWords(one?.filename || one, two?.filename || two);
188
+ } else if (schema.type === 'array') {
189
+ oneArray = (one || []).map((i) => i?.title || i);
190
+ twoArray = (two || []).map((j) => j?.title || j);
191
+ parts = diffWords(oneArray, twoArray);
192
+ } else {
193
+ parts = diffWords(one?.title || one, two?.title || two);
194
+ }
195
+
196
+ return (
197
+ <Grid data-testid="DiffField">
198
+ <Grid.Row>
199
+ <Grid.Column width={12}>{schema.title}</Grid.Column>
200
+ </Grid.Row>
201
+
202
+ {view === 'split' && (
203
+ <Grid.Row>
204
+ <Grid.Column width={6} verticalAlign="top">
205
+ <span
206
+ dangerouslySetInnerHTML={{
207
+ __html: join(
208
+ map(parts, (part) => {
209
+ let combined = (part.value || []).reduce((acc, value) => {
210
+ if (
211
+ part.removed &&
212
+ !value.includes('<') &&
213
+ !value.includes('>') &&
214
+ !value.includes('>') &&
215
+ !value.includes('</') &&
216
+ !value.includes('"') &&
217
+ !value.includes('src') &&
218
+ !value.includes('href') &&
219
+ !value.includes('=')
220
+ )
221
+ return acc + `<span class="deletion">${value}</span>`;
222
+ if (
223
+ part.added &&
224
+ !value.includes('<') &&
225
+ !value.includes('>') &&
226
+ !value.includes('>') &&
227
+ !value.includes('</') &&
228
+ !value.includes('"') &&
229
+ !value.includes('src') &&
230
+ !value.includes('href') &&
231
+ !value.includes('=')
232
+ )
233
+ return acc;
234
+ return acc + value;
235
+ }, '');
236
+ return combined;
237
+ }),
238
+ '',
239
+ ),
240
+ }}
241
+ />
242
+ </Grid.Column>
243
+ <Grid.Column width={6} verticalAlign="top">
244
+ <span
245
+ dangerouslySetInnerHTML={{
246
+ __html: join(
247
+ map(parts, (part) => {
248
+ let combined = (part.value || []).reduce((acc, value) => {
249
+ if (
250
+ part.added &&
251
+ !value.includes('<') &&
252
+ !value.includes('>') &&
253
+ !value.includes('>') &&
254
+ !value.includes('</') &&
255
+ !value.includes('"') &&
256
+ !value.includes('src') &&
257
+ !value.includes('href') &&
258
+ !value.includes('=')
259
+ )
260
+ return acc + `<span class="addition">${value}</span>`;
261
+ if (
262
+ part.removed &&
263
+ !value.includes('<') &&
264
+ !value.includes('>') &&
265
+ !value.includes('>') &&
266
+ !value.includes('</') &&
267
+ !value.includes('"') &&
268
+ !value.includes('src') &&
269
+ !value.includes('href') &&
270
+ !value.includes('=')
271
+ )
272
+ return acc;
273
+ return acc + value;
274
+ }, '');
275
+ return combined;
276
+ }),
277
+ '',
278
+ ),
279
+ }}
280
+ />
281
+ </Grid.Column>
282
+ </Grid.Row>
283
+ )}
284
+ {view === 'unified' && (
285
+ <Grid.Row>
286
+ <Grid.Column width={16} verticalAlign="top">
287
+ <span
288
+ dangerouslySetInnerHTML={{
289
+ __html: join(
290
+ map(parts, (part) => {
291
+ let combined = (part.value || []).reduce((acc, value) => {
292
+ if (
293
+ part.removed &&
294
+ !value.includes('<') &&
295
+ !value.includes('>') &&
296
+ !value.includes('>') &&
297
+ !value.includes('</') &&
298
+ !value.includes('"') &&
299
+ !value.includes('src') &&
300
+ !value.includes('href') &&
301
+ !value.includes('=')
302
+ )
303
+ return acc + `<span class="deletion">${value}</span>`;
304
+
305
+ if (
306
+ part.added &&
307
+ !value.includes('<') &&
308
+ !value.includes('>') &&
309
+ !value.includes('>') &&
310
+ !value.includes('</') &&
311
+ !value.includes('"') &&
312
+ !value.includes('src') &&
313
+ !value.includes('href') &&
314
+ !value.includes('=')
315
+ )
316
+ return acc + `<span class="addition">${value}</span>`;
317
+
318
+ return acc + value;
319
+ }, '');
320
+ return combined;
321
+ }),
322
+ '',
323
+ ),
324
+ }}
325
+ />
326
+ </Grid.Column>
327
+ </Grid.Row>
328
+ )}
329
+ </Grid>
330
+ );
331
+ };
332
+
333
+ /**
334
+ * Property types.
335
+ * @property {Object} propTypes Property types.
336
+ * @static
337
+ */
338
+ DiffField.propTypes = {
339
+ one: PropTypes.any.isRequired,
340
+ two: PropTypes.any.isRequired,
341
+ contentOne: PropTypes.any,
342
+ contentTwo: PropTypes.any,
343
+ view: PropTypes.string.isRequired,
344
+ schema: PropTypes.shape({
345
+ widget: PropTypes.string,
346
+ type: PropTypes.string,
347
+ title: PropTypes.string,
348
+ }).isRequired,
349
+ };
350
+
351
+ export default injectLazyLibs('diffLib')(DiffField);
@@ -0,0 +1,154 @@
1
+ /*
2
+ * UniversalLink
3
+ * @module components/UniversalLink
4
+ * Removed noreferrer from rel attribute
5
+ */
6
+
7
+ import React from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { HashLink as Link } from 'react-router-hash-link';
10
+ import { useSelector } from 'react-redux';
11
+ import {
12
+ flattenToAppURL,
13
+ isInternalURL,
14
+ URLUtils,
15
+ } from '@plone/volto/helpers/Url/Url';
16
+
17
+ import config from '@plone/volto/registry';
18
+
19
+ const UniversalLink = ({
20
+ href,
21
+ item = null,
22
+ openLinkInNewTab,
23
+ download = false,
24
+ children,
25
+ className = null,
26
+ title = null,
27
+ ...props
28
+ }) => {
29
+ const token = useSelector((state) => state.userSession?.token);
30
+
31
+ let url = href;
32
+ if (!href && item) {
33
+ if (!item['@id']) {
34
+ // eslint-disable-next-line no-console
35
+ console.error(
36
+ 'Invalid item passed to UniversalLink',
37
+ item,
38
+ props,
39
+ children,
40
+ );
41
+ url = '#';
42
+ } else {
43
+ //case: generic item
44
+ url = flattenToAppURL(item['@id']);
45
+
46
+ //case: item like a Link
47
+ let remoteUrl = item.remoteUrl || item.getRemoteUrl;
48
+ if (!token && remoteUrl) {
49
+ url = remoteUrl;
50
+ }
51
+
52
+ //case: item of type 'File'
53
+ if (
54
+ !token &&
55
+ config.settings.downloadableObjects.includes(item['@type'])
56
+ ) {
57
+ url = `${url}/@@download/file`;
58
+ }
59
+
60
+ if (
61
+ !token &&
62
+ config.settings.viewableInBrowserObjects.includes(item['@type'])
63
+ ) {
64
+ url = `${url}/@@display-file/file`;
65
+ }
66
+ }
67
+ }
68
+
69
+ const isExternal = !isInternalURL(url);
70
+
71
+ const isDownload = (!isExternal && url.includes('@@download')) || download;
72
+ const isDisplayFile =
73
+ (!isExternal && url.includes('@@display-file')) || false;
74
+
75
+ const checkedURL = URLUtils.checkAndNormalizeUrl(url);
76
+
77
+ url = checkedURL.url;
78
+ let tag = (
79
+ <Link
80
+ to={flattenToAppURL(url)}
81
+ target={openLinkInNewTab ?? false ? '_blank' : null}
82
+ title={title}
83
+ className={className}
84
+ smooth={config.settings.hashLinkSmoothScroll}
85
+ {...props}
86
+ >
87
+ {children}
88
+ </Link>
89
+ );
90
+
91
+ if (isExternal) {
92
+ tag = (
93
+ <a
94
+ href={url}
95
+ title={title}
96
+ target={
97
+ !checkedURL.isMail &&
98
+ !checkedURL.isTelephone &&
99
+ !(openLinkInNewTab === false)
100
+ ? '_blank'
101
+ : null
102
+ }
103
+ rel="noopener"
104
+ className={className}
105
+ {...props}
106
+ >
107
+ {children}
108
+ </a>
109
+ );
110
+ } else if (isDownload) {
111
+ tag = (
112
+ <a
113
+ href={flattenToAppURL(url)}
114
+ download
115
+ title={title}
116
+ className={className}
117
+ {...props}
118
+ >
119
+ {children}
120
+ </a>
121
+ );
122
+ } else if (isDisplayFile) {
123
+ tag = (
124
+ <a
125
+ href={flattenToAppURL(url)}
126
+ title={title}
127
+ rel="noopener"
128
+ className={className}
129
+ {...props}
130
+ >
131
+ {children}
132
+ </a>
133
+ );
134
+ }
135
+ return tag;
136
+ };
137
+
138
+ UniversalLink.propTypes = {
139
+ href: PropTypes.string,
140
+ openLinkInNewTab: PropTypes.bool,
141
+ download: PropTypes.bool,
142
+ className: PropTypes.string,
143
+ title: PropTypes.string,
144
+ item: PropTypes.shape({
145
+ '@id': PropTypes.string.isRequired,
146
+ remoteUrl: PropTypes.string, //of plone @type 'Link'
147
+ }),
148
+ children: PropTypes.oneOfType([
149
+ PropTypes.arrayOf(PropTypes.node),
150
+ PropTypes.node,
151
+ ]),
152
+ };
153
+
154
+ export default UniversalLink;
@@ -0,0 +1,27 @@
1
+ //this should be deleted when upgraded to a volto version that supports App Extras exceptions
2
+ import React from 'react';
3
+ import { matchPath } from 'react-router';
4
+ import config from '@plone/volto/registry';
5
+
6
+ const AppExtras = (props) => {
7
+ const { settings } = config;
8
+ const { appExtras = [] } = settings;
9
+ const { pathname } = props;
10
+ const active = appExtras
11
+ .map((reg) => {
12
+ const excluded = matchPath(pathname, reg.exclude);
13
+ if (excluded) return null;
14
+ const match = matchPath(pathname, reg.match);
15
+ return match ? { reg, match } : null;
16
+ })
17
+ .filter((reg) => reg);
18
+
19
+ return active.map(({ reg: { component, props: extraProps }, match }, i) => {
20
+ const Insert = component;
21
+ return (
22
+ <Insert key={`appextra-${i}`} match={match} {...props} {...extraProps} />
23
+ );
24
+ });
25
+ };
26
+
27
+ export default AppExtras;
@@ -116,7 +116,7 @@ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
116
116
  <a
117
117
  href="https://europa.eu/european-union/contact/institutions-bodies_en"
118
118
  target="_blank"
119
- rel="noreferrer"
119
+ rel="noopener"
120
120
  onKeyDown={(evt) => evt.stopPropagation()}
121
121
  >
122
122
  See all EU institutions and bodies
@@ -140,7 +140,7 @@ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
140
140
  href={item.href}
141
141
  className="site"
142
142
  target="_blank"
143
- rel="noreferrer"
143
+ rel="noopener"
144
144
  onKeyDown={(evt) => evt.stopPropagation()}
145
145
  >
146
146
  {item.title}
package/src/index.js CHANGED
@@ -29,6 +29,9 @@ import installSlate from './slate';
29
29
  import installReducers from './reducers';
30
30
  import installMiddlewares from './middleware';
31
31
 
32
+ import { nanoid } from '@plone/volto-slate/utils';
33
+ import { v4 as uuid } from 'uuid';
34
+
32
35
  import * as eea from './config';
33
36
  import React from 'react';
34
37
 
@@ -85,11 +88,7 @@ function tabVariationCustomization(tabs_block_variations, config) {
85
88
  innerSchema.properties.icon.description = (
86
89
  <>
87
90
  Ex. ri-home-line. See{' '}
88
- <a
89
- target="_blank"
90
- rel="noopener noreferrer"
91
- href="https://remixicon.com/"
92
- >
91
+ <a target="_blank" rel="noopener" href="https://remixicon.com/">
93
92
  Remix Icon set
94
93
  </a>
95
94
  </>
@@ -98,6 +97,7 @@ function tabVariationCustomization(tabs_block_variations, config) {
98
97
  };
99
98
  return schema;
100
99
  };
100
+
101
101
  const oldDefaultSchemaEnhancer = defaultVariation.schemaEnhancer;
102
102
  defaultVariation.schemaEnhancer = (props) => {
103
103
  const newSchema = oldDefaultSchemaEnhancer(props);
@@ -110,7 +110,6 @@ function tabVariationCustomization(tabs_block_variations, config) {
110
110
  ];
111
111
  return newSchema;
112
112
  };
113
-
114
113
  const oldHorizontalSchemaEnhancer = horizontalVariation.schemaEnhancer;
115
114
  horizontalVariation.schemaEnhancer = (props) => {
116
115
  const newSchema = oldHorizontalSchemaEnhancer(props);
@@ -139,6 +138,40 @@ const applyConfig = (config) => {
139
138
  if (config.settings?.serverConfig?.extractScripts) {
140
139
  config.settings.serverConfig.extractScripts.errorPages = true;
141
140
  }
141
+ // Set cloneData function for slate block, in order to change the uuids of fragments in the copy process
142
+ if (config.blocks?.blocksConfig?.slate) {
143
+ config.blocks.blocksConfig.slate.cloneData = (data) => {
144
+ const replaceAllUidsWithNewOnes = (value) => {
145
+ if (value?.children?.length > 0) {
146
+ const newChildren = value.children.map((childrenData) => {
147
+ if (childrenData?.data?.uid) {
148
+ return {
149
+ ...childrenData,
150
+ data: { ...childrenData.data, uid: nanoid(5) },
151
+ };
152
+ }
153
+ return childrenData;
154
+ });
155
+ return {
156
+ ...value,
157
+ children: newChildren,
158
+ };
159
+ }
160
+ return value;
161
+ };
162
+ return [
163
+ uuid(),
164
+ {
165
+ ...data,
166
+ value: [
167
+ ...(data?.value || []).map((value) =>
168
+ replaceAllUidsWithNewOnes(value),
169
+ ),
170
+ ],
171
+ },
172
+ ];
173
+ };
174
+ }
142
175
 
143
176
  // Disable tags on View
144
177
  config.settings.showTags = false;
package/src/index.test.js CHANGED
@@ -144,7 +144,7 @@ describe('applyConfig', () => {
144
144
  { match: '', component: 'MockedDraftBackground' },
145
145
  { match: '', component: 'MockedSubsiteClass' },
146
146
  { match: '', component: BaseTag },
147
- { match: '*', component: 'MockedRemoveSchema' },
147
+ { match: '*', exclude: '/**/diff', component: 'MockedRemoveSchema' },
148
148
  ]);
149
149
  expect(config.settings.available_colors).toEqual(eea.colors);
150
150
  expect(config.settings.hasLanguageDropdown).toBe(false);
@@ -303,7 +303,7 @@ describe('applyConfig', () => {
303
303
  { match: '', component: 'MockedDraftBackground' },
304
304
  { match: '', component: 'MockedSubsiteClass' },
305
305
  { match: '', component: BaseTag },
306
- { match: '*', component: 'MockedRemoveSchema' },
306
+ { match: '*', exclude: '/**/diff', component: 'MockedRemoveSchema' },
307
307
  ]);
308
308
  expect(config.settings.available_colors).toEqual(eea.colors);
309
309
  expect(config.settings.hasLanguageDropdown).toBe(false);
@@ -9,6 +9,7 @@ export default function applyConfig(config) {
9
9
  ...(config.settings.appExtras || []),
10
10
  {
11
11
  match: '*',
12
+ exclude: '/**/diff',
12
13
  component: RemoveSchema,
13
14
  },
14
15
  ];