From 3ce9df9bae23d3f433f18ffc8325f8b38ba65a00 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 1 Jun 2026 14:02:03 +0200 Subject: [PATCH] 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) --- containers/novela/static/editor.js | 31 ++++++++++++++++++++----- containers/novela/templates/editor.html | 3 ++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/containers/novela/static/editor.js b/containers/novela/static/editor.js index ef4a058..520768b 100644 --- a/containers/novela/static/editor.js +++ b/containers/novela/static/editor.js @@ -596,6 +596,7 @@ async function replaceInAllChapters() { const replaceVal = document.getElementById('rp-replace').value; const useRegex = document.getElementById('rp-regex').checked; const caseSens = document.getElementById('rp-case').checked; + const currentOnly = document.getElementById('rp-current').checked; const runBtn = document.getElementById('rp-run'); const prog = document.getElementById('rp-progress'); @@ -620,10 +621,24 @@ async function replaceInAllChapters() { const curCh = currentCh(); if (curCh) pendingContent.set(curCh._id, editor.getValue()); - for (let i = 0; i < chapters.length; i++) { - const ch = chapters[i]; + // Determine which chapters to process + 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.textContent = `Checking chapter ${i + 1} / ${chapters.length}…`; + prog.textContent = `Checking chapter ${i + 1} / ${targets.length}…`; let original; if (pendingContent.has(ch._id)) { @@ -665,9 +680,13 @@ async function replaceInAllChapters() { updateSaveAll(); prog.className = totalOccurrences > 0 ? 'modal-progress ok' : 'modal-progress'; - prog.textContent = totalOccurrences > 0 - ? `${totalOccurrences} replacement${totalOccurrences !== 1 ? 's' : ''} in ${chaptersChanged} chapter${chaptersChanged !== 1 ? 's' : ''} — not saved yet.` - : 'No matches found.'; + if (totalOccurrences === 0) { + prog.textContent = '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; } diff --git a/containers/novela/templates/editor.html b/containers/novela/templates/editor.html index fca0712..1504eb7 100644 --- a/containers/novela/templates/editor.html +++ b/containers/novela/templates/editor.html @@ -82,7 +82,7 @@