GROWI, an open source wiki, has a plug-in feature. You can use it to display your own data or customize the display.
This time, we will introduce a PDF viewer I created as a GROWI plugin, which can be easily extended by creating it as a Remark plugin.
About the code
The code is goofmint/growi-plugin-pdf-viewer: Viewing PDF File inside of GROWI
The code can be found at The two files to view are as follows.
Add the plugin
To use it, please add it at Plugin
in the admin panel of GROWI, the URL is https://github.com/goofmint/growi-plugin-pdf-viewer
.
Usage
The plugin uses the notation $pdfviewer
. Upload a PDF file in the editor and write $pdfviewer(filename)
to display the PDF viewer.
For example, the following statement.
$pdfviewer(/attachment/669c803453e575a188286be3)
However, the embedding size will not work as it is, so you need to adjust the width
and height
options.
$pdfviewer(/attachment/669c803453e575a188286be3,width=75%,height=850px)
About implementation
Here is the code for the registration part of the plugin client-entry.tsx
.
import { plugin } from './src/pdfviewer';
const activate = (): void => {
if (growiFacade == null || growiFacade.markdownRenderer == null) {
return;
}
const { optionsGenerators } = growiFacade.markdownRenderer;
optionsGenerators.customGenerateViewOptions = (...args) => {
const options = optionsGenerators.generateViewOptions(...args);
// プラグインを追加
options.remarkPlugins.push(plugin as any);
return options;
};
};
PDF Viewer part
This time, I use ts-pdf
based on PDF.js as the PDF Viewer; It needs a web worker, so I get it from Cloudfare CDN. It also needs a div tag to display the PDF so it renders it once and then (500ms later) displays the PDF.
Several times this plugin code part has been called, so we are checking if there is a Shadow DOM in the rendered div tag. If there is, we do not initialize the PDF viewer.
The div tag id is hashed with the file path using sha256. This allows multiple PDF viewers within a single page.
import sha256 from 'crypto-js/sha256';
import { TsPdfViewer, TsPdfViewerOptions } from 'ts-pdf';
import type { Plugin } from 'unified';
import { visit } from 'unist-util-visit';
interface GrowiNode extends Node {
name: string;
type: string;
attributes: {[key: string]: string}
children: GrowiNode[];
value: string;
}
export const plugin: Plugin = function() {
return (tree) => {
visit(tree, (node) => {
const n = node as unknown as GrowiNode;
try {
if (n.type === 'leafGrowiPluginDirective' && n.name === 'pdfviewer') {
const filePath = Object.keys(n.attributes)[0];
const { width, height } = n.attributes;
// ファイル名からユニークなIDを生成
const key = sha256(filePath);
const containerSelector = `#pdf-${key}`;
const options: TsPdfViewerOptions = {
containerSelector,
workerSource: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js',
};
n.type = 'html';
// PDFビューワーを表示するdivタグをレンダリング
n.value = `<div id="pdf-${key}" style="width: ${width}; height: ${height};"></div>`;
// HTML描画を待って、500ms後にPDFビューワーを初期化
setTimeout(() => {
if (!document.querySelector(containerSelector)?.shadowRoot) {
const viewer = new TsPdfViewer(options);
viewer.openPdfAsync(filePath);
}
}, 500);
}
}
catch (e) {
n.type = 'html';
n.value = `<div style="color: red;">Error: ${(e as Error).message}</div>`;
}
});
};
};
Notes.
PDF.js has a function to adjust the display size, but ts-pdf does not, so the display size must be adjusted manually. Also, I can't find an option to specify a CMap file, and currently it does not support the display of Japanese PDFs (if you know how to specify it, please let me know!).
Summary
GROWI's Remark plugin allows you to freely extend the Markdown notation. If there are any missing features, you can add more and more. By all means, customize your own wiki.
GROWI, an OSS development wiki tool | comfortable information sharing for all
Top comments (0)