107 lines
3.1 KiB
HTML
107 lines
3.1 KiB
HTML
|
<script src="{{ static "go_wasm_exec.js" }}"></script>
|
||
|
<script>
|
||
|
const previewWorker = new Worker('/assets/markdown_worker.js');
|
||
|
|
||
|
/*
|
||
|
Automatically save and restore content from a text field on change.
|
||
|
|
||
|
Return type:
|
||
|
|
||
|
{
|
||
|
// Call this function when you submit the form or otherwise want
|
||
|
// to delete the work-in-progress user content.
|
||
|
clearStorage: () => {},
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
function autosaveContent({
|
||
|
// HTML input or textarea
|
||
|
inputEl,
|
||
|
// Unique string identifying this field across the site.
|
||
|
storageKey,
|
||
|
}) {
|
||
|
const storagePrefix = 'saved-content';
|
||
|
|
||
|
// Delete old irrelevant local contents
|
||
|
const aWeekAgo = new Date().getTime() - (7 * 24 * 60 * 60 * 1000);
|
||
|
for (const key in window.localStorage) {
|
||
|
if (!window.localStorage.hasOwnProperty(key)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (key.startsWith(storagePrefix)) {
|
||
|
try {
|
||
|
const { when } = JSON.parse(window.localStorage.getItem(key));
|
||
|
if (when <= aWeekAgo) {
|
||
|
window.localStorage.removeItem(key);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
console.error(e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Load any stored content from localStorage
|
||
|
const storageKeyFull = `${storagePrefix}/${storageKey}`;
|
||
|
const storedContents = window.localStorage.getItem(storageKeyFull);
|
||
|
if (storedContents && !inputEl.value) {
|
||
|
try {
|
||
|
const { contents } = JSON.parse(storedContents);
|
||
|
inputEl.value = contents;
|
||
|
} catch (e) {
|
||
|
console.error(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function updateContentCache() {
|
||
|
window.localStorage.setItem(storageKeyFull, JSON.stringify({
|
||
|
when: new Date().getTime(),
|
||
|
contents: inputEl.value,
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
inputEl.addEventListener('input', () => updateContentCache());
|
||
|
|
||
|
return {
|
||
|
clear() {
|
||
|
window.localStorage.removeItem(storageKeyFull);
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const markdownIds = [];
|
||
|
|
||
|
/*
|
||
|
Initialize live Markdown rendering.
|
||
|
*/
|
||
|
function initLiveMarkdown({
|
||
|
// HTML input or textarea
|
||
|
inputEl,
|
||
|
// HTML element in which to render markdown
|
||
|
previewEl,
|
||
|
}) {
|
||
|
if (markdownIds.includes(inputEl.id)) {
|
||
|
console.warn(`Multiple elements with ID "${inputEl.id}" are being used for Markdown. Results will be very confusing!`);
|
||
|
}
|
||
|
markdownIds.push(inputEl.id);
|
||
|
|
||
|
previewWorker.onmessage = ({ data }) => {
|
||
|
const { elementID, html } = data;
|
||
|
if (elementID === inputEl.id) {
|
||
|
previewEl.innerHTML = html;
|
||
|
MathJax.typeset();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function doMarkdown() {
|
||
|
previewWorker.postMessage({
|
||
|
elementID: inputEl.id,
|
||
|
markdown: inputEl.value,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
doMarkdown();
|
||
|
inputEl.addEventListener('input', () => doMarkdown());
|
||
|
}
|
||
|
</script>
|