Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,47 @@ addAction(
- args _`{Object}`_ By default, this is an object containing the `element`, `pattern`, `text` and `status`.
<br/>

#### `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.
<br/>

#### `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:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
10 changes: 8 additions & 2 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions search-replace-for-block-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -46,7 +46,7 @@
'wp-plugins',
'wp-edit-post',
],
'1.4.0',
'1.6.0',
false,
);

Expand Down
66 changes: 47 additions & 19 deletions src/core/app.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -190,33 +190,61 @@ 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 ]
) {
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 ) {
Expand Down
53 changes: 51 additions & 2 deletions src/core/filters.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addAction } from '@wordpress/hooks';
import { addAction, addFilter } from '@wordpress/hooks';

/**
* Replace Block Attribute.
Expand All @@ -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':
Expand All @@ -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,
};
}
}
);