Browse Source

LibMarkdown: Add support for images :^)

Sergey Bugaev 5 years ago
parent
commit
f1a8fb1e88
2 changed files with 35 additions and 3 deletions
  1. 34 3
      Libraries/LibMarkdown/Text.cpp
  2. 1 0
      Libraries/LibMarkdown/Text.h

+ 34 - 3
Libraries/LibMarkdown/Text.cpp

@@ -65,6 +65,8 @@ String Text::render_to_html() const
         auto it = open_tags.find([&](const String& open_tag) {
         auto it = open_tags.find([&](const String& open_tag) {
             if (open_tag == "a" && current_style.href != span.style.href)
             if (open_tag == "a" && current_style.href != span.style.href)
                 return true;
                 return true;
+            if (open_tag == "img" && current_style.img != span.style.img)
+                return true;
             for (auto& tag_and_flag : tags_and_flags) {
             for (auto& tag_and_flag : tags_and_flags) {
                 if (open_tag == tag_and_flag.tag && !(span.style.*tag_and_flag.flag))
                 if (open_tag == tag_and_flag.tag && !(span.style.*tag_and_flag.flag))
                     return true;
                     return true;
@@ -79,6 +81,11 @@ String Text::render_to_html() const
             // it.
             // it.
             for (ssize_t j = open_tags.size() - 1; j >= static_cast<ssize_t>(it.index()); --j) {
             for (ssize_t j = open_tags.size() - 1; j >= static_cast<ssize_t>(it.index()); --j) {
                 auto& tag = open_tags[j];
                 auto& tag = open_tags[j];
+                if (tag == "img") {
+                    builder.append("\" />");
+                    current_style.img = {};
+                    continue;
+                }
                 builder.appendf("</%s>", tag.characters());
                 builder.appendf("</%s>", tag.characters());
                 if (tag == "a") {
                 if (tag == "a") {
                     current_style.href = {};
                     current_style.href = {};
@@ -94,6 +101,10 @@ String Text::render_to_html() const
             open_tags.append("a");
             open_tags.append("a");
             builder.appendf("<a href=\"%s\">", span.style.href.characters());
             builder.appendf("<a href=\"%s\">", span.style.href.characters());
         }
         }
+        if (current_style.img.is_null() && !span.style.img.is_null()) {
+            open_tags.append("img");
+            builder.appendf("<img src=\"%s\" alt=\"", span.style.img.characters());
+        }
         for (auto& tag_and_flag : tags_and_flags) {
         for (auto& tag_and_flag : tags_and_flags) {
             if (current_style.*tag_and_flag.flag != span.style.*tag_and_flag.flag) {
             if (current_style.*tag_and_flag.flag != span.style.*tag_and_flag.flag) {
                 open_tags.append(tag_and_flag.tag);
                 open_tags.append(tag_and_flag.tag);
@@ -107,6 +118,10 @@ String Text::render_to_html() const
 
 
     for (ssize_t i = open_tags.size() - 1; i >= 0; --i) {
     for (ssize_t i = open_tags.size() - 1; i >= 0; --i) {
         auto& tag = open_tags[i];
         auto& tag = open_tags[i];
+        if (tag == "img") {
+            builder.append("\" />");
+            continue;
+        }
         builder.appendf("</%s>", tag.characters());
         builder.appendf("</%s>", tag.characters());
     }
     }
 
 
@@ -147,6 +162,11 @@ String Text::render_for_terminal() const
                 builder.appendf(" <%s>", span.style.href.characters());
                 builder.appendf(" <%s>", span.style.href.characters());
             }
             }
         }
         }
+        if (!span.style.img.is_null()) {
+            if (strstr(span.style.img.characters(), "://") != nullptr) {
+                builder.appendf(" <%s>", span.style.img.characters());
+            }
+        }
     }
     }
 
 
     return builder.build();
     return builder.build();
@@ -157,6 +177,7 @@ bool Text::parse(const StringView& str)
     Style current_style;
     Style current_style;
     size_t current_span_start = 0;
     size_t current_span_start = 0;
     int first_span_in_the_current_link = -1;
     int first_span_in_the_current_link = -1;
+    bool current_link_is_actually_img = false;
 
 
     auto append_span_if_needed = [&](size_t offset) {
     auto append_span_if_needed = [&](size_t offset) {
         ASSERT(current_span_start <= offset);
         ASSERT(current_span_start <= offset);
@@ -182,7 +203,7 @@ bool Text::parse(const StringView& str)
         bool is_special_character = false;
         bool is_special_character = false;
         is_special_character |= ch == '`';
         is_special_character |= ch == '`';
         if (!current_style.code)
         if (!current_style.code)
-            is_special_character |= ch == '*' || ch == '_' || ch == '[' || ch == ']';
+            is_special_character |= ch == '*' || ch == '_' || ch == '[' || ch == ']' || ch == '!';
         if (!is_special_character)
         if (!is_special_character)
             continue;
             continue;
 
 
@@ -201,6 +222,11 @@ bool Text::parse(const StringView& str)
                 current_style.emph = !current_style.emph;
                 current_style.emph = !current_style.emph;
             }
             }
             break;
             break;
+        case '!':
+            if (offset + 1 >= str.length() || str[offset + 1] != '[')
+                continue;
+            current_link_is_actually_img = true;
+            break;
         case '[':
         case '[':
             if (first_span_in_the_current_link != -1)
             if (first_span_in_the_current_link != -1)
                 dbg() << "Dropping the outer link";
                 dbg() << "Dropping the outer link";
@@ -213,6 +239,7 @@ bool Text::parse(const StringView& str)
             }
             }
             ScopeGuard guard = [&] {
             ScopeGuard guard = [&] {
                 first_span_in_the_current_link = -1;
                 first_span_in_the_current_link = -1;
+                current_link_is_actually_img = false;
             };
             };
             if (offset + 2 >= str.length() || str[offset + 1] != '(')
             if (offset + 2 >= str.length() || str[offset + 1] != '(')
                 continue;
                 continue;
@@ -226,8 +253,12 @@ bool Text::parse(const StringView& str)
                 offset--;
                 offset--;
 
 
             const StringView href = str.substring_view(start_of_href, offset - start_of_href);
             const StringView href = str.substring_view(start_of_href, offset - start_of_href);
-            for (size_t i = first_span_in_the_current_link; i < m_spans.size(); i++)
-                m_spans[i].style.href = href;
+            for (size_t i = first_span_in_the_current_link; i < m_spans.size(); i++) {
+                if (current_link_is_actually_img)
+                    m_spans[i].style.img = href;
+                else
+                    m_spans[i].style.href = href;
+            }
             break;
             break;
         }
         }
         default:
         default:

+ 1 - 0
Libraries/LibMarkdown/Text.h

@@ -38,6 +38,7 @@ public:
         bool strong { false };
         bool strong { false };
         bool code { false };
         bool code { false };
         String href;
         String href;
+        String img;
     };
     };
 
 
     struct Span {
     struct Span {