diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 80594c39..49db4386 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -11139,7 +11139,6 @@ ${selector} .arrowheadPath { renderMathJaxNodes(roots, rawVal, context, { snapshotReviewTargets: true }); decorateReviewTargets(); - updateDocumentStats(); updateFindHighlights(); scheduleLineNumberUpdate(); scheduleAdvancedPostProcessRecovery(rawVal, context); @@ -11188,6 +11187,10 @@ ${selector} .arrowheadPath { options = options || {}; const rawVal = markdownEditor.value; const force = options.force === true; + // Stats must reflect the current editor content on every render call, even when + // the preview HTML itself is skipped below because it's already up to date + // (e.g. switching back to a tab whose content didn't change). + updateDocumentStats(); const previewDocumentId = getActivePreviewDocumentId(); const hasCurrentPreview = previewHasCommittedRender && diff --git a/script.js b/script.js index 80594c39..49db4386 100644 --- a/script.js +++ b/script.js @@ -11139,7 +11139,6 @@ ${selector} .arrowheadPath { renderMathJaxNodes(roots, rawVal, context, { snapshotReviewTargets: true }); decorateReviewTargets(); - updateDocumentStats(); updateFindHighlights(); scheduleLineNumberUpdate(); scheduleAdvancedPostProcessRecovery(rawVal, context); @@ -11188,6 +11187,10 @@ ${selector} .arrowheadPath { options = options || {}; const rawVal = markdownEditor.value; const force = options.force === true; + // Stats must reflect the current editor content on every render call, even when + // the preview HTML itself is skipped below because it's already up to date + // (e.g. switching back to a tab whose content didn't change). + updateDocumentStats(); const previewDocumentId = getActivePreviewDocumentId(); const hasCurrentPreview = previewHasCommittedRender && diff --git a/tests/e2e/tab-split-sidebar-update.spec.js b/tests/e2e/tab-split-sidebar-update.spec.js index 2879b8d4..75fbe452 100644 --- a/tests/e2e/tab-split-sidebar-update.spec.js +++ b/tests/e2e/tab-split-sidebar-update.spec.js @@ -257,6 +257,24 @@ test('closing a tab keeps the document in Files and reopening restores the tab', await expect(reopenedRow).toHaveCount(0); }); +test('reopening the only closed tab restores the word/char/reading-time stats', async ({ page }) => { + const closedTabId = await page.locator('#tab-list .tab-item.active').getAttribute('data-tab-id'); + await setEditorContent(page, '# Kept document\n\nSome words to count here.'); + + await expect(page.locator('#word-count')).toHaveText('8'); + await expect(page.locator('#char-count')).toHaveText('42'); + + await page.locator('#tab-list .tab-item.active .tab-close-btn').click(); + await expect(page.locator('#word-count')).toHaveText('0'); + await expect(page.locator('#char-count')).toHaveText('0'); + + await page.locator(`.document-tree-row[data-document-id="${closedTabId}"] .document-tree-main`).click(); + await expect(page.locator('#markdown-editor')).toHaveValue('# Kept document\n\nSome words to count here.'); + await expect(page.locator('#word-count')).toHaveText('8'); + await expect(page.locator('#char-count')).toHaveText('42'); + await expect(page.locator('#reading-time')).toHaveText('1'); +}); + test('format toolbar consolidates heading, case, alignment, and insert actions', async ({ page }) => { await expect(page.locator('[data-md-action="clear-formatting"]')).toHaveCount(0); await expect(page.locator('[data-md-action="help"]')).toHaveCount(0);