diff --git a/tinymce-per-block/README.md b/tinymce-per-block/README.md index 5e394708c698d..e3c44a5460644 100644 --- a/tinymce-per-block/README.md +++ b/tinymce-per-block/README.md @@ -16,23 +16,85 @@ Examples: - [Text Block](./src/blocks/text-block) - [Image Block](./src/blocks/image-block) -## Status +## Data Flow -This prototype currently implements: +![TinyMCE per block Data Flow](./doc/data-flow.png) -- Content parsing -- Block registration -- Editor block list rendering -- Binding TinyMCE to blocks ([see `wp-blocks/bind-editable`](./src/external/wp-blocks/bind-editable)) -- Block-level control changes (e.g. text centering) -- Serializing block content +## Block API -The prototype lacks: +### Registering a block +We do so by calling `wpblocks.registerBlock` with a name and an object defining the block to be registered. This object has the following attributes: + + * title: A string representing the label of the block + * icon: The wpblocks component to display the icon of the block + * form: The wpblocks component to display the block form (controls and contenteditables) + * parse: A function that takes a raw grammar block as argument and returns the parsed block (if this function returns `false` we fallback to an HTML block) + * serialize: The opposite of `parse`, transforms the current block to a raw grammar block + * create: A function that returns an empty block object + * transformations: An array of possible transformations. A transformation is the ability for a block to be switched to another block (for example, transforming a heading block to a text block) + * merge: When the user hits backspace at the beginning of the blocks, the current block needs to be merged with the previous blocks. This attribute is an array of possible merge functions depending on the blockType. + + +### The Block Form component + +It’s a wpblocks component (Abstraction of React for now, could be any vdom library) responsible of rendering the block form to edit the content of the blocks. + +For example, a text block can show a TinyMCE instance. A quote block can render a TinyMCE instance for the content and a simple textarea for the cite etc… +Editor commands + +The form component can trigger commands in response to any user event. For now the editor can handle these type of commands: change, append, remove, mergeWithPrevious, focus, moveCurosrUp, moveCurosrDown, moveBlockUp, moveBlockDown, select, unselect, hover, unhover. + +#### Commands + +The form receives an `api` object as a prop containing the different commands callbacks. + +*change:* This command is triggered when the block changes, for example when the user type into the tinymce instance of a text block, or any attribute change. + +*appendBlock:* This command should be triggered to append a new block right after the current block, for example when hitting “Enter” on a paragraph block + +*remove:* This command should be triggered to remove the current block, for example when typing “backspace” on an empty paragraph block + +*mergeWithPrevious:* This command should be triggered to ask for a merging the current block with the previous one. For example when we hit “backspace” and we’re focusing the beginning of a block paragraph + +*focus:* This command should be triggered to focus the current block, the focus config is a free object passed as an argument to this helper, it contains all the data necessary to focus the current block at the right position. + +*moveCursorUp:* This command should be triggered to ask for moving the cursor to the previous block for example when we hit the “up” arrow and we’re focusing the beginning of a block paragraph. + +*moveCursorDown:* This command should be triggered to ask for moving the cursor to the next block for example when we hit the “down” arrow and we’re focusing the end of a block paragraph. +Block form interface +A block form should also implement some functions in response to other block commands: + +*moveBlockUp:* Moves the block up + +*moveBlockDown:* Moves the block down + +*select:* Selects the current block + +*unselect:* Unselects the current block + +*hover:* to be called when the current block is hovered + +*unhover:* to be called when the current block is "unhovered" + +#### Form Props + +The form also receives the following props: + +*isFocused and focusConfig:* A block form should watch changes to these props and focus in consequence. +Utils + +*isSelected:* Whether the block is selected + +*isHovevered:* Whether the block is hovered + +To ease writing block forms in the context of this prototype, we could reuse the two generic components: + +#### Helpers + +**EditableComponent:** which is an enhanced TinyMCE wrapper to catch different events (moveUp, moveDown, remove, mergeWithPrevious …) + +**EnhancedInputComponent:** which is an autogrowing textarea wrapper. It also catches the different events (moveUp, moveDown, removePrevious, ….) -- Block reordering -- Inserting new blocks (including creating or splitting paragraphs) -- Selecting across paragraphs of text -- Backwards compatibility for non-block content ## Development diff --git a/tinymce-per-block/doc/data-flow.png b/tinymce-per-block/doc/data-flow.png new file mode 100644 index 0000000000000..53c3b35d997bd Binary files /dev/null and b/tinymce-per-block/doc/data-flow.png differ diff --git a/tinymce-per-block/doc/data-flow.xml b/tinymce-per-block/doc/data-flow.xml new file mode 100644 index 0000000000000..9d0af7d608248 --- /dev/null +++ b/tinymce-per-block/doc/data-flow.xml @@ -0,0 +1 @@ +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 \ No newline at end of file