From 527b658ca026e8c4535920ee90c4ba79d4b69054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 22 Mar 2021 17:32:57 +0100 Subject: [PATCH] [ckeditor][markdown] introduce twig filter `chill_markdown_to_html` --- .../Resources/public/sass/_custom.scss | 21 +++-- .../ChillMarkdownRenderExtension.php | 56 ++++++++++++++ .../ChillMarkdownRenderExtensionTest.php | 76 +++++++++++++++++++ .../config/services/templating.yaml | 4 + .../Resources/views/Person/view.html.twig | 18 +++-- 5 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Templating/ChillMarkdownRenderExtensionTest.php diff --git a/src/Bundle/ChillMainBundle/Resources/public/sass/_custom.scss b/src/Bundle/ChillMainBundle/Resources/public/sass/_custom.scss index 3d7ce19af..0fe6bd846 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/sass/_custom.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/sass/_custom.scss @@ -157,16 +157,27 @@ dl.chill_view_data { } -blockquote.chill-user-quote { +blockquote.chill-user-quote, +div.chill-user-quote { border-left: 10px solid $chill-yellow; margin: 1.5em 10px; padding: 0.5em 10px; quotes: "\201C""\201D""\2018""\2019"; background-color: $chill-llight-gray; - - - p { display: inline; } - + + blockquote { + margin: 1.5em 10px; + padding: 0.5em 10px; + } + + blockquote:before { + color: #ccc; + content: open-quote; + font-size: 4em; + line-height: 0.1em; + margin-right: 0.25em; + vertical-align: -0.4em; + } } .chill-no-data-statement { diff --git a/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php b/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php new file mode 100644 index 000000000..8615150c3 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php @@ -0,0 +1,56 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Templating; + +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; + +use Parsedown; + +/** + * Render markdown + * + */ +class ChillMarkdownRenderExtension extends AbstractExtension +{ + /** + * + * @var Parsedown + */ + protected $parsedown; + + public function __construct() + { + $this->parsedown = new Parsedown(); + $this->parsedown->setSafeMode(true); + } + + public function getFilters() + { + return [ + new TwigFilter('chill_markdown_to_html', [$this, 'renderMarkdownToHtml'], [ + 'is_safe' => [ 'html' ] + ]) + ]; + } + + public function renderMarkdownToHtml($var) + { + return $this->parsedown->parse($var); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Templating/ChillMarkdownRenderExtensionTest.php b/src/Bundle/ChillMainBundle/Tests/Templating/ChillMarkdownRenderExtensionTest.php new file mode 100644 index 000000000..d95969b9d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Templating/ChillMarkdownRenderExtensionTest.php @@ -0,0 +1,76 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Tests\Templating; + +use PHPUnit\Framework\TestCase; +use Chill\MainBundle\Templating\ChillMarkdownRenderExtension; + +/** + * Test the service ChillMarkdownRenderExtension + * + * @internal we do not want to test the markdown transformation. We just want to + * test that the markdown is correctly transformed into html, and that the html + * is safe. + */ +class ChillMarkdownRenderExtensionTest extends TestCase +{ + + private const SIMPLE_MARKDOWN = <<test +

Text.

+HTML; + + private const UNAUTHORIZED_MARKDOWN = <<alert("ok"); +MD; + + private const UNAUTHORIZED_HTML = <<<script>alert("ok");</script>

+HTML; + + /** + * Test that the markdown input is transformed into html + */ + public function testRendering() + { + $extension = new ChillMarkdownRenderExtension(); + + $this->assertEquals(self::SIMPLE_HTML, + $extension->renderMarkdownToHtml(self::SIMPLE_MARKDOWN)); + } + + /** + * Test that the output of the markdown content is sanitized + */ + public function testSecurity() + { + $extension = new ChillMarkdownRenderExtension(); + + $this->assertEquals(self::UNAUTHORIZED_HTML, + $extension->renderMarkdownToHtml(self::UNAUTHORIZED_MARKDOWN)); + } +} diff --git a/src/Bundle/ChillMainBundle/config/services/templating.yaml b/src/Bundle/ChillMainBundle/config/services/templating.yaml index 0dfb92380..f9bd8d7fb 100644 --- a/src/Bundle/ChillMainBundle/config/services/templating.yaml +++ b/src/Bundle/ChillMainBundle/config/services/templating.yaml @@ -36,3 +36,7 @@ services: - '@chill.main.user_repository' tags: - { name: 'chill.render_entity' } + + Chill\MainBundle\Templating\ChillMarkdownRenderExtension: + tags: + - { name: twig.extension } diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig index d9a0d8d31..45c8cd1ed 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig @@ -48,11 +48,9 @@ This view should receive those arguments: {#

{{ person.memo|nl2br }}

#} -
+
+ {{ person.memo|chill_markdown_to_html }}
- {% apply markdown_to_html %} - {{ person.memo }} - {% endapply %}
{% endif %} @@ -214,7 +212,7 @@ This view should receive those arguments: {%- if chill_person.fields.email == 'visible' -%}
{{ 'Email'|trans }} :
-
{% if person.email is not empty %}
{{ person.email|nl2br }}
{% else %}{{ 'No data given'|trans }}{% endif %}
+
{% if person.email is not empty %}{{ person.email }}{% else %}{{ 'No data given'|trans }}{% endif %}
{%- endif -%} {%- if chill_person.fields.phonenumber == 'visible' -%} @@ -232,7 +230,15 @@ This view should receive those arguments: {%- if chill_person.fields.contact_info == 'visible' -%}
{{ 'Notes on contact information'|trans }} :
-
{% if person.contactInfo is not empty %}{{ person.contactInfo|nl2br }}{% else %}{{ 'No data given'|trans }}{% endif %}
+
+ {% if person.contactInfo is not empty %} +
+ {{ person.contactInfo|chill_markdown_to_html }} +
+ {% else %} + {{ 'No data given'|trans }} + {% endif %} +
{%- endif -%}