From bcc7834650e5145066d6cdf0c27687998b5675c2 Mon Sep 17 00:00:00 2001
From: Nick O'Leary <nick.oleary@gmail.com>
Date: Fri, 5 Oct 2018 17:56:54 +0100
Subject: [PATCH] Add markdown formatting toolbar

---
 .../editor-client/src/js/ui/common/panels.js  | 40 ++++++---
 .../src/js/ui/editors/markdown.js             | 83 ++++++++++++++++++-
 2 files changed, 110 insertions(+), 13 deletions(-)

diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js
index 22e415099..3ccaa6b43 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js
@@ -32,8 +32,7 @@ RED.panels = (function() {
         var startPosition;
         var panelSizes = [];
         var modifiedSizes = false;
-        var panelRatio;
-
+        var panelRatio = 0.5;
         separator.draggable({
                 axis: vertical?"y":"x",
                 containment: container,
@@ -62,31 +61,47 @@ RED.panels = (function() {
                     if (options.resize) {
                         options.resize(newSizes[0],newSizes[1]);
                     }
-                    panelRatio = newSizes[0]/size;
+                    panelRatio = newSizes[0]/(size-8);
                 },
                 stop:function(event,ui) {
                     modifiedSizes = true;
                 }
         });
 
-        return {
-            resize: function(size) {
-                var panelSizes = [$(children[0]).height(),$(children[1]).height()];
+        var panel = {
+            ratio: function(ratio) {
+                panelRatio = ratio;
+                modifiedSizes = true;
+                if (ratio === 0 || ratio === 1) {
+                    separator.hide();
+                } else {
+                    separator.show();
+                }
                 if (vertical) {
+                    panel.resize(container.height());
+                } else {
+                    panel.resize(container.width());
+                }
+            },
+            resize: function(size) {
+                var panelSizes;
+                if (vertical) {
+                    panelSizes = [$(children[0]).height(),$(children[1]).height()];
                     container.height(size);
                 } else {
+                    panelSizes = [$(children[0]).width(),$(children[1]).width()];
                     container.width(size);
                 }
                 if (modifiedSizes) {
-                    var topPanelSize = panelRatio*size;
-                    var bottomPanelSize = size - topPanelSize - 48;
+                    var topPanelSize = panelRatio*(size-8);
+                    var bottomPanelSize = size - topPanelSize - 8;
                     panelSizes = [topPanelSize,bottomPanelSize];
                     if (vertical) {
-                        $(children[0]).height(panelSizes[0]);
-                        $(children[1]).height(panelSizes[1]);
+                        $(children[0]).outerHeight(panelSizes[0]);
+                        $(children[1]).outerHeight(panelSizes[1]);
                     } else {
-                        $(children[0]).width(panelSizes[0]);
-                        $(children[1]).width(panelSizes[1]);
+                        $(children[0]).outerWidth(panelSizes[0]);
+                        $(children[1]).outerWidth(panelSizes[1]);
                     }
                 }
                 if (options.resize) {
@@ -94,6 +109,7 @@ RED.panels = (function() {
                 }
             }
         }
+        return panel;
     }
 
     return {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js
index 161988150..3e34591c0 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js
@@ -19,7 +19,29 @@ RED.editor.types._markdown = (function() {
     var template = '<script type="text/x-red" data-template-name="_markdown">'+
     '<div id="node-input-markdown-panels">'+
     '<div id="node-input-markdown-panel-editor" class="red-ui-panel">'+
-        '<div class="node-text-editor" style="height: calc(100% - 20px)" id="node-input-markdown"></div>'+
+        '<div id="node-input-markdown-toolbar" style="margin-bottom: 5px">'+
+            '<span class="button-group">'+
+            '<button class="editor-button" data-style="h1" style="font-size:1.1em; font-weight: bold">h1</button>'+
+            '<button class="editor-button" data-style="h2" style="font-size:1.0em; font-weight: bold">h2</button>'+
+            '<button class="editor-button" data-style="h3" style="font-size:0.9em; font-weight: bold">h3</button>'+
+            '</span>'+
+            '<span class="button-group">'+
+                '<button class="editor-button" data-style="b"><i class="fa fa-bold"></i></button>'+
+                '<button class="editor-button" data-style="i"><i class="fa fa-italic"></i></button>'+
+                '<button class="editor-button" data-style="code"><i class="fa fa-code"></i></button>'+
+            '</span>'+
+            '<span class="button-group">'+
+                '<button class="editor-button" data-style="ol"><i class="fa fa-list-ol"></i></button>'+
+                '<button class="editor-button" data-style="ul"><i class="fa fa-list-ul"></i></button>'+
+                '<button class="editor-button" data-style="bq"><i class="fa fa-quote-left"></i></button>'+
+                '<button class="editor-button" data-style="hr"><i class="fa fa-minus"></i></button>'+
+                '<button class="editor-button" data-style="link"><i class="fa fa-link"></i></button>'+
+            '</span>'+
+            '<span class="button-group">'+
+                '<button id="node-btn-markdown-preview" class="editor-button toggle single"><i class="fa fa-eye"></i></button>'+
+            '</span>'+
+        '</div>'+
+        '<div class="node-text-editor" style="height: calc(100% - 50px)" id="node-input-markdown"></div>'+
     '</div>'+
     '<div class="red-ui-panel">'+
         '<div id="node-input-markdown-panel-preview" style="padding: 20px;" class="node-help"></div>'+
@@ -29,6 +51,20 @@ RED.editor.types._markdown = (function() {
 
     var panels;
 
+    var styleActions = {
+        'h1': { newline: true, before:"# ", tooltip:"Heading 1"},
+        'h2': { newline: true, before:"## ", tooltip:"Heading 2"},
+        'h3': { newline: true, before:"### ", tooltip:"Heading 3"},
+        'b': { before:"**", after: "**", tooltip: "Bold" },
+        'i': { before:"_", after: "_", tooltip: "Italic" },
+        'code': { before:"`", after: "`", tooltip: "Code" },
+        'ol': { before:" * ", newline: true, tooltip: "Ordered list" },
+        'ul': { before:" - ", newline: true, tooltip: "Unordered list"  },
+        'bq': { before:"> ", newline: true, tooltip: "Quote"  },
+        'link': { before:"[", after: "]()", tooltip: "Link"},
+        'hr': { before:"\n---\n\n", tooltip: "Horizontal rule"  }
+    }
+
     return {
         init: function() {
             $(template).appendTo(document.body);
@@ -100,6 +136,51 @@ RED.editor.types._markdown = (function() {
                             expressionEditor.resize();
                         }
                     });
+                    panels.ratio(1);
+
+                    $("#node-btn-markdown-preview").click(function(e) {
+                        e.preventDefault();
+                        if ($(this).hasClass("selected")) {
+                            $(this).removeClass("selected");
+                            panels.ratio(1);
+                        } else {
+                            $(this).addClass("selected");
+                            panels.ratio(0.5);
+                        }
+                    });
+
+                    $('#node-input-markdown-toolbar').find('button[data-style]').each(function(el) {
+                        var style = styleActions[$(this).data('style')];
+                        $(this).click(function(e) {
+                            e.preventDefault();
+                            var current = expressionEditor.getSelectedText();
+                            var range = expressionEditor.selection.getRange();
+                            if (style.newline) {
+                                var offset = 0;
+                                var beforeOffset = ((style.before||"").match(/\n/g)||[]).length;
+                                var afterOffset = ((style.after||"").match(/\n/g)||[]).length;
+                                for (var i = range.start.row; i<= range.end.row+offset; i++) {
+                                    if (style.before) {
+                                        expressionEditor.session.insert({row:i, column:0},style.before);
+                                        offset += beforeOffset;
+                                        i += beforeOffset;
+                                    }
+                                    if (style.after) {
+                                        expressionEditor.session.insert({row:i, column:Infinity},style.after);
+                                        offset += afterOffset;
+                                        i += afterOffset;
+                                    }
+                                }
+                            } else {
+                                expressionEditor.session.replace(expressionEditor.selection.getRange(), (style.before||"")+current+(style.after||""));
+                            }
+                            expressionEditor.focus();
+                        });
+                        if (style.tooltip) {
+                            RED.popover.tooltip($(this),style.tooltip);
+                        }
+
+                    })
 
                     if (options.cursor) {
                         expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);