PubliraGitHub

独立して使えるライブラリ

いずれもApache-2.0ライセンスで、Publiraの本番の処理でも使われています。プラットフォームを導入しなくても利用できます。

@publira/comic-viewer

エピソード画面を描画しているReact製のコミックビューアーを切り出したものです。UIもデータの取得や加工も、すべてアプリケーション側で自由に実装できます。

  • ヘッドレスUIアーキテクチャ。tree-shaking可能な独立したコンポーネントを組み合わせ、すべてのスタイルを自分で定義できます。
  • コンテナの幅に応じて単ページと見開きを切り替えるレスポンシブな見開き表示。
  • 高解像度のページを大量に読み込んでもモバイルブラウザがクラッシュしないための仮想化。
  • 差し替え可能なデータパイプライン。definePlugin()でデータの取得、復号、アクセス解析などの処理を組み込めます。
  • 既定はマンガ向けの右から左で、欧米のコミック向けに左から右にも切り替えられます。スワイプ、クリック、キーボードでの操作に標準で対応します。
  • resolvePage()によるページメタデータの遅延取得。ページ数の多い文書や、有効期限付きの署名付きURLに対応します。

1.0未満です。0.x系の中ではパッチリリースは互換性の維持を目指しますが、マイナーリリースでは公開APIが変わることがあります。アップグレードの前に変更履歴を確認してください。

ドキュメントを読む
インストール
npm install @publira/comic-viewer
app/reader.tsx
import * as ComicViewer from "@publira/comic-viewer";
import "@publira/comic-viewer/core.css";

export function Reader({ pages }: ReaderProps) {
  return (
    <ComicViewer.Root
      initialReadingDirection="rtl"
      pages={pages}
    >
      <ComicViewer.Viewport />
      <ComicViewer.Toolbar />
      <ComicViewer.PageNavigation />
    </ComicViewer.Root>
  );
}

publira/epub

EPUB 3のデコード、エンコード、検証を行うGoライブラリです。ディスク上のファイルにアクセスしないサーバー向けに設計されています。

  • ファイルシステムに依存しません。Decodeが受け取るのはio.ReaderAtとアーカイブのサイズだけです。
  • フェイルファスト。構造上の違反はただちにDecodeErrorとして返ります。
  • メモリ効率が高く、Asset.Openでオンデマンドにストリームへアクセスできます。
  • EBPAJとKADOKAWA方式のファイル名とディレクトリ構成の規則を厳密に検証します。
  • 固定レイアウトの画像ページをSVGで包むので、EPUBリーダーの種類にかかわらずページが画面に収まるように表示されます。
  • 表紙、目次、本文、索引、用語集のランドマークに構造的なセマンティクスを付与します。

生成した出版物は、リポジトリに同梱のスクリプトでW3C公式のEPUBCheckにかけて検証できます。ツールは.tools/以下にキャッシュされます。

ドキュメントを読む
インストール
go get github.com/publira/epub
main.go
f, err := os.Open("book.epub")
if err != nil {
	log.Fatal(err)
}
defer f.Close()

st, err := f.Stat()
if err != nil {
	log.Fatal(err)
}

opt := epub.WithCompliance(epub.LevelEBPAJ)
doc, err := epub.Decode(f, st.Size(), opt)
if err != nil {
	log.Fatal(err)
}

if err := epub.Encode(out, doc); err != nil {
	log.Fatal(err)
}

publira/messageformat-dart

Unicode MessageFormat 2.0のピュアDart実装で、LDML 48.2に準拠しています。Publiraのモバイルクライアントのメッセージ整形に使っています。

  • ピュアDartでFlutterに依存しません。サーバーでもコマンドラインでもFlutterアプリでも同じように動きます。
  • MessageFormatワーキンググループの適合性テストスイート (LDML48.2) の461件すべてにスキップなしで合格します。CIで変更のたびに実行しています。
  • 仕様でStableに分類されている関数 (:string, :number, :integer, :offset, :currency, :percent) をすべてサポートし、数値はCLDRのすべてのロケールで整形できます。
  • Draftに分類されている日付と時刻の関数はmessageformat_datetimeパッケージに分けているので、日付を整形しないアプリにはそのCLDRデータが含まれません。
  • formatToPartsはパーツをDartのsealedクラスによる型の階層で返すので、装飾付きテキストのような出力も組み立てられます。
  • 整形中のエラーは例外を投げずにコールバックへ報告し、フォールバック値で表示を続けます。標準の関数に加えて独自の関数も登録できます。

1.0未満です。LDML 48.2 (UTS #35 Part 9, tr35-78) とUnicode CLDR 48.2のデータに従い、新しいバージョンの仕様への移行はそれだけを含むリリースとして行います。

ドキュメントを読む
インストール
dart pub add messageformat
main.dart
import 'package:messageformat/messageformat.dart';

final mf = MessageFormat(
  'en',
  r'''
.input {$count :number}
.match $count
0   {{No episodes}}
one {{{$count} episode}}
*   {{{$count} episodes}}
''',
  options: const MessageFormatOptions(
    bidiIsolation: BidiIsolation.none,
  ),
);

mf.format({'count': 0}); // 'No episodes'
mf.format({'count': 1}); // '1 episode'
mf.format({'count': 1000}); // '1,000 episodes'