/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ (function() { /** * Converts dropped image file to date URL */ function file2base64Image(file, cb) { var reader = new FileReader(); reader.onload = (function (fd) { return function (e) { cb(e.target.result); }; })(file); reader.readAsDataURL(file); } var initialized = false; var currentEditor = null; /** * Initialize handler for image file drag events */ function initImageDrag(elem, editor) { $(elem).on("dragenter", function (ev) { ev.preventDefault(); $("#red-ui-image-drop-target").css({display:'table'}).focus(); currentEditor = editor; }); if (!initialized) { initialized = true; $("#red-ui-image-drop-target").on("dragover", function (ev) { ev.preventDefault(); }).on("dragleave", function (ev) { $("#red-ui-image-drop-target").hide(); }).on("drop", function (ev) { ev.preventDefault(); if ($.inArray("Files",ev.originalEvent.dataTransfer.types) != -1) { var files = ev.originalEvent.dataTransfer.files; if (files.length === 1) { var file = files[0]; var name = file.name.toLowerCase(); if (name.match(/\.(apng|avif|gif|jpeg|png|svg|webp)$/)) { file2base64Image(file, function (image) { var session = currentEditor.getSession(); var img = `\n`; var pos = session.getCursorPosition(); session.insert(pos, img); $("#red-ui-image-drop-target").hide(); }); return; } } } $("#red-ui-image-drop-target").hide(); }); } } var toolbarTemplate = '
'+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ '
'; var template = ''; var panels; var definition = { show: function(options) { var value = options.value; var onCancel = options.cancel; var onComplete = options.complete; var type = "_markdown" if ($("script[data-template-name='"+type+"']").length === 0) { $(template).appendTo("#red-ui-editor-node-configs"); } RED.view.state(RED.state.EDITING); var expressionEditor; var trayOptions = { title: options.title, focusElement: options.focusElement, width: options.width||Infinity, buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { if (onCancel) { onCancel(); } RED.tray.close(); } }, { id: "node-dialog-ok", text: RED._("common.label.done"), class: "primary", click: function() { expressionEditor.saveView(); if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(), expressionEditor); } RED.tray.close(); } } ], resize: function(dimensions) { var width = $("#dialog-form").width(); if (panels) { panels.resize(width); } }, open: function(tray) { var trayBody = tray.find('.red-ui-tray-body'); trayBody.addClass("red-ui-editor-type-markdown-editor") var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); expressionEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-markdown', value: value, stateId: options.stateId, focus: true, mode:"ace/mode/markdown", expandable: false }); var changeTimer; expressionEditor.getSession().on("change", function() { clearTimeout(changeTimer); changeTimer = setTimeout(function() { var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop(); $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); $(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop); RED.editor.mermaid.render() },200); }) if (options.header) { options.header.appendTo(tray.find('#red-ui-editor-type-markdown-title')); } if (value) { $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); RED.editor.mermaid.render() } panels = RED.panels.create({ id:"red-ui-editor-type-markdown-panels", dir: "horizontal", resize: function(p1Width,p2Width) { expressionEditor.resize(); } }); panels.ratio(1); $(''+ ''+ '').appendTo(expressionEditor.toolbar); $("#node-btn-markdown-preview").on("click", function(e) { e.preventDefault(); if ($(this).hasClass("selected")) { $(this).removeClass("selected"); panels.ratio(1); } else { $(this).addClass("selected"); panels.ratio(0.5); } }); RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview")); if(!expressionEditor._initState) { if (options.cursor) { expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); } else { expressionEditor.gotoLine(0, 0, false); } } dialogForm.i18n(); }, close: function() { if (options.onclose) { options.onclose(); } expressionEditor.destroy(); }, show: function() {} } RED.tray.show(trayOptions); }, buildToolbar: function(container, editor) { var styleActions = { 'h1': { newline: true, before:"# ", tooltip:RED._("markdownEditor.heading1")}, 'h2': { newline: true, before:"## ", tooltip:RED._("markdownEditor.heading2")}, 'h3': { newline: true, before:"### ", tooltip:RED._("markdownEditor.heading3")}, 'b': { before:"**", after: "**", tooltip: RED._("markdownEditor.bold")}, 'i': { before:"_", after: "_", tooltip: RED._("markdownEditor.italic")}, 'code': { before:"`", after: "`", tooltip: RED._("markdownEditor.code")}, 'ol': { before:" 1. ", newline: true, tooltip: RED._("markdownEditor.ordered-list")}, 'ul': { before:" - ", newline: true, tooltip: RED._("markdownEditor.unordered-list")}, 'bq': { before:"> ", newline: true, tooltip: RED._("markdownEditor.quote")}, 'link': { before:"[", after: "]()", tooltip: RED._("markdownEditor.link")}, 'hr': { before:"\n---\n\n", tooltip: RED._("markdownEditor.horizontal-rule")} } var toolbar = $(toolbarTemplate).appendTo(container); toolbar.find('button[data-style]').each(function(el) { var style = styleActions[$(this).data('style')]; $(this).on("click", function(e) { e.preventDefault(); var current = editor.getSelectedText(); var range = editor.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) { editor.session.insert({row:i, column:0},style.before); offset += beforeOffset; i += beforeOffset; } if (style.after) { editor.session.insert({row:i, column:Infinity},style.after); offset += afterOffset; i += afterOffset; } } } else { editor.session.replace(editor.selection.getRange(), (style.before||"")+current+(style.after||"")); if (current === "") { editor.gotoLine(range.start.row+1,range.start.column+(style.before||"").length,false); } } editor.focus(); }); if (style.tooltip) { RED.popover.tooltip($(this),style.tooltip); } }) return toolbar; }, postInit: function (editor, options) { var elem = $("#"+options.id); initImageDrag(elem, editor); } } RED.editor.registerTypeEditor("_markdown", definition); })();