Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
README.md 17.25 KiB

Wax Editor

MIT license

This library is being developed by the Coko Foundation. Wax Editor is build on top of the Prosemirror library. Check Prosemirror website and GitHub repo for more information.

Roadmap

Wax-prosemirror is under active development. The current roadmap is as follows:

September 2020

Alpha version, including comments and track changes. See the rest of this file for a full list of current functionality.

November 2020

Beta version, including some new features:

  • Find and replace
  • Spellchecker
  • Special characters
  • Transform cases
  • Word counter
  • Custom tags

January 2021

V1.0, freeze new feature development, focus on stability, testing and bug fixes

Get up and running

Run a local version of the editor

  1. git clone git@gitlab.coko.foundation:wax/wax-prosemirror.git

  2. yarn with node >= 12

  3. yarn build

  4. yarn editoria Will bring up a demo of the Editoria Ediitor

  5. yarn storybook Will bring up storybook for components

Scripts: yarn , yarn clean, yarn reset

Introduction

Wax depends on the following libraries.

  • React for the view(ui)

  • Styled-components for theming and styling.

  • Inversify.io as service containers

Assemble your own Editor

Currently Wax is under heavy development. Master holds a as possible as stable version of the editor. For latest versions see here. Documentation follows, but it is rather limited for now. It lists all the basic parts , and includes a brief explanation on how to configure Wax for your own project. More detailed examples will follow.

Check editoria editor, editoria's package.json and editoria's configuration file for a full example on how to mount Wax and all available packages(services).

Editor Properties

All available editor properties

autoFocus; // sets cursor in the begging of the document
onChange; // when the editor's surface is updated (perform an action ex. save)
value; // the actual HTML content of the editor
fileUpload; // used for uploading images (should return a promise with the actual file path)
placeholder; // a placeholder used for empty documents
config; // adds on the editor anything from new services, tools, Pmpplugins etc. Check [editoria config](https://gitlab.coko.foundation/wax/wax-prosemirror/blob/master/editors/editoria/src/config/config.js)
readonly; // editor in in read-only mode
onBlur; // on focus lost
layout; // used to create your own Layout using React components
TrackChange; // enables track changes (under development)
debug; // dev-tools (https://github.com/d4rkr00t/prosemirror-dev-tools)

Current Tools and Toolgroups:

  1. Base Tool group: undo, redo, save

  2. Inline Annotations Tool group: strong, italic, link, strikethrough, underline, subscript, superscript, small caps

  3. Lists Tool group: numbered list, bullet list

  4. Image Tool group: image

  5. Table Tool group: create table, edit table dropdown that includes: insert/delete row, insert/delete column ,merge cells, split cell, delete table, Toggle header column, Toggle header row

  6. Display Tool group: Title, Author, Subtitle, Epigraph Prose, Epigraph Poetry, Heading 1, Heading 2, Heading 3

  7. Text Tool group: Paragraph, Paragraph Continued, Extract Prose, Extract Poetry, Source Note, Block Quote

  8. Notes Tool group: notes

  9. Comments Tool group: comments ((currently under development))

wax-prosemirror-core

The role of wax-core is

  • Mount a prosemirror instance

  • Initiate default services

    1. LayoutService

    2. SchemaService

    3. MenuService

    4. RulesService

    5. ShortCutsService

A big part of wax-core is the application layer, which is responsible for the application’s lifecycle by registering and booting services, merging configs, using the schema and gathering all prosemirror plugins.

Also holds some default prosemirror plugins that are necessary like the dropCursor, gapCursor, history and some optional as the placeholder.

wax-prosemirror-schema

Holds all the nodes and marks currently supported by Wax. You can either have a node/mark in “Wax node/mark structure” or a default prosemirror node/mark. For more information on how a Wax node/mark is different check the SchemaService

wax-prosemirror-components

React components to support various features of the editor from buttons to overlays to comment discussions etc. Right now is really basic as the focus is not yet on UI.

wax-prosemirror-themes

Holds the different themes of the editor. Check the options in the CokoTheme

wax-prosemirror-layouts

Holds different layouts of the editor. Through the layout service you can configure the areas of different components. As an example check EditoriaLayout

wax-prosemirror-utilities

Various helpers methods needed throughout Wax to support the funcionality needed.

Editors

Editors are private pakages inside the monorepo, for development/demo purposes.

wax-prosemirror-services

Service providers are the central place of Wax bootstrapping. Your own services, as well as all of Wax's core services are bootstrapped via application provider and are initiated before everything else.

But, what do we mean by "bootstrapped"? In general, we mean registering things, including registering service container bindings and event listeners. Service providers are the central place to configure your application.

If you open editoria's config file, you will see the config file where you can configure the extra services (apart from those Wax will load on init) of your editor. These are all of the service provider classes that will be loaded for your application.

In the following overview we will see how to write our own service providers and register them within the Editor.

Writing Service Providers

All service providers extend the Service class. Most service providers contain a register and a boot method. Within the register method, you should only bind things into the service container.

The Register Method

Let’s take a look at a simple service like the StrongService. Within any of your service provider methods, you always have access to the config and schema properties and also you have access to the service container using inversify.io.

import { toggleMark } from 'prosemirror-commands';
import Service from 'wax-prosemirror-core/src/services/Service';
import { strongMark } from 'wax-prosemirror-schema';
import Strong from './Strong';

class StrongService extends Service {
  boot() {
    const shortCuts = this.container.get('ShortCuts');
    shortCuts.addShortCut({ 'Mod-b': toggleMark(this.schema.marks.strong) });
  }

  register() {
    this.container.bind('Strong').to(Strong);
    const createMark = this.container.get('CreateMark');
    createMark(
      {
        strong: strongMark,
      },
      { toWaxSchema: true },
    );
  }
}

export default StrongService;

This service provider defines a register method, it registers a class and in this case is the strong tool. For more information on how to use service container check inversify.io documentation.

A slightly more complicated example could be the ShortCutsService register method.

register() {
    const PmPlugins = this.app.PmPlugins;
    this.container
      .bind("ShortCuts")
      .toDynamicValue(() => {
        const { schema: { schema } } = this.app;

        return new ShortCuts(PmPlugins, schema);
      })
      .inSingletonScope();
  }

In the above example we bind ShortCuts to a factory method which injects PmPlugins and schema into ShortCuts class.

The Boot Method

So, what if we need to register a view component within our service provider? This should be done within the boot method. This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered.

A good example could be the MenuSerivce

boot() {
    const { menus } = this.container.get("MenuCollection");
    const layout = this.container.get("Layout");
    menus.forEach(menu => {
      layout.addComponent(menu.config.templateArea, menu.render());
    });
  }