Repackages Gutenberg's editor playground as a full-featured multi-instance editor that does not require WordPress.
The key features are:
And a full list of features:
The Isolated Block Editor is provided in three forms:
This library only works with the specific versions of Gutenberg listed below.
Requires: Gutenberg 16.9
Examples:
textarea
on any page with a full Gutenberg editorDo you use this in your own project? Let us know!
Gutenberg already provides a playground which allows it to be used outside of WordPress. This is actually used as the basis for the Isolated Block Editor.
However, it provides a limited set of features, and extending it further into a usable editor can take some effort. For example, it doesn't include any undo history.
The Isolated Block Editor is a full editor that handles a lot of these complexities. It should not be considered a replacement for the Gutenberg playground, but more of an opinionated layer on top.
This should be considered experimental, and subject to changes.
The Isolated Block Editor aims to provide an editor that is as isolated from WordPress as possible. However, it can still be used on a WordPress site, and the decision comes down to the bundling:
Examples are provided for both situations (see Plain text editor for bundled and Blocks Everywhere for unbundled).
The key difference is in the Webpack config. If you don't want to bundle Gutenberg with your editor then you can use the DependencyExtractionWebpackPlugin
plugin:
plugins: [
new DependencyExtractionWebpackPlugin( { injectPolyfill: true } )
]
Alternatively you can use the @wordpress/scripts
build system, which automatically runs DependencyExtractionWebpackPlugin
:
wp-scripts start
You can use the provided iso-gutenberg.php
file to help when using the IsolatedBlockEditor on a WordPress site. It will load Gutenberg and set up your configuration.
You can use the provided isolated-block-editor.js
, core.css
, and isolated-block-editor.css
files on any web page, regardless of whether it is on WordPress. It will provide two global functions which can turn a textarea
into a block editor. Here's an example:
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://github.com/Automattic/isolated-block-editor/raw/trunk/isolated-block-editor.js"></script>
<link rel="stylesheet" href="https://github.com/Automattic/isolated-block-editor/blob/trunk/core.css" />
<link rel="stylesheet" href="https://github.com/Automattic/isolated-block-editor/blob/trunk/isolated-block-editor.css" />
<body>
<textarea id="editor"></textarea>
<script>
wp.attachEditor( document.getElementById( 'editor' ) );
</script>
</body>
Note that you must load React before loading the editor.
You can find an example in src/browser/index.html
.
If you are using on a WordPress site then WordPress will load the core Gutenberg CSS as part of the iso-gutenberg.php
script.
If you are not using on a WordPress site then you will need to load the core CSS yourself. You can either do this by including the following modules and importing directly:
@wordpress/components
@wordpress/block-editor
@wordpress/block-library
@wordpress/format-library
@import '@wordpress/components/build-style/style.css';
@import '@wordpress/block-editor/build-style/style.css';
@import '@wordpress/block-library/build-style/style.css';
@import '@wordpress/block-library/build-style/editor.css';
@import '@wordpress/block-library/build-style/theme.css';
@import '@wordpress/format-library/build-style/style.css';
Alternatively you can directly import the bundled build-browser/core.css
CSS:
import '@automattic/isolated-block-editor/build-browser/core.css';
The module is currently only available on Github and can be added with:
npm install @automattic/isolated-block-editor@1.2.0 --save
(where 1.2.0
is the version you want to use)
The code here deals with two kinds of problems:
It is hoped that most of the workarounds can be migrated back to Gutenberg so that they are no longer needed. Sometimes these workarounds involve duplicating parts of Gutenberg, which is not ideal. It is possible that the Isolated Block Editor may no longer be needed as a seperate entity.
If multiple editors are on-screen then the IsolatedBlockEditor
will ensure that the wp
global refers to the currently focussed instance. This should make it more compatible with plugins and third-party code that uses the wp
global.
Include the IsolatedBlockEditor
module and then create an instance:
import IsolatedBlockEditor from '@automattic/isolated-block-editor';
render(
<IsolatedBlockEditor
settings={ settings }
onSaveContent={ ( html ) => saveContent( html ) }
onLoad={ ( parse ) => loadInitialContent( parse ) }
onError={ () => document.location.reload() }
>
</IsolatedBlockEditor>,
document.querySelector( '#editor' )
);
The IsolatedBlockEditor
also exports the following support components:
EditorLoaded
- Include this to be notified when the editor is loading and has loadedDocumentSection
- Wrap up a component to appear in the document tab of the inspectorToolbarSlot
- Insert content into the toolbarFooterSlot
- Insert content into the footerEditorHeadingSlot
- Insert content at the beginning of the editor area. Suitable for titles.ActionArea
- Insert content into the actions sidebar
import IsolatedBlockEditor, { EditorLoaded, DocumentSection, ToolbarSlot } from 'isolated-block-editor';
render(
<IsolatedBlockEditor
settings={ settings }
onSaveContent={ ( html ) => saveContent( html ) }
onLoad={ ( parse ) => loadInitialContent( parse ) }
onError={ () => document.location.reload() }
>
<EditorLoaded onLoaded={ () => {} } onLoading={ () => {} } />
<DocumentSection>Extra Information</DocumentSection>
<ToolbarSlot>
<button>Beep!</button>
</ToolbarSlot>
</IsolatedBlockEditor>,
document.querySelector( '#editor' )
);
The following function is also provided:
initializeEditor
- Call this to initialize the editor if it needs to be done before being used.iso [object]
- IsolatedBlockEditor settings object
iso.preferencesKey [string|null]
- Preferences key. Default to null to disable
iso.defaultPreferences {object} - Default preferences
iso.persistenceKey [string|null]
- Persistence key. Default to null to disable
iso.customStores [array]
- Array of store objects, in a form suitable for passing to Gutenberg's createReduxStore
iso.blocks [object]
- Block restrictions
iso.blocks.allowBlocks [string[]]
- list of block names to allow, defaults to none
iso.blocks.disallowBlocks [string[]]
- list of block names to disallow, defaults to none
iso.disallowEmbed [string[]]
- List of embed names to remove, defaults to none.
iso.toolbar [Object]
- Toolbar settings
iso.toolbar.navigation [boolean]
- Enable or disable the toolbar navigation button, defaults to false
iso.toolbar.undo [boolean]
- Enable or disable the toolbar undo/redo buttons, defaults to true
iso.toolbar.documentInspector [string|null]
- Set to a string to show as a new tab in the inspector and filled with DocumentSection
, otherwise defaults to no new tab
iso.sidebar [Object]
- Sidebar settings
iso.sidebar.inserter [boolean]
- Enable or disable the sidebar block inserter, defaults to true
iso.sidebar.inspector [boolean]
- Enable or disable the sidebar block inspector, defaults to false
iso.sidebar.customComponent [function]
- A function returning a custom sidebar component, or null to uses the default sidebar
iso.moreMenu [Object]
- More menu settings
iso.moreMenu.editor [boolean]
- Enable or disable the editor sub menu (visual/code editing), defaults to false
iso.moreMenu.fullscreen [boolean]
- Enable or disable the fullscreen option, defaults to false
iso.moreMenu.preview [boolean]
- Enable or disable the preview option, defaults to false
iso.moreMenu.topToolbar [boolean]
- Enable or disable the 'top toolbar' option, defaults to false
iso.linkMenu [array]
- Link menu settings. Array of title
and url
, defaults to none
iso.currentPattern [string]
- The pattern to start with, defaults to none
iso.allowApi [boolean]
- Allow API requests, defaults to false
editor [object]
- Gutenberg settings object
A settings object that contains all settings for the IsolatedBlockEditor, as well as for Gutenberg. Any settings not provided will use defaults.
The block allow and disallow list works as follows:
allowBlocks
option is set which defines the list of allowed blocksdisallowBlocks
list is removed from the list of allowed blocks.Save callback that saves the content as an HTML string. Will be called for each change in the editor content.
[Array]
- blocks to be saved[Array]
- array of HTML strings of content that can be ignoredSave callback that is supplied with a list of blocks and a list of ignored content. This gives more control than onSaveContent
, and is used if you want to filter the saved blocks. For example,
if you are using a template then it will appear in the ignoredContent
, and you can then ignore the onSaveBlocks
call if it matches the blocks
.
[string]
- Gutenberg parse
function that parses HTML as a string and returns blocksLoad the initial content into the editor. This is a callback that runs after the editor has been created, and is supplied with a parse
function that is specific to this editor instance. This should
be used so that the appropriate blocks are available.
An alternative history undo/redo manager to be used by the editor. The passed in object must contain an undo
and a redo
methods, as well as a undoStack
and a redoStack
array properties containing the corresponding history. If not provided, the default history management will be used. This property is experimental and can change or be removed at any time.
An optional callback that will be passed down to the Gutenberg editor if provided.This property is experimental and can change or be removed at any time.
An optional callback that will be passed down to the Gutenberg editor if provided.This property is experimental and can change or be removed at any time.
An optional value (blocks) for the editor to show. If provided, it will be used as the internal value/blocks to display.This property is experimental and can change or be removed at any time.
An optional callback that will be called when the selection changes in the editor. The only parameter passed to the callback will be the new selection value.
Callback if an error occurs.
Additional class name attached to the editor.
[object]
- settings for this particular editor[func]
- Callback to close the more menuRender additional components in the more menu.
Note: this needs improving or replacing with something more flexible
Add any components to customise the editor. These components will have access to the editor's Redux store.
If you want to make use of a media uploader and media library then you must set this up similar using the editor.MediaUpload
filter. For example, if you want to use the Gutenberg media library then this would be:
import { MediaUpload } from '@wordpress/media-utils';
addFilter( 'editor.MediaUpload', 'your-namespace/media-upload', () => MediaUpload );
You will also need to pass in the media uploader as part of the editor settings:
import { mediaUpload } from '@wordpress/editor';
const settings = { your settings };
settings.editor.mediaUpload = mediaUpload;
In versions earlier than 2.21.0 this was automatically done, but this meant that you were unable to modify or disable it.
By default the editor will use the Gutenberg settings sidebar. This provides the block and document inspector tabs, along with associated content.
If you wish to customise this sidebar then you can use the iso.sidebar.customComponent
setting and pass a function that returns a React component.
You will need to manage the display of the sidebar yourself, including whether it should appear or not. It may help to look at the existing sidebar code for reference.
For example:
sidebar: {
customComponent: () => <div>My custom sidebar</div>
},
Custom behaviour can be added through child components. These components will have access to the isolated/editor
store, as well as to the editor instance versions of core/block-editor
.
Gutenberg uses iframes to display various parts of the editor, and it uses the global window.__editorAssets
to store styles and scripts that will be added to this iframe. You may need to also
use this.
The default is:
window.__editorAssets = { styles: '', scripts: '' }
The values should be full <link>
and <script>
tags.
To make a release, ensure you are on the trunk branch. Do not update the version number in package.json
- the release process will do this for you. Then run:
GITHUB_TOKEN=<TOKEN> yarn dist
If Storybook complains about different ES6 problems then it can sometimes be solved with npx yarn-deduplicate --scopes @babel