@fiduswriter/editor

@fiduswriter/editor

The ProseMirror-based editor component of Fidus Writer

This package is part of the Fidus Writer ecosystem. It provides the main browser-based collaborative editor: real-time collaboration, comments, tracked changes, footnotes, citations, end-to-end encryption, menus, dialogs, and clipboard import/export.

Key features

Demo

Try the standalone browser demo that runs without a backend server:

Installation

npm install @fiduswriter/editor

Exports

ExportDescription
EditorMain editor class — orchestrates ProseMirror, collaboration, and all subsystems.
createStaticEditorHigh-level helper that creates and initializes an editor without a backend server.
createStaticAppLower-level helper that builds an in-memory EditorApp for static deployments.
./state_pluginsProseMirror state plugins.
./state_plugins/*Individual plugins (inline math, references, links, etc.).
./menusEditor menus and toolbar.
./dialogsEditor dialogs (figure, citation, link, table, etc.).
./keymapKeyboard shortcut bindings.
./exporter/native/fileDownload the current document as a .fidus file.

Usage

The library can be used in two modes: static (no backend server, like the standalone demo) or server-backed (the classic Fidus Writer Django setup).

Static usage

For a statically served editor, use createStaticEditor. It sets up the runtime globals, loads locale strings, creates the in-memory app shell, and initializes the editor.

import {createStaticEditor} from "@fiduswriter/editor/static_editor"
import {ExportFidusFile} from "@fiduswriter/editor/exporter/native/file"

const editor = await createStaticEditor({
    locale: "en",
    username: "Demo User",
    documentData: async () => ({
        doc: {
            v: 0,
            content: { /* ProseMirror document JSON */ },
            comments: {},
            bibliography: {},
            images: {}
        },
        doc_info: {
            id: 1,
            rights: "write",
            is_owner: true,
            path: "",
            updated: new Date(),
            dir: "ltr",
            access_rights: "write",
            e2ee: false,
            owner: {id: 1, name: "Demo User", type: "user", contacts: []}
        },
        time: Date.now()
    }),
    documentStyles: [
        {
            title: "Standard article",
            slug: "standard-article",
            contents: "",
            documentstylefile_set: []
        }
    ],
    exportTemplates: [
        {
            title: "Fidus Writer",
            file_type: "fidus",
            template_file: "/static/export-templates/template.fidus"
        }
    ],
    documentTemplates: {
        "1": {title: "Standard article"}
    }
})

// Download the document as a .fidus file.
const doc = editor.getDoc({use_current_view: true})
new ExportFidusFile(
    editor.app,
    doc,
    editor.mod.db.bibDB,
    editor.mod.db.imageDB,
    false
)

createStaticEditor accepts a StaticEditorConfig. The most important options are:

Note: Import createStaticEditor from @fiduswriter/editor/static_editor rather than the main package entry. This keeps the Editor class out of the initial bundle and prevents editor modules from being evaluated before the runtime globals are set.
If you bundle a static page with esbuild, configure a loader for .gz assets — citeproc-plus loads compressed style and locale files:
loader: { ".gz": "file" }

For more control, build the app shell manually with createStaticApp and then instantiate the Editor class yourself:

import {Editor, createStaticApp} from "@fiduswriter/editor"

const app = await createStaticApp({
    locale: "en",
    gettext: msgid => msgid,
    csl,
    documentData: async () => ({doc, doc_info, time: Date.now()})
})

const editor = new Editor({app, user}, "", "1", [])
await editor.init()

Server-backed usage

When a backend server is available, construct Editor directly with an EditorApp object that provides API connectors, settings, and the CSL engine. This is how the main Fidus Writer Django application uses the library.

import {Editor} from "@fiduswriter/editor"

const editor = new Editor(
    {app, user},
    "/documents/123",
    "123",
    [["my-plugin", {MyPlugin}]]
)
await editor.init()

The app object must satisfy the EditorApp interface:

Development

npm install          # Install dependencies
npm run build        # Compile TypeScript to dist/
npm run typecheck    # Check types without emitting
npm run lint         # Lint with ESLint
npm run format:check # Check formatting with Prettier
npm test             # Run the test suite