mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
add support for mermaid diagram to markdown editor
This commit is contained in:
parent
928131cf08
commit
038f75e48f
@ -151,6 +151,7 @@ module.exports = function(grunt) {
|
|||||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
|
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
|
||||||
|
"packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
|
||||||
@ -225,7 +226,7 @@ module.exports = function(grunt) {
|
|||||||
"node_modules/jsonata/jsonata-es5.min.js",
|
"node_modules/jsonata/jsonata-es5.min.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
|
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
|
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js",
|
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js"
|
||||||
],
|
],
|
||||||
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
|
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
|
||||||
// // TODO: resolve relative resource paths in
|
// // TODO: resolve relative resource paths in
|
||||||
@ -234,6 +235,9 @@ module.exports = function(grunt) {
|
|||||||
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
|
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
|
||||||
"node_modules/jsonata/jsonata-es5.min.js",
|
"node_modules/jsonata/jsonata-es5.min.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
|
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
|
||||||
|
],
|
||||||
|
"packages/node_modules/@node-red/editor-client/public/vendor/mermaid/mermaid.min.js": [
|
||||||
|
"node_modules/mermaid/dist/mermaid.min.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@
|
|||||||
"jquery-i18next": "1.2.1",
|
"jquery-i18next": "1.2.1",
|
||||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||||
"marked": "4.2.3",
|
"marked": "4.2.3",
|
||||||
|
"mermaid": "^9.3.0",
|
||||||
"minami": "1.2.3",
|
"minami": "1.2.3",
|
||||||
"mocha": "9.2.2",
|
"mocha": "9.2.2",
|
||||||
"node-red-node-test-helper": "^0.3.0",
|
"node-red-node-test-helper": "^0.3.0",
|
||||||
|
33
packages/node_modules/@node-red/editor-api/lib/editor/editor-libs.js
vendored
Normal file
33
packages/node_modules/@node-red/editor-api/lib/editor/editor-libs.js
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Dynamic loading support for editor libraries
|
||||||
|
|
||||||
|
var apiUtils = require("../util");
|
||||||
|
var fs = require("fs");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
var lib2path = {
|
||||||
|
"mermaid": "../../../editor-client/public/vendor/mermaid/mermaid.min.js",
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(_settings, _runtimeAPI) {
|
||||||
|
settings = _settings;
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function(req,res) {
|
||||||
|
var name = req.params.name;
|
||||||
|
|
||||||
|
if (name in lib2path) {
|
||||||
|
try {
|
||||||
|
var lib = path.join(__dirname, lib2path[name]);
|
||||||
|
var code = fs.readFileSync(lib);
|
||||||
|
res.send(code);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
res.status(500).json({code: "runtime_error", message: e.toString()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.status(400).json({code: "invalid_request", message: `no library: ${name}`});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
@ -116,6 +116,11 @@ module.exports = {
|
|||||||
// SSH keys
|
// SSH keys
|
||||||
editorApp.use("/settings/user/keys",needsPermission("settings.write"),info.sshkeys());
|
editorApp.use("/settings/user/keys",needsPermission("settings.write"),info.sshkeys());
|
||||||
|
|
||||||
|
// Editor Libraries
|
||||||
|
var editorLibs = require("./editor-libs");
|
||||||
|
editorLibs.init(settings, runtimeAPI);
|
||||||
|
editorApp.get("/editor-libs/:name", needsPermission("editor-libs.read"), editorLibs.get, apiUtil.errorHandler);
|
||||||
|
|
||||||
return editorApp;
|
return editorApp;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -987,7 +987,10 @@
|
|||||||
"quote": "Quote",
|
"quote": "Quote",
|
||||||
"link": "Link",
|
"link": "Link",
|
||||||
"horizontal-rule": "Horizontal rule",
|
"horizontal-rule": "Horizontal rule",
|
||||||
"toggle-preview": "Toggle preview"
|
"toggle-preview": "Toggle preview",
|
||||||
|
"mermaid": {
|
||||||
|
"summary": "Mermaid Diagram"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"bufferEditor": {
|
"bufferEditor": {
|
||||||
"title": "Buffer editor",
|
"title": "Buffer editor",
|
||||||
|
@ -987,7 +987,10 @@
|
|||||||
"quote": "引用",
|
"quote": "引用",
|
||||||
"link": "リンク",
|
"link": "リンク",
|
||||||
"horizontal-rule": "区切り線",
|
"horizontal-rule": "区切り線",
|
||||||
"toggle-preview": "プレビュー表示切替え"
|
"toggle-preview": "プレビュー表示切替え",
|
||||||
|
"mermaid": {
|
||||||
|
"summary": "Mermaid図"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"bufferEditor": {
|
"bufferEditor": {
|
||||||
"title": "バッファエディタ",
|
"title": "バッファエディタ",
|
||||||
|
@ -114,6 +114,7 @@
|
|||||||
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
|
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").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||||
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
||||||
|
mermaid.init();
|
||||||
},200);
|
},200);
|
||||||
})
|
})
|
||||||
if (options.header) {
|
if (options.header) {
|
||||||
@ -122,6 +123,7 @@
|
|||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||||
|
mermaid.init();
|
||||||
}
|
}
|
||||||
panels = RED.panels.create({
|
panels = RED.panels.create({
|
||||||
id:"red-ui-editor-type-markdown-panels",
|
id:"red-ui-editor-type-markdown-panels",
|
||||||
|
46
packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js
vendored
Normal file
46
packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Mermaid diagram stub library for on-demand dynamic loading
|
||||||
|
// Will be overwritten after script loading by $.getScript
|
||||||
|
var mermaid = (function () {
|
||||||
|
var enabled /* = undefined */;
|
||||||
|
|
||||||
|
var initializing = false;
|
||||||
|
var initCalled = false;
|
||||||
|
|
||||||
|
function initialize(opt) {
|
||||||
|
if (enabled === undefined) {
|
||||||
|
if (RED.settings.markdownEditor &&
|
||||||
|
RED.settings.markdownEditor.mermaid) {
|
||||||
|
enabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (enabled) {
|
||||||
|
initializing = true;
|
||||||
|
$.getScript("/editor-libs/mermaid",
|
||||||
|
function (data, stat, jqxhr) {
|
||||||
|
$(".mermaid").show();
|
||||||
|
// invoke loaded mermaid API
|
||||||
|
initializing = false;
|
||||||
|
mermaid.initialize(opt);
|
||||||
|
if (initCalled) {
|
||||||
|
mermaid.init();
|
||||||
|
initCalled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (initializing) {
|
||||||
|
$(".mermaid").hide();
|
||||||
|
initCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
initialize: initialize,
|
||||||
|
init: init,
|
||||||
|
};
|
||||||
|
})();
|
@ -463,7 +463,8 @@ RED.sidebar.info = (function() {
|
|||||||
el = el.next();
|
el = el.next();
|
||||||
}
|
}
|
||||||
$(this).toggleClass('expanded',!isExpanded);
|
$(this).toggleClass('expanded',!isExpanded);
|
||||||
})
|
});
|
||||||
|
mermaid.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
var tips = (function() {
|
var tips = (function() {
|
||||||
|
@ -96,6 +96,37 @@ RED.utils = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mermaidIsInitialized = false;
|
||||||
|
var mermaidIsEnabled /* = undefined */;
|
||||||
|
|
||||||
|
renderer.code = function (code, lang) {
|
||||||
|
if(lang === "mermaid") {
|
||||||
|
// mermaid diagram rendering
|
||||||
|
if (mermaidIsEnabled === undefined) {
|
||||||
|
if (RED.settings.markdownEditor &&
|
||||||
|
RED.settings.markdownEditor.mermaid) {
|
||||||
|
mermaidIsEnabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mermaidIsEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mermaidIsEnabled) {
|
||||||
|
if (!mermaidIsInitialized) {
|
||||||
|
mermaidIsInitialized = true;
|
||||||
|
mermaid.initialize({startOnLoad:false});
|
||||||
|
}
|
||||||
|
return `<pre class='mermaid'>${code}</pre>`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return `<details><summary>${RED._("markdownEditor.mermaid.summary")}</summary><pre><code>${code}</code></pre></details>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "<pre><code>" +code +"</code></pre>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window._marked.setOptions({
|
window._marked.setOptions({
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
|
@ -89,11 +89,17 @@ var api = module.exports = {
|
|||||||
|
|
||||||
if (!runtime.settings.disableEditor) {
|
if (!runtime.settings.disableEditor) {
|
||||||
safeSettings.context = runtime.nodes.listContextStores();
|
safeSettings.context = runtime.nodes.listContextStores();
|
||||||
if (runtime.settings.editorTheme && runtime.settings.editorTheme.codeEditor) {
|
if (runtime.settings.editorTheme) {
|
||||||
|
if (runtime.settings.editorTheme.codeEditor) {
|
||||||
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
||||||
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
||||||
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
||||||
}
|
}
|
||||||
|
if (runtime.settings.editorTheme.markdownEditor) {
|
||||||
|
safeSettings.markdownEditor = runtime.settings.editorTheme.markdownEditor || {};
|
||||||
|
safeSettings.markdownEditor.mermaid = safeSettings.markdownEditor.mermaid || { enabled: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
safeSettings.libraries = runtime.library.getLibraries();
|
safeSettings.libraries = runtime.library.getLibraries();
|
||||||
if (util.isArray(runtime.settings.paletteCategories)) {
|
if (util.isArray(runtime.settings.paletteCategories)) {
|
||||||
safeSettings.paletteCategories = runtime.settings.paletteCategories;
|
safeSettings.paletteCategories = runtime.settings.paletteCategories;
|
||||||
|
9
packages/node_modules/node-red/settings.js
vendored
9
packages/node_modules/node-red/settings.js
vendored
@ -422,9 +422,18 @@ module.exports = {
|
|||||||
//fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace",
|
//fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace",
|
||||||
//fontLigatures: true,
|
//fontLigatures: true,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
markdownEditor: {
|
||||||
|
mermaid: {
|
||||||
|
/** enable or disable mermaid diagram in markdown document
|
||||||
|
*/
|
||||||
|
enabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Node Settings
|
* Node Settings
|
||||||
* - fileWorkingDirectory
|
* - fileWorkingDirectory
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
const should = require("should");
|
||||||
|
const request = require('supertest');
|
||||||
|
const express = require('express');
|
||||||
|
const bodyParser = require("body-parser");
|
||||||
|
const sinon = require('sinon');
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
const NR_TEST_UTILS = require("nr-test-utils");
|
||||||
|
const editorLibs = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/editor-libs");
|
||||||
|
|
||||||
|
describe("api/editor/editor-libs", function() {
|
||||||
|
before(function() {
|
||||||
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.get("/editor-libs/:name", editorLibs.get);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns the editor library for mermaid", function(done) {
|
||||||
|
const settings = {};
|
||||||
|
const runtimeAPI = {};
|
||||||
|
|
||||||
|
editorLibs.init(settings, runtimeAPI);
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.get("/editor-libs/mermaid")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err || (typeof res.error === "object")) {
|
||||||
|
return done(err || res.error);
|
||||||
|
}
|
||||||
|
res.should.have.property("statusCode",200);
|
||||||
|
res.should.have.property("_body");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error when called with unknown library', function(done) {
|
||||||
|
const settings = {};
|
||||||
|
const runtimeAPI = {};
|
||||||
|
|
||||||
|
editorLibs.init(settings, runtimeAPI);
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.get("/editor-libs/unknown")
|
||||||
|
.expect(400)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user