💄 display number of words in sentence
This commit is contained in:
@@ -677,6 +677,22 @@ function countWords(text: string): number {
|
|||||||
return text.trim() === '' ? 0 : text.trim().split(/\s+/).length
|
return text.trim() === '' ? 0 : text.trim().split(/\s+/).length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSentenceWordCount(text: string, pos: number): number {
|
||||||
|
// Scan back to find sentence start (after .!? followed by space, or paragraph break, or doc start)
|
||||||
|
let start = 0
|
||||||
|
for (let i = pos - 1; i >= 0; i--) {
|
||||||
|
if (text[i] === '\n' && i > 0 && text[i - 1] === '\n') { start = i + 1; break }
|
||||||
|
if (/[.!?]/.test(text[i]) && i + 1 < text.length && /\s/.test(text[i + 1])) { start = i + 1; break }
|
||||||
|
}
|
||||||
|
// Scan forward to find sentence end
|
||||||
|
let end = text.length
|
||||||
|
for (let i = pos; i < text.length; i++) {
|
||||||
|
if (text[i] === '\n' && i + 1 < text.length && text[i + 1] === '\n') { end = i; break }
|
||||||
|
if (/[.!?]/.test(text[i])) { end = i + 1; break }
|
||||||
|
}
|
||||||
|
return countWords(text.slice(start, end))
|
||||||
|
}
|
||||||
|
|
||||||
export function MarkdownEditor(): JSX.Element {
|
export function MarkdownEditor(): JSX.Element {
|
||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const viewRef = useRef<EditorView | null>(null)
|
const viewRef = useRef<EditorView | null>(null)
|
||||||
@@ -685,6 +701,7 @@ export function MarkdownEditor(): JSX.Element {
|
|||||||
const [pendingComment, setPendingComment] = useState<{ from: number; to: number; text: string } | null>(null)
|
const [pendingComment, setPendingComment] = useState<{ from: number; to: number; text: string } | null>(null)
|
||||||
const [commentDraft, setCommentDraft] = useState('')
|
const [commentDraft, setCommentDraft] = useState('')
|
||||||
const [wordStats, setWordStats] = useState<{ atCursor: number; total: number }>({ atCursor: 0, total: 0 })
|
const [wordStats, setWordStats] = useState<{ atCursor: number; total: number }>({ atCursor: 0, total: 0 })
|
||||||
|
const [sentenceWordCount, setSentenceWordCount] = useState<number>(0)
|
||||||
const wordTotalRef = useRef(0)
|
const wordTotalRef = useRef(0)
|
||||||
const { activeFilePath, activeFileContent, setContent, annotations, fontSize, theme, focusMode, scrollPositions, pendingScrollToLine, clearPendingScrollToLine, selectionWordCount, projectWordCount } = useEditorStore()
|
const { activeFilePath, activeFileContent, setContent, annotations, fontSize, theme, focusMode, scrollPositions, pendingScrollToLine, clearPendingScrollToLine, selectionWordCount, projectWordCount } = useEditorStore()
|
||||||
|
|
||||||
@@ -836,6 +853,8 @@ export function MarkdownEditor(): JSX.Element {
|
|||||||
useEditorStore.getState().setSelectionWordCount(words)
|
useEditorStore.getState().setSelectionWordCount(words)
|
||||||
} else {
|
} else {
|
||||||
useEditorStore.getState().setSelectionWordCount(null)
|
useEditorStore.getState().setSelectionWordCount(null)
|
||||||
|
const text = update.state.doc.toString()
|
||||||
|
setSentenceWordCount(getSentenceWordCount(text, to))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// When the user Cmd+Z's through an Apply, invertedEffects fires a
|
// When the user Cmd+Z's through an Apply, invertedEffects fires a
|
||||||
@@ -1147,9 +1166,11 @@ export function MarkdownEditor(): JSX.Element {
|
|||||||
{activeFilePath && (
|
{activeFilePath && (
|
||||||
<div className="editor-statusbar">
|
<div className="editor-statusbar">
|
||||||
<span>word {wordStats.atCursor.toLocaleString()} of {wordStats.total.toLocaleString()}</span>
|
<span>word {wordStats.atCursor.toLocaleString()} of {wordStats.total.toLocaleString()}</span>
|
||||||
{selectionWordCount !== null && (
|
{selectionWordCount !== null ? (
|
||||||
<span className="statusbar-selection-wordcount">{selectionWordCount.toLocaleString()} selected</span>
|
<span className="statusbar-selection-wordcount">{selectionWordCount.toLocaleString()} selected</span>
|
||||||
)}
|
) : sentenceWordCount > 0 ? (
|
||||||
|
<span className="statusbar-selection-wordcount">{sentenceWordCount} in sentence</span>
|
||||||
|
) : null}
|
||||||
<div className="statusbar-right">
|
<div className="statusbar-right">
|
||||||
{(() => {
|
{(() => {
|
||||||
const docWc = countWords(activeFileContent)
|
const docWc = countWords(activeFileContent)
|
||||||
|
|||||||
Reference in New Issue
Block a user