Creating a new plugin (outdated) - serlo/documentation GitHub Wiki

Creating a New Plugin in the Serlo Editor

Creating a new plugin for the editor involves several steps. These steps ensure the plugin is recognized, initialized, rendered, and serialized correctly. A full example PR can be seen here https://github.com/serlo/frontend/pull/2768, meanwhile the documentation below will walk you through the changes step by step.

Step 1: Add plugin name to EditorPluginType enum

Located in serlo-editor-integration/types/editor-plugin-type:

export enum EditorPluginType {
  // ....
  Article = 'article',
  Audio = 'audio',
  // ...
}

Step 2: Create your plugin config and component

Create a new folder within serlo-editor/plugins and export your component.

export type AudioProps = EditorPluginProps<AudioPluginState>
export type AudioPluginState = typeof audioState

export const audioPlugin: EditorPlugin<AudioPluginState> = {
  Component: AudioEditor,
  config: {},
  state: audioState,
}

Step 3: Register the Plugin in create-plugins.tsx

Add your new plugin to the create-plugins.tsx file.

  {
    type: EditorPluginType.Audio,
    plugin: audioPlugin,
    visibleInSuggestions: true,
    icon: <IconAudio />,
  },

This should already allow your plugin to be selected when clicking the plus in the edit mode of the editor, or when typing /Audio in a new line.

Step 4: Extend frontend-node-type.ts

Extend the existing types to accommodate your plugin.

For example:

// In frontend-node-type.ts
export type FrontendAudioNode = EditorAudioPlugin & {
  type: FrontendNodeType.Audio;
  children?: undefined;
  pluginId?: string;
  src: string;
};

Then add it to the appropriate Node type. As this particular plugin doesn't have to render a slate editor, it is considered a void node FrontendVoidNode.

Step 5: Update Frontend Renderer (article-renderer.tsx)

Include your plugin in the src/schema/article-renderer.tsx file so that it can be properly rendered in articles.

Step 6: Convert Plugin State for Frontend in convert-edtr-io-state.tsx

You'll need to add some code that converts your plugin's state into the state format the frontend expects. Modify the convert-edtr-io-state.tsx file as follows:

if (node.plugin === EditorPluginType.Audio) {
  if (!node.state.src) {
    // here we simply remove the plugin from being rendered if no URL was provided
    return []
  }

  return [
    {
      type: FrontendNodeType.Audio,
      src: node.state.src,
      pluginId: node.id,
      plugin: EditorPluginType.Audio,
      state: node.state,
    },
  ]
}

Step 7: Add to editor-plugins.ts

Finally, add your plugin to the types/editor-plugins.ts file to complete its integration into the editor.

export interface EditorAudioPlugin {
  plugin: EditorPluginType.Audio
  state: StateTypeSerializedType<AudioPluginState>
  id?: string
}

export type SupportedEditorPlugin =
  | EditorArticlePlugin
  | EditorAudioPlugin

Step 8: Allow inside Multimedia Plugin (Optional)

If your plugin makes sense in the explanation part of the multimedia plugin, add it to plugins/multimedia/index.ts.

Last step: Test usual suspects (known sources of bugs)

  • Focus management:
    • Test if the new plugin works well with all focus management features:
      • Autofocus the plugin when newly added
      • Tab and Shift+Tab work as expected within the plugin
    • Test if general focus management still works as expected:
      • Title still autofocused on page load
      • Tab and Shift+Tab work as expected between different plugins
      • Moving among plugins with Up and Down arrows