OpenProject extensions for the BlockNote editor.
This repo is split into two parts:
- The library itself, which is located in the
/libfolder and can be built and packaged withnpm run build. - A demo app, which is located in the
src/App.tsxfile and can be run locally withnpm run dev.
Include the following entry to your package.json.
"op-blocknote-extensions": "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/opf/op-blocknote-extensions/releases/download/<VERSION>/op-blocknote-extensions-<VERSION>.tgz"(please note: at the time being, you need to replace the version in two places of the url.)
First, initialize the library configuration:
initializeOpBlockNoteExtensions({ baseUrl: 'https://my.openproject.url', locale: 'en' });Then set up a BlockNote schema extending it with the block and inline specs:
const schema = BlockNoteSchema.create().extend({
blockSpecs: {
openProjectWorkPackageBlock: openProjectWorkPackageBlockSpec(),
},
inlineContentSpecs: {
openProjectWorkPackageInline: openProjectWorkPackageInlineSpec,
},
});
type EditorType = typeof schema.BlockNoteEditor;Create the editor, passing PasteDeduplicateInstanceIdsExtension in extensions.
This must be done at construction time — registering the plugin post-mount via
editor.registerPlugin() triggers ProseMirror's reconfigure(), which destroys
the Y.js UndoManager and silently breaks Ctrl+Z.
const editor = useCreateBlockNote({
schema,
extensions: [PasteDeduplicateInstanceIdsExtension],
});Wire the runtime hooks and build the slash and hash menus:
useOpBlockNoteExtensions(editor);
const getSlashItems = useCallback(
async (query: string) =>
filterSuggestionItems(
[...getDefaultReactSlashMenuItems(editor), workPackageSlashMenu(editor)],
query
),
[editor]
);
const { getHashItems, HashWpMenu } = useHashWpMenu(editor);Include everything in a BlockNoteView:
return (
<BlockNoteView editor={editor} slashMenu={false}>
<SuggestionMenuController
triggerCharacter="/"
getItems={getSlashItems}
/>
<SuggestionMenuController
triggerCharacter="#"
getItems={getHashItems}
suggestionMenuComponent={HashWpMenu}
/>
</BlockNoteView>
);There's a working example in the src/App.tsx in this repository. You can test it locally by running:
npm run devWhich will start a vite server with a BlockNote editor instance including the available extensions.
This project uses styledComponents to define styles. This means that styles are, by default, injected onto the page header. To be able to use styles onto a shadow dom root it is necessary to use our ShadowDomWrapper component targeting the root for the styles.
<ShadowDomWrapper target={targetHtmlElementOrShadowRoot}>
<MyBlockNoteView />
</ShadowDomWrapper>Step 1: Copy .env.example to .env and fill in:
VITE_OPENPROJECT_URL— your OpenProject instance (e.g.https://openproject.local). Defaults tohttp://localhost:3000if unset.VITE_API_KEY— an API key generated athttps://openproject.local/my/access_tokens.
Step 2: Enable CORS and add the dev origin (http://localhost:5173) at https://openproject.local/admin/settings/api.
Step 3: Start the development server — npm run dev.
| Component | Description |
|---|---|
| WorkPackage block | Search and display elegantly work package links |
| ... | ... |
To build the library and generate types and source maps. This will update the dist folder.
npm run buildTo develop with OpenProject locally
npm run build
npm pack
cp op-blocknote-extensions-*.tgz ../openproject/frontend
cd ../openproject/frontend
npm i -S op-blocknote-extensions-*.tgzThis should make sure that the package is available for OpenProject even if running on a container.
Updating the version field in package.json will automatically create a new Git tag with the corresponding version. Pushing this tag to the repository triggers the generation of a new release.
To publish a new release, simply update the version in package.json and merge the changes into the main branch.