From c8a7acb6c7459caee96de296b4342f8f3554a5f6 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Fri, 29 Apr 2022 12:17:14 +0100
Subject: [PATCH] Fixed drawing handling on HTML to Markdown conversion

---
 .../Tools/Markdown/CustomDivConverter.php     | 20 ++++++++++++++++
 .../Tools/Markdown/CustomImageConverter.php   | 24 +++++++++++++++++++
 .../Markdown/CustomParagraphConverter.php     |  2 +-
 .../Tools/Markdown/HtmlToMarkdown.php         |  4 ++--
 tests/Entity/MarkdownToHtmlTest.php           |  8 +++++++
 5 files changed, 55 insertions(+), 3 deletions(-)
 create mode 100644 app/Entities/Tools/Markdown/CustomDivConverter.php
 create mode 100644 app/Entities/Tools/Markdown/CustomImageConverter.php

diff --git a/app/Entities/Tools/Markdown/CustomDivConverter.php b/app/Entities/Tools/Markdown/CustomDivConverter.php
new file mode 100644
index 000000000..486062390
--- /dev/null
+++ b/app/Entities/Tools/Markdown/CustomDivConverter.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace BookStack\Entities\Tools\Markdown;
+
+use League\HTMLToMarkdown\Converter\DivConverter;
+use League\HTMLToMarkdown\ElementInterface;
+
+class CustomDivConverter extends DivConverter
+{
+    public function convert(ElementInterface $element): string
+    {
+        // Clean up draw.io diagrams
+        $drawIoDiagram = $element->getAttribute('drawio-diagram');
+        if ($drawIoDiagram) {
+            return "<div drawio-diagram=\"{$drawIoDiagram}\">{$element->getValue()}</div>\n\n";
+        }
+
+        return parent::convert($element);
+    }
+}
diff --git a/app/Entities/Tools/Markdown/CustomImageConverter.php b/app/Entities/Tools/Markdown/CustomImageConverter.php
new file mode 100644
index 000000000..97b7afd1a
--- /dev/null
+++ b/app/Entities/Tools/Markdown/CustomImageConverter.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace BookStack\Entities\Tools\Markdown;
+
+use League\HTMLToMarkdown\Converter\ImageConverter;
+use League\HTMLToMarkdown\ElementInterface;
+
+class CustomImageConverter extends ImageConverter
+{
+    public function convert(ElementInterface $element): string
+    {
+        $parent = $element->getParent();
+
+        // Remain as HTML if within diagram block.
+        $withinDrawing = $parent && !empty($parent->getAttribute('drawio-diagram'));
+        if ($withinDrawing) {
+            $src = e($element->getAttribute('src'));
+            $alt = e($element->getAttribute('alt'));
+            return "<img src=\"{$src}\" alt=\"{$alt}\"/>";
+        }
+
+        return parent::convert($element);
+    }
+}
diff --git a/app/Entities/Tools/Markdown/CustomParagraphConverter.php b/app/Entities/Tools/Markdown/CustomParagraphConverter.php
index bd493aa03..db36042cd 100644
--- a/app/Entities/Tools/Markdown/CustomParagraphConverter.php
+++ b/app/Entities/Tools/Markdown/CustomParagraphConverter.php
@@ -9,7 +9,7 @@ class CustomParagraphConverter extends ParagraphConverter
 {
     public function convert(ElementInterface $element): string
     {
-        $class = $element->getAttribute('class');
+        $class = e($element->getAttribute('class'));
         if (strpos($class, 'callout') !== false) {
             return "<{$element->getTagName()} class=\"{$class}\">{$element->getValue()}</{$element->getTagName()}>\n\n";
         }
diff --git a/app/Entities/Tools/Markdown/HtmlToMarkdown.php b/app/Entities/Tools/Markdown/HtmlToMarkdown.php
index 5c7b388ea..aafb2733b 100644
--- a/app/Entities/Tools/Markdown/HtmlToMarkdown.php
+++ b/app/Entities/Tools/Markdown/HtmlToMarkdown.php
@@ -75,12 +75,12 @@ class HtmlToMarkdown
         $environment->addConverter(new BlockquoteConverter());
         $environment->addConverter(new CodeConverter());
         $environment->addConverter(new CommentConverter());
-        $environment->addConverter(new DivConverter());
+        $environment->addConverter(new CustomDivConverter());
         $environment->addConverter(new EmphasisConverter());
         $environment->addConverter(new HardBreakConverter());
         $environment->addConverter(new HeaderConverter());
         $environment->addConverter(new HorizontalRuleConverter());
-        $environment->addConverter(new ImageConverter());
+        $environment->addConverter(new CustomImageConverter());
         $environment->addConverter(new LinkConverter());
         $environment->addConverter(new ListBlockConverter());
         $environment->addConverter(new ListItemConverter());
diff --git a/tests/Entity/MarkdownToHtmlTest.php b/tests/Entity/MarkdownToHtmlTest.php
index 1a439636e..0b04f9cc4 100644
--- a/tests/Entity/MarkdownToHtmlTest.php
+++ b/tests/Entity/MarkdownToHtmlTest.php
@@ -39,6 +39,14 @@ class MarkdownToHtmlTest extends TestCase
         );
     }
 
+    public function test_drawing_blocks_remain_html()
+    {
+        $this->assertConversion(
+            '<div drawio-diagram="190" id="bkmrk--0" contenteditable="false"><img src="http://example.com/uploads/images/drawio/2022-04/drawing-1.png" alt="" /></div>Some text',
+            '<div drawio-diagram="190"><img src="http://example.com/uploads/images/drawio/2022-04/drawing-1.png" alt=""/></div>' . "\n\nSome text"
+        );
+    }
+
     protected function assertConversion(string $html, string $expectedMarkdown, bool $partialMdMatch = false)
     {
         $markdown = (new HtmlToMarkdown($html))->convert();