mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-23 16:52:31 +01:00
feature (#12): syntax highlighting for a wide range of language
This commit is contained in:
parent
870d4e7ba5
commit
f25428ca53
31 changed files with 291 additions and 211 deletions
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import CodeMirror from 'codemirror/lib/codemirror';
|
||||
window.CodeMirror = CodeMirror;
|
||||
|
||||
// keybinding
|
||||
import 'codemirror/keymap/emacs.js';
|
||||
|
|
@ -17,99 +18,6 @@ import 'codemirror/addon/dialog/dialog.js';
|
|||
import 'codemirror/addon/fold/foldcode';
|
||||
import 'codemirror/addon/fold/foldgutter';
|
||||
|
||||
// modes
|
||||
import 'codemirror/addon/mode/simple';
|
||||
|
||||
CodeMirror.defineSimpleMode("orgmode", {
|
||||
start: [
|
||||
{regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING){0,1}(CANCEL|DEFERRED|DONE){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]},
|
||||
{regex: /(^\+[^\/]*\+)/, token: ["strikethrough"]},
|
||||
{regex: /(^\*[^\/]*\*)/, token: ["strong"]},
|
||||
{regex: /(^\/[^\/]*\/)/, token: ["em"]},
|
||||
{regex: /(^\_[^\/]*\_)/, token: ["link"]},
|
||||
{regex: /(^\~[^\/]*\~)/, token: ["comment"]},
|
||||
{regex: /(^\=[^\/]*\=)/, token: ["comment"]},
|
||||
// special syntax
|
||||
//{regex: /(^[\*]+)(\s[TODO|NEXT|DONE|DEFERRED|REJECTED|WAITING]{2,})?(.*)/, token: ['comment', 'qualifier', 'header']}, // headline
|
||||
{regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links
|
||||
{regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox
|
||||
{regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments
|
||||
{regex: /:?[A-Z_]+\:.*/, token: "comment"}, // property drawers
|
||||
{regex: /(\#\+[A-Z_]*)(\:.*)/, token: ["keyword", 'qualifier']}, // environments
|
||||
{regex: /(CLOCK\:|SHEDULED\:)(\s.+)/, token: ["comment", "keyword"]}
|
||||
],
|
||||
env: [
|
||||
{regex: /.*?\#\+END_[A-Z]*/, token: "comment", next: "start"},
|
||||
{regex: /.*/, token: "comment"}
|
||||
]
|
||||
});
|
||||
CodeMirror.registerHelper("fold", "orgmode", function(cm, start) {
|
||||
// init
|
||||
const levelToMatch = headerLevel(start.line);
|
||||
|
||||
// no folding needed
|
||||
if(levelToMatch === null) return;
|
||||
|
||||
// find folding limits
|
||||
const lastLine = cm.lastLine();
|
||||
let end = start.line;
|
||||
while(end < lastLine){
|
||||
end += 1;
|
||||
let level = headerLevel(end);
|
||||
if(level && level <= levelToMatch) {
|
||||
end = end - 1;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
|
||||
to: CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
|
||||
function headerLevel(lineNo) {
|
||||
var line = cm.getLine(lineNo);
|
||||
var match = /^\*+/.exec(line);
|
||||
if(match && match.length === 1 && /header/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)))){
|
||||
return match[0].length;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
CodeMirror.registerGlobalHelper("fold", "drawer", function(mode) {
|
||||
return mode.name === 'orgmode' ? true : false;
|
||||
}, function(cm, start) {
|
||||
const drawer = isBeginningOfADrawer(start.line);
|
||||
if(drawer === false) return;
|
||||
|
||||
// find folding limits
|
||||
const lastLine = cm.lastLine();
|
||||
let end = start.line;
|
||||
while(end < lastLine){
|
||||
end += 1;
|
||||
if(isEndOfADrawer(end)){
|
||||
break
|
||||
}
|
||||
}
|
||||
return {
|
||||
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
|
||||
to: CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
|
||||
function isBeginningOfADrawer(lineNo) {
|
||||
var line = cm.getLine(lineNo);
|
||||
var match = /^\:.*\:$/.exec(line);
|
||||
if(match && match.length === 1 && match[0] !== ':END:'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isEndOfADrawer(lineNo){
|
||||
var line = cm.getLine(lineNo);
|
||||
return line.trim() === ':END:' ? true : false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export class Editor extends React.Component {
|
||||
constructor(props){
|
||||
|
|
@ -133,88 +41,23 @@ export class Editor extends React.Component {
|
|||
this.loadMode(this.props.filename)
|
||||
.then(loadCodeMirror.bind(this))
|
||||
|
||||
function loadCodeMirror(mode){
|
||||
function loadCodeMirror(CodeMirror){
|
||||
const size_small = 500;
|
||||
let editor = CodeMirror(document.getElementById('editor'), {
|
||||
value: this.props.content,
|
||||
lineNumbers: document.body.offsetWidth > size_small ? true : false,
|
||||
mode: mode,
|
||||
mode: CodeMirror.__mode,
|
||||
keyMap: "emacs",
|
||||
lineWrapping: true,
|
||||
foldGutter: {
|
||||
minFoldSize: 1
|
||||
}
|
||||
});
|
||||
if(mode === 'orgmode'){
|
||||
let state = {
|
||||
stab: 'OVERVIEW'
|
||||
};
|
||||
editor.setOption("extraKeys", {
|
||||
"Tab": function(cm) {
|
||||
let pos = cm.getCursor();
|
||||
isFold(cm, pos) ? unfold(cm, pos) : fold(cm, pos);
|
||||
},
|
||||
"Shift-Tab": function(cm){
|
||||
if(state.stab === "SHOW_ALL"){
|
||||
// fold everything that can be fold
|
||||
state.stab = 'OVERVIEW';
|
||||
cm.operation(function() {
|
||||
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
|
||||
fold(cm, CodeMirror.Pos(i, 0));
|
||||
}
|
||||
});
|
||||
}else{
|
||||
// unfold all headers
|
||||
state.stab = 'SHOW_ALL';
|
||||
cm.operation(function() {
|
||||
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
|
||||
if(/header/.test(cm.getTokenTypeAt(CodeMirror.Pos(i, 0))) === true){
|
||||
unfold(cm, CodeMirror.Pos(i, 0))
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function fold(cm, start){
|
||||
cm.foldCode(start, null, "fold");
|
||||
}
|
||||
function unfold(cm, start){
|
||||
cm.foldCode(start, null, "unfold");
|
||||
}
|
||||
function isFold(cm, start){
|
||||
const line = start.line;
|
||||
const marks = cm.findMarks(CodeMirror.Pos(line, 0), CodeMirror.Pos(line + 1, 0));
|
||||
for (let i = 0; i < marks.length; ++i)
|
||||
if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
|
||||
return false;
|
||||
}
|
||||
editor.on('touchstart', function(cm, e){
|
||||
setTimeout(() => {
|
||||
isFold(cm, cm.getCursor()) ? unfold(cm, cm.getCursor()) : fold(cm, cm.getCursor())
|
||||
}, 150);
|
||||
});
|
||||
// fold everything except headers by default
|
||||
editor.operation(function() {
|
||||
for (var i = 0; i < editor.lineCount() ; i++) {
|
||||
if(/header/.test(editor.getTokenTypeAt(CodeMirror.Pos(i, 0))) === false){
|
||||
fold(editor, CodeMirror.Pos(i, 0));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function collapseWidget(){
|
||||
let $widget = document.createElement('span');
|
||||
$widget.appendChild(document.createTextNode('colapse'));
|
||||
return $widget;
|
||||
}
|
||||
function expandWidget(){
|
||||
let $widget = document.createElement('span');
|
||||
$widget.appendChild(document.createTextNode('expand'));
|
||||
return $widget;
|
||||
}
|
||||
if(CodeMirror.afterInit){
|
||||
CodeMirror.afterInit(editor);
|
||||
}
|
||||
|
||||
this.setState({editor: editor});
|
||||
this.updateHeight(this.props.height);
|
||||
|
||||
|
|
@ -222,7 +65,8 @@ export class Editor extends React.Component {
|
|||
if(this.props.onChange){
|
||||
this.props.onChange(edit.getValue());
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
CodeMirror.commands.save = () => {
|
||||
let elt = editor.getWrapperElement();
|
||||
elt.style.background = "rgba(0,0,0,0.1)";
|
||||
|
|
@ -249,52 +93,43 @@ export class Editor extends React.Component {
|
|||
|
||||
ext = ext.replace(/~$/, ''); // remove emacs mark when a file is opened
|
||||
|
||||
if(ext === 'org' || ext === 'org_archive'){ return Promise.resolve('orgmode'); }
|
||||
else if(ext === 'js' || ext === 'json'){
|
||||
// import('../pages/editpage/index')
|
||||
// .then((m) => {console.log(m);})
|
||||
// .catch((err) => {
|
||||
// console.trace(err)
|
||||
// })
|
||||
// require(["../pages/editpage/javascript"], function(a) {
|
||||
// console.log("DONEEE");
|
||||
// console.log("HEREEE")
|
||||
// }, function(err){
|
||||
// console.log(err)
|
||||
// });
|
||||
|
||||
//
|
||||
// return System.import('../pages/editpage/index')
|
||||
// .then((mode) => {
|
||||
// console.log(mode)
|
||||
// return Promise.resolve('javascript')
|
||||
// })
|
||||
//System.import('codemirror/mode/javascript/javascript')
|
||||
return Promise.resolve('javascript')
|
||||
if(ext === 'org' || ext === 'org_archive'){ mode = 'orgmode'; }
|
||||
else if(ext === 'sh'){ mode = 'shell'; }
|
||||
else if(ext === 'py'){ mode = 'python'; }
|
||||
else if(ext === 'html'){ mode = 'html'; }
|
||||
else if(ext === 'css'){ mode = 'css'; }
|
||||
else if(ext === 'less' || ext === 'scss'){ mode = 'sass'; }
|
||||
else if(ext === 'js' || ext === 'json'){ mode = 'javascript'; }
|
||||
else if(ext === 'jsx'){ mode = 'jsx' }
|
||||
else if(ext === 'php' || ext === 'php5'){ mode = 'php'; }
|
||||
else if(ext === 'elm'){ mode = 'elm'; }
|
||||
else if(ext === 'erl'){ mode = 'erlang'; }
|
||||
else if(ext === 'go'){mode = 'go'; }
|
||||
else if(ext === 'markdown' || ext === 'md'){mode = 'markdown'; }
|
||||
else if(ext === 'pl' || ext === 'pm'){mode = 'perl'; }
|
||||
else if(ext === 'clj'){ mode = 'clojure'; }
|
||||
else if(ext === 'el' || ext === 'lisp' || ext === 'cl'){ mode = 'lisp'; }
|
||||
else if(ext === 'Dockerfile'){ mode = 'dockerfile'}
|
||||
else if(ext === 'R'){ mode = 'r'; }
|
||||
else if(ext === 'Makefile'){ mode = 'cmake'; }
|
||||
else if(ext === 'rb'){ mode = 'ruby'; }
|
||||
else if(ext === 'sql'){ mode = 'sql'; }
|
||||
else if(ext === 'xml'){ mode = 'xml'; }
|
||||
else if(ext === 'yml'){ mode = 'yml'; }
|
||||
else if(ext === 'lua'){ mode = 'lua'; }
|
||||
else if(ext === 'csv'){ mode = 'csv'; }
|
||||
else if(ext === 'rs' || ext === 'rlib'){ mode = 'rust'; }
|
||||
else if(ext === 'c' || ext === 'cpp' || ext === 'java'){
|
||||
mode = 'clike';
|
||||
}else{
|
||||
mode = 'text';
|
||||
}
|
||||
// else if(ext === 'sh'){ mode = 'shell'; }
|
||||
// else if(ext === 'py'){ mode = 'python'; }
|
||||
// else if(ext === 'html'){ mode = 'htmlmixed'; }
|
||||
// else if(ext === 'css'){ mode = 'css'; }
|
||||
// else if(ext === 'erl'){ mode = 'erlang'; }
|
||||
// else if(ext === 'go'){mode = 'go'; }
|
||||
// else if(ext === 'markdown' || ext === 'md'){mode = 'markdown'; }
|
||||
// else if(ext === 'pl'){mode = 'perl'; }
|
||||
// else if(ext === 'clj'){ mode = 'clojure'; }
|
||||
// else if(ext === 'php'){ mode = 'php'; }
|
||||
// else if(ext === 'r'){ mode = 'r'; }
|
||||
// else if(ext === 'rb'){ mode = 'ruby'; }
|
||||
// else if(ext === 'less' || ext === 'scss'){ mode = 'sass'; }
|
||||
// else if(ext === 'sql'){ mode = 'sql'; }
|
||||
// else if(ext === 'xml'){ mode = 'xml'; }
|
||||
// else if(ext === 'yml'){
|
||||
// System.import('codemirror/mode/javascript/javascript')
|
||||
// //.then(() => Promise.resolve('javascript'));
|
||||
// }
|
||||
// else if(ext === 'c' || ext === 'cpp' || ext === 'java'){
|
||||
// mode = 'clike';
|
||||
// }
|
||||
else{ return Promise.resolve('orgmode') }
|
||||
|
||||
// haskell
|
||||
|
||||
console.log(mode)
|
||||
return import(/* webpackChunkName: "editor" */'../pages/viewerpage/editor/'+mode)
|
||||
.then((module) => Promise.resolve(module.default));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export function opener(file){
|
|||
return 'pdf';
|
||||
}else if(mime.split('/')[0] === 'image'){
|
||||
return 'image';
|
||||
}else if(['application/javascript', 'application/xml', 'application/json'].indexOf(mime) !== -1){
|
||||
}else if(['application/javascript', 'application/xml', 'application/json', 'application/x-perl'].indexOf(mime) !== -1){
|
||||
return 'editor';
|
||||
}else if(['audio/wav', 'audio/mp3', 'audio/flac'].indexOf(mime) !== -1){
|
||||
return 'audio';
|
||||
|
|
|
|||
3
client/pages/viewerpage/editor/clike.js
Normal file
3
client/pages/viewerpage/editor/clike.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/clike/clike';
|
||||
CodeMirror.__mode = 'clike';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/clojure.js
Normal file
3
client/pages/viewerpage/editor/clojure.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/clojure/clojure';
|
||||
CodeMirror.__mode = 'clojure';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/cmake.js
Normal file
3
client/pages/viewerpage/editor/cmake.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/cmake/cmake';
|
||||
CodeMirror.__mode = 'cmake';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/css.js
Normal file
3
client/pages/viewerpage/editor/css.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/css/css';
|
||||
CodeMirror.__mode = 'css';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/csv.js
Normal file
3
client/pages/viewerpage/editor/csv.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/spreadsheet/spreadsheet';
|
||||
CodeMirror.__mode = 'spreadsheet';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/dockerfile.js
Normal file
3
client/pages/viewerpage/editor/dockerfile.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/dockerfile/dockerfile';
|
||||
CodeMirror.__mode = 'dockerfile';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/elm.js
Normal file
3
client/pages/viewerpage/editor/elm.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/elm/elm';
|
||||
CodeMirror.__mode = 'elm';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/erlang.js
Normal file
3
client/pages/viewerpage/editor/erlang.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/erlang/erlang';
|
||||
CodeMirror.__mode = 'css';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/go.js
Normal file
3
client/pages/viewerpage/editor/go.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/go/go';
|
||||
CodeMirror.__mode = 'go';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/html.js
Normal file
3
client/pages/viewerpage/editor/html.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/htmlmixed/htmlmixed';
|
||||
CodeMirror.__mode = 'htmlmixed';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/javascript.js
Normal file
3
client/pages/viewerpage/editor/javascript.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/javascript/javascript';
|
||||
CodeMirror.__mode = 'javascript';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/jsx.js
Normal file
3
client/pages/viewerpage/editor/jsx.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/jsx/jsx';
|
||||
CodeMirror.__mode = 'jsx';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/lisp.js
Normal file
3
client/pages/viewerpage/editor/lisp.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/commonlisp/commonlisp';
|
||||
CodeMirror.__mode = 'commonlisp';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/lua.js
Normal file
3
client/pages/viewerpage/editor/lua.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/lua/lua';
|
||||
CodeMirror.__mode = 'lua';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/markdown.js
Normal file
3
client/pages/viewerpage/editor/markdown.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/markdown/markdown';
|
||||
CodeMirror.__mode = 'go';
|
||||
export default CodeMirror;
|
||||
166
client/pages/viewerpage/editor/orgmode.js
Normal file
166
client/pages/viewerpage/editor/orgmode.js
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
import 'codemirror/addon/mode/simple';
|
||||
|
||||
CodeMirror.__mode = 'orgmode';
|
||||
|
||||
CodeMirror.defineSimpleMode("orgmode", {
|
||||
start: [
|
||||
{regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING){0,1}(CANCEL|DEFERRED|DONE){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]},
|
||||
{regex: /(^\+[^\/]*\+)/, token: ["strikethrough"]},
|
||||
{regex: /(^\*[^\/]*\*)/, token: ["strong"]},
|
||||
{regex: /(^\/[^\/]*\/)/, token: ["em"]},
|
||||
{regex: /(^\_[^\/]*\_)/, token: ["link"]},
|
||||
{regex: /(^\~[^\/]*\~)/, token: ["comment"]},
|
||||
{regex: /(^\=[^\/]*\=)/, token: ["comment"]},
|
||||
// special syntax
|
||||
//{regex: /(^[\*]+)(\s[TODO|NEXT|DONE|DEFERRED|REJECTED|WAITING]{2,})?(.*)/, token: ['comment', 'qualifier', 'header']}, // headline
|
||||
{regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links
|
||||
{regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox
|
||||
{regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments
|
||||
{regex: /:?[A-Z_]+\:.*/, token: "comment"}, // property drawers
|
||||
{regex: /(\#\+[A-Z_]*)(\:.*)/, token: ["keyword", 'qualifier']}, // environments
|
||||
{regex: /(CLOCK\:|SHEDULED\:)(\s.+)/, token: ["comment", "keyword"]}
|
||||
],
|
||||
env: [
|
||||
{regex: /.*?\#\+END_[A-Z]*/, token: "comment", next: "start"},
|
||||
{regex: /.*/, token: "comment"}
|
||||
]
|
||||
});
|
||||
CodeMirror.registerHelper("fold", "orgmode", function(cm, start) {
|
||||
// init
|
||||
const levelToMatch = headerLevel(start.line);
|
||||
|
||||
// no folding needed
|
||||
if(levelToMatch === null) return;
|
||||
|
||||
// find folding limits
|
||||
const lastLine = cm.lastLine();
|
||||
let end = start.line;
|
||||
while(end < lastLine){
|
||||
end += 1;
|
||||
let level = headerLevel(end);
|
||||
if(level && level <= levelToMatch) {
|
||||
end = end - 1;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
|
||||
to: CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
|
||||
function headerLevel(lineNo) {
|
||||
var line = cm.getLine(lineNo);
|
||||
var match = /^\*+/.exec(line);
|
||||
if(match && match.length === 1 && /header/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)))){
|
||||
return match[0].length;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
CodeMirror.registerGlobalHelper("fold", "drawer", function(mode) {
|
||||
return mode.name === 'orgmode' ? true : false;
|
||||
}, function(cm, start) {
|
||||
const drawer = isBeginningOfADrawer(start.line);
|
||||
if(drawer === false) return;
|
||||
|
||||
// find folding limits
|
||||
const lastLine = cm.lastLine();
|
||||
let end = start.line;
|
||||
while(end < lastLine){
|
||||
end += 1;
|
||||
if(isEndOfADrawer(end)){
|
||||
break
|
||||
}
|
||||
}
|
||||
return {
|
||||
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
|
||||
to: CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
|
||||
function isBeginningOfADrawer(lineNo) {
|
||||
var line = cm.getLine(lineNo);
|
||||
var match = /^\:.*\:$/.exec(line);
|
||||
if(match && match.length === 1 && match[0] !== ':END:'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isEndOfADrawer(lineNo){
|
||||
var line = cm.getLine(lineNo);
|
||||
return line.trim() === ':END:' ? true : false;
|
||||
}
|
||||
});
|
||||
|
||||
CodeMirror.afterInit = function(editor){
|
||||
let state = {
|
||||
stab: 'OVERVIEW'
|
||||
};
|
||||
editor.setOption("extraKeys", {
|
||||
"Tab": function(cm) {
|
||||
let pos = cm.getCursor();
|
||||
isFold(cm, pos) ? unfold(cm, pos) : fold(cm, pos);
|
||||
},
|
||||
"Shift-Tab": function(cm){
|
||||
if(state.stab === "SHOW_ALL"){
|
||||
// fold everything that can be fold
|
||||
state.stab = 'OVERVIEW';
|
||||
cm.operation(function() {
|
||||
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
|
||||
fold(cm, CodeMirror.Pos(i, 0));
|
||||
}
|
||||
});
|
||||
}else{
|
||||
// unfold all headers
|
||||
state.stab = 'SHOW_ALL';
|
||||
cm.operation(function() {
|
||||
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
|
||||
if(/header/.test(cm.getTokenTypeAt(CodeMirror.Pos(i, 0))) === true){
|
||||
unfold(cm, CodeMirror.Pos(i, 0))
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function fold(cm, start){
|
||||
cm.foldCode(start, null, "fold");
|
||||
}
|
||||
function unfold(cm, start){
|
||||
cm.foldCode(start, null, "unfold");
|
||||
}
|
||||
function isFold(cm, start){
|
||||
const line = start.line;
|
||||
const marks = cm.findMarks(CodeMirror.Pos(line, 0), CodeMirror.Pos(line + 1, 0));
|
||||
for (let i = 0; i < marks.length; ++i)
|
||||
if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
|
||||
return false;
|
||||
}
|
||||
editor.on('touchstart', function(cm, e){
|
||||
setTimeout(() => {
|
||||
isFold(cm, cm.getCursor()) ? unfold(cm, cm.getCursor()) : fold(cm, cm.getCursor())
|
||||
}, 150);
|
||||
});
|
||||
// fold everything except headers by default
|
||||
editor.operation(function() {
|
||||
for (var i = 0; i < editor.lineCount() ; i++) {
|
||||
if(/header/.test(editor.getTokenTypeAt(CodeMirror.Pos(i, 0))) === false){
|
||||
fold(editor, CodeMirror.Pos(i, 0));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function collapseWidget(){
|
||||
let $widget = document.createElement('span');
|
||||
$widget.appendChild(document.createTextNode('colapse'));
|
||||
return $widget;
|
||||
}
|
||||
function expandWidget(){
|
||||
let $widget = document.createElement('span');
|
||||
$widget.appendChild(document.createTextNode('expand'));
|
||||
return $widget;
|
||||
}
|
||||
}
|
||||
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/perl.js
Normal file
3
client/pages/viewerpage/editor/perl.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/perl/perl';
|
||||
CodeMirror.__mode = 'perl';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/php.js
Normal file
3
client/pages/viewerpage/editor/php.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/php/php';
|
||||
CodeMirror.__mode = 'php';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/python.js
Normal file
3
client/pages/viewerpage/editor/python.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/python/python';
|
||||
CodeMirror.__mode = 'python';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/r.js
Normal file
3
client/pages/viewerpage/editor/r.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/r/r';
|
||||
CodeMirror.__mode = 'r';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/ruby.js
Normal file
3
client/pages/viewerpage/editor/ruby.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/ruby/ruby';
|
||||
CodeMirror.__mode = 'ruby';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/rust.js
Normal file
3
client/pages/viewerpage/editor/rust.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/rust/rust';
|
||||
CodeMirror.__mode = 'rust';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/sass.js
Normal file
3
client/pages/viewerpage/editor/sass.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/sass/sass';
|
||||
CodeMirror.__mode = 'sass';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/shell.js
Normal file
3
client/pages/viewerpage/editor/shell.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/shell/shell';
|
||||
CodeMirror.__mode = 'shell';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/sql.js
Normal file
3
client/pages/viewerpage/editor/sql.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/sql/sql';
|
||||
CodeMirror.__mode = 'sql';
|
||||
export default CodeMirror;
|
||||
1
client/pages/viewerpage/editor/text.js
Normal file
1
client/pages/viewerpage/editor/text.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/xml.js
Normal file
3
client/pages/viewerpage/editor/xml.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/xml/xml';
|
||||
CodeMirror.__mode = 'xml';
|
||||
export default CodeMirror;
|
||||
3
client/pages/viewerpage/editor/yml.js
Normal file
3
client/pages/viewerpage/editor/yml.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import 'codemirror/mode/yaml/yaml';
|
||||
CodeMirror.__mode = 'yaml';
|
||||
export default CodeMirror;
|
||||
|
|
@ -18,7 +18,7 @@ module.exports.opener = function(file){
|
|||
return 'pdf';
|
||||
}else if(mime.split('/')[0] === 'image'){
|
||||
return 'image';
|
||||
}else if(['application/javascript', 'application/xml'].indexOf(mime) !== -1){
|
||||
}else if(['application/javascript', 'application/xml', 'application/x-perl'].indexOf(mime) !== -1){
|
||||
return 'editor';
|
||||
}else if(['audio/wav', 'audio/mp3', 'audio/flac'].indexOf(mime) !== -1){
|
||||
return 'audio';
|
||||
|
|
|
|||
Loading…
Reference in a new issue