feature (plg_application_docx): another docx reader

This commit is contained in:
MickaelK
2025-08-26 13:30:21 +10:00
parent adb51ac8b9
commit ff17bc2732
4 changed files with 98 additions and 0 deletions

View File

@ -0,0 +1,15 @@
all:
make setup
make build
make install
setup:
[ -d lib/vendor ] || mkdir -p lib/vendor
curl -L https://raw.githubusercontent.com/VolodymyrBaydalka/docxjs/refs/heads/master/dist/docx-preview.js > lib/vendor/docx-preview.js
curl -L https://unpkg.com/jszip/dist/jszip.min.js > lib/vendor/jszip.min.js
build:
zip -r application_docx.zip .
install:
mv application_docx.zip ../../../dist/data/state/plugins/

View File

@ -0,0 +1,16 @@
.component_docx {
width: 100%;
}
.component_docx .docx-wrapper {
background: #f5f5f5;
}
.component_docx .docx-wrapper > section.docx {
box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
.component_filedownloader {
width: 100%;
margin: 0 auto;
}

View File

@ -0,0 +1,55 @@
import { createElement } from "../../lib/skeleton/index.js";
import rxjs, { effect } from "../../lib/rx.js";
import ajax from "../../lib/ajax.js";
import { loadJS, loadCSS } from "../../helpers/loader.js";
import ctrlError from "../../pages/ctrl_error.js";
import { transition } from "../../pages/viewerpage/common.js";
import ctrlDownloader, { init as initDownloader } from "../../pages/viewerpage/application_downloader.js";
import { createLoader } from "../../components/loader.js";
await init();
/*
* This viewer application is for rendering a docx onto an HTML document. To get a smooth UI, the whole
* flow is broken down to these steps:
* 1) show a loading spinner => `... = createLoader($page);`
* 2) fetch the docx file => effect(ajax({ xxxx })).pipe(
* 3) remove the spinner => cancelLoader,
* 4) render + transition => ... renderDocx ...
* 5) fallback on error => ... catchError ... ctrlDownloader(...)
*
* note: you don't have to use rxjs if you don't like it, the same code could be written with plain
* promises instead. We just happen to be rxjs fanboys who enjoy the automatic resource cleanup it
* enforces. In this example, if the user navigates away before the docx is loaded, the ajax call
* is cancelled automatically. Additionally, we prefer thinking in terms of streams rather than
* the classical state management approach used by most frameworks.
*/
export default async function(render, { getDownloadUrl, getFilename, $menubar, acl$ }) {
const $page = createElement(`
<div class="component_docx"></div>
`);
render($page);
const cancelLoader = createLoader($page);
effect(ajax({ url: getDownloadUrl(), responseType: "arraybuffer" }).pipe(
cancelLoader,
rxjs.mergeMap(async ({ response }) => renderDocx(response, $page)),
rxjs.catchError(() => ctrlDownloader(render, { acl$, getFilename, getDownloadUrl, hasMenubar: false })),
));
}
async function renderDocx(response, $page) {
$page.classList.add("hidden");
await window.docx.renderAsync(response, $page)
$page.classList.remove("hidden");
$page.parentElement.classList.add("scroll-y");
transition($page);
}
function init() {
return Promise.all([
loadCSS(import.meta.url, "./loader_docx.css"),
initDownloader(),
loadJS(import.meta.url, "./lib/vendor/jszip.min.js").then(() => loadJS(import.meta.url, "./lib/vendor/docx-preview.js")),
]);
}

View File

@ -0,0 +1,12 @@
{
"author": "Filestash Pty Ltd",
"version": "v0.0",
"modules": [
{
"type": "xdg-open",
"mime": "application/word",
"entrypoint": "loader_docx.js",
"application": "skeleton"
}
]
}