From f3680ea7de7318f9ee85ef3de9471cf70510abee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 6 Mar 2022 14:54:08 +0100 Subject: [PATCH] Parse markdown using stimulus controller. --- .../controllers/common/markdown_controller.js | 56 +++++++++++++++++++ config/packages/doctrine.yaml | 3 +- src/Services/MarkdownParser.php | 2 +- webpack.config.js | 16 +++++- 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 assets/controllers/common/markdown_controller.js diff --git a/assets/controllers/common/markdown_controller.js b/assets/controllers/common/markdown_controller.js new file mode 100644 index 00000000..cba78b49 --- /dev/null +++ b/assets/controllers/common/markdown_controller.js @@ -0,0 +1,56 @@ +'use strict'; + +import { Controller } from '@hotwired/stimulus'; +import * as marked from "marked"; +import DOMPurify from 'dompurify'; + +export default class extends Controller { + + connect() + { + console.log('Markdown controller called'); + this.render(); + } + + render() { + let raw = this.element.dataset['markdown']; + + //Apply purified parsed markdown + this.element.innerHTML = DOMPurify.sanitize(marked(this.unescapeHTML(raw))); + + for(let a of this.element.querySelectorAll('a')) { + //Mark all links as external + a.classList.add('link-external'); + //Open links in new tag + a.setAttribute('target', '_blank'); + //Dont track + a.setAttribute('rel', 'noopener'); + } + + //Apply bootstrap styles to + for(let table of this.element.querySelectorAll('table')) { + table.classList.add('table', 'table-hover', 'table-striped', 'table-bordered', 'table-sm'); + } + } + + /** + * Unescape the given HTML + * @param {string} html + * @returns {string} + */ + unescapeHTML(html) { + var txt = document.createElement('textarea'); + txt.innerHTML = html; + return txt.value; + } + + /** + * Configure the marked parser + */ + configureMarked() + { + marked.setOptions({ + gfm: true, + }); + } +} \ No newline at end of file diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index 5d3bdc81..8f9d1586 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -15,7 +15,8 @@ doctrine: class: App\Helpers\BigDecimalType schema_filter: ~^(?!internal)~ - profiling_collect_backtrace: true + # Only enable this when needed + profiling_collect_backtrace: false orm: auto_generate_proxy_classes: true diff --git a/src/Services/MarkdownParser.php b/src/Services/MarkdownParser.php index 224a15a5..fc25b1ad 100644 --- a/src/Services/MarkdownParser.php +++ b/src/Services/MarkdownParser.php @@ -68,7 +68,7 @@ class MarkdownParser public function markForRendering(string $markdown, bool $inline_mode = false): string { return sprintf( - '
%s
', + '
%s
', htmlspecialchars($markdown), $this->translator->trans('markdown.loading') ); diff --git a/webpack.config.js b/webpack.config.js index 785608c3..eb5fc6fe 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -98,7 +98,7 @@ Encore //.enableSassLoader() // uncomment if you use TypeScript - .enableTypeScriptLoader() + //.enableTypeScriptLoader() // uncomment if you use React //.enableReactPreset() @@ -124,9 +124,19 @@ Encore // uncomment if you're having problems with a jQuery plugin .autoProvidejQuery() - ; +//Copy bootstrap map if in debug mode +if (Encore.isDev()) { + Encore.addPlugin(new CopyPlugin({ + patterns: [ + { + from: 'node_modules/bootstrap/dist/css/bootstrap.min.css.map', + to: 'themes/bootstrap.min.css.map' + } + ]})) +} + if (Encore.isProduction()) { Encore.addPlugin(new CompressionPlugin({ filename: '[path][base].br', @@ -151,7 +161,7 @@ if (Encore.isProduction()) { if (Encore.isDev()) { //Only uncomment if needed, as this cause problems with Github actions (job does not finish) - //Encore.addPlugin(new BundleAnalyzerPlugin()); + Encore.addPlugin(new BundleAnalyzerPlugin()); }