Adding Custom Notebook Exporters#
Introduction#
JupyterLite provides a built-in notebook export system that allows users to download notebooks in different formats. By default, JupyterLite includes exporters for:
Notebook (ipynb): Download the notebook as a
.ipynbfileExecutable Script: Convert and download the notebook as an executable script (e.g.,
.pyfor Python notebooks)
You can extend this functionality by creating custom exporters in your JupyterLite extension or plugin. This allows you to add support for additional export formats such as HTML, PDF, Markdown, or any custom format you need.
The export system in JupyterLite is based on the following extension points:
INbConvertExporters: A token that provides access to the exporter registryIExporter: An interface that all exporters must implement registered exporters
Creating a Custom Exporter#
Step 1: Implement the IExporter Interface#
Create a class that implements the IExporter interface from @jupyterlite/services:
import { Contents } from '@jupyterlab/services';
import { IExporter } from '@jupyterlite/services';
export class MarkdownExporter implements IExporter {
/**
* The MIME type of the exported format.
*/
readonly mimeType = 'text/markdown';
/**
* Export a notebook to Markdown format.
*
* @param model The notebook model to export
* @param path The path to the notebook
*/
async export(model: Contents.IModel, path: string): Promise<void> {
const content = this._convertToMarkdown(model.content);
const filename = path.replace(/\.ipynb$/, '.md');
this.triggerDownload(content, this.mimeType, filename);
}
/**
* Convert notebook content to Markdown.
*/
private _convertToMarkdown(notebook: any): string {
const cells = notebook.cells || [];
const lines: string[] = [];
for (const cell of cells) {
const source = Array.isArray(cell.source) ? cell.source.join('') : cell.source;
if (cell.cell_type === 'markdown' || cell.cell_type === 'raw') {
lines.push(source);
} else if (cell.cell_type === 'code') {
lines.push('```' + (notebook.metadata?.language_info?.name || 'python'));
lines.push(source);
lines.push('```');
}
lines.push(''); // blank line between cells
}
return lines.join('\n');
}
/**
* Trigger a browser download of the exported content.
*/
protected triggerDownload(content: string, mimeType: string, filename: string): void {
const element = document.createElement('a');
element.href = `data:${mimeType};charset=utf-8,${encodeURIComponent(content)}`;
element.download = filename;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
}
Step 2: Register the Exporter in a Plugin#
Create a JupyterLab plugin that requires the INbConvertExporters token and registers
your custom exporter. Note that this should be a ServiceManagerPlugin since exporters
are part of the services layer:
import { ServiceManagerPlugin } from '@jupyterlab/services';
import { INbConvertExporters } from '@jupyterlite/services';
import { MarkdownExporter } from './exporters';
/**
* Plugin to register custom exporters.
*/
const exporterPlugin: ServiceManagerPlugin<void> = {
id: 'my-extension:custom-exporters',
autoStart: true,
requires: [INbConvertExporters],
activate: (_: null, exporters: INbConvertExporters): void => {
// Register the custom exporter
exporters.register('Markdown', new MarkdownExporter());
console.log('Custom Markdown exporter registered');
},
};
export default exporterPlugin;
Step 3: Build#
Build your extension following the standard JupyterLab extension build process
Install the extension in your environment
Build your JupyterLite site with
jupyter lite buildThe custom exporter will now appear in the File menu under “Save and Export Notebook As…”