: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (options.layoutStyles) {
/* Add alignment / layout styles */
ruleset = ruleset + '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
ruleset = ruleset + '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
ruleset = ruleset + '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
if (options.blockGap && hasBlockGapSupport) {
// Use fallback of `0.5em` just in case, however if there is blockGap support, there should nearly always be a real value.
const gapValue = getGapCSSValue(tree?.styles?.spacing?.blockGap) || '0.5em';
ruleset = ruleset + `:root :where(.wp-site-blocks) > * { margin-block-start: ${gapValue}; margin-block-end: 0; }`;
ruleset = ruleset + ':root :where(.wp-site-blocks) > :first-child { margin-block-start: 0; }';
ruleset = ruleset + ':root :where(.wp-site-blocks) > :last-child { margin-block-end: 0; }';
nodesWithSettings.forEach(({
if (ROOT_BLOCK_SELECTOR === selector || ROOT_CSS_PROPERTIES_SELECTOR === selector) {
// Do not add extra specificity for top-level classes.
const classes = getPresetsClasses(selector, presets);
if (classes.length > 0) {
function toSvgFilters(tree, blockSelectors) {
const nodesWithSettings = getNodesWithSettings(tree, blockSelectors);
return nodesWithSettings.flatMap(({
return getPresetsSvgFilters(presets);
const getSelectorsConfig = (blockType, rootSelector) => {
if (blockType?.selectors && Object.keys(blockType.selectors).length > 0) {
return blockType.selectors;
Object.entries(BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS).forEach(([featureKey, featureName]) => {
const featureSelector = getBlockCSSSelector(blockType, featureKey);
config[featureName] = featureSelector;
const getBlockSelectors = (blockTypes, getBlockStyles, variationInstanceId) => {
blockTypes.forEach(blockType => {
const name = blockType.name;
const selector = getBlockCSSSelector(blockType);
let duotoneSelector = getBlockCSSSelector(blockType, 'filter.duotone');
// Keep backwards compatibility for support.color.__experimentalDuotone.
const rootSelector = getBlockCSSSelector(blockType);
const duotoneSupport = (0,external_wp_blocks_namespaceObject.getBlockSupport)(blockType, 'color.__experimentalDuotone', false);
duotoneSelector = duotoneSupport && scopeSelector(rootSelector, duotoneSupport);
const hasLayoutSupport = !!blockType?.supports?.layout || !!blockType?.supports?.__experimentalLayout;
const fallbackGapValue = blockType?.supports?.spacing?.blockGap?.__experimentalDefault;
const blockStyleVariations = getBlockStyles(name);
const styleVariationSelectors = {};
blockStyleVariations?.forEach(variation => {
const variationSuffix = variationInstanceId ? `-${variationInstanceId}` : '';
const variationName = `${variation.name}${variationSuffix}`;
const styleVariationSelector = getBlockStyleVariationSelector(variationName, selector);
styleVariationSelectors[variationName] = styleVariationSelector;
// For each block support feature add any custom selectors.
const featureSelectors = getSelectorsConfig(blockType, selector);
featureSelectors: Object.keys(featureSelectors).length ? featureSelectors : undefined,
styleVariationSelectors: blockStyleVariations?.length ? styleVariationSelectors : undefined
* If there is a separator block whose color is defined in theme.json via background,
* update the separator color to the same value by using border color.
* @param {Object} config Theme.json configuration file object.
* @return {Object} configTheme.json configuration file object updated.
function updateConfigWithSeparator(config) {
const needsSeparatorStyleUpdate = config.styles?.blocks?.['core/separator'] && config.styles?.blocks?.['core/separator'].color?.background && !config.styles?.blocks?.['core/separator'].color?.text && !config.styles?.blocks?.['core/separator'].border?.color;
if (needsSeparatorStyleUpdate) {
...config.styles.blocks['core/separator'],
...config.styles.blocks['core/separator'].color,
text: config.styles?.blocks['core/separator'].color.background
function processCSSNesting(css, blockSelector) {
if (!css || css.trim() === '') {
// Split CSS nested rules.
const parts = css.split('&');
if (!part || part.trim() === '') {
const isRootCss = !part.includes('{');
// If the part doesn't contain braces, it applies to the root level.
processedCSS += `:root :where(${blockSelector}){${part.trim()}}`;
// If the part contains braces, it's a nested CSS rule.
const splittedPart = part.replace('}', '').split('{');
if (splittedPart.length !== 2) {
const [nestedSelector, cssValue] = splittedPart;
// Handle pseudo elements such as ::before, ::after, etc. Regex will also
// capture any leading combinator such as >, +, or ~, as well as spaces.
// This allows pseudo elements as descendants e.g. `.parent ::before`.
const matches = nestedSelector.match(/([>+~\s]*::[a-zA-Z-]+)/);
const pseudoPart = matches ? matches[1] : '';
const withoutPseudoElement = matches ? nestedSelector.replace(pseudoPart, '').trim() : nestedSelector.trim();
if (withoutPseudoElement === '') {
// Only contained a pseudo element to use the block selector to form
// the final `:root :where()` selector.
combinedSelector = blockSelector;
// If the nested selector is a descendant of the block scope it with the
// block selector. Otherwise append it to the block selector.
combinedSelector = nestedSelector.startsWith(' ') ? scopeSelector(blockSelector, withoutPseudoElement) : appendToSelector(blockSelector, withoutPseudoElement);
// Build final rule, re-adding any pseudo element outside the `:where()`
// to maintain valid CSS selector.
processedCSS += `:root :where(${combinedSelector})${pseudoPart}{${cssValue.trim()}}`;
* Returns the global styles output using a global styles configuration.
* If wishing to generate global styles and settings based on the
* global styles config loaded in the editor context, use `useGlobalStylesOutput()`.
* The use case for a custom config is to generate bespoke styles
* and settings for previews, or other out-of-editor experiences.
* @param {Object} mergedConfig Global styles configuration.
* @param {boolean} disableRootPadding Disable root padding styles.
* @return {Array} Array of stylesheets and settings.
function useGlobalStylesOutputWithConfig(mergedConfig = {}, disableRootPadding) {
const [blockGap] = useGlobalSetting('spacing.blockGap');
mergedConfig = setThemeFileUris(mergedConfig, mergedConfig?._links?.['wp:theme-file']);
const hasBlockGapSupport = blockGap !== null;
const hasFallbackGapSupport = !hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support.
const disableLayoutStyles = (0,external_wp_data_namespaceObject.useSelect)(select => {
return !!getSettings().disableLayoutStyles;
} = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blocks_namespaceObject.store);
return (0,external_wp_element_namespaceObject.useMemo)(() => {
var _updatedConfig$styles;
if (!mergedConfig?.styles || !mergedConfig?.settings) {
const updatedConfig = updateConfigWithSeparator(mergedConfig);
const blockSelectors = getBlockSelectors((0,external_wp_blocks_namespaceObject.getBlockTypes)(), getBlockStyles);
const customProperties = toCustomProperties(updatedConfig, blockSelectors);
const globalStyles = toStyles(updatedConfig, blockSelectors, hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, disableRootPadding);
const svgs = toSvgFilters(updatedConfig, blockSelectors);
// Load custom CSS in own stylesheet so that any invalid CSS entered in the input won't break all the global styles in the editor.
css: (_updatedConfig$styles = updatedConfig.styles.css) !== null && _updatedConfig$styles !== void 0 ? _updatedConfig$styles : '',
// Loop through the blocks to check if there are custom CSS values.
// If there are, get the block selector and push the selector together with
// the CSS value to the 'stylesheets' array.
(0,external_wp_blocks_namespaceObject.getBlockTypes)().forEach(blockType => {
if (updatedConfig.styles.blocks[blockType.name]?.css) {
const selector = blockSelectors[blockType.name].selector;
css: processCSSNesting(updatedConfig.styles.blocks[blockType.name]?.css, selector),
return [styles, updatedConfig.settings];
}, [hasBlockGapSupport, hasFallbackGapSupport, mergedConfig, disableLayoutStyles, disableRootPadding, getBlockStyles]);
* Returns the global styles output based on the current state of global styles config loaded in the editor context.
* @param {boolean} disableRootPadding Disable root padding styles.
* @return {Array} Array of stylesheets and settings.
function useGlobalStylesOutput(disableRootPadding = false) {
} = (0,external_wp_element_namespaceObject.useContext)(GlobalStylesContext);
return useGlobalStylesOutputWithConfig(mergedConfig, disableRootPadding);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/hooks/block-style-variation.js
const VARIATION_PREFIX = 'is-style-';
function getVariationMatches(className) {
return className.split(/\s+/).reduce((matches, name) => {
if (name.startsWith(VARIATION_PREFIX)) {
const match = name.slice(VARIATION_PREFIX.length);
if (match !== 'default') {
* Get the first block style variation that has been registered from the class string.
* @param {string} className CSS class string for a block.
* @param {Array} registeredStyles Currently registered block styles.
* @return {string|null} The name of the first registered variation.
function getVariationNameFromClass(className, registeredStyles = []) {
// The global flag affects how capturing groups work in JS. So the regex
// below will only return full CSS classes not just the variation name.
const matches = getVariationMatches(className);
for (const variation of matches) {
if (registeredStyles.some(style => style.name === variation)) {
// A helper component to apply a style override using the useStyleOverride hook.
function OverrideStyles({
useStyleOverride(override);
* This component is used to generate new block style variation overrides
* based on an incoming theme config. If a matching style is found in the config,
* a new override is created and returned. The overrides can be used in conjunction with
* useStyleOverride to apply the new styles to the editor. Its use is
* @param {Object} props Props.
* @param {Object} props.config A global styles object, containing settings and styles.
* @return {JSX.Element|undefined} An array of new block variation overrides.
function __unstableBlockStyleVariationOverridesWithConfig({
} = (0,external_wp_data_namespaceObject.useSelect)(select => ({
getBlockStyles: select(external_wp_blocks_namespaceObject.store).getBlockStyles,
overrides: unlock(select(store)).getStyleOverrides()
} = (0,external_wp_data_namespaceObject.useSelect)(store);
const overridesWithConfig = (0,external_wp_element_namespaceObject.useMemo)(() => {
if (!overrides?.length) {
const overriddenClientIds = [];
for (const [, override] of overrides) {
if (override?.variation && override?.clientId &&
* Because this component overwrites existing style overrides,
* filter out any overrides that are already present in the store.
!overriddenClientIds.includes(override.clientId)) {
const blockName = getBlockName(override.clientId);
const configStyles = config?.styles?.blocks?.[blockName]?.variations?.[override.variation];
const variationConfig = {
settings: config?.settings,
// The variation style data is all that is needed to generate
// the styles for the current application to a block. The variation
// name is updated to match the instance specific class name.
[`${override.variation}-${override.clientId}`]: configStyles
const blockSelectors = getBlockSelectors((0,external_wp_blocks_namespaceObject.getBlockTypes)(), getBlockStyles, override.clientId);
const hasBlockGapSupport = false;
const hasFallbackGapSupport = true;
const disableLayoutStyles = true;
const disableRootPadding = true;
const variationStyles = toStyles(variationConfig, blockSelectors, hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, disableRootPadding, {
id: `${override.variation}-${override.clientId}`,
__unstableType: 'variation',
variation: override.variation,
// The clientId will be stored with the override and used to ensure
// the order of overrides matches the order of blocks so that the
// correct CSS cascade is maintained.
clientId: override.clientId
overriddenClientIds.push(override.clientId);
}, [config, overrides, getBlockStyles, getBlockName]);
if (!overridesWithConfig || !overridesWithConfig.length) {
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, {
children: overridesWithConfig.map(override => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(OverrideStyles, {
* Retrieves any variation styles data and resolves any referenced values.
* @param {Object} globalStyles A complete global styles object, containing settings and styles.
* @param {string} name The name of the desired block type.
* @param {variation} variation The of the block style variation to retrieve data for.
* @return {Object|undefined} The global styles data for the specified variation.
function getVariationStylesWithRefValues(globalStyles, name, variation) {
if (!globalStyles?.styles?.blocks?.[name]?.variations?.[variation]) {
// Helper to recursively look for `ref` values to resolve.
const replaceRefs = variationStyles => {
Object.keys(variationStyles).forEach(key => {
const value = variationStyles[key];
if (typeof value === 'object' && value !== null) {
// Process `ref` value if present.
if (value.ref !== undefined) {
if (typeof value.ref !== 'string' || value.ref.trim() === '') {
delete variationStyles[key];
const refValue = getValueFromObjectPath(globalStyles, value.ref);
variationStyles[key] = refValue;
delete variationStyles[key];
// Recursively resolve `ref` values in nested objects.
// After recursion, if value is empty due to explicitly
// `undefined` ref value, remove it.
if (Object.keys(value).length === 0) {
delete variationStyles[key];
// Deep clone variation node to avoid mutating it within global styles and losing refs.
const styles = JSON.parse(JSON.stringify(globalStyles.styles.blocks[name].variations[variation]));
function useBlockStyleVariation(name, variation, clientId) {
// Prefer global styles data in GlobalStylesContext, which are available
// if in the site editor. Otherwise fall back to whatever is in the
// editor settings and available in the post editor.
} = (0,external_wp_element_namespaceObject.useContext)(GlobalStylesContext);
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
const settings = select(store).getSettings();
globalSettings: settings.__experimentalFeatures,
globalStyles: settings[globalStylesDataKey]
return (0,external_wp_element_namespaceObject.useMemo)(() => {
var _mergedConfig$setting, _mergedConfig$styles, _mergedConfig$setting2;
const variationStyles = getVariationStylesWithRefValues({
settings: (_mergedConfig$setting = mergedConfig?.settings) !== null && _mergedConfig$setting !== void 0 ? _mergedConfig$setting : globalSettings,
styles: (_mergedConfig$styles = mergedConfig?.styles) !== null && _mergedConfig$styles !== void 0 ? _mergedConfig$styles : globalStyles
settings: (_mergedConfig$setting2 = mergedConfig?.settings) !== null && _mergedConfig$setting2 !== void 0 ? _mergedConfig$setting2 : globalSettings,
// The variation style data is all that is needed to generate
// the styles for the current application to a block. The variation
// name is updated to match the instance specific class name.