2
1

PDFビューワー for GROWIプラグインの紹介

Posted at

オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。

今回は、GROWIプラグインとして作ったPDFビューワーを紹介します。Remarkプラグインとして作れば、手軽に拡張できます。

FireShot Capture 358 - PDF - GROWI - localhost 358.jpg

コードについて

コードはgoofmint/growi-plugin-pdf-viewer: Viewing PDF File inside of GROWI
にあります。見るべきファイルとしては、以下の2つになります。

プラグインを追加する

利用する際には、GROWIの管理画面の プラグイン にて追加してください。URLは https://github.com/goofmint/growi-plugin-pdf-viewer です。

FireShot Capture 359 - プラグイン - GROWI - localhost 359.jpg

使い方

プラグインは $pdfviewer という記法を使います。エディタにて、PDFファイルをアップロードし、 $pdfviewer(ファイル名) と記述すると、PDFビューワーが表示されます。

たとえば以下のような記述です。

$pdfviewer(/attachment/669c803453e575a188286be3)

ただし、そのままだと埋め込みサイズがうまくいかないので、 widthheight のオプションで調整してください。

$pdfviewer(/attachment/669c803453e575a188286be3,width=75%,height=850px)

実装について

プラグインの登録部分 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ビューワー部分

今回はPDF Viewerとして、PDF.jsをベースにした ts-pdf を利用しています。Webワーカーが必要なので、CloudfareのCDNから取得しています。また、PDFを表示するdivタグが必要なので一旦それをレンダリングし、その後(500ms後)にPDFを表示します。

何度かこのプラグインコード部分が呼ばれることがあったので、描画したdivタグの中にShadow DOMが存在しないかを確認しています。あればPDFビューワーを初期化しません。

divタグのidは、ファイルパスをsha256でハッシュ化しています。これにより、1ページの中で複数のPDFビューワーを表示しても問題ありません。

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>`;
      }
    });
  };
};

注意点

PDF.jsには表示サイズを調整してくれる機能があるのですが、ts-pdfにはないため、表示サイズを手動調整する必要があります。また、CMapファイルを指定するオプションが見当たらず、現状では日本語PDFの表示には対応していません(指定方法があれば教えてください!)。

まとめ

GROWIのRemarkプラグインを使うと、Markdown記法を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。

OSS開発wikiツールのGROWI | 快適な情報共有を、全ての人へ

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1