@plone/volto 16.33.0 → 16.34.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.
- package/.changelog.draft +2 -17
- package/.readthedocs.yaml +4 -5
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/packages/volto-slate/package.json +1 -1
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +23 -0
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +135 -0
- package/src/components/theme/View/View.jsx +2 -0
- package/src/express-middleware/devproxy.js +7 -2
- package/src/middleware/api.js +1 -1
- package/.python-version +0 -1
- package/packages/README.md +0 -7
package/.changelog.draft
CHANGED
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
## 16.
|
|
2
|
-
|
|
3
|
-
### Feature
|
|
4
|
-
|
|
5
|
-
- URL Management control panel: add a filter for redirects created after a given date.
|
|
6
|
-
**Note:** This requires `Products.CMFPlone` 6.0.14 and `plone.restapi` 9.7.3 or later.
|
|
7
|
-
@davisagli [#6414](https://github.com/plone/volto/issues/6414)
|
|
8
|
-
- URL Management control panel: Move the form for adding a new redirect into a modal. @davisagli [#6421](https://github.com/plone/volto/issues/6421)
|
|
9
|
-
- URL Management control panel: Add feature to bulk upload redirects in a CSV file.
|
|
10
|
-
**Note:** This requires `plone.restapi` 9.7.3 or later.
|
|
11
|
-
@davisagli [#6421](https://github.com/plone/volto/issues/6421)
|
|
12
|
-
- URL Management control panel: Add a way to edit existing aliases. @davisagli [#6425](https://github.com/plone/volto/issues/6425)
|
|
1
|
+
## 16.34.1 (2025-09-29)
|
|
13
2
|
|
|
14
3
|
### Bugfix
|
|
15
4
|
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
### Internal
|
|
19
|
-
|
|
20
|
-
- Update upload-artifact action to fix CI. @davisagli [#6432](https://github.com/plone/volto/issues/6432)
|
|
5
|
+
- Added guard in API REDUX middleware. @sneridagh [#7412](https://github.com/plone/volto/issues/7412)
|
|
21
6
|
|
|
22
7
|
|
package/.readthedocs.yaml
CHANGED
|
@@ -3,8 +3,7 @@ build:
|
|
|
3
3
|
os: "ubuntu-22.04"
|
|
4
4
|
tools:
|
|
5
5
|
python: "3.12"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- exit 183;
|
|
6
|
+
commands:
|
|
7
|
+
# Cancel the Read the Docs build
|
|
8
|
+
# https://docs.readthedocs.io/en/stable/build-customization.html#cancel-build-based-on-a-condition
|
|
9
|
+
- exit 183;
|
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,22 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 16.34.1 (2025-09-29)
|
|
12
|
+
|
|
13
|
+
### Bugfix
|
|
14
|
+
|
|
15
|
+
- Added guard in API REDUX middleware. @sneridagh [#7412](https://github.com/plone/volto/issues/7412)
|
|
16
|
+
|
|
17
|
+
## 16.34.0 (2025-08-25)
|
|
18
|
+
|
|
19
|
+
### Feature
|
|
20
|
+
|
|
21
|
+
- Provide language alternate links @erral [#6615](https://github.com/plone/volto/issues/6615)
|
|
22
|
+
|
|
23
|
+
### Bugfix
|
|
24
|
+
|
|
25
|
+
- Fix corner case in devproxy when pathname is null. @sneridagh [#7276](https://github.com/plone/volto/issues/7276)
|
|
26
|
+
|
|
11
27
|
## 16.33.0 (2024-10-23)
|
|
12
28
|
|
|
13
29
|
### Feature
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import config from '@plone/volto/registry';
|
|
2
|
+
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
3
|
+
|
|
4
|
+
const AlternateHrefLangs = (props) => {
|
|
5
|
+
const { content } = props;
|
|
6
|
+
return (
|
|
7
|
+
<Helmet>
|
|
8
|
+
{config.settings.isMultilingual &&
|
|
9
|
+
content['@components']?.translations?.items?.map((item, key) => {
|
|
10
|
+
return (
|
|
11
|
+
<link
|
|
12
|
+
key={key}
|
|
13
|
+
rel="alternate"
|
|
14
|
+
hrefLang={item.language}
|
|
15
|
+
href={item['@id']}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
})}
|
|
19
|
+
</Helmet>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { AlternateHrefLangs };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
3
|
+
|
|
4
|
+
import renderer from 'react-test-renderer';
|
|
5
|
+
import configureStore from 'redux-mock-store';
|
|
6
|
+
import { Provider } from 'react-intl-redux';
|
|
7
|
+
import config from '@plone/volto/registry';
|
|
8
|
+
|
|
9
|
+
import { AlternateHrefLangs } from './AlternateHrefLangs';
|
|
10
|
+
|
|
11
|
+
const mockStore = configureStore();
|
|
12
|
+
|
|
13
|
+
describe('AlternateHrefLangs', () => {
|
|
14
|
+
beforeEach(() => {});
|
|
15
|
+
it('non multilingual site, renders nothing', () => {
|
|
16
|
+
config.settings.isMultilingual = false;
|
|
17
|
+
const content = {
|
|
18
|
+
'@id': '/',
|
|
19
|
+
'@components': {},
|
|
20
|
+
};
|
|
21
|
+
const store = mockStore({
|
|
22
|
+
intl: {
|
|
23
|
+
locale: 'en',
|
|
24
|
+
messages: {},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
// We need to force the component rendering
|
|
28
|
+
// to fill the Helmet
|
|
29
|
+
renderer.create(
|
|
30
|
+
<Provider store={store}>
|
|
31
|
+
<AlternateHrefLangs content={content} />
|
|
32
|
+
</Provider>,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
36
|
+
expect(helmetLinks.length).toBe(0);
|
|
37
|
+
});
|
|
38
|
+
it('multilingual site, with some translations', () => {
|
|
39
|
+
config.settings.isMultilingual = true;
|
|
40
|
+
config.settings.supportedLanguages = ['en', 'es', 'eu'];
|
|
41
|
+
|
|
42
|
+
const content = {
|
|
43
|
+
'@components': {
|
|
44
|
+
translations: {
|
|
45
|
+
items: [
|
|
46
|
+
{ '@id': '/en', language: 'en' },
|
|
47
|
+
{ '@id': '/es', language: 'es' },
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const store = mockStore({
|
|
54
|
+
intl: {
|
|
55
|
+
locale: 'en',
|
|
56
|
+
messages: {},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// We need to force the component rendering
|
|
61
|
+
// to fill the Helmet
|
|
62
|
+
renderer.create(
|
|
63
|
+
<Provider store={store}>
|
|
64
|
+
<>
|
|
65
|
+
<AlternateHrefLangs content={content} />
|
|
66
|
+
</>
|
|
67
|
+
</Provider>,
|
|
68
|
+
);
|
|
69
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
70
|
+
|
|
71
|
+
expect(helmetLinks.length).toBe(2);
|
|
72
|
+
|
|
73
|
+
expect(helmetLinks).toContainEqual({
|
|
74
|
+
rel: 'alternate',
|
|
75
|
+
href: '/es',
|
|
76
|
+
hrefLang: 'es',
|
|
77
|
+
});
|
|
78
|
+
expect(helmetLinks).toContainEqual({
|
|
79
|
+
rel: 'alternate',
|
|
80
|
+
href: '/en',
|
|
81
|
+
hrefLang: 'en',
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it('multilingual site, with all available translations', () => {
|
|
85
|
+
config.settings.isMultilingual = true;
|
|
86
|
+
config.settings.supportedLanguages = ['en', 'es', 'eu'];
|
|
87
|
+
const store = mockStore({
|
|
88
|
+
intl: {
|
|
89
|
+
locale: 'en',
|
|
90
|
+
messages: {},
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const content = {
|
|
95
|
+
'@components': {
|
|
96
|
+
translations: {
|
|
97
|
+
items: [
|
|
98
|
+
{ '@id': '/en', language: 'en' },
|
|
99
|
+
{ '@id': '/eu', language: 'eu' },
|
|
100
|
+
{ '@id': '/es', language: 'es' },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// We need to force the component rendering
|
|
107
|
+
// to fill the Helmet
|
|
108
|
+
renderer.create(
|
|
109
|
+
<Provider store={store}>
|
|
110
|
+
<AlternateHrefLangs content={content} />
|
|
111
|
+
</Provider>,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
115
|
+
|
|
116
|
+
// We expect having 3 links
|
|
117
|
+
expect(helmetLinks.length).toBe(3);
|
|
118
|
+
|
|
119
|
+
expect(helmetLinks).toContainEqual({
|
|
120
|
+
rel: 'alternate',
|
|
121
|
+
href: '/eu',
|
|
122
|
+
hrefLang: 'eu',
|
|
123
|
+
});
|
|
124
|
+
expect(helmetLinks).toContainEqual({
|
|
125
|
+
rel: 'alternate',
|
|
126
|
+
href: '/es',
|
|
127
|
+
hrefLang: 'es',
|
|
128
|
+
});
|
|
129
|
+
expect(helmetLinks).toContainEqual({
|
|
130
|
+
rel: 'alternate',
|
|
131
|
+
href: '/en',
|
|
132
|
+
hrefLang: 'en',
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
Tags,
|
|
19
19
|
Toolbar,
|
|
20
20
|
} from '@plone/volto/components';
|
|
21
|
+
import { AlternateHrefLangs } from '@plone/volto/components/theme/AlternateHrefLangs/AlternateHrefLangs';
|
|
21
22
|
import { listActions, getContent } from '@plone/volto/actions';
|
|
22
23
|
import {
|
|
23
24
|
BodyClass,
|
|
@@ -236,6 +237,7 @@ class View extends Component {
|
|
|
236
237
|
return (
|
|
237
238
|
<div id="view">
|
|
238
239
|
<ContentMetadataTags content={this.props.content} />
|
|
240
|
+
<AlternateHrefLangs content={this.props.content} />
|
|
239
241
|
{/* Body class if displayName in component is set */}
|
|
240
242
|
<BodyClass
|
|
241
243
|
className={
|
|
@@ -10,8 +10,13 @@ import querystring from 'querystring';
|
|
|
10
10
|
import { parse as parseUrl } from 'url';
|
|
11
11
|
|
|
12
12
|
const filter = function (pathname, req) {
|
|
13
|
-
//
|
|
14
|
-
|
|
13
|
+
// Check if pathname is defined, there are some corner cases that pathname is null
|
|
14
|
+
if (pathname) {
|
|
15
|
+
// This is the proxy to the API in case the accept header is 'application/json'
|
|
16
|
+
return config.settings.devProxyToApiPath && pathname.startsWith('/++api++');
|
|
17
|
+
} else {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
15
20
|
};
|
|
16
21
|
|
|
17
22
|
let _env = null;
|
package/src/middleware/api.js
CHANGED
|
@@ -331,7 +331,7 @@ const apiMiddlewareFactory = (api) => ({ dispatch, getState }) => (next) => (
|
|
|
331
331
|
...rest,
|
|
332
332
|
error,
|
|
333
333
|
statusCode: error.response,
|
|
334
|
-
message: error.response
|
|
334
|
+
message: error.response?.body?.message,
|
|
335
335
|
connectionRefused: false,
|
|
336
336
|
type: SET_APIERROR,
|
|
337
337
|
});
|
package/.python-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.9.13
|
package/packages/README.md
DELETED