Skip to content

Commit

Permalink
Merge pull request #160 from Automattic/fix/escaping-html-entities
Browse files Browse the repository at this point in the history
Fix escaping issues with HTML entities
  • Loading branch information
yscik authored Sep 7, 2020
2 parents d2a6435 + d4ae347 commit c2043ab
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 57 deletions.
52 changes: 3 additions & 49 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,63 +20,17 @@ addons:
# Test against these versions of PHP.
# Some additional PHP versions are also included in the matrix below.
php:
- 5.4
- 5.5
- 5.6
- '7.0'
- 7.1
- 7.2
- 7.3
- nightly

# Test against these versions of WordPress.
env:
- WP_VERSION=4.7 # Plugin minimum version
- WP_VERSION=4.8
- WP_VERSION=4.9
- WP_VERSION=5.2 # Plugin minimum version
- WP_VERSION=5.3
- WP_VERSION=5.4
- WP_VERSION=latest
- WP_VERSION=nightly

# Some additional environments to test:
# * PHP 5.2 and 5.3 require precise not trusty
# * PHP_CodeSniffer
matrix:
include:
- php: 5.2
dist: precise
env: WP_VERSION=4.7
- php: 5.2
dist: precise
env: WP_VERSION=4.8
- php: 5.2
dist: precise
env: WP_VERSION=latest
- php: 5.2
dist: precise
env: WP_VERSION=nightly
- php: 5.3
dist: precise
env: WP_VERSION=4.7
- php: 5.3
dist: precise
env: WP_VERSION=4.8
- php: 5.3
dist: precise
env: WP_VERSION=latest
- php: 5.3
dist: precise
env: WP_VERSION=nightly
exclude: # WordPress 4.7 doesn't like running unit tests under PHP 7.x, see https://travis-ci.org/Viper007Bond/regenerate-thumbnails/builds/281022291
- php: '7.0'
env: WP_VERSION=4.7
- php: 7.1
env: WP_VERSION=4.7
- php: 7.2
env: WP_VERSION=4.7
- php: 7.3
env: WP_VERSION=4.7
- php: nightly
env: WP_VERSION=4.7

before_script:
- |
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"preinstall": "npx npm-force-resolutions"
},
"dependencies": {
"@wordpress/escape-html": "1.9.0",
"cgb-scripts": "1.23.0",
"npm-force-resolutions": "0.0.3"
},
Expand Down
17 changes: 10 additions & 7 deletions src/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import {
} from '@wordpress/components';
import { PlainText, InspectorControls } from '@wordpress/editor';

/**
* Internal dependencies
*/
import deprecated from './deprecated';
import save from './save';

registerBlockType( 'syntaxhighlighter/code', {
title: __( 'SyntaxHighlighter Code', 'syntaxhighlighter' ),

Expand All @@ -37,8 +43,8 @@ registerBlockType( 'syntaxhighlighter/code', {
attributes: {
content: {
type: 'string',
source: 'text',
selector: 'pre',
source: 'text',
selector: 'code',
},

language: {
Expand Down Expand Up @@ -296,9 +302,6 @@ registerBlockType( 'syntaxhighlighter/code', {
return [ blockSettings, editView ];
},

save( { attributes } ) {
const { content } = attributes;

return( <pre>{ content }</pre> );
},
save,
deprecated,
} );
49 changes: 49 additions & 0 deletions src/deprecated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
export default [
{
attributes: {
content: {
type: 'string',
source: 'text',
selector: 'pre',
},

language: {
type: 'string',
default: syntaxHighlighterData.settings.language.default,
},

lineNumbers: {
type: 'boolean',
default: syntaxHighlighterData.settings.lineNumbers.default,
},

firstLineNumber: {
type: 'string',
default: syntaxHighlighterData.settings.firstLineNumber.default,
},

highlightLines: {
type: 'string',
},

wrapLines: {
type: 'boolean',
default: syntaxHighlighterData.settings.wrapLines.default,
},

makeURLsClickable: {
type: 'boolean',
default: syntaxHighlighterData.settings.makeURLsClickable.default,
},

quickCode: {
type: 'boolean',
default: syntaxHighlighterData.settings.quickCode.default,
},
},

save( { attributes } ) {
return( <pre>{ attributes.content }</pre> );
},
},
];
12 changes: 12 additions & 0 deletions src/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Internal dependencies
*/
import { escape } from './utils';

export default function save( { attributes } ) {
return (
<pre>
<code>{ escape( attributes.content ) }</code>
</pre>
);
}
61 changes: 61 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import { flow } from 'lodash';

/**
* WordPress dependencies
*/
import { escapeEditableHTML } from '@wordpress/escape-html';

/**
* Escapes ampersands, shortcodes, and links.
*
* @param {string} content The content of a code block.
* @return {string} The given content with some characters escaped.
*/
export function escape( content ) {
return flow(
escapeEditableHTML,
escapeOpeningSquareBrackets,
escapeProtocolInIsolatedUrls
)( content || '' );
}

/**
* Returns the given content with all opening shortcode characters converted
* into their HTML entity counterpart (i.e. [ => &#91;). For instance, a
* shortcode like [embed] becomes &#91;embed]
*
* This function replicates the escaping of HTML tags, where a tag like
* <strong> becomes &lt;strong>.
*
* @param {string} content The content of a code block.
* @return {string} The given content with its opening shortcode characters
* converted into their HTML entity counterpart
* (i.e. [ => &#91;)
*/
function escapeOpeningSquareBrackets( content ) {
return content.replace( /\[/g, '&#91;' );
}

/**
* Converts the first two forward slashes of any isolated URL into their HTML
* counterparts (i.e. // => &#47;&#47;). For instance, https://youtube.com/watch?x
* becomes https:&#47;&#47;youtube.com/watch?x.
*
* An isolated URL is a URL that sits in its own line, surrounded only by spacing
* characters.
*
* See https://github.com/WordPress/wordpress-develop/blob/5.1.1/src/wp-includes/class-wp-embed.php#L403
*
* @param {string} content The content of a code block.
* @return {string} The given content with its ampersands converted into
* their HTML entity counterpart (i.e. & => &amp;)
*/
function escapeProtocolInIsolatedUrls( content ) {
return content.replace(
/^(\s*https?:)\/\/([^\s<>"]+\s*)$/m,
'$1&#47;&#47;$2'
);
}
6 changes: 5 additions & 1 deletion syntaxhighlighter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
Text Domain: syntaxhighlighter
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Requires at least: 5.2
Tested up to: 5.4
Requires PHP: 7.0
**************************************************************************/

Expand Down Expand Up @@ -524,10 +527,11 @@ public function render_block( $attributes, $content ) {
}
}

$code = preg_replace( '#<pre [^>]+>([^<]+)?</pre>#', '$1', $content );
$code = preg_replace( '#<pre [^>]+><code>([^<]+)?</code></pre>#', '$1', $content );

// Undo escaping done by WordPress
$code = str_replace( '&lt;', '<', $code );
$code = str_replace( '&amp;', '&', $code );

return $this->shortcode_callback( $attributes, $code, 'code' );
}
Expand Down

0 comments on commit c2043ab

Please sign in to comment.