diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
index ff2c1e8ff7..822ea19365 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
@@ -36,17 +36,18 @@ export const pasteHtml = [
return false
}
- // allow pasting an image to create a figure, if the HTML doesn't contain a table
- // (because desktop Excel puts both an image and the HTML table on the clipboard)
- if (clipboardData.files.length > 0 && !html.includes('
0 && !hasProgId(documentElement)) {
+ return false
+ }
+
// if the only content is in a code block, use the plain text version
if (onlyCode(documentElement)) {
return false
@@ -55,7 +56,7 @@ export const pasteHtml = [
const latex = htmlToLaTeX(documentElement)
// if there's no formatting, use the plain text version
- if (latex === text) {
+ if (latex === text && clipboardData.files.length === 0) {
return false
}
@@ -112,6 +113,13 @@ const onlyCode = (documentElement: HTMLElement) => {
)
}
+const hasProgId = (documentElement: HTMLElement) => {
+ const meta = documentElement.querySelector(
+ 'meta[name="ProgId"]'
+ )
+ return meta && meta.content.trim().length > 0
+}
+
const htmlToLaTeX = (documentElement: HTMLElement) => {
// remove style elements
removeUnwantedElements(documentElement, 'style')
diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx
index 0a3896b400..01a7800977 100644
--- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx
+++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx
@@ -29,6 +29,7 @@ describe(' paste HTML in Visual mode', function () {
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
window.metaAttributesCache.set('ol-splitTestVariants', {
'paste-html': 'enabled',
+ 'figure-modal': 'enabled',
})
cy.interceptEvents()
cy.interceptSpelling()
@@ -659,4 +660,38 @@ describe(' paste HTML in Visual mode', function () {
cy.get('.cm-line').should('have.length', 8)
})
+
+ it('treats a pasted image as a figure even if there is HTML', function () {
+ mountEditor()
+
+ cy.fixture('images/gradient.png').then(image => {
+ const file = new File([image], 'gradient.png', { type: 'image/png' })
+ const html = ``
+
+ const clipboardData = new DataTransfer()
+ clipboardData.setData('text/html', html)
+ clipboardData.items.add(file)
+ cy.get('.cm-content').trigger('paste', { clipboardData })
+
+ // figure modal paste handler should appear
+ cy.findByText('Upload from computer').should('be.visible')
+ })
+ })
+
+ it('does not treat a pasted image as a figure if there is Office HTML', function () {
+ mountEditor()
+
+ cy.fixture('images/gradient.png').then(image => {
+ const file = new File([image], 'gradient.png', { type: 'image/png' })
+ const html = ``
+
+ const clipboardData = new DataTransfer()
+ clipboardData.setData('text/html', html)
+ clipboardData.items.add(file)
+ cy.get('.cm-content').trigger('paste', { clipboardData })
+
+ // paste options button should appear
+ cy.findByLabelText('Paste options').should('be.visible')
+ })
+ })
})