mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-14 22:23:42 +01:00
Merge pull request #32135 from overleaf/mg-comment-empty-select
Allow adding comments on empty selection GitOrigin-RevId: 14e742bb563fab99624be860691f1a9d2dabc00e
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { EditorState } from '@codemirror/state'
|
||||
|
||||
/**
|
||||
* Returns true when the cursor is on an empty line with no active selection.
|
||||
*
|
||||
* Used to disable the "Add comment" action — there is nothing to anchor a
|
||||
* comment to on a blank line.
|
||||
*/
|
||||
export function isCursorOnEmptyLine(state: EditorState): boolean {
|
||||
const { main } = state.selection
|
||||
|
||||
if (!main.empty) {
|
||||
return false
|
||||
}
|
||||
|
||||
const line = state.doc.lineAt(main.head)
|
||||
return line.text.trim().length === 0
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
import { EditorState } from '@codemirror/state'
|
||||
import { isCursorOnEmptyLine } from './is-cursor-on-empty-line'
|
||||
|
||||
/**
|
||||
* Returns the current highlighted range, or the nearest non-whitespace token
|
||||
* to the cursor when there is no active selection.
|
||||
*
|
||||
* "Token" here means any contiguous run of non-whitespace characters (`/\S+/`),
|
||||
* not necessarily an alphanumeric word. When two tokens are equidistant the
|
||||
* earlier one (closer to document start) wins.
|
||||
*
|
||||
* Only searches the current line.
|
||||
*
|
||||
* Only called on user-initiated actions (e.g. "Add comment"), not on every render.
|
||||
* Returns null when the cursor is on an empty/whitespace-only line.
|
||||
*/
|
||||
export function selectHighlightedOrNearestToken(
|
||||
state: EditorState
|
||||
): { from: number; to: number } | null {
|
||||
if (isCursorOnEmptyLine(state)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const { main } = state.selection
|
||||
|
||||
if (!main.empty) {
|
||||
return { from: main.from, to: main.to }
|
||||
}
|
||||
|
||||
const pos = main.head
|
||||
const line = state.doc.lineAt(pos)
|
||||
|
||||
let bestFrom = 0
|
||||
let bestTo = 0
|
||||
let bestDist = Infinity
|
||||
|
||||
for (const match of line.text.matchAll(/\S+/g)) {
|
||||
const from = line.from + match.index!
|
||||
const to = from + match[0].length
|
||||
|
||||
let dist = 0
|
||||
if (pos < from) {
|
||||
dist = from - pos
|
||||
} else if (pos > to) {
|
||||
dist = pos - to
|
||||
}
|
||||
|
||||
if (dist === 0) {
|
||||
return { from, to }
|
||||
}
|
||||
|
||||
if (dist < bestDist) {
|
||||
bestFrom = from
|
||||
bestTo = to
|
||||
bestDist = dist
|
||||
}
|
||||
|
||||
// Past the cursor — no closer match possible on this line
|
||||
if (from > pos) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (bestDist < Infinity) {
|
||||
return { from: bestFrom, to: bestTo }
|
||||
}
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user