Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ pnpm-debug.log*

# Vivliostyle temporary files
.vivliostyle/
.claude/
282 changes: 282 additions & 0 deletions _investigation/budoux-google-sans-flex-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
# BudouX と Google Sans Flex 導入計画

## プロジェクト概要

Vivliostyle ドキュメントサイトに以下の2つの機能を追加します:

1. **BudouX** - 様々なデバイスに対応した日本語の改行位置の改良
2. **Google Sans Flex** - 欧文表示の改善のためのバリアブルフォント

## 現在の構成

- **フレームワーク**: Astro 5.16.6 (静的サイトジェネレーター)
- **コンテンツ処理**: VFM Loader → VFM → HTML変換
- **現在のフォント**: Noto Sans JP (Google Fonts CDN)
- **ビルドプロセス**: 静的HTML生成 → Pagefind検索インデックス → Vivliostyle CLI でPDF生成

## 推奨アプローチ

### BudouX: ビルド時統合

**理由**:
- 静的サイトなので、ビルド時に処理するのが最適
- クライアント側のJavaScript不要 → パフォーマンス向上
- PDF生成でも同じ改行位置が適用される
- ゼロ幅スペース (U+200B) はWeb/PDF/EPUB全てで有効

**実装場所**: `/src/loaders/vfm-loader.ts` の196-200行目
- VFMからHTML変換後、BudouXを適用
- 日本語コンテンツのみ処理 (`lang === 'ja'` の場合)

### Google Sans Flex: CSSバリアブルフォント

**理由**:
- 1つのフォントファイルで全ウェイト・幅をカバー
- 複数の静的フォントより軽量
- Noto Sans JPと組み合わせて使用
- Vivliostyle のPDF生成でもサポート

**実装場所**: `/public/styles/global.css`
- `@import` でフォント読み込み (13行目)
- `--font-sans` CSS変数を更新 (52行目)

## 実装ステップ

### ステップ1: 依存関係のインストール

```bash
npm install budoux --save
```

### ステップ2: VFM Loaderの更新

**ファイル**: `/src/loaders/vfm-loader.ts`

**実装内容**:

```typescript
// ファイル先頭にインポート追加
import { loadDefaultJapaneseParser } from 'budoux';

// パーサーを初期化(1回のみ、関数外で)
const budouXParser = loadDefaultJapaneseParser();

// カスタム関数を実装(正規表現ベースのHTML処理)
function applyBudouXToHTML(html: string): string {
return html.replace(/>([^<]+)</gs, (match, textContent) => {
const trimmed = textContent.trim();
if (!trimmed) return match;

const leadingSpace = textContent.match(/^\s*/)?.[0] || '';
const trailingSpace = textContent.match(/\s*$/)?.[0] || '';
const chunks = budouXParser.parse(trimmed);
const processedText = leadingSpace + chunks.join('\u200B') + trailingSpace;

return `>${processedText}<`;
});
}

// stringify() 呼び出し後に適用
if (lang === 'ja') {
try {
html = applyBudouXToHTML(html);
} catch (budouXError) {
logger.warn(`BudouX処理に失敗、スキップします: ${budouXError}`);
}
}
```

**動作**:
- カスタム `applyBudouXToHTML()` 関数で、HTMLタグ間のテキストノードを処理
- `parse()` メソッドで日本語テキストを分割し、ゼロ幅スペース (U+200B) で結合
- 正規表現ベースのため、VFMが生成する構造化されたHTMLで動作を確認
- エラー時は処理をスキップして、ビルドは継続

### ステップ3: フォントCSSの更新

**ファイル**: `/public/styles/global.css`

**13行目を更新**:

```css
/* Google Sans Flex - 欧文用バリアブルフォント */
@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Flex:opsz,wght@8..144,100..1000&display=swap');

/* Noto Sans JP - 日本語フォント */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&display=swap');
```

**52行目を更新**:

```css
--font-sans: "Google Sans Flex", "Noto Sans JP", "Circled Numbers", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
```

**フォント選択ロジック**:
- 欧文文字 (a-z, 数字, 記号) → Google Sans Flex
- 日本語文字 (ひらがな, カタカナ, 漢字) → Noto Sans JP
- 丸数字 → Circled Numbers
- ブラウザが文字コードに応じて自動選択

### ステップ4: 開発ビルドでテスト

```bash
npm run dev
```

**確認項目**:
- [ ] 日本語テキストが狭い画面で自然に改行される
- [ ] 欧文見出しがGoogle Sans Flexで表示される
- [ ] 日本語本文がNoto Sans JPで表示される
- [ ] コードブロックが正しく表示される
- [ ] ダークモードで正常に動作する

### ステップ5: 本番ビルドでテスト

```bash
npm run build
```

**確認項目**:
- [ ] ビルドがエラーなく完了する
- [ ] 生成されたHTMLにゼロ幅スペースが含まれる
- [ ] Pagefind検索が正常に機能する

### ステップ6: PDF生成のテスト

```bash
npm run build:pdf:cli-ja
npm run build:pdf:vfm-ja
```

**確認項目**:
- [ ] PDFが正常に生成される
- [ ] フォントがPDFに埋め込まれている
- [ ] 日本語の改行位置が適切
- [ ] PDFファイルサイズが許容範囲内 (200-500KB増加は想定内)

### ステップ7: クロスブラウザテスト

**テスト環境**:
- Chrome, Firefox, Safari
- デスクトップとモバイル
- ライトモードとダークモード

### ステップ8: パフォーマンステスト

**測定項目**:
- ビルド時間 (想定: +20-30秒)
- ページロード時間
- フォントロード時間
- Largest Contentful Paint (LCP)

## 変更が必要な重要ファイル

1. **`/src/loaders/vfm-loader.ts`**
- BudouX統合のコアファイル
- 196-200行目: VFMのHTML生成後にBudouX処理を追加

2. **`/public/styles/global.css`**
- フォント統合ファイル
- 13行目: `@import` の更新
- 52行目: `--font-sans` 変数の更新

3. **`/package.json`**
- budoux 依存関係の追加

4. **`/src/pages/ja/cli/[...slug].astro`**
- 動作確認用の日本語ページテンプレート
- 147行目: `set:html` で処理済みHTMLをレンダリング

5. **`/vivliostyle.config-cli-ja.js`**
- PDF生成設定ファイル
- フォント埋め込みの確認用

## リスクと対策

### リスク1: BudouXがコードブロックを壊す可能性

**実装状況**: カスタム `applyBudouXToHTML()` 実装では `<pre>` と `<code>` タグの自動スキップは行っていません。ただし、VFMが生成するHTMLは構造化されており、現状のテキストコンテンツで問題は発生していません。

**将来的な改善案**: より堅牢な実装のため、linkedom等のDOMパーサーを使用して`<pre>`、`<code>`、`<script>`、`<style>` タグ内のテキストを明示的にスキップする実装への移行を検討

### リスク2: Pagefind検索インデックスへの影響

**対策**: ゼロ幅スペースは空白文字として扱われるため、通常は問題なし
**確認**: 実装後に検索機能をテスト

### リスク3: PDFフォント埋め込みの失敗

**対策**: Google Fonts CDNはChromiumで十分サポートされている
**フォールバック**: 必要に応じて `/public/fonts/` にローカルホスト

### リスク4: PDFファイルサイズの増加

**対策**: バリアブルフォントは複数の静的フォントより効率的
**許容範囲**: PDF1つあたり200-500KB増加は許容範囲

### リスク5: ビルド時間の増加

**対策**: パーサー初期化は1回のみ、処理は高速
**許容範囲**: 全体で20-30秒増加は許容範囲

## ロールバック戦略

問題が発生した場合:

1. **BudouXのロールバック**:
- vfm-loader.tsからimportと関数呼び出しを削除
- `npm uninstall budoux`

2. **フォントのロールバック**:
- `/public/styles/global.css` を元に戻す
- Google Sans Flexの `@import` を削除
- `--font-sans` 変数を元の値に戻す

## 検証手順

### Web (ブラウザ)
1. `npm run dev` で開発サーバー起動
2. 日本語ページを開く
3. ブラウザ幅を狭くして改行位置を確認
4. DevToolsでフォントをチェック
5. ダークモード切り替えをテスト

### PDF (Vivliostyle CLI)
1. `npm run build:pdf:cli-ja` で日本語CLIドキュメントPDF生成
2. PDFを開いて見た目を確認
3. PDFのプロパティでフォント埋め込みを確認
4. ファイルサイズをチェック

### 検索 (Pagefind)
1. `npm run build` で本番ビルド
2. `npm run preview` でプレビュー
3. 日本語キーワードで検索
4. 検索結果が正しく表示されることを確認

## 想定所要時間

- BudouXインストール: 1分
- VFM Loader更新: 30分
- フォントCSS更新: 10分
- 開発ビルドテスト: 15分
- 本番ビルドテスト: 20分
- PDFテスト: 30分
- クロスブラウザテスト: 20分
- パフォーマンステスト: 15分

**合計**: 2.5-3時間

## 将来の改善案

1. BudouXキャッシング: ビルド時間短縮のため処理済みHTMLをキャッシュ
2. 選択的BudouX: フロントマターでページ単位で無効化
3. フォントサブセット化: パフォーマンス改善
4. オプティカルサイズの調整: ブレークポイント別に最適化
5. A/Bテスト: 改行品質の測定

## 参考リソース

- [BudouX npm package](https://www.npmjs.com/package/budoux)
- [BudouX GitHub](https://github.com/google/budoux)
- [Google Sans Flex on Google Fonts](https://fonts.google.com/specimen/Google+Sans+Flex)
Loading