Skip to content

Commit 44eca37

Browse files
mecskyversemecskyversetalldanMamadukaannezazu
authored
Headings support for Word Online while pasting. (#70771)
Co-authored-by: mecskyverse <aakashverma1@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> Co-authored-by: mrwweb <mrwweb@git.wordpress.org>
1 parent 0c606a3 commit 44eca37

4 files changed

Lines changed: 53 additions & 9 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Transforms paragraphs with heading semantics into proper heading tags.
3+
*
4+
* This handles cases where content (like from Microsoft Word Online) comes in as
5+
* <p> tags with role="heading" and aria-level attributes, and converts them to
6+
* proper <h1>, <h2>, etc. tags.
7+
*
8+
* @param {Node} node The node to check and potentially transform.
9+
*/
10+
export default function headingTransformer( node ) {
11+
if ( node.nodeType !== node.ELEMENT_NODE ) {
12+
return;
13+
}
14+
15+
// Check if this is a paragraph with heading semantics.
16+
if (
17+
node.tagName === 'P' &&
18+
node.getAttribute( 'role' ) === 'heading' &&
19+
node.hasAttribute( 'aria-level' )
20+
) {
21+
const level = parseInt( node.getAttribute( 'aria-level' ), 10 );
22+
23+
// To ensure valid heading level (1-6).
24+
if ( level >= 1 && level <= 6 ) {
25+
const headingTag = `H${ level }`;
26+
const newHeading = node.ownerDocument.createElement( headingTag );
27+
28+
// Copying all attributes except role and aria-level.
29+
Array.from( node.attributes ).forEach( ( attr ) => {
30+
if ( attr.name !== 'role' && attr.name !== 'aria-level' ) {
31+
newHeading.setAttribute( attr.name, attr.value );
32+
}
33+
} );
34+
35+
while ( node.firstChild ) {
36+
newHeading.appendChild( node.firstChild );
37+
}
38+
39+
// Replacing the paragraph with the heading.
40+
node.parentNode.replaceChild( newHeading, node );
41+
}
42+
}
43+
}

‎packages/blocks/src/api/raw-handling/paste-handler.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import emptyParagraphRemover from './empty-paragraph-remover';
3434
import slackParagraphCorrector from './slack-paragraph-corrector';
3535
import isLatexMathMode from './latex-to-math';
3636
import { createBlock } from '../factory';
37+
import headingTransformer from './heading-transformer';
3738

3839
const log = ( ...args ) => window?.console?.log?.( ...args );
3940

@@ -204,6 +205,7 @@ export function pasteHandler( {
204205
figureContentReducer,
205206
blockquoteNormaliser(),
206207
divNormaliser,
208+
headingTransformer,
207209
];
208210

209211
const schema = {

‎packages/blocks/src/api/raw-handling/readme.md‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@ This folder contains all paste specific logic (filters, converters, normalisers.
99
| Google Docs | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ [1] |
1010
| Apple Pages | ✓ | ✘ [2] | ✓ | ✘ [2] | n/a | ✓ | ✘ [1] |
1111
| MS Word | ✓ | ✓ | ✓ | ✓ | n/a | ✓ | ✓ |
12-
| MS Word Online | ✓ | ✘ [4] | ✓ | ✓ | n/a | ✓ | ✘ [1] |
12+
| MS Word Online | ✓ | ✓ | ✓ | ✓ | n/a | ✓ | ✘ [1] |
1313
| LibreOffice | ✓ | ✓ | ✓ | ✘ [3] | ✓ | ✓ | ✓ |
14-
| Evernote | ✓ | ✘ [5] | ✓ | ✓ | ✓ | ✓ | n/a |
14+
| Evernote | ✓ | ✘ [4] | ✓ | ✓ | ✓ | ✓ | n/a |
1515
| Markdown | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | n/a |
16-
| Legacy WordPress | ✓ | ✓ | ✓ | … [6] | ✓ | ✓ | n/a |
16+
| Legacy WordPress | ✓ | ✓ | ✓ | … [5] | ✓ | ✓ | n/a |
1717
| Web | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | n/a |
1818

1919
1. Google Docs, Apple Pages and MS Word online don't pass footnote nor endnote information.
2020
2. Apple Pages does not pass heading and image information.
2121
3. LibreOffice only provide a local file path, which cannot be accessed in JavaScript for security reasons. Image placeholders will be provided instead. Single images, however, _can_ be copied and pasted without any problem.
22-
4. Still to do for MS Word Online.
23-
5. Evernote does not have headings.
24-
6. For caption and gallery shortcodes, see #2874.
22+
4. Evernote does not have headings.
23+
5. For caption and gallery shortcodes, see #2874.
2524

2625
## Other notable capabilities
2726

‎test/integration/fixtures/documents/ms-word-online-out.html‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<!-- wp:paragraph -->
2-
<p>This is a <em>heading</em>&nbsp;</p>
3-
<!-- /wp:paragraph -->
1+
<!-- wp:heading {"level":1} -->
2+
<h1 class="wp-block-heading">This is a <em>heading</em>&nbsp;</h1>
3+
<!-- /wp:heading -->
44

55
<!-- wp:paragraph -->
66
<p>This is a <strong>paragraph </strong>with a <a href="https://w.org/" target="_blank" rel="noreferrer noopener">link</a>.&nbsp;</p>

0 commit comments

Comments
 (0)