@plone/volto 19.0.0-alpha.3 → 19.0.0-alpha.4
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.md +28 -0
- package/cypress/support/commands.js +5 -0
- package/locales/af.json +1 -1
- package/locales/ar.json +1 -1
- package/locales/bg.json +1 -1
- package/locales/bn.json +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +5 -1
- package/locales/ca.json +1 -1
- package/locales/cs.json +1 -1
- package/locales/cy.json +1 -1
- package/locales/da.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +5 -1
- package/locales/de.json +1 -1
- package/locales/el.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +5 -1
- package/locales/en.json +1 -1
- package/locales/en_AU.json +1 -1
- package/locales/en_GB.json +1 -1
- package/locales/eo.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +5 -1
- package/locales/es.json +1 -1
- package/locales/et.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +5 -1
- package/locales/eu.json +1 -1
- package/locales/fa.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +5 -1
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +5 -1
- package/locales/fr.json +1 -1
- package/locales/fu.json +1 -1
- package/locales/gl.json +1 -1
- package/locales/he.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +5 -1
- package/locales/hi.json +1 -1
- package/locales/hr.json +1 -1
- package/locales/hu.json +1 -1
- package/locales/hy.json +1 -1
- package/locales/id.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +5 -1
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +5 -1
- package/locales/ja.json +1 -1
- package/locales/ka.json +1 -1
- package/locales/kn.json +1 -1
- package/locales/ko.json +1 -1
- package/locales/lt.json +1 -1
- package/locales/lv.json +1 -1
- package/locales/mi.json +1 -1
- package/locales/mk.json +1 -1
- package/locales/my.json +1 -1
- package/locales/nb_NO.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +5 -1
- package/locales/nl.json +1 -1
- package/locales/nn.json +1 -1
- package/locales/pl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +5 -1
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +5 -1
- package/locales/pt_BR.json +1 -1
- package/locales/rm.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +5 -1
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +5 -1
- package/locales/ru.json +1 -1
- package/locales/sk.json +1 -1
- package/locales/sl.json +1 -1
- package/locales/sm.json +1 -1
- package/locales/sq.json +1 -1
- package/locales/sr.json +1 -1
- package/locales/sr@cyrl.json +1 -1
- package/locales/sr@latn.json +1 -1
- package/locales/sv.json +1 -1
- package/locales/ta.json +1 -1
- package/locales/te.json +1 -1
- package/locales/th.json +1 -1
- package/locales/to.json +1 -1
- package/locales/tr.json +1 -1
- package/locales/uk.json +1 -1
- package/locales/vi.json +1 -1
- package/locales/volto.pot +6 -2
- package/locales/zh_CN/LC_MESSAGES/volto.po +5 -1
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant.json +1 -1
- package/locales/zh_Hant_HK.json +1 -1
- package/package.json +5 -5
- package/src/components/manage/Contents/ContentsItem.jsx +1 -1
- package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
- package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +1 -1
- package/src/components/manage/Widgets/SelectAutoComplete.jsx +29 -12
- package/src/config/ControlPanels.js +1 -0
- package/src/config/index.js +1 -1
- package/src/express-middleware/devproxy.js +7 -2
- package/src/helpers/Html/Html.jsx +9 -1
- package/src/helpers/Url/bulkFlattenToAppURL.test.ts +122 -0
- package/src/helpers/Url/bulkFlattenToAppURL.ts +24 -0
- package/types/helpers/Url/bulkFlattenToAppURL.d.ts +5 -0
package/src/config/index.js
CHANGED
|
@@ -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;
|
|
@@ -11,6 +11,7 @@ import join from 'lodash/join';
|
|
|
11
11
|
import BodyClass from '@plone/volto/helpers/BodyClass/BodyClass';
|
|
12
12
|
import { runtimeConfig } from '@plone/volto/runtime_config';
|
|
13
13
|
import config from '@plone/volto/registry';
|
|
14
|
+
import { bulkFlattenToAppURL } from '../Url/bulkFlattenToAppURL';
|
|
14
15
|
|
|
15
16
|
const CRITICAL_CSS_TEMPLATE = `function alter() {
|
|
16
17
|
document.querySelectorAll("head link[rel='prefetch']").forEach(function(el) { el.rel = 'stylesheet'});
|
|
@@ -189,7 +190,14 @@ class Html extends Component {
|
|
|
189
190
|
<script
|
|
190
191
|
dangerouslySetInnerHTML={{
|
|
191
192
|
__html: `window.__data=${serialize(
|
|
192
|
-
loadReducers(
|
|
193
|
+
loadReducers({
|
|
194
|
+
...store.getState(),
|
|
195
|
+
// Flatten the content URLs in initial request in SSR
|
|
196
|
+
// it normalizes the URLs in case the INTERNAL_API_PATH is set
|
|
197
|
+
// and prevents unwanted leaks of INTERNAL_API_PATH in the client
|
|
198
|
+
// (only in the first request)
|
|
199
|
+
content: bulkFlattenToAppURL(store.getState().content),
|
|
200
|
+
}),
|
|
193
201
|
)};`,
|
|
194
202
|
}}
|
|
195
203
|
charSet="UTF-8"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import config from '@plone/registry';
|
|
3
|
+
import { bulkFlattenToAppURL } from './bulkFlattenToAppURL';
|
|
4
|
+
|
|
5
|
+
const API_PATH = 'http://example.com/api';
|
|
6
|
+
const INTERNAL_API_PATH = 'http://backend/api';
|
|
7
|
+
|
|
8
|
+
describe('bulkFlattenToAppURL', () => {
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
config.settings = {};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should flatten URLs correctly with API_PATH', () => {
|
|
14
|
+
config.settings.apiPath = API_PATH;
|
|
15
|
+
|
|
16
|
+
const input = {
|
|
17
|
+
'@id': `${API_PATH}/path/to/resource`,
|
|
18
|
+
anotherField: `${API_PATH}/another/path`,
|
|
19
|
+
nested: {
|
|
20
|
+
'@id': `${API_PATH}/nested/resource`,
|
|
21
|
+
anotherNestedField: `${API_PATH}/nested/another/path`,
|
|
22
|
+
},
|
|
23
|
+
arrayField: [
|
|
24
|
+
{
|
|
25
|
+
'@id': `${API_PATH}/array/resource/1`,
|
|
26
|
+
anotherArrayField: `${API_PATH}/array/another/path/1`,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
'@id': `${API_PATH}/array/resource/2`,
|
|
30
|
+
anotherArrayField: `${API_PATH}/array/another/path/2`,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
stringField: 'This is a string',
|
|
34
|
+
numberField: 42,
|
|
35
|
+
booleanField: true,
|
|
36
|
+
nullField: null,
|
|
37
|
+
undefinedField: undefined,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const expectedOutput = {
|
|
41
|
+
'@id': '/path/to/resource',
|
|
42
|
+
anotherField: '/another/path',
|
|
43
|
+
nested: {
|
|
44
|
+
'@id': '/nested/resource',
|
|
45
|
+
anotherNestedField: '/nested/another/path',
|
|
46
|
+
},
|
|
47
|
+
arrayField: [
|
|
48
|
+
{
|
|
49
|
+
'@id': '/array/resource/1',
|
|
50
|
+
anotherArrayField: '/array/another/path/1',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
'@id': '/array/resource/2',
|
|
54
|
+
anotherArrayField: '/array/another/path/2',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
stringField: 'This is a string',
|
|
58
|
+
numberField: 42,
|
|
59
|
+
booleanField: true,
|
|
60
|
+
nullField: null,
|
|
61
|
+
undefinedField: undefined,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const result = bulkFlattenToAppURL(input as any);
|
|
65
|
+
expect(result).toEqual(expectedOutput);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should flatten URLs correctly with INTERNAL_API_PATH', () => {
|
|
69
|
+
config.settings.internalApiPath = INTERNAL_API_PATH;
|
|
70
|
+
|
|
71
|
+
const input = {
|
|
72
|
+
'@id': `${INTERNAL_API_PATH}/path/to/resource`,
|
|
73
|
+
anotherField: `${INTERNAL_API_PATH}/another/path`,
|
|
74
|
+
nested: {
|
|
75
|
+
'@id': `${INTERNAL_API_PATH}/nested/resource`,
|
|
76
|
+
anotherNestedField: `${INTERNAL_API_PATH}/nested/another/path`,
|
|
77
|
+
},
|
|
78
|
+
arrayField: [
|
|
79
|
+
{
|
|
80
|
+
'@id': `${INTERNAL_API_PATH}/array/resource/1`,
|
|
81
|
+
anotherArrayField: `${INTERNAL_API_PATH}/array/another/path/1`,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
'@id': `${INTERNAL_API_PATH}/array/resource/2`,
|
|
85
|
+
anotherArrayField: `${INTERNAL_API_PATH}/array/another/path/2`,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
stringField: 'This is a string',
|
|
89
|
+
numberField: 42,
|
|
90
|
+
booleanField: true,
|
|
91
|
+
nullField: null,
|
|
92
|
+
undefinedField: undefined,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const expectedOutput = {
|
|
96
|
+
'@id': '/path/to/resource',
|
|
97
|
+
anotherField: '/another/path',
|
|
98
|
+
nested: {
|
|
99
|
+
'@id': '/nested/resource',
|
|
100
|
+
anotherNestedField: '/nested/another/path',
|
|
101
|
+
},
|
|
102
|
+
arrayField: [
|
|
103
|
+
{
|
|
104
|
+
'@id': '/array/resource/1',
|
|
105
|
+
anotherArrayField: '/array/another/path/1',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
'@id': '/array/resource/2',
|
|
109
|
+
anotherArrayField: '/array/another/path/2',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
stringField: 'This is a string',
|
|
113
|
+
numberField: 42,
|
|
114
|
+
booleanField: true,
|
|
115
|
+
nullField: null,
|
|
116
|
+
undefinedField: undefined,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const result = bulkFlattenToAppURL(input as any);
|
|
120
|
+
expect(result).toEqual(expectedOutput);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import config from '@plone/registry';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The definitive flattenToAppURL function
|
|
5
|
+
* Flattens all the URLs in the response to the current app URL (or internalApiPath if set).
|
|
6
|
+
*/
|
|
7
|
+
export function bulkFlattenToAppURL<T>(data: T) {
|
|
8
|
+
// Convert data to string to perform replacements
|
|
9
|
+
let stringData = JSON.stringify(data);
|
|
10
|
+
|
|
11
|
+
// Replace all occurrences of backend URLs
|
|
12
|
+
stringData = stringData.replaceAll(`${config.settings.apiPath}/`, '/');
|
|
13
|
+
stringData = stringData.replaceAll(config.settings.apiPath, '/');
|
|
14
|
+
if (config.settings.internalApiPath) {
|
|
15
|
+
stringData = stringData.replaceAll(
|
|
16
|
+
`${config.settings.internalApiPath}/`,
|
|
17
|
+
'/',
|
|
18
|
+
);
|
|
19
|
+
stringData = stringData.replaceAll(config.settings.internalApiPath, '/');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Parse back to object
|
|
23
|
+
return JSON.parse(stringData) as T;
|
|
24
|
+
}
|