diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-includes/js/dist/core-data.js --- a/wp/wp-includes/js/dist/core-data.js Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-includes/js/dist/core-data.js Fri Sep 05 18:52:52 2025 +0200 @@ -2,188 +2,6 @@ /******/ "use strict"; /******/ var __webpack_modules__ = ({ -/***/ 6689: -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ createUndoManager: () => (/* binding */ createUndoManager) -/* harmony export */ }); -/* harmony import */ var _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(923); -/* harmony import */ var _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0__); -/** - * WordPress dependencies - */ - - -/** @typedef {import('./types').HistoryRecord} HistoryRecord */ -/** @typedef {import('./types').HistoryChange} HistoryChange */ -/** @typedef {import('./types').HistoryChanges} HistoryChanges */ -/** @typedef {import('./types').UndoManager} UndoManager */ - -/** - * Merge changes for a single item into a record of changes. - * - * @param {Record< string, HistoryChange >} changes1 Previous changes - * @param {Record< string, HistoryChange >} changes2 NextChanges - * - * @return {Record< string, HistoryChange >} Merged changes - */ -function mergeHistoryChanges(changes1, changes2) { - /** - * @type {Record< string, HistoryChange >} - */ - const newChanges = { - ...changes1 - }; - Object.entries(changes2).forEach(([key, value]) => { - if (newChanges[key]) { - newChanges[key] = { - ...newChanges[key], - to: value.to - }; - } else { - newChanges[key] = value; - } - }); - return newChanges; -} - -/** - * Adds history changes for a single item into a record of changes. - * - * @param {HistoryRecord} record The record to merge into. - * @param {HistoryChanges} changes The changes to merge. - */ -const addHistoryChangesIntoRecord = (record, changes) => { - const existingChangesIndex = record?.findIndex(({ - id: recordIdentifier - }) => { - return typeof recordIdentifier === 'string' ? recordIdentifier === changes.id : _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default()(recordIdentifier, changes.id); - }); - const nextRecord = [...record]; - if (existingChangesIndex !== -1) { - // If the edit is already in the stack leave the initial "from" value. - nextRecord[existingChangesIndex] = { - id: changes.id, - changes: mergeHistoryChanges(nextRecord[existingChangesIndex].changes, changes.changes) - }; - } else { - nextRecord.push(changes); - } - return nextRecord; -}; - -/** - * Creates an undo manager. - * - * @return {UndoManager} Undo manager. - */ -function createUndoManager() { - /** - * @type {HistoryRecord[]} - */ - let history = []; - /** - * @type {HistoryRecord} - */ - let stagedRecord = []; - /** - * @type {number} - */ - let offset = 0; - const dropPendingRedos = () => { - history = history.slice(0, offset || undefined); - offset = 0; - }; - const appendStagedRecordToLatestHistoryRecord = () => { - var _history$index; - const index = history.length === 0 ? 0 : history.length - 1; - let latestRecord = (_history$index = history[index]) !== null && _history$index !== void 0 ? _history$index : []; - stagedRecord.forEach(changes => { - latestRecord = addHistoryChangesIntoRecord(latestRecord, changes); - }); - stagedRecord = []; - history[index] = latestRecord; - }; - - /** - * Checks whether a record is empty. - * A record is considered empty if it the changes keep the same values. - * Also updates to function values are ignored. - * - * @param {HistoryRecord} record - * @return {boolean} Whether the record is empty. - */ - const isRecordEmpty = record => { - const filteredRecord = record.filter(({ - changes - }) => { - return Object.values(changes).some(({ - from, - to - }) => typeof from !== 'function' && typeof to !== 'function' && !_wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default()(from, to)); - }); - return !filteredRecord.length; - }; - return { - /** - * Record changes into the history. - * - * @param {HistoryRecord=} record A record of changes to record. - * @param {boolean} isStaged Whether to immediately create an undo point or not. - */ - addRecord(record, isStaged = false) { - const isEmpty = !record || isRecordEmpty(record); - if (isStaged) { - if (isEmpty) { - return; - } - record.forEach(changes => { - stagedRecord = addHistoryChangesIntoRecord(stagedRecord, changes); - }); - } else { - dropPendingRedos(); - if (stagedRecord.length) { - appendStagedRecordToLatestHistoryRecord(); - } - if (isEmpty) { - return; - } - history.push(record); - } - }, - undo() { - if (stagedRecord.length) { - dropPendingRedos(); - appendStagedRecordToLatestHistoryRecord(); - } - const undoRecord = history[history.length - 1 + offset]; - if (!undoRecord) { - return; - } - offset -= 1; - return undoRecord; - }, - redo() { - const redoRecord = history[history.length + offset]; - if (!redoRecord) { - return; - } - offset += 1; - return redoRecord; - }, - hasUndo() { - return !!history[history.length - 1 + offset]; - }, - hasRedo() { - return !!history[history.length + offset]; - } - }; -} - - -/***/ }), - /***/ 3249: /***/ ((module) => { @@ -575,13 +393,6 @@ }; -/***/ }), - -/***/ 923: -/***/ ((module) => { - -module.exports = window["wp"]["isShallowEqual"]; - /***/ }) /******/ }); @@ -653,59 +464,26 @@ /******/ /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { EntityProvider: () => (/* reexport */ EntityProvider), - __experimentalFetchLinkSuggestions: () => (/* reexport */ _experimental_fetch_link_suggestions), + __experimentalFetchLinkSuggestions: () => (/* reexport */ fetchLinkSuggestions), __experimentalFetchUrlData: () => (/* reexport */ _experimental_fetch_url_data), __experimentalUseEntityRecord: () => (/* reexport */ __experimentalUseEntityRecord), __experimentalUseEntityRecords: () => (/* reexport */ __experimentalUseEntityRecords), __experimentalUseResourcePermissions: () => (/* reexport */ __experimentalUseResourcePermissions), fetchBlockPatterns: () => (/* reexport */ fetchBlockPatterns), + privateApis: () => (/* reexport */ privateApis), store: () => (/* binding */ store), useEntityBlockEditor: () => (/* reexport */ useEntityBlockEditor), useEntityId: () => (/* reexport */ useEntityId), useEntityProp: () => (/* reexport */ useEntityProp), useEntityRecord: () => (/* reexport */ useEntityRecord), useEntityRecords: () => (/* reexport */ useEntityRecords), - useResourcePermissions: () => (/* reexport */ useResourcePermissions) -}); - -// NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/actions.js -var build_module_actions_namespaceObject = {}; -__webpack_require__.r(build_module_actions_namespaceObject); -__webpack_require__.d(build_module_actions_namespaceObject, { - __experimentalBatch: () => (__experimentalBatch), - __experimentalReceiveCurrentGlobalStylesId: () => (__experimentalReceiveCurrentGlobalStylesId), - __experimentalReceiveThemeBaseGlobalStyles: () => (__experimentalReceiveThemeBaseGlobalStyles), - __experimentalReceiveThemeGlobalStyleVariations: () => (__experimentalReceiveThemeGlobalStyleVariations), - __experimentalSaveSpecifiedEntityEdits: () => (__experimentalSaveSpecifiedEntityEdits), - __unstableCreateUndoLevel: () => (__unstableCreateUndoLevel), - addEntities: () => (addEntities), - deleteEntityRecord: () => (deleteEntityRecord), - editEntityRecord: () => (editEntityRecord), - receiveAutosaves: () => (receiveAutosaves), - receiveCurrentTheme: () => (receiveCurrentTheme), - receiveCurrentUser: () => (receiveCurrentUser), - receiveDefaultTemplateId: () => (receiveDefaultTemplateId), - receiveEmbedPreview: () => (receiveEmbedPreview), - receiveEntityRecords: () => (receiveEntityRecords), - receiveNavigationFallbackId: () => (receiveNavigationFallbackId), - receiveRevisions: () => (receiveRevisions), - receiveThemeGlobalStyleRevisions: () => (receiveThemeGlobalStyleRevisions), - receiveThemeSupports: () => (receiveThemeSupports), - receiveUploadPermissions: () => (receiveUploadPermissions), - receiveUserPermission: () => (receiveUserPermission), - receiveUserQuery: () => (receiveUserQuery), - redo: () => (redo), - saveEditedEntityRecord: () => (saveEditedEntityRecord), - saveEntityRecord: () => (saveEntityRecord), - undo: () => (undo) + useResourcePermissions: () => (/* reexport */ use_resource_permissions) }); // NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/selectors.js @@ -718,7 +496,6 @@ __experimentalGetDirtyEntityRecords: () => (__experimentalGetDirtyEntityRecords), __experimentalGetEntitiesBeingSaved: () => (__experimentalGetEntitiesBeingSaved), __experimentalGetEntityRecordNoResolver: () => (__experimentalGetEntityRecordNoResolver), - __experimentalGetTemplateForLink: () => (__experimentalGetTemplateForLink), canUser: () => (canUser), canUserEditEntityRecord: () => (canUserEditEntityRecord), getAuthors: () => (getAuthors), @@ -770,10 +547,56 @@ __webpack_require__.r(private_selectors_namespaceObject); __webpack_require__.d(private_selectors_namespaceObject, { getBlockPatternsForPostType: () => (getBlockPatternsForPostType), + getEntityRecordPermissions: () => (getEntityRecordPermissions), + getEntityRecordsPermissions: () => (getEntityRecordsPermissions), + getHomePage: () => (getHomePage), getNavigationFallbackId: () => (getNavigationFallbackId), + getPostsPageId: () => (getPostsPageId), + getRegisteredPostMeta: () => (getRegisteredPostMeta), + getTemplateId: () => (getTemplateId), getUndoManager: () => (getUndoManager) }); +// NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/actions.js +var build_module_actions_namespaceObject = {}; +__webpack_require__.r(build_module_actions_namespaceObject); +__webpack_require__.d(build_module_actions_namespaceObject, { + __experimentalBatch: () => (__experimentalBatch), + __experimentalReceiveCurrentGlobalStylesId: () => (__experimentalReceiveCurrentGlobalStylesId), + __experimentalReceiveThemeBaseGlobalStyles: () => (__experimentalReceiveThemeBaseGlobalStyles), + __experimentalReceiveThemeGlobalStyleVariations: () => (__experimentalReceiveThemeGlobalStyleVariations), + __experimentalSaveSpecifiedEntityEdits: () => (__experimentalSaveSpecifiedEntityEdits), + __unstableCreateUndoLevel: () => (__unstableCreateUndoLevel), + addEntities: () => (addEntities), + deleteEntityRecord: () => (deleteEntityRecord), + editEntityRecord: () => (editEntityRecord), + receiveAutosaves: () => (receiveAutosaves), + receiveCurrentTheme: () => (receiveCurrentTheme), + receiveCurrentUser: () => (receiveCurrentUser), + receiveDefaultTemplateId: () => (receiveDefaultTemplateId), + receiveEmbedPreview: () => (receiveEmbedPreview), + receiveEntityRecords: () => (receiveEntityRecords), + receiveNavigationFallbackId: () => (receiveNavigationFallbackId), + receiveRevisions: () => (receiveRevisions), + receiveThemeGlobalStyleRevisions: () => (receiveThemeGlobalStyleRevisions), + receiveThemeSupports: () => (receiveThemeSupports), + receiveUploadPermissions: () => (receiveUploadPermissions), + receiveUserPermission: () => (receiveUserPermission), + receiveUserPermissions: () => (receiveUserPermissions), + receiveUserQuery: () => (receiveUserQuery), + redo: () => (redo), + saveEditedEntityRecord: () => (saveEditedEntityRecord), + saveEntityRecord: () => (saveEntityRecord), + undo: () => (undo) +}); + +// NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/private-actions.js +var private_actions_namespaceObject = {}; +__webpack_require__.r(private_actions_namespaceObject); +__webpack_require__.d(private_actions_namespaceObject, { + receiveRegisteredPostMeta: () => (receiveRegisteredPostMeta) +}); + // NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/resolvers.js var resolvers_namespaceObject = {}; __webpack_require__.r(resolvers_namespaceObject); @@ -781,7 +604,6 @@ __experimentalGetCurrentGlobalStylesId: () => (resolvers_experimentalGetCurrentGlobalStylesId), __experimentalGetCurrentThemeBaseGlobalStyles: () => (resolvers_experimentalGetCurrentThemeBaseGlobalStyles), __experimentalGetCurrentThemeGlobalStylesVariations: () => (resolvers_experimentalGetCurrentThemeGlobalStylesVariations), - __experimentalGetTemplateForLink: () => (resolvers_experimentalGetTemplateForLink), canUser: () => (resolvers_canUser), canUserEditEntityRecord: () => (resolvers_canUserEditEntityRecord), getAuthors: () => (resolvers_getAuthors), @@ -795,26 +617,201 @@ getDefaultTemplateId: () => (resolvers_getDefaultTemplateId), getEditedEntityRecord: () => (resolvers_getEditedEntityRecord), getEmbedPreview: () => (resolvers_getEmbedPreview), + getEntitiesConfig: () => (resolvers_getEntitiesConfig), getEntityRecord: () => (resolvers_getEntityRecord), getEntityRecords: () => (resolvers_getEntityRecords), getNavigationFallbackId: () => (resolvers_getNavigationFallbackId), getRawEntityRecord: () => (resolvers_getRawEntityRecord), + getRegisteredPostMeta: () => (resolvers_getRegisteredPostMeta), getRevision: () => (resolvers_getRevision), getRevisions: () => (resolvers_getRevisions), getThemeSupports: () => (resolvers_getThemeSupports), getUserPatternCategories: () => (resolvers_getUserPatternCategories) }); -;// CONCATENATED MODULE: external ["wp","data"] +;// external ["wp","data"] const external_wp_data_namespaceObject = window["wp"]["data"]; // EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js var es6 = __webpack_require__(7734); var es6_default = /*#__PURE__*/__webpack_require__.n(es6); -;// CONCATENATED MODULE: external ["wp","compose"] +;// external ["wp","compose"] const external_wp_compose_namespaceObject = window["wp"]["compose"]; -// EXTERNAL MODULE: ./node_modules/@wordpress/undo-manager/build-module/index.js -var build_module = __webpack_require__(6689); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/if-matching-action.js +;// external ["wp","isShallowEqual"] +const external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"]; +var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject); +;// ./node_modules/@wordpress/undo-manager/build-module/index.js +/** + * WordPress dependencies + */ + + +/** @typedef {import('./types').HistoryRecord} HistoryRecord */ +/** @typedef {import('./types').HistoryChange} HistoryChange */ +/** @typedef {import('./types').HistoryChanges} HistoryChanges */ +/** @typedef {import('./types').UndoManager} UndoManager */ + +/** + * Merge changes for a single item into a record of changes. + * + * @param {Record< string, HistoryChange >} changes1 Previous changes + * @param {Record< string, HistoryChange >} changes2 NextChanges + * + * @return {Record< string, HistoryChange >} Merged changes + */ +function mergeHistoryChanges(changes1, changes2) { + /** + * @type {Record< string, HistoryChange >} + */ + const newChanges = { + ...changes1 + }; + Object.entries(changes2).forEach(([key, value]) => { + if (newChanges[key]) { + newChanges[key] = { + ...newChanges[key], + to: value.to + }; + } else { + newChanges[key] = value; + } + }); + return newChanges; +} + +/** + * Adds history changes for a single item into a record of changes. + * + * @param {HistoryRecord} record The record to merge into. + * @param {HistoryChanges} changes The changes to merge. + */ +const addHistoryChangesIntoRecord = (record, changes) => { + const existingChangesIndex = record?.findIndex(({ + id: recordIdentifier + }) => { + return typeof recordIdentifier === 'string' ? recordIdentifier === changes.id : external_wp_isShallowEqual_default()(recordIdentifier, changes.id); + }); + const nextRecord = [...record]; + if (existingChangesIndex !== -1) { + // If the edit is already in the stack leave the initial "from" value. + nextRecord[existingChangesIndex] = { + id: changes.id, + changes: mergeHistoryChanges(nextRecord[existingChangesIndex].changes, changes.changes) + }; + } else { + nextRecord.push(changes); + } + return nextRecord; +}; + +/** + * Creates an undo manager. + * + * @return {UndoManager} Undo manager. + */ +function createUndoManager() { + /** + * @type {HistoryRecord[]} + */ + let history = []; + /** + * @type {HistoryRecord} + */ + let stagedRecord = []; + /** + * @type {number} + */ + let offset = 0; + const dropPendingRedos = () => { + history = history.slice(0, offset || undefined); + offset = 0; + }; + const appendStagedRecordToLatestHistoryRecord = () => { + var _history$index; + const index = history.length === 0 ? 0 : history.length - 1; + let latestRecord = (_history$index = history[index]) !== null && _history$index !== void 0 ? _history$index : []; + stagedRecord.forEach(changes => { + latestRecord = addHistoryChangesIntoRecord(latestRecord, changes); + }); + stagedRecord = []; + history[index] = latestRecord; + }; + + /** + * Checks whether a record is empty. + * A record is considered empty if it the changes keep the same values. + * Also updates to function values are ignored. + * + * @param {HistoryRecord} record + * @return {boolean} Whether the record is empty. + */ + const isRecordEmpty = record => { + const filteredRecord = record.filter(({ + changes + }) => { + return Object.values(changes).some(({ + from, + to + }) => typeof from !== 'function' && typeof to !== 'function' && !external_wp_isShallowEqual_default()(from, to)); + }); + return !filteredRecord.length; + }; + return { + /** + * Record changes into the history. + * + * @param {HistoryRecord=} record A record of changes to record. + * @param {boolean} isStaged Whether to immediately create an undo point or not. + */ + addRecord(record, isStaged = false) { + const isEmpty = !record || isRecordEmpty(record); + if (isStaged) { + if (isEmpty) { + return; + } + record.forEach(changes => { + stagedRecord = addHistoryChangesIntoRecord(stagedRecord, changes); + }); + } else { + dropPendingRedos(); + if (stagedRecord.length) { + appendStagedRecordToLatestHistoryRecord(); + } + if (isEmpty) { + return; + } + history.push(record); + } + }, + undo() { + if (stagedRecord.length) { + dropPendingRedos(); + appendStagedRecordToLatestHistoryRecord(); + } + const undoRecord = history[history.length - 1 + offset]; + if (!undoRecord) { + return; + } + offset -= 1; + return undoRecord; + }, + redo() { + const redoRecord = history[history.length + offset]; + if (!redoRecord) { + return; + } + offset += 1; + return redoRecord; + }, + hasUndo() { + return !!history[history.length - 1 + offset]; + }, + hasRedo() { + return !!history[history.length + offset]; + } + }; +} + +;// ./node_modules/@wordpress/core-data/build-module/utils/if-matching-action.js /** @typedef {import('../types').AnyFunction} AnyFunction */ /** @@ -834,7 +831,7 @@ }; /* harmony default export */ const if_matching_action = (ifMatchingAction); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/replace-action.js +;// ./node_modules/@wordpress/core-data/build-module/utils/replace-action.js /** @typedef {import('../types').AnyFunction} AnyFunction */ /** @@ -850,7 +847,7 @@ }; /* harmony default export */ const replace_action = (replaceAction); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/conservative-map-item.js +;// ./node_modules/@wordpress/core-data/build-module/utils/conservative-map-item.js /** * External dependencies */ @@ -896,7 +893,7 @@ return result; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/on-sub-key.js +;// ./node_modules/@wordpress/core-data/build-module/utils/on-sub-key.js /** @typedef {import('../types').AnyFunction} AnyFunction */ /** @@ -928,7 +925,7 @@ }; /* harmony default export */ const on_sub_key = (onSubKey); -;// CONCATENATED MODULE: ./node_modules/tslib/tslib.es6.mjs +;// ./node_modules/tslib/tslib.es6.mjs /****************************************************************************** Copyright (c) Microsoft Corporation. @@ -943,7 +940,7 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ -/* global Reflect, Promise, SuppressedError, Symbol */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || @@ -1054,8 +1051,8 @@ } function __generator(thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); @@ -1159,8 +1156,9 @@ function __asyncGenerator(thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; - function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } @@ -1193,10 +1191,19 @@ o["default"] = v; }; +var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); +}; + function __importStar(mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; } @@ -1226,16 +1233,18 @@ function __addDisposableResource(env, value, async) { if (value !== null && value !== void 0) { if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); - var dispose; + var dispose, inner; if (async) { - if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); - dispose = value[Symbol.asyncDispose]; + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; } if (dispose === void 0) { - if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); - dispose = value[Symbol.dispose]; + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + if (async) inner = dispose; } if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; env.stack.push({ value: value, dispose: dispose, async: async }); } else if (async) { @@ -1254,28 +1263,46 @@ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; env.hasError = true; } + var r, s = 0; function next() { - while (env.stack.length) { - var rec = env.stack.pop(); + while (r = env.stack.pop()) { try { - var result = rec.dispose && rec.dispose.call(rec.value); - if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; } catch (e) { - fail(e); + fail(e); } } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); if (env.hasError) throw env.error; } return next(); } +function __rewriteRelativeImportExtension(path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); + }); + } + return path; +} + /* harmony default export */ const tslib_es6 = ({ __extends, __assign, __rest, __decorate, __param, + __esDecorate, + __runInitializers, + __propKey, + __setFunctionName, __metadata, __awaiter, __generator, @@ -1298,9 +1325,10 @@ __classPrivateFieldIn, __addDisposableResource, __disposeResources, + __rewriteRelativeImportExtension, }); -;// CONCATENATED MODULE: ./node_modules/lower-case/dist.es2015/index.js +;// ./node_modules/lower-case/dist.es2015/index.js /** * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt */ @@ -1349,7 +1377,7 @@ return str.toLowerCase(); } -;// CONCATENATED MODULE: ./node_modules/no-case/dist.es2015/index.js +;// ./node_modules/no-case/dist.es2015/index.js // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case"). var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g]; @@ -1381,7 +1409,7 @@ return re.reduce(function (input, re) { return input.replace(re, value); }, input); } -;// CONCATENATED MODULE: ./node_modules/upper-case-first/dist.es2015/index.js +;// ./node_modules/upper-case-first/dist.es2015/index.js /** * Upper case the first character of an input string. */ @@ -1389,7 +1417,7 @@ return input.charAt(0).toUpperCase() + input.substr(1); } -;// CONCATENATED MODULE: ./node_modules/capital-case/dist.es2015/index.js +;// ./node_modules/capital-case/dist.es2015/index.js @@ -1401,7 +1429,7 @@ return noCase(input, __assign({ delimiter: " ", transform: capitalCaseTransform }, options)); } -;// CONCATENATED MODULE: ./node_modules/pascal-case/dist.es2015/index.js +;// ./node_modules/pascal-case/dist.es2015/index.js function pascalCaseTransform(input, index) { @@ -1420,1302 +1448,14 @@ return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options)); } -;// CONCATENATED MODULE: external ["wp","apiFetch"] +;// external ["wp","apiFetch"] const external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; var external_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_wp_apiFetch_namespaceObject); -;// CONCATENATED MODULE: external ["wp","i18n"] +;// external ["wp","i18n"] const external_wp_i18n_namespaceObject = window["wp"]["i18n"]; -;// CONCATENATED MODULE: external ["wp","richText"] +;// external ["wp","richText"] const external_wp_richText_namespaceObject = window["wp"]["richText"]; -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/native.js -const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); -/* harmony default export */ const esm_browser_native = ({ - randomUUID -}); -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/rng.js -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -let getRandomValues; -const rnds8 = new Uint8Array(16); -function rng() { - // lazy load so that environments that need to polyfill have a chance to do so - if (!getRandomValues) { - // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. - getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); - - if (!getRandomValues) { - throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); - } - } - - return getRandomValues(rnds8); -} -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/stringify.js - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ - -const byteToHex = []; - -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 0x100).toString(16).slice(1)); -} - -function unsafeStringify(arr, offset = 0) { - // Note: Be careful editing this code! It's been tuned for performance - // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 - return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; -} - -function stringify(arr, offset = 0) { - const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one - // of the following: - // - One or more input array values don't map to a hex octet (leading to - // "undefined" in the uuid) - // - Invalid input values for the RFC `version` or `variant` fields - - if (!validate(uuid)) { - throw TypeError('Stringified UUID is invalid'); - } - - return uuid; -} - -/* harmony default export */ const esm_browser_stringify = ((/* unused pure expression or super */ null && (stringify))); -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/v4.js - - - - -function v4(options, buf, offset) { - if (esm_browser_native.randomUUID && !buf && !options) { - return esm_browser_native.randomUUID(); - } - - options = options || {}; - const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - rnds[6] = rnds[6] & 0x0f | 0x40; - rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - - return buf; - } - - return unsafeStringify(rnds); -} - -/* harmony default export */ const esm_browser_v4 = (v4); -;// CONCATENATED MODULE: external ["wp","url"] -const external_wp_url_namespaceObject = window["wp"]["url"]; -;// CONCATENATED MODULE: external ["wp","deprecated"] -const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"]; -var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/set-nested-value.js -/** - * Sets the value at path of object. - * If a portion of path doesn’t exist, it’s created. - * Arrays are created for missing index properties while objects are created - * for all other missing properties. - * - * Path is specified as either: - * - a string of properties, separated by dots, for example: "x.y". - * - an array of properties, for example `[ 'x', 'y' ]`. - * - * This function intentionally mutates the input object. - * - * Inspired by _.set(). - * - * @see https://lodash.com/docs/4.17.15#set - * - * @todo Needs to be deduplicated with its copy in `@wordpress/edit-site`. - * - * @param {Object} object Object to modify - * @param {Array|string} path Path of the property to set. - * @param {*} value Value to set. - */ -function setNestedValue(object, path, value) { - if (!object || typeof object !== 'object') { - return object; - } - const normalizedPath = Array.isArray(path) ? path : path.split('.'); - normalizedPath.reduce((acc, key, idx) => { - if (acc[key] === undefined) { - if (Number.isInteger(normalizedPath[idx + 1])) { - acc[key] = []; - } else { - acc[key] = {}; - } - } - if (idx === normalizedPath.length - 1) { - acc[key] = value; - } - return acc[key]; - }, object); - return object; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/get-nested-value.js -/** - * Helper util to return a value from a certain path of the object. - * Path is specified as either: - * - a string of properties, separated by dots, for example: "x.y". - * - an array of properties, for example `[ 'x', 'y' ]`. - * You can also specify a default value in case the result is nullish. - * - * @param {Object} object Input object. - * @param {string|Array} path Path to the object property. - * @param {*} defaultValue Default value if the value at the specified path is undefined. - * @return {*} Value of the object property at the specified path. - */ -function getNestedValue(object, path, defaultValue) { - if (!object || typeof object !== 'object' || typeof path !== 'string' && !Array.isArray(path)) { - return object; - } - const normalizedPath = Array.isArray(path) ? path : path.split('.'); - let value = object; - normalizedPath.forEach(fieldName => { - value = value?.[fieldName]; - }); - return value !== undefined ? value : defaultValue; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/actions.js -/** - * Returns an action object used in signalling that items have been received. - * - * @param {Array} items Items received. - * @param {?Object} edits Optional edits to reset. - * @param {?Object} meta Meta information about pagination. - * - * @return {Object} Action object. - */ -function receiveItems(items, edits, meta) { - return { - type: 'RECEIVE_ITEMS', - items: Array.isArray(items) ? items : [items], - persistedEdits: edits, - meta - }; -} - -/** - * Returns an action object used in signalling that entity records have been - * deleted and they need to be removed from entities state. - * - * @param {string} kind Kind of the removed entities. - * @param {string} name Name of the removed entities. - * @param {Array|number|string} records Record IDs of the removed entities. - * @param {boolean} invalidateCache Controls whether we want to invalidate the cache. - * @return {Object} Action object. - */ -function removeItems(kind, name, records, invalidateCache = false) { - return { - type: 'REMOVE_ITEMS', - itemIds: Array.isArray(records) ? records : [records], - kind, - name, - invalidateCache - }; -} - -/** - * Returns an action object used in signalling that queried data has been - * received. - * - * @param {Array} items Queried items received. - * @param {?Object} query Optional query object. - * @param {?Object} edits Optional edits to reset. - * @param {?Object} meta Meta information about pagination. - * - * @return {Object} Action object. - */ -function receiveQueriedItems(items, query = {}, edits, meta) { - return { - ...receiveItems(items, edits, meta), - query - }; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/batch/default-processor.js -/** - * WordPress dependencies - */ - - -/** - * Maximum number of requests to place in a single batch request. Obtained by - * sending a preflight OPTIONS request to /batch/v1/. - * - * @type {number?} - */ -let maxItems = null; -function chunk(arr, chunkSize) { - const tmp = [...arr]; - const cache = []; - while (tmp.length) { - cache.push(tmp.splice(0, chunkSize)); - } - return cache; -} - -/** - * Default batch processor. Sends its input requests to /batch/v1. - * - * @param {Array} requests List of API requests to perform at once. - * - * @return {Promise} Promise that resolves to a list of objects containing - * either `output` (if that request was successful) or `error` - * (if not ). - */ -async function defaultProcessor(requests) { - if (maxItems === null) { - const preflightResponse = await external_wp_apiFetch_default()({ - path: '/batch/v1', - method: 'OPTIONS' - }); - maxItems = preflightResponse.endpoints[0].args.requests.maxItems; - } - const results = []; - - // @ts-ignore We would have crashed or never gotten to this point if we hadn't received the maxItems count. - for (const batchRequests of chunk(requests, maxItems)) { - const batchResponse = await external_wp_apiFetch_default()({ - path: '/batch/v1', - method: 'POST', - data: { - validation: 'require-all-validate', - requests: batchRequests.map(request => ({ - path: request.path, - body: request.data, - // Rename 'data' to 'body'. - method: request.method, - headers: request.headers - })) - } - }); - let batchResults; - if (batchResponse.failed) { - batchResults = batchResponse.responses.map(response => ({ - error: response?.body - })); - } else { - batchResults = batchResponse.responses.map(response => { - const result = {}; - if (response.status >= 200 && response.status < 300) { - result.output = response.body; - } else { - result.error = response.body; - } - return result; - }); - } - results.push(...batchResults); - } - return results; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/batch/create-batch.js -/** - * Internal dependencies - */ - - -/** - * Creates a batch, which can be used to combine multiple API requests into one - * API request using the WordPress batch processing API (/v1/batch). - * - * ``` - * const batch = createBatch(); - * const dunePromise = batch.add( { - * path: '/v1/books', - * method: 'POST', - * data: { title: 'Dune' } - * } ); - * const lotrPromise = batch.add( { - * path: '/v1/books', - * method: 'POST', - * data: { title: 'Lord of the Rings' } - * } ); - * const isSuccess = await batch.run(); // Sends one POST to /v1/batch. - * if ( isSuccess ) { - * console.log( - * 'Saved two books:', - * await dunePromise, - * await lotrPromise - * ); - * } - * ``` - * - * @param {Function} [processor] Processor function. Can be used to replace the - * default functionality which is to send an API - * request to /v1/batch. Is given an array of - * inputs and must return a promise that - * resolves to an array of objects containing - * either `output` or `error`. - */ -function createBatch(processor = defaultProcessor) { - let lastId = 0; - /** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */ - let queue = []; - const pending = new ObservableSet(); - return { - /** - * Adds an input to the batch and returns a promise that is resolved or - * rejected when the input is processed by `batch.run()`. - * - * You may also pass a thunk which allows inputs to be added - * asychronously. - * - * ``` - * // Both are allowed: - * batch.add( { path: '/v1/books', ... } ); - * batch.add( ( add ) => add( { path: '/v1/books', ... } ) ); - * ``` - * - * If a thunk is passed, `batch.run()` will pause until either: - * - * - The thunk calls its `add` argument, or; - * - The thunk returns a promise and that promise resolves, or; - * - The thunk returns a non-promise. - * - * @param {any|Function} inputOrThunk Input to add or thunk to execute. - * - * @return {Promise|any} If given an input, returns a promise that - * is resolved or rejected when the batch is - * processed. If given a thunk, returns the return - * value of that thunk. - */ - add(inputOrThunk) { - const id = ++lastId; - pending.add(id); - const add = input => new Promise((resolve, reject) => { - queue.push({ - input, - resolve, - reject - }); - pending.delete(id); - }); - if (typeof inputOrThunk === 'function') { - return Promise.resolve(inputOrThunk(add)).finally(() => { - pending.delete(id); - }); - } - return add(inputOrThunk); - }, - /** - * Runs the batch. This calls `batchProcessor` and resolves or rejects - * all promises returned by `add()`. - * - * @return {Promise} A promise that resolves to a boolean that is true - * if the processor returned no errors. - */ - async run() { - if (pending.size) { - await new Promise(resolve => { - const unsubscribe = pending.subscribe(() => { - if (!pending.size) { - unsubscribe(); - resolve(undefined); - } - }); - }); - } - let results; - try { - results = await processor(queue.map(({ - input - }) => input)); - if (results.length !== queue.length) { - throw new Error('run: Array returned by processor must be same size as input array.'); - } - } catch (error) { - for (const { - reject - } of queue) { - reject(error); - } - throw error; - } - let isSuccess = true; - results.forEach((result, key) => { - const queueItem = queue[key]; - if (result?.error) { - queueItem?.reject(result.error); - isSuccess = false; - } else { - var _result$output; - queueItem?.resolve((_result$output = result?.output) !== null && _result$output !== void 0 ? _result$output : result); - } - }); - queue = []; - return isSuccess; - } - }; -} -class ObservableSet { - constructor(...args) { - this.set = new Set(...args); - this.subscribers = new Set(); - } - get size() { - return this.set.size; - } - add(value) { - this.set.add(value); - this.subscribers.forEach(subscriber => subscriber()); - return this; - } - delete(value) { - const isSuccess = this.set.delete(value); - this.subscribers.forEach(subscriber => subscriber()); - return isSuccess; - } - subscribe(subscriber) { - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - } -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/name.js -/** - * The reducer key used by core data in store registration. - * This is defined in a separate file to avoid cycle-dependency - * - * @type {string} - */ -const STORE_NAME = 'core'; - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/actions.js -/** - * External dependencies - */ - - - -/** - * WordPress dependencies - */ - - - - -/** - * Internal dependencies - */ - - - - - - - -/** - * Returns an action object used in signalling that authors have been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} queryID Query ID. - * @param {Array|Object} users Users received. - * - * @return {Object} Action object. - */ -function receiveUserQuery(queryID, users) { - return { - type: 'RECEIVE_USER_QUERY', - users: Array.isArray(users) ? users : [users], - queryID - }; -} - -/** - * Returns an action used in signalling that the current user has been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {Object} currentUser Current user object. - * - * @return {Object} Action object. - */ -function receiveCurrentUser(currentUser) { - return { - type: 'RECEIVE_CURRENT_USER', - currentUser - }; -} - -/** - * Returns an action object used in adding new entities. - * - * @param {Array} entities Entities received. - * - * @return {Object} Action object. - */ -function addEntities(entities) { - return { - type: 'ADD_ENTITIES', - entities - }; -} - -/** - * Returns an action object used in signalling that entity records have been received. - * - * @param {string} kind Kind of the received entity record. - * @param {string} name Name of the received entity record. - * @param {Array|Object} records Records received. - * @param {?Object} query Query Object. - * @param {?boolean} invalidateCache Should invalidate query caches. - * @param {?Object} edits Edits to reset. - * @param {?Object} meta Meta information about pagination. - * @return {Object} Action object. - */ -function receiveEntityRecords(kind, name, records, query, invalidateCache = false, edits, meta) { - // Auto drafts should not have titles, but some plugins rely on them so we can't filter this - // on the server. - if (kind === 'postType') { - records = (Array.isArray(records) ? records : [records]).map(record => record.status === 'auto-draft' ? { - ...record, - title: '' - } : record); - } - let action; - if (query) { - action = receiveQueriedItems(records, query, edits, meta); - } else { - action = receiveItems(records, edits, meta); - } - return { - ...action, - kind, - name, - invalidateCache - }; -} - -/** - * Returns an action object used in signalling that the current theme has been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {Object} currentTheme The current theme. - * - * @return {Object} Action object. - */ -function receiveCurrentTheme(currentTheme) { - return { - type: 'RECEIVE_CURRENT_THEME', - currentTheme - }; -} - -/** - * Returns an action object used in signalling that the current global styles id has been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} currentGlobalStylesId The current global styles id. - * - * @return {Object} Action object. - */ -function __experimentalReceiveCurrentGlobalStylesId(currentGlobalStylesId) { - return { - type: 'RECEIVE_CURRENT_GLOBAL_STYLES_ID', - id: currentGlobalStylesId - }; -} - -/** - * Returns an action object used in signalling that the theme base global styles have been received - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} stylesheet The theme's identifier - * @param {Object} globalStyles The global styles object. - * - * @return {Object} Action object. - */ -function __experimentalReceiveThemeBaseGlobalStyles(stylesheet, globalStyles) { - return { - type: 'RECEIVE_THEME_GLOBAL_STYLES', - stylesheet, - globalStyles - }; -} - -/** - * Returns an action object used in signalling that the theme global styles variations have been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} stylesheet The theme's identifier - * @param {Array} variations The global styles variations. - * - * @return {Object} Action object. - */ -function __experimentalReceiveThemeGlobalStyleVariations(stylesheet, variations) { - return { - type: 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS', - stylesheet, - variations - }; -} - -/** - * Returns an action object used in signalling that the index has been received. - * - * @deprecated since WP 5.9, this is not useful anymore, use the selector direclty. - * - * @return {Object} Action object. - */ -function receiveThemeSupports() { - external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeSupports", { - since: '5.9' - }); - return { - type: 'DO_NOTHING' - }; -} - -/** - * Returns an action object used in signalling that the theme global styles CPT post revisions have been received. - * Ignored from documentation as it's internal to the data store. - * - * @deprecated since WordPress 6.5.0. Callers should use `dispatch( 'core' ).receiveRevision` instead. - * - * @ignore - * - * @param {number} currentId The post id. - * @param {Array} revisions The global styles revisions. - * - * @return {Object} Action object. - */ -function receiveThemeGlobalStyleRevisions(currentId, revisions) { - external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeGlobalStyleRevisions()", { - since: '6.5.0', - alternative: "wp.data.dispatch( 'core' ).receiveRevisions" - }); - return { - type: 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS', - currentId, - revisions - }; -} - -/** - * Returns an action object used in signalling that the preview data for - * a given URl has been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} url URL to preview the embed for. - * @param {*} preview Preview data. - * - * @return {Object} Action object. - */ -function receiveEmbedPreview(url, preview) { - return { - type: 'RECEIVE_EMBED_PREVIEW', - url, - preview - }; -} - -/** - * Action triggered to delete an entity record. - * - * @param {string} kind Kind of the deleted entity. - * @param {string} name Name of the deleted entity. - * @param {string} recordId Record ID of the deleted entity. - * @param {?Object} query Special query parameters for the - * DELETE API call. - * @param {Object} [options] Delete options. - * @param {Function} [options.__unstableFetch] Internal use only. Function to - * call instead of `apiFetch()`. - * Must return a promise. - * @param {boolean} [options.throwOnError=false] If false, this action suppresses all - * the exceptions. Defaults to false. - */ -const deleteEntityRecord = (kind, name, recordId, query, { - __unstableFetch = (external_wp_apiFetch_default()), - throwOnError = false -} = {}) => async ({ - dispatch -}) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.kind === kind && config.name === name); - let error; - let deletedRecord = false; - if (!entityConfig || entityConfig?.__experimentalNoFetch) { - return; - } - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId], { - exclusive: true - }); - try { - dispatch({ - type: 'DELETE_ENTITY_RECORD_START', - kind, - name, - recordId - }); - let hasError = false; - try { - let path = `${entityConfig.baseURL}/${recordId}`; - if (query) { - path = (0,external_wp_url_namespaceObject.addQueryArgs)(path, query); - } - deletedRecord = await __unstableFetch({ - path, - method: 'DELETE' - }); - await dispatch(removeItems(kind, name, recordId, true)); - } catch (_error) { - hasError = true; - error = _error; - } - dispatch({ - type: 'DELETE_ENTITY_RECORD_FINISH', - kind, - name, - recordId, - error - }); - if (hasError && throwOnError) { - throw error; - } - return deletedRecord; - } finally { - dispatch.__unstableReleaseStoreLock(lock); - } -}; - -/** - * Returns an action object that triggers an - * edit to an entity record. - * - * @param {string} kind Kind of the edited entity record. - * @param {string} name Name of the edited entity record. - * @param {number|string} recordId Record ID of the edited entity record. - * @param {Object} edits The edits. - * @param {Object} options Options for the edit. - * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. - * - * @return {Object} Action object. - */ -const editEntityRecord = (kind, name, recordId, edits, options = {}) => ({ - select, - dispatch -}) => { - const entityConfig = select.getEntityConfig(kind, name); - if (!entityConfig) { - throw new Error(`The entity being edited (${kind}, ${name}) does not have a loaded config.`); - } - const { - mergedEdits = {} - } = entityConfig; - const record = select.getRawEntityRecord(kind, name, recordId); - const editedRecord = select.getEditedEntityRecord(kind, name, recordId); - const edit = { - kind, - name, - recordId, - // Clear edits when they are equal to their persisted counterparts - // so that the property is not considered dirty. - edits: Object.keys(edits).reduce((acc, key) => { - const recordValue = record[key]; - const editedRecordValue = editedRecord[key]; - const value = mergedEdits[key] ? { - ...editedRecordValue, - ...edits[key] - } : edits[key]; - acc[key] = es6_default()(recordValue, value) ? undefined : value; - return acc; - }, {}) - }; - if (window.__experimentalEnableSync && entityConfig.syncConfig) { - if (false) {} - } else { - if (!options.undoIgnore) { - select.getUndoManager().addRecord([{ - id: { - kind, - name, - recordId - }, - changes: Object.keys(edits).reduce((acc, key) => { - acc[key] = { - from: editedRecord[key], - to: edits[key] - }; - return acc; - }, {}) - }], options.isCached); - } - dispatch({ - type: 'EDIT_ENTITY_RECORD', - ...edit - }); - } -}; - -/** - * Action triggered to undo the last edit to - * an entity record, if any. - */ -const undo = () => ({ - select, - dispatch -}) => { - const undoRecord = select.getUndoManager().undo(); - if (!undoRecord) { - return; - } - dispatch({ - type: 'UNDO', - record: undoRecord - }); -}; - -/** - * Action triggered to redo the last undoed - * edit to an entity record, if any. - */ -const redo = () => ({ - select, - dispatch -}) => { - const redoRecord = select.getUndoManager().redo(); - if (!redoRecord) { - return; - } - dispatch({ - type: 'REDO', - record: redoRecord - }); -}; - -/** - * Forces the creation of a new undo level. - * - * @return {Object} Action object. - */ -const __unstableCreateUndoLevel = () => ({ - select -}) => { - select.getUndoManager().addRecord(); -}; - -/** - * Action triggered to save an entity record. - * - * @param {string} kind Kind of the received entity. - * @param {string} name Name of the received entity. - * @param {Object} record Record to be saved. - * @param {Object} options Saving options. - * @param {boolean} [options.isAutosave=false] Whether this is an autosave. - * @param {Function} [options.__unstableFetch] Internal use only. Function to - * call instead of `apiFetch()`. - * Must return a promise. - * @param {boolean} [options.throwOnError=false] If false, this action suppresses all - * the exceptions. Defaults to false. - */ -const saveEntityRecord = (kind, name, record, { - isAutosave = false, - __unstableFetch = (external_wp_apiFetch_default()), - throwOnError = false -} = {}) => async ({ - select, - resolveSelect, - dispatch -}) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.kind === kind && config.name === name); - if (!entityConfig || entityConfig?.__experimentalNoFetch) { - return; - } - const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; - const recordId = record[entityIdKey]; - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId || esm_browser_v4()], { - exclusive: true - }); - try { - // Evaluate optimized edits. - // (Function edits that should be evaluated on save to avoid expensive computations on every edit.) - for (const [key, value] of Object.entries(record)) { - if (typeof value === 'function') { - const evaluatedValue = value(select.getEditedEntityRecord(kind, name, recordId)); - dispatch.editEntityRecord(kind, name, recordId, { - [key]: evaluatedValue - }, { - undoIgnore: true - }); - record[key] = evaluatedValue; - } - } - dispatch({ - type: 'SAVE_ENTITY_RECORD_START', - kind, - name, - recordId, - isAutosave - }); - let updatedRecord; - let error; - let hasError = false; - try { - const path = `${entityConfig.baseURL}${recordId ? '/' + recordId : ''}`; - const persistedRecord = select.getRawEntityRecord(kind, name, recordId); - if (isAutosave) { - // Most of this autosave logic is very specific to posts. - // This is fine for now as it is the only supported autosave, - // but ideally this should all be handled in the back end, - // so the client just sends and receives objects. - const currentUser = select.getCurrentUser(); - const currentUserId = currentUser ? currentUser.id : undefined; - const autosavePost = await resolveSelect.getAutosave(persistedRecord.type, persistedRecord.id, currentUserId); - // Autosaves need all expected fields to be present. - // So we fallback to the previous autosave and then - // to the actual persisted entity if the edits don't - // have a value. - let data = { - ...persistedRecord, - ...autosavePost, - ...record - }; - data = Object.keys(data).reduce((acc, key) => { - if (['title', 'excerpt', 'content', 'meta'].includes(key)) { - acc[key] = data[key]; - } - return acc; - }, { - // Do not update the `status` if we have edited it when auto saving. - // It's very important to let the user explicitly save this change, - // because it can lead to unexpected results. An example would be to - // have a draft post and change the status to publish. - status: data.status === 'auto-draft' ? 'draft' : undefined - }); - updatedRecord = await __unstableFetch({ - path: `${path}/autosaves`, - method: 'POST', - data - }); - - // An autosave may be processed by the server as a regular save - // when its update is requested by the author and the post had - // draft or auto-draft status. - if (persistedRecord.id === updatedRecord.id) { - let newRecord = { - ...persistedRecord, - ...data, - ...updatedRecord - }; - newRecord = Object.keys(newRecord).reduce((acc, key) => { - // These properties are persisted in autosaves. - if (['title', 'excerpt', 'content'].includes(key)) { - acc[key] = newRecord[key]; - } else if (key === 'status') { - // Status is only persisted in autosaves when going from - // "auto-draft" to "draft". - acc[key] = persistedRecord.status === 'auto-draft' && newRecord.status === 'draft' ? newRecord.status : persistedRecord.status; - } else { - // These properties are not persisted in autosaves. - acc[key] = persistedRecord[key]; - } - return acc; - }, {}); - dispatch.receiveEntityRecords(kind, name, newRecord, undefined, true); - } else { - dispatch.receiveAutosaves(persistedRecord.id, updatedRecord); - } - } else { - let edits = record; - if (entityConfig.__unstablePrePersist) { - edits = { - ...edits, - ...entityConfig.__unstablePrePersist(persistedRecord, edits) - }; - } - updatedRecord = await __unstableFetch({ - path, - method: recordId ? 'PUT' : 'POST', - data: edits - }); - dispatch.receiveEntityRecords(kind, name, updatedRecord, undefined, true, edits); - } - } catch (_error) { - hasError = true; - error = _error; - } - dispatch({ - type: 'SAVE_ENTITY_RECORD_FINISH', - kind, - name, - recordId, - error, - isAutosave - }); - if (hasError && throwOnError) { - throw error; - } - return updatedRecord; - } finally { - dispatch.__unstableReleaseStoreLock(lock); - } -}; - -/** - * Runs multiple core-data actions at the same time using one API request. - * - * Example: - * - * ``` - * const [ savedRecord, updatedRecord, deletedRecord ] = - * await dispatch( 'core' ).__experimentalBatch( [ - * ( { saveEntityRecord } ) => saveEntityRecord( 'root', 'widget', widget ), - * ( { saveEditedEntityRecord } ) => saveEntityRecord( 'root', 'widget', 123 ), - * ( { deleteEntityRecord } ) => deleteEntityRecord( 'root', 'widget', 123, null ), - * ] ); - * ``` - * - * @param {Array} requests Array of functions which are invoked simultaneously. - * Each function is passed an object containing - * `saveEntityRecord`, `saveEditedEntityRecord`, and - * `deleteEntityRecord`. - * - * @return {(thunkArgs: Object) => Promise} A promise that resolves to an array containing the return - * values of each function given in `requests`. - */ -const __experimentalBatch = requests => async ({ - dispatch -}) => { - const batch = createBatch(); - const api = { - saveEntityRecord(kind, name, record, options) { - return batch.add(add => dispatch.saveEntityRecord(kind, name, record, { - ...options, - __unstableFetch: add - })); - }, - saveEditedEntityRecord(kind, name, recordId, options) { - return batch.add(add => dispatch.saveEditedEntityRecord(kind, name, recordId, { - ...options, - __unstableFetch: add - })); - }, - deleteEntityRecord(kind, name, recordId, query, options) { - return batch.add(add => dispatch.deleteEntityRecord(kind, name, recordId, query, { - ...options, - __unstableFetch: add - })); - } - }; - const resultPromises = requests.map(request => request(api)); - const [, ...results] = await Promise.all([batch.run(), ...resultPromises]); - return results; -}; - -/** - * Action triggered to save an entity record's edits. - * - * @param {string} kind Kind of the entity. - * @param {string} name Name of the entity. - * @param {Object} recordId ID of the record. - * @param {Object} options Saving options. - */ -const saveEditedEntityRecord = (kind, name, recordId, options) => async ({ - select, - dispatch -}) => { - if (!select.hasEditsForEntityRecord(kind, name, recordId)) { - return; - } - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.kind === kind && config.name === name); - if (!entityConfig) { - return; - } - const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; - const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); - const record = { - [entityIdKey]: recordId, - ...edits - }; - return await dispatch.saveEntityRecord(kind, name, record, options); -}; - -/** - * Action triggered to save only specified properties for the entity. - * - * @param {string} kind Kind of the entity. - * @param {string} name Name of the entity. - * @param {Object} recordId ID of the record. - * @param {Array} itemsToSave List of entity properties or property paths to save. - * @param {Object} options Saving options. - */ -const __experimentalSaveSpecifiedEntityEdits = (kind, name, recordId, itemsToSave, options) => async ({ - select, - dispatch -}) => { - if (!select.hasEditsForEntityRecord(kind, name, recordId)) { - return; - } - const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); - const editsToSave = {}; - for (const item of itemsToSave) { - setNestedValue(editsToSave, item, getNestedValue(edits, item)); - } - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.kind === kind && config.name === name); - const entityIdKey = entityConfig?.key || DEFAULT_ENTITY_KEY; - - // If a record key is provided then update the existing record. - // This necessitates providing `recordKey` to saveEntityRecord as part of the - // `record` argument (here called `editsToSave`) to stop that action creating - // a new record and instead cause it to update the existing record. - if (recordId) { - editsToSave[entityIdKey] = recordId; - } - return await dispatch.saveEntityRecord(kind, name, editsToSave, options); -}; - -/** - * Returns an action object used in signalling that Upload permissions have been received. - * - * @deprecated since WP 5.9, use receiveUserPermission instead. - * - * @param {boolean} hasUploadPermissions Does the user have permission to upload files? - * - * @return {Object} Action object. - */ -function receiveUploadPermissions(hasUploadPermissions) { - external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveUploadPermissions", { - since: '5.9', - alternative: 'receiveUserPermission' - }); - return receiveUserPermission('create/media', hasUploadPermissions); -} - -/** - * Returns an action object used in signalling that the current user has - * permission to perform an action on a REST resource. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {string} key A key that represents the action and REST resource. - * @param {boolean} isAllowed Whether or not the user can perform the action. - * - * @return {Object} Action object. - */ -function receiveUserPermission(key, isAllowed) { - return { - type: 'RECEIVE_USER_PERMISSION', - key, - isAllowed - }; -} - -/** - * Returns an action object used in signalling that the autosaves for a - * post have been received. - * Ignored from documentation as it's internal to the data store. - * - * @ignore - * - * @param {number} postId The id of the post that is parent to the autosave. - * @param {Array|Object} autosaves An array of autosaves or singular autosave object. - * - * @return {Object} Action object. - */ -function receiveAutosaves(postId, autosaves) { - return { - type: 'RECEIVE_AUTOSAVES', - postId, - autosaves: Array.isArray(autosaves) ? autosaves : [autosaves] - }; -} - -/** - * Returns an action object signalling that the fallback Navigation - * Menu id has been received. - * - * @param {integer} fallbackId the id of the fallback Navigation Menu - * @return {Object} Action object. - */ -function receiveNavigationFallbackId(fallbackId) { - return { - type: 'RECEIVE_NAVIGATION_FALLBACK_ID', - fallbackId - }; -} - -/** - * Returns an action object used to set the template for a given query. - * - * @param {Object} query The lookup query. - * @param {string} templateId The resolved template id. - * - * @return {Object} Action object. - */ -function receiveDefaultTemplateId(query, templateId) { - return { - type: 'RECEIVE_DEFAULT_TEMPLATE', - query, - templateId - }; -} - -/** - * Action triggered to receive revision items. - * - * @param {string} kind Kind of the received entity record revisions. - * @param {string} name Name of the received entity record revisions. - * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch. - * @param {Array|Object} records Revisions received. - * @param {?Object} query Query Object. - * @param {?boolean} invalidateCache Should invalidate query caches. - * @param {?Object} meta Meta information about pagination. - */ -const receiveRevisions = (kind, name, recordKey, records, query, invalidateCache = false, meta) => async ({ - dispatch -}) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.kind === kind && config.name === name); - const key = entityConfig && entityConfig?.revisionKey ? entityConfig.revisionKey : DEFAULT_ENTITY_KEY; - dispatch({ - type: 'RECEIVE_ITEM_REVISIONS', - key, - items: Array.isArray(records) ? records : [records], - recordKey, - meta, - query, - kind, - name, - invalidateCache - }); -}; - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/entities.js +;// ./node_modules/@wordpress/core-data/build-module/entities.js /** * External dependencies */ @@ -2727,12 +1467,6 @@ - -/** - * Internal dependencies - */ - - const DEFAULT_ENTITY_KEY = 'id'; const POST_RAW_ATTRIBUTES = ['title', 'excerpt', 'content']; const rootEntitiesConfig = [{ @@ -2741,7 +1475,9 @@ name: '__unstableBase', baseURL: '/', baseURLParams: { - _fields: ['description', 'gmt_offset', 'home', 'name', 'site_icon', 'site_icon_url', 'site_logo', 'timezone_string', 'url'].join(',') + // Please also change the preload path when changing this. + // @see lib/compat/wordpress-6.8/preload.php + _fields: ['description', 'gmt_offset', 'home', 'name', 'site_icon', 'site_icon_url', 'site_logo', 'timezone_string', 'url', 'page_for_posts', 'page_on_front', 'show_on_front'].join(',') }, // The entity doesn't support selecting multiple records. // The property is maintained for backward compatibility. @@ -3173,59 +1909,10 @@ const suffix = pascalCase(name); return `${prefix}${kindPrefix}${suffix}`; }; -function registerSyncConfigs(configs) { - configs.forEach(({ - syncObjectType, - syncConfig - }) => { - getSyncProvider().register(syncObjectType, syncConfig); - const editSyncConfig = { - ...syncConfig - }; - delete editSyncConfig.fetch; - getSyncProvider().register(syncObjectType + '--edit', editSyncConfig); - }); -} - -/** - * Loads the entities into the store. - * - * Note: The `name` argument is used for `root` entities requiring additional server data. - * - * @param {string} kind Kind - * @param {string} name Name - * @return {(thunkArgs: object) => Promise} Entities - */ -const getOrLoadEntitiesConfig = (kind, name) => async ({ - select, - dispatch -}) => { - let configs = select.getEntitiesConfig(kind); - const hasConfig = !!select.getEntityConfig(kind, name); - if (configs?.length > 0 && hasConfig) { - if (window.__experimentalEnableSync) { - if (false) {} - } - return configs; - } - const loader = additionalEntityConfigLoaders.find(l => { - if (!name || !l.name) { - return l.kind === kind; - } - return l.kind === kind && l.name === name; - }); - if (!loader) { - return []; - } - configs = await loader.loadEntities(); - if (window.__experimentalEnableSync) { - if (false) {} - } - dispatch(addEntities(configs)); - return configs; -}; - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/get-normalized-comma-separable.js + +;// external ["wp","url"] +const external_wp_url_namespaceObject = window["wp"]["url"]; +;// ./node_modules/@wordpress/core-data/build-module/utils/get-normalized-comma-separable.js /** * Given a value which can be specified as one or the other of a comma-separated * string or an array, returns a value normalized to an array of strings, or @@ -3245,7 +1932,7 @@ } /* harmony default export */ const get_normalized_comma_separable = (getNormalizedCommaSeparable); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/with-weak-map-cache.js +;// ./node_modules/@wordpress/core-data/build-module/utils/with-weak-map-cache.js /** * Given a function, returns an enhanced function which caches the result and * tracks in WeakMap. The result is only cached if the original function is @@ -3276,7 +1963,7 @@ } /* harmony default export */ const with_weak_map_cache = (withWeakMapCache); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/get-query-parts.js +;// ./node_modules/@wordpress/core-data/build-module/queried-data/get-query-parts.js /** * WordPress dependencies */ @@ -3380,7 +2067,7 @@ } /* harmony default export */ const get_query_parts = (with_weak_map_cache(getQueryParts)); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/reducer.js +;// ./node_modules/@wordpress/core-data/build-module/queried-data/reducer.js /** * WordPress dependencies */ @@ -3616,7 +2303,7 @@ queries })); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/reducer.js +;// ./node_modules/@wordpress/core-data/build-module/reducer.js /** * External dependencies */ @@ -4025,7 +2712,7 @@ /** * @type {UndoManager} */ -function undoManager(state = (0,build_module.createUndoManager)()) { +function undoManager(state = createUndoManager()) { return state; } function editsReference(state = {}, action) { @@ -4077,6 +2764,11 @@ ...state, [action.key]: action.isAllowed }; + case 'RECEIVE_USER_PERMISSIONS': + return { + ...state, + ...action.permissions + }; } return state; } @@ -4169,6 +2861,25 @@ } return state; } + +/** + * Reducer returning an object of registered post meta. + * + * @param {Object} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +function registeredPostMeta(state = {}, action) { + switch (action.type) { + case 'RECEIVE_REGISTERED_POST_META': + return { + ...state, + [action.postType]: action.registeredPostMeta + }; + } + return state; +} /* harmony default export */ const build_module_reducer = ((0,external_wp_data_namespaceObject.combineReducers)({ terms, users, @@ -4189,13 +2900,70 @@ blockPatternCategories, userPatternCategories, navigationFallbackId, - defaultTemplates + defaultTemplates, + registeredPostMeta })); +;// external ["wp","deprecated"] +const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"]; +var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject); +;// ./node_modules/@wordpress/core-data/build-module/name.js +/** + * The reducer key used by core data in store registration. + * This is defined in a separate file to avoid cycle-dependency + * + * @type {string} + */ +const STORE_NAME = 'core'; + // EXTERNAL MODULE: ./node_modules/equivalent-key-map/equivalent-key-map.js var equivalent_key_map = __webpack_require__(3249); var equivalent_key_map_default = /*#__PURE__*/__webpack_require__.n(equivalent_key_map); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/selectors.js +;// ./node_modules/@wordpress/core-data/build-module/utils/set-nested-value.js +/** + * Sets the value at path of object. + * If a portion of path doesn’t exist, it’s created. + * Arrays are created for missing index properties while objects are created + * for all other missing properties. + * + * Path is specified as either: + * - a string of properties, separated by dots, for example: "x.y". + * - an array of properties, for example `[ 'x', 'y' ]`. + * + * This function intentionally mutates the input object. + * + * Inspired by _.set(). + * + * @see https://lodash.com/docs/4.17.15#set + * + * @todo Needs to be deduplicated with its copy in `@wordpress/edit-site`. + * + * @param {Object} object Object to modify + * @param {Array|string} path Path of the property to set. + * @param {*} value Value to set. + */ +function setNestedValue(object, path, value) { + if (!object || typeof object !== 'object') { + return object; + } + const normalizedPath = Array.isArray(path) ? path : path.split('.'); + normalizedPath.reduce((acc, key, idx) => { + if (acc[key] === undefined) { + if (Number.isInteger(normalizedPath[idx + 1])) { + acc[key] = []; + } else { + acc[key] = {}; + } + } + if (idx === normalizedPath.length - 1) { + acc[key] = value; + } + return acc[key]; + }, object); + return object; +} + +;// ./node_modules/@wordpress/core-data/build-module/queried-data/selectors.js /** * External dependencies */ @@ -4330,7 +3098,7 @@ return (_state$queries$contex2 = state.queries?.[context]?.[stableKey]?.meta?.totalPages) !== null && _state$queries$contex2 !== void 0 ? _state$queries$contex2 : null; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/is-numeric-id.js +;// ./node_modules/@wordpress/core-data/build-module/utils/is-numeric-id.js /** * Checks argument to determine if it's a numeric ID. * For example, '123' is a numeric ID, but '123abc' is not. @@ -4342,7 +3110,7 @@ return /^\s*\d+\s*$/.test(id); } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/is-raw-attribute.js +;// ./node_modules/@wordpress/core-data/build-module/utils/is-raw-attribute.js /** * Checks whether the attribute is a "raw" attribute or not. * @@ -4355,7 +3123,30 @@ return (entity.rawAttributes || []).includes(attribute); } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/selectors.js +;// ./node_modules/@wordpress/core-data/build-module/utils/user-permissions.js +const ALLOWED_RESOURCE_ACTIONS = ['create', 'read', 'update', 'delete']; +function getUserPermissionsFromAllowHeader(allowedMethods) { + const permissions = {}; + if (!allowedMethods) { + return permissions; + } + const methods = { + create: 'POST', + read: 'GET', + update: 'PUT', + delete: 'DELETE' + }; + for (const [actionName, methodName] of Object.entries(methods)) { + permissions[actionName] = allowedMethods.includes(methodName); + } + return permissions; +} +function getUserPermissionCacheKey(action, resource, id) { + const key = (typeof resource === 'object' ? [action, resource.kind, resource.name, resource.id] : [action, resource, id]).filter(Boolean).join('/'); + return key; +} + +;// ./node_modules/@wordpress/core-data/build-module/selectors.js /** * WordPress dependencies */ @@ -4475,7 +3266,9 @@ * * @return Array of entities with config matching kind. */ -const getEntitiesConfig = (0,external_wp_data_namespaceObject.createSelector)((state, kind) => state.entities.config.filter(entity => entity.kind === kind), (state, kind) => state.entities.config); +const getEntitiesConfig = (0,external_wp_data_namespaceObject.createSelector)((state, kind) => state.entities.config.filter(entity => entity.kind === kind), /* eslint-disable @typescript-eslint/no-unused-vars */ +(state, kind) => state.entities.config +/* eslint-enable @typescript-eslint/no-unused-vars */); /** * Returns the entity config given its kind and name. * @@ -4540,7 +3333,7 @@ * @param state State tree * @param kind Entity kind. * @param name Entity name. - * @param key Record's key + * @param key Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. * @param query Optional query. If requesting specific * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". * @@ -4626,11 +3419,10 @@ const record = getEntityRecord(state, kind, name, key); return record && Object.keys(record).reduce((accumulator, _key) => { if (isRawAttribute(getEntityConfig(state, kind, name), _key)) { - var _record$_key$raw; // Because edits are the "raw" attribute values, // we return those from record selectors to make rendering, // comparisons, and joins with edits easier. - accumulator[_key] = (_record$_key$raw = record[_key]?.raw) !== null && _record$_key$raw !== void 0 ? _record$_key$raw : record[_key]; + accumulator[_key] = record[_key]?.raw !== undefined ? record[_key]?.raw : record[_key]; } else { accumulator[_key] = record[_key]; } @@ -4981,6 +3773,7 @@ return state.entities.records?.[kind]?.[name]?.deleting?.[recordId]?.error; } +/* eslint-disable @typescript-eslint/no-unused-vars */ /** * Returns the previous edit from the current undo offset * for the entity records edits history, if any. @@ -4997,7 +3790,9 @@ }); return undefined; } - +/* eslint-enable @typescript-eslint/no-unused-vars */ + +/* eslint-disable @typescript-eslint/no-unused-vars */ /** * Returns the next edit from the current undo offset * for the entity records edits history, if any. @@ -5014,6 +3809,7 @@ }); return undefined; } +/* eslint-enable @typescript-eslint/no-unused-vars */ /** * Returns true if there is a previous edit from the current undo offset @@ -5120,14 +3916,19 @@ * * @param state Data state. * @param action Action to check. One of: 'create', 'read', 'update', 'delete'. - * @param resource REST resource to check, e.g. 'media' or 'posts'. + * @param resource Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` + * or REST base as a string - `media`. * @param id Optional ID of the rest resource to check. * * @return Whether or not the user can perform the action, * or `undefined` if the OPTIONS request is still being made. */ function canUser(state, action, resource, id) { - const key = [action, resource, id].filter(Boolean).join('/'); + const isEntity = typeof resource === 'object'; + if (isEntity && (!resource.kind || !resource.name)) { + return false; + } + const key = getUserPermissionCacheKey(action, resource, id); return state.userPermissions[key]; } @@ -5147,12 +3948,15 @@ * or `undefined` if the OPTIONS request is still being made. */ function canUserEditEntityRecord(state, kind, name, recordId) { - const entityConfig = getEntityConfig(state, kind, name); - if (!entityConfig) { - return false; - } - const resource = entityConfig.__unstable_rest_base; - return canUser(state, 'update', resource, recordId); + external_wp_deprecated_default()(`wp.data.select( 'core' ).canUserEditEntityRecord()`, { + since: '6.7', + alternative: `wp.data.select( 'core' ).canUser( 'update', { kind, name, id } )` + }); + return canUser(state, 'update', { + kind, + name, + id: recordId + }); } /** @@ -5225,24 +4029,6 @@ } /** - * Retrieve the frontend template used for a given link. - * - * @param state Editor state. - * @param link Link. - * - * @return The template record. - */ -function __experimentalGetTemplateForLink(state, link) { - const records = getEntityRecords(state, 'postType', 'wp_template', { - 'find-template': link - }); - if (records?.length) { - return getEditedEntityRecord(state, 'postType', 'wp_template', records[0].id); - } - return null; -} - -/** * Retrieve the current theme's base global styles * * @param state Editor state. @@ -5408,7 +4194,19 @@ return [state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]?.items?.[context]?.[revisionKey], state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]?.itemIsComplete?.[context]?.[revisionKey]]; }); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/private-selectors.js +;// external ["wp","privateApis"] +const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"]; +;// ./node_modules/@wordpress/core-data/build-module/lock-unlock.js +/** + * WordPress dependencies + */ + +const { + lock, + unlock +} = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/core-data'); + +;// ./node_modules/@wordpress/core-data/build-module/private-selectors.js /** * WordPress dependencies */ @@ -5419,6 +4217,7 @@ */ + /** * Returns the previous edit from the current undo offset * for the entity records edits history, if any. @@ -5444,7 +4243,1430 @@ postTypes }) => !postTypes || Array.isArray(postTypes) && postTypes.includes(postType)), () => [select(STORE_NAME).getBlockPatterns()])); -;// CONCATENATED MODULE: ./node_modules/camel-case/dist.es2015/index.js +/** + * Returns the entity records permissions for the given entity record ids. + */ +const getEntityRecordsPermissions = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, ids) => { + const normalizedIds = Array.isArray(ids) ? ids : [ids]; + return normalizedIds.map(id => ({ + delete: select(STORE_NAME).canUser('delete', { + kind, + name, + id + }), + update: select(STORE_NAME).canUser('update', { + kind, + name, + id + }) + })); +}, state => [state.userPermissions])); + +/** + * Returns the entity record permissions for the given entity record id. + * + * @param state Data state. + * @param kind Entity kind. + * @param name Entity name. + * @param id Entity record id. + * + * @return The entity record permissions. + */ +function getEntityRecordPermissions(state, kind, name, id) { + return getEntityRecordsPermissions(state, kind, name, id)[0]; +} + +/** + * Returns the registered post meta fields for a given post type. + * + * @param state Data state. + * @param postType Post type. + * + * @return Registered post meta fields. + */ +function getRegisteredPostMeta(state, postType) { + var _state$registeredPost; + return (_state$registeredPost = state.registeredPostMeta?.[postType]) !== null && _state$registeredPost !== void 0 ? _state$registeredPost : {}; +} +function normalizePageId(value) { + if (!value || !['number', 'string'].includes(typeof value)) { + return null; + } + + // We also need to check if it's not zero (`'0'`). + if (Number(value) === 0) { + return null; + } + return value.toString(); +} +const getHomePage = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)(() => { + const siteData = select(STORE_NAME).getEntityRecord('root', '__unstableBase'); + if (!siteData) { + return null; + } + const homepageId = siteData?.show_on_front === 'page' ? normalizePageId(siteData.page_on_front) : null; + if (homepageId) { + return { + postType: 'page', + postId: homepageId + }; + } + const frontPageTemplateId = select(STORE_NAME).getDefaultTemplateId({ + slug: 'front-page' + }); + return { + postType: 'wp_template', + postId: frontPageTemplateId + }; +}, state => [getEntityRecord(state, 'root', '__unstableBase'), getDefaultTemplateId(state, { + slug: 'front-page' +})])); +const getPostsPageId = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => () => { + const siteData = select(STORE_NAME).getEntityRecord('root', '__unstableBase'); + return siteData?.show_on_front === 'page' ? normalizePageId(siteData.page_for_posts) : null; +}); +const getTemplateId = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, postType, postId) => { + const homepage = unlock(select(STORE_NAME)).getHomePage(); + if (!homepage) { + return; + } + + // For the front page, we always use the front page template if existing. + if (postType === 'page' && postType === homepage?.postType && postId.toString() === homepage?.postId) { + // The /lookup endpoint cannot currently handle a lookup + // when a page is set as the front page, so specifically in + // that case, we want to check if there is a front page + // template, and instead of falling back to the home + // template, we want to fall back to the page template. + const templates = select(STORE_NAME).getEntityRecords('postType', 'wp_template', { + per_page: -1 + }); + if (!templates) { + return; + } + const id = templates.find(({ + slug + }) => slug === 'front-page')?.id; + if (id) { + return id; + } + // If no front page template is found, continue with the + // logic below (fetching the page template). + } + const editedEntity = select(STORE_NAME).getEditedEntityRecord('postType', postType, postId); + if (!editedEntity) { + return; + } + const postsPageId = unlock(select(STORE_NAME)).getPostsPageId(); + // Check if the current page is the posts page. + if (postType === 'page' && postsPageId === postId.toString()) { + return select(STORE_NAME).getDefaultTemplateId({ + slug: 'home' + }); + } + // First see if the post/page has an assigned template and fetch it. + const currentTemplateSlug = editedEntity.template; + if (currentTemplateSlug) { + const currentTemplate = select(STORE_NAME).getEntityRecords('postType', 'wp_template', { + per_page: -1 + })?.find(({ + slug + }) => slug === currentTemplateSlug); + if (currentTemplate) { + return currentTemplate.id; + } + } + // If no template is assigned, use the default template. + let slugToCheck; + // In `draft` status we might not have a slug available, so we use the `single` + // post type templates slug(ex page, single-post, single-product etc..). + // Pages do not need the `single` prefix in the slug to be prioritized + // through template hierarchy. + if (editedEntity.slug) { + slugToCheck = postType === 'page' ? `${postType}-${editedEntity.slug}` : `single-${postType}-${editedEntity.slug}`; + } else { + slugToCheck = postType === 'page' ? 'page' : `single-${postType}`; + } + return select(STORE_NAME).getDefaultTemplateId({ + slug: slugToCheck + }); +}); + +;// ./node_modules/@wordpress/core-data/node_modules/uuid/dist/esm-browser/native.js +const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); +/* harmony default export */ const esm_browser_native = ({ + randomUUID +}); +;// ./node_modules/@wordpress/core-data/node_modules/uuid/dist/esm-browser/rng.js +// Unique ID creation requires a high quality random # generator. In the browser we therefore +// require the crypto API and do not support built-in fallback to lower quality random number +// generators (like Math.random()). +let getRandomValues; +const rnds8 = new Uint8Array(16); +function rng() { + // lazy load so that environments that need to polyfill have a chance to do so + if (!getRandomValues) { + // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. + getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); + + if (!getRandomValues) { + throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); + } + } + + return getRandomValues(rnds8); +} +;// ./node_modules/@wordpress/core-data/node_modules/uuid/dist/esm-browser/stringify.js + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ + +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).slice(1)); +} + +function unsafeStringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; +} + +function stringify(arr, offset = 0) { + const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!validate(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +/* harmony default export */ const esm_browser_stringify = ((/* unused pure expression or super */ null && (stringify))); +;// ./node_modules/@wordpress/core-data/node_modules/uuid/dist/esm-browser/v4.js + + + + +function v4(options, buf, offset) { + if (esm_browser_native.randomUUID && !buf && !options) { + return esm_browser_native.randomUUID(); + } + + options = options || {}; + const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return unsafeStringify(rnds); +} + +/* harmony default export */ const esm_browser_v4 = (v4); +;// ./node_modules/@wordpress/core-data/build-module/utils/get-nested-value.js +/** + * Helper util to return a value from a certain path of the object. + * Path is specified as either: + * - a string of properties, separated by dots, for example: "x.y". + * - an array of properties, for example `[ 'x', 'y' ]`. + * You can also specify a default value in case the result is nullish. + * + * @param {Object} object Input object. + * @param {string|Array} path Path to the object property. + * @param {*} defaultValue Default value if the value at the specified path is undefined. + * @return {*} Value of the object property at the specified path. + */ +function getNestedValue(object, path, defaultValue) { + if (!object || typeof object !== 'object' || typeof path !== 'string' && !Array.isArray(path)) { + return object; + } + const normalizedPath = Array.isArray(path) ? path : path.split('.'); + let value = object; + normalizedPath.forEach(fieldName => { + value = value?.[fieldName]; + }); + return value !== undefined ? value : defaultValue; +} + +;// ./node_modules/@wordpress/core-data/build-module/queried-data/actions.js +/** + * Returns an action object used in signalling that items have been received. + * + * @param {Array} items Items received. + * @param {?Object} edits Optional edits to reset. + * @param {?Object} meta Meta information about pagination. + * + * @return {Object} Action object. + */ +function receiveItems(items, edits, meta) { + return { + type: 'RECEIVE_ITEMS', + items: Array.isArray(items) ? items : [items], + persistedEdits: edits, + meta + }; +} + +/** + * Returns an action object used in signalling that entity records have been + * deleted and they need to be removed from entities state. + * + * @param {string} kind Kind of the removed entities. + * @param {string} name Name of the removed entities. + * @param {Array|number|string} records Record IDs of the removed entities. + * @param {boolean} invalidateCache Controls whether we want to invalidate the cache. + * @return {Object} Action object. + */ +function removeItems(kind, name, records, invalidateCache = false) { + return { + type: 'REMOVE_ITEMS', + itemIds: Array.isArray(records) ? records : [records], + kind, + name, + invalidateCache + }; +} + +/** + * Returns an action object used in signalling that queried data has been + * received. + * + * @param {Array} items Queried items received. + * @param {?Object} query Optional query object. + * @param {?Object} edits Optional edits to reset. + * @param {?Object} meta Meta information about pagination. + * + * @return {Object} Action object. + */ +function receiveQueriedItems(items, query = {}, edits, meta) { + return { + ...receiveItems(items, edits, meta), + query + }; +} + +;// ./node_modules/@wordpress/core-data/build-module/batch/default-processor.js +/** + * WordPress dependencies + */ + + +/** + * Maximum number of requests to place in a single batch request. Obtained by + * sending a preflight OPTIONS request to /batch/v1/. + * + * @type {number?} + */ +let maxItems = null; +function chunk(arr, chunkSize) { + const tmp = [...arr]; + const cache = []; + while (tmp.length) { + cache.push(tmp.splice(0, chunkSize)); + } + return cache; +} + +/** + * Default batch processor. Sends its input requests to /batch/v1. + * + * @param {Array} requests List of API requests to perform at once. + * + * @return {Promise} Promise that resolves to a list of objects containing + * either `output` (if that request was successful) or `error` + * (if not ). + */ +async function defaultProcessor(requests) { + if (maxItems === null) { + const preflightResponse = await external_wp_apiFetch_default()({ + path: '/batch/v1', + method: 'OPTIONS' + }); + maxItems = preflightResponse.endpoints[0].args.requests.maxItems; + } + const results = []; + + // @ts-ignore We would have crashed or never gotten to this point if we hadn't received the maxItems count. + for (const batchRequests of chunk(requests, maxItems)) { + const batchResponse = await external_wp_apiFetch_default()({ + path: '/batch/v1', + method: 'POST', + data: { + validation: 'require-all-validate', + requests: batchRequests.map(request => ({ + path: request.path, + body: request.data, + // Rename 'data' to 'body'. + method: request.method, + headers: request.headers + })) + } + }); + let batchResults; + if (batchResponse.failed) { + batchResults = batchResponse.responses.map(response => ({ + error: response?.body + })); + } else { + batchResults = batchResponse.responses.map(response => { + const result = {}; + if (response.status >= 200 && response.status < 300) { + result.output = response.body; + } else { + result.error = response.body; + } + return result; + }); + } + results.push(...batchResults); + } + return results; +} + +;// ./node_modules/@wordpress/core-data/build-module/batch/create-batch.js +/** + * Internal dependencies + */ + + +/** + * Creates a batch, which can be used to combine multiple API requests into one + * API request using the WordPress batch processing API (/v1/batch). + * + * ``` + * const batch = createBatch(); + * const dunePromise = batch.add( { + * path: '/v1/books', + * method: 'POST', + * data: { title: 'Dune' } + * } ); + * const lotrPromise = batch.add( { + * path: '/v1/books', + * method: 'POST', + * data: { title: 'Lord of the Rings' } + * } ); + * const isSuccess = await batch.run(); // Sends one POST to /v1/batch. + * if ( isSuccess ) { + * console.log( + * 'Saved two books:', + * await dunePromise, + * await lotrPromise + * ); + * } + * ``` + * + * @param {Function} [processor] Processor function. Can be used to replace the + * default functionality which is to send an API + * request to /v1/batch. Is given an array of + * inputs and must return a promise that + * resolves to an array of objects containing + * either `output` or `error`. + */ +function createBatch(processor = defaultProcessor) { + let lastId = 0; + /** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */ + let queue = []; + const pending = new ObservableSet(); + return { + /** + * Adds an input to the batch and returns a promise that is resolved or + * rejected when the input is processed by `batch.run()`. + * + * You may also pass a thunk which allows inputs to be added + * asynchronously. + * + * ``` + * // Both are allowed: + * batch.add( { path: '/v1/books', ... } ); + * batch.add( ( add ) => add( { path: '/v1/books', ... } ) ); + * ``` + * + * If a thunk is passed, `batch.run()` will pause until either: + * + * - The thunk calls its `add` argument, or; + * - The thunk returns a promise and that promise resolves, or; + * - The thunk returns a non-promise. + * + * @param {any|Function} inputOrThunk Input to add or thunk to execute. + * + * @return {Promise|any} If given an input, returns a promise that + * is resolved or rejected when the batch is + * processed. If given a thunk, returns the return + * value of that thunk. + */ + add(inputOrThunk) { + const id = ++lastId; + pending.add(id); + const add = input => new Promise((resolve, reject) => { + queue.push({ + input, + resolve, + reject + }); + pending.delete(id); + }); + if (typeof inputOrThunk === 'function') { + return Promise.resolve(inputOrThunk(add)).finally(() => { + pending.delete(id); + }); + } + return add(inputOrThunk); + }, + /** + * Runs the batch. This calls `batchProcessor` and resolves or rejects + * all promises returned by `add()`. + * + * @return {Promise} A promise that resolves to a boolean that is true + * if the processor returned no errors. + */ + async run() { + if (pending.size) { + await new Promise(resolve => { + const unsubscribe = pending.subscribe(() => { + if (!pending.size) { + unsubscribe(); + resolve(undefined); + } + }); + }); + } + let results; + try { + results = await processor(queue.map(({ + input + }) => input)); + if (results.length !== queue.length) { + throw new Error('run: Array returned by processor must be same size as input array.'); + } + } catch (error) { + for (const { + reject + } of queue) { + reject(error); + } + throw error; + } + let isSuccess = true; + results.forEach((result, key) => { + const queueItem = queue[key]; + if (result?.error) { + queueItem?.reject(result.error); + isSuccess = false; + } else { + var _result$output; + queueItem?.resolve((_result$output = result?.output) !== null && _result$output !== void 0 ? _result$output : result); + } + }); + queue = []; + return isSuccess; + } + }; +} +class ObservableSet { + constructor(...args) { + this.set = new Set(...args); + this.subscribers = new Set(); + } + get size() { + return this.set.size; + } + add(value) { + this.set.add(value); + this.subscribers.forEach(subscriber => subscriber()); + return this; + } + delete(value) { + const isSuccess = this.set.delete(value); + this.subscribers.forEach(subscriber => subscriber()); + return isSuccess; + } + subscribe(subscriber) { + this.subscribers.add(subscriber); + return () => { + this.subscribers.delete(subscriber); + }; + } +} + +;// ./node_modules/@wordpress/core-data/build-module/actions.js +/** + * External dependencies + */ + + + +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + + + + + + +/** + * Returns an action object used in signalling that authors have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} queryID Query ID. + * @param {Array|Object} users Users received. + * + * @return {Object} Action object. + */ +function receiveUserQuery(queryID, users) { + return { + type: 'RECEIVE_USER_QUERY', + users: Array.isArray(users) ? users : [users], + queryID + }; +} + +/** + * Returns an action used in signalling that the current user has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {Object} currentUser Current user object. + * + * @return {Object} Action object. + */ +function receiveCurrentUser(currentUser) { + return { + type: 'RECEIVE_CURRENT_USER', + currentUser + }; +} + +/** + * Returns an action object used in adding new entities. + * + * @param {Array} entities Entities received. + * + * @return {Object} Action object. + */ +function addEntities(entities) { + return { + type: 'ADD_ENTITIES', + entities + }; +} + +/** + * Returns an action object used in signalling that entity records have been received. + * + * @param {string} kind Kind of the received entity record. + * @param {string} name Name of the received entity record. + * @param {Array|Object} records Records received. + * @param {?Object} query Query Object. + * @param {?boolean} invalidateCache Should invalidate query caches. + * @param {?Object} edits Edits to reset. + * @param {?Object} meta Meta information about pagination. + * @return {Object} Action object. + */ +function receiveEntityRecords(kind, name, records, query, invalidateCache = false, edits, meta) { + // Auto drafts should not have titles, but some plugins rely on them so we can't filter this + // on the server. + if (kind === 'postType') { + records = (Array.isArray(records) ? records : [records]).map(record => record.status === 'auto-draft' ? { + ...record, + title: '' + } : record); + } + let action; + if (query) { + action = receiveQueriedItems(records, query, edits, meta); + } else { + action = receiveItems(records, edits, meta); + } + return { + ...action, + kind, + name, + invalidateCache + }; +} + +/** + * Returns an action object used in signalling that the current theme has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {Object} currentTheme The current theme. + * + * @return {Object} Action object. + */ +function receiveCurrentTheme(currentTheme) { + return { + type: 'RECEIVE_CURRENT_THEME', + currentTheme + }; +} + +/** + * Returns an action object used in signalling that the current global styles id has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} currentGlobalStylesId The current global styles id. + * + * @return {Object} Action object. + */ +function __experimentalReceiveCurrentGlobalStylesId(currentGlobalStylesId) { + return { + type: 'RECEIVE_CURRENT_GLOBAL_STYLES_ID', + id: currentGlobalStylesId + }; +} + +/** + * Returns an action object used in signalling that the theme base global styles have been received + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} stylesheet The theme's identifier + * @param {Object} globalStyles The global styles object. + * + * @return {Object} Action object. + */ +function __experimentalReceiveThemeBaseGlobalStyles(stylesheet, globalStyles) { + return { + type: 'RECEIVE_THEME_GLOBAL_STYLES', + stylesheet, + globalStyles + }; +} + +/** + * Returns an action object used in signalling that the theme global styles variations have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} stylesheet The theme's identifier + * @param {Array} variations The global styles variations. + * + * @return {Object} Action object. + */ +function __experimentalReceiveThemeGlobalStyleVariations(stylesheet, variations) { + return { + type: 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS', + stylesheet, + variations + }; +} + +/** + * Returns an action object used in signalling that the index has been received. + * + * @deprecated since WP 5.9, this is not useful anymore, use the selector directly. + * + * @return {Object} Action object. + */ +function receiveThemeSupports() { + external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeSupports", { + since: '5.9' + }); + return { + type: 'DO_NOTHING' + }; +} + +/** + * Returns an action object used in signalling that the theme global styles CPT post revisions have been received. + * Ignored from documentation as it's internal to the data store. + * + * @deprecated since WordPress 6.5.0. Callers should use `dispatch( 'core' ).receiveRevision` instead. + * + * @ignore + * + * @param {number} currentId The post id. + * @param {Array} revisions The global styles revisions. + * + * @return {Object} Action object. + */ +function receiveThemeGlobalStyleRevisions(currentId, revisions) { + external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeGlobalStyleRevisions()", { + since: '6.5.0', + alternative: "wp.data.dispatch( 'core' ).receiveRevisions" + }); + return { + type: 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS', + currentId, + revisions + }; +} + +/** + * Returns an action object used in signalling that the preview data for + * a given URl has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} url URL to preview the embed for. + * @param {*} preview Preview data. + * + * @return {Object} Action object. + */ +function receiveEmbedPreview(url, preview) { + return { + type: 'RECEIVE_EMBED_PREVIEW', + url, + preview + }; +} + +/** + * Action triggered to delete an entity record. + * + * @param {string} kind Kind of the deleted entity. + * @param {string} name Name of the deleted entity. + * @param {number|string} recordId Record ID of the deleted entity. + * @param {?Object} query Special query parameters for the + * DELETE API call. + * @param {Object} [options] Delete options. + * @param {Function} [options.__unstableFetch] Internal use only. Function to + * call instead of `apiFetch()`. + * Must return a promise. + * @param {boolean} [options.throwOnError=false] If false, this action suppresses all + * the exceptions. Defaults to false. + */ +const deleteEntityRecord = (kind, name, recordId, query, { + __unstableFetch = (external_wp_apiFetch_default()), + throwOnError = false +} = {}) => async ({ + dispatch, + resolveSelect +}) => { + const configs = await resolveSelect.getEntitiesConfig(kind); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + let error; + let deletedRecord = false; + if (!entityConfig) { + return; + } + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId], { + exclusive: true + }); + try { + dispatch({ + type: 'DELETE_ENTITY_RECORD_START', + kind, + name, + recordId + }); + let hasError = false; + try { + let path = `${entityConfig.baseURL}/${recordId}`; + if (query) { + path = (0,external_wp_url_namespaceObject.addQueryArgs)(path, query); + } + deletedRecord = await __unstableFetch({ + path, + method: 'DELETE' + }); + await dispatch(removeItems(kind, name, recordId, true)); + } catch (_error) { + hasError = true; + error = _error; + } + dispatch({ + type: 'DELETE_ENTITY_RECORD_FINISH', + kind, + name, + recordId, + error + }); + if (hasError && throwOnError) { + throw error; + } + return deletedRecord; + } finally { + dispatch.__unstableReleaseStoreLock(lock); + } +}; + +/** + * Returns an action object that triggers an + * edit to an entity record. + * + * @param {string} kind Kind of the edited entity record. + * @param {string} name Name of the edited entity record. + * @param {number|string} recordId Record ID of the edited entity record. + * @param {Object} edits The edits. + * @param {Object} options Options for the edit. + * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. + * + * @return {Object} Action object. + */ +const editEntityRecord = (kind, name, recordId, edits, options = {}) => ({ + select, + dispatch +}) => { + const entityConfig = select.getEntityConfig(kind, name); + if (!entityConfig) { + throw new Error(`The entity being edited (${kind}, ${name}) does not have a loaded config.`); + } + const { + mergedEdits = {} + } = entityConfig; + const record = select.getRawEntityRecord(kind, name, recordId); + const editedRecord = select.getEditedEntityRecord(kind, name, recordId); + const edit = { + kind, + name, + recordId, + // Clear edits when they are equal to their persisted counterparts + // so that the property is not considered dirty. + edits: Object.keys(edits).reduce((acc, key) => { + const recordValue = record[key]; + const editedRecordValue = editedRecord[key]; + const value = mergedEdits[key] ? { + ...editedRecordValue, + ...edits[key] + } : edits[key]; + acc[key] = es6_default()(recordValue, value) ? undefined : value; + return acc; + }, {}) + }; + if (window.__experimentalEnableSync && entityConfig.syncConfig) { + if (false) {} + } else { + if (!options.undoIgnore) { + select.getUndoManager().addRecord([{ + id: { + kind, + name, + recordId + }, + changes: Object.keys(edits).reduce((acc, key) => { + acc[key] = { + from: editedRecord[key], + to: edits[key] + }; + return acc; + }, {}) + }], options.isCached); + } + dispatch({ + type: 'EDIT_ENTITY_RECORD', + ...edit + }); + } +}; + +/** + * Action triggered to undo the last edit to + * an entity record, if any. + */ +const undo = () => ({ + select, + dispatch +}) => { + const undoRecord = select.getUndoManager().undo(); + if (!undoRecord) { + return; + } + dispatch({ + type: 'UNDO', + record: undoRecord + }); +}; + +/** + * Action triggered to redo the last undone + * edit to an entity record, if any. + */ +const redo = () => ({ + select, + dispatch +}) => { + const redoRecord = select.getUndoManager().redo(); + if (!redoRecord) { + return; + } + dispatch({ + type: 'REDO', + record: redoRecord + }); +}; + +/** + * Forces the creation of a new undo level. + * + * @return {Object} Action object. + */ +const __unstableCreateUndoLevel = () => ({ + select +}) => { + select.getUndoManager().addRecord(); +}; + +/** + * Action triggered to save an entity record. + * + * @param {string} kind Kind of the received entity. + * @param {string} name Name of the received entity. + * @param {Object} record Record to be saved. + * @param {Object} options Saving options. + * @param {boolean} [options.isAutosave=false] Whether this is an autosave. + * @param {Function} [options.__unstableFetch] Internal use only. Function to + * call instead of `apiFetch()`. + * Must return a promise. + * @param {boolean} [options.throwOnError=false] If false, this action suppresses all + * the exceptions. Defaults to false. + */ +const saveEntityRecord = (kind, name, record, { + isAutosave = false, + __unstableFetch = (external_wp_apiFetch_default()), + throwOnError = false +} = {}) => async ({ + select, + resolveSelect, + dispatch +}) => { + const configs = await resolveSelect.getEntitiesConfig(kind); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + if (!entityConfig) { + return; + } + const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; + const recordId = record[entityIdKey]; + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId || esm_browser_v4()], { + exclusive: true + }); + try { + // Evaluate optimized edits. + // (Function edits that should be evaluated on save to avoid expensive computations on every edit.) + for (const [key, value] of Object.entries(record)) { + if (typeof value === 'function') { + const evaluatedValue = value(select.getEditedEntityRecord(kind, name, recordId)); + dispatch.editEntityRecord(kind, name, recordId, { + [key]: evaluatedValue + }, { + undoIgnore: true + }); + record[key] = evaluatedValue; + } + } + dispatch({ + type: 'SAVE_ENTITY_RECORD_START', + kind, + name, + recordId, + isAutosave + }); + let updatedRecord; + let error; + let hasError = false; + try { + const path = `${entityConfig.baseURL}${recordId ? '/' + recordId : ''}`; + const persistedRecord = select.getRawEntityRecord(kind, name, recordId); + if (isAutosave) { + // Most of this autosave logic is very specific to posts. + // This is fine for now as it is the only supported autosave, + // but ideally this should all be handled in the back end, + // so the client just sends and receives objects. + const currentUser = select.getCurrentUser(); + const currentUserId = currentUser ? currentUser.id : undefined; + const autosavePost = await resolveSelect.getAutosave(persistedRecord.type, persistedRecord.id, currentUserId); + // Autosaves need all expected fields to be present. + // So we fallback to the previous autosave and then + // to the actual persisted entity if the edits don't + // have a value. + let data = { + ...persistedRecord, + ...autosavePost, + ...record + }; + data = Object.keys(data).reduce((acc, key) => { + if (['title', 'excerpt', 'content', 'meta'].includes(key)) { + acc[key] = data[key]; + } + return acc; + }, { + // Do not update the `status` if we have edited it when auto saving. + // It's very important to let the user explicitly save this change, + // because it can lead to unexpected results. An example would be to + // have a draft post and change the status to publish. + status: data.status === 'auto-draft' ? 'draft' : undefined + }); + updatedRecord = await __unstableFetch({ + path: `${path}/autosaves`, + method: 'POST', + data + }); + + // An autosave may be processed by the server as a regular save + // when its update is requested by the author and the post had + // draft or auto-draft status. + if (persistedRecord.id === updatedRecord.id) { + let newRecord = { + ...persistedRecord, + ...data, + ...updatedRecord + }; + newRecord = Object.keys(newRecord).reduce((acc, key) => { + // These properties are persisted in autosaves. + if (['title', 'excerpt', 'content'].includes(key)) { + acc[key] = newRecord[key]; + } else if (key === 'status') { + // Status is only persisted in autosaves when going from + // "auto-draft" to "draft". + acc[key] = persistedRecord.status === 'auto-draft' && newRecord.status === 'draft' ? newRecord.status : persistedRecord.status; + } else { + // These properties are not persisted in autosaves. + acc[key] = persistedRecord[key]; + } + return acc; + }, {}); + dispatch.receiveEntityRecords(kind, name, newRecord, undefined, true); + } else { + dispatch.receiveAutosaves(persistedRecord.id, updatedRecord); + } + } else { + let edits = record; + if (entityConfig.__unstablePrePersist) { + edits = { + ...edits, + ...entityConfig.__unstablePrePersist(persistedRecord, edits) + }; + } + updatedRecord = await __unstableFetch({ + path, + method: recordId ? 'PUT' : 'POST', + data: edits + }); + dispatch.receiveEntityRecords(kind, name, updatedRecord, undefined, true, edits); + } + } catch (_error) { + hasError = true; + error = _error; + } + dispatch({ + type: 'SAVE_ENTITY_RECORD_FINISH', + kind, + name, + recordId, + error, + isAutosave + }); + if (hasError && throwOnError) { + throw error; + } + return updatedRecord; + } finally { + dispatch.__unstableReleaseStoreLock(lock); + } +}; + +/** + * Runs multiple core-data actions at the same time using one API request. + * + * Example: + * + * ``` + * const [ savedRecord, updatedRecord, deletedRecord ] = + * await dispatch( 'core' ).__experimentalBatch( [ + * ( { saveEntityRecord } ) => saveEntityRecord( 'root', 'widget', widget ), + * ( { saveEditedEntityRecord } ) => saveEntityRecord( 'root', 'widget', 123 ), + * ( { deleteEntityRecord } ) => deleteEntityRecord( 'root', 'widget', 123, null ), + * ] ); + * ``` + * + * @param {Array} requests Array of functions which are invoked simultaneously. + * Each function is passed an object containing + * `saveEntityRecord`, `saveEditedEntityRecord`, and + * `deleteEntityRecord`. + * + * @return {(thunkArgs: Object) => Promise} A promise that resolves to an array containing the return + * values of each function given in `requests`. + */ +const __experimentalBatch = requests => async ({ + dispatch +}) => { + const batch = createBatch(); + const api = { + saveEntityRecord(kind, name, record, options) { + return batch.add(add => dispatch.saveEntityRecord(kind, name, record, { + ...options, + __unstableFetch: add + })); + }, + saveEditedEntityRecord(kind, name, recordId, options) { + return batch.add(add => dispatch.saveEditedEntityRecord(kind, name, recordId, { + ...options, + __unstableFetch: add + })); + }, + deleteEntityRecord(kind, name, recordId, query, options) { + return batch.add(add => dispatch.deleteEntityRecord(kind, name, recordId, query, { + ...options, + __unstableFetch: add + })); + } + }; + const resultPromises = requests.map(request => request(api)); + const [, ...results] = await Promise.all([batch.run(), ...resultPromises]); + return results; +}; + +/** + * Action triggered to save an entity record's edits. + * + * @param {string} kind Kind of the entity. + * @param {string} name Name of the entity. + * @param {Object} recordId ID of the record. + * @param {Object=} options Saving options. + */ +const saveEditedEntityRecord = (kind, name, recordId, options) => async ({ + select, + dispatch, + resolveSelect +}) => { + if (!select.hasEditsForEntityRecord(kind, name, recordId)) { + return; + } + const configs = await resolveSelect.getEntitiesConfig(kind); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + if (!entityConfig) { + return; + } + const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; + const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); + const record = { + [entityIdKey]: recordId, + ...edits + }; + return await dispatch.saveEntityRecord(kind, name, record, options); +}; + +/** + * Action triggered to save only specified properties for the entity. + * + * @param {string} kind Kind of the entity. + * @param {string} name Name of the entity. + * @param {number|string} recordId ID of the record. + * @param {Array} itemsToSave List of entity properties or property paths to save. + * @param {Object} options Saving options. + */ +const __experimentalSaveSpecifiedEntityEdits = (kind, name, recordId, itemsToSave, options) => async ({ + select, + dispatch, + resolveSelect +}) => { + if (!select.hasEditsForEntityRecord(kind, name, recordId)) { + return; + } + const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); + const editsToSave = {}; + for (const item of itemsToSave) { + setNestedValue(editsToSave, item, getNestedValue(edits, item)); + } + const configs = await resolveSelect.getEntitiesConfig(kind); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + const entityIdKey = entityConfig?.key || DEFAULT_ENTITY_KEY; + + // If a record key is provided then update the existing record. + // This necessitates providing `recordKey` to saveEntityRecord as part of the + // `record` argument (here called `editsToSave`) to stop that action creating + // a new record and instead cause it to update the existing record. + if (recordId) { + editsToSave[entityIdKey] = recordId; + } + return await dispatch.saveEntityRecord(kind, name, editsToSave, options); +}; + +/** + * Returns an action object used in signalling that Upload permissions have been received. + * + * @deprecated since WP 5.9, use receiveUserPermission instead. + * + * @param {boolean} hasUploadPermissions Does the user have permission to upload files? + * + * @return {Object} Action object. + */ +function receiveUploadPermissions(hasUploadPermissions) { + external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveUploadPermissions", { + since: '5.9', + alternative: 'receiveUserPermission' + }); + return receiveUserPermission('create/media', hasUploadPermissions); +} + +/** + * Returns an action object used in signalling that the current user has + * permission to perform an action on a REST resource. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {string} key A key that represents the action and REST resource. + * @param {boolean} isAllowed Whether or not the user can perform the action. + * + * @return {Object} Action object. + */ +function receiveUserPermission(key, isAllowed) { + return { + type: 'RECEIVE_USER_PERMISSION', + key, + isAllowed + }; +} + +/** + * Returns an action object used in signalling that the current user has + * permission to perform an action on a REST resource. Ignored from + * documentation as it's internal to the data store. + * + * @ignore + * + * @param {Object} permissions An object where keys represent + * actions and REST resources, and + * values indicate whether the user + * is allowed to perform the + * action. + * + * @return {Object} Action object. + */ +function receiveUserPermissions(permissions) { + return { + type: 'RECEIVE_USER_PERMISSIONS', + permissions + }; +} + +/** + * Returns an action object used in signalling that the autosaves for a + * post have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore + * + * @param {number} postId The id of the post that is parent to the autosave. + * @param {Array|Object} autosaves An array of autosaves or singular autosave object. + * + * @return {Object} Action object. + */ +function receiveAutosaves(postId, autosaves) { + return { + type: 'RECEIVE_AUTOSAVES', + postId, + autosaves: Array.isArray(autosaves) ? autosaves : [autosaves] + }; +} + +/** + * Returns an action object signalling that the fallback Navigation + * Menu id has been received. + * + * @param {integer} fallbackId the id of the fallback Navigation Menu + * @return {Object} Action object. + */ +function receiveNavigationFallbackId(fallbackId) { + return { + type: 'RECEIVE_NAVIGATION_FALLBACK_ID', + fallbackId + }; +} + +/** + * Returns an action object used to set the template for a given query. + * + * @param {Object} query The lookup query. + * @param {string} templateId The resolved template id. + * + * @return {Object} Action object. + */ +function receiveDefaultTemplateId(query, templateId) { + return { + type: 'RECEIVE_DEFAULT_TEMPLATE', + query, + templateId + }; +} + +/** + * Action triggered to receive revision items. + * + * @param {string} kind Kind of the received entity record revisions. + * @param {string} name Name of the received entity record revisions. + * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch. + * @param {Array|Object} records Revisions received. + * @param {?Object} query Query Object. + * @param {?boolean} invalidateCache Should invalidate query caches. + * @param {?Object} meta Meta information about pagination. + */ +const receiveRevisions = (kind, name, recordKey, records, query, invalidateCache = false, meta) => async ({ + dispatch, + resolveSelect +}) => { + const configs = await resolveSelect.getEntitiesConfig(kind); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + const key = entityConfig && entityConfig?.revisionKey ? entityConfig.revisionKey : DEFAULT_ENTITY_KEY; + dispatch({ + type: 'RECEIVE_ITEM_REVISIONS', + key, + items: Array.isArray(records) ? records : [records], + recordKey, + meta, + query, + kind, + name, + invalidateCache + }); +}; + +;// ./node_modules/@wordpress/core-data/build-module/private-actions.js +/** + * Returns an action object used in signalling that the registered post meta + * fields for a post type have been received. + * + * @param {string} postType Post type slug. + * @param {Object} registeredPostMeta Registered post meta. + * + * @return {Object} Action object. + */ +function receiveRegisteredPostMeta(postType, registeredPostMeta) { + return { + type: 'RECEIVE_REGISTERED_POST_META', + postType, + registeredPostMeta + }; +} + +;// ./node_modules/camel-case/dist.es2015/index.js function camelCaseTransform(input, index) { @@ -5462,9 +5684,9 @@ return pascalCase(input, __assign({ transform: camelCaseTransform }, options)); } -;// CONCATENATED MODULE: external ["wp","htmlEntities"] +;// external ["wp","htmlEntities"] const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"]; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/forward-resolver.js +;// ./node_modules/@wordpress/core-data/build-module/utils/forward-resolver.js /** * Higher-order function which forward the resolution to another resolver with the same arguments. * @@ -5479,7 +5701,10 @@ }; /* harmony default export */ const forward_resolver = (forwardResolver); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-link-suggestions.js +;// ./node_modules/@wordpress/core-data/build-module/utils/receive-intermediate-results.js +const RECEIVE_INTERMEDIATE_RESULTS = Symbol('RECEIVE_INTERMEDIATE_RESULTS'); + +;// ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-link-suggestions.js /** * WordPress dependencies */ @@ -5487,63 +5712,15 @@ - -/** - * Filters the search by type - * - * @typedef { 'attachment' | 'post' | 'term' | 'post-format' } WPLinkSearchType - */ - -/** - * A link with an id may be of kind post-type or taxonomy - * - * @typedef { 'post-type' | 'taxonomy' } WPKind - */ - -/** - * @typedef WPLinkSearchOptions - * - * @property {boolean} [isInitialSuggestions] Displays initial search suggestions, when true. - * @property {WPLinkSearchType} [type] Filters by search type. - * @property {string} [subtype] Slug of the post-type or taxonomy. - * @property {number} [page] Which page of results to return. - * @property {number} [perPage] Search results per page. - */ - -/** - * @typedef WPLinkSearchResult - * - * @property {number} id Post or term id. - * @property {string} url Link url. - * @property {string} title Title of the link. - * @property {string} type The taxonomy or post type slug or type URL. - * @property {WPKind} [kind] Link kind of post-type or taxonomy - */ - -/** - * @typedef WPLinkSearchResultAugments - * - * @property {{kind: WPKind}} [meta] Contains kind information. - * @property {WPKind} [subtype] Optional subtype if it exists. - */ - -/** - * @typedef {WPLinkSearchResult & WPLinkSearchResultAugments} WPLinkSearchResultAugmented - */ - -/** - * @typedef WPEditorSettings - * - * @property {boolean} [ disablePostFormats ] Disables post formats, when true. - */ - -/** - * Fetches link suggestions from the API. - * - * @async - * @param {string} search - * @param {WPLinkSearchOptions} [searchOptions] - * @param {WPEditorSettings} [settings] +/** + * Fetches link suggestions from the WordPress API. + * + * WordPress does not support searching multiple tables at once, e.g. posts and terms, so we + * perform multiple queries at the same time and then merge the results together. + * + * @param search + * @param searchOptions + * @param editorSettings * * @example * ```js @@ -5558,31 +5735,22 @@ * searchOptions * ) => fetchLinkSuggestions( search, searchOptions, settings ); * ``` - * @return {Promise< WPLinkSearchResult[] >} List of search suggestions - */ -const fetchLinkSuggestions = async (search, searchOptions = {}, settings = {}) => { + */ +async function fetchLinkSuggestions(search, searchOptions = {}, editorSettings = {}) { + const searchOptionsToUse = searchOptions.isInitialSuggestions && searchOptions.initialSuggestionsSearchOptions ? { + ...searchOptions, + ...searchOptions.initialSuggestionsSearchOptions + } : searchOptions; const { - isInitialSuggestions = false, - initialSuggestionsSearchOptions = undefined - } = searchOptions; + type, + subtype, + page, + perPage = searchOptions.isInitialSuggestions ? 3 : 20 + } = searchOptionsToUse; const { disablePostFormats = false - } = settings; - let { - type = undefined, - subtype = undefined, - page = undefined, - perPage = isInitialSuggestions ? 3 : 20 - } = searchOptions; - - /** @type {Promise[]} */ + } = editorSettings; const queries = []; - if (isInitialSuggestions && initialSuggestionsSearchOptions) { - type = initialSuggestionsSearchOptions.type || type; - subtype = initialSuggestionsSearchOptions.subtype || subtype; - page = initialSuggestionsSearchOptions.page || page; - perPage = initialSuggestionsSearchOptions.perPage || perPage; - } if (!type || type === 'post') { queries.push(external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', { @@ -5595,11 +5763,11 @@ }).then(results => { return results.map(result => { return { - ...result, - meta: { - kind: 'post-type', - subtype - } + id: result.id, + url: result.url, + title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(result.title || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), + type: result.subtype || result.type, + kind: 'post-type' }; }); }).catch(() => []) // Fail by returning no results. @@ -5617,11 +5785,11 @@ }).then(results => { return results.map(result => { return { - ...result, - meta: { - kind: 'taxonomy', - subtype - } + id: result.id, + url: result.url, + title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(result.title || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), + type: result.subtype || result.type, + kind: 'taxonomy' }; }); }).catch(() => []) // Fail by returning no results. @@ -5639,11 +5807,11 @@ }).then(results => { return results.map(result => { return { - ...result, - meta: { - kind: 'taxonomy', - subtype - } + id: result.id, + url: result.url, + title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(result.title || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), + type: result.subtype || result.type, + kind: 'taxonomy' }; }); }).catch(() => []) // Fail by returning no results. @@ -5659,42 +5827,75 @@ }).then(results => { return results.map(result => { return { - ...result, - meta: { - kind: 'media' - } + id: result.id, + url: result.source_url, + title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(result.title.rendered || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), + type: result.type, + kind: 'media' }; }); }).catch(() => []) // Fail by returning no results. ); } - return Promise.all(queries).then(results => { - return results.reduce(( /** @type {WPLinkSearchResult[]} */accumulator, current) => accumulator.concat(current), - // Flatten list. - []).filter( - /** - * @param {{ id: number }} result - */ - result => { - return !!result.id; - }).slice(0, perPage).map(( /** @type {WPLinkSearchResultAugmented} */result) => { - const isMedia = result.type === 'attachment'; - return { - id: result.id, - // @ts-ignore fix when we make this a TS file - url: isMedia ? result.source_url : result.url, - title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(isMedia ? - // @ts-ignore fix when we make this a TS file - result.title.rendered : result.title || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), - type: result.subtype || result.type, - kind: result?.meta?.kind - }; - }); - }); -}; -/* harmony default export */ const _experimental_fetch_link_suggestions = (fetchLinkSuggestions); - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-url-data.js + const responses = await Promise.all(queries); + let results = responses.flat(); + results = results.filter(result => !!result.id); + results = sortResults(results, search); + results = results.slice(0, perPage); + return results; +} + +/** + * Sort search results by relevance to the given query. + * + * Sorting is necessary as we're querying multiple endpoints and merging the results. For example + * a taxonomy title might be more relevant than a post title, but by default taxonomy results will + * be ordered after all the (potentially irrelevant) post results. + * + * We sort by scoring each result, where the score is the number of tokens in the title that are + * also in the search query, divided by the total number of tokens in the title. This gives us a + * score between 0 and 1, where 1 is a perfect match. + * + * @param results + * @param search + */ +function sortResults(results, search) { + const searchTokens = tokenize(search); + const scores = {}; + for (const result of results) { + if (result.title) { + const titleTokens = tokenize(result.title); + const exactMatchingTokens = titleTokens.filter(titleToken => searchTokens.some(searchToken => titleToken === searchToken)); + const subMatchingTokens = titleTokens.filter(titleToken => searchTokens.some(searchToken => titleToken !== searchToken && titleToken.includes(searchToken))); + + // The score is a combination of exact matches and sub-matches. + // More weight is given to exact matches, as they are more relevant (e.g. "cat" vs "caterpillar"). + // Diving by the total number of tokens in the title normalizes the score and skews + // the results towards shorter titles. + const exactMatchScore = exactMatchingTokens.length / titleTokens.length * 10; + const subMatchScore = subMatchingTokens.length / titleTokens.length; + scores[result.id] = exactMatchScore + subMatchScore; + } else { + scores[result.id] = 0; + } + } + return results.sort((a, b) => scores[b.id] - scores[a.id]); +} + +/** + * Turns text into an array of tokens, with whitespace and punctuation removed. + * + * For example, `"I'm having a ball."` becomes `[ "im", "having", "a", "ball" ]`. + * + * @param text + */ +function tokenize(text) { + // \p{L} matches any kind of letter from any language. + // \p{N} matches any kind of numeric character. + return text.toLowerCase().match(/[\p{L}\p{N}]+/gu) || []; +} + +;// ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-url-data.js /** * WordPress dependencies */ @@ -5720,7 +5921,7 @@ * * @async * @param {string} url the URL to request details from. - * @param {Object?} options any options to pass to the underlying fetch. + * @param {?Object} options any options to pass to the underlying fetch. * @example * ```js * import { __experimentalFetchUrlData as fetchUrlData } from '@wordpress/core-data'; @@ -5763,7 +5964,7 @@ }; /* harmony default export */ const _experimental_fetch_url_data = (fetchUrlData); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/index.js +;// ./node_modules/@wordpress/core-data/build-module/fetch/index.js /** * External dependencies */ @@ -5785,7 +5986,7 @@ return restPatterns.map(pattern => Object.fromEntries(Object.entries(pattern).map(([key, value]) => [camelCase(key), value]))); } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/resolvers.js +;// ./node_modules/@wordpress/core-data/build-module/resolvers.js /** * External dependencies */ @@ -5847,11 +6048,13 @@ */ const resolvers_getEntityRecord = (kind, name, key = '', query) => async ({ select, - dispatch + dispatch, + registry, + resolveSelect }) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const configs = await resolveSelect.getEntitiesConfig(kind); const entityConfig = configs.find(config => config.name === name && config.kind === kind); - if (!entityConfig || entityConfig?.__experimentalNoFetch) { + if (!entityConfig) { return; } const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, key], { @@ -5884,7 +6087,7 @@ ...entityConfig.baseURLParams, ...query }); - if (query !== undefined) { + if (query !== undefined && query._fields) { query = { ...query, include: [key] @@ -5898,10 +6101,31 @@ return; } } - const record = await external_wp_apiFetch_default()({ - path + const response = await external_wp_apiFetch_default()({ + path, + parse: false }); - dispatch.receiveEntityRecords(kind, name, record, query); + const record = await response.json(); + const permissions = getUserPermissionsFromAllowHeader(response.headers?.get('allow')); + const canUserResolutionsArgs = []; + const receiveUserPermissionArgs = {}; + for (const action of ALLOWED_RESOURCE_ACTIONS) { + receiveUserPermissionArgs[getUserPermissionCacheKey(action, { + kind, + name, + id: key + })] = permissions[action]; + canUserResolutionsArgs.push([action, { + kind, + name, + id: key + }]); + } + registry.batch(() => { + dispatch.receiveEntityRecords(kind, name, record, query); + dispatch.receiveUserPermissions(receiveUserPermissionArgs); + dispatch.finishResolutions('canUser', canUserResolutionsArgs); + }); } } finally { dispatch.__unstableReleaseStoreLock(lock); @@ -5923,21 +6147,26 @@ * * @param {string} kind Entity kind. * @param {string} name Entity name. - * @param {Object?} query Query Object. If requesting specific fields, fields + * @param {?Object} query Query Object. If requesting specific fields, fields * must always include the ID. */ const resolvers_getEntityRecords = (kind, name, query = {}) => async ({ dispatch, - registry + registry, + resolveSelect }) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const configs = await resolveSelect.getEntitiesConfig(kind); const entityConfig = configs.find(config => config.name === name && config.kind === kind); - if (!entityConfig || entityConfig?.__experimentalNoFetch) { + if (!entityConfig) { return; } const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name], { exclusive: false }); + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + function getResolutionsArgs(records) { + return records.filter(record => record?.[key]).map(record => [kind, name, record[key]]); + } try { if (query._fields) { // If requesting specific fields, items and query association to said @@ -5952,7 +6181,8 @@ ...entityConfig.baseURLParams, ...query }); - let records, meta; + let records = [], + meta; if (entityConfig.supportsPagination && query.per_page !== -1) { const response = await external_wp_apiFetch_default()({ path, @@ -5963,10 +6193,38 @@ totalItems: parseInt(response.headers.get('X-WP-Total')), totalPages: parseInt(response.headers.get('X-WP-TotalPages')) }; + } else if (query.per_page === -1 && query[RECEIVE_INTERMEDIATE_RESULTS] === true) { + let page = 1; + let totalPages; + do { + const response = await external_wp_apiFetch_default()({ + path: (0,external_wp_url_namespaceObject.addQueryArgs)(path, { + page, + per_page: 100 + }), + parse: false + }); + const pageRecords = Object.values(await response.json()); + totalPages = parseInt(response.headers.get('X-WP-TotalPages')); + records.push(...pageRecords); + registry.batch(() => { + dispatch.receiveEntityRecords(kind, name, records, query); + dispatch.finishResolutions('getEntityRecord', getResolutionsArgs(pageRecords)); + }); + page++; + } while (page <= totalPages); + meta = { + totalItems: records.length, + totalPages: 1 + }; } else { records = Object.values(await external_wp_apiFetch_default()({ path })); + meta = { + totalItems: records.length, + totalPages: 1 + }; } // If we request fields but the result doesn't contain the fields, @@ -5985,22 +6243,34 @@ registry.batch(() => { dispatch.receiveEntityRecords(kind, name, records, query, false, undefined, meta); - // When requesting all fields, the list of results can be used to - // resolve the `getEntityRecord` selector in addition to `getEntityRecords`. + // When requesting all fields, the list of results can be used to resolve + // the `getEntityRecord` and `canUser` selectors in addition to `getEntityRecords`. // See https://github.com/WordPress/gutenberg/pull/26575 + // See https://github.com/WordPress/gutenberg/pull/64504 if (!query?._fields && !query.context) { - const key = entityConfig.key || DEFAULT_ENTITY_KEY; - const resolutionsArgs = records.filter(record => record?.[key]).map(record => [kind, name, record[key]]); - dispatch({ - type: 'START_RESOLUTIONS', - selectorName: 'getEntityRecord', - args: resolutionsArgs - }); - dispatch({ - type: 'FINISH_RESOLUTIONS', - selectorName: 'getEntityRecord', - args: resolutionsArgs - }); + const targetHints = records.filter(record => record?.[key]).map(record => ({ + id: record[key], + permissions: getUserPermissionsFromAllowHeader(record?._links?.self?.[0].targetHints.allow) + })); + const canUserResolutionsArgs = []; + const receiveUserPermissionArgs = {}; + for (const targetHint of targetHints) { + for (const action of ALLOWED_RESOURCE_ACTIONS) { + canUserResolutionsArgs.push([action, { + kind, + name, + id: targetHint.id + }]); + receiveUserPermissionArgs[getUserPermissionCacheKey(action, { + kind, + name, + id: targetHint.id + })] = targetHint.permissions[action]; + } + } + dispatch.receiveUserPermissions(receiveUserPermissionArgs); + dispatch.finishResolutions('getEntityRecord', getResolutionsArgs(records)); + dispatch.finishResolutions('canUser', canUserResolutionsArgs); } dispatch.__unstableReleaseStoreLock(lock); }); @@ -6055,26 +6325,26 @@ * Checks whether the current user can perform the given action on the given * REST resource. * - * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update', - * 'delete'. - * @param {string} resource REST resource to check, e.g. 'media' or 'posts'. - * @param {?string} id ID of the rest resource to check. + * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update', + * 'delete'. + * @param {string|Object} resource Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` + * or REST base as a string - `media`. + * @param {?string} id ID of the rest resource to check. */ const resolvers_canUser = (requestedAction, resource, id) => async ({ dispatch, - registry + registry, + resolveSelect }) => { + if (!ALLOWED_RESOURCE_ACTIONS.includes(requestedAction)) { + throw new Error(`'${requestedAction}' is not a valid action.`); + } const { hasStartedResolution } = registry.select(STORE_NAME); - const resourcePath = id ? `${resource}/${id}` : resource; - const retrievedActions = ['create', 'read', 'update', 'delete']; - if (!retrievedActions.includes(requestedAction)) { - throw new Error(`'${requestedAction}' is not a valid action.`); - } // Prevent resolving the same resource twice. - for (const relatedAction of retrievedActions) { + for (const relatedAction of ALLOWED_RESOURCE_ACTIONS) { if (relatedAction === requestedAction) { continue; } @@ -6083,10 +6353,24 @@ return; } } + let resourcePath = null; + if (typeof resource === 'object') { + if (!resource.kind || !resource.name) { + throw new Error('The entity resource object is not valid.'); + } + const configs = await resolveSelect.getEntitiesConfig(resource.kind); + const entityConfig = configs.find(config => config.name === resource.name && config.kind === resource.kind); + if (!entityConfig) { + return; + } + resourcePath = entityConfig.baseURL + (resource.id ? '/' + resource.id : ''); + } else { + resourcePath = `/wp/v2/${resource}` + (id ? '/' + id : ''); + } let response; try { response = await external_wp_apiFetch_default()({ - path: `/wp/v2/${resourcePath}`, + path: resourcePath, method: 'OPTIONS', parse: false }); @@ -6097,43 +6381,38 @@ } // Optional chaining operator is used here because the API requests don't - // return the expected result in the native version. Instead, API requests + // return the expected result in the React native version. Instead, API requests // only return the result, without including response properties like the headers. - const allowHeader = response.headers?.get('allow'); - const allowedMethods = allowHeader?.allow || allowHeader || ''; - const permissions = {}; - const methods = { - create: 'POST', - read: 'GET', - update: 'PUT', - delete: 'DELETE' - }; - for (const [actionName, methodName] of Object.entries(methods)) { - permissions[actionName] = allowedMethods.includes(methodName); - } - for (const action of retrievedActions) { - dispatch.receiveUserPermission(`${action}/${resourcePath}`, permissions[action]); - } + const permissions = getUserPermissionsFromAllowHeader(response.headers?.get('allow')); + registry.batch(() => { + for (const action of ALLOWED_RESOURCE_ACTIONS) { + const key = getUserPermissionCacheKey(action, resource, id); + dispatch.receiveUserPermission(key, permissions[action]); + + // Mark related action resolutions as finished. + if (action !== requestedAction) { + dispatch.finishResolution('canUser', [action, resource, id]); + } + } + }); }; /** * Checks whether the current user can perform the given action on the given * REST resource. * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {string} recordId Record's id. + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} recordId Record's id. */ const resolvers_canUserEditEntityRecord = (kind, name, recordId) => async ({ dispatch }) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); - const entityConfig = configs.find(config => config.name === name && config.kind === kind); - if (!entityConfig) { - return; - } - const resource = entityConfig.__unstable_rest_base; - await dispatch(resolvers_canUser('update', resource, recordId)); + await dispatch(resolvers_canUser('update', { + kind, + name, + id: recordId + })); }; /** @@ -6148,8 +6427,12 @@ }) => { const { rest_base: restBase, - rest_namespace: restNamespace = 'wp/v2' + rest_namespace: restNamespace = 'wp/v2', + supports } = await resolveSelect.getPostType(postType); + if (!supports?.autosave) { + return; + } const autosaves = await external_wp_apiFetch_default()({ path: `/${restNamespace}/${restBase}/${postId}/autosaves?context=edit` }); @@ -6172,43 +6455,6 @@ }) => { await resolveSelect.getAutosaves(postType, postId); }; - -/** - * Retrieve the frontend template used for a given link. - * - * @param {string} link Link. - */ -const resolvers_experimentalGetTemplateForLink = link => async ({ - dispatch, - resolveSelect -}) => { - let template; - try { - // This is NOT calling a REST endpoint but rather ends up with a response from - // an Ajax function which has a different shape from a WP_REST_Response. - template = await external_wp_apiFetch_default()({ - url: (0,external_wp_url_namespaceObject.addQueryArgs)(link, { - '_wp-find-template': true - }) - }).then(({ - data - }) => data); - } catch (e) { - // For non-FSE themes, it is possible that this request returns an error. - } - if (!template) { - return; - } - const record = await resolveSelect.getEntityRecord('postType', 'wp_template', template.id); - if (record) { - dispatch.receiveEntityRecords('postType', 'wp_template', [record], { - 'find-template': link - }); - } -}; -resolvers_experimentalGetTemplateForLink.shouldInvalidate = action => { - return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && action.kind === 'postType' && action.name === 'wp_template'; -}; const resolvers_experimentalGetCurrentGlobalStylesId = () => async ({ dispatch, resolveSelect @@ -6234,8 +6480,9 @@ dispatch }) => { const currentTheme = await resolveSelect.getCurrentTheme(); + // Please adjust the preloaded requests if this changes! const themeGlobalStyles = await external_wp_apiFetch_default()({ - path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}` + path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}?context=view` }); dispatch.__experimentalReceiveThemeBaseGlobalStyles(currentTheme.stylesheet, themeGlobalStyles); }; @@ -6244,8 +6491,9 @@ dispatch }) => { const currentTheme = await resolveSelect.getCurrentTheme(); + // Please adjust the preloaded requests if this changes! const variations = await external_wp_apiFetch_default()({ - path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}/variations` + path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}/variations?context=view` }); dispatch.__experimentalReceiveThemeGlobalStyleVariations(currentTheme.stylesheet, variations); }; @@ -6312,7 +6560,8 @@ }; const resolvers_getNavigationFallbackId = () => async ({ dispatch, - select + select, + registry }) => { const fallback = await external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp-block-editor/v1/navigation-fallback', { @@ -6320,8 +6569,12 @@ }) }); const record = fallback?._embedded?.self; - dispatch.receiveNavigationFallbackId(fallback?.id); - if (record) { + registry.batch(() => { + dispatch.receiveNavigationFallbackId(fallback?.id); + if (!record) { + return; + } + // If the fallback is already in the store, don't invalidate navigation queries. // Otherwise, invalidate the cache for the scenario where there were no Navigation // posts in the state and the fallback created one. @@ -6331,17 +6584,27 @@ // Resolve to avoid further network requests. dispatch.finishResolution('getEntityRecord', ['postType', 'wp_navigation', fallback.id]); - } + }); }; const resolvers_getDefaultTemplateId = query => async ({ - dispatch + dispatch, + registry, + resolveSelect }) => { const template = await external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/templates/lookup', query) }); + // Wait for the the entities config to be loaded, otherwise receiving + // the template as an entity will not work. + await resolveSelect.getEntitiesConfig('postType'); // Endpoint may return an empty object if no template is found. if (template?.id) { - dispatch.receiveDefaultTemplateId(query, template.id); + registry.batch(() => { + dispatch.receiveDefaultTemplateId(query, template.id); + dispatch.receiveEntityRecords('postType', 'wp_template', [template]); + // Avoid further network requests. + dispatch.finishResolution('getEntityRecord', ['postType', 'wp_template', template.id]); + }); } }; @@ -6356,11 +6619,13 @@ * fields, fields must always include the ID. */ const resolvers_getRevisions = (kind, name, recordKey, query = {}) => async ({ - dispatch + dispatch, + registry, + resolveSelect }) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const configs = await resolveSelect.getEntitiesConfig(kind); const entityConfig = configs.find(config => config.name === name && config.kind === kind); - if (!entityConfig || entityConfig?.__experimentalNoFetch) { + if (!entityConfig) { return; } if (query._fields) { @@ -6406,24 +6671,17 @@ return record; }); } - dispatch.receiveRevisions(kind, name, recordKey, records, query, false, meta); - - // When requesting all fields, the list of results can be used to - // resolve the `getRevision` selector in addition to `getRevisions`. - if (!query?._fields && !query.context) { - const key = entityConfig.key || DEFAULT_ENTITY_KEY; - const resolutionsArgs = records.filter(record => record[key]).map(record => [kind, name, recordKey, record[key]]); - dispatch({ - type: 'START_RESOLUTIONS', - selectorName: 'getRevision', - args: resolutionsArgs - }); - dispatch({ - type: 'FINISH_RESOLUTIONS', - selectorName: 'getRevision', - args: resolutionsArgs - }); - } + registry.batch(() => { + dispatch.receiveRevisions(kind, name, recordKey, records, query, false, meta); + + // When requesting all fields, the list of results can be used to + // resolve the `getRevision` selector in addition to `getRevisions`. + if (!query?._fields && !query.context) { + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + const resolutionsArgs = records.filter(record => record[key]).map(record => [kind, name, recordKey, record[key]]); + dispatch.finishResolutions('getRevision', resolutionsArgs); + } + }); } }; @@ -6442,11 +6700,12 @@ * fields, fields must always include the ID. */ const resolvers_getRevision = (kind, name, recordKey, revisionKey, query) => async ({ - dispatch + dispatch, + resolveSelect }) => { - const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const configs = await resolveSelect.getEntitiesConfig(kind); const entityConfig = configs.find(config => config.name === name && config.kind === kind); - if (!entityConfig || entityConfig?.__experimentalNoFetch) { + if (!entityConfig) { return; } if (query !== undefined && query._fields) { @@ -6473,7 +6732,58 @@ } }; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/utils.js +/** + * Requests a specific post type options from the REST API. + * + * @param {string} postType Post type slug. + */ +const resolvers_getRegisteredPostMeta = postType => async ({ + dispatch, + resolveSelect +}) => { + let options; + try { + const { + rest_namespace: restNamespace = 'wp/v2', + rest_base: restBase + } = (await resolveSelect.getPostType(postType)) || {}; + options = await external_wp_apiFetch_default()({ + path: `${restNamespace}/${restBase}/?context=edit`, + method: 'OPTIONS' + }); + } catch (error) { + // Do nothing if the request comes back with an API error. + return; + } + if (options) { + dispatch.receiveRegisteredPostMeta(postType, options?.schema?.properties?.meta?.properties); + } +}; + +/** + * Requests entity configs for the given kind from the REST API. + * + * @param {string} kind Entity kind. + */ +const resolvers_getEntitiesConfig = kind => async ({ + dispatch +}) => { + const loader = additionalEntityConfigLoaders.find(l => l.kind === kind); + if (!loader) { + return; + } + try { + const configs = await loader.loadEntities(); + if (!configs.length) { + return; + } + dispatch.addEntities(configs); + } catch { + // Do nothing if the request comes back with an API error. + } +}; + +;// ./node_modules/@wordpress/core-data/build-module/locks/utils.js function deepCopyLocksTreePath(tree, path) { const newTree = { ...tree @@ -6535,7 +6845,7 @@ return false; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/reducer.js +;// ./node_modules/@wordpress/core-data/build-module/locks/reducer.js /** * Internal dependencies */ @@ -6606,7 +6916,7 @@ return state; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/selectors.js +;// ./node_modules/@wordpress/core-data/build-module/locks/selectors.js /** * Internal dependencies */ @@ -6647,7 +6957,7 @@ return true; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/engine.js +;// ./node_modules/@wordpress/core-data/build-module/locks/engine.js /** * Internal dependencies */ @@ -6709,7 +7019,7 @@ }; } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/actions.js +;// ./node_modules/@wordpress/core-data/build-module/locks/actions.js /** * Internal dependencies */ @@ -6730,95 +7040,47 @@ }; } -;// CONCATENATED MODULE: external ["wp","privateApis"] -const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"]; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/private-apis.js -/** - * WordPress dependencies - */ - -const { - lock, - unlock -} = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/core-data'); - -;// CONCATENATED MODULE: external ["wp","element"] -const external_wp_element_namespaceObject = window["wp"]["element"]; -;// CONCATENATED MODULE: external ["wp","blocks"] -const external_wp_blocks_namespaceObject = window["wp"]["blocks"]; -;// CONCATENATED MODULE: external ["wp","blockEditor"] -const external_wp_blockEditor_namespaceObject = window["wp"]["blockEditor"]; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/get-rich-text-values-cached.js -/** - * WordPress dependencies - */ - - +;// ./node_modules/@wordpress/core-data/build-module/dynamic-entities.js /** * Internal dependencies */ - -// TODO: The following line should have been: -// -// const unlockedApis = unlock( blockEditorPrivateApis ); -// -// But there are hidden circular dependencies in RNMobile code, specifically in -// certain native components in the `components` package that depend on -// `block-editor`. What follows is a workaround that defers the `unlock` call -// to prevent native code from failing. -// -// Fix once https://github.com/WordPress/gutenberg/issues/52692 is closed. -let unlockedApis; -const cache = new WeakMap(); -function getRichTextValuesCached(block) { - if (!unlockedApis) { - unlockedApis = unlock(external_wp_blockEditor_namespaceObject.privateApis); - } - if (!cache.has(block)) { - const values = unlockedApis.getRichTextValues([block]); - cache.set(block, values); - } - return cache.get(block); -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/get-footnotes-order.js -/** - * Internal dependencies - */ - -const get_footnotes_order_cache = new WeakMap(); -function getBlockFootnotesOrder(block) { - if (!get_footnotes_order_cache.has(block)) { - const order = []; - for (const value of getRichTextValuesCached(block)) { - if (!value) { - continue; - } - - // replacements is a sparse array, use forEach to skip empty slots. - value.replacements.forEach(({ - type, - attributes - }) => { - if (type === 'core/footnote') { - order.push(attributes['data-fn']); - } - }); - } - get_footnotes_order_cache.set(block, order); - } - return get_footnotes_order_cache.get(block); -} -function getFootnotesOrder(blocks) { - // We can only separate getting order from blocks at the root level. For - // deeper inner blocks, this will not work since it's possible to have both - // inner blocks and block attributes, so order needs to be computed from the - // Edit functions as a whole. - return blocks.flatMap(getBlockFootnotesOrder); -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/index.js +/** + * A simple utility that pluralizes a string. + * Converts: + * - "post" to "posts" + * - "taxonomy" to "taxonomies" + * - "media" to "mediaItems" + * - "status" to "statuses" + * + * It does not pluralize "GlobalStyles" due to lack of clarity about it at time of writing. + */ + +/** + * A simple utility that singularizes a string. + * + * Converts: + * - "posts" to "post" + * - "taxonomies" to "taxonomy" + * - "mediaItems" to "media" + * - "statuses" to "status" + */ + +let dynamicActions; +let dynamicSelectors; + +;// external ["wp","element"] +const external_wp_element_namespaceObject = window["wp"]["element"]; +;// ./node_modules/@wordpress/core-data/build-module/entity-context.js +/** + * WordPress dependencies + */ + +const EntityContext = (0,external_wp_element_namespaceObject.createContext)({}); + +;// external "ReactJSXRuntime" +const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"]; +;// ./node_modules/@wordpress/core-data/build-module/entity-provider.js /** * WordPress dependencies */ @@ -6828,124 +7090,6 @@ * Internal dependencies */ -let oldFootnotes = {}; -function updateFootnotesFromMeta(blocks, meta) { - const output = { - blocks - }; - if (!meta) { - return output; - } - - // If meta.footnotes is empty, it means the meta is not registered. - if (meta.footnotes === undefined) { - return output; - } - const newOrder = getFootnotesOrder(blocks); - const footnotes = meta.footnotes ? JSON.parse(meta.footnotes) : []; - const currentOrder = footnotes.map(fn => fn.id); - if (currentOrder.join('') === newOrder.join('')) { - return output; - } - const newFootnotes = newOrder.map(fnId => footnotes.find(fn => fn.id === fnId) || oldFootnotes[fnId] || { - id: fnId, - content: '' - }); - function updateAttributes(attributes) { - // Only attempt to update attributes, if attributes is an object. - if (!attributes || Array.isArray(attributes) || typeof attributes !== 'object') { - return attributes; - } - attributes = { - ...attributes - }; - for (const key in attributes) { - const value = attributes[key]; - if (Array.isArray(value)) { - attributes[key] = value.map(updateAttributes); - continue; - } - - // To do, remove support for string values? - if (typeof value !== 'string' && !(value instanceof external_wp_richText_namespaceObject.RichTextData)) { - continue; - } - const richTextValue = typeof value === 'string' ? external_wp_richText_namespaceObject.RichTextData.fromHTMLString(value) : new external_wp_richText_namespaceObject.RichTextData(value); - richTextValue.replacements.forEach(replacement => { - if (replacement.type === 'core/footnote') { - const id = replacement.attributes['data-fn']; - const index = newOrder.indexOf(id); - // The innerHTML contains the count wrapped in a link. - const countValue = (0,external_wp_richText_namespaceObject.create)({ - html: replacement.innerHTML - }); - countValue.text = String(index + 1); - countValue.formats = Array.from({ - length: countValue.text.length - }, () => countValue.formats[0]); - countValue.replacements = Array.from({ - length: countValue.text.length - }, () => countValue.replacements[0]); - replacement.innerHTML = (0,external_wp_richText_namespaceObject.toHTMLString)({ - value: countValue - }); - } - }); - attributes[key] = typeof value === 'string' ? richTextValue.toHTMLString() : richTextValue; - } - return attributes; - } - function updateBlocksAttributes(__blocks) { - return __blocks.map(block => { - return { - ...block, - attributes: updateAttributes(block.attributes), - innerBlocks: updateBlocksAttributes(block.innerBlocks) - }; - }); - } - - // We need to go through all block attributes deeply and update the - // footnote anchor numbering (textContent) to match the new order. - const newBlocks = updateBlocksAttributes(blocks); - oldFootnotes = { - ...oldFootnotes, - ...footnotes.reduce((acc, fn) => { - if (!newOrder.includes(fn.id)) { - acc[fn.id] = fn; - } - return acc; - }, {}) - }; - return { - meta: { - ...meta, - footnotes: JSON.stringify(newFootnotes) - }, - blocks: newBlocks - }; -} - -;// CONCATENATED MODULE: external "ReactJSXRuntime" -const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"]; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/entity-provider.js -/** - * WordPress dependencies - */ - - - - -/** - * Internal dependencies - */ - - - -/** @typedef {import('@wordpress/blocks').WPBlock} WPBlock */ - -const EMPTY_ARRAY = []; -const EntityContext = (0,external_wp_element_namespaceObject.createContext)({}); /** * Context provider component for providing @@ -6960,6 +7104,7 @@ * @return {Object} The provided children, wrapped with * the entity's context provider. */ + function EntityProvider({ kind, type: name, @@ -6980,182 +7125,7 @@ }); } -/** - * Hook that returns the ID for the nearest - * provided entity of the specified type. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - */ -function useEntityId(kind, name) { - const context = (0,external_wp_element_namespaceObject.useContext)(EntityContext); - return context?.[kind]?.[name]; -} - -/** - * Hook that returns the value and a setter for the - * specified property of the nearest provided - * entity of the specified type. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - * @param {string} prop The property name. - * @param {string} [_id] An entity ID to use instead of the context-provided one. - * - * @return {[*, Function, *]} An array where the first item is the - * property value, the second is the - * setter and the third is the full value - * object from REST API containing more - * information like `raw`, `rendered` and - * `protected` props. - */ -function useEntityProp(kind, name, prop, _id) { - const providerId = useEntityId(kind, name); - const id = _id !== null && _id !== void 0 ? _id : providerId; - const { - value, - fullValue - } = (0,external_wp_data_namespaceObject.useSelect)(select => { - const { - getEntityRecord, - getEditedEntityRecord - } = select(STORE_NAME); - const record = getEntityRecord(kind, name, id); // Trigger resolver. - const editedRecord = getEditedEntityRecord(kind, name, id); - return record && editedRecord ? { - value: editedRecord[prop], - fullValue: record[prop] - } : {}; - }, [kind, name, id, prop]); - const { - editEntityRecord - } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); - const setValue = (0,external_wp_element_namespaceObject.useCallback)(newValue => { - editEntityRecord(kind, name, id, { - [prop]: newValue - }); - }, [editEntityRecord, kind, name, id, prop]); - return [value, setValue, fullValue]; -} -const parsedBlocksCache = new WeakMap(); - -/** - * Hook that returns block content getters and setters for - * the nearest provided entity of the specified type. - * - * The return value has the shape `[ blocks, onInput, onChange ]`. - * `onInput` is for block changes that don't create undo levels - * or dirty the post, non-persistent changes, and `onChange` is for - * persistent changes. They map directly to the props of a - * `BlockEditorProvider` and are intended to be used with it, - * or similar components or hooks. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - * @param {Object} options - * @param {string} [options.id] An entity ID to use instead of the context-provided one. - * - * @return {[WPBlock[], Function, Function]} The block array and setters. - */ -function useEntityBlockEditor(kind, name, { - id: _id -} = {}) { - const providerId = useEntityId(kind, name); - const id = _id !== null && _id !== void 0 ? _id : providerId; - const { - getEntityRecord, - getEntityRecordEdits - } = (0,external_wp_data_namespaceObject.useSelect)(STORE_NAME); - const { - content, - editedBlocks, - meta - } = (0,external_wp_data_namespaceObject.useSelect)(select => { - if (!id) { - return {}; - } - const { - getEditedEntityRecord - } = select(STORE_NAME); - const editedRecord = getEditedEntityRecord(kind, name, id); - return { - editedBlocks: editedRecord.blocks, - content: editedRecord.content, - meta: editedRecord.meta - }; - }, [kind, name, id]); - const { - __unstableCreateUndoLevel, - editEntityRecord - } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); - const blocks = (0,external_wp_element_namespaceObject.useMemo)(() => { - if (!id) { - return undefined; - } - if (editedBlocks) { - return editedBlocks; - } - if (!content || typeof content !== 'string') { - return EMPTY_ARRAY; - } - - // If there's an edit, cache the parsed blocks by the edit. - // If not, cache by the original enity record. - const edits = getEntityRecordEdits(kind, name, id); - const isUnedited = !edits || !Object.keys(edits).length; - const cackeKey = isUnedited ? getEntityRecord(kind, name, id) : edits; - let _blocks = parsedBlocksCache.get(cackeKey); - if (!_blocks) { - _blocks = (0,external_wp_blocks_namespaceObject.parse)(content); - parsedBlocksCache.set(cackeKey, _blocks); - } - return _blocks; - }, [kind, name, id, editedBlocks, content, getEntityRecord, getEntityRecordEdits]); - const updateFootnotes = (0,external_wp_element_namespaceObject.useCallback)(_blocks => updateFootnotesFromMeta(_blocks, meta), [meta]); - const onChange = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { - const noChange = blocks === newBlocks; - if (noChange) { - return __unstableCreateUndoLevel(kind, name, id); - } - const { - selection, - ...rest - } = options; - - // We create a new function here on every persistent edit - // to make sure the edit makes the post dirty and creates - // a new undo level. - const edits = { - selection, - content: ({ - blocks: blocksForSerialization = [] - }) => (0,external_wp_blocks_namespaceObject.__unstableSerializeAndClean)(blocksForSerialization), - ...updateFootnotes(newBlocks) - }; - editEntityRecord(kind, name, id, edits, { - isCached: false, - ...rest - }); - }, [kind, name, id, blocks, updateFootnotes, __unstableCreateUndoLevel, editEntityRecord]); - const onInput = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { - const { - selection, - ...rest - } = options; - const footnotesChanges = updateFootnotes(newBlocks); - const edits = { - selection, - ...footnotesChanges - }; - editEntityRecord(kind, name, id, edits, { - isCached: true, - ...rest - }); - }, [kind, name, id, updateFootnotes, editEntityRecord]); - return [blocks, onInput, onChange]; -} - -;// CONCATENATED MODULE: ./node_modules/memize/dist/index.js +;// ./node_modules/memize/dist/index.js /** * Memize options object. * @@ -7317,7 +7287,7 @@ -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/memoize.js +;// ./node_modules/@wordpress/core-data/build-module/hooks/memoize.js /** * External dependencies */ @@ -7326,7 +7296,7 @@ // re-export due to restrictive esModuleInterop setting /* harmony default export */ const memoize = (memize); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/constants.js +;// ./node_modules/@wordpress/core-data/build-module/hooks/constants.js let Status = /*#__PURE__*/function (Status) { Status["Idle"] = "IDLE"; Status["Resolving"] = "RESOLVING"; @@ -7335,7 +7305,7 @@ return Status; }({}); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-query-select.js +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-query-select.js /** * WordPress dependencies */ @@ -7441,7 +7411,7 @@ return resolvers; }); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-record.js +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-record.js /** * WordPress dependencies */ @@ -7524,6 +7494,8 @@ * return ( *
* select(store).getEntityConfig(kind, name), [kind, name]); + const { + records: data, + ...ret + } = useEntityRecords(kind, name, queryArgs, options); + const ids = (0,external_wp_element_namespaceObject.useMemo)(() => { + var _data$map; + return (_data$map = data?.map( + // @ts-ignore + record => { + var _entityConfig$key; + return record[(_entityConfig$key = entityConfig?.key) !== null && _entityConfig$key !== void 0 ? _entityConfig$key : 'id']; + })) !== null && _data$map !== void 0 ? _data$map : []; + }, [data, entityConfig?.key]); + const permissions = (0,external_wp_data_namespaceObject.useSelect)(select => { + const { + getEntityRecordsPermissions + } = unlock(select(store)); + return getEntityRecordsPermissions(kind, name, ids); + }, [ids, kind, name]); + const dataWithPermissions = (0,external_wp_element_namespaceObject.useMemo)(() => { + var _data$map2; + return (_data$map2 = data?.map((record, index) => ({ + // @ts-ignore + ...record, + permissions: permissions[index] + }))) !== null && _data$map2 !== void 0 ? _data$map2 : []; + }, [data, permissions]); + return { + records: dataWithPermissions, + ...ret + }; +} + +;// external ["wp","warning"] +const external_wp_warning_namespaceObject = window["wp"]["warning"]; +var external_wp_warning_default = /*#__PURE__*/__webpack_require__.n(external_wp_warning_namespaceObject); +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-resource-permissions.js /** * WordPress dependencies */ + /** * Internal dependencies */ @@ -7731,15 +7745,17 @@ * * @since 6.1.0 Introduced in WordPress core. * - * @param resource The resource in question, e.g. media. - * @param id ID of a specific resource entry, if needed, e.g. 10. + * @param resource Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` + * or REST base as a string - `media`. + * @param id Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged + * when using an entity object as a resource to check permissions and will be ignored. * * @example * ```js * import { useResourcePermissions } from '@wordpress/core-data'; * * function PagesList() { - * const { canCreate, isResolving } = useResourcePermissions( 'pages' ); + * const { canCreate, isResolving } = useResourcePermissions( { kind: 'postType', name: 'page' } ); * * if ( isResolving ) { * return 'Loading ...'; @@ -7767,7 +7783,7 @@ * canUpdate, * canDelete, * isResolving - * } = useResourcePermissions( 'pages', pageId ); + * } = useResourcePermissions( { kind: 'postType', name: 'page', id: pageId } ); * * if ( isResolving ) { * return 'Loading ...'; @@ -7795,12 +7811,25 @@ * @template IdType */ function useResourcePermissions(resource, id) { + // Serialize `resource` to a string that can be safely used as a React dep. + // We can't just pass `resource` as one of the deps, because if it is passed + // as an object literal, then it will be a different object on each call even + // if the values remain the same. + const isEntity = typeof resource === 'object'; + const resourceAsString = isEntity ? JSON.stringify(resource) : resource; + if (isEntity && typeof id !== 'undefined') { + true ? external_wp_warning_default()(`When 'resource' is an entity object, passing 'id' as a separate argument isn't supported.`) : 0; + } return useQuerySelect(resolve => { + const hasId = isEntity ? !!resource.id : !!id; const { canUser } = resolve(store); - const create = canUser('create', resource); - if (!id) { + const create = canUser('create', isEntity ? { + kind: resource.kind, + name: resource.name + } : resource); + if (!hasId) { const read = canUser('read', resource); const isResolving = create.isResolving || read.isResolving; const hasResolved = create.hasResolved && read.hasResolved; @@ -7838,8 +7867,9 @@ canUpdate: hasResolved && update.data, canDelete: hasResolved && _delete.data }; - }, [resource, id]); -} + }, [resourceAsString, id]); +} +/* harmony default export */ const use_resource_permissions = (useResourcePermissions); function __experimentalUseResourcePermissions(resource, id) { external_wp_deprecated_default()(`wp.data.__experimentalUseResourcePermissions`, { alternative: 'wp.data.useResourcePermissions', @@ -7848,12 +7878,104 @@ return useResourcePermissions(resource, id); } -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/index.js - - - - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/index.js +;// external ["wp","blocks"] +const external_wp_blocks_namespaceObject = window["wp"]["blocks"]; +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-id.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + +/** + * Hook that returns the ID for the nearest + * provided entity of the specified type. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + */ +function useEntityId(kind, name) { + const context = (0,external_wp_element_namespaceObject.useContext)(EntityContext); + return context?.[kind]?.[name]; +} + +;// external ["wp","blockEditor"] +const external_wp_blockEditor_namespaceObject = window["wp"]["blockEditor"]; +;// ./node_modules/@wordpress/core-data/build-module/footnotes/get-rich-text-values-cached.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + +// TODO: The following line should have been: +// +// const unlockedApis = unlock( blockEditorPrivateApis ); +// +// But there are hidden circular dependencies in RNMobile code, specifically in +// certain native components in the `components` package that depend on +// `block-editor`. What follows is a workaround that defers the `unlock` call +// to prevent native code from failing. +// +// Fix once https://github.com/WordPress/gutenberg/issues/52692 is closed. +let unlockedApis; +const cache = new WeakMap(); +function getRichTextValuesCached(block) { + if (!unlockedApis) { + unlockedApis = unlock(external_wp_blockEditor_namespaceObject.privateApis); + } + if (!cache.has(block)) { + const values = unlockedApis.getRichTextValues([block]); + cache.set(block, values); + } + return cache.get(block); +} + +;// ./node_modules/@wordpress/core-data/build-module/footnotes/get-footnotes-order.js +/** + * Internal dependencies + */ + +const get_footnotes_order_cache = new WeakMap(); +function getBlockFootnotesOrder(block) { + if (!get_footnotes_order_cache.has(block)) { + const order = []; + for (const value of getRichTextValuesCached(block)) { + if (!value) { + continue; + } + + // replacements is a sparse array, use forEach to skip empty slots. + value.replacements.forEach(({ + type, + attributes + }) => { + if (type === 'core/footnote') { + order.push(attributes['data-fn']); + } + }); + } + get_footnotes_order_cache.set(block, order); + } + return get_footnotes_order_cache.get(block); +} +function getFootnotesOrder(blocks) { + // We can only separate getting order from blocks at the root level. For + // deeper inner blocks, this will not work since it's possible to have both + // inner blocks and block attributes, so order needs to be computed from the + // Edit functions as a whole. + return blocks.flatMap(getBlockFootnotesOrder); +} + +;// ./node_modules/@wordpress/core-data/build-module/footnotes/index.js /** * WordPress dependencies */ @@ -7863,6 +7985,332 @@ * Internal dependencies */ +let oldFootnotes = {}; +function updateFootnotesFromMeta(blocks, meta) { + const output = { + blocks + }; + if (!meta) { + return output; + } + + // If meta.footnotes is empty, it means the meta is not registered. + if (meta.footnotes === undefined) { + return output; + } + const newOrder = getFootnotesOrder(blocks); + const footnotes = meta.footnotes ? JSON.parse(meta.footnotes) : []; + const currentOrder = footnotes.map(fn => fn.id); + if (currentOrder.join('') === newOrder.join('')) { + return output; + } + const newFootnotes = newOrder.map(fnId => footnotes.find(fn => fn.id === fnId) || oldFootnotes[fnId] || { + id: fnId, + content: '' + }); + function updateAttributes(attributes) { + // Only attempt to update attributes, if attributes is an object. + if (!attributes || Array.isArray(attributes) || typeof attributes !== 'object') { + return attributes; + } + attributes = { + ...attributes + }; + for (const key in attributes) { + const value = attributes[key]; + if (Array.isArray(value)) { + attributes[key] = value.map(updateAttributes); + continue; + } + + // To do, remove support for string values? + if (typeof value !== 'string' && !(value instanceof external_wp_richText_namespaceObject.RichTextData)) { + continue; + } + const richTextValue = typeof value === 'string' ? external_wp_richText_namespaceObject.RichTextData.fromHTMLString(value) : new external_wp_richText_namespaceObject.RichTextData(value); + let hasFootnotes = false; + richTextValue.replacements.forEach(replacement => { + if (replacement.type === 'core/footnote') { + const id = replacement.attributes['data-fn']; + const index = newOrder.indexOf(id); + // The innerHTML contains the count wrapped in a link. + const countValue = (0,external_wp_richText_namespaceObject.create)({ + html: replacement.innerHTML + }); + countValue.text = String(index + 1); + countValue.formats = Array.from({ + length: countValue.text.length + }, () => countValue.formats[0]); + countValue.replacements = Array.from({ + length: countValue.text.length + }, () => countValue.replacements[0]); + replacement.innerHTML = (0,external_wp_richText_namespaceObject.toHTMLString)({ + value: countValue + }); + hasFootnotes = true; + } + }); + if (hasFootnotes) { + attributes[key] = typeof value === 'string' ? richTextValue.toHTMLString() : richTextValue; + } + } + return attributes; + } + function updateBlocksAttributes(__blocks) { + return __blocks.map(block => { + return { + ...block, + attributes: updateAttributes(block.attributes), + innerBlocks: updateBlocksAttributes(block.innerBlocks) + }; + }); + } + + // We need to go through all block attributes deeply and update the + // footnote anchor numbering (textContent) to match the new order. + const newBlocks = updateBlocksAttributes(blocks); + oldFootnotes = { + ...oldFootnotes, + ...footnotes.reduce((acc, fn) => { + if (!newOrder.includes(fn.id)) { + acc[fn.id] = fn; + } + return acc; + }, {}) + }; + return { + meta: { + ...meta, + footnotes: JSON.stringify(newFootnotes) + }, + blocks: newBlocks + }; +} + +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-block-editor.js +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + + +const use_entity_block_editor_EMPTY_ARRAY = []; +const parsedBlocksCache = new WeakMap(); + +/** + * Hook that returns block content getters and setters for + * the nearest provided entity of the specified type. + * + * The return value has the shape `[ blocks, onInput, onChange ]`. + * `onInput` is for block changes that don't create undo levels + * or dirty the post, non-persistent changes, and `onChange` is for + * persistent changes. They map directly to the props of a + * `BlockEditorProvider` and are intended to be used with it, + * or similar components or hooks. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + * @param {Object} options + * @param {string} [options.id] An entity ID to use instead of the context-provided one. + * + * @return {[unknown[], Function, Function]} The block array and setters. + */ +function useEntityBlockEditor(kind, name, { + id: _id +} = {}) { + const providerId = useEntityId(kind, name); + const id = _id !== null && _id !== void 0 ? _id : providerId; + const { + getEntityRecord, + getEntityRecordEdits + } = (0,external_wp_data_namespaceObject.useSelect)(STORE_NAME); + const { + content, + editedBlocks, + meta + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + if (!id) { + return {}; + } + const { + getEditedEntityRecord + } = select(STORE_NAME); + const editedRecord = getEditedEntityRecord(kind, name, id); + return { + editedBlocks: editedRecord.blocks, + content: editedRecord.content, + meta: editedRecord.meta + }; + }, [kind, name, id]); + const { + __unstableCreateUndoLevel, + editEntityRecord + } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); + const blocks = (0,external_wp_element_namespaceObject.useMemo)(() => { + if (!id) { + return undefined; + } + if (editedBlocks) { + return editedBlocks; + } + if (!content || typeof content !== 'string') { + return use_entity_block_editor_EMPTY_ARRAY; + } + + // If there's an edit, cache the parsed blocks by the edit. + // If not, cache by the original entity record. + const edits = getEntityRecordEdits(kind, name, id); + const isUnedited = !edits || !Object.keys(edits).length; + const cackeKey = isUnedited ? getEntityRecord(kind, name, id) : edits; + let _blocks = parsedBlocksCache.get(cackeKey); + if (!_blocks) { + _blocks = (0,external_wp_blocks_namespaceObject.parse)(content); + parsedBlocksCache.set(cackeKey, _blocks); + } + return _blocks; + }, [kind, name, id, editedBlocks, content, getEntityRecord, getEntityRecordEdits]); + const onChange = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { + const noChange = blocks === newBlocks; + if (noChange) { + return __unstableCreateUndoLevel(kind, name, id); + } + const { + selection, + ...rest + } = options; + + // We create a new function here on every persistent edit + // to make sure the edit makes the post dirty and creates + // a new undo level. + const edits = { + selection, + content: ({ + blocks: blocksForSerialization = [] + }) => (0,external_wp_blocks_namespaceObject.__unstableSerializeAndClean)(blocksForSerialization), + ...updateFootnotesFromMeta(newBlocks, meta) + }; + editEntityRecord(kind, name, id, edits, { + isCached: false, + ...rest + }); + }, [kind, name, id, blocks, meta, __unstableCreateUndoLevel, editEntityRecord]); + const onInput = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { + const { + selection, + ...rest + } = options; + const footnotesChanges = updateFootnotesFromMeta(newBlocks, meta); + const edits = { + selection, + ...footnotesChanges + }; + editEntityRecord(kind, name, id, edits, { + isCached: true, + ...rest + }); + }, [kind, name, id, meta, editEntityRecord]); + return [blocks, onInput, onChange]; +} + +;// ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-prop.js +/** + * WordPress dependencies + */ + + + +/** + * Internal dependencies + */ + + + +/** + * Hook that returns the value and a setter for the + * specified property of the nearest provided + * entity of the specified type. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + * @param {string} prop The property name. + * @param {number|string} [_id] An entity ID to use instead of the context-provided one. + * + * @return {[*, Function, *]} An array where the first item is the + * property value, the second is the + * setter and the third is the full value + * object from REST API containing more + * information like `raw`, `rendered` and + * `protected` props. + */ +function useEntityProp(kind, name, prop, _id) { + const providerId = useEntityId(kind, name); + const id = _id !== null && _id !== void 0 ? _id : providerId; + const { + value, + fullValue + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + const { + getEntityRecord, + getEditedEntityRecord + } = select(STORE_NAME); + const record = getEntityRecord(kind, name, id); // Trigger resolver. + const editedRecord = getEditedEntityRecord(kind, name, id); + return record && editedRecord ? { + value: editedRecord[prop], + fullValue: record[prop] + } : {}; + }, [kind, name, id, prop]); + const { + editEntityRecord + } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); + const setValue = (0,external_wp_element_namespaceObject.useCallback)(newValue => { + editEntityRecord(kind, name, id, { + [prop]: newValue + }); + }, [editEntityRecord, kind, name, id, prop]); + return [value, setValue, fullValue]; +} + +;// ./node_modules/@wordpress/core-data/build-module/hooks/index.js + + + + + + + +;// ./node_modules/@wordpress/core-data/build-module/private-apis.js +/** + * Internal dependencies + */ + + + +const privateApis = {}; +lock(privateApis, { + useEntityRecordsWithPermissions: useEntityRecordsWithPermissions, + RECEIVE_INTERMEDIATE_RESULTS: RECEIVE_INTERMEDIATE_RESULTS +}); + +;// ./node_modules/@wordpress/core-data/build-module/index.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + + @@ -7915,11 +8363,13 @@ const storeConfig = () => ({ reducer: build_module_reducer, actions: { + ...dynamicActions, ...build_module_actions_namespaceObject, ...entityActions, ...createLocksActions() }, selectors: { + ...dynamicSelectors, ...build_module_selectors_namespaceObject, ...entitySelectors }, @@ -7936,6 +8386,7 @@ */ const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, storeConfig()); unlock(store).registerPrivateSelectors(private_selectors_namespaceObject); +unlock(store).registerPrivateActions(private_actions_namespaceObject); (0,external_wp_data_namespaceObject.register)(store); // Register store after unlocking private selectors to allow resolvers to use them. @@ -7944,7 +8395,6 @@ -})(); (window.wp = window.wp || {}).coreData = __webpack_exports__; /******/ })()