@plone/volto 15.1.0 → 15.2.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/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "15.1.0",
12
+ "version": "15.2.0",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "git@github.com:plone/volto.git"
@@ -296,6 +296,7 @@
296
296
  "cypress-axe": "0.12.2",
297
297
  "cypress-file-upload": "5.0.7",
298
298
  "debug": "4.3.2",
299
+ "deep-freeze": "0.0.1",
299
300
  "dependency-graph": "0.10.0",
300
301
  "detect-browser": "5.1.0",
301
302
  "diff": "3.5.0",
package/razzle.config.js CHANGED
@@ -5,6 +5,7 @@ const nodeExternals = require('webpack-node-externals');
5
5
  const LoadablePlugin = require('@loadable/webpack-plugin');
6
6
  const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
7
7
  const fs = require('fs');
8
+ const { pickBy } = require('lodash');
8
9
  const RootResolverPlugin = require('./webpack-plugins/webpack-root-resolver');
9
10
  const RelativeResolverPlugin = require('./webpack-plugins/webpack-relative-resolver');
10
11
  const createAddonsLoader = require('./create-addons-loader');
@@ -188,7 +189,7 @@ const defaultModify = ({
188
189
 
189
190
  const addonsLoaderPath = createAddonsLoader(
190
191
  registry.getAddonDependencies(),
191
- registry.packages,
192
+ registry.getAddons(),
192
193
  );
193
194
 
194
195
  config.resolve.plugins = [
@@ -230,15 +231,17 @@ const defaultModify = ({
230
231
  if (packageJson.name !== '@plone/volto') {
231
232
  include.push(fs.realpathSync(`${registry.voltoPath}/src`));
232
233
  }
234
+
233
235
  // Add babel support external (ie. node_modules npm published packages)
234
- if (registry.addonNames && registry.addonNames.length > 0) {
235
- registry.addonNames.forEach((addon) => {
236
+ const packagesNames = Object.keys(registry.packages);
237
+ if (registry.packages && packagesNames.length > 0) {
238
+ packagesNames.forEach((addon) => {
236
239
  const p = fs.realpathSync(registry.packages[addon].modulePath);
237
240
  if (include.indexOf(p) === -1) {
238
241
  include.push(p);
239
242
  }
240
243
  });
241
- addonsAsExternals = registry.addonNames.map((addon) => new RegExp(addon));
244
+ addonsAsExternals = packagesNames.map((addon) => new RegExp(addon));
242
245
  }
243
246
 
244
247
  if (process.env.ADDONS) {
@@ -250,9 +253,12 @@ const defaultModify = ({
250
253
  if (include.indexOf(p) === -1) {
251
254
  include.push(p);
252
255
  }
253
- addonsAsExternals = registry.addonNames.map(
254
- (normalizedAddonName) => new RegExp(normalizedAddonName),
255
- );
256
+ addonsAsExternals = [
257
+ ...addonsAsExternals,
258
+ ...packagesNames.map(
259
+ (normalizedAddonName) => new RegExp(normalizedAddonName),
260
+ ),
261
+ ];
256
262
  });
257
263
  }
258
264
 
@@ -25,7 +25,7 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
25
25
  {items.map((item) => (
26
26
  <div className="listing-item" key={item['@id']}>
27
27
  <ConditionalLink item={item} condition={!isEditMode}>
28
- <Component componentName="PreviewImage" item={item} />
28
+ <Component componentName="PreviewImage" item={item} alt="" />
29
29
  <div className="listing-body">
30
30
  <h3>{item.title ? item.title : item.id}</h3>
31
31
  <p>{item.description}</p>
@@ -53,8 +53,8 @@ const VersionOverview = ({
53
53
  <p>{intl.formatMessage(messages.no_addons)}</p>
54
54
  ) : (
55
55
  <ul style={{ fontSize: '16px', fontFamily: 'Monospace' }}>
56
- {Object.keys(addonsInfo).map((addon) => (
57
- <li>{`${addon} ${addonsInfo[addon].version || ''}`}</li>
56
+ {addonsInfo.map((addon) => (
57
+ <li>{`${addon.name} ${addon.version || ''}`}</li>
58
58
  ))}
59
59
  </ul>
60
60
  )}
@@ -10,12 +10,12 @@ import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/defau
10
10
  *
11
11
  */
12
12
  function PreviewImage(props) {
13
- const { item, size = 'preview', ...rest } = props;
13
+ const { item, size = 'preview', alt, ...rest } = props;
14
14
  const src = item.image_field
15
15
  ? flattenToAppURL(`${item['@id']}/@@images/${item.image_field}/${size}`)
16
16
  : DefaultImageSVG;
17
17
 
18
- return <img src={src} alt={item.title} {...rest} />;
18
+ return <img src={src} alt={alt ?? item.title} {...rest} />;
19
19
  }
20
20
 
21
21
  PreviewImage.propTypes = {
@@ -62,4 +62,28 @@ describe('PreviewImage', () => {
62
62
  const json = component.toJSON();
63
63
  expect(json).toMatchSnapshot();
64
64
  });
65
+
66
+ it('renders a fallback image with alt prop empty', () => {
67
+ const item = {
68
+ title: 'Item title',
69
+ '@id': 'http://localhost:3000/something',
70
+ };
71
+ const component = renderer.create(
72
+ <PreviewImage item={item} className="extra" alt="" />,
73
+ );
74
+ const json = component.toJSON();
75
+ expect(json).toMatchSnapshot();
76
+ });
77
+
78
+ it('renders a fallback image with alt prop', () => {
79
+ const item = {
80
+ title: 'Item title',
81
+ '@id': 'http://localhost:3000/something',
82
+ };
83
+ const component = renderer.create(
84
+ <PreviewImage item={item} className="extra" alt="Alt prop" />,
85
+ );
86
+ const json = component.toJSON();
87
+ expect(json).toMatchSnapshot();
88
+ });
65
89
  });
@@ -80,6 +80,10 @@ const langmap = new Proxy(
80
80
  nativeName: 'Brezhoneg',
81
81
  englishName: 'Breton',
82
82
  },
83
+ bs: {
84
+ nativeName: 'Bosanski',
85
+ englishName: 'Bosnian',
86
+ },
83
87
  'bs-BA': {
84
88
  nativeName: 'Bosanski',
85
89
  englishName: 'Bosnian',
@@ -109,6 +109,7 @@ const safeColors = [
109
109
  'Teal',
110
110
  ];
111
111
  const namedColors = {};
112
+
112
113
  /**
113
114
  * Will generate initials from string
114
115
  * @param {string} name
@@ -198,3 +199,53 @@ export const hasApiExpander = (expander, path = '', type = 'GET_CONTENT') => {
198
199
  .map((expand) => expand[type]),
199
200
  ).includes(expander);
200
201
  };
202
+
203
+ /**
204
+ * Insert element into array at a give index
205
+ * @param {Array} array Array with data
206
+ * @param {*} element Element to be inserted
207
+ * @param {number} index Index of item to be inserted at
208
+ * @returns {Array} Array with inserted element
209
+ */
210
+ export const insertInArray = (array, element, index) => [
211
+ ...array.slice(0, index),
212
+ element,
213
+ ...array.slice(index),
214
+ ];
215
+
216
+ /**
217
+ * Replace element in array at a give index
218
+ * @param {Array} array Array with data
219
+ * @param {*} element Element to be replaced
220
+ * @param {number} index Index of item to be replaced at
221
+ * @returns {Array} Array with replaced element
222
+ */
223
+ export const replaceItemOfArray = (array, index, value) =>
224
+ Object.assign([...array], { [index]: value });
225
+
226
+ /**
227
+ * Remove item from array at given index
228
+ * @param {Array} array Array with data
229
+ * @param {number} index Index of item to be removed
230
+ * @returns {Array} Array without deleted element
231
+ */
232
+ export const removeFromArray = (array, index) => {
233
+ let newArray = array.slice();
234
+ newArray.splice(index, 1);
235
+ return newArray;
236
+ };
237
+
238
+ /**
239
+ * Reorder array
240
+ * @param {Array} array Array with data
241
+ * @param {number} origin Index of item to be reordered
242
+ * @param {number} target Index of item to be reordered to
243
+ * @returns {Array} Array with reordered elements
244
+ */
245
+ export const reorderArray = (array, origin, target) => {
246
+ const result = Array.from(array);
247
+ const [removed] = result.splice(origin, 1);
248
+ result.splice(target, 0, removed);
249
+
250
+ return result;
251
+ };
@@ -4,12 +4,16 @@ import {
4
4
  difference,
5
5
  getColor,
6
6
  getInitials,
7
- safeWrapper,
8
- normalizeLanguageName,
9
7
  hasApiExpander,
8
+ normalizeLanguageName,
10
9
  parseDateTime,
10
+ removeFromArray,
11
+ reorderArray,
12
+ replaceItemOfArray,
13
+ safeWrapper,
11
14
  } from './Utils';
12
15
  import moment from 'moment';
16
+ import deepFreeze from 'deep-freeze';
13
17
 
14
18
  describe('Utils tests', () => {
15
19
  describe('difference', () => {
@@ -345,4 +349,31 @@ describe('Utils tests', () => {
345
349
  ).toBe(`${isoDate}Z`);
346
350
  });
347
351
  });
352
+
353
+ describe('replaceItemOfArray', () => {
354
+ it('replaces the position of an element into an array immutable-ish', () => {
355
+ const array = ['a', 'b', 'c'];
356
+ deepFreeze(array);
357
+ const result = replaceItemOfArray(array, 2, 'v');
358
+ expect(result).toEqual(['a', 'b', 'v']);
359
+ });
360
+ });
361
+
362
+ describe('removeFromArray', () => {
363
+ it('removes an element from the array immutable-ish', () => {
364
+ const array = ['a', 'b', 'c'];
365
+ deepFreeze(array);
366
+ const result = removeFromArray(array, 2);
367
+ expect(result).toEqual(['a', 'b']);
368
+ });
369
+ });
370
+
371
+ describe('reorderArray', () => {
372
+ it('reorders an array immutable-ish', () => {
373
+ const array = ['a', 'b', 'c'];
374
+ deepFreeze(array);
375
+ const result = reorderArray(array, 2, 0);
376
+ expect(result).toEqual(['c', 'a', 'b']);
377
+ });
378
+ });
348
379
  });