Editor: Find & Replace scope option

Add a "Current chapter only" checkbox to the Find & Replace modal. When
checked, search/replace runs against the open chapter instead of every chapter
in the book. Default unchecked, preserving the existing all-chapters behaviour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ivo Oskamp 2026-06-01 14:02:03 +02:00
parent 347f959d80
commit 3ce9df9bae
2 changed files with 27 additions and 7 deletions

View File

@ -596,6 +596,7 @@ async function replaceInAllChapters() {
const replaceVal = document.getElementById('rp-replace').value; const replaceVal = document.getElementById('rp-replace').value;
const useRegex = document.getElementById('rp-regex').checked; const useRegex = document.getElementById('rp-regex').checked;
const caseSens = document.getElementById('rp-case').checked; const caseSens = document.getElementById('rp-case').checked;
const currentOnly = document.getElementById('rp-current').checked;
const runBtn = document.getElementById('rp-run'); const runBtn = document.getElementById('rp-run');
const prog = document.getElementById('rp-progress'); const prog = document.getElementById('rp-progress');
@ -620,10 +621,24 @@ async function replaceInAllChapters() {
const curCh = currentCh(); const curCh = currentCh();
if (curCh) pendingContent.set(curCh._id, editor.getValue()); if (curCh) pendingContent.set(curCh._id, editor.getValue());
for (let i = 0; i < chapters.length; i++) { // Determine which chapters to process
const ch = chapters[i]; let targets;
if (currentOnly) {
if (!curCh) {
prog.className = 'modal-progress error';
prog.textContent = 'No chapter open.';
runBtn.disabled = false;
return;
}
targets = [curCh];
} else {
targets = chapters;
}
for (let i = 0; i < targets.length; i++) {
const ch = targets[i];
prog.className = 'modal-progress'; prog.className = 'modal-progress';
prog.textContent = `Checking chapter ${i + 1} / ${chapters.length}`; prog.textContent = `Checking chapter ${i + 1} / ${targets.length}`;
let original; let original;
if (pendingContent.has(ch._id)) { if (pendingContent.has(ch._id)) {
@ -665,9 +680,13 @@ async function replaceInAllChapters() {
updateSaveAll(); updateSaveAll();
prog.className = totalOccurrences > 0 ? 'modal-progress ok' : 'modal-progress'; prog.className = totalOccurrences > 0 ? 'modal-progress ok' : 'modal-progress';
prog.textContent = totalOccurrences > 0 if (totalOccurrences === 0) {
? `${totalOccurrences} replacement${totalOccurrences !== 1 ? 's' : ''} in ${chaptersChanged} chapter${chaptersChanged !== 1 ? 's' : ''} — not saved yet.` prog.textContent = 'No matches found.';
: 'No matches found.'; } else if (currentOnly) {
prog.textContent = `${totalOccurrences} replacement${totalOccurrences !== 1 ? 's' : ''} in current chapter — not saved yet.`;
} else {
prog.textContent = `${totalOccurrences} replacement${totalOccurrences !== 1 ? 's' : ''} in ${chaptersChanged} chapter${chaptersChanged !== 1 ? 's' : ''} — not saved yet.`;
}
runBtn.disabled = false; runBtn.disabled = false;
} }

View File

@ -82,7 +82,7 @@
<!-- Find & Replace modal --> <!-- Find & Replace modal -->
<div class="modal-backdrop" id="replace-modal"> <div class="modal-backdrop" id="replace-modal">
<div class="modal"> <div class="modal">
<div class="modal-title">Find &amp; Replace — all chapters</div> <div class="modal-title">Find &amp; Replace</div>
<div class="modal-field"> <div class="modal-field">
<label class="modal-label">Search</label> <label class="modal-label">Search</label>
<input class="modal-input" id="rp-search" type="text" placeholder="Search…" autocomplete="off"/> <input class="modal-input" id="rp-search" type="text" placeholder="Search…" autocomplete="off"/>
@ -94,6 +94,7 @@
<div class="modal-options"> <div class="modal-options">
<label class="modal-opt"><input type="checkbox" id="rp-regex"/> Regex</label> <label class="modal-opt"><input type="checkbox" id="rp-regex"/> Regex</label>
<label class="modal-opt"><input type="checkbox" id="rp-case"/> Case sensitive</label> <label class="modal-opt"><input type="checkbox" id="rp-case"/> Case sensitive</label>
<label class="modal-opt"><input type="checkbox" id="rp-current"/> Current chapter only</label>
</div> </div>
<div class="modal-progress" id="rp-progress"></div> <div class="modal-progress" id="rp-progress"></div>
<div class="modal-actions"> <div class="modal-actions">