var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; navigator.saveBlob = navigator.saveBlob || navigator.msSaveBlob || navigator.mozSaveBlob || navigator.webkitSaveBlob; window.saveAs = window.saveAs || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs; // Because highlight.js is a bit awkward at times var languageOverrides = { js: 'javascript', html: 'xml' }; var livestyles; emojify.setConfig({ img_dir: 'emoji' }); var md = markdownit({ html: true, highlight: function(code, lang) { if (languageOverrides[lang]) lang = languageOverrides[lang]; if (lang && hljs.getLanguage(lang)) { try { return hljs.highlight(lang, code).value; } catch (e) {} } return ''; } }) .use(markdownitFootnote); var hashto; function update(e) { setOutput(e.getValue()); //If a title is added to the document it will be the new document.title, otherwise use default var headerElements = document.querySelectorAll('h1'); if (headerElements.length > 0 && headerElements[0].textContent.length > 0) { title = headerElements[0].textContent; } else { title = 'Markdown Editor' } //To avoid to much title changing we check if is not the same as before oldTitle = document.title; if (oldTitle != title) { oldTitle = title; document.title = title; } //clearTimeout(hashto); //hashto = setTimeout(updateHash, 1000); } /* This function is used to check for task list notation. If regex matches the string to task-list markdown format, then the task-list is rendered to its correct form. User: @austinmm */ var render_tasklist = function(str){ // Checked task-list box match if(str.match(/
  • \[x\]\s+\w+/gi)){ str = str.replace(/(\[x\]\s+)(\w+)/gi, `$1 style="list-style-type: none;"> $3`); } // Unchecked task-list box match if (str.match(/
  • \[ \]\s+\w+/gi)){ str = str.replace(/(\[ \]\s+)(\w+)/gi, `$1 style="list-style-type: none;"> $3`); } return str } function setOutput(val) { val = val.replace(/((.*?\n)*?.*?)<\/equation>/ig, function(a, b) { return ''; }); var out = document.getElementById('out'); var old = out.cloneNode(true); out.innerHTML = md.render(val); emojify.run(out); console.log(out.innerHTML); // Checks if there are any task-list present in out.innerHTML out.innerHTML = render_tasklist(out.innerHTML); var allold = old.getElementsByTagName("*"); if (allold === undefined) return; var allnew = out.getElementsByTagName("*"); if (allnew === undefined) return; for (var i = 0, max = Math.min(allold.length, allnew.length); i < max; i++) { if (!allold[i].isEqualNode(allnew[i])) { out.scrollTop = allnew[i].offsetTop; return; } } } CodeMirrorSpellChecker({ codeMirrorInstance: CodeMirror, }); var editor = CodeMirror.fromTextArea(document.getElementById('code'), { mode: "spell-checker", backdrop: "gfm", lineNumbers: false, matchBrackets: true, lineWrapping: true, theme: 'base16-light', extraKeys: { "Enter": "newlineAndIndentContinueMarkdownList" } }); editor.on('change', update); function selectionChanger(selection,operator,endoperator){ if(selection == ""){ return operator; } if(!endoperator){ endoperator = operator } var isApplied = selection.slice(0, 2) === operator && selection.slice(-2) === endoperator; var finaltext = isApplied ? selection.slice(2, -2) : operator + selection + endoperator; return finaltext; } editor.addKeyMap({ // bold 'Ctrl-B': function(cm) { cm.replaceSelection(selectionChanger(cm.getSelection(),'**')); }, // italic 'Ctrl-I': function(cm) { cm.replaceSelection(selectionChanger(cm.getSelection(),'_')); }, // code 'Ctrl-K': function(cm) { cm.replaceSelection(selectionChanger(cm.getSelection(),'`')); }, // keyboard shortcut 'Ctrl-L': function(cm) { cm.replaceSelection(selectionChanger(cm.getSelection(),'','')); } }); document.addEventListener('drop', function(e) { e.preventDefault(); e.stopPropagation(); var reader = new FileReader(); reader.onload = function(e) { editor.setValue(e.target.result); }; reader.readAsText(e.dataTransfer.files[0]); }, false); //Print the document named as the document title encoded to avoid strange chars and spaces function saveAsMarkdown() { save(editor.getValue(), document.title.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/\s]/gi, '') + ".md"); } //Print the document named as the document title encoded to avoid strange chars and spaces function saveAsHtml() { save(document.getElementById('out').innerHTML, document.title.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/\s]/gi, '') + ".html"); } document.getElementById('saveas-markdown').addEventListener('click', function() { saveAsMarkdown(); hideMenu(); }); document.getElementById('saveas-html').addEventListener('click', function() { saveAsHtml(); hideMenu(); }); function save(code, name) { var blob = new Blob([code], { type: 'text/plain' }); if (window.saveAs) { window.saveAs(blob, name); } else if (navigator.saveBlob) { navigator.saveBlob(blob, name); } else { url = URL.createObjectURL(blob); var link = document.createElement("a"); link.setAttribute("href", url); link.setAttribute("download", name); var event = document.createEvent('MouseEvents'); event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); link.dispatchEvent(event); } } var menuVisible = false; var menu = document.getElementById('menu'); function showMenu() { menuVisible = true; menu.style.display = 'block'; } function hideMenu() { menuVisible = false; menu.style.display = 'none'; } function openFile(evt) { if (window.File && window.FileReader && window.FileList && window.Blob) { var files = evt.target.files; console.log(files); var reader = new FileReader(); reader.onload = function(file) { console.log(file.target.result); editor.setValue(file.target.result); return true; }; reader.readAsText(files[0]); } else { alert('The File APIs are not fully supported in this browser.'); } } document.getElementById('close-menu').addEventListener('click', function() { hideMenu(); }); document.addEventListener('keydown', function(e) { if (e.keyCode == 83 && (e.ctrlKey || e.metaKey)) { if ( localStorage.getItem('content') == editor.getValue() ) { e.preventDefault(); return false; } e.shiftKey ? showMenu() : saveInBrowser(); e.preventDefault(); return false; } if (e.keyCode === 27 && menuVisible) { hideMenu(); e.preventDefault(); return false; } }); function clearEditor() { editor.setValue(""); } function saveInBrowser() { var text = editor.getValue(); if (localStorage.getItem('content')) { swal({ title: "Existing Data Detected", text: "You will overwrite the data previously saved!", type: "warning", showCancelButton: true, confirmButtonColor: "#DD6B55", confirmButtonText: "Yes, overwrite!", closeOnConfirm: false }, function() { localStorage.setItem('content', text); swal("Saved", "Your Document has been saved.", "success"); }); } else { localStorage.setItem('content', text); swal("Saved", "Your Document has been saved.", "success"); } console.log("Saved"); } function toggleNightMode(button) { button.classList.toggle('selected'); document.getElementById('toplevel').classList.toggle('nightmode'); } function toggleReadMode(button) { button.classList.toggle('selected'); document.getElementById('out').classList.toggle('focused'); document.getElementById('in').classList.toggle('hidden'); } function toggleSpellCheck(button) { button.classList.toggle('selected'); document.body.classList.toggle('no-spellcheck'); } function updateHash() { window.location.hash = btoa( // base64 so url-safe RawDeflate.deflate( // gzip unescape(encodeURIComponent( // convert to utf8 editor.getValue() )) ) ); } function processQueryParams() { var params = window.location.search.split('?')[1]; if (window.location.hash) { document.getElementById('readbutton').click(); // Show reading view } if (params) { var obj = {}; params.split('&').forEach(function(elem) { obj[elem.split('=')[0]] = elem.split('=')[1]; }); if (obj.reading === 'false') { document.getElementById('readbutton').click(); // Hide reading view } if (obj.dark === 'true') { document.getElementById('nightbutton').click(); // Show night view } } } function start() { processQueryParams(); if (window.location.hash) { var h = window.location.hash.replace(/^#/, ''); if (h.slice(0, 5) == 'view:') { setOutput(decodeURIComponent(escape(RawDeflate.inflate(atob(h.slice(5)))))); document.body.className = 'view'; } else { editor.setValue( decodeURIComponent(escape( RawDeflate.inflate( atob( h ) ) )) ); } } else if (localStorage.getItem('content')) { editor.setValue(localStorage.getItem('content')); } update(editor); editor.focus(); document.getElementById('fileInput').addEventListener('change', openFile, false); } window.addEventListener("beforeunload", function (e) { if (!editor.getValue() || editor.getValue() == localStorage.getItem('content')) { return; } var confirmationMessage = 'It looks like you have been editing something. ' + 'If you leave before saving, your changes will be lost.'; (e || window.event).returnValue = confirmationMessage; //Gecko + IE return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. }); start();