From 8fabcd0224b1122a48b495326854bb3562cd2e9d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Thu, 27 Aug 2020 15:25:18 +0200 Subject: Add Markdown Extra formatter Library: [Parsedown Extra](https://github.com/erusev/parsedown-extra) Also sort dependencies alphabetically. Fixes #1169 --- .../formatter/BookmarkMarkdownExtraFormatter.php | 24 +++ .../front/controller/admin/ConfigureController.php | 2 +- composer.json | 10 +- composer.lock | 67 ++++++++- .../BookmarkMarkdownExtraFormatterTest.php | 162 +++++++++++++++++++++ .../controller/admin/ConfigureControllerTest.php | 2 +- tpl/default/includes.html | 2 +- 7 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 application/formatter/BookmarkMarkdownExtraFormatter.php create mode 100644 tests/formatter/BookmarkMarkdownExtraFormatterTest.php diff --git a/application/formatter/BookmarkMarkdownExtraFormatter.php b/application/formatter/BookmarkMarkdownExtraFormatter.php new file mode 100644 index 00000000..0694b23f --- /dev/null +++ b/application/formatter/BookmarkMarkdownExtraFormatter.php @@ -0,0 +1,24 @@ +parsedown = new \ParsedownExtra(); + } +} diff --git a/application/front/controller/admin/ConfigureController.php b/application/front/controller/admin/ConfigureController.php index e675fcca..0ed7ad81 100644 --- a/application/front/controller/admin/ConfigureController.php +++ b/application/front/controller/admin/ConfigureController.php @@ -30,7 +30,7 @@ class ConfigureController extends ShaarliAdminController 'theme_available', ThemeUtils::getThemes($this->container->conf->get('resource.raintpl_tpl')) ); - $this->assignView('formatter_available', ['default', 'markdown']); + $this->assignView('formatter_available', ['default', 'markdown', 'markdownExtra']); list($continents, $cities) = generateTimeZoneData( timezone_identifiers_list(), $this->container->conf->get('general.timezone') diff --git a/composer.json b/composer.json index cd9fcf5b..7e675623 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ }, "keywords": ["bookmark", "link", "share", "web"], "config": { + "sort-packages": true, "platform": { "php": "7.1.29" } @@ -18,12 +19,13 @@ "php": ">=7.1", "ext-json": "*", "ext-zlib": "*", - "shaarli/netscape-bookmark-parser": "^2.1", - "erusev/parsedown": "^1.6", - "slim/slim": "^3.0", "arthurhoaro/web-thumbnailer": "^2.0", + "erusev/parsedown": "^1.6", + "erusev/parsedown-extra": "^0.8.1", + "gettext/gettext": "^4.4", "pubsubhubbub/publisher": "dev-master", - "gettext/gettext": "^4.4" + "shaarli/netscape-bookmark-parser": "^2.1", + "slim/slim": "^3.0" }, "require-dev": { "roave/security-advisories": "dev-master", diff --git a/composer.lock b/composer.lock index 2c8b0ea7..e02491ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "98520a05a7185503ee13d05ffaa535f6", + "content-hash": "f84918821b0dceb0cd569875c0418bb8", "packages": [ { "name": "arthurhoaro/web-thumbnailer", @@ -107,6 +107,57 @@ }, "time": "2019-12-30T22:54:17+00:00" }, + { + "name": "erusev/parsedown-extra", + "version": "0.8.1", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown-extra.git", + "reference": "91ac3ff98f0cea243bdccc688df43810f044dcef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/91ac3ff98f0cea243bdccc688df43810f044dcef", + "reference": "91ac3ff98f0cea243bdccc688df43810f044dcef", + "shasum": "" + }, + "require": { + "erusev/parsedown": "^1.7.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "ParsedownExtra": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "An extension of Parsedown that adds support for Markdown Extra.", + "homepage": "https://github.com/erusev/parsedown-extra", + "keywords": [ + "markdown", + "markdown extra", + "parsedown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown-extra/issues", + "source": "https://github.com/erusev/parsedown-extra/tree/0.8.x" + }, + "time": "2019-12-30T23:20:37+00:00" + }, { "name": "gettext/gettext", "version": "v4.8.2", @@ -1577,12 +1628,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "0749ceaf15c136d085b722a5bb88141398a54142" + "reference": "ba5d234b3a1559321b816b64aafc2ce6728799ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0749ceaf15c136d085b722a5bb88141398a54142", - "reference": "0749ceaf15c136d085b722a5bb88141398a54142", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/ba5d234b3a1559321b816b64aafc2ce6728799ff", + "reference": "ba5d234b3a1559321b816b64aafc2ce6728799ff", "shasum": "" }, "conflict": { @@ -1642,7 +1693,7 @@ "ezsystems/ezplatform-kernel": ">=1,<1.0.2.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.2|>=6,<6.7.9.1|>=6.8,<6.13.6.3|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.7.1", - "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.1|>=2011,<2017.12.7.2|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.4.2", + "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.2|>=2011,<2017.12.7.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", @@ -1685,6 +1736,8 @@ "mittwald/typo3_forum": "<1.2.1", "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", "nystudio107/craft-seomatic": "<3.3", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": ">=1.0.319,<1.0.467", @@ -1720,6 +1773,7 @@ "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<0.7.19|>=1-rc.0,<=1-rc.6", "pusher/pusher-php-server": "<2.2.1", "rainlab/debugbar-plugin": "<3.1", "robrichards/xmlseclibs": "<3.0.4", @@ -1805,6 +1859,7 @@ "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3fluid/fluid": ">=2,<2.0.5|>=2.1,<2.1.4|>=2.2,<2.2.1|>=2.3,<2.3.5|>=2.4,<2.4.1|>=2.5,<2.5.5|>=2.6,<2.6.1", "ua-parser/uap-php": "<3.8", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", @@ -1878,7 +1933,7 @@ "type": "tidelift" } ], - "time": "2020-09-24T17:02:11+00:00" + "time": "2020-10-08T21:02:27+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", diff --git a/tests/formatter/BookmarkMarkdownExtraFormatterTest.php b/tests/formatter/BookmarkMarkdownExtraFormatterTest.php new file mode 100644 index 00000000..d4941ef3 --- /dev/null +++ b/tests/formatter/BookmarkMarkdownExtraFormatterTest.php @@ -0,0 +1,162 @@ +conf = new ConfigManager(self::$testConf); + $this->formatter = new BookmarkMarkdownExtraFormatter($this->conf, true); + } + + /** + * Test formatting a bookmark with all its attribute filled. + */ + public function testFormatExtra(): void + { + $bookmark = new Bookmark(); + $bookmark->setId($id = 11); + $bookmark->setShortUrl($short = 'abcdef'); + $bookmark->setUrl('https://sub.domain.tld?query=here&for=real#hash'); + $bookmark->setTitle($title = 'This is a bookmark'); + $bookmark->setDescription('

Content

`Here is some content

'); + $bookmark->setTags($tags = ['tag1', 'bookmark', 'other', '']); + $bookmark->setThumbnail('http://domain2.tdl2/?type=img&name=file.png'); + $bookmark->setSticky(true); + $bookmark->setCreated($created = DateTime::createFromFormat('Ymd_His', '20190521_190412')); + $bookmark->setUpdated($updated = DateTime::createFromFormat('Ymd_His', '20190521_191213')); + $bookmark->setPrivate(true); + + $link = $this->formatter->format($bookmark); + $this->assertEquals($id, $link['id']); + $this->assertEquals($short, $link['shorturl']); + $this->assertEquals('https://sub.domain.tld?query=here&for=real#hash', $link['url']); + $this->assertEquals( + 'https://sub.domain.tld?query=here&for=real#hash', + $link['real_url'] + ); + $this->assertEquals('This is a <strong>bookmark</strong>', $link['title']); + $this->assertEquals( + '

'. + '<h2>Content</h2><p>`Here is some content</p>'. + '

', + $link['description'] + ); + $tags[3] = '<script>alert("xss");</script>'; + $this->assertEquals($tags, $link['taglist']); + $this->assertEquals(implode(' ', $tags), $link['tags']); + $this->assertEquals( + 'http://domain2.tdl2/?type=img&name=file.png', + $link['thumbnail'] + ); + $this->assertEquals($created, $link['created']); + $this->assertEquals($created->getTimestamp(), $link['timestamp']); + $this->assertEquals($updated, $link['updated']); + $this->assertEquals($updated->getTimestamp(), $link['updated_timestamp']); + $this->assertTrue($link['private']); + $this->assertTrue($link['sticky']); + $this->assertEquals('private', $link['class']); + } + + /** + * Test formatting a bookmark with all its attribute filled. + */ + public function testFormatExtraMinimal(): void + { + $bookmark = new Bookmark(); + + $link = $this->formatter->format($bookmark); + $this->assertEmpty($link['id']); + $this->assertEmpty($link['shorturl']); + $this->assertEmpty($link['url']); + $this->assertEmpty($link['real_url']); + $this->assertEmpty($link['title']); + $this->assertEmpty($link['description']); + $this->assertEmpty($link['taglist']); + $this->assertEmpty($link['tags']); + $this->assertEmpty($link['thumbnail']); + $this->assertEmpty($link['created']); + $this->assertEmpty($link['timestamp']); + $this->assertEmpty($link['updated']); + $this->assertEmpty($link['updated_timestamp']); + $this->assertFalse($link['private']); + $this->assertFalse($link['sticky']); + $this->assertEmpty($link['class']); + } + + /** + * Make sure that the description is properly formatted by the default formatter. + */ + public function testFormatExtrraDescription(): void + { + $description = 'This a description'. PHP_EOL; + $description .= 'text https://sub.domain.tld?query=here&for=real#hash more text'. PHP_EOL; + $description .= 'Also, there is an #hashtag added'. PHP_EOL; + $description .= ' A N D KEEP SPACES ! '. PHP_EOL; + $description .= '# Header {.class}'. PHP_EOL; + + $bookmark = new Bookmark(); + $bookmark->setDescription($description); + $link = $this->formatter->format($bookmark); + + $description = '

'; + $description .= 'This a <strong>description</strong>
'. PHP_EOL; + $url = 'https://sub.domain.tld?query=here&for=real#hash'; + $description .= 'text '. $url .' more text
'. PHP_EOL; + $description .= 'Also, there is an #hashtag added
'. PHP_EOL; + $description .= 'A N D KEEP SPACES !

' . PHP_EOL; + $description .= '

Header

'; + $description .= '
'; + + $this->assertEquals($description, $link['description']); + } + + /** + * Test formatting URL with an index_url set + * It should prepend relative links. + */ + public function testFormatExtraNoteWithIndexUrl(): void + { + $bookmark = new Bookmark(); + $bookmark->setUrl($short = '?abcdef'); + $description = 'Text #hashtag more text'; + $bookmark->setDescription($description); + + $this->formatter->addContextData('index_url', $root = 'https://domain.tld/hithere/'); + + $description = '

'; + $description .= 'Text #hashtag more text'; + $description .= '

'; + + $link = $this->formatter->format($bookmark); + $this->assertEquals($root . $short, $link['url']); + $this->assertEquals($root . $short, $link['real_url']); + $this->assertEquals( + $description, + $link['description'] + ); + } +} diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php index aca6cff3..d82db0a7 100644 --- a/tests/front/controller/admin/ConfigureControllerTest.php +++ b/tests/front/controller/admin/ConfigureControllerTest.php @@ -51,7 +51,7 @@ class ConfigureControllerTest extends TestCase static::assertSame('general.title', $assignedVariables['title']); static::assertSame('resource.theme', $assignedVariables['theme']); static::assertEmpty($assignedVariables['theme_available']); - static::assertSame(['default', 'markdown'], $assignedVariables['formatter_available']); + static::assertSame(['default', 'markdown', 'markdownExtra'], $assignedVariables['formatter_available']); static::assertNotEmpty($assignedVariables['continents']); static::assertNotEmpty($assignedVariables['cities']); static::assertSame('general.retrieve_description', $assignedVariables['retrieve_description']); diff --git a/tpl/default/includes.html b/tpl/default/includes.html index 227f9b52..09768ac4 100644 --- a/tpl/default/includes.html +++ b/tpl/default/includes.html @@ -8,7 +8,7 @@ -{if="$formatter==='markdown'"} +{if="strpos($formatter, 'markdown') !== false"} {/if} {loop="$plugins_includes.css_files"} -- cgit v1.2.3