You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
16 KiB
358 lines
16 KiB
<!-- |
|
# |
|
# Writing is an in-browser text editor, supporting LaTeX (MathJax) and Markdown, designed to be lightweight and, unlike some other similar solutions, |
|
# fast to display (no delay when writing, no flickering when writing math), as close as possible to the math.stackexchange.com editor. |
|
# |
|
# author: Joseph Ernest (twitter: @JosephErnest) |
|
# url: https://github.com/josephernest/writing |
|
# license: MIT license |
|
# based on: Pagedown (https://code.google.com/archive/p/pagedown/, https://github.com/balpha/pagedown) |
|
# Pagedown Extra (https://github.com/jmcmanus/pagedown-extra) |
|
# MathJax (https://www.mathjax.org/) |
|
# StackOverflow's editor (https://gist.github.com/gdalgas/a652bce3a173ddc59f66) |
|
# |
|
--> |
|
|
|
<!DOCTYPE html> |
|
<html class="fixedheight texroman"> |
|
<head> |
|
<link rel="icon" href="/favicon.ico" /> |
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
|
<title>Editor</title> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
<style type="text/css"> |
|
@font-face { font-family: texroman; src: url(cmunrm.otf); font-weight: 400; font-style: normal; font-stretch: normal; } |
|
@font-face { font-family: texroman; src: url(cmunrb.otf); font-weight: 700; font-style: normal; font-stretch: normal; } |
|
|
|
html { font-family: sans-serif; } |
|
* { margin: 0; padding: 0; border: 0; outline: 0; } |
|
.texroman { font-family: texroman !important; } |
|
.unselectable { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } |
|
.fixedheight { height: 100%; } |
|
.column { padding: 20px; } |
|
#wmd-button-bar { display: none; } |
|
#wmd-input { float: left; box-sizing: border-box; width: 50%; resize: horizontal; font-size: 14px; border-right: 1px solid #ddd; height: 100%; overflow: y-scroll; } |
|
#wmd-preview { overflow-y: auto; overflow-x: hidden; font-size: 15px; height: 100%; box-sizing: border-box; min-height: 100vh; } |
|
#wmd-preview li { margin-left: 20px; } |
|
#wmd-preview code, #wmd-input { font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif; } |
|
#wmd-preview p code, #wmd-preview li code { background-color: #f5f5f5; white-space: pre-wrap; padding: 3px 5px; font-size: 13px; } |
|
#wmd-preview pre { background-color: #f5f5f5; padding: 5px; margin: 0.5em 0 1em; overflow-x: auto; word-wrap: normal; font-size: 13px; } |
|
#wmd-preview blockquote { background-color: #defcff; padding: 10px; margin: 0.5em 0 1em; overflow-x: auto; word-wrap: normal; border-left: 2px solid #0ae2f5; } |
|
#wmd-preview blockquote p { margin-bottom: 0; } |
|
#wmd-preview hr { background-color: #ddd; color: #ddd; height: 1px; margin-bottom: 15px; margin-top: 15px; } |
|
#wmd-preview h1 { margin-bottom: 0.5em; font-size: 1.4em; } |
|
#wmd-preview h2 { margin-bottom: 0.5em; font-size: 1.2em; } |
|
#wmd-preview h3 { margin-bottom: 0.5em; font-size: 1em; } |
|
#wmd-preview p { margin-bottom: 1em; line-height: 1.25; } |
|
#wmd-preview ul { margin-bottom: 1.5em; line-height: 1.25; } |
|
#wmd-preview img { max-width: 100%; max-height: 100%; } |
|
#wmd-preview table { display: block; width: 100%; overflow: auto; border-collapse: collapse; margin-bottom: 0.5em; } |
|
#wmd-preview table th { font-weight: bold; } |
|
#wmd-preview table th, #wmd-preview table td { padding: 6px 13px; border: 1px solid #ddd; } |
|
#wmd-preview table tr { background-color: #fff; border-top: 1px solid #ccc; } |
|
#wmd-preview table tr:nth-child(2n) { background-color: #f8f8f8; } |
|
#wmd-preview a { text-decoration: none; color: #07c; } |
|
#wmd-preview .pagebreak { border-bottom: 1px dashed #eee; padding-top: 20px; margin-bottom: 30px; } |
|
#helpicon { position: absolute; bottom: 0; left: 0; margin: 5px; color: #ccc; cursor: pointer; font-family: sans-serif; font-size: 15px; } |
|
#help { display: none; position: fixed; top: 10%; height: 70%; left: 25%; max-width: 50%; overflow: hidden; background-color: white; border: 1px solid #ccc; padding: 15px 30px 20px 30px; overflow-y: auto; } |
|
#help pre { word-wrap: break-word !important; white-space: pre-wrap !important; } |
|
#closeicon { position: fixed; top: 10%; left: 25%; margin: 5px 8px; color: #ccc; cursor: pointer; font-family: sans-serif; } |
|
#openFileInput { position: absolute; display: none; } |
|
|
|
@media print { |
|
#helpicon { display: none; } |
|
#wmd-preview .pagebreak { opacity: 0; } |
|
} |
|
|
|
.dark-mode #wmd-input, .dark-mode #wmd-preview { background-color: #212121; color: #FAFAFA; border-color: #757575;} |
|
.dark-mode #wmd-preview a, .dark-mode #help a, .dark-mode .wmd-prompt-dialog a { color: #90CAF9; } |
|
.dark-mode #wmd-preview p code, .dark-mode #wmd-preview li code, .dark-mode #wmd-preview pre { background-color: #424242; } |
|
.dark-mode #wmd-preview table th, .dark-mode #wmd-preview table td { border-color: #757575; } |
|
.dark-mode #wmd-preview table tr { background-color: #424242; border-color: #757575; } |
|
.dark-mode #help { background-color: #424242; border-color: #757575; color: #FAFAFA; } |
|
.dark-mode .wmd-prompt-dialog { background-color: #424242; color: #FAFAFA; } |
|
.dark-mode .wmd-prompt-dialog input { background-color: #212121; color: #FAFAFA; } |
|
.dark-mode #wmd-preview blockquote { background-color: #00796B; border-color: #004D40; } |
|
|
|
</style> |
|
|
|
</head> |
|
<body class="fixedheight"> |
|
<script type="text/javascript" src="Markdown.Converter.js"></script> |
|
<script type="text/javascript" src="Markdown.Sanitizer.js"></script> |
|
<script type="text/javascript" src="Markdown.Editor.js"></script> |
|
<script type="text/javascript" src="Markdown.Extra.js"></script> |
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_HTML-full"></script> |
|
<script type="text/javascript" src="mathjax-editing_writing.js"></script> |
|
<!-- <script type="text/javascript" src="jspdf.min.js"></script> --> |
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> |
|
<input id="openFileInput" type="file" /> |
|
<div id="wmd-button-bar" class="wmd-button-bar"></div> |
|
<textarea id="wmd-input" class="column wmd-input" spellcheck="false"></textarea> |
|
<div id="wmd-preview" class="column wmd-preview"> |
|
<noscript>This text editor requires JavaScript.</noscript> |
|
</div> |
|
<div id="helpicon" class="unselectable">?</div> |
|
<div id="help"> |
|
<div id="closeicon" class="unselectable">X</div> |
|
<pre> |
|
<a href="https://github.com/josephernest/writing">Writing</a> is a lightweight distraction-free text editor. |
|
Write text on the left, and the result is displayed on the right. |
|
|
|
Commands |
|
-------- |
|
CTRL + D: toggle display mode (editor only, preview only or both-at-the-same-time) |
|
CTRL + P: print or export as PDF |
|
CTRL + S: save source code as .MD file |
|
CTRL + SHIFT + O: open .MD file |
|
CTRL + SHIFT + 7: send to the storage |
|
|
|
CTRL + SHIFT + L: enable / disable LaTeX (i.e. math formulas) |
|
CTRL + SHIFT + D: toggle dark mode |
|
CTRL + SHIFT + R: toggle roman (LaTex-like) or sans-serif font |
|
CTRL + SHIFT + H: show this help dialog |
|
|
|
F11: full-screen (in most browsers) |
|
|
|
Markdown syntax |
|
--------------- |
|
#Title |
|
##Subtitle |
|
This is *italic* and this is **bold**. |
|
This is a [link](http://www.example.com/) and this is an . |
|
Write code with `...` or by adding a 4-whitespace indent to the paragraph. |
|
> This is a quote. |
|
|
|
LaTeX syntax |
|
------------ |
|
This formula $x^2+1$ will be displayed inline. |
|
This formula $$x^2+1$$ will be displayed in a new paragraph. |
|
|
|
Specific syntax |
|
--------------- |
|
\pagebreak will trigger a pagebreak when printing / exporting to PDF. |
|
|
|
About |
|
----- |
|
Made by <a href="https://twitter.com/JosephErnest">@JosephErnest</a> |
|
<a href="https://github.com/josephernest/writing">https://github.com/josephernest/writing</a> |
|
Uses <a href="https://code.google.com/archive/p/pagedown/">Pagedown</a>, <a href="https://github.com/jmcmanus/pagedown-extra">Pagedown Extra</a>, <a href="https://www.mathjax.org/">MathJax</a>, StackOverflow's <a href="https://gist.github.com/gdalgas/a652bce3a173ddc59f66">editor</a> code and the <a href="http://cm-unicode.sourceforge.net/">Computer Modern</a> font. |
|
</pre> |
|
</div> |
|
|
|
<script type="text/javascript"> |
|
togglemathjax = function(enabled) { |
|
if (enabled) { |
|
if (!latexenabledonce) |
|
{ |
|
MathJax.Hub.Config( |
|
{"HTML-CSS": { preferredFont: "TeX", availableFonts: ["STIX","TeX"], linebreaks: { automatic: true }, EqnChunk: (MathJax.Hub.Browser.isMobile ? 10 : 50) }, |
|
tex2jax: { inlineMath: [ ["$", "$"], ["\\\\(","\\\\)"] ], displayMath: [ ["$$","$$"], ["\\[", "\\]"] ], processEscapes: true, ignoreClass: "tex2jax_ignore|dno" }, |
|
TeX: { noUndefined: { attributes: { mathcolor: "red", mathbackground: "#FFEEEE", mathsize: "90%" } }, Macros: { href: "{}" } }, |
|
messageStyle: "none", skipStartupTypeset: true }); |
|
mjpd1.mathjaxEditing.prepareWmdForMathJax(editor, '', [["$", "$"]]); |
|
latexenabledonce = true; |
|
if (editor.refreshPreview !== undefined) |
|
editor.refreshPreview(); |
|
} |
|
else { |
|
MathJax.Hub.queue.pending = 0; |
|
MathJax.Hub.Queue(["Typeset", MathJax.Hub, "wmd-preview"]); |
|
} |
|
} |
|
else { |
|
MathJax.Hub.queue.pending = 1; |
|
if (editor.refreshPreview !== undefined) |
|
editor.refreshPreview(); |
|
else { |
|
MathJax.Hub.Config({ skipStartupTypeset: true }); |
|
} |
|
} |
|
} |
|
|
|
toggledarkmode = function(enabled){ |
|
$('body').toggleClass('dark-mode',enabled); |
|
} |
|
|
|
if (localStorage.getItem("writing") !== null) { |
|
$('#wmd-input').val(localStorage.getItem("writing")); |
|
} |
|
|
|
openFile = function(e) { |
|
readFile(e.target.files[0]); |
|
} |
|
|
|
readFile = function(file){ // https://stackoverflow.com/a/26298948/1422096 |
|
if (!file) { |
|
return; |
|
} |
|
var reader = new FileReader(); |
|
reader.onload = function(e) { |
|
var contents = e.target.result; |
|
$('#wmd-input').val(contents); // display file content |
|
editor.refreshPreview(); |
|
}; |
|
reader.readAsText(file); |
|
} |
|
|
|
document.getElementById('openFileInput').addEventListener('change', openFile, false); |
|
|
|
$('body').on('drag dragstart dragend dragover dragenter dragleave drop', function(e) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
}) |
|
.on('drop', function(e) { |
|
readFile(e.originalEvent.dataTransfer.files[0]); |
|
}); |
|
|
|
$('#wmd-input').on('input', function() { |
|
localStorage.setItem("writing", $('#wmd-input').val()); |
|
}); |
|
|
|
$('#wmd-input').focus(); |
|
|
|
$('#helpicon').click(function() { |
|
$('#help').show(); |
|
}); |
|
|
|
$('#closeicon, #wmd-input, #wmd-preview').click(function() { |
|
$('#help').hide(); |
|
}); |
|
|
|
$(document).on('keydown', function(e) { |
|
if (e.keyCode == 80 && (e.ctrlKey || e.metaKey)) { // CTRL + P |
|
if (mode != 1) { |
|
mode = 1; |
|
$('#wmd-input').hide(); |
|
$('#wmd-preview').show(); |
|
$('body').removeClass('fixedheight'); |
|
$('html').removeClass('fixedheight'); |
|
toggledarkmode(false); |
|
e.preventDefault(); |
|
window.print(); |
|
toggledarkmode(darkmodeenabled); |
|
return false; |
|
} |
|
//var doc = new jsPDF(); |
|
//var specialElementHandlers = {'#editor': function (element, renderer) { return true; } }; |
|
//doc.fromHTML($('#wmd-preview').html(), 15, 15, { 'width': 170, 'elementHandlers': specialElementHandlers }); |
|
//doc.save('file.pdf'); |
|
/*var restorepage = $('body').html(); |
|
var printcontent = $('#wmd-preview').clone(); |
|
$('body').empty().html(printcontent); |
|
window.print(); |
|
$('body').html(restorepage); |
|
e.preventDefault(); |
|
return false;*/ |
|
} |
|
else if (e.keyCode == 83 && (e.ctrlKey || e.metaKey)) { // CTRL + S |
|
var blob = new Blob([$('#wmd-input').val()], {type: 'text'}); // https://stackoverflow.com/a/33542499/1422096 |
|
if (window.navigator.msSaveOrOpenBlob) { |
|
window.navigator.msSaveBlob(blob, 'newfile.md'); |
|
} |
|
else { |
|
var elem = window.document.createElement('a'); |
|
elem.href = window.URL.createObjectURL(blob); |
|
elem.download = 'newfile.md'; |
|
document.body.appendChild(elem); |
|
elem.click(); |
|
document.body.removeChild(elem); |
|
} |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 68 && (e.ctrlKey || e.metaKey) && !e.shiftKey) { // CTRL + D |
|
mode += 1; if (mode == 3) mode = 0; |
|
if (mode == 1) { |
|
$('#wmd-input').hide(); |
|
$('#wmd-preview').show(); |
|
$('body').removeClass('fixedheight'); |
|
$('html').removeClass('fixedheight'); |
|
} |
|
else if (mode == 2) { |
|
$('#wmd-preview').hide(); |
|
$('#wmd-input').show().css('float', 'none').css('width', '100%').focus(); |
|
$('body').addClass('fixedheight'); |
|
$('html').addClass('fixedheight'); |
|
} |
|
else { |
|
$('#wmd-input').show().css('float', 'left').css('width', '50%').focus(); |
|
$('#wmd-preview').show(); |
|
} |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 72 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + H |
|
$('#help').show(); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 55 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + SHIFT + 7 |
|
const text = $('#wmd-input').val(); |
|
let name = text.split("\n")[0].replaceAll("#", "") |
|
const xhr = new XMLHttpRequest(); |
|
const cb = function (status, responseRaw) { |
|
const response = JSON.parse(responseRaw); |
|
if (status < 400 && response.Success) { |
|
localStorage.removeItem("writing"); |
|
window.location.replace("/" + response.Payload) |
|
} else { |
|
$('feedback').innerHTML = status + ": " + response.Payload; |
|
} |
|
} |
|
xhr.open('POST', "/") |
|
xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) return cb(xhr.status, xhr.responseText) }; |
|
const data = new FormData(); |
|
data.append("text", text) |
|
data.append("name", name) |
|
xhr.send(data); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
|
|
else if (e.keyCode == 68 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + SHIFT + D |
|
darkmodeenabled = !darkmodeenabled; |
|
localStorage.setItem("darkmode", darkmodeenabled ? "1" : "0"); |
|
toggledarkmode(darkmodeenabled); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 82 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + SHIFT + R |
|
$('html').toggleClass('texroman'); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 76 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + SHIFT + L |
|
latexenabled = !latexenabled; |
|
localStorage.setItem("latex", latexenabled ? "1" : "0"); |
|
togglemathjax(latexenabled); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 79 && (e.ctrlKey || e.metaKey) && e.shiftKey) { // CTRL + SHIFT + O |
|
$('#openFileInput').click(); |
|
e.preventDefault(); |
|
return false; |
|
} |
|
else if (e.keyCode == 27) { // ESC |
|
$('#help').hide(); |
|
} |
|
}); |
|
|
|
var mode = 0; |
|
var latexenabledonce = false; |
|
var latexenabled = localStorage.getItem("latex") !== "0"; |
|
var darkmodeenabled = localStorage.getItem("darkmode") == "1"; |
|
var converter = Markdown.getSanitizingConverter(); |
|
Markdown.Extra.init(converter); |
|
var editor = new Markdown.Editor(converter, ''); |
|
var mjpd1 = new mjpd(); |
|
togglemathjax(latexenabled); |
|
toggledarkmode(darkmodeenabled); |
|
editor.run(); |
|
</script> |
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-2312083-14"></script><script>window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-2312083-14');</script> |
|
|
|
</body> |
|
</html>
|
|
|