mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #30495 from overleaf/mg-context-menu-paste
[web] Support paste with formatting in context menu GitOrigin-RevId: 551ed1d49ca423395bd9bfc756e10e8d59d71ecd
This commit is contained in:
@@ -81,6 +81,27 @@ function isPositionInsideSelection(pos: number, from: number, to: number) {
|
||||
return from !== to && pos >= from && pos <= to
|
||||
}
|
||||
|
||||
function isPositionInsideAnyRangeOrCursor(view: EditorView, pos: number) {
|
||||
for (const range of view.state.selection.ranges) {
|
||||
// If it's a cursor, treat a right-click anywhere on the same line as "inside".
|
||||
// This avoids collapsing multi-cursor selections when right-clicking on blank lines
|
||||
// or to the right of the caret.
|
||||
if (range.from === range.to) {
|
||||
const clickedLine = view.state.doc.lineAt(pos)
|
||||
const cursorLine = view.state.doc.lineAt(range.from)
|
||||
if (clickedLine.number === cursorLine.number) {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (isPositionInsideSelection(pos, range.from, range.to)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function selectEntireLine(
|
||||
view: EditorView,
|
||||
pos: number
|
||||
@@ -171,8 +192,7 @@ const editorContextMenuHandlers = (): Extension =>
|
||||
return false
|
||||
}
|
||||
|
||||
const { from, to } = view.state.selection.main
|
||||
const clickedInsideSelection = isPositionInsideSelection(pos, from, to)
|
||||
const clickedInsideSelection = isPositionInsideAnyRangeOrCursor(view, pos)
|
||||
|
||||
// Set cursor to clicked position if outside selection
|
||||
let selection: TransactionSpec['selection'] = { anchor: pos }
|
||||
|
||||
@@ -45,35 +45,17 @@ export const pasteHtml = [
|
||||
return false
|
||||
}
|
||||
|
||||
// convert the HTML to LaTeX
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const { documentElement } = parser.parseFromString(html, 'text/html')
|
||||
const latex = convertHtmlStringToLatex(
|
||||
html,
|
||||
clipboardData.files.length
|
||||
)
|
||||
|
||||
// fall back to creating a figure when there's an image on the clipoard,
|
||||
// unless the HTML indicates that it came from an Office application
|
||||
// (which also puts an image on the clipboard)
|
||||
if (
|
||||
clipboardData.files.length > 0 &&
|
||||
!hasProgId(documentElement) &&
|
||||
!isOnlyTable(documentElement)
|
||||
) {
|
||||
// if there's no latex conversion, use plain text version
|
||||
if (latex === null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const bodyElement = documentElement.querySelector('body')
|
||||
// DOMParser should always create a body element, so this is mostly for TypeScript
|
||||
if (!bodyElement) {
|
||||
return false
|
||||
}
|
||||
|
||||
// if the only content is in a code block, use the plain text version
|
||||
if (onlyCode(bodyElement)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const latex = htmlToLaTeX(bodyElement)
|
||||
|
||||
// if there's no formatting, use the plain text version
|
||||
if (latex === text && clipboardData.files.length === 0) {
|
||||
return false
|
||||
@@ -95,6 +77,37 @@ export const pasteHtml = [
|
||||
pastedContent,
|
||||
]
|
||||
|
||||
export function convertHtmlStringToLatex(
|
||||
html: string,
|
||||
filesLength: number
|
||||
): string | null {
|
||||
const parser = new DOMParser()
|
||||
const { documentElement } = parser.parseFromString(html, 'text/html')
|
||||
|
||||
// Do not process HTML as LaTeX when the clipboard contains files (e.g. images),
|
||||
// unless the HTML is from an Office application or is a table-only selection.
|
||||
if (
|
||||
filesLength > 0 &&
|
||||
!hasProgId(documentElement) &&
|
||||
!isOnlyTable(documentElement)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
const bodyElement = documentElement.querySelector('body')
|
||||
// DOMParser should always create a body element, so this is mostly for TypeScript
|
||||
if (!bodyElement) {
|
||||
return null
|
||||
}
|
||||
|
||||
// If the only content is a code block, skip latex conversion
|
||||
if (onlyCode(bodyElement)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return htmlToLaTeX(bodyElement)
|
||||
}
|
||||
|
||||
const removeUnwantedElements = (
|
||||
documentElement: HTMLElement,
|
||||
selector: string
|
||||
|
||||
Reference in New Issue
Block a user