Zennの記事では、本文中のURLがカードとして表示される。
https://zenn.dev/meijin/articles/linaria-class-name-config
これは初期ロード時はPlaceholderが掛かっているため、フロントエンドで動的に表示できていると推測できる。
この仕組みを少しだけ調査したのでメモ。
Zenn本体のソースは公開されていないはずだが、CLIのソースは公開されているため、ほぼ同様の技術とみなして調査できる。
markdownをHTMLにパースするときに、URLを見つけたらiframeに変換している。
// 以下の2つをどちらも満たした場合にリンク化
// 1. パラグラフ先頭 もしくは リンクの前が br
// 2. パラグラフの末尾 もしくは リンクの後が br
const shouldConvertToCard =
(isStartOfLine || isPrevBr) && (isEndOfLine || isNextBr);
if (!shouldConvertToCard) {
newTokens.push(token); // 変換は行わずに出力結果に含める
return;
}
// 埋め込み用のHTMLを生成
const embedToken = new Token('html_inline', '', 0);
if (isTweetUrl(url)) {
embedToken.content = generateTweetHtml(url);
} else if (isYoutubeUrl(url)) {
embedToken.content = generateYoutubeHtmlFromUrl(url);
} else {
embedToken.content = generateCardHtml(url);
}
// a要素自体はカードにより不要になるため非表示に
linkOpenToken.attrJoin('style', 'display: none');
export function generateCardHtml(url: string) {
return `<div class="embed-zenn-link"><iframe src="https://card.zenn.dev/?url=${encodeURIComponent(
url
)}" frameborder="0" scrolling="no" loading="lazy"></iframe></div>`;
}
card.zenn.dev
はURLを受け取って、カードを描画する専用のサイトらしい。iframe埋め込み用で、VercelにホスティングされているらしいことまではHeaderから推測できる。
つまるところ、ざっくりいえば以下の手順でこの実装が実現できるはず。
- iframe用の専用のサイトを立ち上げて公開、iframe埋め込みは許可する( https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options )
- markdownのパーサーでURLのパースをカードに切り替える