apostrophe 4.9.0 → 4.11.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 +53 -0
- package/LICENSE.md +24 -0
- package/defaults.js +1 -0
- package/index.js +7 -0
- package/lib/moog.js +1 -1
- package/modules/@apostrophecms/admin-bar/index.js +6 -6
- package/modules/@apostrophecms/area/index.js +29 -7
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +2 -2
- package/modules/@apostrophecms/asset/index.js +17 -4
- package/modules/@apostrophecms/asset/lib/build/external-module-api.js +7 -6
- package/modules/@apostrophecms/asset/lib/build/internals.js +1 -4
- package/modules/@apostrophecms/asset/lib/refresh-on-restart.js +1 -1
- package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.scss.js +10 -20
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.scss.js +10 -18
- package/modules/@apostrophecms/attachment/index.js +6 -6
- package/modules/@apostrophecms/attachment/lib/tasks/rescale.js +1 -1
- package/modules/@apostrophecms/color-field/index.js +44 -0
- package/modules/@apostrophecms/color-field/ui/apos/components/AposColor.vue +324 -0
- package/modules/@apostrophecms/{schema → color-field}/ui/apos/components/AposInputColor.vue +8 -19
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorAlpha.vue +141 -0
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorCheckerboard.vue +90 -0
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorEditableInput.vue +144 -0
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorHue.vue +213 -0
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorSaturation.vue +127 -0
- package/modules/@apostrophecms/{schema → color-field}/ui/apos/logic/AposInputColor.js +13 -7
- package/modules/@apostrophecms/color-field/ui/apos/mixins/AposColorMixin.js +129 -0
- package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuShortcut.vue +16 -14
- package/modules/@apostrophecms/doc/index.js +7 -3
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +0 -1
- package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +6 -0
- package/modules/@apostrophecms/email/index.js +2 -2
- package/modules/@apostrophecms/image/index.js +1 -1
- package/modules/@apostrophecms/job/index.js +3 -3
- package/modules/@apostrophecms/lock/index.js +2 -2
- package/modules/@apostrophecms/login/index.js +5 -5
- package/modules/@apostrophecms/migration/index.js +5 -5
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +6 -1
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +19 -19
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalShareDraft.vue +18 -18
- package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +72 -9
- package/modules/@apostrophecms/module/index.js +6 -1
- package/modules/@apostrophecms/module/lib/events.js +1 -1
- package/modules/@apostrophecms/oembed/index.js +2 -2
- package/modules/@apostrophecms/page/index.js +39 -4
- package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +1 -1
- package/modules/@apostrophecms/page-type/index.js +4 -4
- package/modules/@apostrophecms/permission/ui/apos/components/AposPermissionGrid.vue +1 -1
- package/modules/@apostrophecms/piece-type/index.js +12 -4
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +1 -3
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +2 -0
- package/modules/@apostrophecms/rich-text-widget/index.js +16 -20
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapColor.vue +13 -10
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +1 -0
- package/modules/@apostrophecms/rich-text-widget/views/widget.html +1 -1
- package/modules/@apostrophecms/schema/index.js +35 -11
- package/modules/@apostrophecms/schema/lib/addFieldTypes.js +51 -29
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +1 -1
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRange.js +2 -2
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +2 -2
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +1 -1
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputChoicesMixin.js +5 -1
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +3 -0
- package/modules/@apostrophecms/schema/ui/apos/scss/AposInputArray.scss +3 -5
- package/modules/@apostrophecms/search/index.js +3 -3
- package/modules/@apostrophecms/template/index.js +34 -8
- package/modules/@apostrophecms/template/lib/bundlesLoader.js +28 -6
- package/modules/@apostrophecms/template/lib/nunjucksLoader.js +2 -2
- package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +12 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +97 -11
- package/modules/@apostrophecms/ui/ui/apos/components/AposToggle.vue +5 -1
- package/modules/@apostrophecms/ui/ui/apos/composables/AposFocusTrap.js +227 -0
- package/modules/@apostrophecms/ui/ui/apos/scss/global/_inputs.scss +1 -1
- package/modules/@apostrophecms/user/index.js +2 -2
- package/modules/@apostrophecms/util/ui/src/util.js +21 -8
- package/modules/@apostrophecms/widget-type/index.js +12 -4
- package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +0 -1
- package/package.json +5 -5
- package/test/asset-external.js +183 -2
- package/modules/@apostrophecms/asset/lib/webpack/media-to-container-queries-loader.js +0 -94
- package/modules/@apostrophecms/asset/lib/webpack/postcss-replace-viewport-units-plugin.js +0 -40
- package/test/postcss.js +0 -64
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.11.0 (2024-12-18)
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* When validating an `area` field, warn the developer if `widgets` is not nested in `options`.
|
|
8
|
+
* Adds support for supplying CSS variable names to a color field's `presetColors` array as selectable values.
|
|
9
|
+
* Adds support for dynamic focus trap in Context menus (prop `dynamicFocus`). When set to `true`, the focusable elements are recalculated on each cycle step.
|
|
10
|
+
* Adds option to disable `tabindex` on `AposToggle` component. A new prop `disableFocus` can be set to `false` to disable the focus on the toggle button. It's enabled by default.
|
|
11
|
+
* Adds support for event on `addContextOperation`, an option `type` can now be passed and can be `modal` (default) or `event`, in this case it does not try to open a modal but emit a bus event using the action as name.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Fixes
|
|
15
|
+
|
|
16
|
+
* Focus properly Widget Editor modals when opened. Keep the previous active focus on the modal when closing the widget editor.
|
|
17
|
+
* a11y improvements for context menus.
|
|
18
|
+
* Fixes broken widget preview URL when the image is overridden (module improve) and external build module is registered.
|
|
19
|
+
* Inject dynamic custom bundle CSS when using external build module with no CSS entry point.
|
|
20
|
+
* Range field now correctly takes 0 into account.
|
|
21
|
+
* Apos style does not go through `postcss-viewport-to-container-toggle` plugin anymore to avoid UI bugs.
|
|
22
|
+
|
|
23
|
+
## 4.10.0 (2024-11-20)
|
|
24
|
+
|
|
25
|
+
### Fixes
|
|
26
|
+
|
|
27
|
+
* Extra bundle detection when using external build module works properly now.
|
|
28
|
+
* Widget players are now properly invoked when they arrive later in the page load process.
|
|
29
|
+
* Fix permission grid tooltip display.
|
|
30
|
+
* Fixes a bug that crashes external frontend applications.
|
|
31
|
+
* Fixes a false positive warning for module not in use for project level submodules (e.g. `widges/module.js`) and dot-folders (e.g. `.DS_Store`).
|
|
32
|
+
* Bumped `express-bearer-token` dependency to address a low-severity `npm audit` warning regarding noncompliant cookie names and values. Apostrophe
|
|
33
|
+
did not actually use any noncompliant cookie names or values, so there was no vulnerability in Apostrophe.
|
|
34
|
+
* Rich text "Styles" toolbar now has visually focused state.
|
|
35
|
+
* The `renderPermalinks` and `renderImages` methods of the `@apostrophecms/rich-text` module now correctly resolve the final URLs of page links and inline images in rich text widgets, even when the user has editing privileges. Formerly this was mistakenly prevented by logic intended to preserve the editing experience. The editing experience never actually relied on the
|
|
36
|
+
rendered output.
|
|
37
|
+
* Search bar will perform the search even if the bar is empty allowing to reset a search.
|
|
38
|
+
* Fixes Color picker being hidden in an inline array schema field, also fixes rgba inputs going off the modal.
|
|
39
|
+
|
|
40
|
+
### Adds
|
|
41
|
+
|
|
42
|
+
* It's possible now to target the HMR build when registering via `template.append` and `template.prepend`. Use `when: 'hmr:public'` or `when: 'hmr:apos'` that will be evaluated against the current asset `options.hmr` configuration.
|
|
43
|
+
* Adds asset module option `options.modulePreloadPolyfill` (default `true`) to allow disabling the polyfill preload for e.g. external front-ends.
|
|
44
|
+
* Adds `bundleMarkup` to the data sent to the external front-end, containing all markup for injecting Apostrophe UI in the front-end.
|
|
45
|
+
* Warns users when two page types have the same field name, but a different field type. This may cause errors or other problems when an editor switches page types.
|
|
46
|
+
* The piece and page `GET` REST APIs now support `?render-areas=inline`. When this parameter is used, an HTML rendering of each widget is added to that specific widget in each area's `items` array as a new `_rendered` property. The existing `?render-areas=1` parameter is still supported to render the entire area as a single `_rendered` property. Note that this older option also causes `items` to be omitted from the response.
|
|
47
|
+
|
|
48
|
+
### Changes
|
|
49
|
+
|
|
50
|
+
* Removes postcss plugin and webpack loader used for breakpoint preview mode. Uses instead the new `postcss-viewport-to-container-toggle` plugin in the webpack config.
|
|
51
|
+
* Implement `vue-color` directly in Apostrophe rather than as a dependency
|
|
52
|
+
* Switch color handling library from `tinycolor2` to `@ctrl/tinycolor`
|
|
53
|
+
* Removes error messages in server console for hidden fields. These messages should not have been printed out in the server console in the first place.
|
|
54
|
+
* Removes invalid error messages on select fields appearing while opening an existing valid document.
|
|
55
|
+
|
|
3
56
|
## 4.9.0 (2024-10-31)
|
|
4
57
|
|
|
5
58
|
### Adds
|
package/LICENSE.md
CHANGED
|
@@ -5,3 +5,27 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
5
5
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
6
|
|
|
7
7
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
8
|
+
|
|
9
|
+
Portions derived from vue-color require the following statement:
|
|
10
|
+
|
|
11
|
+
MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2021 chenkai0520
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in all
|
|
23
|
+
copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
28
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
|
+
SOFTWARE.
|
package/defaults.js
CHANGED
|
@@ -44,6 +44,7 @@ module.exports = {
|
|
|
44
44
|
'@apostrophecms/rich-text-widget': {},
|
|
45
45
|
'@apostrophecms/html-widget': {},
|
|
46
46
|
'@apostrophecms/image-widget': {},
|
|
47
|
+
'@apostrophecms/color-field': {},
|
|
47
48
|
'@apostrophecms/oembed-field': {},
|
|
48
49
|
'@apostrophecms/video-widget': {},
|
|
49
50
|
'@apostrophecms/ui': {},
|
package/index.js
CHANGED
|
@@ -699,11 +699,18 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
async function testDir(name) {
|
|
702
|
+
if (name.startsWith('.')) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
702
705
|
// Projects that have different theme modules activated at different times
|
|
703
706
|
// are a frequent source of false positives for this warning, so ignore
|
|
704
707
|
// seemingly unused modules with "theme" in the name
|
|
705
708
|
if (!validSteps.includes(name)) {
|
|
706
709
|
try {
|
|
710
|
+
// It's a project level modules definition, skip it.
|
|
711
|
+
if (fs.existsSync(path.resolve(self.localModules, name, 'modules.js'))) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
707
714
|
const submodule = await self.root.import(path.resolve(self.localModules, name, 'index.js'));
|
|
708
715
|
if (submodule && submodule.options && submodule.options.ignoreUnusedFolderWarning) {
|
|
709
716
|
return;
|
package/lib/moog.js
CHANGED
|
@@ -433,7 +433,7 @@ module.exports = function(options) {
|
|
|
433
433
|
if (!object.__meta.chain) {
|
|
434
434
|
return false;
|
|
435
435
|
}
|
|
436
|
-
return !!_.find(object.__meta.chain, { name
|
|
436
|
+
return !!_.find(object.__meta.chain, { name });
|
|
437
437
|
};
|
|
438
438
|
|
|
439
439
|
// Given a moog class name like `my-foo` or `@namespace/my-foo`,
|
|
@@ -212,8 +212,8 @@ module.exports = {
|
|
|
212
212
|
const item = {
|
|
213
213
|
name: name.indexOf(':') === -1 ? name : name.split(':')[0],
|
|
214
214
|
action: name,
|
|
215
|
-
label
|
|
216
|
-
permission
|
|
215
|
+
label,
|
|
216
|
+
permission,
|
|
217
217
|
options: options || {}
|
|
218
218
|
};
|
|
219
219
|
if (options && options.after) {
|
|
@@ -294,7 +294,7 @@ module.exports = {
|
|
|
294
294
|
self.items = self.items.concat(moving);
|
|
295
295
|
// ... But then explicit order kicks in
|
|
296
296
|
_.each(self.options.order || [], function (name) {
|
|
297
|
-
const item = _.find(self.items, { name
|
|
297
|
+
const item = _.find(self.items, { name });
|
|
298
298
|
if (item) {
|
|
299
299
|
self.items = [ item ].concat(_.filter(self.items, function (item) {
|
|
300
300
|
return item.name !== name;
|
|
@@ -323,7 +323,7 @@ module.exports = {
|
|
|
323
323
|
self.groupLabels[group.items[0]] = group.label;
|
|
324
324
|
|
|
325
325
|
group.items.forEach(function (name, groupIndex) {
|
|
326
|
-
const item = _.find(self.items, { name
|
|
326
|
+
const item = _.find(self.items, { name });
|
|
327
327
|
if (item) {
|
|
328
328
|
item.menuLeader = group.items[0];
|
|
329
329
|
} else {
|
|
@@ -336,7 +336,7 @@ module.exports = {
|
|
|
336
336
|
if (indexLeader === -1) {
|
|
337
337
|
throw new Error('Admin bar grouping error: no match for ' + item.menuLeader + ' in menu item ' + item.name);
|
|
338
338
|
}
|
|
339
|
-
let indexMe = _.findIndex(self.items, { name
|
|
339
|
+
let indexMe = _.findIndex(self.items, { name });
|
|
340
340
|
if (indexMe !== indexLeader + groupIndex) {
|
|
341
341
|
// Swap ourselves into the right position following our leader
|
|
342
342
|
if (indexLeader + groupIndex < indexMe) {
|
|
@@ -391,7 +391,7 @@ module.exports = {
|
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
393
|
return {
|
|
394
|
-
items
|
|
394
|
+
items,
|
|
395
395
|
components: { the: 'TheAposAdminBar' },
|
|
396
396
|
context: context && {
|
|
397
397
|
_id: context._id,
|
|
@@ -126,6 +126,10 @@ module.exports = {
|
|
|
126
126
|
setWidgetManager(name, manager) {
|
|
127
127
|
self.widgetManagers[name] = manager;
|
|
128
128
|
},
|
|
129
|
+
// Given the options passed to the area field, return the options passed
|
|
130
|
+
// to each widget type, indexed by widget name. This provides a consistent
|
|
131
|
+
// interface regardless of whether `options.widgets` or `options.groups`
|
|
132
|
+
// was used.
|
|
129
133
|
getWidgets(options) {
|
|
130
134
|
let widgets = options.widgets || {};
|
|
131
135
|
|
|
@@ -167,7 +171,11 @@ module.exports = {
|
|
|
167
171
|
},
|
|
168
172
|
// Render the given `area` object via `area.html`, with the given `context`
|
|
169
173
|
// which may be omitted. Called for you by the `{% area %} custom tag.
|
|
170
|
-
|
|
174
|
+
//
|
|
175
|
+
// If `inline` is true then the rendering of each widget is attached
|
|
176
|
+
// to the widget as a `_rendered` property, bypassing normal full-area
|
|
177
|
+
// HTML responses, and the return value of this method is `null`.
|
|
178
|
+
async renderArea(req, area, _with, { inline = false } = {}) {
|
|
171
179
|
if (!area._id) {
|
|
172
180
|
throw new Error('All areas must have an _id property in A3.x. Area details:\n\n' + JSON.stringify(area));
|
|
173
181
|
}
|
|
@@ -193,7 +201,7 @@ module.exports = {
|
|
|
193
201
|
const manager = self.widgetManagers[name];
|
|
194
202
|
if (manager) {
|
|
195
203
|
choices.push({
|
|
196
|
-
name
|
|
204
|
+
name,
|
|
197
205
|
icon: manager.options.icon,
|
|
198
206
|
label: options.addLabel || manager.label || `No label for ${name}`
|
|
199
207
|
});
|
|
@@ -212,6 +220,12 @@ module.exports = {
|
|
|
212
220
|
// just use the helpers
|
|
213
221
|
self.apos.attachment.all(area, { annotate: true });
|
|
214
222
|
}
|
|
223
|
+
if (inline) {
|
|
224
|
+
for (const item of area.items) {
|
|
225
|
+
item._rendered = await self.renderWidget(req, item.type, item, widgets[item.type]);
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
215
229
|
return self.render(req, 'area', {
|
|
216
230
|
// TODO filter area to exclude big relationship objects, but
|
|
217
231
|
// not so sloppy this time please
|
|
@@ -226,7 +240,13 @@ module.exports = {
|
|
|
226
240
|
// Replace documents' area objects with rendered HTML for each area.
|
|
227
241
|
// This is used by GET requests including the `render-areas` query
|
|
228
242
|
// parameter. `within` is an array of Apostrophe documents.
|
|
229
|
-
|
|
243
|
+
//
|
|
244
|
+
// If `inline` is true a rendering of each individual widget is
|
|
245
|
+
// added as an extra `_rendered` property of that widget, alongside
|
|
246
|
+
// its normal properties. Otherwise a rendering of the entire area
|
|
247
|
+
// is supplied as the `_rendered` property of that area and the
|
|
248
|
+
// `items` array is suppressed from the response.
|
|
249
|
+
async renderDocsAreas(req, within, { inline = false } = {}) {
|
|
230
250
|
within = Array.isArray(within) ? within : [];
|
|
231
251
|
let index = 0;
|
|
232
252
|
// Loop over the docs in the array passed in.
|
|
@@ -270,8 +290,10 @@ module.exports = {
|
|
|
270
290
|
async function render(area, path, context, opts) {
|
|
271
291
|
const preppedArea = self.prepForRender(area, context, path);
|
|
272
292
|
|
|
273
|
-
const areaRendered = await self.apos.area.renderArea(req, preppedArea, context);
|
|
274
|
-
|
|
293
|
+
const areaRendered = await self.apos.area.renderArea(req, preppedArea, context, { inline });
|
|
294
|
+
if (inline) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
275
297
|
_.set(context, [ path, '_rendered' ], areaRendered);
|
|
276
298
|
_.set(context, [ path, '_fieldId' ], undefined);
|
|
277
299
|
_.set(context, [ path, 'items' ], undefined);
|
|
@@ -412,7 +434,7 @@ module.exports = {
|
|
|
412
434
|
}
|
|
413
435
|
_.set(doc, dotPath, {
|
|
414
436
|
metaType: 'area',
|
|
415
|
-
items
|
|
437
|
+
items
|
|
416
438
|
});
|
|
417
439
|
return self.apos.doc.update(req, doc);
|
|
418
440
|
}
|
|
@@ -724,7 +746,7 @@ module.exports = {
|
|
|
724
746
|
} else {
|
|
725
747
|
area = doc[name];
|
|
726
748
|
}
|
|
727
|
-
return self.isEmpty({ area
|
|
749
|
+
return self.isEmpty({ area });
|
|
728
750
|
}
|
|
729
751
|
};
|
|
730
752
|
},
|
|
@@ -429,11 +429,11 @@ export default {
|
|
|
429
429
|
},
|
|
430
430
|
|
|
431
431
|
attachKeyboardFocusHandler() {
|
|
432
|
-
this.$refs.wrapper
|
|
432
|
+
this.$refs.wrapper?.addEventListener('keydown', this.handleKeyboardFocus);
|
|
433
433
|
},
|
|
434
434
|
|
|
435
435
|
removeKeyboardFocusHandler() {
|
|
436
|
-
this.$refs.wrapper
|
|
436
|
+
this.$refs.wrapper?.removeEventListener('keydown', this.handleKeyboardFocus);
|
|
437
437
|
},
|
|
438
438
|
|
|
439
439
|
// Focus parent, useful for obtrusive UI
|
|
@@ -98,6 +98,10 @@ module.exports = {
|
|
|
98
98
|
// Force the HMR WS port when it operates on the same process as Apostrophe.
|
|
99
99
|
// Most of the time you won't need to change this.
|
|
100
100
|
hmrPort: null,
|
|
101
|
+
// Let the external build module inject a pollyfill for the module preload,
|
|
102
|
+
// adding the `modulepreload` support for the browsers that don't support it.
|
|
103
|
+
// Can be disabled in e.g. external front-ends.
|
|
104
|
+
modulePreloadPolyfill: true,
|
|
101
105
|
// Completely disable the asset runtime auto-build system.
|
|
102
106
|
// When an external build module is registered, only manifest data
|
|
103
107
|
// will be loaded and no build will be executed.
|
|
@@ -477,9 +481,11 @@ module.exports = {
|
|
|
477
481
|
// - `devServer`: if `false`, the dev server is disabled. Otherwise, it's a string
|
|
478
482
|
// (enum) `public` or `apos`. Note that if `hmr` is disabled, the dev server will be always
|
|
479
483
|
// `false`.
|
|
484
|
+
// - `modulePreloadPolyfill`: if `true`, a module preload polyfill is injected.
|
|
480
485
|
// - `types`: optional array, if present it represents the only entrypoint types (entrypoint.type)
|
|
481
486
|
// that should be built.
|
|
482
487
|
// - `sourcemaps`: if `true`, the source maps are generated in production.
|
|
488
|
+
// - `postcssViewportToContainerToggle`: the configuration for the breakpoint preview plugin.
|
|
483
489
|
//
|
|
484
490
|
// Note that this getter depends on the current build task arguments. You shouldn't
|
|
485
491
|
// use that directly.
|
|
@@ -494,15 +500,22 @@ module.exports = {
|
|
|
494
500
|
isTask: !argv['check-apos-build'],
|
|
495
501
|
hmr: self.hasHMR(),
|
|
496
502
|
hmrPort: self.options.hmrPort,
|
|
497
|
-
|
|
503
|
+
modulePreloadPolyfill: self.options.modulePreloadPolyfill,
|
|
504
|
+
sourcemaps: self.options.productionSourceMaps,
|
|
505
|
+
postcssViewportToContainerToggle: {
|
|
506
|
+
enable: self.options.breakpointPreviewMode?.enable === true,
|
|
507
|
+
debug: self.options.breakpointPreviewMode?.debug === true,
|
|
508
|
+
modifierAttr: 'data-breakpoint-preview-mode',
|
|
509
|
+
transform: self.options.breakpointPreviewMode?.transform
|
|
510
|
+
}
|
|
498
511
|
};
|
|
499
512
|
options.devServer = !options.isTask && self.hasDevServer()
|
|
500
513
|
? self.options.hmr
|
|
501
514
|
: false;
|
|
502
515
|
|
|
503
|
-
// Skip
|
|
516
|
+
// Skip prebundled UI and keep only the apos scenes.
|
|
504
517
|
if (!self.options.publicBundle) {
|
|
505
|
-
options.types = [ 'apos', '
|
|
518
|
+
options.types = [ 'apos', 'index' ];
|
|
506
519
|
}
|
|
507
520
|
|
|
508
521
|
return options;
|
|
@@ -627,7 +640,7 @@ module.exports = {
|
|
|
627
640
|
return;
|
|
628
641
|
}
|
|
629
642
|
|
|
630
|
-
//
|
|
643
|
+
// Hydrate the entrypoints with the saved manifest data and
|
|
631
644
|
// set the current build manifest data.
|
|
632
645
|
const buildOptions = self.getBuildOptions();
|
|
633
646
|
const entrypoints = await self.getBuildModule().entrypoints(buildOptions);
|
|
@@ -69,13 +69,8 @@ module.exports = (self) => {
|
|
|
69
69
|
// Returns an array of objects with the following properties:
|
|
70
70
|
// - `name`: the entrypoint name. It's usually the relative to `ui` folder
|
|
71
71
|
// name(`src`, `apos`, `public`) or an extra bundle name.
|
|
72
|
+
// - `label`: the human-readable label for the entrypoint, used to print CLI messages.
|
|
72
73
|
// - `type`: (enum) the entrypoint type. It can be `index`, `apos`, `custom` (e.g. extra bundles) or
|
|
73
|
-
// `bundled` (e.g. `ui/public`). Every type has associated manager that provides handling for the entrypoint.
|
|
74
|
-
// - `useMeta`: if `true`, the entrypoint will be created based on the source metadata (see
|
|
75
|
-
// `computeSourceMeta()` method).
|
|
76
|
-
// - `bundle`: if `true`, the entrypoint should be bundled by the build module.
|
|
77
|
-
// - `index`: if `true`, the entrypoint processes only `{name}/index.{js,scss}` module files.
|
|
78
|
-
// - `apos`: if `true`, the entrypoint processes components, icons and apps.
|
|
79
74
|
// - `ignoreSources`: an array of sources that shouldn't be processed when creating the entrypoint.
|
|
80
75
|
// - `sources`: an object with `js` and `scss` arrays of extra sources to be included in the entrypoint.
|
|
81
76
|
// These sources are not affected by the `ignoreSources` configuration.
|
|
@@ -84,10 +79,15 @@ module.exports = (self) => {
|
|
|
84
79
|
// - `prologue`: a string with the prologue to be added to the entrypoint.
|
|
85
80
|
// - `condition`: the JS `module` or `nomodule` condition. Undefined for no specific condition.
|
|
86
81
|
// - `outputs`: an array of output extensions for the entrypoint (currently not fully utilized)
|
|
82
|
+
// - `inputs`: an array of input extensions for the entrypoint (currently not fully utilized)
|
|
87
83
|
// - `scenes`: an array of scenes to be in the final post-bundle step. The scenes are instructions
|
|
88
84
|
// for the Apostrophe core to combine the builds and release them. Currently supported scenes are
|
|
89
85
|
// `apos` and `public` and custom scene names equal to extra bundle (only those who should be
|
|
90
86
|
// loaded separately in the browser).
|
|
87
|
+
//
|
|
88
|
+
// Additonal properties added after entrypoints are processed by the core and the external build module:
|
|
89
|
+
// - `manifest`: object, see the manifest section of `configureBuildModule()` docs for more information.
|
|
90
|
+
// - `bundles`: a `Set` containing the bundle names that this entrypoint is part of (both css and js).
|
|
91
91
|
getBuildEntrypoints(types, recompute = false) {
|
|
92
92
|
if (!self.hasBuildModule()) {
|
|
93
93
|
return self.builds;
|
|
@@ -323,6 +323,7 @@ function invoke() {
|
|
|
323
323
|
follow: false,
|
|
324
324
|
absolute: false
|
|
325
325
|
});
|
|
326
|
+
files.sort((a, b) => a.localeCompare(b, 'en'));
|
|
326
327
|
|
|
327
328
|
if (stats) {
|
|
328
329
|
// optimize fs calls
|
|
@@ -88,7 +88,7 @@ module.exports = (self) => {
|
|
|
88
88
|
enhancedConfig.ignoreSources.push(...bundleConfig.scss);
|
|
89
89
|
}
|
|
90
90
|
// 2.3. Add the extra bundle configuration so that
|
|
91
|
-
// it only processes the configured `sources`
|
|
91
|
+
// it only processes the configured `sources`
|
|
92
92
|
if (!bundleConfig.main) {
|
|
93
93
|
entrypoints.push({
|
|
94
94
|
name: bundleName,
|
|
@@ -308,9 +308,6 @@ module.exports = (self) => {
|
|
|
308
308
|
const {
|
|
309
309
|
imports = [], assets = [], dynamicImports = []
|
|
310
310
|
} = files;
|
|
311
|
-
if (!imports.length) {
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
311
|
|
|
315
312
|
for (const file of [ ...imports, ...dynamicImports, ...assets ]) {
|
|
316
313
|
if (seen[file]) {
|
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const postcssReplaceViewportUnitsPlugin = require('../postcss-replace-viewport-units-plugin');
|
|
3
|
-
|
|
4
1
|
module.exports = (options, apos) => {
|
|
5
2
|
const postcssPlugins = [
|
|
6
3
|
'autoprefixer',
|
|
7
4
|
{}
|
|
8
5
|
];
|
|
9
|
-
let mediaToContainerQueriesLoader = '';
|
|
10
|
-
|
|
11
|
-
if (apos.asset.options.breakpointPreviewMode?.enable === true) {
|
|
12
|
-
postcssPlugins.unshift(
|
|
13
|
-
postcssReplaceViewportUnitsPlugin()
|
|
14
|
-
);
|
|
15
|
-
mediaToContainerQueriesLoader = {
|
|
16
|
-
loader: path.resolve(__dirname, '../media-to-container-queries-loader.js'),
|
|
17
|
-
options: {
|
|
18
|
-
debug: apos.asset.options.breakpointPreviewMode?.debug === true,
|
|
19
|
-
transform: apos.asset.options.breakpointPreviewMode?.transform || null
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
6
|
|
|
24
7
|
return {
|
|
25
8
|
module: {
|
|
@@ -28,15 +11,22 @@ module.exports = (options, apos) => {
|
|
|
28
11
|
test: /\.css$/,
|
|
29
12
|
use: [
|
|
30
13
|
'vue-style-loader',
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
'css-loader',
|
|
15
|
+
{
|
|
16
|
+
loader: 'postcss-loader',
|
|
17
|
+
options: {
|
|
18
|
+
sourceMap: true,
|
|
19
|
+
postcssOptions: {
|
|
20
|
+
plugins: [ postcssPlugins ]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
33
24
|
]
|
|
34
25
|
},
|
|
35
26
|
{
|
|
36
27
|
test: /\.s[ac]ss$/,
|
|
37
28
|
use: [
|
|
38
29
|
'vue-style-loader',
|
|
39
|
-
mediaToContainerQueriesLoader,
|
|
40
30
|
'css-loader',
|
|
41
31
|
{
|
|
42
32
|
loader: 'postcss-loader',
|
|
@@ -1,26 +1,18 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
1
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
3
|
-
const
|
|
2
|
+
const postcssViewportToContainerToggle = require('postcss-viewport-to-container-toggle');
|
|
4
3
|
|
|
5
4
|
module.exports = (options, apos, srcBuildNames) => {
|
|
6
5
|
const postcssPlugins = [
|
|
6
|
+
...apos.asset.options.breakpointPreviewMode?.enable === true ? [
|
|
7
|
+
postcssViewportToContainerToggle({
|
|
8
|
+
modifierAttr: 'data-breakpoint-preview-mode',
|
|
9
|
+
debug: apos.asset.options.breakpointPreviewMode?.debug === true,
|
|
10
|
+
transform: apos.asset.options.breakpointPreviewMode?.transform || null
|
|
11
|
+
})
|
|
12
|
+
] : [],
|
|
7
13
|
'autoprefixer',
|
|
8
14
|
{}
|
|
9
15
|
];
|
|
10
|
-
let mediaToContainerQueriesLoader = '';
|
|
11
|
-
|
|
12
|
-
if (apos.asset.options.breakpointPreviewMode?.enable === true) {
|
|
13
|
-
postcssPlugins.unshift(
|
|
14
|
-
postcssReplaceViewportUnitsPlugin()
|
|
15
|
-
);
|
|
16
|
-
mediaToContainerQueriesLoader = {
|
|
17
|
-
loader: path.resolve(__dirname, '../media-to-container-queries-loader.js'),
|
|
18
|
-
options: {
|
|
19
|
-
debug: apos.asset.options.breakpointPreviewMode?.debug === true,
|
|
20
|
-
transform: apos.asset.options.breakpointPreviewMode?.transform || null
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
16
|
|
|
25
17
|
return {
|
|
26
18
|
module: {
|
|
@@ -30,8 +22,8 @@ module.exports = (options, apos, srcBuildNames) => {
|
|
|
30
22
|
use: [
|
|
31
23
|
// Instead of style-loader, to avoid FOUC
|
|
32
24
|
MiniCssExtractPlugin.loader,
|
|
33
|
-
|
|
34
|
-
//
|
|
25
|
+
// Parses CSS imports and make css-loader ignore urls.
|
|
26
|
+
// Urls will still be handled by webpack
|
|
35
27
|
{
|
|
36
28
|
loader: 'css-loader',
|
|
37
29
|
options: { url: false }
|
|
@@ -298,7 +298,7 @@ module.exports = {
|
|
|
298
298
|
texts.push({
|
|
299
299
|
weight: field.weight || 15,
|
|
300
300
|
text: (value && value.title) || '',
|
|
301
|
-
silent
|
|
301
|
+
silent
|
|
302
302
|
});
|
|
303
303
|
},
|
|
304
304
|
// When the field is registered in the schema,
|
|
@@ -414,7 +414,7 @@ module.exports = {
|
|
|
414
414
|
createdAt: new Date(),
|
|
415
415
|
name: self.apos.util.slugify(path.basename(file.name, path.extname(file.name))),
|
|
416
416
|
title: self.apos.util.sortify(path.basename(file.name, path.extname(file.name))),
|
|
417
|
-
extension
|
|
417
|
+
extension,
|
|
418
418
|
type: 'attachment',
|
|
419
419
|
docIds: options.docIds ?? [],
|
|
420
420
|
archivedDocIds: options.archivedDocIds ?? []
|
|
@@ -565,7 +565,7 @@ module.exports = {
|
|
|
565
565
|
|
|
566
566
|
await Promise.promisify(self.uploadfs.copyOut)(originalFile, tempFile);
|
|
567
567
|
await Promise.promisify(self.uploadfs.copyImageIn)(tempFile, croppedFile, {
|
|
568
|
-
crop
|
|
568
|
+
crop,
|
|
569
569
|
sizes: self.imageSizes
|
|
570
570
|
});
|
|
571
571
|
|
|
@@ -909,8 +909,8 @@ module.exports = {
|
|
|
909
909
|
const x = attachment._focalPoint ? attachment._focalPoint.x : attachment.x;
|
|
910
910
|
const y = attachment._focalPoint ? attachment._focalPoint.y : attachment.y;
|
|
911
911
|
return {
|
|
912
|
-
x
|
|
913
|
-
y
|
|
912
|
+
x,
|
|
913
|
+
y
|
|
914
914
|
};
|
|
915
915
|
},
|
|
916
916
|
// Returns true if this type of attachment is croppable.
|
|
@@ -1140,7 +1140,7 @@ module.exports = {
|
|
|
1140
1140
|
continue;
|
|
1141
1141
|
}
|
|
1142
1142
|
const path = self.url(attachment, {
|
|
1143
|
-
crop
|
|
1143
|
+
crop,
|
|
1144
1144
|
uploadfsPath: true,
|
|
1145
1145
|
size: size.name
|
|
1146
1146
|
});
|
|
@@ -68,7 +68,7 @@ module.exports = function(self) {
|
|
|
68
68
|
console.log('Cropping ' + tempFile + ' to ' + originalFile);
|
|
69
69
|
try {
|
|
70
70
|
await Promise.promisify(self.uploadfs.copyImageIn)(tempFile, originalFile, {
|
|
71
|
-
crop
|
|
71
|
+
crop,
|
|
72
72
|
sizes: self.imageSizes
|
|
73
73
|
});
|
|
74
74
|
} catch (e) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const { TinyColor } = require('@ctrl/tinycolor');
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
options: {
|
|
6
|
+
name: 'color',
|
|
7
|
+
alias: 'colorFields'
|
|
8
|
+
},
|
|
9
|
+
init(self) {
|
|
10
|
+
self.name = self.options.name;
|
|
11
|
+
self.addFieldType();
|
|
12
|
+
self.enableBrowserData();
|
|
13
|
+
},
|
|
14
|
+
methods(self) {
|
|
15
|
+
return {
|
|
16
|
+
addFieldType() {
|
|
17
|
+
self.apos.schema.addFieldType({
|
|
18
|
+
name: 'color',
|
|
19
|
+
async convert(req, field, data, destination) {
|
|
20
|
+
destination[field.name] = self.apos.launder.string(data[field.name]);
|
|
21
|
+
|
|
22
|
+
if (field.required && (_.isUndefined(destination[field.name]) || !destination[field.name].toString().length)) {
|
|
23
|
+
throw self.apos.error('required');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const test = new TinyColor(destination[field.name]);
|
|
27
|
+
if (!test.isValid && !destination[field.name].startsWith('--')) {
|
|
28
|
+
destination[field.name] = null;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
isEmpty: function (field, value) {
|
|
32
|
+
return !value.length;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
getBrowserData(req) {
|
|
37
|
+
return {
|
|
38
|
+
name: self.name,
|
|
39
|
+
action: self.action
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|