Browse Source

Replace EasyMDE with GitHub Markdown Toolbar

Peter Justin 3 years ago
parent
commit
2c935f4695

+ 52 - 0
flaskbb/templates/_macros/form.html

@@ -92,6 +92,54 @@
 {%- endmacro -%}
 {%- endmacro -%}
 
 
 
 
+{%- macro render_editor_field(field, div_class='') -%}
+{% if div_class %}
+<div class="{{ div_class }}">
+{% endif %}
+
+    {% set placeholder = kwargs['placeholder']|length or field.label.text %}
+    {% set css_error = ' is-invalid' if field.errors else '' %}
+    {% set css_class = kwargs['class'] if kwargs['class'] else 'flaskbb-editor form-control border-0 rounded-0' %}
+    {% set css_class = css_class + css_error if css_error else css_class %}
+    <div class="card">
+        <div class="card-header">
+            <div class="btn-toolbar">
+                <markdown-toolbar for="{{ field.id }}">
+                    <div class="btn-group btn-group-sm me-2">
+                        <md-header class="btn btn-white" data-tooltip="tooltip" title="Heading"><span class="fas fa-heading"></span></md-header>
+                        <md-bold class="btn btn-white" data-tooltip="tooltip" title="Bold"><span class="fas fa-bold"></span></md-bold>
+                        <md-italic class="btn btn-white" data-tooltip="tooltip" title="Italic"><span class="fas fa-italic"></span></md-italic>
+                        <md-strikethrough class="btn btn-white" data-tooltip="tooltip" title="Strikethrough"><span class="fas fa-strikethrough"></span></md-strikethrough>
+                    </div>
+
+                    <div class="btn-group btn-group-sm me-2">
+                        <md-quote class="btn btn-white" data-tooltip="tooltip" title="Quote"><span class="fas fa-quote-left"></span></md-quote>
+                        <md-code class="btn btn-white" data-tooltip="tooltip" title="Code"><span class="fas fa-code"></span></md-code>
+                        <md-link class="btn btn-white" data-tooltip="tooltip" title="Insert Link"><span class="fas fa-link"></span></md-link>
+                        <md-image class="btn btn-white" data-tooltip="tooltip" title="Insert Image"><span class="fas fa-image"></span></md-image>
+                    </div>
+
+                    <div class="btn-group btn-group-sm me-2">
+                        <md-unordered-list class="btn btn-white" data-tooltip="tooltip" title="Unordered List"><span class="fas fa-list-ul"></span></md-unordered-list>
+                        <md-ordered-list class="btn btn-white" data-tooltip="tooltip" title="Ordered List"><span class="fas fa-list-ol"></span></md-ordered-list>
+                        <md-mention class="btn btn-white" data-tooltip="tooltip" title="Mention"><span class="fas fa-at"></span></md-mention>
+                    </div>
+                </markdown-toolbar>
+
+                <button class="btn btn-sm btn-primary me-2" for="{{ field.id }}">Preview</button>
+                <button class="btn btn-sm btn-success"><span class="fas fa-question"></span></button>
+            </div>
+        </div>
+        {{ field(class=css_class, placeholder=placeholder, **kwargs) }}
+    </div>
+    {{ field_description(field) }}
+    {{ field_errors(field) }}
+{% if div_class %}
+</div>
+{% endif %}
+{%- endmacro -%}
+
+
 {%- macro render_submit_field(field, div_class='') -%}
 {%- macro render_submit_field(field, div_class='') -%}
 {% if div_class %}
 {% if div_class %}
 <div class="{{ div_class }}">
 <div class="{{ div_class }}">
@@ -119,6 +167,8 @@
         {{ render_select_field(field, **kwargs) }}
         {{ render_select_field(field, **kwargs) }}
     {% elif field.type == "SubmitField" %}
     {% elif field.type == "SubmitField" %}
         {{ render_submit_field(field, **kwargs) }}
         {{ render_submit_field(field, **kwargs) }}
+    {% elif field.type == "TextAreaField" %}
+        {{ render_editor_field(field, **kwargs) }}
     {% else %}
     {% else %}
         {{ render_input_field(field, **kwargs) }}
         {{ render_input_field(field, **kwargs) }}
     {% endif %}
     {% endif %}
@@ -141,6 +191,8 @@
         {{ render_select_field(field, **kwargs) }}
         {{ render_select_field(field, **kwargs) }}
     {% elif field.type == "SubmitField" %}
     {% elif field.type == "SubmitField" %}
         {{ render_submit_field(field, **kwargs) }}
         {{ render_submit_field(field, **kwargs) }}
+    {% elif field.type == "TextAreaField" %}
+        {{ render_editor_field(field, **kwargs) }}
     {% else %}
     {% else %}
         {{ render_input_field(field, **kwargs) }}
         {{ render_input_field(field, **kwargs) }}
     {% endif %}
     {% endif %}

+ 2 - 2
flaskbb/templates/forum/new_post.html

@@ -10,7 +10,7 @@
 {% extends theme("layout.html") %}
 {% extends theme("layout.html") %}
 
 
 {% block content %}
 {% block content %}
-{% from theme("_macros/form.html") import render_field, render_input_field, render_submit_field %}
+{% from theme("_macros/form.html") import render_field, render_editor_field, render_submit_field %}
 
 
 <div class="page-view">
 <div class="page-view">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
@@ -34,7 +34,7 @@
                 <div class="row p-3">
                 <div class="row p-3">
                     {{ run_hook("flaskbb_tpl_form_new_post_before", form=form) }}
                     {{ run_hook("flaskbb_tpl_form_new_post_before", form=form) }}
 
 
-                    {{ render_input_field(form.content, class='flaskbb-editor', style="display: none", required="required") }}
+                    {{ render_editor_field(form.content, rows=6) }}
                     {{ render_field(form.track_topic) }}
                     {{ render_field(form.track_topic) }}
 
 
                     {{ run_hook("flaskbb_tpl_form_new_post_after", form=form) }}
                     {{ run_hook("flaskbb_tpl_form_new_post_after", form=form) }}

+ 2 - 2
flaskbb/templates/forum/new_topic.html

@@ -10,7 +10,7 @@
 {% extends theme("layout.html") %}
 {% extends theme("layout.html") %}
 
 
 {% block content %}
 {% block content %}
-{% from theme("_macros/form.html") import render_field, render_input_field, render_submit_field %}
+{% from theme("_macros/form.html") import render_field, render_submit_field %}
 
 
 <div class="page-view">
 <div class="page-view">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
@@ -35,7 +35,7 @@
 
 
                     {{ run_hook("flaskbb_tpl_form_new_topic_before", form=form) }}
                     {{ run_hook("flaskbb_tpl_form_new_topic_before", form=form) }}
 
 
-                    {{ render_input_field(form.content, class='flaskbb-editor', style="display: none", required="required") }}
+                    {{ render_field(form.content, rows=6) }}
                     {{ render_field(form.track_topic) }}
                     {{ render_field(form.track_topic) }}
 
 
                     {{ run_hook("flaskbb_tpl_form_new_topic_after", form=form) }}
                     {{ run_hook("flaskbb_tpl_form_new_topic_after", form=form) }}

+ 2 - 2
flaskbb/templates/forum/topic.html

@@ -4,7 +4,7 @@
 
 
 {% block content %}
 {% block content %}
 {% from theme('_macros/pagination.html') import render_pagination, generate_obj_id, generate_post_url %}
 {% from theme('_macros/pagination.html') import render_pagination, generate_obj_id, generate_post_url %}
-{% from theme('_macros/form.html') import render_input_field, render_submit_field %}
+{% from theme('_macros/form.html') import render_input_field, render_editor_field, render_submit_field %}
 
 
 <div class="topic-view">
 <div class="topic-view">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
     <ol class="breadcrumb flaskbb-breadcrumb bg-light">
@@ -233,7 +233,7 @@
         {{ form.hidden_tag() }}
         {{ form.hidden_tag() }}
         <div class="row">
         <div class="row">
             <div class="offset-md-2 offset-sm-3 col-md-10 col-sm-9 col-12">
             <div class="offset-md-2 offset-sm-3 col-md-10 col-sm-9 col-12">
-                {{ render_input_field(form.content, class='flaskbb-editor', style="display: none", required="required") }}
+                {{ render_editor_field(form.content, rows=6) }}
                 {{ render_submit_field(form.submit, div_class="mt-2 float-end") }}
                 {{ render_submit_field(form.submit, div_class="mt-2 float-end") }}
             </div>
             </div>
         </div>
         </div>

+ 0 - 3
flaskbb/templates/layout.html

@@ -22,9 +22,6 @@
     {% block stylesheets %}
     {% block stylesheets %}
     <!-- style -->
     <!-- style -->
     <link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
     <link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
-
-    <!-- emoji -->
-    <script src="https://twemoji.maxcdn.com/2/twemoji.min.js?2.5"></script>
     {% endblock %}
     {% endblock %}
 
 
     {# for extra stylesheets. e.q. a template has to add something #}
     {# for extra stylesheets. e.q. a template has to add something #}

+ 1 - 1
flaskbb/templates/management/category_form.html

@@ -34,7 +34,7 @@
             <form class="row p-2" role="form" method="post">
             <form class="row p-2" role="form" method="post">
                 {{ form.hidden_tag() }}
                 {{ form.hidden_tag() }}
                 {{ render_field(form.title) }}
                 {{ render_field(form.title) }}
-                {{ render_field(form.description, div_class="col-sm-10", class="flaskbb-editor", style="display:none") }}
+                {{ render_field(form.description, div_class="col-sm-10 mb-3") }}
 
 
                 {{ render_field(form.position) }}
                 {{ render_field(form.position) }}
                 {{ render_field(form.submit) }}
                 {{ render_field(form.submit) }}

+ 1 - 1
flaskbb/templates/management/forum_form.html

@@ -35,7 +35,7 @@
             <form class="row p-2" role="form" method="post">
             <form class="row p-2" role="form" method="post">
                 {{ form.hidden_tag() }}
                 {{ form.hidden_tag() }}
                 {{ render_field(form.title) }}
                 {{ render_field(form.title) }}
-                {{ render_field(form.description, div_class="col-sm-10", class="flaskbb-editor", style="display:none") }}
+                {{ render_field(form.description, div_class="col-sm-10 mb-3") }}
                 {{ render_field(form.category) }}
                 {{ render_field(form.category) }}
                 {{ render_field(form.position) }}
                 {{ render_field(form.position) }}
                 {{ render_field(form.external) }}
                 {{ render_field(form.external) }}

+ 1 - 1
flaskbb/templates/management/group_form.html

@@ -35,7 +35,7 @@
                 {{ form.hidden_tag() }}
                 {{ form.hidden_tag() }}
                 {{ render_field(form.name) }}
                 {{ render_field(form.name) }}
 
 
-                {{ render_field(form.description, div_class="col-sm-10 mb-3", class="flaskbb-editor", style="display:none") }}
+                {{ render_field(form.description, div_class="col-sm-10 mb-3") }}
                 {{ render_field(form.admin) }}
                 {{ render_field(form.admin) }}
                 {{ render_field(form.super_mod) }}
                 {{ render_field(form.super_mod) }}
 
 

+ 2 - 2
flaskbb/templates/management/user_form.html

@@ -52,8 +52,8 @@
                 {{ horizontal_field(form.primary_group) }}
                 {{ horizontal_field(form.primary_group) }}
                 {{ horizontal_field(form.secondary_groups) }}
                 {{ horizontal_field(form.secondary_groups) }}
                 {{ horizontal_field(form.activated, div_class="offset-3 col-4") }}
                 {{ horizontal_field(form.activated, div_class="offset-3 col-4") }}
-                {{ horizontal_field(form.signature, div_class="col-sm-8", class="flaskbb-editor", style="display:none") }}
-                {{ horizontal_field(form.notes, div_class="col-sm-8", class="flaskbb-editor", style="display:none") }}
+                {{ horizontal_field(form.signature, rows=4, div_class="col-sm-8") }}
+                {{ horizontal_field(form.notes, rows=8, div_class="col-sm-8") }}
 
 
                 {{ run_hook('flaskbb_tpl_form_user_details_after', form=form) }}
                 {{ run_hook('flaskbb_tpl_form_user_details_after', form=form) }}
 
 

+ 2 - 2
flaskbb/templates/user/change_user_details.html

@@ -16,8 +16,8 @@
             {{ horizontal_field(form.location) }}
             {{ horizontal_field(form.location) }}
             {{ horizontal_field(form.website) }}
             {{ horizontal_field(form.website) }}
             {{ horizontal_field(form.avatar) }}
             {{ horizontal_field(form.avatar) }}
-            {{ horizontal_field(form.signature, div_class="col-sm-8", class="flaskbb-editor", style="display:none") }}
-            {{ horizontal_field(form.notes, div_class="col-sm-8", class="flaskbb-editor", style="display:none") }}
+            {{ horizontal_field(form.signature, rows=4, div_class="col-sm-8") }}
+            {{ horizontal_field(form.notes, rows=8, div_class="col-sm-8") }}
             {{ run_hook('flaskbb_tpl_form_user_details_after', form=form) }}
             {{ run_hook('flaskbb_tpl_form_user_details_after', form=form) }}
 
 
             {{ horizontal_field(form.submit, div_class="offset-3 col-4") }}
             {{ horizontal_field(form.submit, div_class="offset-3 col-4") }}

+ 5 - 1
flaskbb/themes/aurora/src/app.js

@@ -1,4 +1,5 @@
 import { Alert, Tooltip, Dropdown, Modal } from 'bootstrap';
 import { Alert, Tooltip, Dropdown, Modal } from 'bootstrap';
+import '@github/markdown-toolbar-element'
 
 
 import "./app/emoji.js";
 import "./app/emoji.js";
 import "./app/editor.js";
 import "./app/editor.js";
@@ -8,7 +9,10 @@ import "./app/confirm_modal.js";
 
 
 import "./scss/styles.scss";
 import "./scss/styles.scss";
 export { BulkActions, show_management_search, check_overview_status } from "./app/flaskbb.js";
 export { BulkActions, show_management_search, check_overview_status } from "./app/flaskbb.js";
-export { EDITORS } from './app/editor.js';
+
+var flaskbbAllowList = Tooltip.Default.allowList
+// allow <time> elements
+flaskbbAllowList.time = []
 
 
 var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"], [data-tooltip="tooltip"]'))
 var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"], [data-tooltip="tooltip"]'))
 var tooltipList = tooltips.map(function (el) {
 var tooltipList = tooltips.map(function (el) {

+ 21 - 44
flaskbb/themes/aurora/src/app/editor.js

@@ -1,36 +1,20 @@
-import EasyMDE from "easymde";
-import { CodeMirrorEditor } from "@textcomplete/codemirror";
-import EMOJIS from "./emoji";
+import { TextareaEditor } from "@textcomplete/textarea";
 import { Textcomplete } from "@textcomplete/core";
 import { Textcomplete } from "@textcomplete/core";
+import EMOJIS from "./emoji";
 import { parse_emoji } from "./flaskbb";
 import { parse_emoji } from "./flaskbb";
-export const EDITORS = new Map();
-
-
 
 
-function startsWith(term, limit = 10) {
-    const results = [];
-    // Whether previous key started with the term
-    let prevMatch = false
-    for (const [key, url] of EMOJIS) {
-        if (key.startsWith(term)) {
-            results.push([key, url])
-            if (results.length === limit) break
-            prevMatch = true
-        } else if (prevMatch) {
-            break
-        }
+const TEXTCOMPLETE_CONFIG = {
+    dropdown: {
+        maxCount: 5
     }
     }
-    return results
 }
 }
 
 
-
 const EMOJI_STRATEGY = {
 const EMOJI_STRATEGY = {
     id: "emoji",
     id: "emoji",
     match: /\B:([\-+\w]*)$/,
     match: /\B:([\-+\w]*)$/,
     search: (term, callback) => {
     search: (term, callback) => {
         callback(EMOJIS.map(value => {
         callback(EMOJIS.map(value => {
-            let x =  value[0].indexOf(term) !== -1 ? { character: value[1], name: value[0] } : null;
-            return x;
+            return value[0].indexOf(term) !== -1 ? { character: value[1], name: value[0] } : null;
         }))
         }))
     },
     },
     replace: (value) => {
     replace: (value) => {
@@ -54,21 +38,22 @@ const EMOJI_STRATEGY = {
     },
     },
 }
 }
 
 
+function configureAutocomplete(element) {
+    const editor = new TextareaEditor(element)
+    const textcomplete = new Textcomplete(editor, [EMOJI_STRATEGY], TEXTCOMPLETE_CONFIG)
+}
+
+
+function setupEditor() {
+    const editors = document.querySelectorAll(".flaskbb-editor");
+    for(const e of editors) {
+        configureAutocomplete(e);
+    }
+}
 
 
 
 
-function loadEditor(element) {
-    const easyMDE = new EasyMDE({
-        autoDownloadFontAwesome: false,
-        element: element,
-        autoRefresh: true,
-        forceSync: true,
-        spellChecker: false,
-        sideBySideFullscreen: false,
-        status: false,
-    });
-    const textCompleteEditor = new CodeMirrorEditor(easyMDE.codemirror);
-    const textcomp = new Textcomplete(textCompleteEditor, [EMOJI_STRATEGY], { dropdown: { maxCount: 5 }})
-    return easyMDE;
+function markdownPreview(element) {
+
 }
 }
 
 
 
 
@@ -93,12 +78,4 @@ for (const e of tareas) {
     autoresizeTextarea(e);
     autoresizeTextarea(e);
 }
 }
 
 
-const editorsSelector = document.querySelectorAll(".flaskbb-editor");
-editorsSelector.forEach((value, index) => {
-    if (typeof value.id != 'undefined') {
-        EDITORS.set(value.id, loadEditor(value));
-    } else {
-        EDITORS.set(`easyMDE-${index}`, loadEditor(value));
-    }
-
-});
+setupEditor()

+ 9 - 3
flaskbb/themes/aurora/src/app/flaskbb.js

@@ -4,7 +4,7 @@
  * License: BSD - See LICENSE for more details.
  * License: BSD - See LICENSE for more details.
  */
  */
 import { Modal } from "bootstrap";
 import { Modal } from "bootstrap";
-import { EDITORS } from "./editor.js";
+import twemoji from "twemoji";
 
 
 // get the csrf token from the header
 // get the csrf token from the header
 let csrf_token = document.querySelector("meta[name=csrf-token]").content;
 let csrf_token = document.querySelector("meta[name=csrf-token]").content;
@@ -196,11 +196,11 @@ document.addEventListener("DOMContentLoaded", function (event) {
                     : "";
                     : "";
             const url = `${urlprefix}post/${post_id}/raw`;
             const url = `${urlprefix}post/${post_id}/raw`;
 
 
-            const editor = EDITORS.get("content");
+            const editor = document.querySelector(".flaskbb-editor");
             fetch(url)
             fetch(url)
                 .then((response) => response.text())
                 .then((response) => response.text())
                 .then((data) => {
                 .then((data) => {
-                    editor.value(data);
+                    editor.value = data;
                     editor.selectionStart = editor.selectionEnd =
                     editor.selectionStart = editor.selectionEnd =
                         editor.value.length;
                         editor.value.length;
                     editor.scrollTop = editor.scrollHeight;
                     editor.scrollTop = editor.scrollHeight;
@@ -235,6 +235,12 @@ document.addEventListener("DOMContentLoaded", function (event) {
         if (el.dataset.what_to_display == "date-only") {
         if (el.dataset.what_to_display == "date-only") {
             options.hour = undefined;
             options.hour = undefined;
             options.minute = undefined;
             options.minute = undefined;
+        } else if (el.dataset.what_to_display== "time-only") {
+            options.year = undefined;
+            options.month = undefined;
+            options.day = undefined;
+            options.hour = "2-digit";
+            options.minute = "2-digit";
         } else {
         } else {
             options.hour = "2-digit";
             options.hour = "2-digit";
             options.minute = "2-digit";
             options.minute = "2-digit";

+ 32 - 25
flaskbb/themes/aurora/src/scss/_misc.scss

@@ -10,9 +10,10 @@ body {
 }
 }
 
 
 .emoji {
 .emoji {
-    vertical-align: middle;
-    width: 20px;
-    height: 20px;
+   height: 1em;
+   width: 1em;
+   margin: 0 .05em 0 .1em;
+   vertical-align: -0.1em;
 }
 }
 
 
 .flaskbb-footer {
 .flaskbb-footer {
@@ -32,10 +33,13 @@ body {
 .flaskbb-header {
 .flaskbb-header {
     color: #fff;
     color: #fff;
     text-align: left;
     text-align: left;
-    text-shadow: 0 1px 0 rgba(0,0,0,.1);
+    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
     background-color: $fbb-header-bg-primary;
     background-color: $fbb-header-bg-primary;
-    background-image: -webkit-linear-gradient(top, $fbb-header-bg-secondary 0%, $fbb-header-bg-primary 100%);
-    background-image: linear-gradient(to bottom, $fbb-header-bg-secondary 0%, $fbb-header-bg-primary 100%);
+    background-image: linear-gradient(
+        to bottom,
+        $fbb-header-bg-secondary 0%,
+        $fbb-header-bg-primary 100%
+    );
     background-repeat: repeat-x;
     background-repeat: repeat-x;
     filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$fbb-header-bg-secondary', endColorstr='$fbb-header-bg-primary', GradientType=0);
     filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$fbb-header-bg-secondary', endColorstr='$fbb-header-bg-primary', GradientType=0);
     border: 1px solid $border-color;
     border: 1px solid $border-color;
@@ -78,8 +82,6 @@ body {
             background-color: $fbb-navigation-hover-color;
             background-color: $fbb-navigation-hover-color;
         }
         }
     }
     }
-
-
 }
 }
 
 
 .flaskbb-breadcrumb {
 .flaskbb-breadcrumb {
@@ -94,7 +96,6 @@ p.flaskbb-stats {
     padding: 0;
     padding: 0;
 }
 }
 
 
-
 .controls-row {
 .controls-row {
     padding: 0.5em 0;
     padding: 0.5em 0;
     margin: 0;
     margin: 0;
@@ -114,7 +115,6 @@ p.flaskbb-stats {
     padding: 0;
     padding: 0;
 }
 }
 
 
-
 .cheatsheet {
 .cheatsheet {
     h2 {
     h2 {
         text-align: center;
         text-align: center;
@@ -144,22 +144,29 @@ p.flaskbb-stats {
     }
     }
 }
 }
 
 
-.EasyMDEContainer {
+.textcomplete-dropdown {
+    border: 1px solid #ddd;
+    background-color: white;
+    list-style: none;
+    padding: 0;
+    margin: 0;
+}
 
 
-    .CodeMirror {
-        border-color: $border-color !important;
-    }
+.textcomplete-dropdown li {
+    margin: 0;
+}
 
 
-    .editor-toolbar {
-        border-color: $border-color;
-        //background-color: #e8ecf1;
-    }
+.textcomplete-footer,
+.textcomplete-item {
+    border-top: 1px solid #ddd;
+}
 
 
-    .CodeMirror-focused {
-        //color: #212529;
-        //background-color: #f6f9fc;
-        border-color: #99bddb;
-        outline: 0;
-        box-shadow: 0 0 0 0.25rem rgba(51, 122, 183, 0.25);
-    }
+.textcomplete-item {
+    padding: 2px 5px;
+    cursor: pointer;
+}
+
+.textcomplete-item:hover,
+.textcomplete-item.active {
+    background-color: rgb(110, 183, 219);
 }
 }

+ 0 - 3
flaskbb/themes/aurora/src/scss/styles.scss

@@ -24,6 +24,3 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
 
 
 // Import pygments style
 // Import pygments style
 @import "pygments";
 @import "pygments";
-
-// Import the Easy Markdown Editor
-@import "easymde/dist/easymde.min";