DOCX Export
It's possible to export BlockNote documents to docx, completely client-side.
This feature is provided by the @blocknote/xl-docx-exporter. xl- packages
are fully open source, but released under a copyleft license. A commercial
license for usage in closed source, proprietary products comes as part of the
Business subscription.
First, install the @blocknote/xl-docx-exporter and docx packages:
npm install @blocknote/xl-docx-exporter docxThen, create an instance of the DOCXExporter class. This exposes the following methods:
import {
DOCXExporter,
docxDefaultSchemaMappings,
} from "@blocknote/xl-docx-exporter";
import { Packer } from "docx";
// Create the exporter
const exporter = new DOCXExporter(editor.schema, docxDefaultSchemaMappings);
// Convert the blocks to a docxjs document
const docxDocument = await exporter.toDocxJsDocument(editor.document);
// Use docx to write to file:
await Packer.toBuffer(docxDocument);See the full example below:
Customizing the Docx output file
toDocxJsDocument takes an optional options parameter, which allows you to customize document metadata (like the author) and section options (like headers and footers).
Example usage:
import { Paragraph, TextRun } from "docx";
const doc = await exporter.toDocxJsDocument(testDocument, {
documentOptions: {
creator: "John Doe",
},
sectionOptions: {
headers: {
default: {
options: {
children: [new Paragraph({ children: [new TextRun("Header")] })],
},
},
},
footers: {
default: {
options: {
children: [new Paragraph({ children: [new TextRun("Footer")] })],
},
},
},
},
});Custom mappings / custom schemas
The DOCXExporter constructor takes a schema, mappings and options parameter.
A mapping defines how to convert a BlockNote schema element (a Block, Inline Content, or Style) to a docxjs element.
If you're using a custom schema in your editor, or if you want to overwrite how default BlockNote elements are converted to docx, you can pass your own mappings:
For example, use the following code in case your schema has an extraBlock type:
import {
DOCXExporter,
docxDefaultSchemaMappings,
} from "@blocknote/xl-docx-exporter";
import { Paragraph, TextRun } from "docx";
new DOCXExporter(schema, {
blockMapping: {
...docxDefaultSchemaMappings.blockMapping,
myCustomBlock: (block, exporter) => {
return new Paragraph({
children: [
new TextRun({
text: "My custom block",
}),
],
});
},
},
inlineContentMapping: docxDefaultSchemaMappings.inlineContentMapping,
styleMapping: docxDefaultSchemaMappings.styleMapping,
});Math & diagram blocks
The math and diagram blocks live in separate packages, and so do their DOCX mappings. Spread them into the default mappings to export math as native (editable) Word equations and diagrams as embedded images:
import {
inlineMathMapping,
mathBlockMapping,
} from "@blocknote/math-block/docx-exporter";
import { createDiagramBlockMapping } from "@blocknote/diagram-block/docx-exporter";
const exporter = new DOCXExporter(editor.schema, {
...docxDefaultSchemaMappings,
blockMapping: {
...docxDefaultSchemaMappings.blockMapping,
math: mathBlockMapping,
diagram: createDiagramBlockMapping(),
},
inlineContentMapping: {
...docxDefaultSchemaMappings.inlineContentMapping,
inlineMath: inlineMathMapping,
},
});Invalid LaTeX or Mermaid sources render an error placeholder with the error message, mirroring the editor.
Math exports fine server-side (the LaTeX is converted to OMML without rendering). Rendering diagrams to images, however, requires a browser — when exporting server-side, pass a renderDiagram function to createDiagramBlockMapping (e.g. backed by @mermaid-js/mermaid-cli or a Kroki server); without one, the export throws:
import { createDiagramBlockMapping } from "@blocknote/diagram-block/docx-exporter";
import type { RenderDiagram } from "@blocknote/diagram-block/docx-exporter";
const renderDiagram: RenderDiagram = async (source) => {
// Render the Mermaid source to an image with your renderer of choice.
return { dataURL, width, height };
};
createDiagramBlockMapping({ renderDiagram });Exporter options
The DOCXExporter constructor takes an optional options parameter.
While conversion happens on the client-side, the default setup uses a server hosted proxy to resolve files:
const defaultOptions = {
// a function to resolve external resources in order to avoid CORS issues
// by default, this calls a BlockNote hosted server-side proxy to resolve files
resolveFileUrl: corsProxyResolveFileUrl,
// the strings rendered into the exported document (file link texts, error
// placeholders); pass a locale from @blocknote/core/locales (or your
// editor's dictionary) to export in another language
dictionary: locales.en,
// the colors to use in the Docx for things like highlighting, background colors and font colors.
colors: COLORS_DEFAULT, // defaults from @blocknote/core
};