3.7 KiB
@odfjs/odfjs
Small lib to parse/understand .odf files (.odt, .ods) in the browser and node.js
Rough roadmap
- add odt templating
- remove support for xlsx
- add a .ods minifyer
- add a generic .ods visualizer
- move to a dedicated odf docs org
- add a quick .odt visualiser (maybe converting to markdown first?)
Usage
Install
npm i https://github.com/odfjs/odfjs.git#v0.30.0
Basic - reading an ods file
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent} from '@odfjs/odfjs'
/**
* @param {ArrayBuffer} odsFile - content of an .ods file
* @return {Promise<any[]>}
*/
async function getFileData(odsFile){
return getODSTableRawContent(odsFile)
.then(tableWithoutEmptyRows)
.then(tableRawContentToObjects)
}
The return value is an array of objects where the keys are the column names in the first row and the values are automatically converted from the .ods files (which type numbers, strings, booleans and dates) to the appropriate JavaScript value
Basic - creating an ods file
import {createOdsFile} from '@odfjs/odfjs'
const content = new Map([
[
'La feuille',
[
[
{value: '37', type: 'float'},
{value: '26', type: 'string'}
]
],
],
[
"L'autre feuille",
[
[
{value: '1', type: 'string'},
{value: '2', type: 'string'},
{value: '3', type: 'string'},
{value: '5', type: 'string'},
{value: '8', type: 'string'}
]
],
]
])
const ods = await createOdsFile(content)
// ods is an ArrayBuffer representing an ods file with the content described by the Map
(and there is a tool to test file creation:
node tools/create-an-ods-file.js > yo.ods)
Filling an .odt template
odf.js proposes a template syntax
In an .odt file, write the following:
Hey {nom}!
Your birthdate is {dateNaissance}
And then run the code:
import {join} from 'node:path';
import {getOdtTemplate, fillOdtTemplate} from '@odfjs/odfjs'
// replace with your template path
const templatePath = join(import.meta.dirname, './tests/data/template-anniversaire.odt')
const data = {
nom: 'David Bruant',
dateNaissance: '8 mars 1987'
}
const odtTemplate = await getOdtTemplate(templatePath)
const odtResult = await fillOdtTemplate(odtTemplate, data)
process.stdout.write(new Uint8Array(odtResult))
There are also loops in the form:
- {#each listeCourses as élément}
- {élément}
- {/each}
They can be used to generate lists or tables in .odt files from data and a template using this syntax
Securing calls to fillOdtTemplate
fillOdtTemplate evaluate arbitrary JavaScript code in {#each <collection> as élément} and {#if <condition>} and in {<expression>}
By default, fillOdtTemplate limits access to global functions to only ECMAScript defaults via the use of ses' Compartment, this prevents naïve data exfiltration
However, fillOdtTemplate is vulnerable to prototype pollution inside template code. Two main ways to be secure are:
- control the set of possible templates
- call ses'
lockdownwhich freezes Javascript intrinsics before callingfillOdtTemplate(this may lead to incompatibilities)
Demo
https://odfjs.github.io/odfjs/
Local dev
npm install
npm run dev
Expectations and licence
I hope to be credited for the work on this repo
Everything written by me and contributors to this repo is licenced under CC0 1.0 (Public Domain)