@wordpress/block-library
Version:
Block library for the WordPress editor.
96 lines (92 loc) • 4.05 kB
JavaScript
/**
* WordPress dependencies
*/
import { escapeHTML } from '@wordpress/escape-html';
import { safeDecodeURI } from '@wordpress/url';
/**
* @typedef {'post-type'|'custom'|'taxonomy'|'post-type-archive'} WPNavigationLinkKind
*/
/**
* Navigation Link Block Attributes
*
* @typedef {Object} WPNavigationLinkBlockAttributes
*
* @property {string} [label] Link text.
* @property {WPNavigationLinkKind} [kind] Kind is used to differentiate between term and post ids to check post draft status.
* @property {string} [type] The type such as post, page, tag, category and other custom types.
* @property {string} [rel] The relationship of the linked URL.
* @property {number} [id] A post or term id.
* @property {boolean} [opensInNewTab] Sets link target to _blank when true.
* @property {string} [url] Link href.
* @property {string} [title] Link title attribute.
*/
/**
* Link Control onChange handler that updates block attributes when a setting is changed.
*
* @param {Object} updatedValue New block attributes to update.
* @param {Function} setAttributes Block attribute update function.
* @param {WPNavigationLinkBlockAttributes} blockAttributes Current block attributes.
*/
export const updateAttributes = (updatedValue = {}, setAttributes, blockAttributes = {}) => {
const {
label: originalLabel = '',
kind: originalKind = '',
type: originalType = ''
} = blockAttributes;
const {
title: newLabel = '',
// the title of any provided Post.
url: newUrl = '',
opensInNewTab,
id,
kind: newKind = originalKind,
type: newType = originalType
} = updatedValue;
const newLabelWithoutHttp = newLabel.replace(/http(s?):\/\//gi, '');
const newUrlWithoutHttp = newUrl.replace(/http(s?):\/\//gi, '');
const useNewLabel = newLabel && newLabel !== originalLabel &&
// LinkControl without the title field relies
// on the check below. Specifically, it assumes that
// the URL is the same as a title.
// This logic a) looks suspicious and b) should really
// live in the LinkControl and not here. It's a great
// candidate for future refactoring.
newLabelWithoutHttp !== newUrlWithoutHttp;
// Unfortunately this causes the escaping model to be inverted.
// The escaped content is stored in the block attributes (and ultimately in the database),
// and then the raw data is "recovered" when outputting into the DOM.
// It would be preferable to store the **raw** data in the block attributes and escape it in JS.
// Why? Because there isn't one way to escape data. Depending on the context, you need to do
// different transforms. It doesn't make sense to me to choose one of them for the purposes of storage.
// See also:
// - https://github.com/WordPress/gutenberg/pull/41063
// - https://github.com/WordPress/gutenberg/pull/18617.
const label = useNewLabel ? escapeHTML(newLabel) : originalLabel || escapeHTML(newUrlWithoutHttp);
// In https://github.com/WordPress/gutenberg/pull/24670 we decided to use "tag" in favor of "post_tag"
const type = newType === 'post_tag' ? 'tag' : newType.replace('-', '_');
const isBuiltInType = ['post', 'page', 'tag', 'category'].indexOf(type) > -1;
const isCustomLink = !newKind && !isBuiltInType || newKind === 'custom';
const kind = isCustomLink ? 'custom' : newKind;
setAttributes({
// Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string.
...(newUrl && {
url: encodeURI(safeDecodeURI(newUrl))
}),
...(label && {
label
}),
...(undefined !== opensInNewTab && {
opensInNewTab
}),
...(id && Number.isInteger(id) && {
id
}),
...(kind && {
kind
}),
...(type && type !== 'URL' && {
type
})
});
};
//# sourceMappingURL=update-attributes.js.map