diff --git a/package-lock.json b/package-lock.json index 05760e5a..1398aa0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3878,9 +3878,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz", + "integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -4745,41 +4745,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "puppeteer": { - "version": "npm:puppeteer-core@3.0.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-3.0.0.tgz", - "integrity": "sha512-oWjZFGMc0q2ak+8OxdmMffS79LIT0UEtmpV4h1/AARvESIqqKljf8mrfP+dQ2kas7XttsAZIxRBuWu7Y5JH8KQ==", - "dev": true, - "requires": { - "@types/mime-types": "^2.1.0", - "debug": "^4.1.0", - "extract-zip": "^2.0.0", - "https-proxy-agent": "^4.0.0", - "mime": "^2.0.3", - "mime-types": "^2.1.25", - "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", - "rimraf": "^3.0.2", - "tar-fs": "^2.0.0", - "unbzip2-stream": "^1.3.3", - "ws": "^7.2.3" - } - }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", @@ -5139,7 +5110,7 @@ }, "ansi-escapes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, @@ -14635,7 +14606,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -16524,7 +16495,7 @@ "dev": true }, "prettier": { - "version": "npm:prettier@2.0.5", + "version": "2.0.5", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", "dev": true @@ -16763,6 +16734,37 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "puppeteer": { + "version": "npm:puppeteer-core@3.0.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-3.0.0.tgz", + "integrity": "sha512-oWjZFGMc0q2ak+8OxdmMffS79LIT0UEtmpV4h1/AARvESIqqKljf8mrfP+dQ2kas7XttsAZIxRBuWu7Y5JH8KQ==", + "dev": true, + "requires": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^2.0.0", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^3.0.2", + "tar-fs": "^2.0.0", + "unbzip2-stream": "^1.3.3", + "ws": "^7.2.3" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -18952,7 +18954,7 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, diff --git a/package.json b/package.json index 7f2b0f79..c929e2ef 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@wordpress/components": "^9.8.0", "@wordpress/editor": "^9.18.0", "@wordpress/element": "^2.14.0", + "@wordpress/escape-html": "1.8.0", "@wordpress/hooks": "^2.8.0", "@wordpress/i18n": "^3.13.0", "@wordpress/scripts": "^11.0.0", diff --git a/src/index.js b/src/index.js index 2cb00741..6f4ad9b7 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,7 @@ import * as BlockEditor from '@wordpress/block-editor'; * Internal dependencies */ import languagesNames from './language-names'; +import { escape } from './utils'; /** * Extend code block with syntax highlighting. @@ -272,7 +273,7 @@ const extendCodeBlockWithSyntaxHighlighting = (settings) => { save({ attributes }) { return (
-					{attributes.content}
+					{escape(attributes.content)}
 				
); }, diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 00000000..b1f5b191 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,63 @@ +// Copied from Gutenberg v8.3.0: https://github.com/WordPress/gutenberg/blob/aaa0b32d6d4a82d1e955569c14960f02549bae99/packages/block-library/src/code/utils.js + +/** + * 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. [ => [). For instance, a + * shortcode like [embed] becomes [embed] + * + * This function replicates the escaping of HTML tags, where a tag like + * becomes <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. [ => [) + */ +function escapeOpeningSquareBrackets(content) { + return content.replace(/\[/g, '['); +} + +/** + * Converts the first two forward slashes of any isolated URL into their HTML + * counterparts (i.e. // => //). For instance, https://youtube.com/watch?x + * becomes https://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. & => &) + */ +function escapeProtocolInIsolatedUrls(content) { + return content.replace( + /^(\s*https?:)\/\/([^\s<>"]+\s*)$/m, + '$1//$2' + ); +}