Skip to content

Commit

Permalink
Don't re-encode already encoded post titles (#2407)
Browse files Browse the repository at this point in the history
* Added an entities module with reusable 'decodeEntities'
  • Loading branch information
notnownikki authored Aug 21, 2017
1 parent 5125ee1 commit f08c5f4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 1 deletion.
3 changes: 2 additions & 1 deletion blocks/library/latest-posts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { Component } from '@wordpress/element';
import { Placeholder, Toolbar, Spinner } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/utils';
import moment from 'moment';
import classnames from 'classnames';

Expand Down Expand Up @@ -203,7 +204,7 @@ registerBlockType( 'core/latest-posts', {
>
{ latestPosts.map( ( post, i ) =>
<li key={ i }>
<a href={ post.link } target="_blank">{ post.title.rendered.trim() || __( '(Untitled)' ) }</a>
<a href={ post.link } target="_blank">{ decodeEntities( post.title.rendered.trim() ) || __( '(Untitled)' ) }</a>
{ displayPostDate && post.date_gmt &&
<time dateTime={ moment( post.date_gmt ).utc().format() } className={ `${ this.props.className }__post-date` }>
{ moment( post.date_gmt ).local().format( 'MMMM DD, Y' ) }
Expand Down
22 changes: 22 additions & 0 deletions utils/entities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
let _decodeTextArea;

export function decodeEntities( html ) {
// not a string, or no entities to decode
if ( 'string' !== typeof html || -1 === html.indexOf( '&' ) ) {
return html;
}

// create a textarea for decoding entities, that we can reuse
if ( undefined === _decodeTextArea ) {
if ( document.implementation && document.implementation.createHTMLDocument ) {
_decodeTextArea = document.implementation.createHTMLDocument( '' ).createElement( 'textarea' );
} else {
_decodeTextArea = document.createElement( 'textarea' );
}
}

_decodeTextArea.innerHTML = html;
const decoded = _decodeTextArea.textContent;
_decodeTextArea.innerHTML = '';
return decoded;
}
2 changes: 2 additions & 0 deletions utils/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as keycodes from './keycodes';
import * as nodetypes from './nodetypes';
import { decodeEntities } from './entities';

export { keycodes };
export { nodetypes };
export { decodeEntities };

export * from './mediaupload';
22 changes: 22 additions & 0 deletions utils/test/entities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Internal dependencies
*/
import { decodeEntities } from '../entities';

describe( 'decodeEntities', () => {
it( 'should not change html with no entities', () => {
const html = '<h1>A noble tag embiggens the smallest text.</h1>';
const expected = '<h1>A noble tag embiggens the smallest text.</h1>';
expect( decodeEntities( html ) ).toEqual( expected );
} );
it( 'should decode entities', () => {
const html = '&lt;h1&gt;This post&#8217;s title.&lt;/h1&gt;';
const expected = '<h1>This post’s title.</h1>';
expect( decodeEntities( html ) ).toEqual( expected );
} );
it( 'should not double decode entities', () => {
const html = 'This post&amp;rsquo;s title.';
const expected = 'This post&rsquo;s title.';
expect( decodeEntities( html ) ).toEqual( expected );
} );
} );

0 comments on commit f08c5f4

Please sign in to comment.