From 6ae4acb4fa867fc7520c66dcb4920d5ade3fa6cb Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 29 Jun 2022 11:05:40 -0500 Subject: [PATCH 01/31] Added a new static block to test static context Co-authored-by: david.arenas@automattic.com --- block-hydration-experiments.php | 1 + .../block.json | 1 + src/blocks/static-block/block.json | 29 +++++++++++++++++++ src/blocks/static-block/edit.js | 13 +++++++++ src/blocks/static-block/index.js | 8 +++++ src/blocks/static-block/save.js | 10 +++++++ src/gutenberg-packages/wordpress-blocks.js | 4 ++- 7 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/blocks/static-block/block.json create mode 100644 src/blocks/static-block/edit.js create mode 100644 src/blocks/static-block/index.js create mode 100644 src/blocks/static-block/save.js diff --git a/block-hydration-experiments.php b/block-hydration-experiments.php index 4ee9f5af..9008d72c 100644 --- a/block-hydration-experiments.php +++ b/block-hydration-experiments.php @@ -12,6 +12,7 @@ function block_hydration_experiments_init() { register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/block-hydration-experiments-child/' ); register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/block-hydration-experiments-parent/' ); + register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/static-block/' ); } add_action( 'init', 'block_hydration_experiments_init' ); diff --git a/src/blocks/block-hydration-experiments-parent/block.json b/src/blocks/block-hydration-experiments-parent/block.json index 7fd50445..ea6370bd 100644 --- a/src/blocks/block-hydration-experiments-parent/block.json +++ b/src/blocks/block-hydration-experiments-parent/block.json @@ -32,6 +32,7 @@ "providesContext": { "message": "message" }, + "usesContext": ["bhe/content"], "textdomain": "block-hydration-experiments-parent", "editorScript": "file:./index.js", "editorStyle": "file:./index.css", diff --git a/src/blocks/static-block/block.json b/src/blocks/static-block/block.json new file mode 100644 index 00000000..1d17bff2 --- /dev/null +++ b/src/blocks/static-block/block.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "bhe/static-block", + "version": "0.1.0", + "title": "Static block", + "category": "text", + "icon": "flag", + "description": "", + "attributes": { + "content": { + "type": "string", + "default": "test value" + } + }, + "providesContext": { + "bhe/content": "content" + }, + "supports": { + "color": { + "text": true + }, + "html": true + }, + "textdomain": "static-block", + "editorScript": "file:./index.js", + "style": "file:./style-index.css", + "viewScript": "file:./view.js" +} diff --git a/src/blocks/static-block/edit.js b/src/blocks/static-block/edit.js new file mode 100644 index 00000000..fe39dd99 --- /dev/null +++ b/src/blocks/static-block/edit.js @@ -0,0 +1,13 @@ +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; + +const Edit = ( { attributes } ) => { + const blockProps = useBlockProps(); + return ( +
+

static block

+ +
+ ); +}; + +export default Edit; diff --git a/src/blocks/static-block/index.js b/src/blocks/static-block/index.js new file mode 100644 index 00000000..b6a32483 --- /dev/null +++ b/src/blocks/static-block/index.js @@ -0,0 +1,8 @@ +import { registerBlockType } from '@wordpress/blocks'; +import metadata from './block.json'; +import edit from './edit'; +import save from './save'; + +const { name } = metadata; + +registerBlockType( name, { edit, save } ); diff --git a/src/blocks/static-block/save.js b/src/blocks/static-block/save.js new file mode 100644 index 00000000..f65d678c --- /dev/null +++ b/src/blocks/static-block/save.js @@ -0,0 +1,10 @@ +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; + +const save = () => ( +
+

static block

+ +
+); + +export default save; diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 5f773730..3244f0d2 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -3,10 +3,12 @@ import { registerBlockType as gutenbergRegisterBlockType } from '@wordpress/bloc import { Fragment } from '@wordpress/element'; const save = ( name, Comp ) => - ( { attributes } ) => { + ( { attributes, context } ) => { const blockProps = useBlockProps.save(); const innerBlocksProps = useInnerBlocksProps.save(); + console.log( context ); + return ( From 3dafea234d020df78f522088ef4072879ddfa1c2 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 29 Jun 2022 11:05:40 -0500 Subject: [PATCH 02/31] Add view.js file to static-block and add frontend:true to attributes --- src/blocks/static-block/block.json | 3 ++- src/blocks/static-block/index.js | 6 +++--- src/blocks/static-block/view.js | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 src/blocks/static-block/view.js diff --git a/src/blocks/static-block/block.json b/src/blocks/static-block/block.json index 1d17bff2..d9f81a7f 100644 --- a/src/blocks/static-block/block.json +++ b/src/blocks/static-block/block.json @@ -10,7 +10,8 @@ "attributes": { "content": { "type": "string", - "default": "test value" + "default": "test value", + "frontend": true } }, "providesContext": { diff --git a/src/blocks/static-block/index.js b/src/blocks/static-block/index.js index b6a32483..db009aad 100644 --- a/src/blocks/static-block/index.js +++ b/src/blocks/static-block/index.js @@ -1,8 +1,8 @@ -import { registerBlockType } from '@wordpress/blocks'; +import { registerBlockType } from '../../gutenberg-packages/wordpress-blocks'; import metadata from './block.json'; import edit from './edit'; -import save from './save'; +import frontend from './save'; const { name } = metadata; -registerBlockType( name, { edit, save } ); +registerBlockType( name, { edit, frontend } ); diff --git a/src/blocks/static-block/view.js b/src/blocks/static-block/view.js new file mode 100644 index 00000000..3a5e56a4 --- /dev/null +++ b/src/blocks/static-block/view.js @@ -0,0 +1,4 @@ +import { registerBlockType } from '../../gutenberg-packages/frontend'; +import save from './save'; + +registerBlockType( 'bhe/static-block', save ); From 48c45fa4bf5c22cdcb0f5bd901724d8600464e82 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 29 Jun 2022 11:05:40 -0500 Subject: [PATCH 03/31] Remove the console.log(context) --- src/gutenberg-packages/wordpress-blocks.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 3244f0d2..5f773730 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -3,12 +3,10 @@ import { registerBlockType as gutenbergRegisterBlockType } from '@wordpress/bloc import { Fragment } from '@wordpress/element'; const save = ( name, Comp ) => - ( { attributes, context } ) => { + ( { attributes } ) => { const blockProps = useBlockProps.save(); const innerBlocksProps = useInnerBlocksProps.save(); - console.log( context ); - return ( From aa2b32afb7792ed410a40a72f867dae5746ffa51 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Mon, 4 Jul 2022 16:43:30 -0500 Subject: [PATCH 04/31] Remove unnecessary view file --- src/blocks/static-block/block.json | 3 +-- src/blocks/static-block/index.js | 6 +++--- src/blocks/static-block/view.js | 4 ---- 3 files changed, 4 insertions(+), 9 deletions(-) delete mode 100644 src/blocks/static-block/view.js diff --git a/src/blocks/static-block/block.json b/src/blocks/static-block/block.json index d9f81a7f..ca70ea5e 100644 --- a/src/blocks/static-block/block.json +++ b/src/blocks/static-block/block.json @@ -25,6 +25,5 @@ }, "textdomain": "static-block", "editorScript": "file:./index.js", - "style": "file:./style-index.css", - "viewScript": "file:./view.js" + "style": "file:./style-index.css" } diff --git a/src/blocks/static-block/index.js b/src/blocks/static-block/index.js index db009aad..b6a32483 100644 --- a/src/blocks/static-block/index.js +++ b/src/blocks/static-block/index.js @@ -1,8 +1,8 @@ -import { registerBlockType } from '../../gutenberg-packages/wordpress-blocks'; +import { registerBlockType } from '@wordpress/blocks'; import metadata from './block.json'; import edit from './edit'; -import frontend from './save'; +import save from './save'; const { name } = metadata; -registerBlockType( name, { edit, frontend } ); +registerBlockType( name, { edit, save } ); diff --git a/src/blocks/static-block/view.js b/src/blocks/static-block/view.js deleted file mode 100644 index 3a5e56a4..00000000 --- a/src/blocks/static-block/view.js +++ /dev/null @@ -1,4 +0,0 @@ -import { registerBlockType } from '../../gutenberg-packages/frontend'; -import save from './save'; - -registerBlockType( 'bhe/static-block', save ); From 1391bc6a2ac86dc288486fae0529e4cd6411a851 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 5 Jul 2022 14:16:08 -0500 Subject: [PATCH 05/31] Add context from static parent in bhe-child block --- src/blocks/block-hydration-experiments-child/edit.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/blocks/block-hydration-experiments-child/edit.js b/src/blocks/block-hydration-experiments-child/edit.js index fd282671..e51a5435 100644 --- a/src/blocks/block-hydration-experiments-child/edit.js +++ b/src/blocks/block-hydration-experiments-child/edit.js @@ -12,6 +12,8 @@ const Edit = ( { context } ) => {

Child element

{context?.message} + + {context &&
CONTEXT: {context['bhe/content'] || null}
}
); }; From 4a5dd5ac189fd388f2f8f559b65c1740d9122096 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 5 Jul 2022 14:16:29 -0500 Subject: [PATCH 06/31] Update block registation in static-block --- src/blocks/static-block/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/static-block/index.js b/src/blocks/static-block/index.js index b6a32483..b6dde4f6 100644 --- a/src/blocks/static-block/index.js +++ b/src/blocks/static-block/index.js @@ -1,4 +1,4 @@ -import { registerBlockType } from '@wordpress/blocks'; +import { registerBlockType } from '../../gutenberg-packages/wordpress-blocks'; import metadata from './block.json'; import edit from './edit'; import save from './save'; From 63e02cd84f7d7f79254795346055cb187031e80f Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 5 Jul 2022 18:47:15 -0500 Subject: [PATCH 07/31] Update the block schemas to include hydrate: true --- block-schema.json | 494 ++++++++++++++++++ .../block.json | 11 +- .../block.json | 7 +- 3 files changed, 509 insertions(+), 3 deletions(-) create mode 100644 block-schema.json diff --git a/block-schema.json b/block-schema.json new file mode 100644 index 00000000..c8b84e12 --- /dev/null +++ b/block-schema.json @@ -0,0 +1,494 @@ +{ + "title": "JSON schema for WordPress blocks", + "$schema": "http://json-schema.org/draft-04/schema#", + "definitions": { + "//": { + "reference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/", + "attributesReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/", + "contextReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/", + "supportsReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/", + "registerReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional" + } + }, + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "hydrate": { + "type": "boolean", + "description": "Whether the block should be hydrated", + "default": false + }, + "apiVersion": { + "type": "integer", + "description": "The version of the Block API used by the block. The most recent version is 2 and it was introduced in WordPress 5.6.\n\n See the the API versions documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/ for more details.", + "default": 1, + "enum": [1, 2] + }, + "name": { + "type": "string", + "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$", + "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme." + }, + "__experimental": { + "description": "The name of the experiment this block is a part of, or boolean true if there there is no specific experiment name.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "title": { + "type": "string", + "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name." + }, + "category": { + "description": "Blocks are grouped into categories to help users browse and discover them.\n Core provided categories are: text, media, design, widgets, theme, embed\n\nPlugins and Themes can also register custom block categories.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#managing-block-categories", + "anyOf": [ + { + "type": "string" + }, + { + "enum": [ + "text", + "media", + "design", + "widgets", + "theme", + "embed" + ] + } + ] + }, + "parent": { + "type": "array", + "description": "Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.", + "items": { + "type": "string" + } + }, + "ancestor": { + "type": "array", + "description": "The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block.", + "items": { + "type": "string" + } + }, + "icon": { + "type": "string", + "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts)." + }, + "description": { + "type": "string", + "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector." + }, + "keywords": { + "type": "array", + "description": "Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).", + "items": { + "type": "string" + } + }, + "version": { + "type": "string", + "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead." + }, + "textdomain": { + "type": "string", + "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/" + }, + "attributes": { + "type": "object", + "description": "Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.\n\nSee the attributes documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/ for more details.", + "patternProperties": { + "[a-zA-Z]": { + "type": "object", + "properties": { + "type": { + "description": "The type indicates the type of data that is stored by the attribute. It does not indicate where the data is stored, which is defined by the source field.\n\nA type is required, unless an enum is provided. A type can be used with an enum.\n\nNote that the validity of an object is determined by your source. For an example, see the query details below.", + "oneOf": [ + { + "type": "string", + "enum": [ + "null", + "boolean", + "object", + "array", + "string", + "integer", + "number" + ] + }, + { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "null", + "boolean", + "object", + "array", + "string", + "integer", + "number" + ] + } + } + ] + }, + "enum": { + "type": "array", + "description": "An attribute can be defined as one of a fixed set of values. This is specified by an enum, which contains an array of allowed values:", + "items": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "source": { + "type": "string", + "description": "Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.", + "enum": [ + "attribute", + "text", + "html", + "query", + "meta" + ] + }, + "selector": { + "type": "string", + "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class." + }, + "attribute": { + "type": "string", + "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup." + }, + "multiline": { + "type": "string", + "description": "Use the multiline property to extract the inner HTML of matching tag names for the use in RichText with the multiline prop." + }, + "query": { + "type": "object", + "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources." + }, + "meta": { + "type": "string", + "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/meta-block-3-add/" + }, + "default": { + "description": "A block attribute can contain a default value, which will be used if the type and source do not match anything within the block content.\n\nThe value is provided by the default field, and the value should match the expected format of the attribute." + } + }, + "required": ["type"] + } + }, + "additionalProperties": false + }, + "providesContext": { + "type": "object", + "description": "Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", + "patternProperties": { + "[a-zA-Z]": { + "type": "string" + } + } + }, + "usesContext": { + "type": "array", + "description": "Array of the names of context values to inherit from an ancestor provider.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", + "items": { + "type": "string" + } + }, + "supports": { + "type": "object", + "description": "It contains as set of options to control features used in the editor. See the the supports documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ for more details.", + "properties": { + "anchor": { + "type": "boolean", + "description": "Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link.", + "default": false + }, + "align": { + "default": false, + "description": "This property adds block controls which allow to change block’s alignment.", + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "wide", + "full", + "left", + "center", + "right" + ] + } + } + ] + }, + "alignWide": { + "type": "boolean", + "description": "This property allows to enable wide alignment for your theme. To disable this behavior for a single block, set this flag to false.", + "default": true + }, + "ariaLabel": { + "type": "boolean", + "description": "ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.", + "default": false + }, + "className": { + "type": "boolean", + "description": "By default, the class .wp-block-your-block-name is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.", + "default": true + }, + "color": { + "type": "object", + "description": "This value signals that a block supports some of the properties related to color. When it does, the block editor will show UI controls for the user to set their values.\n\nNote that the background and text keys have a default value of true, so if the color property is present they’ll also be considered enabled", + "properties": { + "background": { + "type": "boolean", + "description": "This property adds UI controls which allow the user to apply a solid background color to a block.\n\nWhen color support is declared, this property is enabled by default (along with text), so simply setting color will enable background color.\n\nTo disable background support while keeping other color supports enabled, set to false.\n\nWhen the block declares support for color.background, the attributes definition is extended to include two new attributes: backgroundColor and style", + "default": true + }, + "gradients": { + "type": "boolean", + "description": "This property adds UI controls which allow the user to apply a gradient background to a block.\n\nGradient presets are sourced from editor-gradient-presets theme support.\n\nWhen the block declares support for color.gradient, the attributes definition is extended to include two new attributes: gradient and style", + "default": false + }, + "link": { + "type": "boolean", + "description": "This property adds block controls which allow the user to set link color in a block, link color is disabled by default.\n\nLink color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.link, the attributes definition is extended to include two new attributes: linkColor and style", + "default": false + }, + "text": { + "type": "boolean", + "description": "This property adds block controls which allow the user to set text color in a block.\n\nWhen color support is declared, this property is enabled by default (along with background), so simply setting color will enable text color.\n\nText color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.text, the attributes definition is extended to include two new attributes: textColor and style", + "default": true + } + } + }, + "customClassName": { + "type": "boolean", + "description": "This property adds a field to define a custom className for the block’s wrapper.", + "default": true + }, + "defaultStylePicker": { + "type": "boolean", + "description": "When the style picker is shown, a dropdown is displayed so the user can select a default style for this block type. If you prefer not to show the dropdown, set this property to false.", + "default": true + }, + "html": { + "type": "boolean", + "description": "By default, a block’s markup can be edited individually. To disable this behavior, set html to false.", + "default": true + }, + "inserter": { + "type": "boolean", + "description": "By default, all blocks will appear in the inserter. To hide a block so that it can only be inserted programmatically, set inserter to false.", + "default": true + }, + "multiple": { + "type": "boolean", + "description": "A non-multiple block can be inserted into each post, one time only. For example, the built-in ‘More’ block cannot be inserted again if it already exists in the post being edited. A non-multiple block’s icon is automatically dimmed (unclickable) to prevent multiple instances.", + "default": true + }, + "reusable": { + "type": "boolean", + "description": "A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.", + "default": true + }, + "lock": { + "type": "boolean", + "description": "A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block 'Options' dropdown by default. To disable this behavior, set lock to false.", + "default": true + }, + "spacing": { + "type": "object", + "description": "This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values, if the theme declares support.\n\nWhen the block declares support for a specific spacing property, the attributes definition is extended to include the style attribute.", + "properties": { + "margin": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "top", + "right", + "left", + "bottom" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": ["vertical", "horizontal"] + } + } + ] + }, + "padding": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "top", + "right", + "left", + "bottom" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": ["vertical", "horizontal"] + } + } + ] + } + } + }, + "typography": { + "type": "object", + "description": "This value signals that a block supports some of the CSS style properties related to typography. When it does, the block editor will show UI controls for the user to set their values, if the theme declares support.\n\nWhen the block declares support for a specific typography property, the attributes definition is extended to include the style attribute.", + "properties": { + "fontSize": { + "type": "boolean", + "description": "This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.\n\nThe values shown in this control are the ones declared by the theme via the editor-font-sizes theme support, or the default ones if none is provided.\n\nWhen the block declares support for fontSize, the attributes definition is extended to include two new attributes: fontSize and style", + "default": false + }, + "lineHeight": { + "type": "boolean", + "description": "This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if the theme declares support.\n\nWhen the block declares support for lineHeight, the attributes definition is extended to include a new attribute style of object type with no default assigned. It stores the custom value set by the user. The block can apply a default style by specifying its own style attribute with a default", + "default": false + } + } + } + }, + "additionalProperties": true + }, + "styles": { + "type": "array", + "description": "Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.\n\nPlugins and Themes can also register custom block style for existing blocks.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#block-styles", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "label": { + "type": "string" + }, + "isDefault": { + "type": "boolean", + "default": false + } + }, + "required": ["name", "label"], + "additionalProperties": false + } + }, + "example": { + "type": "object", + "description": "It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.\n\nSee the the example documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional for more details.", + "properties": { + "viewportWidth": { + "type": "number", + "description": "The viewportWidth controls the width of the iFrame container in which the block preview will get rendered", + "default": 1200 + }, + "attributes": { + "type": "object", + "description": "Set the attribues for the block example" + }, + "innerBlocks": { + "type": "array", + "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this: \n\n [ [ 'core/heading', { content: 'This is an Example' }, [] ] ]\n\n Where each block itself is an array that contains the block name, the block attributes, and the blocks inner blocks." + } + } + }, + "editorScript": { + "type": "string", + "description": "Block type editor script definition. It will only be enqueued in the context of the editor." + }, + "script": { + "type": "string", + "description": "Block type frontend and editor script definition. It will be enqueued both in the editor and when viewing the content on the front of the site." + }, + "viewScript": { + "description": "Block type frontend script definition. It will be enqueued only when viewing the content on the front of the site.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "editorStyle": { + "description": "Block type editor style definition. It will only be enqueued in the context of the editor.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "style": { + "description": "Block type frontend style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "required": ["name", "title"], + "additionalProperties": false +} diff --git a/src/blocks/block-hydration-experiments-child/block.json b/src/blocks/block-hydration-experiments-child/block.json index ff300949..fb2c9b8c 100644 --- a/src/blocks/block-hydration-experiments-child/block.json +++ b/src/blocks/block-hydration-experiments-child/block.json @@ -1,5 +1,5 @@ { - "$schema": "https://schemas.wp.org/trunk/block.json", + "$schema": "../../../block-schema.json", "apiVersion": 2, "name": "bhe/block-hydration-experiments-child", "version": "0.1.0", @@ -7,7 +7,14 @@ "category": "text", "icon": "flag", "description": "", - "usesContext": ["message"], + "hydrate": true, + "attributes": { + "hydrate": { + "type": "boolean", + "default": true + } + }, + "usesContext": ["message", "bhe/content"], "supports": { "color": { "text": true diff --git a/src/blocks/block-hydration-experiments-parent/block.json b/src/blocks/block-hydration-experiments-parent/block.json index ea6370bd..1bf8eb35 100644 --- a/src/blocks/block-hydration-experiments-parent/block.json +++ b/src/blocks/block-hydration-experiments-parent/block.json @@ -1,5 +1,5 @@ { - "$schema": "https://schemas.wp.org/trunk/block.json", + "$schema": "../../../block-schema.json", "apiVersion": 2, "name": "bhe/block-hydration-experiments-parent", "version": "0.1.0", @@ -7,7 +7,12 @@ "category": "text", "icon": "flag", "description": "", + "hydrate": true, "attributes": { + "hydrate": { + "type": "boolean", + "default": true + }, "counter": { "type": "number", "default": 0, From e3b04807b6d2ff9098c63e7225c8c0dff04a39fb Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 5 Jul 2022 18:49:14 -0500 Subject: [PATCH 08/31] Serialize/deserialize context --- .../block-hydration-experiments-child/edit.js | 7 +- .../frontend.js | 5 ++ src/gutenberg-packages/frontend.js | 10 ++- src/gutenberg-packages/wordpress-blocks.js | 77 ++++++++++++++++++- 4 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/blocks/block-hydration-experiments-child/edit.js b/src/blocks/block-hydration-experiments-child/edit.js index e51a5435..db6637eb 100644 --- a/src/blocks/block-hydration-experiments-child/edit.js +++ b/src/blocks/block-hydration-experiments-child/edit.js @@ -12,8 +12,11 @@ const Edit = ( { context } ) => {

Child element

{context?.message} - - {context &&
CONTEXT: {context['bhe/content'] || null}
} + {context && ( +
+ static context: {context['bhe/content']} +
+ )}
); }; diff --git a/src/blocks/block-hydration-experiments-child/frontend.js b/src/blocks/block-hydration-experiments-child/frontend.js index 3e14ce0c..9785e8c2 100644 --- a/src/blocks/block-hydration-experiments-child/frontend.js +++ b/src/blocks/block-hydration-experiments-child/frontend.js @@ -3,6 +3,11 @@ const Frontend = ( { blockProps, context } ) => {

Child element

{context?.message} + {context && ( +
+ static context: {context['bhe/content']} +
+ )}
); }; diff --git a/src/gutenberg-packages/frontend.js b/src/gutenberg-packages/frontend.js index f2b19d2d..bbf0f5b5 100644 --- a/src/gutenberg-packages/frontend.js +++ b/src/gutenberg-packages/frontend.js @@ -27,7 +27,6 @@ const Children = ( { value, providedContext } ) => { if ( el !== null ) { // listen for the ping from the child el.addEventListener( 'gutenberg-context', ( event ) => { - event.stopPropagation(); event.detail.context = providedContext; } ); } @@ -122,3 +121,12 @@ class GutenbergBlock extends HTMLElement { if ( customElements.get( 'gutenberg-interactive-block' ) === undefined ) { customElements.define( 'gutenberg-interactive-block', GutenbergBlock ); } + +window.addEventListener( 'DOMContentLoaded', () => { + document.querySelectorAll( 'static-context' ).forEach( ( el ) => { + el.addEventListener( 'gutenberg-context', ( event ) => { + const context = JSON.parse( el.attributes.context.value ); + event.detail.context = { ...event?.detail?.context, ...context }; + } ); + } ); +} ); diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 5f773730..450a73aa 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -1,6 +1,10 @@ import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; -import { registerBlockType as gutenbergRegisterBlockType } from '@wordpress/blocks'; +import { + getBlockType, + registerBlockType as gutenbergRegisterBlockType, +} from '@wordpress/blocks'; import { Fragment } from '@wordpress/element'; +import { pickKeys } from './utils'; const save = ( name, Comp ) => ( { attributes } ) => { @@ -21,10 +25,77 @@ const save = ( name, Comp ) => ); }; -export const registerBlockType = ( name, { frontend, edit, ...rest } ) => { +const saveWithStaticContext = ( name, blockSave ) => + ( { attributes } ) => { + const blockProps = useBlockProps.save(); + const innerBlocksProps = useInnerBlocksProps.save(); + const blockType = getBlockType( name ); + + // We use the presence of any attribute with `frontend: true` as a signal + // here that the block should pass some context on the frontend as well. + // + // TODO: This should probably be optimized when merged into gutenberg so + // that we don't run this check for EVERY save() of every block. + const hasFrontendAttributes = Object.values( blockType?.attributes ).some( + attribute => attribute?.frontend + ); + + if ( !attributes?.hydrate && hasFrontendAttributes ) { + // Only add the attributes that are explicitly declared with `frontend: true` + let frontendAttributes = {}; + for ( const [ key, value ] of Object.entries( blockType?.attributes ) ) { + if ( + value?.frontend && Object + .values( blockType?.providesContext ) + .includes( key ) + ) { + frontendAttributes[key] = attributes[key]; + } + } + + // Pick the attributes that are explicitly declared in the block's `providesContext`. + let context = blockType?.providesContext && + pickKeys( + frontendAttributes, + Object.values( blockType?.providesContext ), + ); + + // Rename the attributes to match the context names. + for ( const value of Object.keys( context ) ) { + const key = Object.keys( blockType?.providesContext ).find(key => + blockType?.providesContext[key] === value + ); + if ( key ) { + context[key] = context[value]; + delete context[value]; + } + } + + return ( + +
+
+
+ + ); + } + + return ( +
+
+
+ ); + }; + +export const registerBlockType = ( + name, + { frontend, save: blockSave, edit, ...rest }, +) => { gutenbergRegisterBlockType( name, { edit, - save: save( name, frontend ), + save: blockSave ? + saveWithStaticContext( name, blockSave ) : + save( name, frontend ), ...rest, } ); }; From 1fcf22a3f7376e7e3ba402518ea5c994f8bd580d Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 5 Jul 2022 18:49:49 -0500 Subject: [PATCH 09/31] Add RichText fields to change context in editor --- src/blocks/static-block/block.json | 3 ++- src/blocks/static-block/edit.js | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/blocks/static-block/block.json b/src/blocks/static-block/block.json index ca70ea5e..426172ee 100644 --- a/src/blocks/static-block/block.json +++ b/src/blocks/static-block/block.json @@ -10,7 +10,8 @@ "attributes": { "content": { "type": "string", - "default": "test value", + "source": "text", + "selector": ".content", "frontend": true } }, diff --git a/src/blocks/static-block/edit.js b/src/blocks/static-block/edit.js index fe39dd99..bb665f05 100644 --- a/src/blocks/static-block/edit.js +++ b/src/blocks/static-block/edit.js @@ -1,10 +1,22 @@ import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { RichText } from '../../gutenberg-packages/wordpress-blockeditor'; -const Edit = ( { attributes } ) => { +const Edit = ( { attributes, setAttributes } ) => { const blockProps = useBlockProps(); return (
-

static block

+
+ We can use the "content" field below to change the value of the context +
+ setAttributes( { content: val } )} + placeholder='Enter the content' + value={attributes.content} + > + {attributes.content} +
); From 82db94a2c8b0172d87a1cd943c1d0931f7b0c998 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 6 Jul 2022 19:40:06 -0500 Subject: [PATCH 10/31] Add display:contents to static-context --- src/blocks/static-block/style.scss | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/blocks/static-block/style.scss diff --git a/src/blocks/static-block/style.scss b/src/blocks/static-block/style.scss new file mode 100644 index 00000000..3af574a5 --- /dev/null +++ b/src/blocks/static-block/style.scss @@ -0,0 +1,3 @@ +static-context { + display: contents; +} From d3b5ba4808bb2e6d70e7b448a72d005ba700ecff Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 6 Jul 2022 19:40:45 -0500 Subject: [PATCH 11/31] Remove the text from --- src/blocks/static-block/edit.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/blocks/static-block/edit.js b/src/blocks/static-block/edit.js index bb665f05..82f9b5d1 100644 --- a/src/blocks/static-block/edit.js +++ b/src/blocks/static-block/edit.js @@ -5,9 +5,6 @@ const Edit = ( { attributes, setAttributes } ) => { const blockProps = useBlockProps(); return (
-
- We can use the "content" field below to change the value of the context -
Date: Wed, 6 Jul 2022 19:41:51 -0500 Subject: [PATCH 12/31] Block context: support nesting & initially hidden blocks --- src/gutenberg-packages/frontend.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/gutenberg-packages/frontend.js b/src/gutenberg-packages/frontend.js index bbf0f5b5..dd3ec344 100644 --- a/src/gutenberg-packages/frontend.js +++ b/src/gutenberg-packages/frontend.js @@ -27,7 +27,10 @@ const Children = ( { value, providedContext } ) => { if ( el !== null ) { // listen for the ping from the child el.addEventListener( 'gutenberg-context', ( event ) => { - event.detail.context = providedContext; + event.detail.context = { + ...providedContext, + ...event?.detail?.context, + }; } ); } }} @@ -113,6 +116,17 @@ class GutenbergBlock extends HTMLElement { } } +class StaticContext extends HTMLElement { + connectedCallback() { + setTimeout( () => { + this.addEventListener( 'gutenberg-context', ( event ) => { + const context = JSON.parse( this.attributes.context.value ); + event.detail.context = { ...context, ...event?.detail?.context }; + } ); + } ); + } +} + // We need to wrap the element registration code in a conditional for the same // reason we assing `blockTypes` to window (see top of the file). // @@ -121,12 +135,6 @@ class GutenbergBlock extends HTMLElement { if ( customElements.get( 'gutenberg-interactive-block' ) === undefined ) { customElements.define( 'gutenberg-interactive-block', GutenbergBlock ); } - -window.addEventListener( 'DOMContentLoaded', () => { - document.querySelectorAll( 'static-context' ).forEach( ( el ) => { - el.addEventListener( 'gutenberg-context', ( event ) => { - const context = JSON.parse( el.attributes.context.value ); - event.detail.context = { ...event?.detail?.context, ...context }; - } ); - } ); -} ); +if ( customElements.get( 'static-context' ) === undefined ) { + customElements.define( 'static-context', StaticContext ); +} From 680270ecc7439ea2f0bc68cb31684072512217a2 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 12 Jul 2022 16:09:37 -0500 Subject: [PATCH 13/31] Remove useless editorStyles --- src/blocks/block-hydration-experiments-parent/block.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/blocks/block-hydration-experiments-parent/block.json b/src/blocks/block-hydration-experiments-parent/block.json index 1bf8eb35..bedc17b6 100644 --- a/src/blocks/block-hydration-experiments-parent/block.json +++ b/src/blocks/block-hydration-experiments-parent/block.json @@ -40,7 +40,6 @@ "usesContext": ["bhe/content"], "textdomain": "block-hydration-experiments-parent", "editorScript": "file:./index.js", - "editorStyle": "file:./index.css", "style": "file:./style-index.css", "viewScript": "file:./view.js" } From 50a861142f42a0d7e9228df679ca180fddb2e72b Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 12 Jul 2022 16:10:19 -0500 Subject: [PATCH 14/31] Import style.css in index.js of static-block --- src/blocks/static-block/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blocks/static-block/index.js b/src/blocks/static-block/index.js index b6dde4f6..32d00c22 100644 --- a/src/blocks/static-block/index.js +++ b/src/blocks/static-block/index.js @@ -2,6 +2,7 @@ import { registerBlockType } from '../../gutenberg-packages/wordpress-blocks'; import metadata from './block.json'; import edit from './edit'; import save from './save'; +import './style.scss'; const { name } = metadata; From 7afec630862c573bc896eaf947e038ef89e0f488 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Tue, 12 Jul 2022 16:10:42 -0500 Subject: [PATCH 15/31] Improve styling of all blocks --- .../block-hydration-experiments-child/edit.js | 13 ++++++++----- .../frontend.js | 13 ++++++++----- .../style.scss | 16 +++++++++++++++- .../edit.js | 2 +- .../shared/title.js | 2 +- .../style.scss | 16 +++++++++++++++- src/blocks/static-block/edit.js | 4 ++-- src/blocks/static-block/style.scss | 19 +++++++++++++++++++ 8 files changed, 69 insertions(+), 16 deletions(-) diff --git a/src/blocks/block-hydration-experiments-child/edit.js b/src/blocks/block-hydration-experiments-child/edit.js index db6637eb..adbbe8fd 100644 --- a/src/blocks/block-hydration-experiments-child/edit.js +++ b/src/blocks/block-hydration-experiments-child/edit.js @@ -10,12 +10,15 @@ const Edit = ( { context } ) => { return (
-

Child element

- {context?.message} {context && ( -
- static context: {context['bhe/content']} -
+ <> +
+ context from the interactive parent: {context?.message} +
+
+ context from non-interactive parent: {context['bhe/content']} +
+ )}
); diff --git a/src/blocks/block-hydration-experiments-child/frontend.js b/src/blocks/block-hydration-experiments-child/frontend.js index 9785e8c2..a3bafcec 100644 --- a/src/blocks/block-hydration-experiments-child/frontend.js +++ b/src/blocks/block-hydration-experiments-child/frontend.js @@ -1,12 +1,15 @@ const Frontend = ( { blockProps, context } ) => { return (
-

Child element

- {context?.message} {context && ( -
- static context: {context['bhe/content']} -
+ <> +
+ context from the interactive parent: {context?.message} +
+
+ context from non-interactive parent: {context['bhe/content']} +
+ )}
); diff --git a/src/blocks/block-hydration-experiments-child/style.scss b/src/blocks/block-hydration-experiments-child/style.scss index caff100f..9816a2d2 100644 --- a/src/blocks/block-hydration-experiments-child/style.scss +++ b/src/blocks/block-hydration-experiments-child/style.scss @@ -1,6 +1,20 @@ .wp-block-bhe-block-hydration-experiments-child { padding: 15px 10px 15px 50px; - background-color: rgb(238, 237, 237); + border: 1px solid rgb(255, 162, 0); + position: relative; +} + +.wp-block-bhe-block-hydration-experiments-child::before { + position: absolute; + top: 0; + right: 0; + border: 1px solid rgb(255, 162, 0); + background-color: rgb(255, 162, 0); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 9px; + content: "BHE - Child"; } gutenberg-block, diff --git a/src/blocks/block-hydration-experiments-parent/edit.js b/src/blocks/block-hydration-experiments-parent/edit.js index 0c498b52..da376213 100644 --- a/src/blocks/block-hydration-experiments-parent/edit.js +++ b/src/blocks/block-hydration-experiments-parent/edit.js @@ -18,7 +18,7 @@ export default function Edit( setAttributes( { message: val } )} - placeholder='Enter the Title' + placeholder='This will be passed through context to child blocks' /> <Button /> <button onClick={() => setAttributes( { counter: counter + 1 } )}> diff --git a/src/blocks/block-hydration-experiments-parent/shared/title.js b/src/blocks/block-hydration-experiments-parent/shared/title.js index 2370939a..5609b0cc 100644 --- a/src/blocks/block-hydration-experiments-parent/shared/title.js +++ b/src/blocks/block-hydration-experiments-parent/shared/title.js @@ -1,7 +1,7 @@ import { RichText } from '../../../gutenberg-packages/wordpress-blockeditor'; const Title = ( { message, ...props } ) => ( - <RichText tagName='h2' className='title' {...props}>{message}</RichText> + <RichText tagName='h4' className='title' {...props}>{message}</RichText> ); export default Title; diff --git a/src/blocks/block-hydration-experiments-parent/style.scss b/src/blocks/block-hydration-experiments-parent/style.scss index 06eda5a8..a22ddf4f 100644 --- a/src/blocks/block-hydration-experiments-parent/style.scss +++ b/src/blocks/block-hydration-experiments-parent/style.scss @@ -1,6 +1,20 @@ .wp-block-bhe-block-hydration-experiments-parent { padding: 15px 10px 15px 50px; - background-color: rgb(238, 237, 237); + border: 1px solid rgb(31, 185, 64); + position: relative; +} + +.wp-block-bhe-block-hydration-experiments-parent::before { + position: absolute; + top: 0; + right: 0; + background-color: rgb(31, 185, 64); + border: 1px solid rgb(31, 185, 64); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 10px; + content: "BHE - Parent"; } gutenberg-block, diff --git a/src/blocks/static-block/edit.js b/src/blocks/static-block/edit.js index 82f9b5d1..94069981 100644 --- a/src/blocks/static-block/edit.js +++ b/src/blocks/static-block/edit.js @@ -6,10 +6,10 @@ const Edit = ( { attributes, setAttributes } ) => { return ( <div {...blockProps}> <RichText - tagName='h3' + tagName='h4' className='content' onChange={( val ) => setAttributes( { content: val } )} - placeholder='Enter the content' + placeholder='This will be passed through context to child blocks' value={attributes.content} > {attributes.content} diff --git a/src/blocks/static-block/style.scss b/src/blocks/static-block/style.scss index 3af574a5..5d19b80c 100644 --- a/src/blocks/static-block/style.scss +++ b/src/blocks/static-block/style.scss @@ -1,3 +1,22 @@ +.wp-block-bhe-static-block { + border: 1px solid rgb(34, 168, 235); + position: relative; + padding: 25px 10px; +} + +.wp-block-bhe-static-block::before { + content: "BHE - Static (non-interactive) Block"; + position: absolute; + top: 0; + right: 0; + border: 1px solid rgb(34, 168, 235); + background-color: rgb(34, 168, 235); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 10px; +} + static-context { display: contents; } From 907d7a002d5450d972a178d4c1d2292e2be967c7 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski <mmczaplinski@gmail.com> Date: Tue, 12 Jul 2022 18:53:12 -0500 Subject: [PATCH 16/31] Pass content to save() and fix inner blockSave --- src/blocks/static-block/edit.js | 4 ++-- src/blocks/static-block/save.js | 4 ++-- src/gutenberg-packages/wordpress-blocks.js | 26 ++++++++-------------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/blocks/static-block/edit.js b/src/blocks/static-block/edit.js index 94069981..69a30d89 100644 --- a/src/blocks/static-block/edit.js +++ b/src/blocks/static-block/edit.js @@ -10,9 +10,9 @@ const Edit = ( { attributes, setAttributes } ) => { className='content' onChange={( val ) => setAttributes( { content: val } )} placeholder='This will be passed through context to child blocks' - value={attributes.content} + value={attributes?.content} > - {attributes.content} + {attributes?.content} </RichText> <InnerBlocks /> </div> diff --git a/src/blocks/static-block/save.js b/src/blocks/static-block/save.js index f65d678c..d9b8eda7 100644 --- a/src/blocks/static-block/save.js +++ b/src/blocks/static-block/save.js @@ -1,8 +1,8 @@ import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; -const save = () => ( +const save = ( { attributes } ) => ( <div {...useBlockProps.save()}> - <p>static block</p> + <p className='content'>{attributes?.content}</p> <InnerBlocks.Content /> </div> ); diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 450a73aa..658e0ce4 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -25,21 +25,19 @@ const save = ( name, Comp ) => ); }; -const saveWithStaticContext = ( name, blockSave ) => +const saveWithStaticContext = ( name, BlockSave ) => ( { attributes } ) => { - const blockProps = useBlockProps.save(); - const innerBlocksProps = useInnerBlocksProps.save(); const blockType = getBlockType( name ); - // We use the presence of any attribute with `frontend: true` as a signal - // here that the block should pass some context on the frontend as well. - // // TODO: This should probably be optimized when merged into gutenberg so // that we don't run this check for EVERY save() of every block. const hasFrontendAttributes = Object.values( blockType?.attributes ).some( attribute => attribute?.frontend ); + // We use the presence of any attribute with `frontend: true` as a signal + // here that the block should pass some context on the frontend as well. + // if ( !attributes?.hydrate && hasFrontendAttributes ) { // Only add the attributes that are explicitly declared with `frontend: true` let frontendAttributes = {}; @@ -73,28 +71,22 @@ const saveWithStaticContext = ( name, blockSave ) => return ( <static-context context={JSON.stringify( context )}> - <div {...blockProps}> - <div {...innerBlocksProps} /> - </div> + <BlockSave attributes={attributes} /> </static-context> ); } - return ( - <div {...blockProps}> - <div {...innerBlocksProps} /> - </div> - ); + return <BlockSave attributes={attributes} />; }; export const registerBlockType = ( name, - { frontend, save: blockSave, edit, ...rest }, + { frontend, save: BlockSave, edit, ...rest }, ) => { gutenbergRegisterBlockType( name, { edit, - save: blockSave ? - saveWithStaticContext( name, blockSave ) : + save: BlockSave ? + saveWithStaticContext( name, BlockSave ) : save( name, frontend ), ...rest, } ); From 5f5108dc170eb890da833ff05bf08f3407301447 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski <mmczaplinski@gmail.com> Date: Tue, 12 Jul 2022 19:17:12 -0500 Subject: [PATCH 17/31] Add better comments --- src/gutenberg-packages/frontend.js | 5 +++++ src/gutenberg-packages/wordpress-blocks.js | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gutenberg-packages/frontend.js b/src/gutenberg-packages/frontend.js index dd3ec344..84f212cf 100644 --- a/src/gutenberg-packages/frontend.js +++ b/src/gutenberg-packages/frontend.js @@ -27,6 +27,8 @@ const Children = ( { value, providedContext } ) => { if ( el !== null ) { // listen for the ping from the child el.addEventListener( 'gutenberg-context', ( event ) => { + // We have to also destructure `event.detail.context` because there can + // already exist a property in the context with the same name. event.detail.context = { ...providedContext, ...event?.detail?.context, @@ -121,6 +123,9 @@ class StaticContext extends HTMLElement { setTimeout( () => { this.addEventListener( 'gutenberg-context', ( event ) => { const context = JSON.parse( this.attributes.context.value ); + + // We have to also destructure `event.detail.context` because there can + // already exist a property in the context with the same name. event.detail.context = { ...context, ...event?.detail?.context }; } ); } ); diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 658e0ce4..9a5dc5e6 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -37,7 +37,6 @@ const saveWithStaticContext = ( name, BlockSave ) => // We use the presence of any attribute with `frontend: true` as a signal // here that the block should pass some context on the frontend as well. - // if ( !attributes?.hydrate && hasFrontendAttributes ) { // Only add the attributes that are explicitly declared with `frontend: true` let frontendAttributes = {}; From f6f6f4ea221a93dc32b954b203b6542b30d8b836 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski <mmczaplinski@gmail.com> Date: Tue, 12 Jul 2022 19:29:20 -0500 Subject: [PATCH 18/31] Remove unnecessary comment --- src/gutenberg-packages/wordpress-blocks.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index 9a5dc5e6..c273db7b 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -35,9 +35,7 @@ const saveWithStaticContext = ( name, BlockSave ) => attribute => attribute?.frontend ); - // We use the presence of any attribute with `frontend: true` as a signal - // here that the block should pass some context on the frontend as well. - if ( !attributes?.hydrate && hasFrontendAttributes ) { + if ( hasFrontendAttributes ) { // Only add the attributes that are explicitly declared with `frontend: true` let frontendAttributes = {}; for ( const [ key, value ] of Object.entries( blockType?.attributes ) ) { From dec23e8190f138641c31f213bbecfde7e9147e81 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski <mmczaplinski@gmail.com> Date: Tue, 12 Jul 2022 19:33:00 -0500 Subject: [PATCH 19/31] Remove the `hydrate: true` --- block-schema.json | 494 ------------------ .../block.json | 9 +- .../block.json | 7 +- 3 files changed, 2 insertions(+), 508 deletions(-) delete mode 100644 block-schema.json diff --git a/block-schema.json b/block-schema.json deleted file mode 100644 index c8b84e12..00000000 --- a/block-schema.json +++ /dev/null @@ -1,494 +0,0 @@ -{ - "title": "JSON schema for WordPress blocks", - "$schema": "http://json-schema.org/draft-04/schema#", - "definitions": { - "//": { - "reference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/", - "attributesReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/", - "contextReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/", - "supportsReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/", - "registerReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional" - } - }, - "type": "object", - "properties": { - "$schema": { - "type": "string" - }, - "hydrate": { - "type": "boolean", - "description": "Whether the block should be hydrated", - "default": false - }, - "apiVersion": { - "type": "integer", - "description": "The version of the Block API used by the block. The most recent version is 2 and it was introduced in WordPress 5.6.\n\n See the the API versions documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/ for more details.", - "default": 1, - "enum": [1, 2] - }, - "name": { - "type": "string", - "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$", - "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme." - }, - "__experimental": { - "description": "The name of the experiment this block is a part of, or boolean true if there there is no specific experiment name.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "boolean" - } - ] - }, - "title": { - "type": "string", - "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name." - }, - "category": { - "description": "Blocks are grouped into categories to help users browse and discover them.\n Core provided categories are: text, media, design, widgets, theme, embed\n\nPlugins and Themes can also register custom block categories.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#managing-block-categories", - "anyOf": [ - { - "type": "string" - }, - { - "enum": [ - "text", - "media", - "design", - "widgets", - "theme", - "embed" - ] - } - ] - }, - "parent": { - "type": "array", - "description": "Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.", - "items": { - "type": "string" - } - }, - "ancestor": { - "type": "array", - "description": "The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block.", - "items": { - "type": "string" - } - }, - "icon": { - "type": "string", - "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts)." - }, - "description": { - "type": "string", - "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector." - }, - "keywords": { - "type": "array", - "description": "Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).", - "items": { - "type": "string" - } - }, - "version": { - "type": "string", - "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead." - }, - "textdomain": { - "type": "string", - "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/" - }, - "attributes": { - "type": "object", - "description": "Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.\n\nSee the attributes documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/ for more details.", - "patternProperties": { - "[a-zA-Z]": { - "type": "object", - "properties": { - "type": { - "description": "The type indicates the type of data that is stored by the attribute. It does not indicate where the data is stored, which is defined by the source field.\n\nA type is required, unless an enum is provided. A type can be used with an enum.\n\nNote that the validity of an object is determined by your source. For an example, see the query details below.", - "oneOf": [ - { - "type": "string", - "enum": [ - "null", - "boolean", - "object", - "array", - "string", - "integer", - "number" - ] - }, - { - "type": "array", - "uniqueItems": true, - "items": { - "type": "string", - "enum": [ - "null", - "boolean", - "object", - "array", - "string", - "integer", - "number" - ] - } - } - ] - }, - "enum": { - "type": "array", - "description": "An attribute can be defined as one of a fixed set of values. This is specified by an enum, which contains an array of allowed values:", - "items": { - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - } - ] - } - }, - "source": { - "type": "string", - "description": "Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.", - "enum": [ - "attribute", - "text", - "html", - "query", - "meta" - ] - }, - "selector": { - "type": "string", - "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class." - }, - "attribute": { - "type": "string", - "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup." - }, - "multiline": { - "type": "string", - "description": "Use the multiline property to extract the inner HTML of matching tag names for the use in RichText with the multiline prop." - }, - "query": { - "type": "object", - "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources." - }, - "meta": { - "type": "string", - "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/meta-block-3-add/" - }, - "default": { - "description": "A block attribute can contain a default value, which will be used if the type and source do not match anything within the block content.\n\nThe value is provided by the default field, and the value should match the expected format of the attribute." - } - }, - "required": ["type"] - } - }, - "additionalProperties": false - }, - "providesContext": { - "type": "object", - "description": "Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", - "patternProperties": { - "[a-zA-Z]": { - "type": "string" - } - } - }, - "usesContext": { - "type": "array", - "description": "Array of the names of context values to inherit from an ancestor provider.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", - "items": { - "type": "string" - } - }, - "supports": { - "type": "object", - "description": "It contains as set of options to control features used in the editor. See the the supports documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ for more details.", - "properties": { - "anchor": { - "type": "boolean", - "description": "Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link.", - "default": false - }, - "align": { - "default": false, - "description": "This property adds block controls which allow to change block’s alignment.", - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "array", - "items": { - "type": "string", - "enum": [ - "wide", - "full", - "left", - "center", - "right" - ] - } - } - ] - }, - "alignWide": { - "type": "boolean", - "description": "This property allows to enable wide alignment for your theme. To disable this behavior for a single block, set this flag to false.", - "default": true - }, - "ariaLabel": { - "type": "boolean", - "description": "ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.", - "default": false - }, - "className": { - "type": "boolean", - "description": "By default, the class .wp-block-your-block-name is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.", - "default": true - }, - "color": { - "type": "object", - "description": "This value signals that a block supports some of the properties related to color. When it does, the block editor will show UI controls for the user to set their values.\n\nNote that the background and text keys have a default value of true, so if the color property is present they’ll also be considered enabled", - "properties": { - "background": { - "type": "boolean", - "description": "This property adds UI controls which allow the user to apply a solid background color to a block.\n\nWhen color support is declared, this property is enabled by default (along with text), so simply setting color will enable background color.\n\nTo disable background support while keeping other color supports enabled, set to false.\n\nWhen the block declares support for color.background, the attributes definition is extended to include two new attributes: backgroundColor and style", - "default": true - }, - "gradients": { - "type": "boolean", - "description": "This property adds UI controls which allow the user to apply a gradient background to a block.\n\nGradient presets are sourced from editor-gradient-presets theme support.\n\nWhen the block declares support for color.gradient, the attributes definition is extended to include two new attributes: gradient and style", - "default": false - }, - "link": { - "type": "boolean", - "description": "This property adds block controls which allow the user to set link color in a block, link color is disabled by default.\n\nLink color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.link, the attributes definition is extended to include two new attributes: linkColor and style", - "default": false - }, - "text": { - "type": "boolean", - "description": "This property adds block controls which allow the user to set text color in a block.\n\nWhen color support is declared, this property is enabled by default (along with background), so simply setting color will enable text color.\n\nText color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.text, the attributes definition is extended to include two new attributes: textColor and style", - "default": true - } - } - }, - "customClassName": { - "type": "boolean", - "description": "This property adds a field to define a custom className for the block’s wrapper.", - "default": true - }, - "defaultStylePicker": { - "type": "boolean", - "description": "When the style picker is shown, a dropdown is displayed so the user can select a default style for this block type. If you prefer not to show the dropdown, set this property to false.", - "default": true - }, - "html": { - "type": "boolean", - "description": "By default, a block’s markup can be edited individually. To disable this behavior, set html to false.", - "default": true - }, - "inserter": { - "type": "boolean", - "description": "By default, all blocks will appear in the inserter. To hide a block so that it can only be inserted programmatically, set inserter to false.", - "default": true - }, - "multiple": { - "type": "boolean", - "description": "A non-multiple block can be inserted into each post, one time only. For example, the built-in ‘More’ block cannot be inserted again if it already exists in the post being edited. A non-multiple block’s icon is automatically dimmed (unclickable) to prevent multiple instances.", - "default": true - }, - "reusable": { - "type": "boolean", - "description": "A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.", - "default": true - }, - "lock": { - "type": "boolean", - "description": "A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block 'Options' dropdown by default. To disable this behavior, set lock to false.", - "default": true - }, - "spacing": { - "type": "object", - "description": "This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values, if the theme declares support.\n\nWhen the block declares support for a specific spacing property, the attributes definition is extended to include the style attribute.", - "properties": { - "margin": { - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "array", - "items": { - "type": "string", - "enum": [ - "top", - "right", - "left", - "bottom" - ] - } - }, - { - "type": "array", - "items": { - "type": "string", - "enum": ["vertical", "horizontal"] - } - } - ] - }, - "padding": { - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "array", - "items": { - "type": "string", - "enum": [ - "top", - "right", - "left", - "bottom" - ] - } - }, - { - "type": "array", - "items": { - "type": "string", - "enum": ["vertical", "horizontal"] - } - } - ] - } - } - }, - "typography": { - "type": "object", - "description": "This value signals that a block supports some of the CSS style properties related to typography. When it does, the block editor will show UI controls for the user to set their values, if the theme declares support.\n\nWhen the block declares support for a specific typography property, the attributes definition is extended to include the style attribute.", - "properties": { - "fontSize": { - "type": "boolean", - "description": "This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.\n\nThe values shown in this control are the ones declared by the theme via the editor-font-sizes theme support, or the default ones if none is provided.\n\nWhen the block declares support for fontSize, the attributes definition is extended to include two new attributes: fontSize and style", - "default": false - }, - "lineHeight": { - "type": "boolean", - "description": "This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if the theme declares support.\n\nWhen the block declares support for lineHeight, the attributes definition is extended to include a new attribute style of object type with no default assigned. It stores the custom value set by the user. The block can apply a default style by specifying its own style attribute with a default", - "default": false - } - } - } - }, - "additionalProperties": true - }, - "styles": { - "type": "array", - "description": "Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.\n\nPlugins and Themes can also register custom block style for existing blocks.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#block-styles", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "label": { - "type": "string" - }, - "isDefault": { - "type": "boolean", - "default": false - } - }, - "required": ["name", "label"], - "additionalProperties": false - } - }, - "example": { - "type": "object", - "description": "It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.\n\nSee the the example documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional for more details.", - "properties": { - "viewportWidth": { - "type": "number", - "description": "The viewportWidth controls the width of the iFrame container in which the block preview will get rendered", - "default": 1200 - }, - "attributes": { - "type": "object", - "description": "Set the attribues for the block example" - }, - "innerBlocks": { - "type": "array", - "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this: \n\n [ [ 'core/heading', { content: 'This is an Example' }, [] ] ]\n\n Where each block itself is an array that contains the block name, the block attributes, and the blocks inner blocks." - } - } - }, - "editorScript": { - "type": "string", - "description": "Block type editor script definition. It will only be enqueued in the context of the editor." - }, - "script": { - "type": "string", - "description": "Block type frontend and editor script definition. It will be enqueued both in the editor and when viewing the content on the front of the site." - }, - "viewScript": { - "description": "Block type frontend script definition. It will be enqueued only when viewing the content on the front of the site.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "editorStyle": { - "description": "Block type editor style definition. It will only be enqueued in the context of the editor.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "style": { - "description": "Block type frontend style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } - }, - "required": ["name", "title"], - "additionalProperties": false -} diff --git a/src/blocks/block-hydration-experiments-child/block.json b/src/blocks/block-hydration-experiments-child/block.json index fb2c9b8c..30d18642 100644 --- a/src/blocks/block-hydration-experiments-child/block.json +++ b/src/blocks/block-hydration-experiments-child/block.json @@ -1,5 +1,5 @@ { - "$schema": "../../../block-schema.json", + "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, "name": "bhe/block-hydration-experiments-child", "version": "0.1.0", @@ -7,13 +7,6 @@ "category": "text", "icon": "flag", "description": "", - "hydrate": true, - "attributes": { - "hydrate": { - "type": "boolean", - "default": true - } - }, "usesContext": ["message", "bhe/content"], "supports": { "color": { diff --git a/src/blocks/block-hydration-experiments-parent/block.json b/src/blocks/block-hydration-experiments-parent/block.json index bedc17b6..a8abb074 100644 --- a/src/blocks/block-hydration-experiments-parent/block.json +++ b/src/blocks/block-hydration-experiments-parent/block.json @@ -1,5 +1,5 @@ { - "$schema": "../../../block-schema.json", + "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, "name": "bhe/block-hydration-experiments-parent", "version": "0.1.0", @@ -7,12 +7,7 @@ "category": "text", "icon": "flag", "description": "", - "hydrate": true, "attributes": { - "hydrate": { - "type": "boolean", - "default": true - }, "counter": { "type": "number", "default": 0, From 1f3002950d844a8002a39c346155b9a2db1aec4e Mon Sep 17 00:00:00 2001 From: Michal Czaplinski <mmczaplinski@gmail.com> Date: Wed, 13 Jul 2022 17:16:57 -0500 Subject: [PATCH 20/31] Remove setTimeout from the static-context element --- src/gutenberg-packages/frontend.js | 12 +++++------- src/gutenberg-packages/wordpress-blocks.js | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/gutenberg-packages/frontend.js b/src/gutenberg-packages/frontend.js index 84f212cf..d22a8af7 100644 --- a/src/gutenberg-packages/frontend.js +++ b/src/gutenberg-packages/frontend.js @@ -120,14 +120,12 @@ class GutenbergBlock extends HTMLElement { class StaticContext extends HTMLElement { connectedCallback() { - setTimeout( () => { - this.addEventListener( 'gutenberg-context', ( event ) => { - const context = JSON.parse( this.attributes.context.value ); + this.addEventListener( 'gutenberg-context', ( event ) => { + const context = JSON.parse( this.attributes.context.value ); - // We have to also destructure `event.detail.context` because there can - // already exist a property in the context with the same name. - event.detail.context = { ...context, ...event?.detail?.context }; - } ); + // We have to also destructure `event.detail.context` because there can + // already exist a property in the context with the same name. + event.detail.context = { ...context, ...event?.detail?.context }; } ); } } diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index c273db7b..92b97624 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -35,8 +35,8 @@ const saveWithStaticContext = ( name, BlockSave ) => attribute => attribute?.frontend ); + // Only add the attributes that are explicitly declared with `frontend: true` if ( hasFrontendAttributes ) { - // Only add the attributes that are explicitly declared with `frontend: true` let frontendAttributes = {}; for ( const [ key, value ] of Object.entries( blockType?.attributes ) ) { if ( From e3c14914cc064e3a39eea553051655f82f7ea378 Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Fri, 22 Jul 2022 17:31:17 +0200 Subject: [PATCH 21/31] Fix serialization and event name --- src/gutenberg-packages/frontend.js | 2 +- src/gutenberg-packages/wordpress-blocks.js | 24 +++++++--------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/gutenberg-packages/frontend.js b/src/gutenberg-packages/frontend.js index 92bc3306..f884dab1 100644 --- a/src/gutenberg-packages/frontend.js +++ b/src/gutenberg-packages/frontend.js @@ -164,7 +164,7 @@ class GutenbergBlock extends HTMLElement { class StaticContext extends HTMLElement { connectedCallback() { - this.addEventListener("gutenberg-context", (event) => { + this.addEventListener("gutenberg-block-context", (event) => { const context = JSON.parse(this.attributes.context.value); // We have to also destructure `event.detail.context` because there can // already exist a property in the context with the same name. diff --git a/src/gutenberg-packages/wordpress-blocks.js b/src/gutenberg-packages/wordpress-blocks.js index c1c5a267..b234e599 100644 --- a/src/gutenberg-packages/wordpress-blocks.js +++ b/src/gutenberg-packages/wordpress-blocks.js @@ -3,7 +3,6 @@ import { getBlockType, registerBlockType as gutenbergRegisterBlockType, } from "@wordpress/blocks"; -import { pickKeys } from "./utils"; const save = (Comp) => ({ attributes }) => { const blockProps = useBlockProps.save(); @@ -42,24 +41,15 @@ const saveWithStaticContext = (name, BlockSave) => ({ attributes }) => { } } - // Pick the attributes that are explicitly declared in the block's `providesContext`. - let context = - blockType?.providesContext && - pickKeys(frontendAttributes, Object.values(blockType?.providesContext)); - - // Rename the attributes to match the context names. - for (const value of Object.keys(context)) { - const key = Object.keys(blockType?.providesContext).find( - (key) => blockType?.providesContext[key] === value - ); - if (key) { - context[key] = context[value]; - delete context[value]; - } - } + // Pick the attributes that are explicitly declared in the block's + // `providesContext`. + const providedContext = {}; + Object.entries(blockType.providesContext).forEach(([key, attribute]) => { + providedContext[key] = frontendAttributes[attribute]; + }); return ( - <static-context context={JSON.stringify(context)}> + <static-context context={JSON.stringify(providedContext)}> <BlockSave attributes={attributes} /> </static-context> ); From 3a21b5c3d25a9c53a47b52ff6032901cbd53e165 Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Fri, 22 Jul 2022 17:31:26 +0200 Subject: [PATCH 22/31] Rename Static block to match the others --- src/blocks/static-block/block.json | 56 +++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/blocks/static-block/block.json b/src/blocks/static-block/block.json index 426172ee..497bd90e 100644 --- a/src/blocks/static-block/block.json +++ b/src/blocks/static-block/block.json @@ -1,30 +1,30 @@ { - "$schema": "https://schemas.wp.org/trunk/block.json", - "apiVersion": 2, - "name": "bhe/static-block", - "version": "0.1.0", - "title": "Static block", - "category": "text", - "icon": "flag", - "description": "", - "attributes": { - "content": { - "type": "string", - "source": "text", - "selector": ".content", - "frontend": true - } - }, - "providesContext": { - "bhe/content": "content" - }, - "supports": { - "color": { - "text": true - }, - "html": true - }, - "textdomain": "static-block", - "editorScript": "file:./index.js", - "style": "file:./style-index.css" + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "bhe/static-block", + "version": "0.1.0", + "title": "BHE - Static", + "category": "text", + "icon": "flag", + "description": "", + "attributes": { + "content": { + "type": "string", + "source": "text", + "selector": ".content", + "frontend": true + } + }, + "providesContext": { + "bhe/content": "content" + }, + "supports": { + "color": { + "text": true + }, + "html": true + }, + "textdomain": "static-block", + "editorScript": "file:./index.js", + "style": "file:./style-index.css" } From fc6fa92f96f0e60f093605449c45d4157927b3c1 Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Mon, 25 Jul 2022 11:43:00 +0200 Subject: [PATCH 23/31] Refactor block naming --- block-hydration-experiments.php | 12 +-- .../edit.js | 32 ------ .../block.json | 8 +- .../edit.js | 23 ++--- .../frontend.js | 10 +- .../index.js | 2 +- .../style.scss | 8 +- .../view.js | 2 +- .../block.json | 12 +-- src/blocks/interactive-parent/edit.js | 29 ++++++ .../frontend.js} | 15 +-- .../index.js | 2 +- .../shared/button.js | 0 .../shared/title.js | 4 +- .../style.scss | 8 +- .../view.js | 2 +- src/blocks/non-interactive-parent/block.json | 30 ++++++ src/blocks/non-interactive-parent/edit.js | 18 ++++ .../index.js | 0 .../save.js | 4 +- src/blocks/non-interactive-parent/style.scss | 22 +++++ src/blocks/static-block/block.json | 30 ------ src/blocks/static-block/edit.js | 22 ----- src/blocks/static-block/style.scss | 22 ----- src/gutenberg-packages/wordpress-blocks.js | 99 ++++++++++--------- 25 files changed, 207 insertions(+), 209 deletions(-) delete mode 100644 src/blocks/block-hydration-experiments-parent/edit.js rename src/blocks/{block-hydration-experiments-child => interactive-child}/block.json (66%) rename src/blocks/{block-hydration-experiments-child => interactive-child}/edit.js (52%) rename src/blocks/{block-hydration-experiments-child => interactive-child}/frontend.js (67%) rename src/blocks/{block-hydration-experiments-child => interactive-child}/index.js (81%) rename src/blocks/{block-hydration-experiments-child => interactive-child}/style.scss (68%) rename src/blocks/{block-hydration-experiments-child => interactive-child}/view.js (78%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/block.json (73%) create mode 100644 src/blocks/interactive-parent/edit.js rename src/blocks/{block-hydration-experiments-parent/frontend/index.js => interactive-parent/frontend.js} (60%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/index.js (81%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/shared/button.js (100%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/shared/title.js (75%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/style.scss (67%) rename src/blocks/{block-hydration-experiments-parent => interactive-parent}/view.js (78%) create mode 100644 src/blocks/non-interactive-parent/block.json create mode 100644 src/blocks/non-interactive-parent/edit.js rename src/blocks/{static-block => non-interactive-parent}/index.js (100%) rename src/blocks/{static-block => non-interactive-parent}/save.js (64%) create mode 100644 src/blocks/non-interactive-parent/style.scss delete mode 100644 src/blocks/static-block/block.json delete mode 100644 src/blocks/static-block/edit.js delete mode 100644 src/blocks/static-block/style.scss diff --git a/block-hydration-experiments.php b/block-hydration-experiments.php index 3a1f08f9..29e60c53 100644 --- a/block-hydration-experiments.php +++ b/block-hydration-experiments.php @@ -10,9 +10,9 @@ * Text Domain: block-hydration-experiments */ function block_hydration_experiments_init() { - register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/block-hydration-experiments-child/' ); - register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/block-hydration-experiments-parent/' ); - register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/static-block/' ); + register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/interactive-child/' ); + register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/interactive-parent/' ); + register_block_type( plugin_dir_path( __FILE__ ) . 'build/blocks/non-interactive-parent/' ); } add_action( 'init', 'block_hydration_experiments_init' ); @@ -21,8 +21,8 @@ function bhe_block_wrapper( $block_content, $block, $instance ) { if ( ! in_array( $block['blockName'], array( - 'bhe/block-hydration-experiments-parent', - 'bhe/block-hydration-experiments-child' + 'bhe/interactive-parent', + 'bhe/interactive-child' ), true ) ) { @@ -70,7 +70,7 @@ function bhe_block_wrapper( $block_content, $block, $instance ) { $empty_template = sprintf( $template_wrapper, '' ); $template = sprintf( $template_wrapper, sprintf( $block_wrapper, $block_content . $empty_template ) ); - return sprintf( $block_wrapper, $block_content . $template ); + return sprintf( $block_wrapper, $block_content ); } add_filter( 'render_block', 'bhe_block_wrapper', 10, 3 ); \ No newline at end of file diff --git a/src/blocks/block-hydration-experiments-parent/edit.js b/src/blocks/block-hydration-experiments-parent/edit.js deleted file mode 100644 index 14cd4e1f..00000000 --- a/src/blocks/block-hydration-experiments-parent/edit.js +++ /dev/null @@ -1,32 +0,0 @@ -// This import is needed to ensure that the `wp.blockEditor` global is available -// by the time this component gets loaded. The `Title` component consumes the -// global but cannot import it because it shouldn't be loaded on the frontend of -// the site. -import '@wordpress/block-editor'; - -import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; -import Button from './shared/button'; -import Title from './shared/title'; - -export default function Edit({ - attributes: { counter, message }, - setAttributes, -}) { - const blockProps = useBlockProps(); - return ( - <> - <div {...blockProps}> - <Title - value={message} - onChange={(val) => setAttributes({ message: val })} - placeholder="This will be passed through context to child blocks" - /> - <Button /> - <button onClick={() => setAttributes({ counter: counter + 1 })}> - {counter} - </button> - <InnerBlocks /> - </div> - </> - ); -} diff --git a/src/blocks/block-hydration-experiments-child/block.json b/src/blocks/interactive-child/block.json similarity index 66% rename from src/blocks/block-hydration-experiments-child/block.json rename to src/blocks/interactive-child/block.json index 109b0109..aee5271c 100644 --- a/src/blocks/block-hydration-experiments-child/block.json +++ b/src/blocks/interactive-child/block.json @@ -1,13 +1,13 @@ { "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, - "name": "bhe/block-hydration-experiments-child", + "name": "bhe/interactive-child", "version": "0.1.0", - "title": "BHE - Child", + "title": "BHE - Interactive Child", "category": "text", "icon": "flag", "description": "", - "usesContext": ["bhe/title", "bhe/content"], + "usesContext": ["bhe/interactive-title", "bhe/non-interactive-title"], "supports": { "color": { "text": true @@ -17,7 +17,7 @@ }, "html": true }, - "textdomain": "block-hydration-experiments-child", + "textdomain": "block-hydration-experiments", "editorScript": "file:./index.js", "style": "file:./style-index.css", "viewScript": "file:./view.js" diff --git a/src/blocks/block-hydration-experiments-child/edit.js b/src/blocks/interactive-child/edit.js similarity index 52% rename from src/blocks/block-hydration-experiments-child/edit.js rename to src/blocks/interactive-child/edit.js index 0f73087b..ccad5926 100644 --- a/src/blocks/block-hydration-experiments-child/edit.js +++ b/src/blocks/interactive-child/edit.js @@ -5,16 +5,17 @@ import '@wordpress/block-editor'; import { useBlockProps } from '@wordpress/block-editor'; -const Edit = ({ context }) => { - const blockProps = useBlockProps(); - - return ( - <div {...blockProps}> - <p>Child block</p> - <p>Block Context from interactive parent - "bhe/title": {context['bhe/title']}</p> - <p>Block Context from non-interactive parent - "bhe/content": {context['bhe/content']}</p> - </div> - ); -}; +const Edit = ({ context }) => ( + <div {...useBlockProps()}> + <p> + Block Context from interactive parent - "bhe/interactive-title":{' '} + {context['bhe/interactive-title']} + </p> + <p> + Block Context from non-interactive parent - + "bhe/non-interactive-title": {context['bhe/non-interactive-title']} + </p> + </div> +); export default Edit; diff --git a/src/blocks/block-hydration-experiments-child/frontend.js b/src/blocks/interactive-child/frontend.js similarity index 67% rename from src/blocks/block-hydration-experiments-child/frontend.js rename to src/blocks/interactive-child/frontend.js index ec71cac1..d738c420 100644 --- a/src/blocks/block-hydration-experiments-child/frontend.js +++ b/src/blocks/interactive-child/frontend.js @@ -8,14 +8,14 @@ const Frontend = ({ blockProps, context }) => { return ( <div {...blockProps}> - <p>Child block</p> <p> - Block Context from interactive parent - "bhe/title":{' '} - {context['bhe/title']} + Block Context from interactive parent - "bhe/interactive-title":{' '} + {context['bhe/interactive-title']} </p> <p> - Block Context from non-interactive parent - "bhe/title":{' '} - {context['bhe/content']} + Block Context from non-interactive parent - + "bhe/non-interactive-title":{' '} + {context['bhe/non-interactive-title']} </p> <p>React Context - "counter": {counter}</p> <p>React Context - "theme": {theme}</p> diff --git a/src/blocks/block-hydration-experiments-child/index.js b/src/blocks/interactive-child/index.js similarity index 81% rename from src/blocks/block-hydration-experiments-child/index.js rename to src/blocks/interactive-child/index.js index a9737d28..8c88ccbc 100644 --- a/src/blocks/block-hydration-experiments-child/index.js +++ b/src/blocks/interactive-child/index.js @@ -3,7 +3,7 @@ import Edit from './edit'; import Frontend from './frontend'; import './style.scss'; -registerBlockType('bhe/block-hydration-experiments-child', { +registerBlockType('bhe/interactive-child', { edit: Edit, // The Save component is derived from the Frontend component. frontend: Frontend, diff --git a/src/blocks/block-hydration-experiments-child/style.scss b/src/blocks/interactive-child/style.scss similarity index 68% rename from src/blocks/block-hydration-experiments-child/style.scss rename to src/blocks/interactive-child/style.scss index 1706e2bb..93ae89ee 100644 --- a/src/blocks/block-hydration-experiments-child/style.scss +++ b/src/blocks/interactive-child/style.scss @@ -1,10 +1,10 @@ -.wp-block-bhe-block-hydration-experiments-child { +.wp-block-bhe-interactive-child { padding: 15px 10px 15px 50px; border: 1px solid rgb(255, 162, 0); position: relative; } -.wp-block-bhe-block-hydration-experiments-child::before { +.wp-block-bhe-interactive-child::before { position: absolute; top: 0; right: 0; @@ -14,10 +14,10 @@ margin: -1px; padding: 0px 5px; font-size: 9px; - content: 'BHE - Child'; + content: 'BHE - Interactive Child'; } -gutenberg-block, +gutenberg-interactive-block, gutenberg-inner-blocks { display: contents; } diff --git a/src/blocks/block-hydration-experiments-child/view.js b/src/blocks/interactive-child/view.js similarity index 78% rename from src/blocks/block-hydration-experiments-child/view.js rename to src/blocks/interactive-child/view.js index b8fb70bc..cc7038be 100644 --- a/src/blocks/block-hydration-experiments-child/view.js +++ b/src/blocks/interactive-child/view.js @@ -3,6 +3,6 @@ import ThemeContext from '../../context/theme'; import { registerBlockType } from '../../gutenberg-packages/frontend'; import Frontend from './frontend'; -registerBlockType('bhe/block-hydration-experiments-child', Frontend, { +registerBlockType('bhe/interactive-child', Frontend, { usesContext: [ThemeContext, CounterContext], }); diff --git a/src/blocks/block-hydration-experiments-parent/block.json b/src/blocks/interactive-parent/block.json similarity index 73% rename from src/blocks/block-hydration-experiments-parent/block.json rename to src/blocks/interactive-parent/block.json index 99a5a6f3..6834703f 100644 --- a/src/blocks/block-hydration-experiments-parent/block.json +++ b/src/blocks/interactive-parent/block.json @@ -1,9 +1,9 @@ { "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, - "name": "bhe/block-hydration-experiments-parent", + "name": "bhe/interactive-parent", "version": "0.1.0", - "title": "BHE - Parent", + "title": "BHE - Interactive Parent", "category": "text", "icon": "flag", "description": "", @@ -13,7 +13,7 @@ "default": 0, "frontend": true }, - "message": { + "title": { "type": "string", "source": "text", "selector": ".title", @@ -30,10 +30,10 @@ "html": true }, "providesContext": { - "bhe/title": "message" + "bhe/interactive-title": "title" }, - "usesContext": ["bhe/content"], - "textdomain": "block-hydration-experiments-parent", + "usesContext": ["bhe/non-interactive-title"], + "textdomain": "block-hydration-experiments", "editorScript": "file:./index.js", "style": "file:./style-index.css", "viewScript": "file:./view.js" diff --git a/src/blocks/interactive-parent/edit.js b/src/blocks/interactive-parent/edit.js new file mode 100644 index 00000000..352fe6e1 --- /dev/null +++ b/src/blocks/interactive-parent/edit.js @@ -0,0 +1,29 @@ +// This import is needed to ensure that the `wp.blockEditor` global is available +// by the time this component gets loaded. The `Title` component consumes the +// global but cannot import it because it shouldn't be loaded on the frontend of +// the site. +import '@wordpress/block-editor'; + +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import Button from './shared/button'; +import Title from './shared/title'; + +const Edit = ({ attributes: { counter, title }, setAttributes }) => ( + <> + <div {...useBlockProps()}> + <Title + onChange={(val) => setAttributes({ title: val })} + placeholder="This will be passed through context to child blocks" + > + {title} + + + +
+ +); + +export default Edit; diff --git a/src/blocks/block-hydration-experiments-parent/frontend/index.js b/src/blocks/interactive-parent/frontend.js similarity index 60% rename from src/blocks/block-hydration-experiments-parent/frontend/index.js rename to src/blocks/interactive-parent/frontend.js index 7aa201cc..d449a963 100644 --- a/src/blocks/block-hydration-experiments-parent/frontend/index.js +++ b/src/blocks/interactive-parent/frontend.js @@ -1,21 +1,22 @@ -import Counter from '../../../context/counter'; -import Theme from '../../../context/theme'; -import { useState } from '../../../gutenberg-packages/wordpress-element'; -import Button from '../shared/button'; -import Title from '../shared/title'; +import Counter from '../../context/counter'; +import Theme from '../../context/theme'; +import { useState } from '../../gutenberg-packages/wordpress-element'; +import Button from './shared/button'; +import Title from './shared/title'; const Frontend = ({ blockProps, - attributes: { counter: initialCounter, message }, + attributes: { counter: initialCounter, title }, children, }) => { const [show, setShow] = useState(true); const [counter, setCounter] = useState(initialCounter); + return (
- + <Title>{title}