No framework
The class the React, Vue and Angular packages wrap. If you are not using any of them, use this.
The viewer
main.ts
import { createViewer } from '@apertura/viewer';
const viewer = createViewer(document.getElementById('stage')!, { fit: 'width' });
// A File, a Blob, a byte buffer or a URL.
await viewer.open(file);
// State changes push, rather than being polled.
const stop = viewer.subscribe((state) => {
if (state.status === 'loading') progress.value = state.progress;
if (state.status === 'error') console.error(state.error);
});
// Format-specific navigation lives on the view.
viewer.view?.goToPage(4);
// Release the document, the object URLs and the listeners.
stop();
viewer.destroy();destroy() is not optional
Media inside a document is exposed through object URLs whose lifetime the view owns. Dropping the viewer without destroying it leaks them for as long as the page lives.
Parsing without rendering
The parsers have no DOM dependency at all, so this path runs equally in a browser, in a web worker and in Node.
read.ts
import { MemoryByteSource, detectFormat } from '@apertura/core';
import { openDocx } from '@apertura/docx';
const source = new MemoryByteSource(bytes);
const detection = await detectFormat(source); // from the bytes, not the extension
if (detection.format === 'docx') {
const document = await openDocx(source);
await document.extractText();
document.outline(); // headings
document.metadata; // title, author, dates
}Without a bundler
Every package ships as ESM with no dependencies, so a module script and an import map are enough for a prototype.
index.html
<div id="stage" style="height: 90vh"></div>
<script type="module">
import { createViewer } from 'https://esm.sh/@apertura/viewer';
const viewer = createViewer(document.getElementById('stage'), { fit: 'width' });
await viewer.open('/report.docx');
</script>