diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22a7f19..1ce7f5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## 1.6.0
+* Feat: Add search and replace functionality for __Table Block__.
+* Feat: Add new custom hook `search-replace-for-block-editor.handleAttributeReplacement`.
+* Docs: Update README docs.
+* Tested up to WP 6.8.
+
## 1.5.0
* Fix: Missing icon due to recent WP 6.8 upgrade.
* Feat: Add local WP dev env.
diff --git a/README.md b/README.md
index e32c4c5..29e71c6 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,47 @@ addAction(
- args _`{Object}`_ By default, this is an object containing the `element`, `pattern`, `text` and `status`.
+#### `search-replace-for-block-editor.handleAttributeReplacement`
+
+This custom hook (filter) provides a way to modify how the search and replace functionality works for custom attributes for e.g. non-text attributes or objects.
+
+```js
+import { addFilter } from '@wordpress/hooks';
+
+addFilter(
+ 'search-replace-for-block-editor.handleAttributeReplacement',
+ 'yourNamespace',
+ ( oldAttr, args ) => {
+ const { name, pattern, handleAttributeReplacement } = args;
+
+ if ( 'your-custom-block' === name ) {
+ const newAttr = oldAttr.replace(
+ pattern,
+ handleAttributeReplacement
+ );
+
+ return {
+ newAttr,
+ isChanged: oldAttr === newAttr,
+ };
+ }
+
+ return {
+ newAttr: oldAttr,
+ isChanged: false,
+ };
+ }
+);
+```
+
+**Parameters**
+
+- oldAttr _`{any}`_ Old Attribute.
+- name _`{string}`_ Name of Block.
+- pattern _`{RegExp}`_ Regular Expression pattern.
+- handleAttributeReplacement _`{Function}`_ Replace Callback.
+
+
#### `search-replace-for-block-editor.keyboardShortcut`
This custom hook (filter) provides a way for users to specify their preferred keyboard shortcut option. For e.g to use the 'K' option on your keyboard, you could do like so:
diff --git a/package.json b/package.json
index 82176fc..b021305 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "search-and-replace",
- "version": "1.5.0",
+ "version": "1.6.0",
"description": "Search and Replace text within the Block Editor.",
"author": "badasswp",
"license": "GPL-2.0-or-later",
diff --git a/readme.txt b/readme.txt
index c9f7f78..fff5b2e 100644
--- a/readme.txt
+++ b/readme.txt
@@ -2,8 +2,8 @@
Contributors: badasswp, rajanand346, jargovi
Tags: search, replace, text, block, editor.
Requires at least: 6.0
-Tested up to: 6.7.2
-Stable tag: 1.5.0
+Tested up to: 6.8
+Stable tag: 1.6.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -63,6 +63,12 @@ Want to add your personal touch? All of our documentation can be found [here](ht
== Changelog ==
+= 1.6.0 =
+* Feat: Add search and replace functionality for __Table Block__.
+* Feat: Add new custom hook `search-replace-for-block-editor.handleAttributeReplacement`.
+* Docs: Update README docs.
+* Tested up to WP 6.8.
+
= 1.5.0 =
* Fix: Missing icon due to recent WP 6.8 upgrade.
* Feat: Add local WP dev env.
diff --git a/search-replace-for-block-editor.php b/search-replace-for-block-editor.php
index c3d350a..4575535 100644
--- a/search-replace-for-block-editor.php
+++ b/search-replace-for-block-editor.php
@@ -3,7 +3,7 @@
* Plugin Name: Search and Replace for Block Editor
* Plugin URI: https://github.com/badasswp/search-and-replace
* Description: Search and Replace text within the Block Editor.
- * Version: 1.5.0
+ * Version: 1.6.0
* Author: badasswp
* Author URI: https://github.com/badasswp
* License: GPL v2 or later
@@ -46,7 +46,7 @@
'wp-plugins',
'wp-edit-post',
],
- '1.4.0',
+ '1.6.0',
false,
);
diff --git a/src/core/app.tsx b/src/core/app.tsx
index c0c9995..91ce729 100644
--- a/src/core/app.tsx
+++ b/src/core/app.tsx
@@ -1,6 +1,6 @@
import { __ } from '@wordpress/i18n';
import { search } from '@wordpress/icons';
-import { doAction } from '@wordpress/hooks';
+import { applyFilters, doAction } from '@wordpress/hooks';
import { dispatch, select } from '@wordpress/data';
import { useState, useEffect } from '@wordpress/element';
import {
@@ -33,12 +33,12 @@ import '../styles/app.scss';
* @return {JSX.Element} Search & Replace for Block Editor.
*/
const SearchReplaceForBlockEditor = (): JSX.Element => {
- const [ replacements, setReplacements ] = useState( 0 );
- const [ isModalVisible, setIsModalVisible ] = useState( false );
- const [ searchInput, setSearchInput ] = useState( '' );
- const [ replaceInput, setReplaceInput ] = useState( '' );
- const [ caseSensitive, setCaseSensitive ] = useState( false );
- const [ context, setContext ] = useState( false );
+ const [ replacements, setReplacements ] = useState< number >( 0 );
+ const [ isModalVisible, setIsModalVisible ] = useState< boolean >( false );
+ const [ searchInput, setSearchInput ] = useState< string >( '' );
+ const [ replaceInput, setReplaceInput ] = useState< string >( '' );
+ const [ caseSensitive, setCaseSensitive ] = useState< boolean >( false );
+ const [ context, setContext ] = useState< boolean >( false );
/**
* Open Modal.
@@ -190,10 +190,13 @@ const SearchReplaceForBlockEditor = (): JSX.Element => {
*/
const replaceBlockAttribute = ( args: any, attribute: string ): void => {
const property = {};
- const { pattern, text, element, status } = args;
- const { attributes, clientId } = element;
+ const {
+ pattern,
+ text,
+ element: { attributes, clientId, name },
+ status,
+ } = args;
- // Bail out, if attribute is not defined.
if (
undefined === attributes ||
undefined === attributes[ attribute ]
@@ -201,22 +204,47 @@ const SearchReplaceForBlockEditor = (): JSX.Element => {
return;
}
- // Get and replace matched strings.
- const oldString: string =
- attributes[ attribute ].text || attributes[ attribute ];
+ const oldAttr = attributes[ attribute ].text || attributes[ attribute ];
- const newString: string = oldString.replace( pattern, () => {
- setReplacements( ( items ) => items + 1 );
+ /**
+ * Replace Callback.
+ *
+ * @return {string} Replacement Text.
+ */
+ const handleAttributeReplacement = (): string => {
+ setReplacements( ( items: number ) => items + 1 );
return text;
- } );
+ };
+
+ /**
+ * Filter the way we handle the attribute replacement
+ * to cater for special types of blocks.
+ *
+ * @since 1.6.0
+ *
+ * @param {any} oldAttr Old Attribute.
+ * @param {string} name Block Name.
+ * @param {RegExp} pattern Search pattern.
+ * @param {Function} handleAttributeReplacement Handle Attribute Replacement.
+ *
+ * @return {Object}
+ */
+ const { newAttr, isChanged } = applyFilters(
+ 'search-replace-for-block-editor.handleAttributeReplacement',
+ oldAttr,
+ {
+ name,
+ pattern,
+ handleAttributeReplacement,
+ }
+ ) as { newAttr: any; isChanged: boolean };
- // Bail out, if no change.
- if ( newString === oldString ) {
+ if ( ! isChanged ) {
return;
}
// Set the property attribute.
- property[ attribute ] = newString;
+ property[ attribute ] = newAttr;
// Update block property or content (if replace).
if ( status ) {
diff --git a/src/core/filters.tsx b/src/core/filters.tsx
index 2fa095e..cfe03f9 100644
--- a/src/core/filters.tsx
+++ b/src/core/filters.tsx
@@ -1,4 +1,4 @@
-import { addAction } from '@wordpress/hooks';
+import { addAction, addFilter } from '@wordpress/hooks';
/**
* Replace Block Attribute.
@@ -16,7 +16,7 @@ import { addAction } from '@wordpress/hooks';
*/
addAction(
'search-replace-for-block-editor.replaceBlockAttribute',
- 'yourBlock',
+ 'srfbe',
( replaceBlockAttribute, name, args ) => {
switch ( name ) {
case 'core/quote':
@@ -32,9 +32,58 @@ addAction(
replaceBlockAttribute( args, 'summary' );
break;
+ case 'core/table':
+ replaceBlockAttribute( args, 'body' );
+ break;
+
default:
replaceBlockAttribute( args, 'content' );
break;
}
}
);
+
+/**
+ * Filter the way we handle the attribute replacement
+ * to cater for special types of blocks.
+ *
+ * @since 1.6.0
+ *
+ * @param {any} oldAttr Old Attribute.
+ * @param {string} name Block Name.
+ * @param {RegExp} pattern Search pattern.
+ * @param {Function} handleAttributeReplacement Handle Attribute Replacement.
+ *
+ * @return {Object}
+ */
+addFilter(
+ 'search-replace-for-block-editor.handleAttributeReplacement',
+ 'srfbe',
+ ( oldAttr, args ) => {
+ const { name, pattern, handleAttributeReplacement } = args;
+
+ switch ( name ) {
+ case 'core/table':
+ const tableString: string = JSON.stringify( oldAttr ).replace(
+ pattern,
+ handleAttributeReplacement
+ );
+
+ return {
+ newAttr: JSON.parse( tableString ),
+ isChanged: tableString !== JSON.stringify( oldAttr ),
+ };
+
+ default:
+ const defaultString: string = oldAttr.replace(
+ pattern,
+ handleAttributeReplacement
+ );
+
+ return {
+ newAttr: defaultString,
+ isChanged: defaultString !== oldAttr,
+ };
+ }
+ }
+);