ProtonMail / ProtonMail/WebClients
odf-kit — JavaScript/TypeScript library for ODT export from Lexical editor state
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 715
- PR merge metrics
- No merged PRs in 30d
Description
Please complete the following checklist (by adding [x]):
- [X ] I have searched open and closed issues for duplicates
- This isn't a feature request
- [X ] This is not a report about my app not working as expected
Context: The Proton community has been requesting ODT support across several UserVoice threads (1, 2, 3). A Proton team member noted in one thread that "there are no libraries whatsoever for ODT processing for browsers." This is no longer accurate.
odf-kit is a pure TypeScript library (Apache 2.0, ESM, zero dependencies beyond fflate) that generates, reads, and converts ODT files entirely client-side — no LibreOffice, no server required. It passes the OASIS ODF validator on every release.
As of v0.12.0 it includes lexicalToOdt() — a function that converts a Lexical SerializedEditorState directly to a valid .odt file. It handles the node types registered in AllNodes.ts: paragraphs, headings, blockquotes, code blocks, lists (including CustomListNode), tables, links, images, horizontal rules, and inline formatting.
The integration point in this codebase is well-defined:
New file: applications/docs-editor/src/app/Conversion/Exporter/EditorOdtExporter.ts
typescriptimport { lexicalToOdt } from 'odf-kit/lexical'
import { EditorExporter } from './EditorExporter'
export class EditorOdtExporter extends EditorExporter {
async export(): Promise<Uint8Array> {
return lexicalToOdt(this.editor.getEditorState().toJSON(), {
pageFormat: 'A4',
fetchImage: async (src) => {
const b64 = await this.callbacks.fetchExternalImageAsBase64(src)
if (!b64) return undefined
const binary = atob(b64.split(',')[1] ?? b64)
return Uint8Array.from(binary, c => c.charCodeAt(0))
},
})
}
}
Edit: ExportDataFromEditorState.ts — add one case:
typescriptcase 'odt':
return new EditorOdtExporter(editorState, callbacks).export()
Edit: DataTypesThatDocumentCanBeExportedAs in @proton/docs-shared — add 'odt' to the union type.
Posting here in case it's useful. Happy to answer any questions about the library.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing exporter structure around applications/docs-editor/src/app/Conversion/Exporter/EditorExporter.ts and the named ExportDataFromEditorState.ts entry point. Add the ODT exporter and update DataTypesThatDocumentCanBeExportedAs in @proton/docs-shared; done means the odt export path returns a valid ODT file, including the documented image-fetch behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100