apostrophe 4.28.0 → 4.29.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/CHANGELOG.md +33 -3
- package/README.md +142 -0
- package/defaults.js +1 -0
- package/lib/safe-json-script.js +27 -0
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +1 -1
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +1 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +3 -5
- package/modules/@apostrophecms/area/ui/apos/components/AposBreadcrumbOperations.vue +13 -1
- package/modules/@apostrophecms/asset/lib/globalIcons.js +3 -0
- package/modules/@apostrophecms/attachment/index.js +43 -1
- package/modules/@apostrophecms/color-field/index.js +7 -1
- package/modules/@apostrophecms/doc/index.js +11 -1
- package/modules/@apostrophecms/doc-type/index.js +165 -32
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +1 -1
- package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +104 -59
- package/modules/@apostrophecms/file/index.js +109 -9
- package/modules/@apostrophecms/i18n/i18n/de.json +0 -2
- package/modules/@apostrophecms/i18n/i18n/en.json +40 -1
- package/modules/@apostrophecms/i18n/i18n/es.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/fr.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/it.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/sk.json +0 -1
- package/modules/@apostrophecms/i18n/ui/apos/apps/AposI18nBatchReporting.js +18 -1
- package/modules/@apostrophecms/i18n/ui/apos/apps/AposI18nLocalizeActions.js +50 -0
- package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +56 -13
- package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +8 -2
- package/modules/@apostrophecms/layout-column-widget/index.js +156 -163
- package/modules/@apostrophecms/layout-widget/index.js +7 -2
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposAreaLayoutEditor.vue +6 -11
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposGridColumn.vue +3 -5
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposGridLayout.vue +4 -4
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposGridManager.vue +0 -16
- package/modules/@apostrophecms/layout-widget/ui/apos/lib/grid-state.mjs +7 -27
- package/modules/@apostrophecms/layout-widget/views/column.html +7 -9
- package/modules/@apostrophecms/login/index.js +39 -40
- package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +17 -2
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +3 -2
- package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +1 -0
- package/modules/@apostrophecms/page/index.js +2 -0
- package/modules/@apostrophecms/piece-type/index.js +3 -1
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +1 -0
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerDisplay.vue +5 -0
- package/modules/@apostrophecms/recently-edited/index.js +831 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposCellTitle.vue +54 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposRecentlyEditedCombo.vue +454 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposRecentlyEditedFilterTag.vue +75 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposRecentlyEditedFilters.vue +287 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposRecentlyEditedIcon.vue +16 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/components/AposRecentlyEditedManager.vue +346 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/composables/useRecentlyEditedBatch.js +193 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/composables/useRecentlyEditedData.js +276 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/composables/useRecentlyEditedFetch.js +199 -0
- package/modules/@apostrophecms/recently-edited/ui/apos/composables/useRecentlyEditedFilters.js +100 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +8 -4
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +1 -1
- package/modules/@apostrophecms/styles/index.js +10 -0
- package/modules/@apostrophecms/styles/lib/apiRoutes.js +6 -0
- package/modules/@apostrophecms/styles/lib/handlers.js +5 -0
- package/modules/@apostrophecms/styles/lib/methods.js +9 -3
- package/modules/@apostrophecms/styles/lib/presets.js +119 -0
- package/modules/@apostrophecms/styles/ui/apos/components/TheAposStyles.vue +3 -8
- package/modules/@apostrophecms/styles/ui/apos/composables/AposStyles.js +1 -3
- package/modules/@apostrophecms/styles/ui/apos/render-factory.js +29 -0
- package/modules/@apostrophecms/styles/ui/apos/universal/backgroundHelpers.mjs +140 -0
- package/modules/@apostrophecms/styles/ui/apos/universal/customRules.mjs +105 -0
- package/modules/@apostrophecms/styles/ui/apos/universal/render.mjs +195 -15
- package/modules/@apostrophecms/template/index.js +22 -6
- package/modules/@apostrophecms/ui/ui/apos/components/AposCellContextMenu.vue +2 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +18 -4
- package/modules/@apostrophecms/ui/ui/apos/composables/useInfiniteScroll.js +91 -0
- package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +1 -0
- package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +5 -2
- package/modules/@apostrophecms/ui/ui/apos/utils/index.js +9 -0
- package/modules/@apostrophecms/url/index.js +38 -4
- package/modules/@apostrophecms/widget-type/index.js +22 -6
- package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +8 -4
- package/package.json +19 -19
- package/test/files.js +129 -0
- package/test/layout-widget-migration.js +719 -0
- package/test/login-requirements.js +1 -1
- package/test/pieces-public-api.js +80 -0
- package/test/pieces.js +25 -0
- package/test/recently-edited.js +2311 -0
- package/test/schemas.js +39 -3
- package/test/static-build.js +642 -0
- package/test/styles.js +2569 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposLayoutColControlDialog.vue +0 -171
|
@@ -174,7 +174,10 @@ module.exports = {
|
|
|
174
174
|
origin: null,
|
|
175
175
|
preview: true,
|
|
176
176
|
// Set to false to opt out of the automatic styling wrapping of widget output
|
|
177
|
-
stylesWrapper: true
|
|
177
|
+
stylesWrapper: true,
|
|
178
|
+
// If set to true, the widget editor will hide tabs when there is only one,
|
|
179
|
+
// even if groups are defined. Defaults to false for backwards compatibility.
|
|
180
|
+
hideSingleTab: false
|
|
178
181
|
},
|
|
179
182
|
init(self) {
|
|
180
183
|
self.isExplicitOrigin = self.options.origin !== null;
|
|
@@ -306,14 +309,20 @@ module.exports = {
|
|
|
306
309
|
label: 'apostrophe:styles',
|
|
307
310
|
fields: groupFields
|
|
308
311
|
};
|
|
309
|
-
// Create a default group if none exist
|
|
312
|
+
// Create a default group if none exist.
|
|
313
|
+
// Ignore utility group if it's the only one, since it's now the way
|
|
314
|
+
// to hide fields (see layout column widget).
|
|
315
|
+
const visibleFields = Object.keys(self.fields)
|
|
316
|
+
.filter(
|
|
317
|
+
fieldName => !self.fieldsGroups.utility?.fields?.includes(fieldName)
|
|
318
|
+
);
|
|
310
319
|
if (
|
|
311
|
-
!Object.keys(self.fieldsGroups).length &&
|
|
312
|
-
|
|
320
|
+
!Object.keys(self.fieldsGroups).filter(g => g !== 'utility').length &&
|
|
321
|
+
visibleFields.length
|
|
313
322
|
) {
|
|
314
323
|
self.fieldsGroups.basics = {
|
|
315
324
|
label: 'apostrophe:basics',
|
|
316
|
-
fields:
|
|
325
|
+
fields: visibleFields
|
|
317
326
|
};
|
|
318
327
|
}
|
|
319
328
|
self.fieldsGroups.styles = stylesGroup;
|
|
@@ -530,6 +539,12 @@ module.exports = {
|
|
|
530
539
|
// then feeding it our widgets as if they were docs.
|
|
531
540
|
|
|
532
541
|
if (!(widgets.length && widgets[0]._virtual)) {
|
|
542
|
+
// For non-virtual widgets whose loading was deferred,
|
|
543
|
+
// relationships were just populated above but the page-level
|
|
544
|
+
// `attachments` query builder already ran before widget
|
|
545
|
+
// loading occurred. Re-annotate so that attachment `_urls`
|
|
546
|
+
// reflect crop/focal-point data from relationship `_fields`.
|
|
547
|
+
self.apos.attachment.all(widgets, { annotate: true });
|
|
533
548
|
return;
|
|
534
549
|
}
|
|
535
550
|
|
|
@@ -772,7 +787,8 @@ module.exports = {
|
|
|
772
787
|
preview: self.options.preview,
|
|
773
788
|
isExplicitOrigin: self.isExplicitOrigin,
|
|
774
789
|
widgetOperations: self.getWidgetOperations(req),
|
|
775
|
-
widgetBreadcrumbOperations: self.getWidgetBreadcrumbOperations(req)
|
|
790
|
+
widgetBreadcrumbOperations: self.getWidgetBreadcrumbOperations(req),
|
|
791
|
+
hideSingleTab: self.options.hideSingleTab
|
|
776
792
|
});
|
|
777
793
|
return result;
|
|
778
794
|
}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
:items="breadcrumbs"
|
|
57
57
|
/>
|
|
58
58
|
<AposWidgetModalTabs
|
|
59
|
-
v-if="
|
|
59
|
+
v-if="shouldShowTabs"
|
|
60
60
|
:key="tabKey"
|
|
61
61
|
:current="currentTab"
|
|
62
62
|
:tabs="tabs"
|
|
@@ -120,8 +120,7 @@ import AposModalTabsMixin from 'Modules/@apostrophecms/modal/mixins/AposModalTab
|
|
|
120
120
|
import { detectDocChange } from 'Modules/@apostrophecms/schema/lib/detectChange';
|
|
121
121
|
import newInstance from 'apostrophe/modules/@apostrophecms/schema/lib/newInstance.js';
|
|
122
122
|
import { debounceAsync } from 'Modules/@apostrophecms/ui/utils';
|
|
123
|
-
import { renderScopedStyles } from 'Modules/@apostrophecms/styles/
|
|
124
|
-
import checkIfConditions from 'apostrophe/lib/universal/check-if-conditions.mjs';
|
|
123
|
+
import { renderScopedStyles } from 'Modules/@apostrophecms/styles/render-factory.js';
|
|
125
124
|
import breakpointPreviewTransformer from 'postcss-viewport-to-container-toggle/standalone.js';
|
|
126
125
|
import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
|
|
127
126
|
|
|
@@ -227,6 +226,12 @@ export default {
|
|
|
227
226
|
moduleOptions() {
|
|
228
227
|
return window.apos.modules[apos.area.widgetManagers[this.type]];
|
|
229
228
|
},
|
|
229
|
+
shouldShowTabs() {
|
|
230
|
+
if (this.moduleOptions.hideSingleTab) {
|
|
231
|
+
return this.tabs.length > 1;
|
|
232
|
+
}
|
|
233
|
+
return this.tabs.length && this.tabs[0].name !== 'ungrouped';
|
|
234
|
+
},
|
|
230
235
|
typeLabel() {
|
|
231
236
|
return this.moduleOptions.label;
|
|
232
237
|
},
|
|
@@ -553,7 +558,6 @@ export default {
|
|
|
553
558
|
if (recomputeOnlyStyles) {
|
|
554
559
|
const styles = renderScopedStyles(this.schema, value.data, {
|
|
555
560
|
rootSelector: '__placeholder_root_selector__',
|
|
556
|
-
checkIfConditionsFn: checkIfConditions,
|
|
557
561
|
subset: this.moduleOptions.stylesFields
|
|
558
562
|
});
|
|
559
563
|
this.applyPreviewStyles(styles);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apostrophe",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.29.0",
|
|
4
4
|
"description": "The Apostrophe Content Management System.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"autoprefixer": "^10.4.1",
|
|
51
51
|
"bluebird": "^3.7.2",
|
|
52
52
|
"body-parser": "^1.18.2",
|
|
53
|
-
"cheerio": "^1.
|
|
53
|
+
"cheerio": "^1.1.0",
|
|
54
54
|
"chokidar": "^3.5.2",
|
|
55
55
|
"common-tags": "^1.8.0",
|
|
56
56
|
"concat-with-sourcemaps": "^1.1.0",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"cssnano": "^7.1.1",
|
|
62
62
|
"csv-parse": "^5.6.0",
|
|
63
63
|
"dayjs": "^1.9.8",
|
|
64
|
-
"dompurify": "^3.2
|
|
64
|
+
"dompurify": "^3.3.2",
|
|
65
65
|
"encodeurl": "^2.0.0",
|
|
66
|
-
"express": "^4.
|
|
66
|
+
"express": "^4.22.0",
|
|
67
67
|
"express-bearer-token": "^3.0.0",
|
|
68
68
|
"express-session": "^1.18.2",
|
|
69
69
|
"fs-extra": "^7.0.1",
|
|
@@ -77,15 +77,14 @@
|
|
|
77
77
|
"jsdom": "^24.1.0",
|
|
78
78
|
"klona": "^2.0.4",
|
|
79
79
|
"launder": "^1.4.0",
|
|
80
|
-
"lodash": "^4.
|
|
80
|
+
"lodash": "^4.18.1",
|
|
81
81
|
"mini-css-extract-plugin": "^1.6.0",
|
|
82
|
-
"minimatch": "^3.
|
|
82
|
+
"minimatch": "^3.1.4",
|
|
83
83
|
"mkdirp": "^0.5.5",
|
|
84
|
-
"multer": "^2.
|
|
84
|
+
"multer": "^2.1.1",
|
|
85
85
|
"node-fetch": "^2.6.1",
|
|
86
|
-
"nodemailer": "^
|
|
86
|
+
"nodemailer": "^8.0.5",
|
|
87
87
|
"nunjucks": "^3.2.1",
|
|
88
|
-
"oembetter": "^1.1.3",
|
|
89
88
|
"parseurl": "^1.3.3",
|
|
90
89
|
"passport": "^0.6.0",
|
|
91
90
|
"passport-local": "^1.0.0",
|
|
@@ -101,7 +100,7 @@
|
|
|
101
100
|
"regexp-quote": "0.0.0",
|
|
102
101
|
"resolve": "^1.19.0",
|
|
103
102
|
"resolve-from": "^5.0.0",
|
|
104
|
-
"sass": "^1.
|
|
103
|
+
"sass": "^1.85.0",
|
|
105
104
|
"sass-loader": "^16.0.0",
|
|
106
105
|
"server-destroy": "^1.0.1",
|
|
107
106
|
"sluggo": "^1.0.0",
|
|
@@ -110,30 +109,31 @@
|
|
|
110
109
|
"tiny-emitter": "^2.1.0",
|
|
111
110
|
"tough-cookie": "^4.0.0",
|
|
112
111
|
"underscore.string": "^3.3.4",
|
|
113
|
-
"uploadfs": "^1.26.1",
|
|
114
112
|
"void-elements": "^3.1.0",
|
|
115
113
|
"vue": "^3.5.20",
|
|
116
114
|
"vue-advanced-cropper": "^2.8.8",
|
|
117
115
|
"vue-loader": "^17.1.0",
|
|
118
116
|
"vue-style-loader": "^4.1.3",
|
|
119
|
-
"webpack": "^5.
|
|
117
|
+
"webpack": "^5.106.1",
|
|
120
118
|
"webpack-merge": "^5.7.3",
|
|
121
119
|
"xregexp": "^2.0.0",
|
|
122
|
-
"boring": "^1.1.1",
|
|
123
|
-
"postcss-viewport-to-container-toggle": "^2.3.0",
|
|
124
|
-
"sanitize-html": "^2.17.2",
|
|
125
120
|
"@apostrophecms/emulate-mongo-3-driver": "^1.0.6",
|
|
121
|
+
"express-cache-on-demand": "^1.0.4",
|
|
126
122
|
"broadband": "^1.1.0",
|
|
127
|
-
"
|
|
123
|
+
"boring": "^1.1.1",
|
|
124
|
+
"oembetter": "^1.1.4",
|
|
125
|
+
"postcss-viewport-to-container-toggle": "^2.3.0",
|
|
126
|
+
"uploadfs": "^1.26.1",
|
|
127
|
+
"sanitize-html": "^2.17.3"
|
|
128
128
|
},
|
|
129
129
|
"devDependencies": {
|
|
130
130
|
"eslint": "^9.39.1",
|
|
131
131
|
"form-data": "^4.0.4",
|
|
132
|
-
"mocha": "^11.7.
|
|
132
|
+
"mocha": "^11.7.5",
|
|
133
133
|
"nyc": "^17.1.0",
|
|
134
134
|
"stylelint": "^16.5.0",
|
|
135
|
-
"
|
|
136
|
-
"
|
|
135
|
+
"stylelint-config-apostrophe": "^4.4.0",
|
|
136
|
+
"eslint-config-apostrophe": "^6.0.2"
|
|
137
137
|
},
|
|
138
138
|
"browserslist": [
|
|
139
139
|
"ie >= 10"
|
package/test/files.js
CHANGED
|
@@ -133,3 +133,132 @@ describe('Files', function() {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
describe('Files with i18n locale prefixes', function() {
|
|
138
|
+
|
|
139
|
+
let apos;
|
|
140
|
+
|
|
141
|
+
const mockFiles = [
|
|
142
|
+
{
|
|
143
|
+
type: '@apostrophecms/file',
|
|
144
|
+
slug: 'file-locale-test',
|
|
145
|
+
visibility: 'public',
|
|
146
|
+
attachment: {
|
|
147
|
+
type: 'attachment',
|
|
148
|
+
_id: 'testid-locale',
|
|
149
|
+
name: 'localename',
|
|
150
|
+
extension: 'pdf',
|
|
151
|
+
data: 'I am a fake localized PDF'
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
this.timeout(t.timeout);
|
|
157
|
+
|
|
158
|
+
after(async function() {
|
|
159
|
+
return t.destroy(apos);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
before(async function() {
|
|
163
|
+
this.timeout(t.timeout);
|
|
164
|
+
this.slow(2000);
|
|
165
|
+
|
|
166
|
+
apos = await t.create({
|
|
167
|
+
root: module,
|
|
168
|
+
modules: {
|
|
169
|
+
'@apostrophecms/file': {
|
|
170
|
+
options: {
|
|
171
|
+
prettyUrls: true
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
'@apostrophecms/i18n': {
|
|
175
|
+
options: {
|
|
176
|
+
locales: {
|
|
177
|
+
en: {},
|
|
178
|
+
fr: {
|
|
179
|
+
prefix: '/fr'
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
apos.baseUrl = apos.http.getBase();
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
await apos.doc.db.deleteMany({ type: '@apostrophecms/file' });
|
|
191
|
+
try {
|
|
192
|
+
fs.mkdirSync(`${__dirname}/public/uploads/attachments`);
|
|
193
|
+
} catch (e) {
|
|
194
|
+
// May already exist
|
|
195
|
+
}
|
|
196
|
+
} catch (e) {
|
|
197
|
+
assert(false);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Insert the file doc in the default (en) locale
|
|
201
|
+
const req = apos.task.getReq();
|
|
202
|
+
for (const file of mockFiles) {
|
|
203
|
+
await apos.file.insert(req, file);
|
|
204
|
+
const {
|
|
205
|
+
_id, name, extension, data
|
|
206
|
+
} = file.attachment;
|
|
207
|
+
fs.writeFileSync(
|
|
208
|
+
`${__dirname}/public/uploads/attachments/${_id}-${name}.${extension}`,
|
|
209
|
+
data
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Localize the file to FR and give it a distinct French slug
|
|
214
|
+
const enFile = await apos.file.find(req, {}).toObject();
|
|
215
|
+
await apos.file.localize(req, enFile, 'fr');
|
|
216
|
+
const frReq = apos.task.getReq({ locale: 'fr' });
|
|
217
|
+
const frDraft = await apos.file.find(frReq.clone({ mode: 'draft' }), {}).toObject();
|
|
218
|
+
frDraft.slug = 'file-test-locale-fr';
|
|
219
|
+
frDraft.title = 'Test Locale FR';
|
|
220
|
+
await apos.file.update(frReq, frDraft);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should include locale prefix and FR slug in pretty URL for FR locale', async function() {
|
|
224
|
+
const frReq = apos.task.getAnonReq({ locale: 'fr' });
|
|
225
|
+
const files = await apos.file.find(frReq).toArray();
|
|
226
|
+
assert.strictEqual(files.length, 1);
|
|
227
|
+
const file = files[0];
|
|
228
|
+
const attachment = apos.attachment.first(file);
|
|
229
|
+
const url = apos.attachment.url(attachment);
|
|
230
|
+
assert(url);
|
|
231
|
+
// Must use the FR slug (test-locale-fr) and include /fr/ prefix
|
|
232
|
+
assert.strictEqual(
|
|
233
|
+
url,
|
|
234
|
+
`${apos.http.getBase()}/fr/files/test-locale-fr.${attachment.extension}`
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should serve the file at the locale-prefixed pretty URL with FR slug', async function() {
|
|
239
|
+
const frReq = apos.task.getAnonReq({ locale: 'fr' });
|
|
240
|
+
const files = await apos.file.find(frReq).toArray();
|
|
241
|
+
assert.strictEqual(files.length, 1);
|
|
242
|
+
const file = files[0];
|
|
243
|
+
const attachment = apos.attachment.first(file);
|
|
244
|
+
const url = apos.attachment.url(attachment);
|
|
245
|
+
// Verify the locale-prefixed, FR-slug URL actually serves the content
|
|
246
|
+
const body = await apos.http.get(url);
|
|
247
|
+
assert.strictEqual(body, attachment.data);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('should use EN slug without locale prefix for default EN locale', async function() {
|
|
251
|
+
const enReq = apos.task.getAnonReq({ locale: 'en' });
|
|
252
|
+
const files = await apos.file.find(enReq).toArray();
|
|
253
|
+
assert.strictEqual(files.length, 1);
|
|
254
|
+
const file = files[0];
|
|
255
|
+
const attachment = apos.attachment.first(file);
|
|
256
|
+
const url = apos.attachment.url(attachment);
|
|
257
|
+
assert(url);
|
|
258
|
+
// EN keeps its original slug (locale-test) with no locale prefix
|
|
259
|
+
assert.strictEqual(
|
|
260
|
+
url,
|
|
261
|
+
`${apos.http.getBase()}/files/locale-test.${attachment.extension}`
|
|
262
|
+
);
|
|
263
|
+
});
|
|
264
|
+
});
|