feat(export): add visual word-template settings dialog with graceful default-template fallback

Replaces the two native OS dialogs used to configure the DOCX "Enhanced"
export template (an open-file picker + a message-box question) with a
single in-app modal that shows the currently active template state, per
Task 18's original audit finding that this state was invisible until a
user thought to reopen the menu. Consolidates the "Select Word
Template..."/"Template Settings..." menu items into one "Word Template
Settings..." entry wired to the new dialog; Browse still uses the native
file picker since there is genuinely no bundled folder of templates to
enumerate (confirmed by investigation — see task-18-report.md).

Also fixes a related dangling-reference bug: WordTemplateExporter's
hardcoded default template path (word_template.docx) was deleted from
the repo in an earlier commit, but the code still tried to read it and
threw ENOENT whenever no custom template was selected. convert() now
degrades gracefully by generating a minimal, valid DOCX shell (styles +
numbering matching what markdownToWordXml() already references) instead
of crashing, and the new dialog surfaces this state honestly ("using
default formatting, no default template is bundled") rather than
implying a working default exists.

Out of scope, per explicit instruction: bundling fabricated starter
.docx templates to populate a literal multi-item gallery (rejected as
disproportionate/fake-content scope), and an EPUB template gallery (no
EPUB template mechanism exists anywhere in this codebase to build one
for).

Amit Haridas
This commit is contained in:
2026-08-23 19:31:33 +05:30
parent 8a28c21512
commit c8883e77fe
6 changed files with 443 additions and 71 deletions
+50
View File
@@ -2354,6 +2354,56 @@
</div>
</div>
<!-- Word Template Settings Dialog -->
<div
id="word-template-dialog"
class="modal hidden"
role="dialog"
aria-modal="true"
aria-labelledby="word-template-title"
>
<div class="modal-backdrop" data-close></div>
<div class="modal-content">
<div class="modal-header">
<h3 id="word-template-title">Word Template Settings</h3>
<button class="modal-close" id="word-template-close" aria-label="Close">&times;</button>
</div>
<div class="modal-body">
<div class="wt-status-section">
<div id="word-template-status" class="wt-status wt-status-none">
<div class="wt-status-icon" aria-hidden="true">&#128196;</div>
<div class="wt-status-text">
<div id="word-template-status-title" class="wt-status-title">
No template selected
</div>
<div id="word-template-status-detail" class="wt-status-detail">
Using default formatting
</div>
</div>
</div>
<div class="wt-status-actions">
<button id="word-template-browse" class="browse-btn">Browse...</button>
<button id="word-template-clear" class="clear-btn">Clear</button>
</div>
</div>
<div class="wt-startpage-section">
<label for="word-template-start-page">Content starts from page</label>
<input type="number" id="word-template-start-page" min="1" max="100" value="3" />
<p class="wt-help">
Templates usually reserve the first pages for a cover sheet and table of contents;
your Markdown content is inserted starting from this page. Ignored when no template
is selected.
</p>
</div>
</div>
<div class="modal-footer">
<button id="word-template-cancel" class="btn btn-secondary" data-close>Cancel</button>
<button id="word-template-save" class="btn btn-primary">Save Settings</button>
</div>
</div>
</div>
<div class="main-content" id="main-content">
<!-- Sidebar -->
<div class="sidebar collapsed" id="sidebar">