diff --git a/static/index.html b/static/index.html
index 7712ec2..9c02a90 100644
--- a/static/index.html
+++ b/static/index.html
@@ -278,6 +278,7 @@ Double-click any word to look it up on the right.">
Copy to clipboard
Export image
+ Save .txt
rhyme
rhythm
alliteration
@@ -943,6 +944,39 @@ document.getElementById('exportBtn').addEventListener('click', async ()=>{
});
});
+/* ============================================================
+ FILES IN, FILES OUT — drafts shouldn't be hostage to localStorage
+============================================================ */
+function draftFilename(){
+ const doc = docsState.docs.find(d=>d.id===docsState.current);
+ return (((doc && doc.title && doc.title !== 'Untitled') ? doc.title : 'rhymepad')
+ .replace(/[^\w\- ]+/g, '').trim() || 'rhymepad') + '.txt';
+}
+document.getElementById('downloadBtn').addEventListener('click', ()=>{
+ if(!editor.value.trim()) return;
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(new Blob([editor.value], {type: 'text/plain'}));
+ a.download = draftFilename();
+ a.click();
+ setTimeout(()=>URL.revokeObjectURL(a.href), 5000);
+ flash('downloadBtn', 'Saved \u2713');
+});
+// drop a .txt (or any text file) anywhere -> it becomes a new draft
+document.addEventListener('dragover', e=>{ e.preventDefault(); });
+document.addEventListener('drop', async e=>{
+ e.preventDefault();
+ const files = [...(e.dataTransfer?.files || [])].slice(0, 8);
+ for(const f of files){
+ if(f.size > 1024 * 1024) continue;
+ const text = await f.text();
+ if(!text.trim()) continue;
+ const id = newId();
+ docsState.docs.push({id, title: titleOf(text)});
+ localStorage.setItem(docKey(id), text);
+ openDoc(id);
+ }
+});
+
/* ============================================================
COPY / CLEAR / SAMPLE
============================================================ */