Fix indentation, tweak newlines

This commit is contained in:
Ben Visness 2021-09-22 22:35:07 -05:00
parent 7063fd5604
commit a38727ed69
1 changed files with 213 additions and 213 deletions

View File

@ -12,9 +12,9 @@
resize: vertical; resize: vertical;
} }
#editor.drop { #editor.drop {
box-shadow: inset 0px 0px 5px yellow; box-shadow: inset 0px 0px 5px yellow;
} }
</style> </style>
{{ end }} {{ end }}
@ -54,16 +54,16 @@
*/}} */}}
<textarea id="editor" class="w-100 h6 minh-6 pa2 mono lh-copy" name="body">{{ .EditInitialContents }}</textarea> <textarea id="editor" class="w-100 h6 minh-6 pa2 mono lh-copy" name="body">{{ .EditInitialContents }}</textarea>
<div class="flex justify-end items-center mt2"> <div class="flex justify-end items-center mt2">
<div class="upload_bar flex-grow-1"> <div class="upload_bar flex-grow-1">
<div class="instructions"> <div class="instructions">
Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them. Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them.
</div> </div>
<div class="progress flex"> <div class="progress flex">
<div class="progress_text mr3"></div> <div class="progress_text mr3"></div>
<div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div> <div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div>
</div> </div>
</div> </div>
<input type="submit" class="button ml2 flex-grow-0 flex-shrink-0" name="submit" value="{{ .SubmitLabel }}" /> <input type="submit" class="button ml2 flex-grow-0 flex-shrink-0" name="submit" value="{{ .SubmitLabel }}" />
</div> </div>
@ -114,13 +114,13 @@
<div id="preview-container" class="post post-preview mathjax flex-fair-ns overflow-auto mv3 mv0-ns ml3-ns pa3 br3 bg--dim"> <div id="preview-container" class="post post-preview mathjax flex-fair-ns overflow-auto mv3 mv0-ns ml3-ns pa3 br3 bg--dim">
<div id="preview" class="post-content"></div> <div id="preview" class="post-content"></div>
</div> </div>
<input type="file" multiple name="file_input" id="file_input" class="dn" />{{/* NOTE(asaf): Placing this outside the form to avoid submitting it to the server by accident */}} <input type="file" multiple name="file_input" id="file_input" class="dn" />{{/* NOTE(asaf): Placing this outside the form to avoid submitting it to the server by accident */}}
</div> </div>
</div> </div>
<script> <script>
const maxFileSize = {{ .MaxFileSize }}; const maxFileSize = {{ .MaxFileSize }};
const uploadUrl = {{ .UploadUrl }}; const uploadUrl = {{ .UploadUrl }};
const form = document.querySelector('#form'); const form = document.querySelector('#form');
const titleField = document.querySelector('#title'); // may be undefined, be careful! const titleField = document.querySelector('#title'); // may be undefined, be careful!
@ -196,224 +196,224 @@
window.localStorage.removeItem(storageKey); window.localStorage.removeItem(storageKey);
}); });
/* /*
/ Asset upload / Asset upload
*/ */
const submitButton = document.querySelector("#form input[type=submit]"); const submitButton = document.querySelector("#form input[type=submit]");
const submitText = submitButton.value; const submitText = submitButton.value;
const fileInput = document.querySelector('#file_input'); const fileInput = document.querySelector('#file_input');
const uploadBar = document.querySelector('.upload_bar'); const uploadBar = document.querySelector('.upload_bar');
const uploadProgress = document.querySelector('.upload_bar .progress'); const uploadProgress = document.querySelector('.upload_bar .progress');
const uploadProgressText = document.querySelector('.upload_bar .progress_text'); const uploadProgressText = document.querySelector('.upload_bar .progress_text');
const uploadProgressBar = document.querySelector('.upload_bar .progress_bar'); const uploadProgressBar = document.querySelector('.upload_bar .progress_bar');
const uploadProgressBarFill = document.querySelector('.upload_bar .progress_bar > div'); const uploadProgressBarFill = document.querySelector('.upload_bar .progress_bar > div');
let fileCounter = 0; let fileCounter = 0;
let enterCounter = 0; let enterCounter = 0;
let uploadQueue = []; let uploadQueue = [];
let currentUpload = null; let currentUpload = null;
let currentXhr = null; let currentXhr = null;
let currentBatchSize = 0; let currentBatchSize = 0;
let currentBatchDone = 0; let currentBatchDone = 0;
fileInput.addEventListener("change", function(ev) { fileInput.addEventListener("change", function(ev) {
if (fileInput.files.length > 0) { if (fileInput.files.length > 0) {
importUserFiles(fileInput.files); importUserFiles(fileInput.files);
} }
}); });
textField.addEventListener("dragover", function(ev) { textField.addEventListener("dragover", function(ev) {
let effect = "none"; let effect = "none";
for (let i = 0; i < ev.dataTransfer.items.length; ++i) { for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") { if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
effect = "copy"; effect = "copy";
break; break;
} }
} }
ev.dataTransfer.dropEffect = effect; ev.dataTransfer.dropEffect = effect;
ev.preventDefault(); ev.preventDefault();
}); });
textField.addEventListener("dragenter", function(ev) { textField.addEventListener("dragenter", function(ev) {
enterCounter++; enterCounter++;
let droppable = false; let droppable = false;
for (let i = 0; i < ev.dataTransfer.items.length; ++i) { for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") { if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
droppable = true; droppable = true;
break; break;
} }
} }
if (droppable) { if (droppable) {
textField.classList.add("drop"); textField.classList.add("drop");
} }
}); });
textField.addEventListener("dragleave", function(ev) { textField.addEventListener("dragleave", function(ev) {
enterCounter--; enterCounter--;
if (enterCounter == 0) { if (enterCounter == 0) {
textField.classList.remove("drop"); textField.classList.remove("drop");
} }
}); });
function makeUploadString(uploadNumber, filename) { function makeUploadString(uploadNumber, filename) {
return `Uploading file #${uploadNumber}: \`${filename}\`...`; return `Uploading file #${uploadNumber}: \`${filename}\`...`;
} }
textField.addEventListener("drop", function(ev) { textField.addEventListener("drop", function(ev) {
enterCounter = 0; enterCounter = 0;
textField.classList.remove("drop"); textField.classList.remove("drop");
if (ev.dataTransfer && ev.dataTransfer.files) { if (ev.dataTransfer && ev.dataTransfer.files) {
importUserFiles(ev.dataTransfer.files) importUserFiles(ev.dataTransfer.files)
} }
ev.preventDefault(); ev.preventDefault();
}); });
textField.addEventListener("paste", function(ev) { textField.addEventListener("paste", function(ev) {
if (ev.clipboardData && ev.clipboardData.files) { if (ev.clipboardData && ev.clipboardData.files) {
importUserFiles(ev.clipboardData.files) importUserFiles(ev.clipboardData.files)
} }
}); });
function importUserFiles(files) { function importUserFiles(files) {
let items = []; let items = [];
for (let i = 0; i < files.length; ++i) { for (let i = 0; i < files.length; ++i) {
let f = files[i]; let f = files[i];
if (f.size < maxFileSize) { if (f.size < maxFileSize) {
items.push({ file: f, error: null }); items.push({ file: f, error: null });
} else { } else {
items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` }); items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` });
} }
} }
let cursorStart = textField.selectionStart; let cursorStart = textField.selectionStart;
let cursorEnd = textField.selectionEnd; let cursorEnd = textField.selectionEnd;
let toInsert = ""; let toInsert = "";
let linesToCursor = textField.value.substr(0, cursorStart).split("\n"); let linesToCursor = textField.value.substr(0, cursorStart).split("\n");
let cursorLine = linesToCursor[linesToCursor.length-1].trim(); let cursorLine = linesToCursor[linesToCursor.length-1].trim();
if (cursorLine.length > 0) { if (cursorLine.length > 0) {
toInsert = "\n"; toInsert = "\n\n";
} }
for (let i = 0; i < items.length; ++i) { for (let i = 0; i < items.length; ++i) {
if (items[i].file) { if (items[i].file) {
fileCounter++; fileCounter++;
toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n"; toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n\n";
queueUpload(fileCounter, items[i].file); queueUpload(fileCounter, items[i].file);
} else { } else {
toInsert += `${items[i].error}\n`; toInsert += `${items[i].error}\n\n`;
} }
} }
textField.value = textField.value.substring(0, cursorStart) + toInsert + textField.value.substring(cursorEnd, textField.value.length); textField.value = textField.value.substring(0, cursorStart) + toInsert + textField.value.substring(cursorEnd, textField.value.length);
doMarkdown(); doMarkdown();
uploadNext(); uploadNext();
} }
function replaceUploadString(upload, newString) { function replaceUploadString(upload, newString) {
let cursorStart = textField.selectionStart; let cursorStart = textField.selectionStart;
let cursorEnd = textField.selectionEnd; let cursorEnd = textField.selectionEnd;
let uploadString = makeUploadString(upload.uploadNumber, upload.file.name); let uploadString = makeUploadString(upload.uploadNumber, upload.file.name);
let insertIndex = textField.value.indexOf(uploadString) let insertIndex = textField.value.indexOf(uploadString)
textField.value = textField.value.replace(uploadString, newString); textField.value = textField.value.replace(uploadString, newString);
if (cursorStart <= insertIndex + uploadString.length) { if (cursorStart <= insertIndex + uploadString.length) {
textField.selectionStart = cursorStart; textField.selectionStart = cursorStart;
} else { } else {
textField.selectionStart = cursorStart - uploadString.length + newString.length; textField.selectionStart = cursorStart - uploadString.length + newString.length;
} }
if (cursorEnd <= insertIndex + uploadString.length) { if (cursorEnd <= insertIndex + uploadString.length) {
textField.selectionEnd = cursorEnd; textField.selectionEnd = cursorEnd;
} else { } else {
textField.selectionEnd = cursorEnd - uploadString.length + newString.length; textField.selectionEnd = cursorEnd - uploadString.length + newString.length;
} }
doMarkdown(); doMarkdown();
} }
function replaceUploadStringError(upload) { function replaceUploadStringError(upload) {
replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`); replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`);
} }
function queueUpload(uploadNumber, file) { function queueUpload(uploadNumber, file) {
uploadQueue.push({ uploadQueue.push({
uploadNumber: uploadNumber, uploadNumber: uploadNumber,
file: file file: file
}); });
currentBatchSize++; currentBatchSize++;
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`; uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
} }
function uploadDone(ev) { function uploadDone(ev) {
try { try {
if (currentXhr.status == 200 && currentXhr.response) { if (currentXhr.status == 200 && currentXhr.response) {
if (currentXhr.response.url) { if (currentXhr.response.url) {
let url = currentXhr.response.url; let url = currentXhr.response.url;
let newString = `[${currentUpload.file.name}](${url})`; let newString = `[${currentUpload.file.name}](${url})`;
if (currentXhr.response.mime.startsWith("image")) { if (currentXhr.response.mime.startsWith("image")) {
newString = "!" + newString; newString = "!" + newString;
} }
replaceUploadString(currentUpload, newString); replaceUploadString(currentUpload, newString);
} else if (currentXhr.response.error) { } else if (currentXhr.response.error) {
replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`); replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`);
} else { } else {
replaceUploadStringError(currentUpload); replaceUploadStringError(currentUpload);
} }
} else { } else {
replaceUploadStringError(currentUpload); replaceUploadStringError(currentUpload);
} }
} catch (err) { } catch (err) {
console.error(err); console.error(err);
replaceUploadStringError(currentUpload); replaceUploadStringError(currentUpload);
} }
currentUpload = null; currentUpload = null;
currentXhr = null; currentXhr = null;
currentBatchDone++; currentBatchDone++;
uploadNext(); uploadNext();
} }
function updateUploadProgress(ev) { function updateUploadProgress(ev) {
if (ev.lengthComputable) { if (ev.lengthComputable) {
let progress = ev.loaded / ev.total; let progress = ev.loaded / ev.total;
uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%"; uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%";
} }
} }
function uploadNext() { function uploadNext() {
if (currentUpload == null) { if (currentUpload == null) {
next = uploadQueue.shift(); next = uploadQueue.shift();
if (next) { if (next) {
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`; uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
uploadBar.classList.add("uploading"); uploadBar.classList.add("uploading");
uploadProgressBarFill.style.width = "0%"; uploadProgressBarFill.style.width = "0%";
submitButton.disabled = true; submitButton.disabled = true;
submitButton.value = "Uploading files..."; submitButton.value = "Uploading files...";
try { try {
let utf8Filename = strToUTF8Arr(next.file.name); let utf8Filename = strToUTF8Arr(next.file.name);
let base64Filename = base64EncArr(utf8Filename); let base64Filename = base64EncArr(utf8Filename);
// NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2 // NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2
currentXhr = new XMLHttpRequest(); currentXhr = new XMLHttpRequest();
currentXhr.upload.addEventListener("progress", updateUploadProgress); currentXhr.upload.addEventListener("progress", updateUploadProgress);
currentXhr.open("POST", uploadUrl, true); currentXhr.open("POST", uploadUrl, true);
currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename); currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename);
currentXhr.responseType = "json"; currentXhr.responseType = "json";
currentXhr.addEventListener("loadend", uploadDone); currentXhr.addEventListener("loadend", uploadDone);
currentXhr.send(next.file); currentXhr.send(next.file);
currentUpload = next; currentUpload = next;
} catch (err) { } catch (err) {
replaceUploadStringError(next); replaceUploadStringError(next);
console.error(err); console.error(err);
uploadNext(); uploadNext();
} }
} else { } else {
submitButton.disabled = false; submitButton.disabled = false;
submitButton.value = submitText; submitButton.value = submitText;
uploadBar.classList.remove("uploading"); uploadBar.classList.remove("uploading");
currentBatchSize = 0; currentBatchSize = 0;
currentBatchDone = 0; currentBatchDone = 0;
} }
} }
} }
</script> </script>
{{ end }} {{ end }}