From ae96143ac825b079cd9a2b8836b798914e74147c Mon Sep 17 00:00:00 2001
From: Dennis Snell
Date: Sun, 14 Apr 2024 20:34:17 +0200
Subject: [PATCH 1/3] Bits: Introduce the ability to store and render bits
---
src/wp-includes/blocks.php | 2 +
src/wp-includes/html-api/class-wp-bits.php | 77 ++++++++++++++++++++++
src/wp-settings.php | 1 +
3 files changed, 80 insertions(+)
create mode 100644 src/wp-includes/html-api/class-wp-bits.php
diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php
index decc4896c378a..032e08ffc7502 100644
--- a/src/wp-includes/blocks.php
+++ b/src/wp-includes/blocks.php
@@ -2057,6 +2057,8 @@ function render_block( $parsed_block ) {
* }
*/
function parse_blocks( $content ) {
+ $content = wp_replace_bits( $content );
+
/**
* Filter to allow plugins to replace the server-side block parser.
*
diff --git a/src/wp-includes/html-api/class-wp-bits.php b/src/wp-includes/html-api/class-wp-bits.php
new file mode 100644
index 0000000000000..a7652bf64da1c
--- /dev/null
+++ b/src/wp-includes/html-api/class-wp-bits.php
@@ -0,0 +1,77 @@
+set_bookmark( 'here' );
+ $here = $this->bookmarks['here'];
+
+ $this->deferred_updates[] = new WP_HTML_Text_Replacement(
+ $here->start,
+ $here->length,
+ $new_content
+ );
+ }
+
+ public function flush_updates() {
+ foreach ( $this->deferred_updates as $update ) {
+ $this->lexical_updates[] = $update;
+ }
+ }
+ };
+
+ while ( $processor->next_token() ) {
+ switch ( $processor->get_token_type() ) {
+ case '#funky-comment':
+ $processor->replace_token( 'blarg' );
+ break;
+
+ case '#tag':
+ foreach ( $processor->get_attribute_names_with_prefix( '' ) ?? [] as $name ) {
+ $value = $processor->get_attribute( $name );
+ if ( is_string( $value ) ) {
+ $new_value = preg_replace_callback(
+ '~/wp:([^>]+)>~',
+ static function ( $bit ) {
+ return 'blarg';
+ },
+ $value
+ );
+
+ if ( $new_value !== $value ) {
+ $processor->set_attribute( $name, $new_value );
+ }
+ }
+ }
+ break;
+
+ case '#comment':
+ if ( WP_HTML_Tag_Processor::COMMENT_AS_HTML_COMMENT !== $processor->get_comment_type() ) {
+ break;
+ }
+
+ $text = $processor->get_modifiable_text();
+ if ( 1 === preg_match( '~^/wp:([^>]+)>$~', $text ) ) {
+ $processor->replace_token( 'Blarg!' );
+ break;
+ }
+
+ $new_value = preg_replace_callback(
+ '~/wp:([^>]+)>~',
+ static function ( $bit ) {
+ return 'blarg';
+ },
+ $text
+ );
+
+ $processor->replace_token( "" );
+ break;
+ }
+ }
+ $processor->flush_updates();
+ $content = $processor->get_updated_html();
+
+ return $content;
+}
diff --git a/src/wp-settings.php b/src/wp-settings.php
index a682c2a50380a..2e343f5d6ac06 100644
--- a/src/wp-settings.php
+++ b/src/wp-settings.php
@@ -262,6 +262,7 @@
require ABSPATH . WPINC . '/html-api/class-wp-html-stack-event.php';
require ABSPATH . WPINC . '/html-api/class-wp-html-processor-state.php';
require ABSPATH . WPINC . '/html-api/class-wp-html-processor.php';
+require ABSPATH . WPINC . '/html-api/class-wp-bits.php';
require ABSPATH . WPINC . '/class-wp-http.php';
require ABSPATH . WPINC . '/class-wp-http-streams.php';
require ABSPATH . WPINC . '/class-wp-http-curl.php';
From 667d6144a5680dd01a01de55b6d09e4ebeb97bf1 Mon Sep 17 00:00:00 2001
From: Dennis Snell
Date: Wed, 12 Jun 2024 13:06:21 +0200
Subject: [PATCH 2/3] Add Hello Dolly Bit
---
src/wp-includes/bits.php | 50 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 src/wp-includes/bits.php
diff --git a/src/wp-includes/bits.php b/src/wp-includes/bits.php
new file mode 100644
index 0000000000000..7e982c1addd97
--- /dev/null
+++ b/src/wp-includes/bits.php
@@ -0,0 +1,50 @@
+` produces `array( 'year' => '2024' )`.
+ * @param mixed $context Context passed into the Bit from the surrounding system.
+ * This argument is not yet specified and will always be `null`.
+ *
+ * @return mixed An HTML template for rendering into the page, either as a plain string or in array form.
+ */
+function core_bit_hello_dolly( string $name, string $output_type, ?array $attributes, mixed $context ): mixed {
+ static $vocalists = array(
+ 'Julie Dahle Aagård',
+ 'Mindi Abair',
+ 'Lorez Alexandria',
+ 'Karrin Allyson',
+ 'Michelle Amato',
+ 'Ernestine Anderson',
+ 'Ivie Anderson',
+ );
+
+ $vocalist = $vocalists[ wp_rand( 0, count( $vocalists ) - 1 ) ];
+
+ switch ( $output_type ) {
+ case 'plaintext':
+ return $vocalist;
+
+ case 'rich-text':
+ return array(
+ '%name>',
+ array( 'name' => $vocalist ),
+ );
+ }
+}
+
From 0993cc192b4d9c0e91f8c1f5283d21af6fc35e66 Mon Sep 17 00:00:00 2001
From: Dennis Snell
Date: Sat, 15 Jun 2024 17:36:40 +0200
Subject: [PATCH 3/3] Explore different ways of providing Bit renderers.
---
src/wp-includes/bits.php | 75 +++++++++++++++++++
.../html-api/class-wp-html-template.php | 48 ++++++++++++
src/wp-settings.php | 1 +
3 files changed, 124 insertions(+)
create mode 100644 src/wp-includes/html-api/class-wp-html-template.php
diff --git a/src/wp-includes/bits.php b/src/wp-includes/bits.php
index 7e982c1addd97..a4edd2dea0dc1 100644
--- a/src/wp-includes/bits.php
+++ b/src/wp-includes/bits.php
@@ -8,6 +8,8 @@
* @since {WP_VERSION}
*/
+declare( strict_types=1 );
+
/**
* Hello Dolly Bit Rendering function.
*
@@ -48,3 +50,76 @@ function core_bit_hello_dolly( string $name, string $output_type, ?array $attrib
}
}
+class WP_Hello_Dolly_Bit extends BitProvider {
+ /**
+ * @inheritDoc
+ */
+ public function handle_plaintext( string $bit_name, ?array $attributes ): string {
+ return self::get_random_vocalist();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function handle_richtext( string $bit_name, ?array $attributes ): WP_HTML_Template {
+ $name = self::get_random_vocalist();
+
+ return new WP_HTML_Template(
+ '%name>',
+ array( 'name' => $name )
+ );
+ }
+
+ /**
+ * Returns the name of a random Jazz vocalist.
+ *
+ * @return string
+ */
+ private function get_random_vocalist(): string {
+ static $vocalists = array(
+ 'Julie Dahle Aagård',
+ 'Mindi Abair',
+ 'Lorez Alexandria',
+ 'Karrin Allyson',
+ 'Michelle Amato',
+ 'Ernestine Anderson',
+ 'Ivie Anderson',
+ );
+
+ return $vocalists[ wp_rand( 0, count( $vocalists ) - 1 ) ];
+ }
+}
+
+abstract class BitProvider {
+ /**
+ * Performs initialize of Bit Provider during WordPress bootup.
+ */
+ public function register(): void {
+ // This is optional.
+ };
+
+ /**
+ * Called to source content in plaintext contexts. For example, when a
+ * Bit is found within an HTML attribute, or inside a `TITLE` element.
+ *
+ * @see WP_HTML_Template
+ *
+ * @param string $bit_name Full name with namespace of matched Bit, e.g. "core/post-author".
+ * @param array|null $attributes Configured attributes found on Bit, if found, otherwise `null`.
+ *
+ * @return string Plaintext value for provided content.
+ */
+ abstract public function handle_plaintext( string $bit_name, ?array $attributes ): string;
+
+ /**
+ * Called to source content in Rich Text (HTML Markup) contexts. For example,
+ * when a Bit is found within the inner content of an HTML tag.
+ *
+ * @see WP_HTML_Template
+ *
+ * @param string $bit_name Full name with namespace of matched Bit, e.g. "core/post-author".
+ * @param array|null $attributes Configured attributes found on Bit, if found, otherwise `null`.
+ * @return WP_HTML_Template HTML template for provided content: a string or array.
+ */
+ abstract public function handle_richtext( string $bit_name, ?array $attributes ): WP_HTML_Template;
+}
diff --git a/src/wp-includes/html-api/class-wp-html-template.php b/src/wp-includes/html-api/class-wp-html-template.php
new file mode 100644
index 0000000000000..f181478e41e63
--- /dev/null
+++ b/src/wp-includes/html-api/class-wp-html-template.php
@@ -0,0 +1,48 @@
+Hello, World!
' );
+ *
+ * // Placeholders for simple substitution.
+ * new WP_HTML_Template( 'Hello, %name>!
', array( 'name' => $name ) );
+ *
+ * // Spread-operator for sets of attributes.
+ * new WP_HTML_Template(
+ * '',
+ * array(
+ * 'data-wp-text="context.buttonLabel"',
+ * 'data-wp-click="actions.clickButton",
+ * )
+ * );
+ *
+ * @param string $template Static HTML template, possibly including placeholders.
+ * @param array|null $data Optional. Data provided for placeholders, if any.
+ */
+ public function __construct( string $template, array $data = null ) {
+ $this->template = $template;
+ $this->data = $data;
+ }
+}
diff --git a/src/wp-settings.php b/src/wp-settings.php
index 2e343f5d6ac06..2071922cd2da0 100644
--- a/src/wp-settings.php
+++ b/src/wp-settings.php
@@ -262,6 +262,7 @@
require ABSPATH . WPINC . '/html-api/class-wp-html-stack-event.php';
require ABSPATH . WPINC . '/html-api/class-wp-html-processor-state.php';
require ABSPATH . WPINC . '/html-api/class-wp-html-processor.php';
+require ABSPATH . WPINC . '/html-api/class-wp-html-template.php';
require ABSPATH . WPINC . '/html-api/class-wp-bits.php';
require ABSPATH . WPINC . '/class-wp-http.php';
require ABSPATH . WPINC . '/class-wp-http-streams.php';