@wordpress/plugins
Version:
Plugins module for WordPress.
231 lines (212 loc) • 5.9 kB
JavaScript
/* eslint no-console: [ 'error', { allow: [ 'error' ] } ] */
/**
* WordPress dependencies
*/
import { applyFilters, doAction } from '@wordpress/hooks';
import { plugins as pluginsIcon } from '@wordpress/icons';
/**
* External dependencies
*/
import { isFunction } from 'lodash';
/**
* Defined behavior of a plugin type.
*
* @typedef {Object} WPPlugin
*
* @property {string} name A string identifying the plugin. Must be
* unique across all registered plugins.
* @property {string|WPElement|Function} [icon] An icon to be shown in the UI. It can
* be a slug of the Dashicon, or an element
* (or function returning an element) if you
* choose to render your own SVG.
* @property {Function} render A component containing the UI elements
* to be rendered.
* @property {string} [scope] The optional scope to be used when rendering inside
* a plugin area. No scope by default.
*/
/**
* Plugin definitions keyed by plugin name.
*
* @type {Object.<string,WPPlugin>}
*/
const plugins = {};
/**
* Registers a plugin to the editor.
*
* @param {string} name A string identifying the plugin.Must be
* unique across all registered plugins.
* @param {WPPlugin} settings The settings for this plugin.
*
* @example
* ```js
* // Using ES5 syntax
* var el = wp.element.createElement;
* var Fragment = wp.element.Fragment;
* var PluginSidebar = wp.editPost.PluginSidebar;
* var PluginSidebarMoreMenuItem = wp.editPost.PluginSidebarMoreMenuItem;
* var registerPlugin = wp.plugins.registerPlugin;
* var moreIcon = wp.element.createElement( 'svg' ); //... svg element.
*
* function Component() {
* return el(
* Fragment,
* {},
* el(
* PluginSidebarMoreMenuItem,
* {
* target: 'sidebar-name',
* },
* 'My Sidebar'
* ),
* el(
* PluginSidebar,
* {
* name: 'sidebar-name',
* title: 'My Sidebar',
* },
* 'Content of the sidebar'
* )
* );
* }
* registerPlugin( 'plugin-name', {
* icon: moreIcon,
* render: Component,
* scope: 'my-page',
* } );
* ```
*
* @example
* ```js
* // Using ESNext syntax
* import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
* import { registerPlugin } from '@wordpress/plugins';
* import { more } from '@wordpress/icons';
*
* const Component = () => (
* <>
* <PluginSidebarMoreMenuItem
* target="sidebar-name"
* >
* My Sidebar
* </PluginSidebarMoreMenuItem>
* <PluginSidebar
* name="sidebar-name"
* title="My Sidebar"
* >
* Content of the sidebar
* </PluginSidebar>
* </>
* );
*
* registerPlugin( 'plugin-name', {
* icon: more,
* render: Component,
* scope: 'my-page',
* } );
* ```
*
* @return {WPPlugin} The final plugin settings object.
*/
export function registerPlugin( name, settings ) {
if ( typeof settings !== 'object' ) {
console.error( 'No settings object provided!' );
return null;
}
if ( typeof name !== 'string' ) {
console.error( 'Plugin name must be string.' );
return null;
}
if ( ! /^[a-z][a-z0-9-]*$/.test( name ) ) {
console.error(
'Plugin name must include only lowercase alphanumeric characters or dashes, and start with a letter. Example: "my-plugin".'
);
return null;
}
if ( plugins[ name ] ) {
console.error( `Plugin "${ name }" is already registered.` );
}
settings = applyFilters( 'plugins.registerPlugin', settings, name );
const { render, scope } = settings;
if ( ! isFunction( render ) ) {
console.error(
'The "render" property must be specified and must be a valid function.'
);
return null;
}
if ( scope ) {
if ( typeof scope !== 'string' ) {
console.error( 'Plugin scope must be string.' );
return null;
}
if ( ! /^[a-z][a-z0-9-]*$/.test( scope ) ) {
console.error(
'Plugin scope must include only lowercase alphanumeric characters or dashes, and start with a letter. Example: "my-page".'
);
return null;
}
}
plugins[ name ] = {
name,
icon: pluginsIcon,
...settings,
};
doAction( 'plugins.pluginRegistered', settings, name );
return settings;
}
/**
* Unregisters a plugin by name.
*
* @param {string} name Plugin name.
*
* @example
* ```js
* // Using ES5 syntax
* var unregisterPlugin = wp.plugins.unregisterPlugin;
*
* unregisterPlugin( 'plugin-name' );
* ```
*
* @example
* ```js
* // Using ESNext syntax
* import { unregisterPlugin } from '@wordpress/plugins';
*
* unregisterPlugin( 'plugin-name' );
* ```
*
* @return {?WPPlugin} The previous plugin settings object, if it has been
* successfully unregistered; otherwise `undefined`.
*/
export function unregisterPlugin( name ) {
if ( ! plugins[ name ] ) {
console.error( 'Plugin "' + name + '" is not registered.' );
return;
}
const oldPlugin = plugins[ name ];
delete plugins[ name ];
doAction( 'plugins.pluginUnregistered', oldPlugin, name );
return oldPlugin;
}
/**
* Returns a registered plugin settings.
*
* @param {string} name Plugin name.
*
* @return {?WPPlugin} Plugin setting.
*/
export function getPlugin( name ) {
return plugins[ name ];
}
/**
* Returns all registered plugins without a scope or for a given scope.
*
* @param {string} [scope] The scope to be used when rendering inside
* a plugin area. No scope by default.
*
* @return {WPPlugin[]} The list of plugins without a scope or for a given scope.
*/
export function getPlugins( scope ) {
return Object.values( plugins ).filter(
( plugin ) => plugin.scope === scope
);
}