Skip to content

OJS Integration Guide

This guide covers what you need to embed the SciFlow editor in an OJS plugin. It assumes you are familiar with OJS plugin development and focuses on the SciFlow-specific wiring.

1. Load the Bundle

Install and copy the pre-built bundle into your plugin:

npm install @sciflow/editor-start
cp node_modules/@sciflow/editor-start/dist/bundle/sciflow-editor.js vendor/sciflow-editor.js

Register it as a module script via addJavaScript:

$templateMgr->addJavaScript(
    'sciflow-editor',
    $request->getBaseUrl() . '/plugins/generic/myPlugin/vendor/sciflow-editor.js',
    ['type' => 'module', 'priority' => STYLE_SEQUENCE_LATE]
);

Icons are bundled as inline SVGs — no external fonts or CDN links required.

2. Self-host MathJax

Many institutional OJS hosts enforce CSP policies that block CDN scripts. Self-host MathJax alongside your plugin:

npm install mathjax@4
cp -r node_modules/mathjax/es5 vendor/mathjax/

Register vendor/mathjax/tex-svg.js the same way. Copy the entire es5/ directory — MathJax loads sub-resources dynamically at runtime.

3. Feed References

OJS uses rawCitation for bibliography strings; SciFlow uses rawReference. Map between them when loading and saving:

// OJS → SciFlow
const sciflowRef = {
  id: ojsCitation.id,
  rawReference: ojsCitation.rawCitation,
  mimeType: 'application/vnd.citationstyles.csl+json',
};

// SciFlow → OJS
const ojsCitation = {
  id: sciflowRef.id,
  rawCitation: sciflowRef.rawReference,
};

Pass the mapped array into the <sciflow-reference-list> component and wire it to the editor:

const editor = document.querySelector('sciflow-editor');
const refList = document.querySelector('sciflow-reference-list');

editor.addEventListener('editor-change', (event) => {
  refList.references = event.detail.references ?? [];
});

editor.addEventListener('editor-selection-change', (event) => {
  refList.cursorActive = true;
  refList.highlight(extractCitationIds(event.detail));
});

editor.addEventListener('editor-ready', () => {
  refList.cursorActive = false;
});

refList.addEventListener('sciflow-insert-citation', (event) => {
  const { reference } = event.detail;
  editor.commands?.commands?.insertCitation?.({
    items: [{ id: reference.id }],
    text: reference.rawReference,
  });
});

References also support drag-and-drop into the editor out of the box. See sciflow-reference-list and the Reference Integration guide for details.

4. Connect Figure Uploads

The editor does not upload files — you provide the storage workflow. Wire your OJS file API into the figure feature:

import { createFigureFeature } from '@sciflow/editor-core/features/figure';

const figureFeature = createFigureFeature({
  imageUpload: {
    async uploadFile(file) {
      // Upload via your OJS file API
      const formData = new FormData();
      formData.append('file', file);
      const res = await fetch('/api/files', { method: 'POST', body: formData });
      const asset = await res.json();

      return {
        id: asset.id,
        mimeType: file.type || 'application/octet-stream',
        url: asset.url,           // full-resolution URL for the snapshot
        previewSrc: asset.preview, // optional preview shown in the editor
      };
    },
  },
});

await editor.configureFeatures([figureFeature, /* ...other features */]);

See the Figure File API guide for the full handler interface and drag/drop support.

5. Avoid the Native Fullscreen API

If you offer a fullscreen editing mode, use CSS-based fullscreen (position: fixed; inset: 0) instead of the browser's native Fullscreen API. The native API captures the Escape key at the browser level, which breaks ProseMirror's selectParentNode command and the math editor's cancel action (Escape to discard changes).

.editor-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 9999;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

Toggle the class on your editor container and provide a close button to exit:

fullscreenBtn.addEventListener('click', () => {
  editorContainer.classList.add('editor-fullscreen');
});
closeBtn.addEventListener('click', () => {
  editorContainer.classList.remove('editor-fullscreen');
});

This keeps Escape available for the editor while still filling the viewport.

6. Troubleshooting

Symptom Fix
Equations show raw TeX Check browser console for CSP errors; verify the MathJax script path
MathJax sub-resources 404 Copy the full es5/ directory, not just tex-svg.js
sciflow-editor is undefined Ensure type is set to module in addJavaScript
MathJax loads from CDN Search templates for cdn.jsdelivr.net/npm/mathjax and remove