: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @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.
* @param {WPLinkSearchOptions} [searchOptions]
* @param {WPEditorSettings} [settings]
* import { __experimentalFetchLinkSuggestions as fetchLinkSuggestions } from '@wordpress/core-data';
* export function initialize( id, settings ) {
* settings.__experimentalFetchLinkSuggestions = (
* ) => fetchLinkSuggestions( search, searchOptions, settings );
* @return {Promise< WPLinkSearchResult[] >} List of search suggestions
const fetchLinkSuggestions = async (search, searchOptions = {}, settings = {}) => {
isInitialSuggestions = false,
initialSuggestionsSearchOptions = undefined
disablePostFormats = false
perPage = isInitialSuggestions ? 3 : 20
/** @type {Promise<WPLinkSearchResult>[]} */
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', {
return results.map(result => {
}).catch(() => []) // Fail by returning no results.
if (!type || type === 'term') {
queries.push(external_wp_apiFetch_default()({
path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', {
return results.map(result => {
}).catch(() => []) // Fail by returning no results.
if (!disablePostFormats && (!type || type === 'post-format')) {
queries.push(external_wp_apiFetch_default()({
path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', {
return results.map(result => {
}).catch(() => []) // Fail by returning no results.
if (!type || type === 'attachment') {
queries.push(external_wp_apiFetch_default()({
path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/media', {
return results.map(result => {
}).catch(() => []) // Fail by returning no results.
return Promise.all(queries).then(results => {
return results.reduce(( /** @type {WPLinkSearchResult[]} */accumulator, current) => accumulator.concat(current),
* @param {{ id: number }} result
}).slice(0, perPage).map(( /** @type {WPLinkSearchResultAugmented} */result) => {
const isMedia = result.type === 'attachment';
// @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,
/* harmony default export */ const _experimental_fetch_link_suggestions = (fetchLinkSuggestions);
;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-url-data.js
* A simple in-memory cache for requests.
* This avoids repeat HTTP requests which may be beneficial
* for those wishing to preserve low-bandwidth.
* @typedef WPRemoteUrlData
* @property {string} title contents of the remote URL's `<title>` tag.
* Fetches data about a remote URL.
* eg: <title> tag, favicon...etc.
* @param {string} url the URL to request details from.
* @param {Object?} options any options to pass to the underlying fetch.
* import { __experimentalFetchUrlData as fetchUrlData } from '@wordpress/core-data';
* export function initialize( id, settings ) {
* settings.__experimentalFetchUrlData = (
* ) => fetchUrlData( url );
* @return {Promise< WPRemoteUrlData[] >} Remote URL data.
const fetchUrlData = async (url, options = {}) => {
const endpoint = '/wp-block-editor/v1/url-details';
url: (0,external_wp_url_namespaceObject.prependHTTP)(url)
if (!(0,external_wp_url_namespaceObject.isURL)(url)) {
return Promise.reject(`${url} is not a valid URL.`);
// Test for "http" based URL as it is possible for valid
// yet unusable URLs such as `tel:123456` to be passed.
const protocol = (0,external_wp_url_namespaceObject.getProtocol)(url);
if (!protocol || !(0,external_wp_url_namespaceObject.isValidProtocol)(protocol) || !protocol.startsWith('http') || !/^https?:\/\/[^\/\s]/i.test(url)) {
return Promise.reject(`${url} does not have a valid protocol. URLs must be "http" based`);
return external_wp_apiFetch_default()({
path: (0,external_wp_url_namespaceObject.addQueryArgs)(endpoint, args),
/* harmony default export */ const _experimental_fetch_url_data = (fetchUrlData);
;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/index.js
async function fetchBlockPatterns() {
const restPatterns = await external_wp_apiFetch_default()({
path: '/wp/v2/block-patterns/patterns'
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
* Requests authors from the REST API.
* @param {Object|undefined} query Optional object of query parameters to
const resolvers_getAuthors = query => async ({
const path = (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/users/?who=authors&per_page=100', query);
const users = await external_wp_apiFetch_default()({
dispatch.receiveUserQuery(path, users);
* Requests the current user from the REST API.
const resolvers_getCurrentUser = () => async ({
const currentUser = await external_wp_apiFetch_default()({
dispatch.receiveCurrentUser(currentUser);
* Requests an entity's record from the REST API.
* @param {string} kind Entity kind.
* @param {string} name Entity name.
* @param {number|string} key Record's key
* @param {Object|undefined} query Optional object of query parameters to
* include with request. If requesting specific
* fields, fields must always include the ID.
const resolvers_getEntityRecord = (kind, name, key = '', query) => async ({
const configs = await dispatch(getOrLoadEntitiesConfig(kind, name));
const entityConfig = configs.find(config => config.name === name && config.kind === kind);
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, key], {
// Entity supports configs,
// use the sync algorithm instead of the old fetch behavior.
if (window.__experimentalEnableSync && entityConfig.syncConfig && !query) {
if (query !== undefined && query._fields) {
// If requesting specific fields, items and query association to said
// records are stored by ID reference. Thus, fields must always include
_fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join()
// Disable reason: While true that an early return could leave `path`
// unused, it's important that path is derived using the query prior to
// additional query modifications in the condition below, since those
// modifications are relevant to how the data is tracked in state, and not
// for how the request is made to the REST API.
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL + (key ? '/' + key : ''), {
...entityConfig.baseURLParams,
if (query !== undefined) {
// The resolution cache won't consider query as reusable based on the
// fields, so it's tested here, prior to initiating the REST request,
// and without causing `getEntityRecords` resolution to occur.
const hasRecords = select.hasEntityRecords(kind, name, query);
const record = await external_wp_apiFetch_default()({
dispatch.receiveEntityRecords(kind, name, record, query);
dispatch.__unstableReleaseStoreLock(lock);
* Requests an entity's record from the REST API.
const resolvers_getRawEntityRecord = forward_resolver('getEntityRecord');
* Requests an entity's record from the REST API.
const resolvers_getEditedEntityRecord = forward_resolver('getEntityRecord');
* Requests the entity's records from the REST API.
* @param {string} kind Entity kind.
* @param {string} name Entity name.
* @param {Object?} query Query Object. If requesting specific fields, fields
* must always include the ID.
const resolvers_getEntityRecords = (kind, name, query = {}) => async ({
const configs = await dispatch(getOrLoadEntitiesConfig(kind, name));
const entityConfig = configs.find(config => config.name === name && config.kind === kind);
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name], {
// If requesting specific fields, items and query association to said
// records are stored by ID reference. Thus, fields must always include
_fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join()
const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL, {
...entityConfig.baseURLParams,
if (entityConfig.supportsPagination && query.per_page !== -1) {
const response = await external_wp_apiFetch_default()({
records = Object.values(await response.json());
totalItems: parseInt(response.headers.get('X-WP-Total')),
totalPages: parseInt(response.headers.get('X-WP-TotalPages'))
records = Object.values(await external_wp_apiFetch_default()({
// If we request fields but the result doesn't contain the fields,
// explicitly set these fields as "undefined"
// that way we consider the query "fulfilled".
records = records.map(record => {
query._fields.split(',').forEach(field => {
if (!record.hasOwnProperty(field)) {
record[field] = undefined;
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`.
// See https://github.com/WordPress/gutenberg/pull/26575
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]]);
type: 'START_RESOLUTIONS',
selectorName: 'getEntityRecord',
type: 'FINISH_RESOLUTIONS',