[[Reading view]] および [[Editing view]] において、[[内部リンク]]を[[ポインティングデバイス]]でクリックしたときに、[[内部リンク]]が指すファイルのパスを取得する方法。
クリックイベントの処理をinterceptし、パスを取得した後、必要に応じて独自の処理を追加する。
```ts
import { getActiveEditor } from "src/lib/helpers/editors/basic";
import { getLinkTokenAtOffset, linkText2Path } from "src/lib/helpers/links";
import { map } from "src/lib/utils/guard";
const handler = async (ev: MouseEvent) => {
// 特定の修飾キーとセットの場合のみ発動させる場合はearly returnする
// if (!ev.metaKey || ev.button !== 0) {
// return;
// }
// リンクの要素を取得. Live PreviewがあるのでEditing viewかどうかだけでは判定不可
const linkEl = (ev.target as HTMLElement).closest(
".cm-hmd-internal-link,.internal-link",
);
if (!linkEl) {
return;
}
// クリックの対象として内部リンクの要素が存在するなら、伝播を停止する
// (標準の挙動がキャンセルされるのは偶然かも..?)
ev.stopPropagation();
// リンクを構成するテキストを取得
const linkText =
// プレビュー表示の場合
linkEl.getAttribute("data-href") ??
// 編集表示の場合
map(
getActiveEditor()?.cm,
(cm) => getLinkTokenAtOffset(cm.posAtDOM(linkEl))?.text,
);
if (!linkText) {
return;
}
// リンク対象のファイルパスに変換
const path = linkText2Path(linkText);
};
document.addEventListener("click", handler, true);
```
> [!note]
> 以下の関数は[[🦉Carnelian]]の実装を確認すること。
>
> - `getActiveEditor`
> - `getLinkFileAtOffset`
> - `linkText2Path`
> - `map`
> [!caution]
> `onunload` のときにhandlerの解除を忘れないように。
>
> ```ts
> document.removeEventListener("click", handler, true);
> ```
## 参考
- [carnelian/src/services/link-click-service.ts at bc29f95246cf8b1bbd85481491ae145bffe4a028 · tadashi-aikawa/carnelian](https://github.com/tadashi-aikawa/carnelian/blob/bc29f95246cf8b1bbd85481491ae145bffe4a028/src/services/link-click-service.ts?plain=1#L10)