From 35cb54324f6c9f9288717173a9bc6b283f4af62d Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 26 Nov 2021 21:49:21 +0100 Subject: [PATCH] added a new item content type: markdown - emacs editor has an option to select markdown, now it has two planes: one for content editing and the other to show preview - CodeMirror editor updated to 5.64.0 - to convert markdown to html we use showdown https://github.com/showdownjs/showdown (conversion is done on the client side) --- winixd/functions/functions.cpp | 139 ++++++++++++++++++--------- winixd/functions/functions.h | 7 +- winixd/html/fun_emacs_post.html | 58 +++++++++++- winixd/html/index_head_adder.html | 150 +++++++++++++++++++++++++----- winixd/locale/en | 3 + winixd/locale/pl | 4 + winixd/models/itemcontent.cpp | 61 +++++++++++- winixd/models/itemcontent.h | 6 ++ 8 files changed, 355 insertions(+), 73 deletions(-) diff --git a/winixd/functions/functions.cpp b/winixd/functions/functions.cpp index 6eff8fe..483799f 100644 --- a/winixd/functions/functions.cpp +++ b/winixd/functions/functions.cpp @@ -614,7 +614,7 @@ void Functions::ReadItemUrlSubject(Item & item, Item::Type item_type) } -void Functions::ReadItemFilterHtml(Item & item) +void Functions::ReadItemFilterHtml(const std::wstring & html, std::wstring & html_filtered) { //html_filter.BreakWord(0); html_filter.WrapLine(0); @@ -624,65 +624,111 @@ void Functions::ReadItemFilterHtml(Item & item) html_filter.ClearOrphans(); // SetNoFilterTag doesn't have to be called (default empty tag) - html_filter.filter(cur->request->PostVar(L"itemcontent"), item.item_content.content_raw); + //html_filter.filter(cur->request->PostVar(L"itemcontent"), item.item_content.content_raw); + html_filter.filter(html, html_filtered); } -void Functions::ReadItemContent(Item & item, const std::wstring & content_type) +void Functions::ReadItemContent(Item & item) { + bool filter_html = config->editors_html_safe_mode; bool is_root = cur->session->puser && cur->session->puser->is_super_user; - bool filter_html = (content_type == L"2") && config->editors_html_safe_mode; - if( filter_html && is_root && config->editors_html_safe_mode_skip_root ) + if( is_root && config->editors_html_safe_mode_skip_root ) filter_html = false; - if( filter_html ) - ReadItemFilterHtml(item); - else - cur->request->PostVar(L"itemcontent", item.item_content.content_raw); + std::wstring * content = cur->request->PostVarp(L"itemcontent"); + std::wstring * content_parsed = cur->request->PostVarp(L"itemcontent_parsed"); + + if( item.item_content.content_raw_type != ItemContent::ct_markdown ) + { + item.item_content.content_parsed.clear(); + } + + if( content ) + { + if( item.item_content.content_raw_type == ItemContent::ct_html ) + { + if( filter_html ) + { + ReadItemFilterHtml(*content, item.item_content.content_raw); + } + else + { + item.item_content.content_raw = *content; + } + } + else + { + item.item_content.content_raw = *content; + } + } + + if( content_parsed ) + { + if( item.item_content.content_raw_type == ItemContent::ct_markdown ) + { + if( filter_html ) + { + ReadItemFilterHtml(*content_parsed, item.item_content.content_parsed); + } + else + { + item.item_content.content_parsed = *content_parsed; + } + + item.item_content.content_parsed_type = ItemContent::ct_html; + } + } } -void Functions::ReadItemContentWithType(Item & item) +void Functions::ReadItemContentType(Item & item) { item.item_content.content_raw_type = ItemContent::ct_formatted_text; // default is formatted text - cur->request->PostVar(L"contenttype", temp); + item.item_content.content_parsed_type = ItemContent::ct_formatted_text; + std::wstring * content_type_str = cur->request->PostVarp(L"contenttype"); - ReadItemContent(item, temp); + if( content_type_str ) + item.item_content.content_raw_type = ItemContent::get_content_type_from_str(*content_type_str); - - // ct_text and ct_formatted_text can use everyone - - if( temp == L"0" ) - item.item_content.content_raw_type = ItemContent::ct_text; - else - if( temp == L"1" ) - item.item_content.content_raw_type = ItemContent::ct_formatted_text; - - - // those below need special privileges - - if( !cur->session->puser ) - return; - - long user_id = cur->session->puser->id; - - if( temp == L"2" ) + if( item.item_content.content_raw_type != ItemContent::ct_text && + item.item_content.content_raw_type != ItemContent::ct_formatted_text ) { - if( system->CanUseHtml(user_id) ) - item.item_content.content_raw_type = ItemContent::ct_html; - } - else - if( temp == L"3" ) - { - if( system->CanUseBBCode(user_id) ) - item.item_content.content_raw_type = ItemContent::ct_bbcode; - } - else - if( temp == L"4" ) - { - if( system->CanUseOther(user_id) ) - item.item_content.content_raw_type = ItemContent::ct_other; + // ct_text and ct_formatted_text can use everyone + bool has_privileges = false; + + if( cur->session->puser ) + { + long user_id = cur->session->puser->id; + + switch(item.item_content.content_raw_type) + { + case ItemContent::ct_html: + has_privileges = system->CanUseHtml(user_id); + break; + + case ItemContent::ct_bbcode: + has_privileges = system->CanUseBBCode(user_id); // may test 'allow html' in such a case? + break; + + case ItemContent::ct_other: + has_privileges = system->CanUseOther(user_id); + break; + + case ItemContent::ct_markdown: + has_privileges = system->CanUseHtml(user_id); + break; + + default: + break; + } + } + + if( !has_privileges ) + { + item.item_content.content_raw_type = ItemContent::ct_formatted_text; + } } } @@ -704,7 +750,10 @@ void Functions::ReadItem(Item & item, Item::Type item_type) ReadItemUrlSubject(item, item_type); if( item_type == Item::file ) - ReadItemContentWithType(item); + { + ReadItemContentType(item); + ReadItemContent(item); + } } diff --git a/winixd/functions/functions.h b/winixd/functions/functions.h index 2ab74ad..7cfd924 100644 --- a/winixd/functions/functions.h +++ b/winixd/functions/functions.h @@ -180,9 +180,9 @@ public: bool CheckAbuse(SLog * slog = nullptr); // !! dac lepsze nazwy - void ReadItemFilterHtml(Item & item); - void ReadItemContent(Item & item, const std::wstring & content_type); - void ReadItemContentWithType(Item & item); + void ReadItemFilterHtml(const std::wstring & html, std::wstring & html_filtered); + void ReadItemContent(Item & item); + void ReadItemContentType(Item & item); // if item.url is not empty and there is not a post variable "url" // then the item.url will not be changed @@ -205,7 +205,6 @@ private: Templates * templates; SessionManager * session_manager; - std::wstring temp; pt::HTMLParser html_filter; std::wstring link_to_temp; diff --git a/winixd/html/fun_emacs_post.html b/winixd/html/fun_emacs_post.html index 9f598e3..6711a61 100644 --- a/winixd/html/fun_emacs_post.html +++ b/winixd/html/fun_emacs_post.html @@ -1,6 +1,7 @@
+[if false] [if winix_function_is "upload"] [else] @@ -8,10 +9,56 @@ [if mount_type_is "thread"][end] [if mount_type_is "ticket"][end] [end] +[end]
[# CodeMirror doesn't work correctly inside fieldset tag -- horizontal scroll is broken] - + + +
+ + + +
+
+ +
+ + +[if false] + + +
    + +
  • + +
  • + +
  • +
    +
    +
  • + +
+[end] + + +
@@ -22,9 +69,16 @@ {form_emacs_content_type_text} {form_emacs_content_type_formatted_text} [if user_can_use_html]{form_emacs_content_type_html}[end] - [if user_can_use_bbcode]{form_emacs_content_type_bbcode}[end] + [if user_can_use_html]{form_emacs_content_type_markdown}[end] [if user_can_use_other]{form_emacs_content_type_other}[end] + + +[if false] + [if user_can_use_bbcode]{form_emacs_content_type_bbcode}[end] +[end] + + diff --git a/winixd/html/index_head_adder.html b/winixd/html/index_head_adder.html index 24042f1..9a87b7a 100644 --- a/winixd/html/index_head_adder.html +++ b/winixd/html/index_head_adder.html @@ -69,28 +69,36 @@ [if or [winix_function_is "emacs"] [winix_function_is "env"] [winix_function_is "meta"]] - - + + - - - - + + + + + - + - - + + [if false] - - + + [end] - - + + + + + + + [# markdown to html converter] + [# https://github.com/showdownjs/showdown ] + + -