Create ods file (#5)

* Ajout de création de fichier .ods

* Ajout d'un outil pour créer un fichier .ods + rajout de styles.xml et meta.xml pour peut-être plaire à LibreOffice

* Créer des fichiers considérés corrompus-mais-réparables LibreOffice

* Creating libre-office-validated ods files

* readme with ods creation
This commit is contained in:
David Bruant 2024-10-23 19:13:29 +02:00 committed by GitHub
parent c90359bc7b
commit 57e0145ec7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 320 additions and 16 deletions

167
package-lock.json generated
View File

@ -9,7 +9,8 @@
"version": "0.7.0", "version": "0.7.0",
"dependencies": { "dependencies": {
"@xmldom/xmldom": "^0.8.10", "@xmldom/xmldom": "^0.8.10",
"unzipit": "^1.4.3" "unzipit": "^1.4.3",
"xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-commonjs": "^25.0.7",
@ -649,6 +650,15 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -1062,6 +1072,19 @@
"node": ">=16" "node": ">=16"
} }
}, },
"node_modules/cfb": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
"license": "Apache-2.0",
"dependencies": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/chalk": { "node_modules/chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@ -1247,6 +1270,15 @@
"@types/estree": "^1.0.0" "@types/estree": "^1.0.0"
} }
}, },
"node_modules/codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -1350,6 +1382,18 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
"license": "Apache-2.0",
"bin": {
"crc32": "bin/crc32.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/css-tree": { "node_modules/css-tree": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
@ -1667,6 +1711,15 @@
} }
} }
}, },
"node_modules/frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/fs-minipass": { "node_modules/fs-minipass": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@ -3666,6 +3719,18 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true "dev": true
}, },
"node_modules/ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"license": "Apache-2.0",
"dependencies": {
"frac": "~1.1.2"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/stack-utils": { "node_modules/stack-utils": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@ -4212,6 +4277,24 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -4343,6 +4426,27 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
"license": "Apache-2.0",
"dependencies": {
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
},
"bin": {
"xlsx": "bin/xlsx.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@ -4846,6 +4950,11 @@
"acorn": "^8.11.0" "acorn": "^8.11.0"
} }
}, },
"adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
},
"agent-base": { "agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -5156,6 +5265,15 @@
"nofilter": "^3.1.0" "nofilter": "^3.1.0"
} }
}, },
"cfb": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
"requires": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0"
}
},
"chalk": { "chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@ -5301,6 +5419,11 @@
} }
} }
}, },
"codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
},
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -5388,6 +5511,11 @@
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
"dev": true "dev": true
}, },
"crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
},
"css-tree": { "css-tree": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
@ -5621,6 +5749,11 @@
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true "dev": true
}, },
"frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
},
"fs-minipass": { "fs-minipass": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@ -7091,6 +7224,14 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true "dev": true
}, },
"ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"requires": {
"frac": "~1.1.2"
}
},
"stack-utils": { "stack-utils": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@ -7478,6 +7619,16 @@
} }
} }
}, },
"wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
},
"word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
},
"wrap-ansi": { "wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -7577,6 +7728,20 @@
} }
} }
}, },
"xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
"requires": {
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
}
},
"y18n": { "y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

View File

@ -27,6 +27,7 @@
}, },
"dependencies": { "dependencies": {
"@xmldom/xmldom": "^0.8.10", "@xmldom/xmldom": "^0.8.10",
"unzipit": "^1.4.3" "unzipit": "^1.4.3",
"xlsx": "^0.18.5"
} }
} }

View File

@ -8,13 +8,13 @@ Small lib to parse/understand .ods and .xsls files in the browser and node.js
### Install ### Install
```sh ```sh
npm i https://github.com/DavidBruant/ods-xlsx.git#v0.8.0 npm i https://github.com/DavidBruant/ods-xlsx.git#v0.9.0
``` ```
### Usage ### Usage
#### Basic #### Basic - reading an ods/xlsx file
```js ```js
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent} from 'ods-xlsx' import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent} from 'ods-xlsx'
@ -36,6 +36,40 @@ the **values** are automatically converted from the .ods or .xlsx files (which t
to the appropriate JavaScript value to the appropriate JavaScript value
#### Basic - creating an ods file
```js
import {createOdsFile} from 'ods-xlsx'
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
```
#### Low-level #### Low-level
See exports See exports

View File

@ -1,14 +1,15 @@
//@ts-check //@ts-check
function parseXML(str){
return (new DOMParser()).parseFromString(str, 'application/xml');
}
import { import {
_getODSTableRawContent, _getODSTableRawContent,
_getXLSXTableRawContent _getXLSXTableRawContent
} from './shared.js' } from './shared.js'
function parseXML(str){
return (new DOMParser()).parseFromString(str, 'application/xml');
}
/** /**
* @param {ArrayBuffer} odsArrBuff * @param {ArrayBuffer} odsArrBuff
* @returns {ReturnType<_getODSTableRawContent>} * @returns {ReturnType<_getODSTableRawContent>}
@ -26,6 +27,8 @@ export function getXLSXTableRawContent(xlsxArrBuff){
} }
export {createOdsFile} from './createOdsFile.js'
export { export {
// table-level exports // table-level exports
tableWithoutEmptyRows, tableWithoutEmptyRows,

27
scripts/createOdsFile.js Normal file
View File

@ -0,0 +1,27 @@
//@ts-check
import XLSX from 'xlsx'
import {tableRawContentToValues} from './shared.js'
/** @import {SheetName, SheetRawContent, SheetRowRawContent, SheetCellRawContent} from './types.js' */
const officeVersion = '1.2'
/**
* Crée un fichier .ods à partir d'un Map de feuilles de calcul
* @param {Map<SheetName, SheetRawContent>} sheetsData
* @returns {Promise<ArrayBuffer>}
*/
export async function createOdsFile(sheetsData) {
const workbook = XLSX.utils.book_new();
const sheetsDataValues = tableRawContentToValues(sheetsData)
for(const [sheetName, table] of sheetsDataValues){
const worksheet = XLSX.utils.aoa_to_sheet(table);
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
}
return XLSX.write(workbook, {bookType: 'ods', type: 'array'});
}

View File

@ -2,15 +2,17 @@
import {DOMParser} from '@xmldom/xmldom' import {DOMParser} from '@xmldom/xmldom'
function parseXML(str){
return (new DOMParser()).parseFromString(str, 'application/xml');
}
import { import {
_getODSTableRawContent, _getODSTableRawContent,
_getXLSXTableRawContent _getXLSXTableRawContent
} from './shared.js' } from './shared.js'
function parseXML(str){
return (new DOMParser()).parseFromString(str, 'application/xml');
}
/** /**
* @param {ArrayBuffer} odsArrBuff * @param {ArrayBuffer} odsArrBuff
* @returns {ReturnType<_getODSTableRawContent>} * @returns {ReturnType<_getODSTableRawContent>}
@ -27,6 +29,7 @@ export function getXLSXTableRawContent(xlsxArrBuff){
return _getXLSXTableRawContent(xlsxArrBuff, parseXML) return _getXLSXTableRawContent(xlsxArrBuff, parseXML)
} }
export {createOdsFile} from './createOdsFile.js'
export { export {
// table-level exports // table-level exports

View File

@ -1,7 +1,7 @@
//@ts-check //@ts-check
import { unzip } from 'unzipit'; import { unzip } from 'unzipit';
import './types.js' /** @import {SheetName, SheetRawContent, SheetRowRawContent, SheetCellRawContent} from './types.js' */
// https://dom.spec.whatwg.org/#interface-node // https://dom.spec.whatwg.org/#interface-node
const TEXT_NODE = 3 const TEXT_NODE = 3
@ -44,7 +44,7 @@ function extraxtODSCellText(cell) {
/** /**
* Extracts raw table content from an ODS file. * Extracts raw table content from an ODS file.
* @param {ArrayBuffer} arrayBuffer - The ODS file. * @param {ArrayBuffer} arrayBuffer - The ODS file.
* @param {(str: String) => Document} parseXML - Function to parse XML content. * @param {(str: string) => Document} parseXML - Function to parse XML content.
* @returns {Promise<Map<SheetName, SheetRawContent>>} * @returns {Promise<Map<SheetName, SheetRawContent>>}
*/ */
export async function _getODSTableRawContent(arrayBuffer, parseXML) { export async function _getODSTableRawContent(arrayBuffer, parseXML) {
@ -105,7 +105,7 @@ export async function _getODSTableRawContent(arrayBuffer, parseXML) {
/** /**
* Extracts raw table content from an XLSX file. * Extracts raw table content from an XLSX file.
* @param {ArrayBuffer} arrayBuffer - The XLSX file. * @param {ArrayBuffer} arrayBuffer - The XLSX file.
* @param {(str: String) => Document} parseXML - Function to parse XML content. * @param {(str: string) => Document} parseXML - Function to parse XML content.
* @returns {Promise<Map<SheetName, SheetRawContent>>} * @returns {Promise<Map<SheetName, SheetRawContent>>}
*/ */
export async function _getXLSXTableRawContent(arrayBuffer, parseXML) { export async function _getXLSXTableRawContent(arrayBuffer, parseXML) {

View File

@ -9,3 +9,5 @@
/** @typedef {SheetRowRawContent[]} SheetRawContent */ /** @typedef {SheetRowRawContent[]} SheetRawContent */
/** @typedef {string} SheetName */ /** @typedef {string} SheetName */
export {}

34
tests/create-ods-file.js Normal file
View File

@ -0,0 +1,34 @@
import test from 'ava';
import {getODSTableRawContent, createOdsFile} from '../scripts/node.js'
test('basic file creation', async t => {
const content = new Map([
[
'La feuille',
[
[
{value: 'azerty', type: 'string'},
{value: '37', type: 'float'}
]
]
]
])
// @ts-ignore
const odsFile = await createOdsFile(content)
const parsedContent = await getODSTableRawContent(odsFile)
t.assert(parsedContent.has('La feuille'))
const feuille = parsedContent.get('La feuille')
t.deepEqual(feuille, [
[
{value: 'azerty', type: 'string'},
{value: '37', type: 'float'}
]
])
});

View File

@ -0,0 +1,35 @@
//@ts-check
import {createOdsFile} from '../scripts/node.js'
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'}
]
],
]
])
// @ts-ignore
const ods = await createOdsFile(content)
//console.log('writableHighWaterMark', process.stdout.writableHighWaterMark) // 16384
process.stdout.write(new Uint8Array(ods))