Răsfoiți Sursa

Handle more cases where CSS styles override semantics of pasted elements (#14755)

GitOrigin-RevId: f125d201fe18120c80fe1b681775ca2545da128c
Alf Eaton 3 ani în urmă
părinte
comite
2961a93bb5

+ 10 - 3
services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts

@@ -450,6 +450,7 @@ const selectors = [
     selector: 'b',
     match: element =>
       element.style.fontWeight !== 'normal' &&
+      !(parseInt(element.style.fontWeight) < 700) &&
       !isHeading(element.parentElement) &&
       hasContent(element),
     start: () => '\\textbf{',
@@ -458,14 +459,19 @@ const selectors = [
   createSelector({
     selector: '*',
     match: element =>
-      parseInt(element.style.fontWeight) >= 700 && hasContent(element),
+      (element.style.fontWeight === 'bold' ||
+        parseInt(element.style.fontWeight) >= 700) &&
+      hasContent(element),
     start: () => '\\textbf{',
     end: () => '}',
     inside: true,
   }),
   createSelector({
     selector: 'strong',
-    match: element => hasContent(element),
+    match: element =>
+      element.style.fontWeight !== 'normal' &&
+      !(parseInt(element.style.fontWeight) < 700) &&
+      hasContent(element),
     start: () => '\\textbf{',
     end: () => '}',
   }),
@@ -485,7 +491,8 @@ const selectors = [
   }),
   createSelector({
     selector: 'em',
-    match: element => hasContent(element),
+    match: element =>
+      element.style.fontStyle !== 'normal' && hasContent(element),
     start: () => '\\textit{',
     end: () => '}',
   }),

+ 55 - 0
services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx

@@ -424,6 +424,61 @@ describe('<CodeMirrorEditor/> paste HTML in Visual mode', function () {
     cy.get('.ol-cm-command-textsubscript').should('have.length', 1)
   })
 
+  it('handles pasted text with bold CSS formatting', function () {
+    mountEditor()
+
+    const data =
+      '<span style="font-weight:bold">foo</span> <span style="font-weight:800">foo</span> foo'
+
+    const clipboardData = new DataTransfer()
+    clipboardData.setData('text/html', data)
+    cy.get('@content').trigger('paste', { clipboardData })
+
+    cy.get('@content').should('have.text', 'foo foo foo')
+    cy.get('.ol-cm-command-textbf').should('have.length', 2)
+  })
+
+  it('handles pasted text with italic CSS formatting', function () {
+    mountEditor()
+
+    const data = '<span style="font-style:italic">foo</span> foo'
+
+    const clipboardData = new DataTransfer()
+    clipboardData.setData('text/html', data)
+    cy.get('@content').trigger('paste', { clipboardData })
+
+    cy.get('@content').should('have.text', 'foo foo')
+    cy.get('.ol-cm-command-textit').should('have.length', 1)
+  })
+
+  it('handles pasted text with non-bold CSS', function () {
+    mountEditor()
+
+    const data =
+      '<strong style="font-weight:normal">foo</strong> <strong style="font-weight:200">foo</strong> foo'
+
+    const clipboardData = new DataTransfer()
+    clipboardData.setData('text/html', data)
+    cy.get('@content').trigger('paste', { clipboardData })
+
+    cy.get('@content').should('have.text', 'foo foo foo')
+    cy.get('.ol-cm-command-textbf').should('have.length', 0)
+  })
+
+  it('handles pasted text with non-italic CSS', function () {
+    mountEditor()
+
+    const data =
+      '<em style="font-style:normal">foo</em> <i style="font-style:normal">foo</i> foo'
+
+    const clipboardData = new DataTransfer()
+    clipboardData.setData('text/html', data)
+    cy.get('@content').trigger('paste', { clipboardData })
+
+    cy.get('@content').should('have.text', 'foo foo foo')
+    cy.get('.ol-cm-command-textit').should('have.length', 0)
+  })
+
   it('removes a non-breaking space when a text node contains no other content', function () {
     mountEditor()