You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
simplemde-markdown-editor/src/js/base.js

258 lines
6.6 KiB
JavaScript

/**
* @description :: Basic operation
*/
export default new class Base {
constructor (){}
getState (cm, pos = cm.getCursor("start")){
let stat = cm.getTokenAt(pos);
if(!stat.type) return {};
const typeMap = {
'strong': () => ({bold: true}),
'variable-2': () => ({[/^\s*\d+\.\s/.test(cm.getLine(pos.line))? 'ordered-list': 'unordered-list']: true}),
'atom': () => ({quote: true}),
'em': () => ({italic: true}),
'quote': () => ({quote: true}),
'strikethrough': () => ({strikethrough: true}),
'comment': () => ({code: true}),
'link': () => ({link: true}),
'tag': () => ({image: true}),
'_other': v => v.match(/^header(\-[1-6])?$/)? ({[v.replace("header", "heading")]: true}): ({})
}
const objectResult = stat.type.split(" ")
.map(v => typeMap[v]? typeMap[v](): typeMap['_other'](v))
.reduce((pv, cv) => Object.assign(pv, cv), {})
return objectResult;
}
toggleBlock (editor, type, start_chars, end_chars){
if(/editor-preview-active/.test(editor.codemirror.getWrapperElement().lastChild.className)) return;
end_chars = (typeof end_chars === "undefined") ? start_chars : end_chars;
let cm = editor.codemirror;
let stat = this.getState(cm);
let text;
let start = start_chars;
let end = end_chars;
let startPoint = cm.getCursor("start");
let endPoint = cm.getCursor("end");
if(stat[type]) {
text = cm.getLine(startPoint.line);
start = text.slice(0, startPoint.ch);
end = text.slice(startPoint.ch);
if(type == "bold") {
start = start.replace(/(\*\*|__)(?![\s\S]*(\*\*|__))/, "");
end = end.replace(/(\*\*|__)/, "");
} else if(type == "italic") {
start = start.replace(/(\*|_)(?![\s\S]*(\*|_))/, "");
end = end.replace(/(\*|_)/, "");
} else if(type == "strikethrough") {
start = start.replace(/(\*\*|~~)(?![\s\S]*(\*\*|~~))/, "");
end = end.replace(/(\*\*|~~)/, "");
}
cm.replaceRange(start + end, {
line: startPoint.line,
ch: 0
}, {
line: startPoint.line,
ch: 99999999999999
});
if(type == "bold" || type == "strikethrough") {
startPoint.ch -= 2;
if(startPoint !== endPoint) {
endPoint.ch -= 2;
}
} else if(type == "italic") {
startPoint.ch -= 1;
if(startPoint !== endPoint) {
endPoint.ch -= 1;
}
}
} else {
text = cm.getSelection();
if(type == "bold") {
text = text.split("**").join("");
text = text.split("__").join("");
} else if(type == "italic") {
text = text.split("*").join("");
text = text.split("_").join("");
} else if(type == "strikethrough") {
text = text.split("~~").join("");
}
cm.replaceSelection(start + text + end);
startPoint.ch += start_chars.length;
endPoint.ch = startPoint.ch + text.length;
}
cm.setSelection(startPoint, endPoint);
cm.focus();
}
replaceSelection (cm, active, startEnd, url){
if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
return;
let text;
let start = startEnd[0];
let end = startEnd[1];
let startPoint = cm.getCursor("start");
let endPoint = cm.getCursor("end");
if(url) {
end = end.replace("#url#", url);
}
if(active) {
text = cm.getLine(startPoint.line);
start = text.slice(0, startPoint.ch);
end = text.slice(startPoint.ch);
cm.replaceRange(start + end, {
line: startPoint.line,
ch: 0
});
} else {
text = cm.getSelection();
cm.replaceSelection(start + text + end);
startPoint.ch += start.length;
if(startPoint !== endPoint) {
endPoint.ch += start.length;
}
}
cm.setSelection(startPoint, endPoint);
cm.focus();
}
toggleHeading (cm, direction, size){
if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
return;
const startPoint = cm.getCursor("start");
const endPoint = cm.getCursor("end");
for(let i = startPoint.line; i <= endPoint.line; i++) {
(function(i) {
let text = cm.getLine(i);
let currHeadingLevel = text.search(/[^#]/);
if(direction !== undefined) {
if(currHeadingLevel <= 0) {
if(direction == "bigger") {
text = "###### " + text;
} else {
text = "# " + text;
}
} else if(currHeadingLevel == 6 && direction == "smaller") {
text = text.substr(7);
} else if(currHeadingLevel == 1 && direction == "bigger") {
text = text.substr(2);
} else {
if(direction == "bigger") {
text = text.substr(1);
} else {
text = "#" + text;
}
}
} else {
if(size == 1) {
if(currHeadingLevel <= 0) {
text = "# " + text;
} else if(currHeadingLevel == size) {
text = text.substr(currHeadingLevel + 1);
} else {
text = "# " + text.substr(currHeadingLevel + 1);
}
} else if(size == 2) {
if(currHeadingLevel <= 0) {
text = "## " + text;
} else if(currHeadingLevel == size) {
text = text.substr(currHeadingLevel + 1);
} else {
text = "## " + text.substr(currHeadingLevel + 1);
}
} else {
if(currHeadingLevel <= 0) {
text = "### " + text;
} else if(currHeadingLevel == size) {
text = text.substr(currHeadingLevel + 1);
} else {
text = "### " + text.substr(currHeadingLevel + 1);
}
}
}
cm.replaceRange(text, {
line: i,
ch: 0
}, {
line: i,
ch: 99999999999999
});
})(i);
}
cm.focus();
}
toggleLine (cm, name){
if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className)) return;
let stat = this.getState(cm);
const startPoint = cm.getCursor("start");
const endPoint = cm.getCursor("end");
const repl = {
"quote": /^(\s*)\>\s+/,
"unordered-list": /^(\s*)(\*|\-|\+)\s+/,
"ordered-list": /^(\s*)\d+\.\s+/
};
const map = {
"quote": "> ",
"unordered-list": "* ",
"ordered-list": "1. "
};
for(let i = startPoint.line; i <= endPoint.line; i++) {
(function(i) {
let text = cm.getLine(i);
if(stat[name]) {
text = text.replace(repl[name], "$1");
} else {
text = map[name] + text;
}
cm.replaceRange(text, {
line: i,
ch: 0
}, {
line: i,
ch: 99999999999999
});
})(i);
}
cm.focus();
}
cleanBlock (cm){
if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
return;
const startPoint = cm.getCursor("start");
const endPoint = cm.getCursor("end");
let text;
for(let line = startPoint.line; line <= endPoint.line; line++) {
text = cm.getLine(line);
text = text.replace(/^[ ]*([# ]+|\*|\-|[> ]+|[0-9]+(.|\)))[ ]*/, "");
cm.replaceRange(text, {
line: line,
ch: 0
}, {
line: line,
ch: 99999999999999
});
}
}
}