diff --git a/src/components/StatusBar.vue b/src/components/StatusBar.vue index 4a2ded9a..da139df2 100644 --- a/src/components/StatusBar.vue +++ b/src/components/StatusBar.vue @@ -36,6 +36,7 @@ "currentCursorLine", "currentLanguage", "currentSelectionSize", + "currentSelectionWordCount", "currentLanguage", "currentLanguageAuto", "currentCreatedTime", @@ -109,6 +110,9 @@ Col {{ currentCursorLine?.col }}
{ (sel) => getSelectionSize(update.state, sel) ).reduce((a, b) => a + b, 0) + const selectionWordCount = update.state.selection.ranges.map( + (sel) => getSelectionWordCount(update.state, sel) + ).reduce((a, b) => a + b, 0) + const block = getActiveNoteBlock(update.state) if (block && cursorLine) { heynoteStore.currentCursorLine = cursorLine heynoteStore.currentSelectionSize = selectionSize + heynoteStore.currentSelectionWordCount = selectionWordCount heynoteStore.currentLanguage = block.language.name heynoteStore.currentLanguageAuto = block.language.auto heynoteStore.currentBufferName = editor.name diff --git a/src/stores/heynote-store.js b/src/stores/heynote-store.js index 7ebe9332..e48fb56b 100644 --- a/src/stores/heynote-store.js +++ b/src/stores/heynote-store.js @@ -23,6 +23,7 @@ export const useHeynoteStore = defineStore("heynote", { currentLanguageAuto: null, currentCursorLine: null, currentSelectionSize: null, + currentSelectionWordCount: null, currentCreatedTime: null, libraryId: 0, createBufferParams: { diff --git a/tests/playwright/markdown.spec.js b/tests/playwright/markdown.spec.js index 3617fa74..79a50496 100644 --- a/tests/playwright/markdown.spec.js +++ b/tests/playwright/markdown.spec.js @@ -21,6 +21,56 @@ test("test markdown mode", async ({ page }) => { await expect(page.locator("css=.status .status-block.lang")).toHaveText("Markdown") }) +test("selection word count is shown in status bar", async ({ page }) => { + await heynotePage.setContent(` +∞∞∞text +Hello world test +`) + await page.waitForTimeout(200) + + await page.evaluate(() => { + const view = window._heynote_editor.view + const text = view.state.doc.toString() + const start = text.indexOf("Hello") + const end = text.indexOf("test") + "test".length + view.dispatch({ + selection: { anchor: start, head: end }, + scrollIntoView: true, + }) + }) + + await page.waitForTimeout(100) + await expect(page.locator("css=.status .status-block.line-number")).toContainText("Words 3") +}) + +test("fenced Markdown code blocks are syntax highlighted by language", async ({ page }) => { + await heynotePage.setContent(` +∞∞∞markdown +\`\`\`js +class StrictModel { + static fields = new Set(); +} +\`\`\` +\`\`\`py +def strict_function(): + return 1 +\`\`\` +`) + await page.waitForTimeout(300) + + const classToken = await page.locator("css=.cm-content span:has-text('class')").first().evaluate(el => el.className) + const strictModelToken = await page.locator("css=.cm-content span:has-text('StrictModel')").first().evaluate(el => el.className) + const defToken = await page.locator("css=.cm-content span:has-text('def')").first().evaluate(el => el.className) + + expect(classToken).not.toBe("") + expect(strictModelToken).not.toBe("") + expect(defToken).not.toBe("") + + // keyword-like tokens in JS and Python should have same style class and differ from identifiers. + expect(classToken).toBe(defToken) + expect(classToken).not.toBe(strictModelToken) +}) + test("checkbox toggle", async ({ page }) => { await heynotePage.setContent(` ∞∞∞markdown