Merge pull request #8023 from MrPetovan/bug/7808-markdown-unescape-chevrons

Fix chevron display in BBCode/Markdown conversion
This commit is contained in:
Tobias Diekershoff 2019-12-28 08:07:30 +01:00 committed by GitHub
commit d6274ab6f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 92 deletions

99
composer.lock generated
View File

@ -759,16 +759,16 @@
}, },
{ {
"name": "league/html-to-markdown", "name": "league/html-to-markdown",
"version": "4.8.2", "version": "4.9.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git", "url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413" "reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e747489191f8e9144a7270eb61f8b9516e99e413", "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413", "reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -778,7 +778,7 @@
}, },
"require-dev": { "require-dev": {
"mikehaertl/php-shellcommand": "~1.1.0", "mikehaertl/php-shellcommand": "~1.1.0",
"phpunit/phpunit": "4.*", "phpunit/phpunit": "^4.8|^5.7",
"scrutinizer/ocular": "~1.1" "scrutinizer/ocular": "~1.1"
}, },
"bin": [ "bin": [
@ -787,7 +787,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "4.9-dev" "dev-master": "4.10-dev"
} }
}, },
"autoload": { "autoload": {
@ -819,7 +819,7 @@
"html", "html",
"markdown" "markdown"
], ],
"time": "2019-08-02T11:57:39+00:00" "time": "2019-12-28T01:32:28+00:00"
}, },
{ {
"name": "level-2/dice", "name": "level-2/dice",
@ -1128,7 +1128,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.2.2.tgz", "url": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.2.2.tgz",
"reference": null,
"shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55" "shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55"
}, },
"require-dev": { "require-dev": {
@ -1222,7 +1221,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz", "url": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz",
"reference": null,
"shasum": "8f18b0ce5c76a5d18017f71c0a795c65b9138f2a" "shasum": "8f18b0ce5c76a5d18017f71c0a795c65b9138f2a"
}, },
"type": "npm-asset-library", "type": "npm-asset-library",
@ -1265,7 +1263,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.10.1.tgz", "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.10.1.tgz",
"reference": null,
"shasum": "cca3f9a2656a7e978a3f3facb7f35934a91185db" "shasum": "cca3f9a2656a7e978a3f3facb7f35934a91185db"
}, },
"type": "npm-asset-library", "type": "npm-asset-library",
@ -1312,28 +1309,11 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/imagesloaded/-/imagesloaded-4.1.4.tgz", "url": "https://registry.npmjs.org/imagesloaded/-/imagesloaded-4.1.4.tgz",
"reference": null,
"shasum": "1376efcd162bb768c34c3727ac89cc04051f3cc7" "shasum": "1376efcd162bb768c34c3727ac89cc04051f3cc7"
}, },
"require": { "require": {
"npm-asset/ev-emitter": ">=1.0.0,<2.0.0" "npm-asset/ev-emitter": ">=1.0.0,<2.0.0"
}, },
"require-dev": {
"npm-asset/chalk": ">=1.1.1,<2.0.0",
"npm-asset/cheerio": ">=0.19.0,<0.20.0",
"npm-asset/gulp": ">=3.9.0,<4.0.0",
"npm-asset/gulp-jshint": ">=1.11.2,<2.0.0",
"npm-asset/gulp-json-lint": ">=0.1.0,<0.2.0",
"npm-asset/gulp-rename": ">=1.2.2,<2.0.0",
"npm-asset/gulp-replace": ">=0.5.4,<0.6.0",
"npm-asset/gulp-requirejs-optimize": "dev-github:metafizzy/gulp-requirejs-optimize",
"npm-asset/gulp-uglify": ">=1.4.2,<2.0.0",
"npm-asset/gulp-util": ">=3.0.7,<4.0.0",
"npm-asset/highlight.js": ">=8.9.1,<9.0.0",
"npm-asset/marked": ">=0.3.5,<0.4.0",
"npm-asset/minimist": ">=1.2.0,<2.0.0",
"npm-asset/transfob": ">=1.0.0,<2.0.0"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1376,17 +1356,8 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/jgrowl/-/jgrowl-1.4.6.tgz", "url": "https://registry.npmjs.org/jgrowl/-/jgrowl-1.4.6.tgz",
"reference": null,
"shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3" "shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3"
}, },
"require-dev": {
"npm-asset/grunt": "~0.4.2",
"npm-asset/grunt-contrib-cssmin": "~0.9.0",
"npm-asset/grunt-contrib-jshint": "~0.6.3",
"npm-asset/grunt-contrib-less": "~0.11.0",
"npm-asset/grunt-contrib-uglify": "~0.4.0",
"npm-asset/grunt-contrib-watch": "~0.6.1"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1417,35 +1388,8 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", "url": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz",
"reference": null,
"shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02" "shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02"
}, },
"require-dev": {
"npm-asset/commitplease": "2.0.0",
"npm-asset/core-js": "0.9.17",
"npm-asset/grunt": "0.4.5",
"npm-asset/grunt-babel": "5.0.1",
"npm-asset/grunt-cli": "0.1.13",
"npm-asset/grunt-compare-size": "0.4.0",
"npm-asset/grunt-contrib-jshint": "0.11.2",
"npm-asset/grunt-contrib-uglify": "0.9.2",
"npm-asset/grunt-contrib-watch": "0.6.1",
"npm-asset/grunt-git-authors": "2.0.1",
"npm-asset/grunt-jscs": "2.1.0",
"npm-asset/grunt-jsonlint": "1.0.4",
"npm-asset/grunt-npmcopy": "0.1.0",
"npm-asset/gzip-js": "0.3.2",
"npm-asset/jsdom": "5.6.1",
"npm-asset/load-grunt-tasks": "1.0.0",
"npm-asset/qunit-assert-step": "1.0.3",
"npm-asset/qunitjs": "1.17.1",
"npm-asset/requirejs": "2.1.17",
"npm-asset/sinon": "1.10.3",
"npm-asset/sizzle": "2.2.1",
"npm-asset/strip-json-comments": "1.0.3",
"npm-asset/testswarm": "1.1.0",
"npm-asset/win-spawn": "2.0.0"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1488,7 +1432,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/jquery-colorbox/-/jquery-colorbox-1.6.4.tgz", "url": "https://registry.npmjs.org/jquery-colorbox/-/jquery-colorbox-1.6.4.tgz",
"reference": null,
"shasum": "799452523a6c494839224ef702e807deb9c06cc5" "shasum": "799452523a6c494839224ef702e807deb9c06cc5"
}, },
"require": { "require": {
@ -1535,7 +1478,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.21.tgz", "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.21.tgz",
"reference": null,
"shasum": "00c388a78df2732fedfdb5c6529b6e84d53e0235" "shasum": "00c388a78df2732fedfdb5c6529b6e84d53e0235"
}, },
"require": { "require": {
@ -1593,15 +1535,8 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz", "url": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz",
"reference": null,
"shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5" "shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5"
}, },
"require-dev": {
"npm-asset/grunt": "~0.4.1",
"npm-asset/grunt-contrib-connect": "~0.5.0",
"npm-asset/grunt-contrib-jshint": "~0.7.1",
"npm-asset/grunt-contrib-uglify": "~0.2.7"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1648,7 +1583,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "url": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"reference": null,
"shasum": "0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" "shasum": "0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
}, },
"type": "npm-asset-library", "type": "npm-asset-library",
@ -1765,7 +1699,6 @@
"dist": { "dist": {
"type": "tar", "type": "tar",
"url": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.11.1.tgz", "url": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.11.1.tgz",
"reference": null,
"shasum": "4e64e671b22310a8606f4aec805924ba84b015b8" "shasum": "4e64e671b22310a8606f4aec805924ba84b015b8"
}, },
"require": { "require": {
@ -3402,8 +3335,8 @@
"authors": [ "authors": [
{ {
"name": "Sebastian Bergmann", "name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de", "role": "lead",
"role": "lead" "email": "sb@sebastian-bergmann.de"
} }
], ],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
@ -3670,8 +3603,8 @@
"authors": [ "authors": [
{ {
"name": "Sebastian Bergmann", "name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de", "role": "lead",
"role": "lead" "email": "sebastian@phpunit.de"
} }
], ],
"description": "The PHP Unit Testing framework.", "description": "The PHP Unit Testing framework.",
@ -3844,7 +3777,7 @@
} }
], ],
"description": "Provides the functionality to compare PHP values for equality", "description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator", "homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [ "keywords": [
"comparator", "comparator",
"compare", "compare",
@ -3946,7 +3879,7 @@
} }
], ],
"description": "Provides functionality to handle HHVM/PHP environments", "description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "https://github.com/sebastianbergmann/environment", "homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [ "keywords": [
"Xdebug", "Xdebug",
"environment", "environment",
@ -4014,7 +3947,7 @@
} }
], ],
"description": "Provides the functionality to export PHP variables for visualization", "description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://github.com/sebastianbergmann/exporter", "homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [ "keywords": [
"export", "export",
"exporter" "exporter"
@ -4066,7 +3999,7 @@
} }
], ],
"description": "Snapshotting of global state", "description": "Snapshotting of global state",
"homepage": "https://github.com/sebastianbergmann/global-state", "homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [ "keywords": [
"global state" "global state"
], ],
@ -4168,7 +4101,7 @@
} }
], ],
"description": "Provides functionality to recursively process PHP variables", "description": "Provides functionality to recursively process PHP variables",
"homepage": "https://github.com/sebastianbergmann/recursion-context", "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19T07:33:16+00:00" "time": "2016-11-19T07:33:16+00:00"
}, },
{ {

View File

@ -1283,9 +1283,9 @@ class BBCode extends BaseObject
function ($matches) use (&$codeblocks) { function ($matches) use (&$codeblocks) {
$return = '#codeblock-' . count($codeblocks) . '#'; $return = '#codeblock-' . count($codeblocks) . '#';
if (strpos($matches[2], "\n") !== false) { if (strpos($matches[2], "\n") !== false) {
$codeblocks[] = '<pre><code class="language-' . trim($matches[1]) . '">' . trim($matches[2], "\n\r") . '</code></pre>'; $codeblocks[] = '<pre><code class="language-' . trim($matches[1]) . '">' . htmlspecialchars(trim($matches[2], "\n\r"), ENT_NOQUOTES, 'UTF-8') . '</code></pre>';
} else { } else {
$codeblocks[] = '<code>' . $matches[2] . '</code>'; $codeblocks[] = '<code>' . htmlspecialchars($matches[2], ENT_NOQUOTES, 'UTF-8') . '</code>';
} }
return $return; return $return;
@ -2052,9 +2052,6 @@ class BBCode extends BaseObject
$text = self::convert($text, false, 4); $text = self::convert($text, false, 4);
} }
// mask some special HTML chars from conversation to markdown
$text = str_replace(['&lt;', '&gt;', '&amp;'], ['&_lt_;', '&_gt_;', '&_amp_;'], $text);
// If a link is followed by a quote then there should be a newline before it // If a link is followed by a quote then there should be a newline before it
// Maybe we should make this newline at every time before a quote. // Maybe we should make this newline at every time before a quote.
$text = str_replace(['</a><blockquote>'], ['</a><br><blockquote>'], $text); $text = str_replace(['</a><blockquote>'], ['</a><br><blockquote>'], $text);
@ -2064,9 +2061,6 @@ class BBCode extends BaseObject
// Now convert HTML to Markdown // Now convert HTML to Markdown
$text = HTML::toMarkdown($text); $text = HTML::toMarkdown($text);
// unmask the special chars back to HTML
$text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['&lt;', '&gt;', '&amp;'], $text);
$a->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack()); $a->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack());
// Libertree has a problem with escaped hashtags. // Libertree has a problem with escaped hashtags.

View File

@ -59,10 +59,14 @@ class Babel extends BaseModule
$markdown = Text\BBCode::toMarkdown($bbcode); $markdown = Text\BBCode::toMarkdown($bbcode);
$results[] = [ $results[] = [
'title' => L10n::t('BBCode::toMarkdown'), 'title' => L10n::t('BBCode::toMarkdown'),
'content' => visible_whitespace($markdown) 'content' => visible_whitespace(htmlspecialchars($markdown))
]; ];
$html2 = Text\Markdown::convert($markdown); $html2 = Text\Markdown::convert($markdown);
$results[] = [
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert (raw HTML)'),
'content' => visible_whitespace(htmlspecialchars($html2))
];
$results[] = [ $results[] = [
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert'), 'title' => L10n::t('BBCode::toMarkdown => Markdown::convert'),
'content' => $html2 'content' => $html2

View File

@ -203,6 +203,18 @@ class BBCodeTest extends MockedTest
'text' => '[audio]http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3[/audio]', 'text' => '[audio]http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3[/audio]',
'try_oembed' => true, 'try_oembed' => true,
], ],
'bug-7808-code-lt' => [
'expectedHtml' => '<code>&lt;</code>',
'text' => '[code]<[/code]',
],
'bug-7808-code-gt' => [
'expectedHtml' => '<code>&gt;</code>',
'text' => '[code]>[/code]',
],
'bug-7808-code-amp' => [
'expectedHtml' => '<code>&amp;</code>',
'text' => '[code]&[/code]',
]
]; ];
} }
@ -224,4 +236,39 @@ class BBCodeTest extends MockedTest
$this->assertEquals($expectedHtml, $actual); $this->assertEquals($expectedHtml, $actual);
} }
public function dataBBCodesToMarkdown()
{
return [
'bug-7808-gt' => [
'expected' => '&gt;`>`',
'text' => '>[code]>[/code]',
],
'bug-7808-lt' => [
'expected' => '&lt;`<`',
'text' => '<[code]<[/code]',
],
'bug-7808-amp' => [
'expected' => '&amp;`&`',
'text' => '&[code]&[/code]',
],
];
}
/**
* Test convert bbcodes to Markdown
*
* @dataProvider dataBBCodesToMarkdown
*
* @param string $expected Expected Markdown output
* @param string $text BBCode text
* @param bool $for_diaspora
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function testToMarkdown($expected, $text, $for_diaspora = false)
{
$actual = BBCode::toMarkdown($text, $for_diaspora);
$this->assertEquals($expected, $actual);
}
} }