Skip to content

Commit

Permalink
Block API: Replace JSON-escaped quotation mark with unicode escape se…
Browse files Browse the repository at this point in the history
…quence (#6619)

* Block API: Replace JSON-escaped quotation mark with unicode escape sequence

* Parser: Test full lifecycle of quote-escaped attributes parse
  • Loading branch information
aduth authored and gziolo committed Jun 21, 2018
1 parent 7dff9bd commit f989b9c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
29 changes: 23 additions & 6 deletions blocks/api/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,29 @@ export function getCommentAttributes( allAttributes, blockType ) {
return attributes;
}

export function serializeAttributes( attrs ) {
return JSON.stringify( attrs )
.replace( /--/g, '\\u002d\\u002d' ) // don't break HTML comments
.replace( /</g, '\\u003c' ) // don't break standard-non-compliant tools
.replace( />/g, '\\u003e' ) // ibid
.replace( /&/g, '\\u0026' ); // ibid
/**
* Given an attributes object, returns a string in the serialized attributes
* format prepared for post content.
*
* @param {Object} attributes Attributes object.
*
* @return {string} Serialized attributes.
*/
export function serializeAttributes( attributes ) {
return JSON.stringify( attributes )
// Don't break HTML comments.
.replace( /--/g, '\\u002d\\u002d' )

// Don't break non-standard-compliant tools.
.replace( /</g, '\\u003c' )
.replace( />/g, '\\u003e' )
.replace( /&/g, '\\u0026' )

// Bypass server stripslashes behavior which would unescape stringify's
// escaping of quotation mark.
//
// See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
.replace( /\\"/g, '\\u0022' );
}

/**
Expand Down
21 changes: 21 additions & 0 deletions blocks/api/test/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
getBlockTypes,
setUnknownTypeHandlerName,
} from '../registration';
import { createBlock } from '../factory';
import serialize from '../serializer';

describe( 'block parser', () => {
const defaultBlockSettings = {
Expand Down Expand Up @@ -571,5 +573,24 @@ describe( 'block parser', () => {
'core/test-block', 'core/void-block',
] );
} );

it( 'should parse with unicode escaped returned to original representation', () => {
registerBlockType( 'core/code', {
category: 'common',
title: 'Code Block',
attributes: {
content: {
type: 'string',
},
},
save: ( { attributes } ) => attributes.content,
} );

const content = '$foo = "My \"escaped\" text.";';
const block = createBlock( 'core/code', { content } );
const serialized = serialize( block );
const parsed = parse( serialized );
expect( parsed[ 0 ].attributes.content ).toBe( content );
} );
} );
} );
7 changes: 7 additions & 0 deletions blocks/api/test/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,22 @@ describe( 'block serializer', () => {
it( 'should not break HTML comments', () => {
expect( serializeAttributes( { a: '-- and --' } ) ).toBe( '{"a":"\\u002d\\u002d and \\u002d\\u002d"}' );
} );

it( 'should not break standard-non-compliant tools for "<"', () => {
expect( serializeAttributes( { a: '< and <' } ) ).toBe( '{"a":"\\u003c and \\u003c"}' );
} );

it( 'should not break standard-non-compliant tools for ">"', () => {
expect( serializeAttributes( { a: '> and >' } ) ).toBe( '{"a":"\\u003e and \\u003e"}' );
} );

it( 'should not break standard-non-compliant tools for "&"', () => {
expect( serializeAttributes( { a: '& and &' } ) ).toBe( '{"a":"\\u0026 and \\u0026"}' );
} );

it( 'should replace quotation marks', () => {
expect( serializeAttributes( { a: '" and "' } ) ).toBe( '{"a":"\\u0022 and \\u0022"}' );
} );
} );

describe( 'getCommentDelimitedContent()', () => {
Expand Down

0 comments on commit f989b9c

Please sign in to comment.