• Andry

    (@blackstar1991)


    I try create create Gutenberg element for my site. I use <TextControl> Component for this task.

    Now I need undertand how to make sanitize data into value of input of this component. I don’t need that users can write somthing like

    <script>alert("OK")</script>

    into input. My code look like:

    import "./index.scss"
    import {TextControl, Flex, FlexBlock, FlexItem, Button, Icon, PanelBody, PanelRow, ColorPicker} from '@wordpress/components'
    import {InspectorControls, BlockControls, AlignmentToolbar, useBlockProps } from '@wordpress/block-editor'
    import { __ } from '@wordpress/i18n'
    import { sanitizeText } from '@wordpress/dom';
    
    wp.blocks.registerBlockType(
        'gcb/custom-questionnaire', {
            title: __('Questionnaire block', 'gcb'),
            description: __('Gives your audience to do a survey of important issues', 'gcb'),
            icon: 'editor-help',
            category: 'text',
            attributes: {
                question: {type: "string"},
                answers: {type: "array", default: [""]},
                correctAnswer: {type:"number", default: undefined},
                theAlignment: {type:"string", default:"left"}
            },
    
            example:{
              attributes:{
                  question: __('What are the three basic questions of life?', 'gcb'),
                  correctAnswer: 3,
                  answers: [__('Who am I?', 'gcb'), __('Why am I here?', 'gcb'), __('What happens after I die?', 'gcb')],
                  theAlignment: "center",
              }
            },
    
            edit: EditComponent,
            save: function (props) {
                return null
            }
        })
    
    function EditComponent(props) {
        const blockProps = useBlockProps({
            className:"gcb_adm__box",
    
            }
        )
    
        function updateQuestion(value){
            const sanitizedValue = sanitizeText(value, 'text');
            props.setAttributes({question: sanitizedValue})
        }
    
        function deleteAnswer(indexToDelete){
            const newAnswers = props.attributes.answers.filter(
                function (x, index){
                    return index !== indexToDelete
                }
            );
            props.setAttributes({ answers:newAnswers})
    
            if( indexToDelete === props.attributes.correctAnswer){
                props.setAttributes( {correctAnswer: undefined})
            }
        }
    
    
    
        function markAsCorrect(index){
            props.setAttributes({correctAnswer: index})
        }
    
    
    
        return (
            <div  {...blockProps} >
    
                <BlockControls>
                    <AlignmentToolbar value={props.attributes.theAlignment} onChange={x => props.setAttributes({theAlignment: x})} />
                </BlockControls>
    
                <InspectorControls>
                    <PanelBody title={__("Supplementing questionnaire data", 'gcb')} initialOpen={true}>
                        <PanelRow>
                            test
                        </PanelRow>
                    </PanelBody>
                </InspectorControls>
    
    
                <TextControl label={__("Write name of Questionnaire", 'gcb')} value={ props.attributes.question} onChange={updateQuestion}  style={{fontSize: "20px"}} />
                <p style={{fontSize:"13px", margin: "20px 0 8px 0"}}>{__('Answers:', 'gcb')}</p>
    
                {/* SET data for all answers */}
                {props.attributes.answers.map(function (answer, index){
                    return (
                        <Flex>
                            <FlexBlock>
                                <TextControl  value={answer} onChange={newValue => {
                                    const newAnswers = props.attributes.answers.concat([]);
                                    newAnswers[index] = newValue
                                    props.setAttributes({ answers: newAnswers})
                                } } />
                            </FlexBlock>
                            <FlexItem>
                                <Button onClick={ () => markAsCorrect(index) }>
                                    <Icon className={"gcb_icon-star"} icon={ props.attributes.correctAnswer === index ? 'star-filled' : 'star-empty' } />
                                </Button>
                            </FlexItem>
                            <FlexItem>
                                <Button className={"gcb_delete"} onClick={ () => deleteAnswer(index) }>{__('Delete', 'gcb')}</Button>
                            </FlexItem>
                        </Flex>
                    )
                } )}
                <Button isPrimary className={"gcb_addNew__button"} onClick={ () => {
                    props.setAttributes({answers: props.attributes.answers.concat([""])})
                }} >{__('Add another answer', 'gcb')}</Button>
            </div>
        )
    }

    Function updateQuestion does not work correctly. I don’t understand why.

Viewing 3 replies - 1 through 3 (of 3 total)
  • The updateQuestion function in your code uses the sanitizeText function from the @wordpress/dom package, which is designed to sanitize HTML content. However, since you only allow plain text input in the TextControl component, you should use the sanitizeText function from the @wordpress/server-side-render package instead.

    You can import and use it like this:

    import { sanitizeText } from '@wordpress/server-side-render';
    
    function updateQuestion(value) {
      const sanitizedValue = sanitizeText(value);
      props.setAttributes({ question: sanitizedValue });
    }

    This should sanitize the user input and remove any HTML tags and attributes to prevent potential security issues.

    Thread Starter Andry

    (@blackstar1991)

    I tried the option you suggested

    import "./index.scss"
    import {TextControl, Flex, FlexBlock, FlexItem, Button, Icon, PanelBody, PanelRow, ColorPicker} from '@wordpress/components'
    import {InspectorControls, BlockControls, AlignmentToolbar, useBlockProps } from '@wordpress/block-editor'
    import { __ } from '@wordpress/i18n'
    import {sanitizeText} from '@wordpress/server-side-render';
    
    wp.blocks.registerBlockType(
        'gcb/custom-questionnaire', {
            title: __('Questionnaire block', 'gcb'),
            description: __('Gives your audience to do a survey of important issues', 'gcb'),
            icon: 'editor-help',
            category: 'text',
            attributes: {
                question: {type: "string"},
                answers: {type: "array", default: [""]},
                correctAnswer: {type:"number", default: undefined},
                theAlignment: {type:"string", default:"left"}
            },
    
            example:{
              attributes:{
                  question: __('What are the three basic questions of life?', 'gcb'),
                  correctAnswer: 3,
                  answers: [__('Who am I?', 'gcb'), __('Why am I here?', 'gcb'), __('What happens after I die?', 'gcb')],
                  theAlignment: "center",
              }
            },
    
            edit: EditComponent,
            save: function (props) {
                return null
            }
        })
    
    function EditComponent(props) {
        const blockProps = useBlockProps({
            className:"gcb_adm__box",
    
            }
        )
    
        function updateQuestion(value) {
            const sanitizedValue = sanitizeText(value);
            props.setAttributes({ question: sanitizedValue });
        }
    
        function deleteAnswer(indexToDelete){
            const newAnswers = props.attributes.answers.filter(
                function (x, index){
                    return index !== indexToDelete
                }
            );
            props.setAttributes({ answers:newAnswers})
    
            if( indexToDelete === props.attributes.correctAnswer){
                props.setAttributes( {correctAnswer: undefined})
            }
        }
    
    
    
        function markAsCorrect(index){
            props.setAttributes({correctAnswer: index})
        }
    
    
    
        return (
            <div  {...blockProps} >
    
                <BlockControls>
                    <AlignmentToolbar value={props.attributes.theAlignment} onChange={x => props.setAttributes({theAlignment: x})} />
                </BlockControls>
    
                <InspectorControls>
                    <PanelBody title={__("Supplementing questionnaire data", 'gcb')} initialOpen={true}>
                        <PanelRow>
                            test
                        </PanelRow>
                    </PanelBody>
                </InspectorControls>
    
    
                <TextControl label={__("Write name of Questionnaire", 'gcb')} value={ props.attributes.question} onChange={updateQuestion}  style={{fontSize: "20px"}} />
                <p style={{fontSize:"13px", margin: "20px 0 8px 0"}}>{__('Answers:', 'gcb')}</p>
    
                {/* SET data for all answers */}
                {props.attributes.answers.map(function (answer, index){
                    return (
                        <Flex>
                            <FlexBlock>
                                <TextControl  value={answer} onChange={newValue => {
                                    const newAnswers = props.attributes.answers.concat([]);
                                    newAnswers[index] = newValue
                                    props.setAttributes({ answers: newAnswers})
                                } } />
                            </FlexBlock>
                            <FlexItem>
                                <Button onClick={ () => markAsCorrect(index) }>
                                    <Icon className={"gcb_icon-star"} icon={ props.attributes.correctAnswer === index ? 'star-filled' : 'star-empty' } />
                                </Button>
                            </FlexItem>
                            <FlexItem>
                                <Button className={"gcb_delete"} onClick={ () => deleteAnswer(index) }>{__('Delete', 'gcb')}</Button>
                            </FlexItem>
                        </Flex>
                    )
                } )}
                <Button isPrimary className={"gcb_addNew__button"} onClick={ () => {
                    props.setAttributes({answers: props.attributes.answers.concat([""])})
                }} >{__('Add another answer', 'gcb')}</Button>
            </div>
        )
    }

    But it did not help in solving the problem.

    Perhaps you have more tips?

    * I Installed the module

    npm install @wordpress/server-side-render --save
    • This reply was modified 2 years ago by Andry.
    Faisal Ahammad

    (@faisalahammad)

    If the updated updateQuestion function using sanitizeText from @wordpress/server-side-render still doesn’t work, you could try using a regular expression to strip out any HTML tags and special characters.

    Here’s an example implementation of updateQuestion using a regular expression to strip out any HTML tags and special characters:

    function updateQuestion(value) {
      const sanitizedValue = value.replace(/<\/?[^>]+(>|$)/g, '').replace(/[&<>"']/g, '');
      props.setAttributes({ question: sanitizedValue });
    }

    This should remove HTML tags and special characters and only allow plain text input in the TextControl component.

    Note that this implementation is not as secure as using the sanitizeText function, so you should only use this if you are confident that users will not enter malicious content.

    I hope this helps!

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘How to sanitize the WordPress Gutenberg Component ?’ is closed to new replies.