From 1c0f534976b540fa61b4ae1dd0a8e969cc045c74 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 19 Sep 2020 02:13:08 +0200 Subject: [PATCH 1/4] Add BBCode and Markdown wrappers. --- .travis.yml | 4 +- README.md | 67 +---------- composer.json | 9 +- docs/README.md | 112 ++++++++++++++++++ src/Bbcode/BbcodeInterface.php | 19 +++ src/Bbcode/DecodaBbcode.php | 101 ++++++++++++++++ src/Bbcode/Filter/VideoFilter.php | 94 +++++++++++++++ src/Highlighter/Highlighter.php | 2 +- src/Markdown/CommonMarkMarkdown.php | 76 ++++++++++++ src/Markdown/MarkdownInterface.php | 19 +++ src/View/Helper/HighlighterHelper.php | 6 +- src/View/Helper/MarkdownHelper.php | 108 +++++++++++++++++ tests/TestCase/Bbcode/DecodaBbcodeTest.php | 95 +++++++++++++++ .../Markdown/CommonMarkMarkdownTest.php | 86 ++++++++++++++ tests/phpstan.neon | 7 +- 15 files changed, 730 insertions(+), 75 deletions(-) create mode 100644 docs/README.md create mode 100644 src/Bbcode/BbcodeInterface.php create mode 100644 src/Bbcode/DecodaBbcode.php create mode 100644 src/Bbcode/Filter/VideoFilter.php create mode 100644 src/Markdown/CommonMarkMarkdown.php create mode 100644 src/Markdown/MarkdownInterface.php create mode 100644 src/View/Helper/MarkdownHelper.php create mode 100644 tests/TestCase/Bbcode/DecodaBbcodeTest.php create mode 100644 tests/TestCase/Markdown/CommonMarkMarkdownTest.php diff --git a/.travis.yml b/.travis.yml index e2491e1..ba1ee90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,8 +30,8 @@ before_script: script: - if [[ $DEFAULT == 1 ]]; then vendor/bin/phpunit; fi - - if [[ $CHECKS == 1 ]]; then composer cs-check ; fi - - if [[ $CHECKS == 1 ]]; then composer phpstan-setup && composer phpstan; fi + - if [[ $CHECKS == 1 ]]; then composer cs-check; fi + - if [[ $CHECKS == 1 ]]; then composer stan-setup && composer stan; fi - if [[ $CODECOVERAGE == 1 ]]; then vendor/bin/phpunit --coverage-clover=clover.xml || true; fi - if [[ $CODECOVERAGE == 1 ]]; then wget -O codecov.sh https://codecov.io/bash; fi diff --git a/README.md b/README.md index 14e6488..c203ab4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ A CakePHP plugin to - easily use code syntax highlighters. +- quickly convert Markdown snippets. +- quickly convert BBCode snippets. This branch is for **CakePHP 4.0+**. See [version map](https://github.com/dereuromark/cakephp-markup/wiki#cakephp-version-map) for details. @@ -25,70 +27,7 @@ https://sandbox.dereuromark.de/sandbox/markup-examples ## Usage -```php -// You must load the helper before -$this->loadHelper('Markup.Highlighter', $optionalConfigArray); - -// In our ctp file we can now highlight some code snippet -$string = <<<'TEXT' -$result = 'string' . $this->request->query('key'); // Some comment -TEXT; - -echo $this->Highlighter->highlight($string, ['lang' => 'php']); -``` - -### Supported Highlighters - -#### PhpHighlighter -Using native PHP syntax highlighting this default highlighter does not need any dependencies. -Just add some basic CSS styling for all `
` tags.
-
-The output will be automatically escaped (safe) HTML code, e.g. for `php` language code:
-```html
-

-$key = 'string' . $this->something->do(true); // Some comment
-
-``` - -#### JsHighlighter -Using only JS via [highlightjs.org](https://highlightjs.org/) or [prismjs.com](http://prismjs.com/) this parser is lightweight on the server side. -It requires a CSS and JS file on top to do client-side highlighting "just in time". -```php -// Helper option -'highlighter' => 'Markup\Highlighter\JsHighlighter', -``` - -The output for `php` language code will be wrapped in -```html -
...
-``` -tags, for example. -Do not forget to add your custom code style CSS file and the JS code as documented at [highlightjs.org](https://highlightjs.org/usage/) or [prismjs.com](http://prismjs.com/#basic-usage). - -### Write your own highlighter -You just have to implement the `HighlighterInterface` and ideally extend the abstract `Highlighter` class. -Then you can simply switch your code highlighting on demand or globally with Configure: -```php -// Configure -'Highlighter' => [ - 'highlighter' => 'VendorName\PluginName\CustomHighlighter', -], -``` - -You should be able to easily use any custom highlighter this way. - -If you are looking for a good auto-detection highlighter, take a look at [github.com/google/code-prettify](https://github.com/google/code-prettify). -In case you need the full options stack, it would be best to write a custom one here, otherwise a basic code template `
{{content}}
` for `JsHighlighter` should do the trick. - -### Additional Configuration -You can switch the template to use `
` instead of ` for example: -```php -// Helper option -'templates' => [ - 'code' => '{{content}}
', -], -``` +See [Docs](/docs). ## TODO - Add more highlighters (you can also just link your own here) -- Add markup parsers and possibly View classes (BBCode, Markdown, ...) diff --git a/composer.json b/composer.json index 396ee05..9deb24f 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,10 @@ "cakephp/cakephp": "^4.0.0" }, "require-dev": { - "fig-r/psr2r-sniffer": "dev-master" + "fig-r/psr2r-sniffer": "dev-master", + "league/commonmark": "^1.5", + "mjohnson/decoda": "^6.12", + "dereuromark/media-embed": "^0.5" }, "autoload": { "psr-4": { @@ -34,8 +37,8 @@ "source": "https://github.com/dereuromark/cakephp-markup" }, "scripts": { - "phpstan": "phpstan analyse -c tests/phpstan.neon -l 5 src/", - "phpstan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 && mv composer.backup composer.json", + "stan": "phpstan analyse -c tests/phpstan.neon src/", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 && mv composer.backup composer.json", "test": "php phpunit.phar", "test-setup": "[ ! -f phpunit.phar ] && wget https://phar.phpunit.de/phpunit-8.4.3.phar && mv phpunit-8.4.3.phar phpunit.phar || true", "test-coverage": "php phpunit.phar --log-junit tmp/coverage/unitreport.xml --coverage-html tmp/coverage --coverage-clover tmp/coverage/coverage.xml", diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..3257c93 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,112 @@ +# Documentation + +## Highlighter + +```php +// You must load the helper before +$this->loadHelper('Markup.Highlighter', $optionalConfigArray); + +// In our template file we can now highlight some code snippet +$string = <<<'TEXT' +$result = 'string' . $this->request->query('key'); // Some comment +TEXT; + +echo $this->Highlighter->highlight($string, ['lang' => 'php']); +``` + +### Supported Highlighters + +#### PhpHighlighter +Using native PHP syntax highlighting this default highlighter does not need any dependencies. +Just add some basic CSS styling for all `
` tags.
+
+The output will be automatically escaped (safe) HTML code, e.g. for `php` language code:
+```html
+

+$key = 'string' . $this->something->do(true); // Some comment
+
+``` + +#### JsHighlighter +Using only JS via [highlightjs.org](https://highlightjs.org/) or [prismjs.com](http://prismjs.com/) this parser is lightweight on the server side. +It requires a CSS and JS file on top to do client-side highlighting "just in time". +```php +// Helper option +'highlighter' => 'Markup\Highlighter\JsHighlighter', +``` + +The output for `php` language code will be wrapped in +```html +
...
+``` +tags, for example. +Do not forget to add your custom code style CSS file and the JS code as documented at [highlightjs.org](https://highlightjs.org/usage/) or [prismjs.com](http://prismjs.com/#basic-usage). + +### Write your own highlighter +You just have to implement the `HighlighterInterface` and ideally extend the abstract `Highlighter` class. +Then you can simply switch your code highlighting on demand or globally with Configure: +```php +// Configure +'Highlighter' => [ + 'highlighter' => 'VendorName\PluginName\CustomHighlighter', +], +``` + +You should be able to easily use any custom highlighter this way. + +If you are looking for a good auto-detection highlighter, take a look at [github.com/google/code-prettify](https://github.com/google/code-prettify). +In case you need the full options stack, it would be best to write a custom one here, otherwise a basic code template `
{{content}}
` for `JsHighlighter` should do the trick. + +### Additional Configuration +You can switch the template to use `
` instead of ` for example: +```php +// Helper option +'templates' => [ + 'code' => '{{content}}
', +], +``` + +## Markdown + +For this you need to decide on a converter library. +By default, the included `CommonMarkMarkdown` class requires you to install its dependency: +``` +composer require league/commonmark +``` + +Once you configured it the way you want it you can start using it. + +```php +// You must load the helper before +$this->loadHelper('Markup.Markdown', $optionalConfigArray); + +// In our template file we can now convert some markdown code snippet +$string = <<<'TEXT' +Some **bold** text and also some *italic*. +TEXT; + +echo $this->Markdown->convert($string); +``` + + +## BBCode + +For this you need to decide on a converter library. +By default, the included `DecodaBbcode` class requires you to install its dependency: +``` +composer require mjohnson/decoda +``` + +Once you configured it the way you want it you can start using it. + +```php +// You must load the helper before +$this->loadHelper('Markup.Bbcode', $optionalConfigArray); + +// In our template file we can now convert some markdown code snippet +$string = <<<'TEXT' +Some [b]bold[/b] text and also some [i]italic[/i]. +TEXT; + +echo $this->Bbcode->convert($string); +``` diff --git a/src/Bbcode/BbcodeInterface.php b/src/Bbcode/BbcodeInterface.php new file mode 100644 index 0000000..05d053d --- /dev/null +++ b/src/Bbcode/BbcodeInterface.php @@ -0,0 +1,19 @@ +setConfig($config); + } + + /** + * @param string $string + * @return string + */ + protected function _prepare($string) { + return $string; + } + + /** + * @param string $text + * @param array $options + * + * @return string + */ + public function convert(string $text, array $options = []): string { + $options += ['escape' => true]; + if ($options['escape']) { + $text = (string)h($text); + } + + $converter = $this->converter($text); + + return $converter->parse(); + } + + /** + * @param string $text + * @return \Decoda\Decoda + */ + protected function converter(string $text): Decoda { + $options = [ + 'escapeHtml' => false, + ]; + + $this->converter = new Decoda($text, $options); + // For now lets use basic defaults + $this->converter->addFilter(new DefaultFilter()); + $this->converter->addFilter(new EmailFilter()); + $this->converter->addFilter(new ImageFilter()); + $this->converter->addFilter(new UrlFilter()); + $this->converter->addFilter(new TextFilter()); + $this->converter->addFilter(new BlockFilter()); + $this->converter->addFilter(new CodeFilter()); + $this->converter->addFilter(new ListFilter()); + $this->converter->addFilter(new TableFilter()); + if (class_exists(MediaEmbed::class)) { + $this->converter->addFilter(new MediaEmbedVideoFilter()); + } else { + $this->converter->addFilter(new VideoFilter()); + } + + $this->converter->addHook(new CensorHook()); + $this->converter->addHook(new ClickableHook()); + + return $this->converter; + } + +} diff --git a/src/Bbcode/Filter/VideoFilter.php b/src/Bbcode/Filter/VideoFilter.php new file mode 100644 index 0000000..50c9c30 --- /dev/null +++ b/src/Bbcode/Filter/VideoFilter.php @@ -0,0 +1,94 @@ + [ + 'template' => 'video', + 'displayType' => Decoda::TYPE_BLOCK, + 'allowedTypes' => Decoda::TYPE_NONE, + 'contentPattern' => self::VIDEO_PATTERN, + 'attributes' => [ + 'default' => self::ALPHA, + 'size' => self::SIZE_PATTERN, + ], + ], + ]; + + /** + * Custom build the HTML for videos. + * + * @param array $tag + * @param string $content + * @return string + */ + public function parse(array $tag, $content) { + $provider = isset($tag['attributes']['default']) ? $tag['attributes']['default'] : $tag['tag']; + //$size = mb_strtolower(isset($tag['attributes']['size']) ? $tag['attributes']['size'] : 'medium'); + + preg_match('/^\[video\s*=\s*([a-z0-9_-]+)\]$/i', $tag['text'], $matches); + if (!$matches) { + return $tag['text'] . $content . '[/' . $tag['tag'] . ']'; + } + + $provider = $matches[1]; + $result = $this->transform($provider, $content); + if (!$result) { + return $tag['text'] . $content . '[/' . $tag['tag'] . ']'; + } + + return $result; + } + + /** + * @param string $provider + * @param string $id + * + * @return string|null + */ + protected function transform($provider, $id) { + // timestamp? + if (strpos($id, ',') !== false) { + [$id, $t] = explode(',', $id, 2); + } + if (!empty($t)) { + // with timestamps we cannot use the embed mode... + //TODO + } + + if (!isset($this->MediaEmbed)) { + $this->MediaEmbed = new MediaEmbed(); + } + $MediaObject = $this->MediaEmbed->parseId($id, $provider); + if (!$MediaObject) { + return null; + } + + $MediaObject->setAttribute('width', '100%'); + + return $MediaObject->getEmbedCode(); + } + +} diff --git a/src/Highlighter/Highlighter.php b/src/Highlighter/Highlighter.php index dda9ab5..497924b 100644 --- a/src/Highlighter/Highlighter.php +++ b/src/Highlighter/Highlighter.php @@ -30,7 +30,7 @@ public function __construct(array $config = []) { */ protected function _prepare($string) { if ($this->_config['tabToSpaces']) { - $string = preg_replace('/\t/', str_repeat(' ', $this->_config['tabToSpaces']), $string); + $string = (string)preg_replace('/\t/', str_repeat(' ', $this->_config['tabToSpaces']), $string); } return $string; diff --git a/src/Markdown/CommonMarkMarkdown.php b/src/Markdown/CommonMarkMarkdown.php new file mode 100644 index 0000000..d096472 --- /dev/null +++ b/src/Markdown/CommonMarkMarkdown.php @@ -0,0 +1,76 @@ +setConfig($config); + } + + /** + * @param string $string + * @return string + */ + protected function _prepare($string) { + return $string; + } + + /** + * @param string $text + * @param array $options + * + * @return string + */ + public function convert(string $text, array $options = []): string { + $converter = $this->converter(); + + $options += ['escape' => true]; + if ($options['escape']) { + $text = (string)h($text); + } + + return $converter->convertToHtml($text); + } + + /** + * @return \League\CommonMark\CommonMarkConverter + */ + protected function converter(): CommonMarkConverter { + if ($this->converter === null) { + $this->converter = static::defaultConverter(); + } + + return $this->converter; + } + + /** + * @return \League\CommonMark\CommonMarkConverter + */ + public static function defaultConverter(): CommonMarkConverter { + $environment = Environment::createGFMEnvironment(); + + return new CommonMarkConverter([], $environment); + } + +} diff --git a/src/Markdown/MarkdownInterface.php b/src/Markdown/MarkdownInterface.php new file mode 100644 index 0000000..1ec3bb3 --- /dev/null +++ b/src/Markdown/MarkdownInterface.php @@ -0,0 +1,19 @@ + false, - 'highlighter' => '\Markup\Highlighter\PhpHighlighter', - 'debug' => null, // Enable caching mode + 'highlighter' => PhpHighlighter::class, + 'debug' => null, // Enable debug display ]; /** diff --git a/src/View/Helper/MarkdownHelper.php b/src/View/Helper/MarkdownHelper.php new file mode 100644 index 0000000..7d39f96 --- /dev/null +++ b/src/View/Helper/MarkdownHelper.php @@ -0,0 +1,108 @@ + CommonMarkMarkdown::class, + 'debug' => null, // Enable debug display + ]; + + /** + * @var float + */ + protected $_time = 0.0; + + /** + * Constructor + * + * @param \Cake\View\View $View The View this helper is being attached to. + * @param array $config Configuration settings for the helper. + */ + public function __construct(View $View, array $config = []) { + $defaults = (array)Configure::read('Markdown'); + parent::__construct($View, $config + $defaults); + + if ($this->_config['debug'] === null) { + $this->_config['debug'] = Configure::read('debug'); + } + } + + /** + * Highlight a string. + * + * Options, depending on the specific highlighter class used: + * - templates + * - escape (defaults to true) + * - tabToSpaces (defaults to 4) + * - prefix (defaults to `language-`) + * + * @param string $text + * @param array $options + * @return string + */ + public function convert(string $text, array $options = []): string { + if ($this->_config['debug']) { + $this->_startTimer(); + } + $highlightedText = $this->_getConverter()->convert($text, $options); + if ($this->_config['debug']) { + $highlightedText .= $this->_timeElapsedFormatted($this->_endTimer()); + } + + return $highlightedText; + } + + /** + * @return \Markup\Markdown\MarkdownInterface + */ + protected function _getConverter() { + if (isset($this->_parser)) { + return $this->_parser; + } + $className = $this->_config['parser']; + + $this->_parser = new $className($this->_config); + + return $this->_parser; + } + + /** + * @return void + */ + protected function _startTimer() { + $this->_time = microtime(true); + } + + /** + * @return float + */ + protected function _endTimer() { + $now = microtime(true); + + return $now - $this->_time; + } + + /** + * @param float $time + * @return string + */ + protected function _timeElapsedFormatted($time) { + return ''; + } + +} diff --git a/tests/TestCase/Bbcode/DecodaBbcodeTest.php b/tests/TestCase/Bbcode/DecodaBbcodeTest.php new file mode 100644 index 0000000..bc70c51 --- /dev/null +++ b/tests/TestCase/Bbcode/DecodaBbcodeTest.php @@ -0,0 +1,95 @@ + false, + ] + ); + + $this->bbcode = new DecodaBbcode(); + } + + /** + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->bbcode); + } + + /** + * @return void + */ + public function testConvertText(): void { + $text = <<<'TEXT' +[h1]Header[/h1] + +My [b]bold[/b] text with [code]code[/code] and more "demo". + +A paragraph [url=http://example.com]with links[/url] and [abbr=xxx]yyy[/abbr]. + + +Another paragraph. + +[h2]Header 2[/h2] + +Foo bar. +TEXT; + + $result = $this->bbcode->convert($text); + $expected = '

Header



My bold text with
code
and more "<b>demo</b>".' + . '

A paragraph with links and yyy.


Another paragraph.

' + . '

Header 2



Foo bar.'; + $this->assertSame($expected, $result); + } + + /** + * @return void + */ + public function testConvertHtml(): void { + $text = <<<'TEXT' +[h1]Header[/h1] + +My [b]bold[/b] text with manual bold markup. +TEXT; + + $result = $this->bbcode->convert($text, ['escape' => false]); + $expected = '

Header



My bold text with manual bold markup.'; + $this->assertSame($expected, $result); + } + + /** + * @return void + */ + public function testConvertVideo(): void { + $text = <<<'TEXT' +Video Demo +[video=youtube]123[/video] +Enjoy! +TEXT; + + $result = $this->bbcode->convert($text, ['escape' => false]); + $expected = 'Video Demo

Enjoy!'; + $this->assertSame($expected, $result); + } + +} diff --git a/tests/TestCase/Markdown/CommonMarkMarkdownTest.php b/tests/TestCase/Markdown/CommonMarkMarkdownTest.php new file mode 100644 index 0000000..ef99c54 --- /dev/null +++ b/tests/TestCase/Markdown/CommonMarkMarkdownTest.php @@ -0,0 +1,86 @@ + false, + ] + ); + + $this->markdown = new CommonMarkMarkdown(); + } + + /** + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->markdown); + } + + /** + * @return void + */ + public function testConvertText(): void { + $text = <<<'TEXT' +# Header + +My **bold** text with `code` and more "demo". + +A paragraph [with links](http://example.com). + +## Header 2 + +Foo bar. +TEXT; + + $result = $this->markdown->convert($text); + $expected = <<Header +

My bold text with code and more "<b>demo</b>".

+

A paragraph with links.

+

Header 2

+

Foo bar.

+ +TXT; + $this->assertSame($expected, $result); + } + + /** + * @return void + */ + public function testConvertHtml(): void { + $text = <<<'TEXT' +# Header + +My **bold** text with manual bold markup. +TEXT; + + $result = $this->markdown->convert($text, ['escape' => false]); + $expected = <<Header +

My bold text with manual bold markup.

+ +TXT; + $this->assertSame($expected, $result); + } + +} diff --git a/tests/phpstan.neon b/tests/phpstan.neon index ec514ca..27d3d87 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -1,3 +1,6 @@ parameters: - autoload_files: - - bootstrap.php + level: 8 + bootstrapFiles: + - bootstrap.php + checkMissingIterableValueType: false + From 27c84a25141d23db30ae89b0f6b7f388af7670b1 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 19 Sep 2020 02:25:55 +0200 Subject: [PATCH 2/4] Add tests --- src/View/Helper/BbcodeHelper.php | 108 ++++++++++++++++++ src/View/Helper/MarkdownHelper.php | 18 +-- tests/TestCase/Bbcode/DecodaBbcodeTest.php | 2 +- .../Markdown/CommonMarkMarkdownTest.php | 2 +- .../TestCase/View/Helper/BbcodeHelperTest.php | 65 +++++++++++ .../View/Helper/HighlighterHelperTest.php | 2 +- .../View/Helper/MarkdownHelperTest.php | 65 +++++++++++ 7 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 src/View/Helper/BbcodeHelper.php create mode 100644 tests/TestCase/View/Helper/BbcodeHelperTest.php create mode 100644 tests/TestCase/View/Helper/MarkdownHelperTest.php diff --git a/src/View/Helper/BbcodeHelper.php b/src/View/Helper/BbcodeHelper.php new file mode 100644 index 0000000..482977d --- /dev/null +++ b/src/View/Helper/BbcodeHelper.php @@ -0,0 +1,108 @@ + DecodaBbcode::class, + 'debug' => null, // Enable debug display + ]; + + /** + * @var float + */ + protected $_time = 0.0; + + /** + * Constructor + * + * @param \Cake\View\View $View The View this helper is being attached to. + * @param array $config Configuration settings for the helper. + */ + public function __construct(View $View, array $config = []) { + $defaults = (array)Configure::read('Bbcode'); + parent::__construct($View, $config + $defaults); + + if ($this->_config['debug'] === null) { + $this->_config['debug'] = Configure::read('debug'); + } + } + + /** + * Highlight a string. + * + * Options, depending on the specific highlighter class used: + * - templates + * - escape (defaults to true) + * - tabToSpaces (defaults to 4) + * - prefix (defaults to `language-`) + * + * @param string $text + * @param array $options + * @return string + */ + public function convert(string $text, array $options = []): string { + if ($this->_config['debug']) { + $this->_startTimer(); + } + $html = $this->_getConverter()->convert($text, $options); + if ($this->_config['debug']) { + $html .= $this->_timeElapsedFormatted($this->_endTimer()); + } + + return $html; + } + + /** + * @return \Markup\Bbcode\BbcodeInterface + */ + protected function _getConverter() { + if (isset($this->_converter)) { + return $this->_converter; + } + $className = $this->_config['converter']; + + $this->_converter = new $className($this->_config); + + return $this->_converter; + } + + /** + * @return void + */ + protected function _startTimer() { + $this->_time = microtime(true); + } + + /** + * @return float + */ + protected function _endTimer() { + $now = microtime(true); + + return $now - $this->_time; + } + + /** + * @param float $time + * @return string + */ + protected function _timeElapsedFormatted($time) { + return ''; + } + +} diff --git a/src/View/Helper/MarkdownHelper.php b/src/View/Helper/MarkdownHelper.php index 7d39f96..66ad45a 100644 --- a/src/View/Helper/MarkdownHelper.php +++ b/src/View/Helper/MarkdownHelper.php @@ -12,7 +12,7 @@ class MarkdownHelper extends Helper { /** * @var \Markup\Markdown\MarkdownInterface */ - protected $_parser; + protected $_converter; /** * @var array @@ -59,26 +59,26 @@ public function convert(string $text, array $options = []): string { if ($this->_config['debug']) { $this->_startTimer(); } - $highlightedText = $this->_getConverter()->convert($text, $options); + $html = $this->_getConverter()->convert($text, $options); if ($this->_config['debug']) { - $highlightedText .= $this->_timeElapsedFormatted($this->_endTimer()); + $html .= $this->_timeElapsedFormatted($this->_endTimer()); } - return $highlightedText; + return trim($html); } /** * @return \Markup\Markdown\MarkdownInterface */ protected function _getConverter() { - if (isset($this->_parser)) { - return $this->_parser; + if (isset($this->_converter)) { + return $this->_converter; } - $className = $this->_config['parser']; + $className = $this->_config['converter']; - $this->_parser = new $className($this->_config); + $this->_converter = new $className($this->_config); - return $this->_parser; + return $this->_converter; } /** diff --git a/tests/TestCase/Bbcode/DecodaBbcodeTest.php b/tests/TestCase/Bbcode/DecodaBbcodeTest.php index bc70c51..06232b5 100644 --- a/tests/TestCase/Bbcode/DecodaBbcodeTest.php +++ b/tests/TestCase/Bbcode/DecodaBbcodeTest.php @@ -1,6 +1,6 @@ false, + ] + ); + + $this->request = new ServerRequest(); + $view = new View($this->request); + $this->helper = new BbcodeHelper($view); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->helper); + } + + /** + * @return void + */ + public function testConvert() { + $text = <<<'TEXT' +Some [b]bold[/b] text. +TEXT; + + $result = $this->helper->convert($text); + $expected = 'Some bold text.'; + $this->assertSame($expected, $result); + } + +} diff --git a/tests/TestCase/View/Helper/HighlighterHelperTest.php b/tests/TestCase/View/Helper/HighlighterHelperTest.php index 2e52797..d4413bc 100644 --- a/tests/TestCase/View/Helper/HighlighterHelperTest.php +++ b/tests/TestCase/View/Helper/HighlighterHelperTest.php @@ -1,6 +1,6 @@ false, + ] + ); + + $this->request = new ServerRequest(); + $view = new View($this->request); + $this->helper = new MarkdownHelper($view); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->helper); + } + + /** + * @return void + */ + public function testConvert() { + $text = <<<'TEXT' +Some **bold** text. +TEXT; + + $result = $this->helper->convert($text); + $expected = '

Some bold text.

'; + $this->assertSame($expected, $result); + } + +} From 07d4ae004490b1caa986f0149630bcc75da1b88b Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 19 Sep 2020 02:31:04 +0200 Subject: [PATCH 3/4] Rename class --- src/Bbcode/{Filter => Decoda}/VideoFilter.php | 2 +- src/Bbcode/DecodaBbcode.php | 2 +- tests/phpstan.neon | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) rename src/Bbcode/{Filter => Decoda}/VideoFilter.php (98%) diff --git a/src/Bbcode/Filter/VideoFilter.php b/src/Bbcode/Decoda/VideoFilter.php similarity index 98% rename from src/Bbcode/Filter/VideoFilter.php rename to src/Bbcode/Decoda/VideoFilter.php index 50c9c30..fc96416 100644 --- a/src/Bbcode/Filter/VideoFilter.php +++ b/src/Bbcode/Decoda/VideoFilter.php @@ -1,6 +1,6 @@ Date: Sat, 19 Sep 2020 02:42:21 +0200 Subject: [PATCH 4/4] Add more tests. --- src/Bbcode/DecodaBbcode.php | 8 ---- src/Highlighter/JsHighlighter.php | 1 + src/Highlighter/PhpHighlighter.php | 1 + src/Markdown/CommonMarkMarkdown.php | 8 ---- .../Highlighter/JsHighlighterTest.php | 48 +++++++++++++++++++ .../Highlighter/PhpHighlighterTest.php | 48 +++++++++++++++++++ .../TestCase/View/Helper/BbcodeHelperTest.php | 17 +++++++ .../View/Helper/MarkdownHelperTest.php | 17 +++++++ 8 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 tests/TestCase/Highlighter/JsHighlighterTest.php create mode 100644 tests/TestCase/Highlighter/PhpHighlighterTest.php diff --git a/src/Bbcode/DecodaBbcode.php b/src/Bbcode/DecodaBbcode.php index 7473d8f..4f3e832 100644 --- a/src/Bbcode/DecodaBbcode.php +++ b/src/Bbcode/DecodaBbcode.php @@ -41,14 +41,6 @@ public function __construct(array $config = []) { $this->setConfig($config); } - /** - * @param string $string - * @return string - */ - protected function _prepare($string) { - return $string; - } - /** * @param string $text * @param array $options diff --git a/src/Highlighter/JsHighlighter.php b/src/Highlighter/JsHighlighter.php index 943d052..4b2f2e7 100644 --- a/src/Highlighter/JsHighlighter.php +++ b/src/Highlighter/JsHighlighter.php @@ -14,6 +14,7 @@ class JsHighlighter extends Highlighter { 'code' => '
{{content}}
', ], 'prefix' => 'language-', + 'lang' => 'txt', ]; /** diff --git a/src/Highlighter/PhpHighlighter.php b/src/Highlighter/PhpHighlighter.php index 8166ec2..aebdfd6 100644 --- a/src/Highlighter/PhpHighlighter.php +++ b/src/Highlighter/PhpHighlighter.php @@ -12,6 +12,7 @@ class PhpHighlighter extends Highlighter { 'code' => '{{content}}
', ], 'prefix' => 'language-', + 'lang' => 'txt', ]; /** diff --git a/src/Markdown/CommonMarkMarkdown.php b/src/Markdown/CommonMarkMarkdown.php index d096472..beb3208 100644 --- a/src/Markdown/CommonMarkMarkdown.php +++ b/src/Markdown/CommonMarkMarkdown.php @@ -28,14 +28,6 @@ public function __construct(array $config = []) { $this->setConfig($config); } - /** - * @param string $string - * @return string - */ - protected function _prepare($string) { - return $string; - } - /** * @param string $text * @param array $options diff --git a/tests/TestCase/Highlighter/JsHighlighterTest.php b/tests/TestCase/Highlighter/JsHighlighterTest.php new file mode 100644 index 0000000..0ad192c --- /dev/null +++ b/tests/TestCase/Highlighter/JsHighlighterTest.php @@ -0,0 +1,48 @@ + false, + ] + ); + + $this->highlighter = new JsHighlighter(); + } + + /** + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->highlighter); + } + + /** + * @return void + */ + public function testConvert(): void { + $result = $this->highlighter->highlight('My text'); + $expected = '
My text
'; + $this->assertSame($expected, $result); + } + +} diff --git a/tests/TestCase/Highlighter/PhpHighlighterTest.php b/tests/TestCase/Highlighter/PhpHighlighterTest.php new file mode 100644 index 0000000..088af91 --- /dev/null +++ b/tests/TestCase/Highlighter/PhpHighlighterTest.php @@ -0,0 +1,48 @@ + false, + ] + ); + + $this->highlighter = new PhpHighlighter(); + } + + /** + * @return void + */ + public function tearDown(): void { + parent::tearDown(); + + unset($this->highlighter); + } + + /** + * @return void + */ + public function testConvert(): void { + $result = $this->highlighter->highlight('My text'); + $expected = '
My text
'; + $this->assertSame($expected, $result); + } + +} diff --git a/tests/TestCase/View/Helper/BbcodeHelperTest.php b/tests/TestCase/View/Helper/BbcodeHelperTest.php index 3f33849..2a8fd19 100644 --- a/tests/TestCase/View/Helper/BbcodeHelperTest.php +++ b/tests/TestCase/View/Helper/BbcodeHelperTest.php @@ -62,4 +62,21 @@ public function testConvert() { $this->assertSame($expected, $result); } + /** + * @return void + */ + public function testConvertDebug() { + $this->helper->setConfig('debug', true); + + $text = <<<'TEXT' +Some [b]bold[/b] text. +TEXT; + + $result = $this->helper->convert($text); + $expected = ''; + $this->assertStringContainsString($expected, $result); + } + } diff --git a/tests/TestCase/View/Helper/MarkdownHelperTest.php b/tests/TestCase/View/Helper/MarkdownHelperTest.php index 2b6e640..278b0a9 100644 --- a/tests/TestCase/View/Helper/MarkdownHelperTest.php +++ b/tests/TestCase/View/Helper/MarkdownHelperTest.php @@ -62,4 +62,21 @@ public function testConvert() { $this->assertSame($expected, $result); } + /** + * @return void + */ + public function testConvertDebug() { + $this->helper->setConfig('debug', true); + + $text = <<<'TEXT' +Some **bold** text. +TEXT; + + $result = $this->helper->convert($text); + $expected = ''; + $this->assertStringContainsString($expected, $result); + } + }