Snippets
Created by
Daniel Shaw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | <?php
/**
* Custom layout block support.
*
* @package Chthonic/Maisie
* @since 0.1.0
* @version 0.1.0
*
*/
/**
* Generates the CSS corresponding to the provided layout.
*
* @since 0.1.0
*
* @param string $selector CSS selector.
* @param array $layout Layout object.
*
* @return string CSS style.
*/
function maisie_get_layout_style( $selector, $layout, $has_block_gap_support = false ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
$style = '';
if ( 'default' === $layout_type ) {
$content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : null;
$wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : null;
$all_max_width_value = $content_size ? $content_size : $wide_size;
// Make sure there is a single CSS rule, and all tags are stripped for security.
// TODO: Use `safecss_filter_attr` instead - once https://core.trac.wordpress.org/ticket/46197 is patched.
$all_max_width_value = wp_strip_all_tags( explode( ';', $all_max_width_value )[0] );
$style = '';
if ( $content_size || $wide_size ) {
$style = "$selector {";
$style .= 'max-width: ' . esc_html( $all_max_width_value ) . ';';
$style .= 'margin-left: auto;';
$style .= 'margin-right: auto;';
$style .= 'width: 100%;';
$style .= '}';
$style .= "$selector.alignfull { grid-template-columns: 1fr min($all_max_width_value, calc(100% - var(--wp--custom--layout--margin))) 1fr; }";
$style .= ".alignfull $selector.alignfull > div { max-width: $all_max_width_value; }";
}
$style .= "$selector .alignleft { float: left; margin-right: 2em; }";
$style .= "$selector .alignright { float: right; margin-left: 2em; }";
} elseif ( 'flex' === $layout_type ) {
$layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';
$justify_content_options = array(
'left' => 'flex-start',
'right' => 'flex-end',
'center' => 'center',
);
if ( 'horizontal' === $layout_orientation ) {
$justify_content_options += array( 'space-between' => 'space-between' );
}
$flex_wrap_options = array( 'wrap', 'nowrap' );
$flex_wrap = ! empty( $layout['flexWrap'] ) && in_array( $layout['flexWrap'], $flex_wrap_options, true ) ?
$layout['flexWrap'] :
'wrap';
$style = "$selector {";
$style .= 'display: flex;';
$style .= 'gap: var(--wp--custom--spacing--block-gap--small);';
$style .= "flex-wrap: $flex_wrap;";
if ( 'horizontal' === $layout_orientation ) {
$style .= 'align-items: center;';
/**
* Add this style only if is not empty for backwards compatibility,
* since we intend to convert blocks that had flex layout implemented
* by custom css.
*/
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
$style .= "justify-content: {$justify_content_options[ $layout['justifyContent'] ]};";
if ( ! empty( $layout['setCascadingProperties'] ) && $layout['setCascadingProperties'] ) {
// --layout-justification-setting allows children to inherit the value regardless or row or column direction.
$style .= "--layout-justification-setting: {$justify_content_options[ $layout['justifyContent'] ]};";
$style .= '--layout-direction: row;';
$style .= "--layout-wrap: $flex_wrap;";
$style .= "--layout-justify: {$justify_content_options[ $layout['justifyContent'] ]};";
$style .= '--layout-align: center;';
}
}
} else {
$style .= 'flex-direction: column;';
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
$style .= "align-items: {$justify_content_options[ $layout['justifyContent'] ]};";
if ( ! empty( $layout['setCascadingProperties'] ) && $layout['setCascadingProperties'] ) {
// --layout-justification-setting allows children to inherit the value regardless or row or column direction.
$style .= "--layout-justification-setting: {$justify_content_options[ $layout['justifyContent'] ]};";
$style .= '--layout-direction: column;';
$style .= '--layout-justify: initial;';
$style .= "--layout-align: {$justify_content_options[ $layout['justifyContent'] ]};";
}
}
}
$style .= '}';
$style .= "$selector > * { margin: 0; }";
}
return $style;
}
/**
* Renders the layout config to the block wrapper. Layout config for this theme
* is based on CSS Grid, superseding the native max-width & left/right auto
* margins layout presumed by core/Gutenberg.
*
* Replaces core implementation at wp-includes/block-supports/layout.php.
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function maisie_render_layout_support_flag( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$support_layout = block_has_support( $block_type, array( '__experimentalLayout' ), false );
if ( ! $support_layout ) {
return $block_content;
}
$block_gap = wp_get_global_settings( array( 'spacing', 'blockGap' ) );
$default_layout = wp_get_global_settings( array( 'layout' ) );
$has_block_gap_support = isset( $block_gap ) ? null !== $block_gap : false;
$default_block_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout', 'default' ), array() );
$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $default_block_layout;
if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
if ( ! $default_layout ) {
return $block_content;
}
$used_layout = $default_layout;
}
$id = uniqid();
$style = maisie_get_layout_style( ".wp-container-$id", $used_layout, $has_block_gap_support );
// This assumes the hook only applies to blocks with a single wrapper.
// I think this is a reasonable limitation for that particular hook.
$content = preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="wp-container-' . $id . ' ',
$block_content,
1
);
// Ideally styles should be loaded in the head, but blocks may be parsed
// after that, so loading in the footer for now.
// See https://core.trac.wordpress.org/ticket/53494.
add_action(
'wp_head', // Opting to load in head, anyway...
function () use ( $style ) {
if ( $style ) { // Added by Maisie theme to prevent empty <style> tags.
echo '<style>' . $style . '</style>'; // phpcs:ignore.
}
}
);
return $content;
}
add_filter( 'render_block', 'maisie_render_layout_support_flag', 10, 2 );
// Remove the core and Gutenberg functions replaced by maisie_render_layout_support_flag().
if ( function_exists( 'maisie_render_layout_support_flag' ) ) {
remove_filter( 'render_block', 'wp_render_layout_support_flag', 10, 2 );
remove_filter( 'render_block', 'gutenberg_render_layout_support_flag', 10, 2 );
}
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.