Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mobile] - Adds new bridge functionality for content #61796

Merged
merged 8 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions packages/edit-post/src/test/__snapshots__/editor.native.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,75 @@ exports[`Editor appends media correctly for allowed types and skips unsupported
<figure class="wp-block-video"><video controls src="file:///local-video-4.mp4"></video></figure>
<!-- /wp:video -->"
`;

exports[`Editor on content update parses markdown into blocks 1`] = `
"<!-- wp:paragraph -->
<p>Lorem ipsum dolor sit amet, consectetur adipiscing<br />elit.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Overview</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Lorem ipsum dolor sit amet</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Consectetur adipiscing<br>elit</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Integer nec odio</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Details</h2>
<!-- /wp:heading -->

<!-- wp:list {"ordered":true} -->
<ol class="wp-block-list"><!-- wp:list-item -->
<li>Sed cursus ante dapibus diam</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Nulla quis sem at nibh elementum imperdiet</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Duis sagittis ipsum <code>## Mixed Lists</code></li>
<!-- /wp:list-item --></ol>
<!-- /wp:list -->

<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Key Points:</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:list {"ordered":true} -->
<ol class="wp-block-list"><!-- wp:list-item -->
<li>Lorem ipsum dolor sit amet</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><br>Consectetur adipiscing elit</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Integer nec odio</li>
<!-- /wp:list-item --></ol>
<!-- /wp:list -->

<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Additional Info:<br>-<br>Sed cursus ante dapibus diam</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Nulla quis sem at nibh elementum imperdiet</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->"
`;
77 changes: 77 additions & 0 deletions packages/edit-post/src/test/editor.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
fireEvent,
getBlock,
getEditorHtml,
getEditorTitle,
initializeEditor,
screen,
setupCoreBlocks,
Expand All @@ -20,6 +21,7 @@ import {
requestMediaImport,
subscribeMediaAppend,
subscribeParentToggleHTMLMode,
subscribeToContentUpdate,
} from '@wordpress/react-native-bridge';

setupCoreBlocks();
Expand All @@ -34,6 +36,11 @@ subscribeMediaAppend.mockImplementation( ( callback ) => {
mediaAppendCallback = callback;
} );

let onContentUpdateCallback;
subscribeToContentUpdate.mockImplementation( ( callback ) => {
onContentUpdateCallback = callback;
} );

const MEDIA = [
{
localId: 1,
Expand Down Expand Up @@ -149,4 +156,74 @@ describe( 'Editor', () => {
screen.queryAllByLabelText( 'Open Settings' );
expect( openBlockSettingsButton.length ).toBe( 0 );
} );

describe( 'on content update', () => {
const MARKDOWN = `# Sample Document\nLorem ipsum dolor sit amet, consectetur adipiscing
elit.\n## Overview\n- Lorem ipsum dolor sit amet\n- Consectetur adipiscing
elit\n- Integer nec odio\n## Details\n1. Sed cursus ante dapibus diam\n2.
Nulla quis sem at nibh elementum imperdiet\n3. Duis sagittis ipsum\n
## Mixed Lists\n- Key Points:\n 1. Lorem ipsum dolor sit amet\n 2.
Consectetur adipiscing elit\n 3. Integer nec odio\n- Additional Info:\n -
Sed cursus ante dapibus diam\n - Nulla quis sem at nibh elementum imperdiet\n`;

it( 'parses markdown into blocks', async () => {
// Arrange
await initializeEditor( {
initialTitle: null,
} );

// Act
act( () => {
onContentUpdateCallback( {
content: MARKDOWN,
} );
} );

// Assert
// Needed to for the "Processed HTML piece" log.
expect( console ).toHaveLogged();
expect( getEditorTitle() ).toBe( 'Sample Document' );
expect( getEditorHtml() ).toMatchSnapshot();
} );

it( 'parses a markdown heading into a title', async () => {
// Arrange
await initializeEditor( {
initialTitle: null,
} );

// Act
act( () => {
onContentUpdateCallback( {
content: `# Sample Document`,
} );
} );

// Assert
// Needed to for the "Processed HTML piece" log.
expect( console ).toHaveLogged();
expect( getEditorTitle() ).toBe( 'Sample Document' );
expect( getEditorHtml() ).toBe( '' );
} );

it( 'parses standard text into blocks', async () => {
// Arrange
await initializeEditor( {
initialTitle: null,
} );

// Act
act( () => {
onContentUpdateCallback( {
content: `Lorem ipsum dolor sit amet`,
} );
} );

// Assert
// Needed to for the "Processed HTML piece" log.
expect( console ).toHaveLogged();
expect( getEditorTitle() ).toBe( 'Lorem ipsum dolor sit amet' );
expect( getEditorHtml() ).toBe( '' );
} );
} );
} );
101 changes: 68 additions & 33 deletions packages/editor/src/components/post-title/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,67 @@ import { store as blockEditorStore, RichText } from '@wordpress/block-editor';
import { store as editorStore } from '@wordpress/editor';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';

/** @typedef {import('./types').RichTextValue} RichTextValue */

/**
* Internal dependencies
*/
import styles from './style.scss';

/**
* Inserts content with title
*
* This function processes the given content and title, updating the title
* and content based on certain conditions. If the content is an array of
* blocks, it will check the first block for a heading or paragraph to use
* as the title. If the content is a string, it will strip HTML and update
* the title and content accordingly.
*
* @param {string} title The post title.
* @param {Array | string} content The content to be processed. It can be an array of blocks or a string.
* @param {Function} onUpdateTitle Callback function to update the title.
* @param {Function} onUpdateContent Callback function to update the content.
* @param {RichTextValue} value The initial value object, default is an object with empty text.
*/
export function insertContentWithTitle(
title,
content,
onUpdateTitle,
onUpdateContent,
value = create( { text: '' } )
) {
if ( ! content.length ) {
return;
}

if ( typeof content !== 'string' ) {
const [ firstBlock ] = content;

if (
! title &&
( firstBlock.name === 'core/heading' ||
firstBlock.name === 'core/paragraph' )
) {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = stripHTML( firstBlock.attributes.content );
onUpdateTitle( contentNoHTML );
onUpdateContent( content.slice( 1 ) );
} else {
onUpdateContent( content );
}
} else {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = stripHTML( content );

const newValue = insert( value, create( { html: contentNoHTML } ) );
onUpdateTitle( toHTMLString( { value: newValue } ) );
}
}

class PostTitle extends Component {
constructor( props ) {
super( props );
Expand Down Expand Up @@ -59,45 +115,24 @@ class PostTitle extends Component {
}

onPaste( { value, plainText, html } ) {
const { title, onInsertBlockAfter, onUpdate } = this.props;
const {
title,
onInsertBlockAfter: onInsertBlocks,
onUpdate,
} = this.props;

const content = pasteHandler( {
HTML: html,
plainText,
} );

if ( ! content.length ) {
return;
}

if ( typeof content !== 'string' ) {
const [ firstBlock ] = content;

if (
! title &&
( firstBlock.name === 'core/heading' ||
firstBlock.name === 'core/paragraph' )
) {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = stripHTML(
firstBlock.attributes.content
);
onUpdate( contentNoHTML );
onInsertBlockAfter( content.slice( 1 ) );
} else {
onInsertBlockAfter( content );
}
} else {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = stripHTML( content );

const newValue = insert( value, create( { html: contentNoHTML } ) );
onUpdate( toHTMLString( { value: newValue } ) );
}
insertContentWithTitle(
title,
content,
onUpdate,
onInsertBlocks,
value
);
}

setRef( richText ) {
Expand Down
Loading
Loading