diff --git a/markitect/document_manager.py b/markitect/document_manager.py
index 4dd5d795..c22031df 100644
--- a/markitect/document_manager.py
+++ b/markitect/document_manager.py
@@ -447,9 +447,12 @@ class DocumentManager:
const header = document.createElement('div');
header.className = 'markitect-floating-header';
header.innerHTML = `
-
-
- Ready
+
+
+ Ready
+
+ Saves as: filename-edited-YYYY-MM-DD-HH-MM-SS.md
+
`;
document.body.insertBefore(header, document.body.firstChild);
@@ -520,10 +523,88 @@ class DocumentManager:
}
save() {
- document.getElementById('save-status').textContent = 'Saved!';
- setTimeout(() => {
- document.getElementById('save-status').textContent = 'Ready';
- }, 2000);
+ try {
+ // Get the current markdown content from the editor
+ const markdownContent = this.getMarkdownContent();
+
+ // Create filename with timestamp suffix for backup convention
+ const now = new Date();
+ const timestamp = now.toISOString().slice(0, 19).replace(/:/g, '-').replace('T', '-');
+ const originalFilename = window.location.pathname.split('/').pop().replace('.html', '.md');
+ const backupFilename = `${originalFilename.replace('.md', '')}-edited-${timestamp}.md`;
+
+ // Create and download the file
+ const blob = new Blob([markdownContent], { type: 'text/markdown' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = backupFilename;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+
+ // Update status with filename convention info
+ const statusEl = document.getElementById('save-status');
+ statusEl.textContent = `Downloaded: ${backupFilename}`;
+ statusEl.title = 'File saved with timestamp to avoid overwriting original';
+ setTimeout(() => {
+ statusEl.textContent = 'Ready';
+ statusEl.title = '';
+ }, 5000);
+
+ } catch (error) {
+ document.getElementById('save-status').textContent = 'Save failed!';
+ console.error('Save error:', error);
+ setTimeout(() => {
+ document.getElementById('save-status').textContent = 'Ready';
+ }, 3000);
+ }
+ }
+
+ getMarkdownContent() {
+ // Reconstruct markdown content from the current state of sections
+ const content = document.getElementById('markdown-content');
+ if (!content) {
+ return markdownContent; // fallback to original
+ }
+
+ // Simple approach: get the text content and convert back to markdown
+ // This is a basic implementation - could be enhanced for better preservation
+ const sections = content.querySelectorAll('.markitect-section-editable');
+ let reconstructed = '';
+
+ sections.forEach(section => {
+ const tagName = section.tagName.toLowerCase();
+ const text = section.textContent.trim();
+
+ if (tagName.startsWith('h')) {
+ const level = parseInt(tagName.charAt(1));
+ reconstructed += '#'.repeat(level) + ' ' + text + '\n\n';
+ } else if (tagName === 'p') {
+ reconstructed += text + '\n\n';
+ } else if (tagName === 'blockquote') {
+ reconstructed += '> ' + text + '\n\n';
+ } else if (tagName === 'pre') {
+ reconstructed += '```\n' + text + '\n```\n\n';
+ } else if (tagName === 'ul') {
+ const items = section.querySelectorAll('li');
+ items.forEach(item => {
+ reconstructed += '- ' + item.textContent.trim() + '\n';
+ });
+ reconstructed += '\n';
+ } else if (tagName === 'ol') {
+ const items = section.querySelectorAll('li');
+ items.forEach((item, index) => {
+ reconstructed += `${index + 1}. ` + item.textContent.trim() + '\n';
+ });
+ reconstructed += '\n';
+ } else {
+ reconstructed += text + '\n\n';
+ }
+ });
+
+ return reconstructed.trim();
}
togglePreview() {