Skip to content

Extending features

SciFlow’s feature system separates schema nodes, commands, and UI integration. Use this guide to add a feature or modify an existing one.

Feature anatomy

A feature lives under packages/editor/core/src/lib/features/<name> and typically exports:

  • Feature object (name, initialize, optional plugins, nodeViews).
  • Commands registered via registerCommands.
  • Node views (Lit or vanilla) when the feature requires custom rendering.
export const figureFeature: Feature = {
  name: 'figure',
  initialize() {
    registerCommands({
      insertFigure:
        (options: InsertFigureOptions) =>
        (props) => runInsertFigure(props.state, options, getDispatch(props)),
    });
  },
  nodeViews() {
    return { figure: createDecoratedNodeViewFactory(FigureNodeView) };
  },
};

Add a feature

  1. Create the schema node (if required) under packages/schema.
  2. Add commands that manipulate the node or mark.
  3. Register ProseMirror plugins through the feature’s addPlugins hook, including drop handlers and keymaps.
  4. Expose UI hooks in the start package (toolbar buttons, dialogs, custom panels).
  5. Add a feature toggle — include the new feature in the demo's FEATURE_OPTIONS array so QA can enable or disable it.

Reuse helpers

The command system provides getDispatch, withCommandRegistration, and flow helpers. Use them to preserve flow behavior and availability checks.

Testing strategy

  • Unit test commands in isolation (Vitest) by instantiating a ProseMirror state and running the command function.
  • Add integration tests in packages/editor/core/src/lib/features/<feature>/<feature>.spec.ts if the feature already has a suite.
  • Exercise node views in the demo to verify that Lit bindings update as expected.

Expose feature APIs to consumers

  • Re-export the command helpers (for example, runInsertFigure) from the feature index so downstream apps can call them with custom dispatchers.
  • Document any additional attributes/events in the User Guide (Customization or Packages chapters).

Update the web components

  • If the feature requires UI controls, modify packages/editor/start/src/lib/format-bar.ts or add a dedicated panel.
  • Keep ARIA labels and keyboard interactions consistent with existing nodes such as headings and citations.

Feature toggles vs. bundles

Features are tree-shakeable: only features registered in editor.configureFeatures() are active. This limits the runtime size as the feature set grows.