From 45d4f2611d76a2af3890d05a18da1e356d9f7c66 Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 14:15:26 -0500 Subject: [PATCH 1/6] Create validateInput utility --- .../editor/js/src/utils/test/validateInput.ts | 37 +++++++++++++++++++ .../editor/js/src/utils/validateInput.ts | 15 ++++++++ 2 files changed, 52 insertions(+) create mode 100644 wp-modules/editor/js/src/utils/test/validateInput.ts create mode 100644 wp-modules/editor/js/src/utils/validateInput.ts diff --git a/wp-modules/editor/js/src/utils/test/validateInput.ts b/wp-modules/editor/js/src/utils/test/validateInput.ts new file mode 100644 index 00000000..6e837250 --- /dev/null +++ b/wp-modules/editor/js/src/utils/test/validateInput.ts @@ -0,0 +1,37 @@ +import { checkIllegalChars, stripIllegalChars } from '../validateInput'; + +const regexPattern = new RegExp( /([^a-z0-9 -]+)/gi ); + +describe( 'validateInput', () => { + describe( 'checkIllegalChars', () => { + it.each( [ + [ '', null ], + [ 'Nothing to strip', null ], + [ 'String with !#@$%^&*() illegal chars', [ '!#@$%^&*()' ] ], + [ + 'String !#@$% with ^&*() separated \'"? illegal []{}|/ chars', + [ '!#@$%', '^&*()', '\'"?', '[]{}|/' ], + ], + ] )( 'matches the illegal characters', ( input, expected ) => { + expect( checkIllegalChars( input, regexPattern ) ).toEqual( + expected + ); + } ); + } ); + describe( 'stripIllegalChars', () => { + it.each( [ + [ '', '' ], + [ 'Nothing to strip', 'Nothing to strip' ], + [ + 'String with !#@$%^&*() illegal chars', + 'String with illegal chars', + ], + [ + "This might've caused a whitescreen previously!", + 'This mightve caused a whitescreen previously', + ], + ] )( 'strips the illegal characters', ( input, expected ) => { + expect( stripIllegalChars( input, regexPattern ) ).toBe( expected ); + } ); + } ); +} ); diff --git a/wp-modules/editor/js/src/utils/validateInput.ts b/wp-modules/editor/js/src/utils/validateInput.ts new file mode 100644 index 00000000..3e6df2da --- /dev/null +++ b/wp-modules/editor/js/src/utils/validateInput.ts @@ -0,0 +1,15 @@ +const defaultPattern = new RegExp( /([^a-z0-9 -]+)/gi ); + +export function checkIllegalChars( + input: string, + regexPattern = defaultPattern +) { + return input.match( regexPattern ); +} + +export function stripIllegalChars( + input: string, + regexPattern = defaultPattern +) { + return input.replace( regexPattern, '' ); +} From ca0e239208c944ca5c5b18143381c0903c9219c0 Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 14:17:04 -0500 Subject: [PATCH 2/6] Use the new util; style the input for illegal chars --- .../SidebarPanels/CategoriesPanel.tsx | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx index 5cd991f5..2772dfc9 100644 --- a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx +++ b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx @@ -1,4 +1,5 @@ import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; import { Spinner } from '@wordpress/components'; @@ -7,6 +8,10 @@ import Creatable from 'react-select/creatable'; import toKebabCase from '../../utils/toKebabCase'; import getSelectedOptions from '../../utils/getSelectedOptions'; import getCustomCategories from '../../utils/getCustomCategories'; +import { + checkIllegalChars, + stripIllegalChars, +} from '../../utils/validateInput'; import type { BaseSidebarProps, AdditionalSidebarProps } from './types'; /** @@ -20,6 +25,9 @@ export default function CategoriesPanel( { handleChange, }: BaseSidebarProps< 'categories' | 'customCategories' > & AdditionalSidebarProps< 'categoryOptions' > ) { + const [ categoryTitleIsInvalid, setCategoryTitleIsInvalid ] = + useState( false ); + return ( { handleChange( 'customCategories', - [ ...customCategories, newCategoryTitle ], + [ + ...customCategories, + stripIllegalChars( newCategoryTitle ), + ], { categories: [ ...categories, @@ -64,12 +75,26 @@ export default function CategoriesPanel( { } ); } } + onInputChange={ ( event ) => { + setCategoryTitleIsInvalid( + !! checkIllegalChars( event ) + ); + } } menuPlacement="auto" styles={ { menu: ( base ) => ( { ...base, zIndex: 100, } ), + control: ( baseStyles ) => ( { + ...baseStyles, + borderColor: categoryTitleIsInvalid + ? 'red !important' + : baseStyles.borderColor, + boxShadow: categoryTitleIsInvalid + ? '0 0 0 1px red' + : baseStyles.boxShadow, + } ), } } /> ) : ( From 6f9e72628986815ce58409fd6ebade7c38a4d233 Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 14:28:40 -0500 Subject: [PATCH 3/6] Format the creation text to also strip illegal chars --- .../editor/js/src/components/SidebarPanels/CategoriesPanel.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx index 2772dfc9..6312ee70 100644 --- a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx +++ b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx @@ -80,6 +80,9 @@ export default function CategoriesPanel( { !! checkIllegalChars( event ) ); } } + formatCreateLabel={ ( userInput ) => + `Create "${ stripIllegalChars( userInput ) }"` + } menuPlacement="auto" styles={ { menu: ( base ) => ( { From 0e133b28fb64ff10e8813ccd7a6c465fef64dd7c Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 20:22:12 -0500 Subject: [PATCH 4/6] Use Ryan's suggestion and return a bool from util; update name to hasIllegalChars --- .../SidebarPanels/CategoriesPanel.tsx | 9 ++------- .../editor/js/src/utils/test/validateInput.ts | 17 ++++++----------- wp-modules/editor/js/src/utils/validateInput.ts | 4 ++-- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx index 6312ee70..e2a6a22c 100644 --- a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx +++ b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx @@ -8,10 +8,7 @@ import Creatable from 'react-select/creatable'; import toKebabCase from '../../utils/toKebabCase'; import getSelectedOptions from '../../utils/getSelectedOptions'; import getCustomCategories from '../../utils/getCustomCategories'; -import { - checkIllegalChars, - stripIllegalChars, -} from '../../utils/validateInput'; +import { hasIllegalChars, stripIllegalChars } from '../../utils/validateInput'; import type { BaseSidebarProps, AdditionalSidebarProps } from './types'; /** @@ -76,9 +73,7 @@ export default function CategoriesPanel( { ); } } onInputChange={ ( event ) => { - setCategoryTitleIsInvalid( - !! checkIllegalChars( event ) - ); + setCategoryTitleIsInvalid( hasIllegalChars( event ) ); } } formatCreateLabel={ ( userInput ) => `Create "${ stripIllegalChars( userInput ) }"` diff --git a/wp-modules/editor/js/src/utils/test/validateInput.ts b/wp-modules/editor/js/src/utils/test/validateInput.ts index 6e837250..9faa8cf3 100644 --- a/wp-modules/editor/js/src/utils/test/validateInput.ts +++ b/wp-modules/editor/js/src/utils/test/validateInput.ts @@ -1,21 +1,16 @@ -import { checkIllegalChars, stripIllegalChars } from '../validateInput'; +import { hasIllegalChars, stripIllegalChars } from '../validateInput'; const regexPattern = new RegExp( /([^a-z0-9 -]+)/gi ); describe( 'validateInput', () => { describe( 'checkIllegalChars', () => { it.each( [ - [ '', null ], - [ 'Nothing to strip', null ], - [ 'String with !#@$%^&*() illegal chars', [ '!#@$%^&*()' ] ], - [ - 'String !#@$% with ^&*() separated \'"? illegal []{}|/ chars', - [ '!#@$%', '^&*()', '\'"?', '[]{}|/' ], - ], + [ '', false ], + [ 'Nothing to strip', false ], + [ "String that might've been a problem", true ], + [ 'String with !#@$% illegal ^&*() chars', true ], ] )( 'matches the illegal characters', ( input, expected ) => { - expect( checkIllegalChars( input, regexPattern ) ).toEqual( - expected - ); + expect( hasIllegalChars( input, regexPattern ) ).toBe( expected ); } ); } ); describe( 'stripIllegalChars', () => { diff --git a/wp-modules/editor/js/src/utils/validateInput.ts b/wp-modules/editor/js/src/utils/validateInput.ts index 3e6df2da..c94f44b4 100644 --- a/wp-modules/editor/js/src/utils/validateInput.ts +++ b/wp-modules/editor/js/src/utils/validateInput.ts @@ -1,10 +1,10 @@ const defaultPattern = new RegExp( /([^a-z0-9 -]+)/gi ); -export function checkIllegalChars( +export function hasIllegalChars( input: string, regexPattern = defaultPattern ) { - return input.match( regexPattern ); + return !! input.match( regexPattern ); } export function stripIllegalChars( From 2dbe12902486c7954911b2e91ab13614f2277f6b Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 20:23:51 -0500 Subject: [PATCH 5/6] Make sure categories array also gets the validated title --- .../src/components/SidebarPanels/CategoriesPanel.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx index e2a6a22c..cfce563f 100644 --- a/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx +++ b/wp-modules/editor/js/src/components/SidebarPanels/CategoriesPanel.tsx @@ -58,16 +58,16 @@ export default function CategoriesPanel( { } ); } } onCreateOption={ ( newCategoryTitle ) => { + const validatedTitle = + stripIllegalChars( newCategoryTitle ); + handleChange( 'customCategories', - [ - ...customCategories, - stripIllegalChars( newCategoryTitle ), - ], + [ ...customCategories, validatedTitle ], { categories: [ ...categories, - toKebabCase( newCategoryTitle ), + toKebabCase( validatedTitle ), ], } ); From 00bee102d3844673762733e51ae380238a1a35f1 Mon Sep 17 00:00:00 2001 From: Michael Day Date: Thu, 15 Jun 2023 20:32:43 -0500 Subject: [PATCH 6/6] Fix a typo in text case decription --- wp-modules/editor/js/src/utils/test/validateInput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wp-modules/editor/js/src/utils/test/validateInput.ts b/wp-modules/editor/js/src/utils/test/validateInput.ts index 9faa8cf3..c6a99d49 100644 --- a/wp-modules/editor/js/src/utils/test/validateInput.ts +++ b/wp-modules/editor/js/src/utils/test/validateInput.ts @@ -3,7 +3,7 @@ import { hasIllegalChars, stripIllegalChars } from '../validateInput'; const regexPattern = new RegExp( /([^a-z0-9 -]+)/gi ); describe( 'validateInput', () => { - describe( 'checkIllegalChars', () => { + describe( 'hasIllegalChars', () => { it.each( [ [ '', false ], [ 'Nothing to strip', false ],