From 93160a354da00f1ba514b68a61a0212b2fd94a13 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:04:17 +1200 Subject: [PATCH 01/33] Add wporg/time block --- mu-plugins/blocks/time/index.php | 174 ++++++++++++++++++++++++++ mu-plugins/blocks/time/src/block.json | 11 ++ mu-plugins/blocks/time/src/index.js | 32 +++++ mu-plugins/loader.php | 1 + 4 files changed, 218 insertions(+) create mode 100644 mu-plugins/blocks/time/index.php create mode 100644 mu-plugins/blocks/time/src/block.json create mode 100644 mu-plugins/blocks/time/src/index.js diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php new file mode 100644 index 000000000..a9ca9835b --- /dev/null +++ b/mu-plugins/blocks/time/index.php @@ -0,0 +1,174 @@ +[time]any-valid-time-string-here[/time] and creates a format that shows it in the viewers local time zone. + * + * @package wporg + */ + +namespace WordPressdotorg\MU_Plugins\Time; + +use function WordPressdotorg\MU_Plugins\Helpers\register_assets_from_metadata; + +add_action( 'init', __NAMESPACE__ . '\init' ); + +/** + * Registers the block using the metadata loaded from the `block.json` file. + * Behind the scenes, it registers also all assets so they can be enqueued + * through the block editor in the corresponding context. + * + * @see https://developer.wordpress.org/reference/functions/register_block_type/ + */ +function init() { + register_block_type( __DIR__ . '/build' ); + add_filter('the_content', __NAMESPACE__ . '\transform_time_blocks', 99, 1); +} + +/** + * Builds the time block output. + * + * This implements replacing the raw time strings in the post content with formatted times able to be converted to local times with JS. + * + * @param string $content Post content. + * @return string Content with display times reformatted. + */ +function transform_time_blocks( $content) { + // Find the time block elements by the classname "wporg-time" + $dom = new \DOMDocument(); + $dom->loadHTML( $content ); + $xpath = new \DOMXPath( $dom ); + $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); + + foreach ( $time_elements as $time_element ) { + $time_content = $time_element->nodeValue; + $parsed_time = parse_time( $time_content ); + + if ( $parsed_time === null ) { + continue; + } + + // Build the link and abbr microformat. + $time_element->setAttribute( 'href', 'https://www.timeanddate.com/worldclock/fixedtime.html?iso=' . gmdate( 'Ymd\THi', $parsed_time ) ); + + $new_time_content = $dom->createElement( 'abbr', $time_content ); + $new_time_content->setAttribute( 'class', 'wporg-time-date' ); + $new_time_content->setAttribute( 'title', gmdate( 'c', $parsed_time ) ); + + // Replace the raw time with the formatted time + $time_element->nodeValue = null; + $time_element->appendChild( $new_time_content ); + } + + $content = $dom->saveHTML(); + + return $content; +} + +/** + * Parse the datetime description string and return a timestamp. + * + * @param string $content Datetime description, eg. `Monday, April 6 at 19:00 UTC` + * @return string Unix timestamp or null if the time string could not be parsed. + */ +function parse_time( $content ) { + // Replace non-breaking spaces with a regular white space. + $gmtcontent = preg_replace( '/\xC2\xA0| /', ' ', $content ); + + // PHP understands "GMT" better than "UTC" for timezones. + $gmtcontent = str_replace( 'UTC', 'GMT', $gmtcontent ); + + // Remove the word "at" from the string, if present. Allows strings like "Monday, April 6 at 19:00 UTC" to work. + $gmtcontent = str_replace( ' at ', ' ', $gmtcontent ); + + // Try to parse the time, relative to the post time. + $time = strtotime( $gmtcontent, get_the_date( 'U' ) ); + + // If that didn't work, give up. + if ( false === $time || -1 === $time ) { + return null; + } + + // Add the time converter JS code. + if ( ! has_action( 'wp_footer', __NAMESPACE__ . '\time_converter_script' ) ) { + add_action( 'wp_footer', __NAMESPACE__ . '\time_converter_script', 999 ); + } + + return $time; +} + +/** + * Prints script to convert time in the viewers local time zone. + */ +function time_converter_script() { + ?> + +[time]any-valid-time-string-here[/time] and creates a format that shows it in the viewers local time zone.", + "textdomain": "wporg", + "editorScript": "file:./index.js" +} diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js new file mode 100644 index 000000000..5b487441d --- /dev/null +++ b/mu-plugins/blocks/time/src/index.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { registerFormatType, toggleFormat } from '@wordpress/rich-text'; +import { RichTextToolbarButton } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import metadata from './block.json'; + +const Edit = ( { isActive, onChange, value } ) => ( + { + onChange( + toggleFormat( value, { + type: metadata.name, + } ) + ); + } } + isActive={ isActive } + /> +); + +registerFormatType( metadata.name, { + title: metadata.title, + tagName: 'a', + className: 'wporg-time', + edit: Edit, +} ); diff --git a/mu-plugins/loader.php b/mu-plugins/loader.php index 784297ecb..a56471a34 100644 --- a/mu-plugins/loader.php +++ b/mu-plugins/loader.php @@ -38,6 +38,7 @@ require_once __DIR__ . '/blocks/screenshot-preview/block.php'; require_once __DIR__ . '/blocks/site-breadcrumbs/index.php'; require_once __DIR__ . '/blocks/table-of-contents/index.php'; +require_once __DIR__ . '/blocks/time/index.php'; require_once __DIR__ . '/global-fonts/index.php'; require_once __DIR__ . '/plugin-tweaks/index.php'; require_once __DIR__ . '/rest-api/index.php'; From ff374544db0434e2cf433f38faf113a5ca9f144c Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:48:42 +1200 Subject: [PATCH 02/33] Remove debug --- mu-plugins/blocks/time/index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index a9ca9835b..c5fe1e46b 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -153,7 +153,6 @@ function() { if ( date ) { if ( ! toLocaleTimeStringSupportsLocales ) { - console.log("🚀 ~ file: index.php:143 ~ document.querySelectorAll ~ toLocaleTimeStringSupportsLocales:", toLocaleTimeStringSupportsLocales) localTime += formatDate( date ); localTime += ' '; } From be048ab5719d6dda8a1ba4974b01318d6105d872 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 11 Jul 2023 20:19:41 +1200 Subject: [PATCH 03/33] Stop parsing content if empty --- mu-plugins/blocks/time/index.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index c5fe1e46b..7e2fecc17 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -33,6 +33,10 @@ function init() { * @return string Content with display times reformatted. */ function transform_time_blocks( $content) { + if ( empty( $content ) ) { + return $content; + } + // Find the time block elements by the classname "wporg-time" $dom = new \DOMDocument(); $dom->loadHTML( $content ); @@ -169,5 +173,5 @@ function() { } ); } )(); - Date: Mon, 17 Jul 2023 11:53:07 +1200 Subject: [PATCH 04/33] Remove usage of register_block_type as this isn't a block --- mu-plugins/blocks/time/index.php | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 7e2fecc17..f2707f3f5 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -13,15 +13,26 @@ add_action( 'init', __NAMESPACE__ . '\init' ); /** - * Registers the block using the metadata loaded from the `block.json` file. - * Behind the scenes, it registers also all assets so they can be enqueued - * through the block editor in the corresponding context. - * - * @see https://developer.wordpress.org/reference/functions/register_block_type/ + * Enqueues the script for the Time format in the block editor using the metadata loaded from the `block.json` file, + * and adds the filter for transforming the time blocks. */ function init() { - register_block_type( __DIR__ . '/build' ); - add_filter('the_content', __NAMESPACE__ . '\transform_time_blocks', 99, 1); + // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, + // and can be read with `wp_json_file_decode` & `register_block_script_handle. + $metadata_file = __DIR__ . '/build/block.json'; + $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); + $metadata['file'] = $metadata_file; + $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); + add_action( + 'enqueue_block_assets', + function() use ( $editor_script_handle ) { + if ( wp_should_load_block_editor_scripts_and_styles() && is_admin() ) { + wp_enqueue_script( $editor_script_handle ); + } + } + ); + + add_filter( 'the_content', __NAMESPACE__ . '\transform_time_blocks', 99, 1 ); } /** @@ -32,7 +43,7 @@ function init() { * @param string $content Post content. * @return string Content with display times reformatted. */ -function transform_time_blocks( $content) { +function transform_time_blocks( $content ) { if ( empty( $content ) ) { return $content; } @@ -42,7 +53,7 @@ function transform_time_blocks( $content) { $dom->loadHTML( $content ); $xpath = new \DOMXPath( $dom ); $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); - + foreach ( $time_elements as $time_element ) { $time_content = $time_element->nodeValue; $parsed_time = parse_time( $time_content ); @@ -50,7 +61,7 @@ function transform_time_blocks( $content) { if ( $parsed_time === null ) { continue; } - + // Build the link and abbr microformat. $time_element->setAttribute( 'href', 'https://www.timeanddate.com/worldclock/fixedtime.html?iso=' . gmdate( 'Ymd\THi', $parsed_time ) ); @@ -77,13 +88,13 @@ function transform_time_blocks( $content) { function parse_time( $content ) { // Replace non-breaking spaces with a regular white space. $gmtcontent = preg_replace( '/\xC2\xA0| /', ' ', $content ); - + // PHP understands "GMT" better than "UTC" for timezones. $gmtcontent = str_replace( 'UTC', 'GMT', $gmtcontent ); - + // Remove the word "at" from the string, if present. Allows strings like "Monday, April 6 at 19:00 UTC" to work. $gmtcontent = str_replace( ' at ', ' ', $gmtcontent ); - + // Try to parse the time, relative to the post time. $time = strtotime( $gmtcontent, get_the_date( 'U' ) ); From f8058d6a3f4c7f4c973501c3683c5d8058305472 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:53:37 +1200 Subject: [PATCH 05/33] Fix phpcs errors --- mu-plugins/blocks/time/index.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index f2707f3f5..6d5e8ab93 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -55,10 +55,10 @@ function transform_time_blocks( $content ) { $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); foreach ( $time_elements as $time_element ) { - $time_content = $time_element->nodeValue; + $time_content = $time_element->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $parsed_time = parse_time( $time_content ); - if ( $parsed_time === null ) { + if ( null === $parsed_time ) { continue; } @@ -70,7 +70,7 @@ function transform_time_blocks( $content ) { $new_time_content->setAttribute( 'title', gmdate( 'c', $parsed_time ) ); // Replace the raw time with the formatted time - $time_element->nodeValue = null; + $time_element->nodeValue = null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $time_element->appendChild( $new_time_content ); } @@ -82,7 +82,7 @@ function transform_time_blocks( $content ) { /** * Parse the datetime description string and return a timestamp. * - * @param string $content Datetime description, eg. `Monday, April 6 at 19:00 UTC` + * @param string $content Datetime description, eg. `Monday, April 6 at 19:00 UTC`. * @return string Unix timestamp or null if the time string could not be parsed. */ function parse_time( $content ) { From f82d9c6dc41d171f4ca70e682db1a53bc2820c1f Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:03:48 +1200 Subject: [PATCH 06/33] Enqueue frontend script if required rather than rendering inline --- mu-plugins/blocks/time/index.php | 106 ++++---------------- mu-plugins/blocks/time/src/block.json | 3 +- mu-plugins/blocks/time/src/convert_times.js | 63 ++++++++++++ 3 files changed, 86 insertions(+), 86 deletions(-) create mode 100644 mu-plugins/blocks/time/src/convert_times.js diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 6d5e8ab93..aebcf35cd 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -19,9 +19,7 @@ function init() { // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, // and can be read with `wp_json_file_decode` & `register_block_script_handle. - $metadata_file = __DIR__ . '/build/block.json'; - $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); - $metadata['file'] = $metadata_file; + $metadata = get_metadata(); $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); add_action( 'enqueue_block_assets', @@ -35,6 +33,17 @@ function() use ( $editor_script_handle ) { add_filter( 'the_content', __NAMESPACE__ . '\transform_time_blocks', 99, 1 ); } +/** + * Reads the block.json file and returns the metadata. + */ +function get_metadata() { + $metadata_file = __DIR__ . '/build/block.json'; + $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); + $metadata['file'] = $metadata_file; + + return $metadata; +} + /** * Builds the time block output. * @@ -44,7 +53,7 @@ function() use ( $editor_script_handle ) { * @return string Content with display times reformatted. */ function transform_time_blocks( $content ) { - if ( empty( $content ) ) { + if ( empty( $content || is_admin() ) ) { return $content; } @@ -54,6 +63,14 @@ function transform_time_blocks( $content ) { $xpath = new \DOMXPath( $dom ); $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); + if ( empty( $time_elements ) ) { + return $content; + } + + $metadata = get_metadata(); + $time_converter_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); + wp_enqueue_script( $time_converter_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); + foreach ( $time_elements as $time_element ) { $time_content = $time_element->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $parsed_time = parse_time( $time_content ); @@ -103,86 +120,5 @@ function parse_time( $content ) { return null; } - // Add the time converter JS code. - if ( ! has_action( 'wp_footer', __NAMESPACE__ . '\time_converter_script' ) ) { - add_action( 'wp_footer', __NAMESPACE__ . '\time_converter_script', 999 ); - } - return $time; } - -/** - * Prints script to convert time in the viewers local time zone. - */ -function time_converter_script() { - ?> - - [time]any-valid-time-string-here[/time] and creates a format that shows it in the viewers local time zone.", "textdomain": "wporg", - "editorScript": "file:./index.js" + "editorScript": "file:./index.js", + "viewScript": "file:./convert_times.js" } diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/convert_times.js new file mode 100644 index 000000000..ef8583fa2 --- /dev/null +++ b/mu-plugins/blocks/time/src/convert_times.js @@ -0,0 +1,63 @@ +function convertTimes() { + const parseDate = function ( text ) { + const match = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\+00:00$/.exec( text ); + + return new Date( + // Date.UTC(year, monthIndex (0..11), day, hour, minute, second) + Date.UTC( +match[ 1 ], +match[ 2 ] - 1, +match[ 3 ], +match[ 4 ], +match[ 5 ], +match[ 6 ] ) + ); + }; + + const formatTime = function ( date ) { + return date.toLocaleTimeString( window.navigator.language, { + weekday: 'long', + month: 'long', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + timeZoneName: 'short', + } ); + }; + + const formatDate = function ( date ) { + return date.toLocaleDateString( window.navigator.language, { + weekday: 'long', + month: 'long', + day: 'numeric', + year: 'numeric', + } ); + }; + + // Not all browsers, particularly Safari, support arguments to .toLocaleTimeString(). + const toLocaleTimeStringSupportsLocales = ( function () { + try { + new Date().toLocaleTimeString( 'i' ); + } catch ( event ) { + return event.name === 'RangeError'; + } + + return false; + } )(); + + document.querySelectorAll( '.wporg-time' ).forEach( ( dateElement ) => { + let localTime = ''; + const datetime = dateElement.getAttribute( 'datetime' ); + const date = datetime && parseDate( datetime ); + + if ( date ) { + if ( ! toLocaleTimeStringSupportsLocales ) { + localTime += formatDate( date ); + localTime += ' '; + } + + localTime += formatTime( date ); + + dateElement.innerText = localTime; + } + } ); +} + +document.addEventListener( 'DOMContentLoaded', () => { + convertTimes(); +} ); From e6eb98b68e2fab220689817b74c3050e5a04a9de Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:04:17 +1200 Subject: [PATCH 07/33] Change to semantic elements for time on frontend --- mu-plugins/blocks/time/index.php | 24 ++++++++++++------------ mu-plugins/blocks/time/src/index.js | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index aebcf35cd..a0ac71a2a 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -30,7 +30,7 @@ function() use ( $editor_script_handle ) { } ); - add_filter( 'the_content', __NAMESPACE__ . '\transform_time_blocks', 99, 1 ); + add_filter( 'the_content', __NAMESPACE__ . '\transform_times', 99, 1 ); } /** @@ -52,14 +52,16 @@ function get_metadata() { * @param string $content Post content. * @return string Content with display times reformatted. */ -function transform_time_blocks( $content ) { +function transform_times( $content ) { if ( empty( $content || is_admin() ) ) { return $content; } // Find the time block elements by the classname "wporg-time" $dom = new \DOMDocument(); - $dom->loadHTML( $content ); + + // Ignore warnings about htlm5 tags. + $dom->loadHTML( $content, LIBXML_NOERROR ); $xpath = new \DOMXPath( $dom ); $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); @@ -79,16 +81,14 @@ function transform_time_blocks( $content ) { continue; } - // Build the link and abbr microformat. - $time_element->setAttribute( 'href', 'https://www.timeanddate.com/worldclock/fixedtime.html?iso=' . gmdate( 'Ymd\THi', $parsed_time ) ); - - $new_time_content = $dom->createElement( 'abbr', $time_content ); - $new_time_content->setAttribute( 'class', 'wporg-time-date' ); - $new_time_content->setAttribute( 'title', gmdate( 'c', $parsed_time ) ); + $time_element->setAttribute( 'datetime', gmdate( 'c', $parsed_time ) ); - // Replace the raw time with the formatted time - $time_element->nodeValue = null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - $time_element->appendChild( $new_time_content ); + // Create a new link with the time as the href, clone the time element inside the link, + // and replace the original time element with the link. + $link_element = $dom->createElement( 'a' ); + $link_element->setAttribute( 'href', 'https://www.timeanddate.com/worldclock/fixedtime.html?iso=' . gmdate( 'Ymd\THi', $parsed_time ) ); + $link_element->appendChild( $time_element->cloneNode( true ) ); + $time_element->parentNode->replaceChild( $link_element, $time_element ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } $content = $dom->saveHTML(); diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 5b487441d..803ad206d 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -26,7 +26,7 @@ const Edit = ( { isActive, onChange, value } ) => ( registerFormatType( metadata.name, { title: metadata.title, - tagName: 'a', + tagName: 'time', className: 'wporg-time', edit: Edit, } ); From c3f936ff5f4b083f15aae349c5f31e4c2b0309af Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:10:43 +1200 Subject: [PATCH 08/33] Fix transform_times bail out logic --- mu-plugins/blocks/time/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index a0ac71a2a..36f93fb07 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -53,7 +53,7 @@ function get_metadata() { * @return string Content with display times reformatted. */ function transform_times( $content ) { - if ( empty( $content || is_admin() ) ) { + if ( empty( $content ) || is_admin() ) { return $content; } From 018f389c84b51c07df96916238b015772b916edd Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 11:53:19 +1200 Subject: [PATCH 09/33] Use Gutenberg non block example approach for registering and enqueuing scripts --- mu-plugins/blocks/time/index.php | 47 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 36f93fb07..ab1b30ce3 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -17,31 +17,34 @@ * and adds the filter for transforming the time blocks. */ function init() { - // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, - // and can be read with `wp_json_file_decode` & `register_block_script_handle. - $metadata = get_metadata(); - $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); + // Register and enqueue the block editor script to add the time format to the toolbar. + $index_asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; + wp_register_script( + 'wporg-time-format', + plugins_url( 'build/index.js', __FILE__ ), + $index_asset_file['dependencies'], + $index_asset_file['version'], + true + ); + add_action( - 'enqueue_block_assets', - function() use ( $editor_script_handle ) { - if ( wp_should_load_block_editor_scripts_and_styles() && is_admin() ) { - wp_enqueue_script( $editor_script_handle ); - } + 'enqueue_block_editor_assets', + function() { + wp_enqueue_script( 'wporg-time-format' ); } ); - add_filter( 'the_content', __NAMESPACE__ . '\transform_times', 99, 1 ); -} - -/** - * Reads the block.json file and returns the metadata. - */ -function get_metadata() { - $metadata_file = __DIR__ . '/build/block.json'; - $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); - $metadata['file'] = $metadata_file; + // Register the script for converting the times to local times on the frontend. + $converter_asset_file = include plugin_dir_path( __FILE__ ) . 'build/convert_times.asset.php'; + wp_register_script( + 'wporg-time-format-converter', + plugins_url( 'build/convert_times.js', __FILE__ ), + $converter_asset_file['dependencies'], + $converter_asset_file['version'], + true + ); - return $metadata; + add_filter( 'the_content', __NAMESPACE__ . '\transform_times', 99, 1 ); } /** @@ -69,9 +72,7 @@ function transform_times( $content ) { return $content; } - $metadata = get_metadata(); - $time_converter_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); - wp_enqueue_script( $time_converter_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); + wp_enqueue_script( 'wporg-time-format-converter' ); foreach ( $time_elements as $time_element ) { $time_content = $time_element->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase From 0dd43dc66151d81a78ad0dc82d2a927f87936035 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 11:55:36 +1200 Subject: [PATCH 10/33] Remove unused helper --- mu-plugins/blocks/time/index.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index ab1b30ce3..85771cd5d 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -8,8 +8,6 @@ namespace WordPressdotorg\MU_Plugins\Time; -use function WordPressdotorg\MU_Plugins\Helpers\register_assets_from_metadata; - add_action( 'init', __NAMESPACE__ . '\init' ); /** From 8eb92428cde47ffc830179399ed605cd8aa22e83 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:06:06 +1200 Subject: [PATCH 11/33] Fix bail out logic for no time elements --- mu-plugins/blocks/time/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 85771cd5d..5657f1d98 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -66,7 +66,7 @@ function transform_times( $content ) { $xpath = new \DOMXPath( $dom ); $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); - if ( empty( $time_elements ) ) { + if ( 0 === $time_elements->length ) { return $content; } From 11329c53669941b13e480c36f9957d035e37c488 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:06:21 +1200 Subject: [PATCH 12/33] Revert "Use Gutenberg non block example approach for registering and enqueuing scripts" This reverts commit a5244fde2a1b99fcb512b926dfcb3d78d5461d55. --- mu-plugins/blocks/time/index.php | 47 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 5657f1d98..25a6cff30 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -15,36 +15,33 @@ * and adds the filter for transforming the time blocks. */ function init() { - // Register and enqueue the block editor script to add the time format to the toolbar. - $index_asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - wp_register_script( - 'wporg-time-format', - plugins_url( 'build/index.js', __FILE__ ), - $index_asset_file['dependencies'], - $index_asset_file['version'], - true - ); - + // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, + // and can be read with `wp_json_file_decode` & `register_block_script_handle. + $metadata = get_metadata(); + $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); add_action( - 'enqueue_block_editor_assets', - function() { - wp_enqueue_script( 'wporg-time-format' ); + 'enqueue_block_assets', + function() use ( $editor_script_handle ) { + if ( wp_should_load_block_editor_scripts_and_styles() && is_admin() ) { + wp_enqueue_script( $editor_script_handle ); + } } ); - // Register the script for converting the times to local times on the frontend. - $converter_asset_file = include plugin_dir_path( __FILE__ ) . 'build/convert_times.asset.php'; - wp_register_script( - 'wporg-time-format-converter', - plugins_url( 'build/convert_times.js', __FILE__ ), - $converter_asset_file['dependencies'], - $converter_asset_file['version'], - true - ); - add_filter( 'the_content', __NAMESPACE__ . '\transform_times', 99, 1 ); } +/** + * Reads the block.json file and returns the metadata. + */ +function get_metadata() { + $metadata_file = __DIR__ . '/build/block.json'; + $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); + $metadata['file'] = $metadata_file; + + return $metadata; +} + /** * Builds the time block output. * @@ -70,7 +67,9 @@ function transform_times( $content ) { return $content; } - wp_enqueue_script( 'wporg-time-format-converter' ); + $metadata = get_metadata(); + $time_converter_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); + wp_enqueue_script( $time_converter_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); foreach ( $time_elements as $time_element ) { $time_content = $time_element->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase From eb1c15cc8fafd5c41197206257fe2626e964551e Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:27:43 +1200 Subject: [PATCH 13/33] Use Moment to parse the date description and add it to the time element on toggle --- mu-plugins/blocks/time/src/convert_times.js | 9 +++-- mu-plugins/blocks/time/src/index.js | 37 +++++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/convert_times.js index ef8583fa2..e0b996a12 100644 --- a/mu-plugins/blocks/time/src/convert_times.js +++ b/mu-plugins/blocks/time/src/convert_times.js @@ -2,9 +2,12 @@ function convertTimes() { const parseDate = function ( text ) { const match = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\+00:00$/.exec( text ); - return new Date( - // Date.UTC(year, monthIndex (0..11), day, hour, minute, second) - Date.UTC( +match[ 1 ], +match[ 2 ] - 1, +match[ 3 ], +match[ 4 ], +match[ 5 ], +match[ 6 ] ) + return ( + match && + new Date( + // Date.UTC(year, monthIndex (0..11), day, hour, minute, second) + Date.UTC( +match[ 1 ], +match[ 2 ] - 1, +match[ 3 ], +match[ 4 ], +match[ 5 ], +match[ 6 ] ) + ) ); }; diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 803ad206d..8706bc063 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -1,7 +1,9 @@ +/* global moment */ + /** * WordPress dependencies */ -import { registerFormatType, toggleFormat } from '@wordpress/rich-text'; +import { getTextContent, registerFormatType, slice, toggleFormat } from '@wordpress/rich-text'; import { RichTextToolbarButton } from '@wordpress/block-editor'; /** @@ -9,14 +11,37 @@ import { RichTextToolbarButton } from '@wordpress/block-editor'; */ import metadata from './block.json'; +const { name, icon, title } = metadata; + const Edit = ( { isActive, onChange, value } ) => ( { + const dateDescription = getTextContent( slice( value ) ); // eg. Tuesday, April 5th, at 15:00 UTC + + if ( ! dateDescription ) { + onChange( + toggleFormat( value, { + type: name, + } ) + ); + + return; + } + + const cleanString = dateDescription.replace( 'at ', '' ); + + // Parse the cleaned string into a Moment object in UTC + const momentDate = moment.utc( cleanString, 'dddd, MMMM Do, HH:mm z' ); + + // Format the Moment object in the desired output format + const formatted = momentDate.isValid() ? momentDate.format( 'YYYY-MM-DDTHH:mm:ssZ' ) : null; + onChange( toggleFormat( value, { - type: metadata.name, + type: name, + attributes: formatted ? { datetime: formatted } : {}, } ) ); } } @@ -24,8 +49,8 @@ const Edit = ( { isActive, onChange, value } ) => ( /> ); -registerFormatType( metadata.name, { - title: metadata.title, +registerFormatType( name, { + title: title, tagName: 'time', className: 'wporg-time', edit: Edit, From 1fa0b11bf14ae128d62df0f9110a5f69340eaf39 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:58:29 +1200 Subject: [PATCH 14/33] Replace php dom manipulation with js --- mu-plugins/blocks/time/index.php | 103 +++----------------- mu-plugins/blocks/time/src/convert_times.js | 12 ++- mu-plugins/blocks/time/src/index.js | 14 +-- 3 files changed, 30 insertions(+), 99 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 25a6cff30..c7ecb4956 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -17,7 +17,10 @@ function init() { // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, // and can be read with `wp_json_file_decode` & `register_block_script_handle. - $metadata = get_metadata(); + $metadata_file = __DIR__ . '/build/block.json'; + $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); + $metadata['file'] = $metadata_file; + $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); add_action( 'enqueue_block_assets', @@ -28,95 +31,13 @@ function() use ( $editor_script_handle ) { } ); - add_filter( 'the_content', __NAMESPACE__ . '\transform_times', 99, 1 ); -} - -/** - * Reads the block.json file and returns the metadata. - */ -function get_metadata() { - $metadata_file = __DIR__ . '/build/block.json'; - $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); - $metadata['file'] = $metadata_file; - - return $metadata; -} - -/** - * Builds the time block output. - * - * This implements replacing the raw time strings in the post content with formatted times able to be converted to local times with JS. - * - * @param string $content Post content. - * @return string Content with display times reformatted. - */ -function transform_times( $content ) { - if ( empty( $content ) || is_admin() ) { - return $content; - } - - // Find the time block elements by the classname "wporg-time" - $dom = new \DOMDocument(); - - // Ignore warnings about htlm5 tags. - $dom->loadHTML( $content, LIBXML_NOERROR ); - $xpath = new \DOMXPath( $dom ); - $time_elements = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' wporg-time ')]" ); - - if ( 0 === $time_elements->length ) { - return $content; - } - - $metadata = get_metadata(); - $time_converter_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); - wp_enqueue_script( $time_converter_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); - - foreach ( $time_elements as $time_element ) { - $time_content = $time_element->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - $parsed_time = parse_time( $time_content ); - - if ( null === $parsed_time ) { - continue; + $view_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); + add_action( + 'wp_enqueue_scripts', + function() use ( $view_script_handle ) { + if ( ! is_admin() ) { + wp_enqueue_script( $view_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); + } } - - $time_element->setAttribute( 'datetime', gmdate( 'c', $parsed_time ) ); - - // Create a new link with the time as the href, clone the time element inside the link, - // and replace the original time element with the link. - $link_element = $dom->createElement( 'a' ); - $link_element->setAttribute( 'href', 'https://www.timeanddate.com/worldclock/fixedtime.html?iso=' . gmdate( 'Ymd\THi', $parsed_time ) ); - $link_element->appendChild( $time_element->cloneNode( true ) ); - $time_element->parentNode->replaceChild( $link_element, $time_element ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - } - - $content = $dom->saveHTML(); - - return $content; -} - -/** - * Parse the datetime description string and return a timestamp. - * - * @param string $content Datetime description, eg. `Monday, April 6 at 19:00 UTC`. - * @return string Unix timestamp or null if the time string could not be parsed. - */ -function parse_time( $content ) { - // Replace non-breaking spaces with a regular white space. - $gmtcontent = preg_replace( '/\xC2\xA0| /', ' ', $content ); - - // PHP understands "GMT" better than "UTC" for timezones. - $gmtcontent = str_replace( 'UTC', 'GMT', $gmtcontent ); - - // Remove the word "at" from the string, if present. Allows strings like "Monday, April 6 at 19:00 UTC" to work. - $gmtcontent = str_replace( ' at ', ' ', $gmtcontent ); - - // Try to parse the time, relative to the post time. - $time = strtotime( $gmtcontent, get_the_date( 'U' ) ); - - // If that didn't work, give up. - if ( false === $time || -1 === $time ) { - return null; - } - - return $time; + ); } diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/convert_times.js index e0b996a12..53bbe766a 100644 --- a/mu-plugins/blocks/time/src/convert_times.js +++ b/mu-plugins/blocks/time/src/convert_times.js @@ -46,9 +46,10 @@ function convertTimes() { document.querySelectorAll( '.wporg-time' ).forEach( ( dateElement ) => { let localTime = ''; const datetime = dateElement.getAttribute( 'datetime' ); + const datetimeISO = dateElement.getAttribute( 'data-iso' ); const date = datetime && parseDate( datetime ); - if ( date ) { + if ( date && !! datetimeISO ) { if ( ! toLocaleTimeStringSupportsLocales ) { localTime += formatDate( date ); localTime += ' '; @@ -56,7 +57,14 @@ function convertTimes() { localTime += formatTime( date ); - dateElement.innerText = localTime; + const linkElement = document.createElement( 'a' ); + linkElement.innerText = localTime; + linkElement.setAttribute( + 'href', + `https://www.timeanddate.com/worldclock/fixedtime.html?iso=${ datetimeISO }` + ); + + dateElement.parentNode.replaceChild( linkElement, dateElement ); } } ); } diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 8706bc063..0ba8bc6b4 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -18,7 +18,7 @@ const Edit = ( { isActive, onChange, value } ) => ( icon={ icon } title={ title } onClick={ () => { - const dateDescription = getTextContent( slice( value ) ); // eg. Tuesday, April 5th, at 15:00 UTC + const dateDescription = getTextContent( slice( value ) ); // eg. Tuesday, April 5th 2022, at 15:00 UTC if ( ! dateDescription ) { onChange( @@ -33,15 +33,17 @@ const Edit = ( { isActive, onChange, value } ) => ( const cleanString = dateDescription.replace( 'at ', '' ); // Parse the cleaned string into a Moment object in UTC - const momentDate = moment.utc( cleanString, 'dddd, MMMM Do, HH:mm z' ); - - // Format the Moment object in the desired output format - const formatted = momentDate.isValid() ? momentDate.format( 'YYYY-MM-DDTHH:mm:ssZ' ) : null; + const momentDate = moment.utc( cleanString, 'dddd, MMMM Do YYYY, HH:mm z' ); onChange( toggleFormat( value, { type: name, - attributes: formatted ? { datetime: formatted } : {}, + attributes: momentDate.isValid() + ? { + datetime: momentDate.format( 'YYYY-MM-DDTHH:mm:ssZ' ), + 'data-iso': momentDate.format( 'YYYYMMDDTHHmm' ), + } + : {}, } ) ); } } From 19e6e6205a2ec73cf63a11b74c26c39378c87ccb Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:00:29 +1200 Subject: [PATCH 15/33] Update descriptions to specify input format --- mu-plugins/blocks/time/index.php | 2 +- mu-plugins/blocks/time/src/block.json | 2 +- mu-plugins/blocks/time/src/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index c7ecb4956..e1ace626d 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -1,7 +1,7 @@ [time]any-valid-time-string-here[/time] and creates a format that shows it in the viewers local time zone. + * Description: Attempts to parse a time string like Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone. * * @package wporg */ diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index 71f56b1dd..ddb320d3a 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -5,7 +5,7 @@ "title": "Time", "icon": "calendar", "category": "common", - "description": "Attempts to parse a time string like [time]any-valid-time-string-here[/time] and creates a format that shows it in the viewers local time zone.", + "description": "Attempts to parse a time string like Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone.", "textdomain": "wporg", "editorScript": "file:./index.js", "viewScript": "file:./convert_times.js" diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 0ba8bc6b4..c2f3565f5 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -18,7 +18,7 @@ const Edit = ( { isActive, onChange, value } ) => ( icon={ icon } title={ title } onClick={ () => { - const dateDescription = getTextContent( slice( value ) ); // eg. Tuesday, April 5th 2022, at 15:00 UTC + const dateDescription = getTextContent( slice( value ) ); if ( ! dateDescription ) { onChange( From be3f4f7387861b209ff6708e4202d2bed346ae00 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:18:14 +1200 Subject: [PATCH 16/33] Update docs --- mu-plugins/blocks/time/index.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index e1ace626d..0f3843686 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -1,6 +1,6 @@ Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone. * * @package wporg @@ -11,8 +11,7 @@ add_action( 'init', __NAMESPACE__ . '\init' ); /** - * Enqueues the script for the Time format in the block editor using the metadata loaded from the `block.json` file, - * and adds the filter for transforming the time blocks. + * Enqueues the scripts for the Time format in the block editor and frontend using the metadata loaded from the `block.json` file. */ function init() { // Add the JS script to add the Time formatting option to the toolbar. The dependencies are autogenerated in block.json, From 10a3340d17cea5bd21f5b389874d84a7043532c2 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:18:44 +1200 Subject: [PATCH 17/33] Skip parsing if format is being deactivated --- mu-plugins/blocks/time/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index c2f3565f5..d55868ad2 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -20,7 +20,7 @@ const Edit = ( { isActive, onChange, value } ) => ( onClick={ () => { const dateDescription = getTextContent( slice( value ) ); - if ( ! dateDescription ) { + if ( ! dateDescription || isActive ) { onChange( toggleFormat( value, { type: name, From 78d87328ac0b57ad9f5348a7d75c50636fcd2b41 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:01:47 +1200 Subject: [PATCH 18/33] Replace Moment usage with locutus --- mu-plugins/blocks/time/src/convert_times.js | 5 +- mu-plugins/blocks/time/src/index.js | 92 ++-- package.json | 4 +- yarn.lock | 459 +++++++++++++++++++- 4 files changed, 517 insertions(+), 43 deletions(-) diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/convert_times.js index 53bbe766a..cf94a56b8 100644 --- a/mu-plugins/blocks/time/src/convert_times.js +++ b/mu-plugins/blocks/time/src/convert_times.js @@ -1,6 +1,9 @@ function convertTimes() { const parseDate = function ( text ) { - const match = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\+00:00$/.exec( text ); + const match = + /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\+([0-2]{1})([0-9]{1}):00$/.exec( + text + ); return ( match && diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index d55868ad2..39eabc0fe 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -1,10 +1,15 @@ -/* global moment */ - /** * WordPress dependencies */ -import { getTextContent, registerFormatType, slice, toggleFormat } from '@wordpress/rich-text'; +import { useSelect } from '@wordpress/data'; import { RichTextToolbarButton } from '@wordpress/block-editor'; +import { useCallback } from '@wordpress/element'; +import { getTextContent, registerFormatType, slice, toggleFormat } from '@wordpress/rich-text'; + +/** + * External dependencies + */ +import { gmdate, strtotime } from 'locutus/php/datetime'; /** * Internal dependencies @@ -13,43 +18,62 @@ import metadata from './block.json'; const { name, icon, title } = metadata; -const Edit = ( { isActive, onChange, value } ) => ( - { - const dateDescription = getTextContent( slice( value ) ); +const Edit = ( { isActive, onChange, value } ) => { + const { date_gmt } = useSelect( ( select ) => select( 'core/editor' ).getCurrentPost() ); + + const toggleWithoutEnhancing = useCallback( () => { + onChange( + toggleFormat( value, { + type: name, + } ) + ); + } ); + + return ( + { + const dateDescription = getTextContent( slice( value ) ); + + if ( ! dateDescription || isActive ) { + toggleWithoutEnhancing(); + + return; + } + + // Remove the word "at" from the string, if present. + // Allows strings like "Monday, April 6 at 19:00 UTC" to work. + const dateCleaned = dateDescription.replace( 'at ', '' ); + + // strtotime understands "GMT" better than "UTC" for timezones. + dateCleaned.replace( 'UTC', 'GMT' ); + + // Try to parse the time, relative to the post time. + const postTimestamp = strtotime( date_gmt ); + const time = strtotime( dateCleaned, postTimestamp ); + + // If that didn't work, give up. + if ( false === time || -1 === time ) { + toggleWithoutEnhancing(); + + return; + } - if ( ! dateDescription || isActive ) { onChange( toggleFormat( value, { type: name, + attributes: { + datetime: gmdate( 'c', time ), + 'data-iso': gmdate( 'Ymd\\THi', time ), + }, } ) ); - - return; - } - - const cleanString = dateDescription.replace( 'at ', '' ); - - // Parse the cleaned string into a Moment object in UTC - const momentDate = moment.utc( cleanString, 'dddd, MMMM Do YYYY, HH:mm z' ); - - onChange( - toggleFormat( value, { - type: name, - attributes: momentDate.isValid() - ? { - datetime: momentDate.format( 'YYYY-MM-DDTHH:mm:ssZ' ), - 'data-iso': momentDate.format( 'YYYYMMDDTHHmm' ), - } - : {}, - } ) - ); - } } - isActive={ isActive } - /> -); + } } + isActive={ isActive } + /> + ); +}; registerFormatType( name, { title: title, diff --git a/package.json b/package.json index 5ca2130e9..d7594949f 100644 --- a/package.json +++ b/package.json @@ -64,5 +64,7 @@ "selector-class-pattern": null } }, - "dependencies": {} + "dependencies": { + "locutus": "^2.0.16" + } } diff --git a/yarn.lock b/yarn.lock index 0edab39ff..3eea12001 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1408,6 +1408,18 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@kwsites/file-exists@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99" + integrity sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw== + dependencies: + debug "^4.1.1" + +"@kwsites/promise-deferred@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" + integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -1471,6 +1483,11 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + "@sinonjs/commons@^1.7.0": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -1589,6 +1606,13 @@ "@svgr/plugin-jsx" "^6.3.1" "@svgr/plugin-svgo" "^6.3.1" +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -1647,6 +1671,16 @@ dependencies: "@types/node" "*" +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + "@types/cheerio@^0.22.22": version "0.22.31" resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.31.tgz#b8538100653d6bb1b08a1e46dec75b4f2a5d5eb6" @@ -1734,6 +1768,11 @@ dependencies: "@types/node" "*" +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + "@types/http-proxy@^1.17.8": version "1.17.9" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" @@ -1770,6 +1809,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -1836,6 +1882,13 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/retry@0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -2238,6 +2291,24 @@ react "^17.0.2" react-dom "^17.0.2" +"@wordpress/env@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@wordpress/env/-/env-5.5.0.tgz#5ff6c7b2d04df78940bde7eb660961eee2cde3c2" + integrity sha512-Dm/XHkCD8rVSfm9fGvK92EbfZ7UhZCkIoNdv8wq21cwiZ0/2O0iPaC73aJ/4pTaY0PBODz5Z/LD4gE/cRSDcxg== + dependencies: + chalk "^4.0.0" + copy-dir "^1.3.0" + docker-compose "^0.22.2" + extract-zip "^1.6.7" + got "^11.8.5" + inquirer "^7.1.0" + js-yaml "^3.13.1" + ora "^4.0.2" + rimraf "^3.0.2" + simple-git "^3.5.0" + terminal-link "^2.0.0" + yargs "^17.3.0" + "@wordpress/escape-html@^2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@wordpress/escape-html/-/escape-html-2.13.0.tgz#c2467cab9ed54017c456712d2ae48dc4f1c6e2df" @@ -2926,6 +2997,24 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" + integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2981,7 +3070,7 @@ chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3003,6 +3092,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-node-version@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/check-node-version/-/check-node-version-4.2.1.tgz#42f7e3c6e2427327b5c9080dae593d8997fe9a06" @@ -3083,6 +3177,23 @@ clean-webpack-plugin@^3.0.0: "@types/webpack" "^4.4.31" del "^4.1.1" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.2.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" + integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -3092,6 +3203,15 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -3119,6 +3239,18 @@ clone-regexp@^2.1.0: dependencies: is-regexp "^2.0.0" +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3230,6 +3362,16 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + connect-history-api-fallback@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" @@ -3264,6 +3406,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +copy-dir@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/copy-dir/-/copy-dir-1.3.0.tgz#8c65130e11d8313a6ac2c0578e4c6c6f70b456ba" + integrity sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw== + copy-webpack-plugin@^10.2.0: version "10.2.4" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" @@ -3571,6 +3718,13 @@ decimal.js@^10.2.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -3598,6 +3752,18 @@ default-gateway@^6.0.3: dependencies: execa "^5.0.0" +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -3693,6 +3859,11 @@ dns-packet@^5.2.2: dependencies: "@leichtgewicht/ip-codec" "^2.0.1" +docker-compose@^0.22.2: + version "0.22.2" + resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.22.2.tgz#37832c58973694965cb721a24c405e7f48fff738" + integrity sha512-iXWb5+LiYmylIMFXvGTYsjI1F+Xyx78Jm/uj1dxwwZLbWkUdH6yOXY5Nr3RjbYX15EgbGJCq78d29CmWQQQMPg== + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -4330,6 +4501,15 @@ express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extract-zip@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -4341,6 +4521,16 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extract-zip@^1.6.7: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -4405,6 +4595,13 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -4796,6 +4993,23 @@ globjoin@^0.1.4: resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" integrity sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg== +got@^11.8.5: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -4928,6 +5142,11 @@ htmlparser2@^8.0.1: domutils "^3.0.1" entities "^4.3.0" +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -4988,6 +5207,14 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -5001,7 +5228,7 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5101,6 +5328,25 @@ ini@~3.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.0.tgz#2f6de95006923aa75feed8894f5686165adc08f1" integrity sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw== +inquirer@^7.1.0: + version "7.3.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.19" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.6.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -5213,6 +5459,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -5903,6 +6154,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -5972,6 +6228,13 @@ jsonfile@^6.0.1: array-includes "^3.1.5" object.assign "^4.1.2" +keyv@^4.0.0: + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + dependencies: + json-buffer "3.0.1" + kind-of@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" @@ -6071,6 +6334,15 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-utils@^1.2.3: + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + loader-utils@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" @@ -6102,6 +6374,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +locutus@^2.0.16: + version "2.0.16" + resolved "https://registry.yarnpkg.com/locutus/-/locutus-2.0.16.tgz#1da15532f1d735712a27e35a1caf0ccb7041f6b3" + integrity sha512-pGfl6Hb/1mXLzrX5kl5lH7gz25ey0vwQssZp8Qo2CEF59di6KrAgdFm+0pW8ghLnvNzzJGj5tlWhhv2QbK3jeQ== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -6142,11 +6419,18 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -6162,6 +6446,11 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -6361,11 +6650,26 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.4.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -6424,6 +6728,13 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== +mkdirp@^0.5.4: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + moo@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" @@ -6457,6 +6768,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -6708,7 +7024,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -6753,11 +7069,35 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ora@^4.0.2: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.1.1.tgz#566cc0348a15c36f5f0e979612842e02ba9dddbc" + integrity sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A== + dependencies: + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-spinners "^2.2.0" + is-interactive "^1.0.0" + log-symbols "^3.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -7660,6 +8000,11 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + raf@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" @@ -7796,6 +8141,19 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^2.2.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -7914,6 +8272,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + resolve-bin@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-bin/-/resolve-bin-1.0.1.tgz#795255591443e7007b21f2eadd8baa39b7378e50" @@ -7976,6 +8339,21 @@ resolve@^2.0.0-next.3: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -8023,6 +8401,11 @@ rtlcss@3.5.0: postcss "^8.3.11" strip-json-comments "^3.1.1" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-con@~1.2.10: version "1.2.11" resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.11.tgz#0014ed430bad034a60568dfe7de2235f32e3f3c4" @@ -8040,6 +8423,13 @@ run-parallel@^1.1.4, run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^6.6.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + rxjs@^7.5.4: version "7.5.6" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" @@ -8094,7 +8484,7 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" -schema-utils@^2.6.5: +schema-utils@^2.5.0, schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -8270,6 +8660,15 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.6, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-git@^3.5.0: + version "3.19.1" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-3.19.1.tgz#ff9c021961a3d876a1b115b1893bed9a28855d30" + integrity sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w== + dependencies: + "@kwsites/file-exists" "^1.1.1" + "@kwsites/promise-deferred" "^1.1.1" + debug "^4.3.4" + sirv@^1.0.7: version "1.0.19" resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" @@ -8783,7 +9182,7 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== -through@^2.3.8: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -8793,6 +9192,13 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -8868,7 +9274,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -8949,6 +9355,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" @@ -9025,6 +9436,15 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-3.0.0.tgz#9f1f11b371acf6e51ed15a50db635e02eec18368" + integrity sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A== + dependencies: + loader-utils "^1.2.3" + mime "^2.4.4" + schema-utils "^2.5.0" + url-loader@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" @@ -9123,6 +9543,13 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -9480,6 +9907,11 @@ yargs-parser@^21.0.0: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" @@ -9506,6 +9938,19 @@ yargs@^17.0.0: y18n "^5.0.5" yargs-parser "^21.0.0" +yargs@^17.3.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From 8b595e86ebe4c32a76d9aa281fd2f934e3e003c6 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:02:10 +1200 Subject: [PATCH 19/33] Keep time element within link --- mu-plugins/blocks/time/src/convert_times.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/convert_times.js index cf94a56b8..42c21e12c 100644 --- a/mu-plugins/blocks/time/src/convert_times.js +++ b/mu-plugins/blocks/time/src/convert_times.js @@ -60,13 +60,16 @@ function convertTimes() { localTime += formatTime( date ); + dateElement.innerText = localTime; + dateElement.removeAttribute( 'data-iso' ); + const linkElement = document.createElement( 'a' ); - linkElement.innerText = localTime; linkElement.setAttribute( 'href', `https://www.timeanddate.com/worldclock/fixedtime.html?iso=${ datetimeISO }` ); + linkElement.appendChild( dateElement.cloneNode( true ) ); dateElement.parentNode.replaceChild( linkElement, dateElement ); } } ); From 98cfec09b18249ebb4554fbcb25c153b7f6adcef Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:03:31 +1200 Subject: [PATCH 20/33] Use wp_script_add_data to output view script in footer Co-authored-by: Kelly Dwan --- mu-plugins/blocks/time/index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index 0f3843686..cd62fe38b 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -35,7 +35,8 @@ function() use ( $editor_script_handle ) { 'wp_enqueue_scripts', function() use ( $view_script_handle ) { if ( ! is_admin() ) { - wp_enqueue_script( $view_script_handle, null, null, filemtime( __DIR__ . '/build/convert_times.js' ), true ); + wp_enqueue_script( $view_script_handle ); + wp_script_add_data( $view_script_handle, 'group', 1 ); } } ); From 56efe04602785c3f546726bf720d9399dc11e542 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:08:52 +1200 Subject: [PATCH 21/33] Rename view script --- mu-plugins/blocks/time/src/block.json | 2 +- mu-plugins/blocks/time/src/{convert_times.js => view.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename mu-plugins/blocks/time/src/{convert_times.js => view.js} (100%) diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index ddb320d3a..b2a89a357 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -8,5 +8,5 @@ "description": "Attempts to parse a time string like Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone.", "textdomain": "wporg", "editorScript": "file:./index.js", - "viewScript": "file:./convert_times.js" + "viewScript": "file:./view.js" } diff --git a/mu-plugins/blocks/time/src/convert_times.js b/mu-plugins/blocks/time/src/view.js similarity index 100% rename from mu-plugins/blocks/time/src/convert_times.js rename to mu-plugins/blocks/time/src/view.js From 33a49c7a475f744f9f783a4c29ebe1be24f6f121 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:17:34 +1200 Subject: [PATCH 22/33] Fix regex to allow negative time offsets --- mu-plugins/blocks/time/src/index.js | 7 +++++-- mu-plugins/blocks/time/src/view.js | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 39eabc0fe..4b7de3537 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -60,12 +60,15 @@ const Edit = ( { isActive, onChange, value } ) => { return; } + const datetime = gmdate( 'c', time ); + const datetimeISO = gmdate( 'Ymd\\THi', time ); + onChange( toggleFormat( value, { type: name, attributes: { - datetime: gmdate( 'c', time ), - 'data-iso': gmdate( 'Ymd\\THi', time ), + datetime: datetime, + 'data-iso': datetimeISO, }, } ) ); diff --git a/mu-plugins/blocks/time/src/view.js b/mu-plugins/blocks/time/src/view.js index 42c21e12c..f77dbe21b 100644 --- a/mu-plugins/blocks/time/src/view.js +++ b/mu-plugins/blocks/time/src/view.js @@ -1,7 +1,7 @@ function convertTimes() { const parseDate = function ( text ) { const match = - /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\+([0-2]{1})([0-9]{1}):00$/.exec( + /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})([+-][0-2]{1}[0-9]{1}):00$/.exec( text ); From 3046990443531eeeae98cf7d50e6a06b2968e9d5 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 26 Jul 2023 10:40:31 +1200 Subject: [PATCH 23/33] Allow time tags in post content --- mu-plugins/blocks/time/index.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index cd62fe38b..dbc252c80 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -40,4 +40,25 @@ function() use ( $view_script_handle ) { } } ); + + add_filter( 'wp_kses_allowed_html', __NAMESPACE__ . '\add_time_to_allowed_html', 10, 2 ); +} + +/** + * Adds the `time` tag to the allowed HTML tags for the block editor. + * + * @param array $allowed_tags Allowed tags, attributes, and/or entities. + * @param string $context Context to judge allowed tags by. + * @return array Allowed tags, attributes, and/or entities. + */ +function add_time_to_allowed_html( $allowed_tags, $context ) { + if ( 'post' === $context ) { + $allowed_tags['time'] = array( + 'class' => true, + 'data-iso' => true, + 'datetime' => true, + ); + } + + return $allowed_tags; } From ff22ba4d0587903663302b8dc585a81ec7ffabc4 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 26 Jul 2023 10:41:07 +1200 Subject: [PATCH 24/33] Execute the view script once all resources have loaded --- mu-plugins/blocks/time/src/view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mu-plugins/blocks/time/src/view.js b/mu-plugins/blocks/time/src/view.js index f77dbe21b..9c5e8660e 100644 --- a/mu-plugins/blocks/time/src/view.js +++ b/mu-plugins/blocks/time/src/view.js @@ -75,6 +75,6 @@ function convertTimes() { } ); } -document.addEventListener( 'DOMContentLoaded', () => { +window.onload = () => { convertTimes(); -} ); +}; From e8884af8276818bfa9fadad8ce6173caf481747d Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 26 Jul 2023 10:45:37 +1200 Subject: [PATCH 25/33] Update descriptions --- mu-plugins/blocks/time/index.php | 3 ++- mu-plugins/blocks/time/src/block.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index dbc252c80..ac9449757 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -1,7 +1,8 @@ Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone. + * Description: Attempts to parse a time string like 'Tuesday, April 5th, at 15:00 UTC' relative to the post date, + * and creates a format that shows it in the viewer's local time zone. * * @package wporg */ diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index b2a89a357..f93c99d2a 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -5,7 +5,7 @@ "title": "Time", "icon": "calendar", "category": "common", - "description": "Attempts to parse a time string like Tuesday, April 5th 2022, at 15:00 UTC and creates a format that shows it in the viewers local time zone.", + "description": "Attempts to parse a time string like 'Tuesday, April 5th, at 15:00 UTC' relative to the post date, and creates a format that shows it in the viewer's local time zone.", "textdomain": "wporg", "editorScript": "file:./index.js", "viewScript": "file:./view.js" From af2572aebfa3f74f1c3e7487f41b1c378ae53e33 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:47:52 +1200 Subject: [PATCH 26/33] Style the time formatted strings --- mu-plugins/blocks/time/index.php | 8 +++++--- mu-plugins/blocks/time/postcss/style.pcss | 3 +++ mu-plugins/blocks/time/src/block.json | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 mu-plugins/blocks/time/postcss/style.pcss diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index ac9449757..af8dd3e09 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -21,17 +21,19 @@ function init() { $metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) ); $metadata['file'] = $metadata_file; - $editor_script_handle = register_block_script_handle( $metadata, 'editorScript', 0 ); + $editor_script_handle = register_block_script_handle( $metadata, 'editorScript' ); + $style_handle = register_block_style_handle( $metadata, 'style' ); add_action( 'enqueue_block_assets', - function() use ( $editor_script_handle ) { + function() use ( $editor_script_handle, $style_handle ) { if ( wp_should_load_block_editor_scripts_and_styles() && is_admin() ) { wp_enqueue_script( $editor_script_handle ); + wp_enqueue_style( $style_handle ); } } ); - $view_script_handle = register_block_script_handle( $metadata, 'viewScript', 0 ); + $view_script_handle = register_block_script_handle( $metadata, 'viewScript' ); add_action( 'wp_enqueue_scripts', function() use ( $view_script_handle ) { diff --git a/mu-plugins/blocks/time/postcss/style.pcss b/mu-plugins/blocks/time/postcss/style.pcss new file mode 100644 index 000000000..68b71592c --- /dev/null +++ b/mu-plugins/blocks/time/postcss/style.pcss @@ -0,0 +1,3 @@ +.wporg-time { + text-decoration: underline; +} diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index f93c99d2a..6f149cd25 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -8,5 +8,6 @@ "description": "Attempts to parse a time string like 'Tuesday, April 5th, at 15:00 UTC' relative to the post date, and creates a format that shows it in the viewer's local time zone.", "textdomain": "wporg", "editorScript": "file:./index.js", + "style": "file:./style.css", "viewScript": "file:./view.js" } From 2ff496250ad2964446aa9134ab8fdf25434194c8 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:51:58 +1200 Subject: [PATCH 27/33] Add block attribute config --- mu-plugins/blocks/time/src/block.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index 6f149cd25..797fc8a34 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -9,5 +9,15 @@ "textdomain": "wporg", "editorScript": "file:./index.js", "style": "file:./style.css", - "viewScript": "file:./view.js" + "viewScript": "file:./view.js", + "attributes": { + "datetime": { + "type": "string", + "default": "" + }, + "data-iso": { + "type": "string", + "default": "" + } + } } From 2b34bd6c6b5844429591fb4cd1486c139547a490 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:52:54 +1200 Subject: [PATCH 28/33] Remove the format if the time description is changed --- mu-plugins/blocks/time/src/index.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 4b7de3537..4917f0263 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -3,7 +3,7 @@ */ import { useSelect } from '@wordpress/data'; import { RichTextToolbarButton } from '@wordpress/block-editor'; -import { useCallback } from '@wordpress/element'; +import { useCallback, useEffect, useRef } from '@wordpress/element'; import { getTextContent, registerFormatType, slice, toggleFormat } from '@wordpress/rich-text'; /** @@ -18,8 +18,25 @@ import metadata from './block.json'; const { name, icon, title } = metadata; +// Return the first time description from the content, if present. +const getTimeFromContent = ( content ) => { + const tempElement = document.createElement( 'div' ); + tempElement.innerHTML = content; + + const wporgTimeElement = tempElement.querySelector( '.wporg-time' ); + + return wporgTimeElement ? wporgTimeElement.textContent : null; +}; + const Edit = ( { isActive, onChange, value } ) => { const { date_gmt } = useSelect( ( select ) => select( 'core/editor' ).getCurrentPost() ); + const { + attributes: { content }, + } = useSelect( ( select ) => { + return select( 'core/block-editor' ).getSelectedBlock(); + }, [] ); + const nextTime = getTimeFromContent( content ); + const timeRef = useRef( nextTime ); const toggleWithoutEnhancing = useCallback( () => { onChange( @@ -29,6 +46,15 @@ const Edit = ( { isActive, onChange, value } ) => { ); } ); + // If the timeRef description changes, toggle the format off. + useEffect( () => { + if ( timeRef.current && nextTime && timeRef.current !== nextTime ) { + toggleWithoutEnhancing(); + } + + timeRef.current = nextTime; + }, [ nextTime, timeRef ] ); + return ( Date: Wed, 2 Aug 2023 11:46:06 +1200 Subject: [PATCH 29/33] Handle multiple times in the selected block --- mu-plugins/blocks/time/src/index.js | 51 ++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 4917f0263..04b2a65c3 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -4,7 +4,7 @@ import { useSelect } from '@wordpress/data'; import { RichTextToolbarButton } from '@wordpress/block-editor'; import { useCallback, useEffect, useRef } from '@wordpress/element'; -import { getTextContent, registerFormatType, slice, toggleFormat } from '@wordpress/rich-text'; +import { getTextContent, registerFormatType, removeFormat, slice, toggleFormat } from '@wordpress/rich-text'; /** * External dependencies @@ -18,25 +18,23 @@ import metadata from './block.json'; const { name, icon, title } = metadata; -// Return the first time description from the content, if present. -const getTimeFromContent = ( content ) => { +// Find all the time elements in the block content, and return their text content as an array. +const getTimesFromContent = ( content ) => { const tempElement = document.createElement( 'div' ); tempElement.innerHTML = content; - const wporgTimeElement = tempElement.querySelector( '.wporg-time' ); + const timeElements = tempElement.querySelectorAll( '.wporg-time' ); - return wporgTimeElement ? wporgTimeElement.textContent : null; + return timeElements.length ? Array.from( timeElements ).map( ( timeElement ) => timeElement.textContent ) : []; }; const Edit = ( { isActive, onChange, value } ) => { const { date_gmt } = useSelect( ( select ) => select( 'core/editor' ).getCurrentPost() ); const { attributes: { content }, - } = useSelect( ( select ) => { - return select( 'core/block-editor' ).getSelectedBlock(); - }, [] ); - const nextTime = getTimeFromContent( content ); - const timeRef = useRef( nextTime ); + } = useSelect( ( select ) => select( 'core/block-editor' ).getSelectedBlock() ); + + const timesRef = useRef( [] ); const toggleWithoutEnhancing = useCallback( () => { onChange( @@ -46,14 +44,37 @@ const Edit = ( { isActive, onChange, value } ) => { ); } ); - // If the timeRef description changes, toggle the format off. + // If any of the times change, toggle the format off for that time. useEffect( () => { - if ( timeRef.current && nextTime && timeRef.current !== nextTime ) { - toggleWithoutEnhancing(); + const nextTimes = getTimesFromContent( content ); + + // If next and previous times are not the same length, + // then a format has been added or removed and we can skip comparison. + if ( nextTimes.length !== timesRef.current.length ) { + timesRef.current = nextTimes; + return; + } + + let index = 0; + while ( index < nextTimes.length ) { + const nextTime = nextTimes[ index ]; + + if ( timesRef.current[ index ] !== nextTime ) { + // find the start and end point of nextTime in the text + const start = value.text.indexOf( nextTime ); + const end = start + nextTime.length; + + onChange( removeFormat( value, name, start, end ) ); + + // exit to rerun this effect with the new times + break; + } + + index++; } - timeRef.current = nextTime; - }, [ nextTime, timeRef ] ); + timesRef.current = nextTimes; + }, [ content, timesRef ] ); return ( Date: Wed, 2 Aug 2023 12:24:02 +1200 Subject: [PATCH 30/33] Use dotted style for the underline --- mu-plugins/blocks/time/postcss/style.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/postcss/style.pcss b/mu-plugins/blocks/time/postcss/style.pcss index 68b71592c..4e03d5741 100644 --- a/mu-plugins/blocks/time/postcss/style.pcss +++ b/mu-plugins/blocks/time/postcss/style.pcss @@ -1,3 +1,3 @@ .wporg-time { - text-decoration: underline; + text-decoration: underline dotted; } From ea1dad6132df73bf94f494d31bf59dee379b5267 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:47:07 +1200 Subject: [PATCH 31/33] Add partial support for the Site Editor Use inline styles in editor and remove on frontend Handle post date being undefined and parse dates based on current time --- mu-plugins/blocks/time/index.php | 4 +--- mu-plugins/blocks/time/postcss/style.pcss | 3 --- mu-plugins/blocks/time/src/block.json | 5 ++++- mu-plugins/blocks/time/src/index.js | 7 +++++-- mu-plugins/blocks/time/src/view.js | 2 ++ 5 files changed, 12 insertions(+), 9 deletions(-) delete mode 100644 mu-plugins/blocks/time/postcss/style.pcss diff --git a/mu-plugins/blocks/time/index.php b/mu-plugins/blocks/time/index.php index af8dd3e09..dbf0cad52 100644 --- a/mu-plugins/blocks/time/index.php +++ b/mu-plugins/blocks/time/index.php @@ -22,13 +22,11 @@ function init() { $metadata['file'] = $metadata_file; $editor_script_handle = register_block_script_handle( $metadata, 'editorScript' ); - $style_handle = register_block_style_handle( $metadata, 'style' ); add_action( 'enqueue_block_assets', - function() use ( $editor_script_handle, $style_handle ) { + function() use ( $editor_script_handle ) { if ( wp_should_load_block_editor_scripts_and_styles() && is_admin() ) { wp_enqueue_script( $editor_script_handle ); - wp_enqueue_style( $style_handle ); } } ); diff --git a/mu-plugins/blocks/time/postcss/style.pcss b/mu-plugins/blocks/time/postcss/style.pcss deleted file mode 100644 index 4e03d5741..000000000 --- a/mu-plugins/blocks/time/postcss/style.pcss +++ /dev/null @@ -1,3 +0,0 @@ -.wporg-time { - text-decoration: underline dotted; -} diff --git a/mu-plugins/blocks/time/src/block.json b/mu-plugins/blocks/time/src/block.json index 797fc8a34..9450adb19 100644 --- a/mu-plugins/blocks/time/src/block.json +++ b/mu-plugins/blocks/time/src/block.json @@ -8,7 +8,6 @@ "description": "Attempts to parse a time string like 'Tuesday, April 5th, at 15:00 UTC' relative to the post date, and creates a format that shows it in the viewer's local time zone.", "textdomain": "wporg", "editorScript": "file:./index.js", - "style": "file:./style.css", "viewScript": "file:./view.js", "attributes": { "datetime": { @@ -18,6 +17,10 @@ "data-iso": { "type": "string", "default": "" + }, + "style": { + "type": "string", + "default": "" } } } diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index 04b2a65c3..fc7de71f7 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -96,8 +96,10 @@ const Edit = ( { isActive, onChange, value } ) => { // strtotime understands "GMT" better than "UTC" for timezones. dateCleaned.replace( 'UTC', 'GMT' ); - // Try to parse the time, relative to the post time. - const postTimestamp = strtotime( date_gmt ); + // Try to parse the time, relative to the post time, if available + // In the Site Editor the post time is not available, so we'll just use the current time. + // TODO: https://github.com/WordPress/wporg-mu-plugins/issues/422 + const postTimestamp = !! date_gmt ? strtotime( date_gmt ) : undefined; const time = strtotime( dateCleaned, postTimestamp ); // If that didn't work, give up. @@ -116,6 +118,7 @@ const Edit = ( { isActive, onChange, value } ) => { attributes: { datetime: datetime, 'data-iso': datetimeISO, + style: 'text-decoration: underline dotted', }, } ) ); diff --git a/mu-plugins/blocks/time/src/view.js b/mu-plugins/blocks/time/src/view.js index 9c5e8660e..64732cf03 100644 --- a/mu-plugins/blocks/time/src/view.js +++ b/mu-plugins/blocks/time/src/view.js @@ -62,6 +62,8 @@ function convertTimes() { dateElement.innerText = localTime; dateElement.removeAttribute( 'data-iso' ); + // Remove the dotted underline style applied for the editor only + dateElement.style.textDecoration = ''; const linkElement = document.createElement( 'a' ); linkElement.setAttribute( From b3a0b0ea61a674ef0dc22e59c05727f88b41f24e Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:58:43 +1200 Subject: [PATCH 32/33] Update yoast/phpunit-polyfills to satisfy CI --- composer.json | 2 +- composer.lock | 107 +++++++++++++++++++++++++------------------------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/composer.json b/composer.json index 11a600593..b307f0760 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "wp-coding-standards/wpcs": "2.*", "wp-phpunit/wp-phpunit": "~6.0", "wporg/wporg-repo-tools": "dev-trunk", - "yoast/phpunit-polyfills": "^1.0" + "yoast/phpunit-polyfills": "^1.1" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 54eed8c43..4b76cd13e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d6c8f14ae0c6a73d1bb3e8a81422f7b1", + "content-hash": "c548ae2328efc93658715e1a6f8613c7", "packages": [ { "name": "adhocore/jwt", @@ -293,30 +293,30 @@ }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -343,7 +343,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -359,7 +359,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "myclabs/deep-copy", @@ -422,16 +422,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -472,9 +472,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -763,16 +763,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "version": "9.2.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", "shasum": "" }, "require": { @@ -828,7 +828,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" }, "funding": [ { @@ -836,7 +837,7 @@ "type": "github" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-07-26T13:44:30+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1081,16 +1082,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.9", + "version": "9.6.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a9aceaf20a682aeacf28d582654a1670d8826778" + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778", - "reference": "a9aceaf20a682aeacf28d582654a1670d8826778", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0", "shasum": "" }, "require": { @@ -1164,7 +1165,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.9" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" }, "funding": [ { @@ -1180,7 +1181,7 @@ "type": "tidelift" } ], - "time": "2023-06-11T06:13:56+00:00" + "time": "2023-08-19T07:10:56+00:00" }, { "name": "sebastian/cli-parser", @@ -1688,16 +1689,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -1740,7 +1741,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -1748,7 +1749,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -2306,16 +2307,16 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.2.0", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", - "reference": "3b7ab767dde017dec9327cc024e9f26fd776a57b" + "reference": "4797791a311c41d213027333e4fcc48073f77df0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/3b7ab767dde017dec9327cc024e9f26fd776a57b", - "reference": "3b7ab767dde017dec9327cc024e9f26fd776a57b", + "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/4797791a311c41d213027333e4fcc48073f77df0", + "reference": "4797791a311c41d213027333e4fcc48073f77df0", "shasum": "" }, "type": "library", @@ -2350,7 +2351,7 @@ "issues": "https://github.com/wp-phpunit/issues", "source": "https://github.com/wp-phpunit/wp-phpunit" }, - "time": "2023-03-30T01:15:51+00:00" + "time": "2023-08-09T01:26:57+00:00" }, { "name": "wporg/wporg-repo-tools", @@ -2358,12 +2359,12 @@ "source": { "type": "git", "url": "https://github.com/WordPress/wporg-repo-tools.git", - "reference": "926e9776aaab7bb8ce2fa2a7feaa6a9f2169fe69" + "reference": "d78f1cf7dc04d96a511a14a23c4ddbe1d4d51499" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/wporg-repo-tools/zipball/926e9776aaab7bb8ce2fa2a7feaa6a9f2169fe69", - "reference": "926e9776aaab7bb8ce2fa2a7feaa6a9f2169fe69", + "url": "https://api.github.com/repos/WordPress/wporg-repo-tools/zipball/d78f1cf7dc04d96a511a14a23c4ddbe1d4d51499", + "reference": "d78f1cf7dc04d96a511a14a23c4ddbe1d4d51499", "shasum": "" }, "default-branch": true, @@ -2380,20 +2381,20 @@ "issues": "https://github.com/WordPress/wporg-repo-tools/issues", "source": "https://github.com/WordPress/wporg-repo-tools/tree/trunk" }, - "time": "2022-11-16T17:56:26+00:00" + "time": "2023-08-01T17:27:15+00:00" }, { "name": "yoast/phpunit-polyfills", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "3b59adeef77fb1c03ff5381dbb9d68b0aaff3171" + "reference": "224e4a1329c03d8bad520e3fc4ec980034a4b212" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/3b59adeef77fb1c03ff5381dbb9d68b0aaff3171", - "reference": "3b59adeef77fb1c03ff5381dbb9d68b0aaff3171", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/224e4a1329c03d8bad520e3fc4ec980034a4b212", + "reference": "224e4a1329c03d8bad520e3fc4ec980034a4b212", "shasum": "" }, "require": { @@ -2440,7 +2441,7 @@ "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2023-03-30T23:39:05+00:00" + "time": "2023-08-19T14:25:08+00:00" } ], "aliases": [], @@ -2452,5 +2453,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.3.0" } From fa1676833367d9e91b016625b4278a5ea0a866f5 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:27:00 +1200 Subject: [PATCH 33/33] Fix editor styles in Safari --- mu-plugins/blocks/time/src/index.js | 2 +- mu-plugins/blocks/time/src/view.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/time/src/index.js b/mu-plugins/blocks/time/src/index.js index fc7de71f7..fe11a6c9e 100644 --- a/mu-plugins/blocks/time/src/index.js +++ b/mu-plugins/blocks/time/src/index.js @@ -118,7 +118,7 @@ const Edit = ( { isActive, onChange, value } ) => { attributes: { datetime: datetime, 'data-iso': datetimeISO, - style: 'text-decoration: underline dotted', + style: 'text-decoration: underline; text-decoration-style: dotted', }, } ) ); diff --git a/mu-plugins/blocks/time/src/view.js b/mu-plugins/blocks/time/src/view.js index 64732cf03..625744aea 100644 --- a/mu-plugins/blocks/time/src/view.js +++ b/mu-plugins/blocks/time/src/view.js @@ -64,6 +64,7 @@ function convertTimes() { dateElement.removeAttribute( 'data-iso' ); // Remove the dotted underline style applied for the editor only dateElement.style.textDecoration = ''; + dateElement.style.textDecorationStyle = ''; const linkElement = document.createElement( 'a' ); linkElement.setAttribute(