mirror of https://github.com/mindoc-org/mindoc.git
Add mte to the Markdown editor to enhance table editing, e.g. https://susisu.github.io/mte-demo/
Signed-off-by: Seanly Liu <seanly@opsbox.dev>pull/872/head
parent
452577ca3d
commit
993089089b
|
@ -113,6 +113,7 @@ $(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
window.isLoad = true;
|
window.isLoad = true;
|
||||||
|
this.tableEditor = TableEditor.initTableEditor(this.cm)
|
||||||
},
|
},
|
||||||
onchange: function () {
|
onchange: function () {
|
||||||
resetEditorChanged(true);
|
resetEditorChanged(true);
|
||||||
|
|
|
@ -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模块进行命名定义
|
||||||
|
},
|
||||||
|
// 配置其他选项...
|
||||||
|
};
|
|
@ -455,6 +455,7 @@
|
||||||
<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