mirror of https://github.com/mindoc-org/mindoc.git
Merge branch 'seanly-feature/support-drawio'
commit
cc34c6309e
|
@ -50,8 +50,6 @@ sessiongcmaxlifetime="${MINDOC_SESSION_MAX_LIFETIME||3600}"
|
||||||
#时区设置
|
#时区设置
|
||||||
timezone = Asia/Shanghai
|
timezone = Asia/Shanghai
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################MySQL 数据库配置###########################
|
####################MySQL 数据库配置###########################
|
||||||
#支持MySQL,sqlite3,postgres三种数据库,如果是sqlite3 则 db_database 标识数据库的物理目录
|
#支持MySQL,sqlite3,postgres三种数据库,如果是sqlite3 则 db_database 标识数据库的物理目录
|
||||||
db_adapter="${MINDOC_DB_ADAPTER||sqlite3}"
|
db_adapter="${MINDOC_DB_ADAPTER||sqlite3}"
|
||||||
|
@ -127,27 +125,27 @@ baidumapkey=
|
||||||
|
|
||||||
################Active Directory/LDAP################
|
################Active Directory/LDAP################
|
||||||
#是否启用ldap
|
#是否启用ldap
|
||||||
ldap_enable=false
|
ldap_enable=${MINDOC_LDAP_ENABLE||false}
|
||||||
#ldap协议(ldap/ldaps)
|
#ldap协议(ldap/ldaps)
|
||||||
ldap_scheme=ldap
|
ldap_scheme="${MINDOC_LDAP_SCHEME||ldap}"
|
||||||
#ldap主机名
|
#ldap主机名
|
||||||
ldap_host=ad.example.com
|
ldap_host="${MINDOC_LDAP_HOST||127.0.0.1}"
|
||||||
#ldap端口
|
#ldap端口
|
||||||
ldap_port=3268
|
ldap_port=${MINDOC_LDAP_PORT||389}
|
||||||
#ldap内哪个属性作为用户名
|
#ldap内哪个属性作为用户名
|
||||||
ldap_account=sAMAccountName
|
ldap_attribute="${MINDOC_LDAP_ATTRIBUTE||sAMAccountName}"
|
||||||
#ldap内哪个属性作为邮箱
|
#ldap内哪个属性作为邮箱
|
||||||
ldap_mail=mail
|
ldap_mail="${MINDOC_LDAP_MAIL||mail}"
|
||||||
#搜索范围
|
#搜索范围
|
||||||
ldap_base=DC=example,DC=com
|
ldap_base="${MINDOC_LDAP_BASE||dc=example,dc=com}"
|
||||||
#第一次绑定ldap用户dn
|
#第一次绑定ldap用户dn
|
||||||
ldap_user=CN=ldap helper,OU=example.com,DC=example,DC=com
|
ldap_user="${MINDOC_LDAP_USER||cn=ldap helper,ou=example.com,dc=example,dc=com}"
|
||||||
#第一次绑定ldap用户密码
|
#第一次绑定ldap用户密码
|
||||||
ldap_password=superSecret
|
ldap_password="${MINDOC_LDAP_PASSWORD||xxx}"
|
||||||
#自动注册用户角色:0 超级管理员 /1 管理员/ 2 普通用户
|
#自动注册用户角色:0 超级管理员 /1 管理员/ 2 普通用户
|
||||||
ldap_user_role=2
|
ldap_user_role=${MINDOC_LDAP_USER_ROLE||2}
|
||||||
#ldap搜索filter规则,AD服务器: objectClass=User, openldap服务器: objectClass=posixAccount ,也可以定义为其他属性,如: title=mindoc
|
#ldap搜索filter规则,AD服务器: objectClass=User, openldap服务器: objectClass=posixAccount ,也可以定义为其他属性,如: title=mindoc
|
||||||
ldap_filter=objectClass=posixAccount
|
ldap_filter="${MINDOC_LDAP_FILTER||objectClass=posixAccount}"
|
||||||
|
|
||||||
############# HTTP自定义接口登录 ################
|
############# HTTP自定义接口登录 ################
|
||||||
http_login_url=
|
http_login_url=
|
||||||
|
|
|
@ -367,6 +367,7 @@ gfm_task = GFM task
|
||||||
attachment = attachment
|
attachment = attachment
|
||||||
json_to_table = Json converted to table
|
json_to_table = Json converted to table
|
||||||
template = template
|
template = template
|
||||||
|
draw = draw
|
||||||
close_preview = disable preview
|
close_preview = disable preview
|
||||||
modify_history = modify history
|
modify_history = modify history
|
||||||
sidebar = sidebar
|
sidebar = sidebar
|
||||||
|
|
|
@ -367,6 +367,7 @@ gfm_task = GFM 任务列表
|
||||||
attachment = 附件
|
attachment = 附件
|
||||||
json_to_table = Json转换为表格
|
json_to_table = Json转换为表格
|
||||||
template = 模板
|
template = 模板
|
||||||
|
draw = 画图
|
||||||
close_preview = 关闭实时预览
|
close_preview = 关闭实时预览
|
||||||
modify_history = 修改历史
|
modify_history = 修改历史
|
||||||
sidebar = 边栏
|
sidebar = 边栏
|
||||||
|
|
|
@ -3950,9 +3950,12 @@
|
||||||
}
|
}
|
||||||
return "<svg class='mindmap' style='width:100%;min-height=150px;height:"+custom_height+"px;' id='mindmap-"+ map_id +"'>"+code+"</svg>";
|
return "<svg class='mindmap' style='width:100%;min-height=150px;height:"+custom_height+"px;' id='mindmap-"+ map_id +"'>"+code+"</svg>";
|
||||||
}
|
}
|
||||||
|
if (lang === "drawio") {
|
||||||
|
var svgCode = decodeURIComponent(escape(window.atob(code)))
|
||||||
|
return "<div class=\"svg\" style=\"overflow: auto; padding: 10px;\">" + svgCode + "</div>"
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
return marked.Renderer.prototype.code.apply(this, arguments);
|
return marked.Renderer.prototype.code.apply(this, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4029,7 +4032,6 @@
|
||||||
html += "<li class=\"directory-item\"><a class=\"directory-item-link directory-item-link-" + level + "\" href=\"#" + id + "\" level=\"" + level + "\">" + text + "</a></li>";
|
html += "<li class=\"directory-item\"><a class=\"directory-item-link directory-item-link-" + level + "\" href=\"#" + id + "\" level=\"" + level + "\">" + text + "</a></li>";
|
||||||
lastLevel = level;
|
lastLevel = level;
|
||||||
}
|
}
|
||||||
console.log(html);
|
|
||||||
|
|
||||||
var tocContainer = container.find(".markdown-toc");
|
var tocContainer = container.find(".markdown-toc");
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,150 @@ $(function () {
|
||||||
js: window.katex.js,
|
js: window.katex.js,
|
||||||
css: window.katex.css
|
css: window.katex.css
|
||||||
};
|
};
|
||||||
|
var drawio = new Object()
|
||||||
|
|
||||||
|
drawio.processMarkers = function (from, to) {
|
||||||
|
var _this = this
|
||||||
|
var found = null
|
||||||
|
var foundStart = 0
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
cm.doc.getAllMarks().forEach(mk => {
|
||||||
|
if (mk.__kind) {
|
||||||
|
mk.clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
cm.eachLine(from, to, function (ln) {
|
||||||
|
const line = ln.lineNo()
|
||||||
|
|
||||||
|
if (ln.text.startsWith('```drawio')) {
|
||||||
|
found = 'drawio'
|
||||||
|
foundStart = line
|
||||||
|
} else if (ln.text === '```' && found) {
|
||||||
|
switch (found) {
|
||||||
|
// -> DRAWIO
|
||||||
|
case 'drawio': {
|
||||||
|
if (line - foundStart !== 2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_this.addMarker({
|
||||||
|
kind: 'drawio',
|
||||||
|
from: { line: foundStart, ch: 3 },
|
||||||
|
to: { line: foundStart, ch: 10 },
|
||||||
|
text: 'drawio',
|
||||||
|
action: (function (start, end) {
|
||||||
|
return function (ev) {
|
||||||
|
cm.doc.setSelection({ line: start, ch: 0 }, { line: end, ch: 3 })
|
||||||
|
try {
|
||||||
|
// save state data
|
||||||
|
const raw = cm.doc.getLine(end - 1)
|
||||||
|
window.sessionStorage.setItem("drawio", raw);
|
||||||
|
_this.show()
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(foundStart, line)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (ln.height > 0) {
|
||||||
|
cm.foldCode(foundStart)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
drawio.addMarker = function ({ kind, from, to, text, action }) {
|
||||||
|
|
||||||
|
const markerElm = document.createElement('span')
|
||||||
|
markerElm.appendChild(document.createTextNode(text))
|
||||||
|
markerElm.className = 'CodeMirror-buttonmarker'
|
||||||
|
markerElm.addEventListener('click', action)
|
||||||
|
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
cm.markText(from, to, { replacedWith: markerElm, __kind: kind })
|
||||||
|
}
|
||||||
|
|
||||||
|
drawio.show = function () {
|
||||||
|
|
||||||
|
const drawUrl = 'https://embed.diagrams.net/?embed=1&libraries=1&proto=json&spin=1&saveAndExit=1&noSaveBtn=1&noExitBtn=0';
|
||||||
|
this.div = document.createElement('div');
|
||||||
|
this.div.id = 'diagram';
|
||||||
|
this.gXml = '';
|
||||||
|
this.div.innerHTML = '';
|
||||||
|
this.iframe = document.createElement('iframe');
|
||||||
|
this.iframe.setAttribute('frameborder', '0');
|
||||||
|
this.iframe.style.zIndex = 9999;
|
||||||
|
this.iframe.style.width = "100%";
|
||||||
|
this.iframe.style.height = "100%";
|
||||||
|
this.iframe.style.position = "absolute";
|
||||||
|
this.iframe.style.top = window.scrollY + "px";
|
||||||
|
binded = this.postMessage.bind(this);
|
||||||
|
window.addEventListener("message", binded, false);
|
||||||
|
this.iframe.setAttribute('src', drawUrl);
|
||||||
|
document.body.appendChild(this.iframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawio.postMessage = function (evt) {
|
||||||
|
if (evt.data.length < 1) return
|
||||||
|
var msg = JSON.parse(evt.data)
|
||||||
|
var svg = '';
|
||||||
|
|
||||||
|
switch (msg.event) {
|
||||||
|
case "configure":
|
||||||
|
this.iframe.contentWindow.postMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
action: "configure",
|
||||||
|
config: {
|
||||||
|
defaultFonts: ["Humor Sans", "Helvetica", "Times New Roman"],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "init":
|
||||||
|
code = window.sessionStorage.getItem("drawio")
|
||||||
|
svg = decodeURIComponent(escape(window.atob(code)))
|
||||||
|
this.iframe.contentWindow.postMessage(
|
||||||
|
JSON.stringify({ action: "load", autosave: 1, xml: svg }),
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "autosave":
|
||||||
|
window.sessionStorage.setItem("drawio", svg);
|
||||||
|
break;
|
||||||
|
case "save":
|
||||||
|
this.iframe.contentWindow.postMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
action: "export",
|
||||||
|
format: "xmlsvg",
|
||||||
|
xml: msg.xml,
|
||||||
|
spin: "Updating page",
|
||||||
|
}),
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "export":
|
||||||
|
svgData = msg.data.substring(msg.data.indexOf(',') + 1);
|
||||||
|
// clean event bind
|
||||||
|
window.removeEventListener("message", this.binded);
|
||||||
|
document.body.removeChild(this.iframe);
|
||||||
|
|
||||||
|
// write back svg data
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
cm.doc.replaceSelection('```drawio\n' + svgData + '\n```', 'start')
|
||||||
|
// clean state data
|
||||||
|
window.sessionStorage.setItem("drawio", '');
|
||||||
|
break;
|
||||||
|
case "exit":
|
||||||
|
window.removeEventListener("message", this.binded);
|
||||||
|
document.body.removeChild(this.iframe);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.editormdLocales = {
|
window.editormdLocales = {
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
|
@ -81,8 +225,10 @@ $(function () {
|
||||||
highlightStyle: window.highlightStyle ? window.highlightStyle : "github",
|
highlightStyle: window.highlightStyle ? window.highlightStyle : "github",
|
||||||
tex: true,
|
tex: true,
|
||||||
saveHTMLToTextarea: true,
|
saveHTMLToTextarea: true,
|
||||||
|
codeFold: true,
|
||||||
|
|
||||||
onload: function () {
|
onload: function() {
|
||||||
|
this.registerHelper()
|
||||||
this.hideToolbar();
|
this.hideToolbar();
|
||||||
var keyMap = {
|
var keyMap = {
|
||||||
"Ctrl-S": function (cm) {
|
"Ctrl-S": function (cm) {
|
||||||
|
@ -113,12 +259,87 @@ $(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
window.isLoad = true;
|
window.isLoad = true;
|
||||||
|
this.tableEditor = TableEditor.initTableEditor(this.cm)
|
||||||
},
|
},
|
||||||
onchange: function () {
|
onchange: function () {
|
||||||
|
/**
|
||||||
|
* 实现画图的事件注入
|
||||||
|
*
|
||||||
|
* 1. 分析文本,添加点击编辑事件,processMarkers
|
||||||
|
* 2. 获取内容,存储状态数据
|
||||||
|
* 3. 打开编辑画面
|
||||||
|
* 4. 推出触发变更事件,并回写数据
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
drawio.processMarkers(cm.firstLine(), cm.lastLine() + 1)
|
||||||
|
|
||||||
resetEditorChanged(true);
|
resetEditorChanged(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editormd.fn.registerHelper = function () {
|
||||||
|
|
||||||
|
const maxDepth = 100
|
||||||
|
const codeBlockStartMatch = /^`{3}[a-zA-Z0-9]+$/
|
||||||
|
const codeBlockEndMatch = /^`{3}$/
|
||||||
|
|
||||||
|
|
||||||
|
editormd.$CodeMirror.registerHelper('fold', 'markdown', function (cm, start) {
|
||||||
|
const firstLine = cm.getLine(start.line)
|
||||||
|
const lastLineNo = cm.lastLine()
|
||||||
|
let end
|
||||||
|
|
||||||
|
function isHeader(lineNo) {
|
||||||
|
const tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0))
|
||||||
|
return tokentype && /\bheader\b/.test(tokentype)
|
||||||
|
}
|
||||||
|
|
||||||
|
function headerLevel(lineNo, line, nextLine) {
|
||||||
|
let match = line && line.match(/^#+/)
|
||||||
|
if (match && isHeader(lineNo)) return match[0].length
|
||||||
|
match = nextLine && nextLine.match(/^[=-]+\s*$/)
|
||||||
|
if (match && isHeader(lineNo + 1)) return nextLine[0] === '=' ? 1 : 2
|
||||||
|
return maxDepth
|
||||||
|
}
|
||||||
|
|
||||||
|
// -> CODE BLOCK
|
||||||
|
|
||||||
|
if (codeBlockStartMatch.test(cm.getLine(start.line))) {
|
||||||
|
end = start.line
|
||||||
|
let nextNextLine = cm.getLine(end + 1)
|
||||||
|
while (end < lastLineNo) {
|
||||||
|
if (codeBlockEndMatch.test(nextNextLine)) {
|
||||||
|
end++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
end++
|
||||||
|
nextNextLine = cm.getLine(end + 1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// -> HEADER
|
||||||
|
|
||||||
|
let nextLine = cm.getLine(start.line + 1)
|
||||||
|
const level = headerLevel(start.line, firstLine, nextLine)
|
||||||
|
if (level === maxDepth) return undefined
|
||||||
|
|
||||||
|
end = start.line
|
||||||
|
let nextNextLine = cm.getLine(end + 2)
|
||||||
|
while (end < lastLineNo) {
|
||||||
|
if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break
|
||||||
|
++end
|
||||||
|
nextLine = nextNextLine
|
||||||
|
nextNextLine = cm.getLine(end + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: CodeMirror.Pos(start.line, firstLine.length),
|
||||||
|
to: CodeMirror.Pos(end, cm.getLine(end).length)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function insertToMarkdown(body) {
|
function insertToMarkdown(body) {
|
||||||
window.isLoad = true;
|
window.isLoad = true;
|
||||||
window.editor.insertValue(body);
|
window.editor.insertValue(body);
|
||||||
|
@ -193,6 +414,21 @@ $(function () {
|
||||||
}
|
}
|
||||||
cm.replaceSelection(selectionText.join("\n"));
|
cm.replaceSelection(selectionText.join("\n"));
|
||||||
}
|
}
|
||||||
|
} else if (name === "drawio") {
|
||||||
|
/**
|
||||||
|
* TODO: 画图功能实现
|
||||||
|
*
|
||||||
|
* 1. 获取光标处数据,存储数据
|
||||||
|
* 2. 打开画图页面,初始化数据(获取数据)
|
||||||
|
*/
|
||||||
|
window.sessionStorage.setItem("drawio", '');
|
||||||
|
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
const selStartLine = cm.getCursor('from').line
|
||||||
|
const selEndLine = cm.getCursor('to').line + 1
|
||||||
|
|
||||||
|
drawio.processMarkers(selStartLine, selEndLine)
|
||||||
|
drawio.show()
|
||||||
} else {
|
} else {
|
||||||
var action = window.editor.toolbarHandlers[name];
|
var action = window.editor.toolbarHandlers[name];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "mte",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build:release": "cross-env NODE_ENV=production webpack",
|
||||||
|
"build:debug": "cross-env NODE_ENV=development webpack",
|
||||||
|
"build": "npm run build:release",
|
||||||
|
"clean": "rimraf build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@susisu/mte-kernel": "^1.0.0",
|
||||||
|
"codemirror": "^5.31.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.26.0",
|
||||||
|
"babel-loader": "^7.1.2",
|
||||||
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"cpx": "^1.5.0",
|
||||||
|
"cross-env": "^5.1.1",
|
||||||
|
"eslint": "^4.11.0",
|
||||||
|
"npm-run-all": "^4.1.2",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
|
"uglifyjs-webpack-plugin": "^1.1.0",
|
||||||
|
"webpack": "^3.8.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
/* global CodeMirror, $ */
|
||||||
|
import { TableEditor, Point, options, Alignment, FormatType } from '@susisu/mte-kernel'
|
||||||
|
|
||||||
|
// port of the code from: https://github.com/susisu/mte-demo/blob/master/src/main.js
|
||||||
|
|
||||||
|
// text editor interface
|
||||||
|
// see https://doc.esdoc.org/github.com/susisu/mte-kernel/class/lib/text-editor.js~ITextEditor.html
|
||||||
|
class TextEditorInterface {
|
||||||
|
constructor (editor) {
|
||||||
|
this.editor = editor
|
||||||
|
this.doc = editor.getDoc()
|
||||||
|
this.transaction = false
|
||||||
|
this.onDidFinishTransaction = null
|
||||||
|
}
|
||||||
|
|
||||||
|
getCursorPosition () {
|
||||||
|
const { line, ch } = this.doc.getCursor()
|
||||||
|
return new Point(line, ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
setCursorPosition (pos) {
|
||||||
|
this.doc.setCursor({ line: pos.row, ch: pos.column })
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectionRange (range) {
|
||||||
|
this.doc.setSelection(
|
||||||
|
{ line: range.start.row, ch: range.start.column },
|
||||||
|
{ line: range.end.row, ch: range.end.column }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastRow () {
|
||||||
|
return this.doc.lineCount() - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptsTableEdit () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
getLine (row) {
|
||||||
|
return this.doc.getLine(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
insertLine (row, line) {
|
||||||
|
const lastRow = this.getLastRow()
|
||||||
|
if (row > lastRow) {
|
||||||
|
const lastLine = this.getLine(lastRow)
|
||||||
|
this.doc.replaceRange(
|
||||||
|
'\n' + line,
|
||||||
|
{ line: lastRow, ch: lastLine.length },
|
||||||
|
{ line: lastRow, ch: lastLine.length }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.doc.replaceRange(
|
||||||
|
line + '\n',
|
||||||
|
{ line: row, ch: 0 },
|
||||||
|
{ line: row, ch: 0 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteLine (row) {
|
||||||
|
const lastRow = this.getLastRow()
|
||||||
|
if (row >= lastRow) {
|
||||||
|
if (lastRow > 0) {
|
||||||
|
const preLastLine = this.getLine(lastRow - 1)
|
||||||
|
const lastLine = this.getLine(lastRow)
|
||||||
|
this.doc.replaceRange(
|
||||||
|
'',
|
||||||
|
{ line: lastRow - 1, ch: preLastLine.length },
|
||||||
|
{ line: lastRow, ch: lastLine.length }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const lastLine = this.getLine(lastRow)
|
||||||
|
this.doc.replaceRange(
|
||||||
|
'',
|
||||||
|
{ line: lastRow, ch: 0 },
|
||||||
|
{ line: lastRow, ch: lastLine.length }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.doc.replaceRange(
|
||||||
|
'',
|
||||||
|
{ line: row, ch: 0 },
|
||||||
|
{ line: row + 1, ch: 0 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceLines (startRow, endRow, lines) {
|
||||||
|
const lastRow = this.getLastRow()
|
||||||
|
if (endRow > lastRow) {
|
||||||
|
const lastLine = this.getLine(lastRow)
|
||||||
|
this.doc.replaceRange(
|
||||||
|
lines.join('\n'),
|
||||||
|
{ line: startRow, ch: 0 },
|
||||||
|
{ line: lastRow, ch: lastLine.length }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.doc.replaceRange(
|
||||||
|
lines.join('\n') + '\n',
|
||||||
|
{ line: startRow, ch: 0 },
|
||||||
|
{ line: endRow, ch: 0 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transact (func) {
|
||||||
|
this.transaction = true
|
||||||
|
func()
|
||||||
|
this.transaction = false
|
||||||
|
if (this.onDidFinishTransaction) {
|
||||||
|
this.onDidFinishTransaction.call(undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initTableEditor (editor) {
|
||||||
|
// create an interface to the text editor
|
||||||
|
const editorIntf = new TextEditorInterface(editor)
|
||||||
|
// create a table editor object
|
||||||
|
const tableEditor = new TableEditor(editorIntf)
|
||||||
|
// options for the table editor
|
||||||
|
const opts = options({
|
||||||
|
smartCursor: true,
|
||||||
|
formatType: FormatType.NORMAL
|
||||||
|
})
|
||||||
|
// keymap of the commands
|
||||||
|
// from https://github.com/susisu/mte-demo/blob/master/src/main.js
|
||||||
|
const keyMap = CodeMirror.normalizeKeyMap({
|
||||||
|
Tab: () => { tableEditor.nextCell(opts) },
|
||||||
|
'Shift-Tab': () => { tableEditor.previousCell(opts) },
|
||||||
|
Enter: () => { tableEditor.nextRow(opts) },
|
||||||
|
'Ctrl-Enter': () => { tableEditor.escape(opts) },
|
||||||
|
'Cmd-Enter': () => { tableEditor.escape(opts) },
|
||||||
|
'Shift-Ctrl-Left': () => { tableEditor.alignColumn(Alignment.LEFT, opts) },
|
||||||
|
'Shift-Cmd-Left': () => { tableEditor.alignColumn(Alignment.LEFT, opts) },
|
||||||
|
'Shift-Ctrl-Right': () => { tableEditor.alignColumn(Alignment.RIGHT, opts) },
|
||||||
|
'Shift-Cmd-Right': () => { tableEditor.alignColumn(Alignment.RIGHT, opts) },
|
||||||
|
'Shift-Ctrl-Up': () => { tableEditor.alignColumn(Alignment.CENTER, opts) },
|
||||||
|
'Shift-Cmd-Up': () => { tableEditor.alignColumn(Alignment.CENTER, opts) },
|
||||||
|
'Shift-Ctrl-Down': () => { tableEditor.alignColumn(Alignment.NONE, opts) },
|
||||||
|
'Shift-Cmd-Down': () => { tableEditor.alignColumn(Alignment.NONE, opts) },
|
||||||
|
'Ctrl-Left': () => { tableEditor.moveFocus(0, -1, opts) },
|
||||||
|
'Cmd-Left': () => { tableEditor.moveFocus(0, -1, opts) },
|
||||||
|
'Ctrl-Right': () => { tableEditor.moveFocus(0, 1, opts) },
|
||||||
|
'Cmd-Right': () => { tableEditor.moveFocus(0, 1, opts) },
|
||||||
|
'Ctrl-Up': () => { tableEditor.moveFocus(-1, 0, opts) },
|
||||||
|
'Cmd-Up': () => { tableEditor.moveFocus(-1, 0, opts) },
|
||||||
|
'Ctrl-Down': () => { tableEditor.moveFocus(1, 0, opts) },
|
||||||
|
'Cmd-Down': () => { tableEditor.moveFocus(1, 0, opts) },
|
||||||
|
'Ctrl-K Ctrl-I': () => { tableEditor.insertRow(opts) },
|
||||||
|
'Cmd-K Cmd-I': () => { tableEditor.insertRow(opts) },
|
||||||
|
'Ctrl-L Ctrl-I': () => { tableEditor.deleteRow(opts) },
|
||||||
|
'Cmd-L Cmd-I': () => { tableEditor.deleteRow(opts) },
|
||||||
|
'Ctrl-K Ctrl-J': () => { tableEditor.insertColumn(opts) },
|
||||||
|
'Cmd-K Cmd-J': () => { tableEditor.insertColumn(opts) },
|
||||||
|
'Ctrl-L Ctrl-J': () => { tableEditor.deleteColumn(opts) },
|
||||||
|
'Cmd-L Cmd-J': () => { tableEditor.deleteColumn(opts) },
|
||||||
|
'Alt-Shift-Ctrl-Left': () => { tableEditor.moveColumn(-1, opts) },
|
||||||
|
'Alt-Shift-Cmd-Left': () => { tableEditor.moveColumn(-1, opts) },
|
||||||
|
'Alt-Shift-Ctrl-Right': () => { tableEditor.moveColumn(1, opts) },
|
||||||
|
'Alt-Shift-Cmd-Right': () => { tableEditor.moveColumn(1, opts) },
|
||||||
|
'Alt-Shift-Ctrl-Up': () => { tableEditor.moveRow(-1, opts) },
|
||||||
|
'Alt-Shift-Cmd-Up': () => { tableEditor.moveRow(-1, opts) },
|
||||||
|
'Alt-Shift-Ctrl-Down': () => { tableEditor.moveRow(1, opts) },
|
||||||
|
'Alt-Shift-Cmd-Down': () => { tableEditor.moveRow(1, opts) }
|
||||||
|
})
|
||||||
|
|
||||||
|
// enable keymap if the cursor is in a table
|
||||||
|
function updateActiveState() {
|
||||||
|
const active = tableEditor.cursorIsInTable();
|
||||||
|
if (active) {
|
||||||
|
editor.setOption("extraKeys", keyMap);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
editor.setOption("extraKeys", null);
|
||||||
|
tableEditor.resetSmartCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// event subscriptions
|
||||||
|
editor.on("cursorActivity", () => {
|
||||||
|
if (!editorIntf.transaction) {
|
||||||
|
updateActiveState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.on("changes", () => {
|
||||||
|
if (!editorIntf.transaction) {
|
||||||
|
updateActiveState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editorIntf.onDidFinishTransaction = () => {
|
||||||
|
updateActiveState();
|
||||||
|
};
|
||||||
|
|
||||||
|
return tableEditor
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// webpack.config.js
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/main.js', // 库的入口文件
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'dist'), // 输出目录
|
||||||
|
filename: 'index.js', // 输出文件名称
|
||||||
|
library: 'TableEditor', // 库的全局变量名
|
||||||
|
libraryTarget: 'umd', // 输出库的目标格式
|
||||||
|
umdNamedDefine: true // 对UMD模块进行命名定义
|
||||||
|
},
|
||||||
|
// 配置其他选项...
|
||||||
|
};
|
|
@ -52,6 +52,15 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.svg {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -101,6 +101,7 @@
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.gfm_task"}}"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.gfm_task"}}"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.attachment"}}"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.attachment"}}"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.json_to_table"}}"><i class="fa fa-wrench item" aria-hidden="true" name="json"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.json_to_table"}}"><i class="fa fa-wrench item" aria-hidden="true" name="json"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.draw"}}"><i class="fa fa-paint-brush item" aria-hidden="true" name="drawio"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.template"}}"><i class="fa fa-tachometer last" name="template"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.template"}}"><i class="fa fa-tachometer last" name="template"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -450,11 +451,12 @@
|
||||||
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||||
<script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/jstree/3.3.4/jstree.min.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/jstree/3.3.4/jstree.min.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/editor.md/editormd.min.js" "version"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/editor.md/editormd.js" "version"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
||||||
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/js/array.js" "version"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/array.js" "version"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/js/editor.js" "version"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/editor.js" "version"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/table-editor/dist/index.js" "version"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/js/markdown.js" "version"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/markdown.js" "version"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||||
|
|
Loading…
Reference in New Issue