561 lines
16 KiB
JavaScript
Raw Normal View History

/*global require,module*/
2017-01-16 19:26:57 +08:00
import CodeMirror from 'codemirror'
import CodeMirrorSpellChecker from 'codemirror-spell-checker'
import marked from 'marked'
import 'codemirror/addon/edit/continuelist'
import 'codemirror/addon/display/fullscreen'
2017-01-17 15:16:52 +08:00
import 'codemirror/addon/mode/overlay'
2017-01-16 19:26:57 +08:00
import 'codemirror/addon/display/placeholder'
import 'codemirror/addon/selection/mark-selection'
import './codemirror/tablist'
import 'codemirror/mode/markdown/markdown'
import 'codemirror/mode/gfm/gfm'
import 'codemirror/mode/xml/xml'
2017-01-17 14:36:15 +08:00
import Action from './action'
import utils from './utils'
import base from './base'
import {
bindings,
shortcuts,
toolbarBuiltInButtons,
blockStyles,
insertTexts,
promptTexts
} from './metadata'
2015-06-19 15:37:06 -05:00
/**
* Create icon element for toolbar.
*/
2017-01-19 19:07:11 +08:00
const createIcon = (options = {}, enableTooltips = true, shortcuts) => {
2017-01-17 14:36:15 +08:00
let el = document.createElement("a");
2015-08-11 12:04:59 -05:00
if(options.title && enableTooltips) {
el.title = createTootlip(options.title, options.action, shortcuts);
2017-01-17 14:36:15 +08:00
if(utils.isMac()) {
el.title = el.title.replace("Ctrl", "⌘");
el.title = el.title.replace("Alt", "⌥");
}
2015-06-19 15:37:06 -05:00
}
el.tabIndex = -1;
el.className = options.className;
return el;
2015-06-19 15:37:06 -05:00
}
2017-01-17 14:36:15 +08:00
const createSep = () => {
let el = document.createElement("i");
el.className = "separator";
el.innerHTML = "|";
return el;
2015-06-19 15:37:06 -05:00
}
2017-01-17 14:36:15 +08:00
const createTootlip = (title, action, shortcuts) => {
2017-01-19 19:05:03 +08:00
if(!action) return title
2017-01-22 16:19:52 +08:00
const actionName = bindings.find(bindingName => bindingName === action)
if(!shortcuts[actionName]) return title
2017-01-22 15:56:28 +08:00
return `${title} ( ${utils.fixShortcut(shortcuts[actionName])} )`
}
2015-06-19 15:37:06 -05:00
/**
2017-01-17 14:36:15 +08:00
* Interface of SimpleMDE.
2015-06-19 15:37:06 -05:00
*/
2017-01-17 16:49:47 +08:00
class SimpleMDE extends Action {
2017-01-17 14:36:15 +08:00
constructor(options = {}) {
2017-01-17 15:16:52 +08:00
super()
2017-01-17 17:19:36 +08:00
2017-01-17 14:36:15 +08:00
// Used later to refer to it"s parent
options.parent = this;
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Check if Font Awesome needs to be auto downloaded
2017-01-18 17:07:03 +08:00
utils.downloadFA(options)
2015-08-12 17:23:09 +01:00
2017-01-17 14:36:15 +08:00
// Find the textarea to use
2017-01-19 19:05:03 +08:00
if(options.element) this.element = options.element;
if(options.element === null) {
2017-01-17 14:36:15 +08:00
// This means that the element option was specified, but no element was found
2017-01-18 17:47:53 +08:00
return console.log("SimpleMDE: Error. No element was found.");
2017-01-17 14:36:15 +08:00
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Handle toolbar
if(options.toolbar === undefined) {
// Initialize
options.toolbar = [];
2017-01-17 14:36:15 +08:00
// Loop over the built in buttons, to get the preferred order
2017-01-20 16:01:06 +08:00
for(const key in toolbarBuiltInButtons) {
2017-01-17 14:36:15 +08:00
if(toolbarBuiltInButtons.hasOwnProperty(key)) {
if(key.indexOf("separator-") != -1) {
options.toolbar.push("|");
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
if(toolbarBuiltInButtons[key].default === true || (options.showIcons && options.showIcons.constructor === Array && options.showIcons.indexOf(key) != -1)) {
options.toolbar.push(key);
}
}
}
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Handle status bar
if(!options.hasOwnProperty("status")) {
options.status = ["autosave", "lines", "words", "cursor"];
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Add default preview rendering function
if(!options.previewRender) {
2017-01-17 17:19:36 +08:00
// Note: "this" refers to the options object
2017-01-17 17:24:23 +08:00
options.previewRender = plainText => options.parent.markdown(plainText)
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Set default options for parsing config
options.parsingConfig = Object.assign({
highlightFormatting: true // needed for toggleCodeBlock to detect types of code
}, options.parsingConfig || {});
2015-07-14 12:34:22 -05:00
2017-01-17 14:36:15 +08:00
// Merging the insertTexts, with the given options
options.insertTexts = Object.assign({}, insertTexts, options.insertTexts || {});
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Merging the promptTexts, with the given options
options.promptTexts = promptTexts;
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// Merging the blockStyles, with the given options
options.blockStyles = Object.assign({}, blockStyles, options.blockStyles || {});
2015-09-01 20:26:52 -05:00
2017-01-17 14:36:15 +08:00
// Merging the shortcuts, with the given options
options.shortcuts = Object.assign({}, shortcuts, options.shortcuts || {});
2015-09-01 01:40:33 -05:00
2017-01-17 14:36:15 +08:00
// Change unique_id to uniqueId for backwards compatibility
if(options.autosave != undefined && options.autosave.unique_id != undefined && options.autosave.unique_id != "")
options.autosave.uniqueId = options.autosave.unique_id;
2017-01-17 14:36:15 +08:00
// Update this options
this.options = options;
2015-09-01 01:40:33 -05:00
2017-01-17 14:36:15 +08:00
// Auto render
this.render();
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
// The codemirror component is only available after rendering
// so, the setter for the initialValue can only run after
// the element has been rendered
if(options.initialValue && (!this.options.autosave || this.options.autosave.foundSavedValue !== true)) {
this.value(options.initialValue);
}
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
/**
* Default markdown render.
*/
markdown(text) {
if(marked) {
// Update options
const update = this.options && this.options.renderingConfig && this.options.renderingConfig.singleLineBreaks === false
2017-01-19 18:59:06 +08:00
const highlight = this.options && this.options.renderingConfig && this.options.renderingConfig.codeSyntaxHighlighting === true && window.hljs
2015-09-01 20:26:52 -05:00
2017-01-17 14:36:15 +08:00
// Set options
2017-01-19 18:59:06 +08:00
marked.setOptions({
breaks: !update,
highlight: highlight ? code => window.hljs.highlightAuto(code).value : undefined
});
2017-01-17 14:36:15 +08:00
return marked(text);
}
};
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
/**
* Render editor to the given element.
*/
render(el = this.element || document.getElementsByTagName("textarea")[0]) {
2017-01-17 17:19:36 +08:00
// Already rendered.
if(this._rendered && this._rendered === el) return;
2017-01-17 14:36:15 +08:00
this.element = el;
const options = this.options;
const self = this;
let keyMaps = {};
2017-01-20 16:01:06 +08:00
for(const key in options.shortcuts) {
2017-01-17 14:36:15 +08:00
// null stands for "do not bind this command"
2017-01-22 16:19:52 +08:00
const isExistent = bindings.find(bindingName => bindingName === key)
2017-01-22 15:53:25 +08:00
if(options.shortcuts[key] !== null && isExistent) {
2017-01-22 16:19:52 +08:00
keyMaps[utils.fixShortcut(options.shortcuts[key])] = () => super[key](this);
}
}
2017-01-17 14:36:15 +08:00
keyMaps["Enter"] = "newlineAndIndentContinueMarkdownList";
keyMaps["Tab"] = "tabAndIndentMarkdownList";
keyMaps["Shift-Tab"] = "shiftTabAndUnindentMarkdownList";
2017-01-22 15:28:46 +08:00
keyMaps["Esc"] = cm => cm.getOption("fullScreen") && super.toggleFullScreen(self);
2016-01-08 14:44:43 +01:00
2017-01-17 17:19:36 +08:00
document.addEventListener("keydown", (e = window.event) => {
2017-01-17 14:36:15 +08:00
if(e.keyCode == 27) {
2017-01-22 15:28:46 +08:00
if(self.codemirror.getOption("fullScreen")) super.toggleFullScreen(self);
2017-01-17 14:36:15 +08:00
}
}, false);
2016-01-08 14:44:43 +01:00
2017-01-17 14:36:15 +08:00
let mode, backdrop;
if(options.spellChecker !== false) {
mode = "spell-checker";
backdrop = options.parsingConfig;
backdrop.name = "gfm";
backdrop.gitHubSpice = false;
2016-01-08 14:44:43 +01:00
2017-01-17 14:36:15 +08:00
CodeMirrorSpellChecker({
codeMirrorInstance: CodeMirror
});
} else {
mode = options.parsingConfig;
mode.name = "gfm";
mode.gitHubSpice = false;
}
this.codemirror = CodeMirror.fromTextArea(el, {
mode: mode,
backdrop: backdrop,
theme: "paper",
tabSize: (options.tabSize != undefined) ? options.tabSize : 2,
indentUnit: (options.tabSize != undefined) ? options.tabSize : 2,
indentWithTabs: !(options.indentWithTabs === false),
lineNumbers: false,
autofocus: options.autofocus === true,
extraKeys: keyMaps,
lineWrapping: !(options.lineWrapping === false),
allowDropFileTypes: ["text/plain"],
placeholder: options.placeholder || el.getAttribute("placeholder") || "",
styleSelectedText: (options.styleSelectedText != undefined) ? options.styleSelectedText : true
2016-01-08 14:44:43 +01:00
});
2017-01-17 14:36:15 +08:00
if(options.forceSync === true) {
this.codemirror.on("change", () => this.codemirror.save());
2015-11-03 10:16:08 -06:00
}
2017-01-17 14:36:15 +08:00
this.gui = {};
2017-01-17 14:36:15 +08:00
if(options.toolbar !== false) {
this.gui.toolbar = this.createToolbar();
}
if(options.status !== false) {
this.gui.statusbar = this.createStatusbar();
}
if(options.autosave != undefined && options.autosave.enabled === true) {
this.autosave();
}
2015-06-19 15:37:06 -05:00
2017-01-17 14:36:15 +08:00
this.gui.sideBySide = this.createSideBySide();
this._rendered = this.element;
2015-09-03 18:01:47 -05:00
2017-01-17 14:36:15 +08:00
// Fixes CodeMirror bug (#344)
setTimeout(() => {
this.codemirror.refresh();
}, 0);
2017-01-17 14:36:15 +08:00
};
2015-09-25 15:21:39 -05:00
2015-09-19 20:42:20 -05:00
2017-01-17 14:36:15 +08:00
autosave() {
2017-01-20 15:19:38 +08:00
if(!utils.isLocalStorageAvailable()) {
return console.log("SimpleMDE: localStorage not available, cannot autosave")
}
const simplemde = this;
2015-06-19 15:09:28 -05:00
2017-01-20 15:19:38 +08:00
if(this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
return console.log("SimpleMDE: You must set a uniqueId to use the autosave feature");
}
2017-01-20 15:19:38 +08:00
if(simplemde.element.form != null && simplemde.element.form != undefined) {
simplemde.element.form.addEventListener("submit", () => {
localStorage.removeItem("smde_" + simplemde.options.autosave.uniqueId);
});
}
2017-01-20 15:19:38 +08:00
if(this.options.autosave.loaded !== true) {
if(typeof localStorage.getItem("smde_" + this.options.autosave.uniqueId) == "string" && localStorage.getItem("smde_" + this.options.autosave.uniqueId) != "") {
this.codemirror.setValue(localStorage.getItem("smde_" + this.options.autosave.uniqueId));
this.options.autosave.foundSavedValue = true;
}
2015-06-19 15:09:28 -05:00
2017-01-20 15:19:38 +08:00
this.options.autosave.loaded = true;
}
2017-01-17 14:36:15 +08:00
2017-01-20 15:19:38 +08:00
localStorage.setItem("smde_" + this.options.autosave.uniqueId, simplemde.value());
2017-01-18 17:47:53 +08:00
2017-01-20 15:19:38 +08:00
let el = document.getElementById("autosaved");
if(el != null && el != undefined && el != "") {
const d = new Date();
const hh = d.getHours();
const mm = d.getMinutes();
2015-09-25 17:10:10 -05:00
2017-01-20 15:19:38 +08:00
// date format, output example: Autosaved: 5:45 pm
const dd = hh >= 12 ? 'pm' : 'am'
const h = hh == 0 ? 12 : hh > 12 ? hh - 12 : hh;
const m = mm < 10 ? `0${mm}` : mm;
2015-09-25 17:10:10 -05:00
2017-01-20 15:19:38 +08:00
el.innerHTML = `Autosaved: ${h}:${m} ${dd}`;
2015-08-31 23:53:32 -05:00
}
2017-01-20 15:19:38 +08:00
this.autosaveTimeoutId = setTimeout(() => {
simplemde.autosave();
}, this.options.autosave.delay || 10000);
2017-01-17 14:36:15 +08:00
};
2015-09-25 17:10:10 -05:00
2017-01-17 14:36:15 +08:00
clearAutosavedValue() {
if(utils.isLocalStorageAvailable()) {
if(this.options.autosave == undefined || this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
2017-01-17 17:19:36 +08:00
return console.log("SimpleMDE: You must set a uniqueId to clear the autosave value");
2017-01-17 14:36:15 +08:00
}
localStorage.removeItem("smde_" + this.options.autosave.uniqueId);
} else {
console.log("SimpleMDE: localStorage not available, cannot autosave");
}
};
2017-01-17 14:36:15 +08:00
createSideBySide() {
let cm = this.codemirror;
let wrapper = cm.getWrapperElement();
let preview = wrapper.nextSibling;
2017-01-20 15:15:50 +08:00
const notCreate = !preview || !/editor-preview-side/.test(preview.className)
2017-01-20 15:15:50 +08:00
if(notCreate) {
2017-01-17 14:36:15 +08:00
preview = document.createElement("div");
preview.className = "editor-preview-side";
wrapper.parentNode.insertBefore(preview, wrapper.nextSibling);
}
2017-01-17 14:36:15 +08:00
// Syncs scroll editor -> preview
let cScroll = false;
let pScroll = false;
2017-01-17 17:19:36 +08:00
cm.on("scroll", v => {
if(cScroll) return cScroll = false;
2017-01-17 14:36:15 +08:00
pScroll = true;
2017-01-20 15:15:50 +08:00
const height = v.getScrollInfo().height - v.getScrollInfo().clientHeight;
const ratio = parseFloat(v.getScrollInfo().top) / height;
2017-01-17 14:36:15 +08:00
preview.scrollTop = (preview.scrollHeight - preview.clientHeight) * ratio;
});
2017-01-17 14:36:15 +08:00
// Syncs scroll preview -> editor
2017-01-17 17:19:36 +08:00
preview.onscroll = () => {
if(pScroll) return pScroll = false;
2017-01-17 14:36:15 +08:00
cScroll = true;
2017-01-20 15:15:50 +08:00
const height = preview.scrollHeight - preview.clientHeight;
const ratio = parseFloat(preview.scrollTop) / height;
const move = (cm.getScrollInfo().height - cm.getScrollInfo().clientHeight) * ratio;
2017-01-17 14:36:15 +08:00
cm.scrollTo(0, move);
};
return preview;
};
2017-01-19 19:57:06 +08:00
createToolbar(items = this.options.toolbar) {
2017-01-17 17:19:36 +08:00
if(!items || items.length === 0) return;
2017-01-19 19:57:06 +08:00
const isExistent = value => toolbarBuiltInButtons[value] != undefined
this.toolbar = items.map(v => isExistent(v) ? toolbarBuiltInButtons[v] : v)
2015-09-01 20:26:52 -05:00
2017-01-17 14:36:15 +08:00
let bar = document.createElement("div");
let toolbarData = {};
2017-01-19 19:57:06 +08:00
const nextLoop = (v, i) => {
const name = v.name
if(name == "guide" && this.options.toolbarGuideIcon === false) return true;
if(this.options.hideIcons && this.options.hideIcons.indexOf(name) != -1) return true;
2016-03-14 20:59:59 -05:00
2017-01-17 14:36:15 +08:00
// Fullscreen does not work well on mobile devices (even tablets)
// In the future, hopefully this can be resolved
2017-01-19 19:57:06 +08:00
if((name == "fullscreen" || name == "side-by-side") && utils.isMobile()) return true;
2017-01-17 14:36:15 +08:00
// Don't include trailing separators
2017-01-19 19:57:06 +08:00
if(v === "|") {
let nonSeparatorIconsFollow = true;
2017-01-22 13:04:38 +08:00
for(let x = (i + 1); x < this.toolbar.length; x++) {
2017-01-19 19:57:06 +08:00
if(this.toolbar[x] !== "|" && (!this.options.hideIcons || this.options.hideIcons.indexOf(name) == -1)) {
nonSeparatorIconsFollow = false;
2017-01-17 14:36:15 +08:00
}
}
2017-01-19 19:57:06 +08:00
if(nonSeparatorIconsFollow) return true
}
2017-01-19 19:57:06 +08:00
return false
}
const createElement = v => {
if(v === "|") return createSep();
return createIcon(v, this.options.toolbarTips, this.options.shortcuts)
}
2017-01-22 15:28:46 +08:00
this.toolbar.forEach((v, i) => {
if(nextLoop(v, i)) return;
2017-01-17 14:36:15 +08:00
// Create the icon and append to the toolbar
2017-01-22 15:28:46 +08:00
const el = createElement(v)
const isCustomMethods = typeof v.action === "function"
2017-01-19 19:57:06 +08:00
// bind events, special for info
if(v.action) {
2017-01-22 15:28:46 +08:00
el.onclick = e => {
e.preventDefault();
isCustomMethods ? v.action(this) : super[v.action](this)
};
2017-01-19 19:57:06 +08:00
}
2017-01-19 19:57:06 +08:00
toolbarData[v.name || v] = el;
bar.appendChild(el);
})
this.toolbarElements = toolbarData;
this.codemirror.on("cursorActivity", () => {
2017-01-22 15:28:46 +08:00
const stat = base.getState(this.codemirror);
2017-01-20 16:01:06 +08:00
for(const key in toolbarData) {
2017-01-22 15:28:46 +08:00
let el = toolbarData[key];
if(stat[key]) {
el.className += " active";
} else if(key != "fullscreen" && key != "side-by-side") {
el.className = el.className.replace(/\s*active\s*/g, "");
}
2017-01-17 14:36:15 +08:00
}
});
2015-09-01 01:40:33 -05:00
2017-01-19 19:57:06 +08:00
const cmWrapper = this.codemirror.getWrapperElement();
bar.className = "editor-toolbar";
2017-01-17 14:36:15 +08:00
cmWrapper.parentNode.insertBefore(bar, cmWrapper);
return bar;
2015-09-01 01:40:33 -05:00
};
2017-01-19 18:28:25 +08:00
createStatusbar(status = this.options.status) {
2017-01-17 14:36:15 +08:00
// Make sure the status variable is valid
2017-01-17 17:19:36 +08:00
if(!status || status.length === 0) return;
2016-01-22 13:16:54 -06:00
2017-01-19 18:28:25 +08:00
const options = this.options;
const cm = this.codemirror;
2017-01-17 14:36:15 +08:00
// Set up the built-in items
let items = [];
2017-01-19 18:28:25 +08:00
let bar = document.createElement("div");
bar.className = "editor-statusbar";
2016-01-22 13:16:54 -06:00
2017-01-19 18:28:25 +08:00
const statusFuncMap = {
words: {
defaultValue: el => el.innerHTML = utils.wordCount(cm.getValue()),
onUpdate: el => el.innerHTML = utils.wordCount(cm.getValue())
},
lines: {
defaultValue: el => el.innerHTML = cm.lineCount(),
onUpdate: el => el.innerHTML = cm.lineCount()
},
cursor: {
defaultValue: el => el.innerHTML = "0:0",
onUpdate: el => el.innerHTML = cm.getCursor().line + ":" + cm.getCursor().ch
},
autosave: {
defaultValue: el => {
if(options.autosave != undefined && options.autosave.enabled === true) {
el.setAttribute("id", "autosaved");
}
},
onUpdate: undefined
}
}
2016-01-22 13:16:54 -06:00
2017-01-19 18:28:25 +08:00
status.forEach(v => {
if(typeof v === "object") {
2017-01-17 14:36:15 +08:00
items.push({
2017-01-19 18:28:25 +08:00
className: v.className,
defaultValue: v.defaultValue,
onUpdate: v.onUpdate
})
}
if(statusFuncMap[v]) {
2017-01-17 14:36:15 +08:00
items.push({
2017-01-19 18:28:25 +08:00
className: v.toString(),
defaultValue: statusFuncMap[v].defaultValue,
onUpdate: statusFuncMap[v].onUpdate
})
2017-01-17 14:36:15 +08:00
}
2017-01-19 18:28:25 +08:00
})
2015-06-19 15:09:28 -05:00
2017-01-17 14:36:15 +08:00
// Create element for the status bar
2017-01-19 18:28:25 +08:00
const createStatusElement = className => {
2017-01-17 14:36:15 +08:00
let el = document.createElement("span");
2017-01-19 18:28:25 +08:00
el.className = className
return el
}
items.forEach(v => {
const el = createStatusElement(v.className)
if(typeof v.defaultValue === "function") v.defaultValue(el)
if(typeof v.onUpdate === "function") {
2017-01-17 14:36:15 +08:00
// Create a closure around the span of the current action, then execute the onUpdate handler
2017-01-19 18:28:25 +08:00
this.codemirror.on("update", () => v.onUpdate(el));
2016-01-22 13:02:39 -06:00
}
2017-01-17 14:36:15 +08:00
// Append the item to the status bar
bar.appendChild(el);
2017-01-19 18:28:25 +08:00
})
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
// Insert the status bar into the DOM
let cmWrapper = this.codemirror.getWrapperElement();
cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
return bar;
};
2017-01-17 14:36:15 +08:00
/**
* Get or set the text content.
*/
value(val) {
2017-01-17 17:19:36 +08:00
if(val === undefined) return this.codemirror.getValue();
this.codemirror.getDoc().setValue(val);
return this;
2017-01-17 14:36:15 +08:00
};
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
/**
* Bind instance methods for exports.
*/
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
isPreviewActive() {
const cm = this.codemirror;
const wrapper = cm.getWrapperElement();
const preview = wrapper.lastChild;
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
return /editor-preview-active/.test(preview.className);
};
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
isSideBySideActive() {
const cm = this.codemirror;
const wrapper = cm.getWrapperElement();
const preview = wrapper.nextSibling;
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
return /editor-preview-active-side/.test(preview.className);
};
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
isFullscreenActive() {
const cm = this.codemirror;
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
return cm.getOption("fullScreen");
};
2017-01-17 14:36:15 +08:00
getState() {
const cm = this.codemirror;
2016-01-22 13:02:39 -06:00
2017-01-17 14:36:15 +08:00
return base.getState(cm);
};
2015-06-19 15:09:28 -05:00
2017-01-17 14:36:15 +08:00
toTextArea() {
const cm = this.codemirror;
const wrapper = cm.getWrapperElement();
2015-06-19 15:09:28 -05:00
2017-01-17 14:36:15 +08:00
if(wrapper.parentNode) {
if(this.gui.toolbar) {
wrapper.parentNode.removeChild(this.gui.toolbar);
}
if(this.gui.statusbar) {
wrapper.parentNode.removeChild(this.gui.statusbar);
}
if(this.gui.sideBySide) {
wrapper.parentNode.removeChild(this.gui.sideBySide);
}
}
2015-06-19 15:09:28 -05:00
2017-01-17 14:36:15 +08:00
cm.toTextArea();
2015-06-19 15:09:28 -05:00
2017-01-17 14:36:15 +08:00
if(this.autosaveTimeoutId) {
clearTimeout(this.autosaveTimeoutId);
this.autosaveTimeoutId = undefined;
this.clearAutosavedValue();
2016-03-31 13:34:12 +03:00
}
2017-01-17 14:36:15 +08:00
};
2017-01-17 16:49:47 +08:00
}
export default SimpleMDE