trilium/src/public/javascripts/services/note_detail_code.js

131 lines
4.2 KiB
JavaScript
Raw Normal View History

2018-03-28 10:42:46 +08:00
import libraryLoader from "./library_loader.js";
import bundleService from "./bundle.js";
2019-10-20 16:00:18 +08:00
import toastService from "./toast.js";
import server from "./server.js";
import noteDetailService from "./note_detail.js";
import keyboardActionService from "./keyboard_actions.js";
2020-01-14 04:48:44 +08:00
const TPL = `
<div class="note-detail-code note-detail-component">
<div class="note-detail-code-editor"></div>
</div>`;
2019-05-04 06:16:41 +08:00
class NoteDetailCode {
2019-05-04 06:16:41 +08:00
/**
2019-05-09 01:55:24 +08:00
* @param {TabContext} ctx
2019-05-04 06:16:41 +08:00
*/
constructor(ctx) {
this.ctx = ctx;
this.codeEditor = null;
2019-05-09 01:55:24 +08:00
this.$component = ctx.$tabContent.find('.note-detail-code');
this.$editorEl = this.$component.find('.note-detail-code-editor');
2019-05-09 01:55:24 +08:00
this.$executeScriptButton = ctx.$tabContent.find(".execute-script-button");
keyboardActionService.setElementActionHandler(ctx.$tabContent, 'RunActiveNote', () => this.executeCurrentNote());
2019-11-10 00:39:48 +08:00
this.$executeScriptButton.on('click', () => this.executeCurrentNote());
}
2019-05-12 18:58:55 +08:00
async render() {
2019-05-04 06:16:41 +08:00
await libraryLoader.requireLibrary(libraryLoader.CODE_MIRROR);
if (!this.codeEditor) {
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
CodeMirror.keyMap.default["Tab"] = "indentMore";
// these conflict with backward/forward navigation shortcuts
delete CodeMirror.keyMap.default["Alt-Left"];
delete CodeMirror.keyMap.default["Alt-Right"];
CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
this.codeEditor = CodeMirror(this.$editorEl[0], {
2019-05-04 06:16:41 +08:00
value: "",
viewportMargin: Infinity,
indentUnit: 4,
matchBrackets: true,
matchTags: {bothTags: true},
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
lint: true,
gutters: ["CodeMirror-lint-markers"],
lineNumbers: true,
tabindex: 100,
// we linewrap partly also because without it horizontal scrollbar displays only when you scroll
// all the way to the bottom of the note. With line wrap there's no horizontal scrollbar so no problem
lineWrapping: true,
dragDrop: false // with true the editor inlines dropped files which is not what we expect
2019-05-04 06:16:41 +08:00
});
2019-05-04 20:34:03 +08:00
this.onNoteChange(() => this.ctx.noteChanged());
2019-05-04 06:16:41 +08:00
}
// lazy loading above can take time and tab might have been already switched to another note
if (this.ctx.note && this.ctx.note.type === 'code') {
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
// we provide fallback
this.codeEditor.setValue(this.ctx.note.content || "");
const info = CodeMirror.findModeByMIME(this.ctx.note.mime);
if (info) {
this.codeEditor.setOption("mode", info.mime);
CodeMirror.autoLoadMode(this.codeEditor, info.mode);
}
this.show();
}
}
show() {
this.$component.show();
2019-09-07 02:50:57 +08:00
if (this.codeEditor) { // show can be called before render
this.codeEditor.refresh();
}
2019-05-04 06:16:41 +08:00
}
2019-05-04 06:16:41 +08:00
getContent() {
return this.codeEditor.getValue();
}
2019-05-04 06:16:41 +08:00
focus() {
this.codeEditor.focus();
}
2019-05-04 06:16:41 +08:00
async executeCurrentNote() {
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
if (this.ctx.note.type !== 'code') {
return;
}
2019-05-04 06:16:41 +08:00
// make sure note is saved so we load latest changes
await noteDetailService.saveNotesIfChanged();
if (this.ctx.note.mime.endsWith("env=frontend")) {
await bundleService.getAndExecuteBundle(this.ctx.note.noteId);
}
2019-05-04 06:16:41 +08:00
if (this.ctx.note.mime.endsWith("env=backend")) {
await server.post('script/run/' + this.ctx.note.noteId);
}
2019-10-20 16:00:18 +08:00
toastService.showMessage("Note executed");
2019-05-04 06:16:41 +08:00
}
2019-05-04 06:16:41 +08:00
onNoteChange(func) {
this.codeEditor.on('change', func);
}
cleanup() {
if (this.codeEditor) {
this.codeEditor.setValue('');
}
2019-05-04 06:16:41 +08:00
}
scrollToTop() {
this.$component.scrollTop(0);
}
}
2019-05-04 06:16:41 +08:00
export default NoteDetailCode;