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.
359 lines
16 KiB
359 lines
16 KiB
|
5 years ago
|
<!--
|
||
|
|
#
|
||
|
|
# 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>
|