リンククリック対応を追加 (Closes #13)#14
Conversation
マークダウン内のリンクに応じて動作を切り替える。 - http/httpsなど外部URLは既定ブラウザで開く - ローカルファイル参照は.md/.markdownでreadableなら別ウインドウで開き、そうでなければ何もしない HTMLFormatterで相対パスをマークダウンファイルのディレクトリ基準で絶対URL化し、 WKWebViewのdecidePolicyFor navigationActionでクリックを捕捉してスキーム別にディスパッチする。 Closes #13 Co-authored-by: Claude Code <claude@anthropic.com>
WKWebViewのloadHTMLStringで表示した場合、decidePolicyFor navigationActionが リンククリックで呼ばれないケースがあった (file originまわりの制約)。 JavaScriptでaタグのclickを捕捉し、WKScriptMessageHandler経由で Swift側に通知する方式に切り替える。 - fragment-only リンク (#section) はJS側で素通しし、ページ内ジャンプを維持 - decidePolicyForは.linkActivated検知時のフォールバックとして残す Co-authored-by: Claude Code <claude@anthropic.com>
|
マージ前に 2 点気になりました。
|
1. 相対パス + fragment (other.md#section) が壊れる問題
URL(fileURLWithPath:)はパス全体をパス名として扱うため、#が%23に
パーセントエンコードされ、pathExtensionが"md%23section"になって
.md判定で弾かれていた。URL(string:relativeTo:)ベースに書き換え、
fragment/queryを正しく保持したまま絶対URL化する。
2. ページ内アンカー (#section) がジャンプしない問題
.linkActivated を無条件cancelしていたためWebKitの既定動作まで
届かなかった。主処理はJSインターセプタ側で href.startsWith('#')
の時に document.getElementById().scrollIntoView() を実行する
形に変更。decidePolicyFor側も保険として、現在ドキュメントと
同一 (scheme/host/path) で fragment のみ異なる navigation を
allow するフォールバックを追加。
openLocalMarkdownFile 側も fragment/query を取り除いた素のファイル
URLでNotificationをpostするよう修正 (受信側は単純なfile URLを期待)。
テスト追加:
- 相対リンク + fragment が file:///.../other.md#section に解決されること
- そのURLをパースしたときpathExtensionが"md"でfragmentが保持されること
- 相対リンク + query が保持されること
Co-authored-by: Claude Code <claude@anthropic.com>
|
ご指摘2点対応しました (d274c47)。 1. 2. テスト3件追加 (fragment保持 / pathExtension判定 / query保持) で合計 22 件通過しています。実機確認でも |
- 見出しにGitHub風のslug IDを付与 (HTMLFormatter.slugify)
例: ## section → <h2 id="section">
同名見出しの衝突時は-1,-2のsuffixを付ける
- fragment-only リンク (#section) がJS側のgetElementById→
scrollIntoViewで正しくジャンプするようになる
- other.md#inner のような別ファイル+fragmentリンクで、
リンク先ファイルを別ウインドウで開いた後、対応する見出しに
スクロールする:
- openLocalMarkdownFile で fragment を保持したまま URL を post
- ContentView.loadMarkdownFile(url:) で fragment を state 化
- MarkdownWebView.initialFragment → Coordinator.pendingFragment
- didFinish で pendingFragment があれば scrollIntoView を実行
(スクロール位置復元より優先)
- テストで HTMLFormatter が swift-markdown の同名型と ambiguous
だったため MarkdownViewer.HTMLFormatter と明示修飾
テスト7件追加 (slug化6件 + query保持1件)、合計29件通過
Co-authored-by: Claude Code <claude@anthropic.com>
|
追加で2点対応しました (15b9627)。
テスト合計 29 件通過、実機でもページ内ジャンプ / 別ファイル fragment ジャンプとも動作確認済みです。 |
|
前回の 2 点は解消されているのを確認できました。追加で 1 点だけ気になっています。
経路としては:
なので、fragment を一度適用したら |
指摘対応: fragment付きURL (other.md#inner) で開いたファイルの 自動リロード時にも毎回 scrollIntoView されてしまい、スクロール位置 維持の挙動が崩れていた。 MarkdownWebView.initialFragment を @binding<String?> に変更し、 updateNSView で pendingFragment に引き渡した直後に親側 state を nil にクリアする。これで initialFragment は一度だけ消費され、 以降の自動リロード等では pendingFragment=nil となり、通常の スクロール位置復元のみが実行される。 Co-authored-by: Claude Code <claude@anthropic.com>
|
ご指摘対応しました (d2fdb64)。
|
|
最新 head
|
Summary
http/https等の外部URL → 既定ブラウザで開く (NSWorkspace.shared.open).md/.markdownかつ読み取り可能なら別ウインドウで開く。それ以外は何もしないHTMLFormatterでリンク先を事前解決し、相対パスをマークダウンファイルのディレクトリ基準で絶対URL化WKWebViewのdecidePolicyFor navigationActionで.linkActivatedを捕捉してスキーム別にディスパッチ実装メモ
loadHTMLString時のbaseURLは bundle パスのまま維持 (mermaid.min.jsの相対ロードに依存)。リンク側は HTML 生成時に絶対化しているためbaseURLと独立に解決できる#section) はそのまま残すTest plan
swift test全通過 (既存 10 件 + 新規HTMLFormatterLinkTests9 件).//親..//絶対パス/fragment/mailto/baseURL 未設定/%エンコード のケースを網羅.mdリンクが別ウインドウで開くこと、存在しないファイルや画像への相対リンクが何もしないこと🤖 Generated with Claude Code