埋め込み#
埋め込みは Markdown 中の HTML 風タグで、変換時に静的 HTML へ展開されます。静的マークアップだけを出す 2 つは既定でオン、それ以外はオプトインです。
| 埋め込み | オプション | 既定 | 書き方 |
|---|---|---|---|
| GitHub カード | embeds.github |
true |
<GitHub repo="owner/name" /> |
| OG リンクカード | embeds.openGraph |
true |
<OgCard url="https://..." /> |
| パッケージマネージャタブ | embeds.pm |
false |
<pm>npm install pkg</pm> |
| Twitter / X | embeds.twitter |
false |
<Tweet /> または <XPost /> |
embeds.reddit |
false |
<Reddit url="https://..." /> |
|
| Bluesky | embeds.bluesky |
false |
<Bluesky /> |
| Google Maps | embeds.googleMaps |
false |
<GoogleMaps url="https://..." /> |
| Qiita | embeds.qiita |
false |
<Qiita url="https://..." /> |
| Zenn | embeds.zenn |
false |
<Zenn url="https://..." /> |
| パッケージ registry | embeds.packageRegistry |
false |
<NpmPackage url="https://..." /> |
| Playgrounds | embeds.playgrounds |
false |
<CodePen url="https://..." /> |
| Vimeo | embeds.vimeo |
false |
<Vimeo url="https://..." /> |
| Twitch | embeds.twitch |
false |
<Twitch url="https://..." /> |
| Discord | embeds.discord |
false |
<Discord url="https://..." /> |
| Fediverse | embeds.fediverse |
false |
<Mastodon url="https://..." /> |
embeds.facebook |
false |
<Facebook url="https://..." /> |
|
| Threads | embeds.threads |
false |
<Threads url="https://..." /> |
embeds.instagram |
false |
<Instagram url="https://..." /> |
|
| Spotify | embeds.spotify |
false |
<Spotify url="https://..." /> |
| Apple Music | embeds.appleMusic |
false |
<AppleMusic url="https://..." /> |
| Speaker Deck | embeds.speakerDeck |
false |
<SpeakerDeck url="https://..." /> |
| Audio | embeds.audio |
false |
<Audio src="https://..." /> |
| Video | embeds.video |
false |
<Video src="https://..." /> |
| StackBlitz | embeds.stackBlitz |
false |
<StackBlitz url="https://..." /> |
| WebContainer | embeds.webContainer |
false |
<WebContainer /> |
タブと YouTube 埋め込みは embeds オプションの外です。SSG ビルドと dev preview では常に処理され、設定は不要です。同じ執筆モデルなので 下 で扱います。
<Tweet> や <OgCard> のようなドキュメント上の PascalCase タグは .md と .mdx の両方で動きます。同じ名前のドキュメントローカル import(import Tweet from "./Tweet")は組み込みより優先され、MDX island のまま残ります。
.md では 1 タグ 1 行#
以下の例は読みやすさのため属性を複数行に分けています。この形式には MDX が必要です。素の .md ファイルでは、タグの開始と > を同じ行に収める必要があります。
<Bluesky url="https://bsky.app/profile/danabra.mov/post/3mqzxmtfnxk2b" handle="danabra.mov">…</Bluesky>
CommonMark が生の HTML ブロックを開始するのは、開始タグがその行の中で閉じている場合だけです。行末でタグが開いたままだと本文として扱われ、属性はテキストとして描画され、URL はリンクになり、> だけの行は引用ブロックになります。複数行で書きたい場合は mdx を有効にしてください。
すべての組み込み埋め込みを切るときは embeds: false、個別に設定するときはオブジェクトです。
import { oxContent } from "@ox-content/vite-plugin";
export default {
plugins: [
oxContent({
embeds: {
github: { maxSourceLines: 120 },
openGraph: { timeout: 5000 },
pm: { sync: true },
twitter: true,
reddit: true,
bluesky: true,
qiita: true,
zenn: true,
packageRegistry: true,
playgrounds: true,
vimeo: true,
twitch: { iframe: true, parent: "docs.example.com" },
},
}),
],
};
GitHub カード#
embeds.github はビルド時に GitHub API からリポジトリカードとソーススニペットを描画します。出力は静的 HTML です。クライアント側 JavaScript も、第三者ウィジェットのスクリプトも使いません。
リポジトリカード:
<GitHub repo="ubugeeei-prod/ox-content" />
all-in-one markdown toolchain ― fastest, tiniest, framework agnostic, powerful, customizable
ref と行範囲を固定したソーススニペット:
<GitHub repo="ubugeeei-prod/ox-content" path="README.md" ref="main" loc="1-10" />
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/oxcontent-light.svg">
<source media="(prefers-color-scheme: light)" srcset="./assets/oxcontent-dark.svg">
<img alt="Ox Content logo" src="./assets/oxcontent-dark.svg" height="60">
</picture>
</p>
<p align="center">
<strong>High-performance Markdown toolkit</strong><br>パーマリンク形式も使えます。#L10-L18 行アンカー付きの GitHub blob URL を貼ります。
<GitHub permalink="https://github.com/ubugeeei-prod/ox-content/blob/278098b/npm/vite-plugin-ox-content/src/plugins/github.ts#L10-L18" />
import rehypeStringify from "rehype-stringify";
import type { Root, Element } from "hast";
export interface GitHubRepoData {
name: string;
full_name: string;
description: string | null;
html_url: string;
stargazers_count: number;ソースカードのヘッダは blob へリンクし、GitHub API が返すときは、その ref でそのパスを最後に触ったコミットも表示します。
| オプション | 既定 | 目的 |
|---|---|---|
token |
"" |
レート制限とプライベートリポジトリ向け GitHub API トークン。 |
cache |
true |
API 応答をメモリにキャッシュする。 |
cacheTTL |
3600000 |
キャッシュ寿命(ミリ秒)。 |
maxSourceBytes |
200000 |
これより大きいファイルは飛ばす。 |
maxSourceLines |
120 |
範囲指定がないときのインライン行数上限。 |
明示的な token がなければ process.env.GITHUB_TOKEN を自動で拾います。ビルド中にリポジトリやファイルが取れないとき — オフライン CI、レート制限、不正なパス — 埋め込みはビルドを落とさず、フォールバックのリンクカードを描画します。
GitHub issue、pull request、commit、discussion、gist の URL も、同じ
embeds.github オプションで静的カードとして描画できます。
<GitHub url="https://github.com/ubugeeei-prod/ox-content/issues/699" />
<GitHub url="https://github.com/ubugeeei-prod/ox-content/pull/1025" />
<GitHub url="https://github.com/ubugeeei-prod/ox-content/commit/5399e080b5320d730e410a49a5aab42ba670a1f1" />
<GitHub url="https://github.com/ubugeeei-prod/ox-content/discussions/1" />
<GitHub url="https://gist.github.com/ubugeeei/0123456789abcdef0123456789abcdef" />
これらの resource card は、認証なしで読める public metadata だけを取得します。削除済み、非公開、レート制限、未対応の resource は deterministic な link-only card に落ちます。
Open Graph カード#
embeds.openGraph はビルド時にページの Open Graph メタデータを取り、静的リンクカードを描画します。
<OgCard url="https://vite.dev" />
| オプション | 既定 | 目的 |
|---|---|---|
timeout |
10000 |
取得タイムアウト(ミリ秒)。 |
cache |
true |
取得したメタデータを現在のプロセスのメモリにキャッシュ。 |
cacheTTL |
3600000 |
鮮度の窓(ミリ秒)。 |
persistCache |
false |
成功・失敗エントリをビルド間でディスクに残す。 |
cacheDir |
.cache/ox-content/ogp |
永続メタデータキャッシュディレクトリ。 |
refresh |
false |
新しいキャッシュがあっても再取得する。 |
userAgent |
ox-content-ogp-bot/1.0 ... |
対象へ送る User-Agent。 |
persistCache: true にすると、クリーンビルドや CI ワーカーでもメタデータを再利用できます。成功した取得と届かなかった URL は、正規化した URL ごとに 1 つの JSON として cacheDir へ保存します。新しいエントリはネットワークを飛ばし、期限切れと refresh: true は再取得してファイルをアトミックに置き換えます。壊れたファイルは無視するので、後続ビルドを汚染しません。変換に渡したメタデータは、キャッシュや取得より優先されます。
届かないページはプレーンなリンクカードに落ちます。localhost、プライベート IP 範囲、HTTP(S) 以外のスキームへのリクエストは拒否するので、Markdown 本文がビルド環境のネットワークを探れません。
カードのテキストはページ自身のマークアップからデコードするので、Tips & Tricks と書かれた og:title は Tips & Tricks として描画されます。og:image は宣言元のページを基準に解決し(絶対・プロトコル相対・文書相対のいずれの形式も動きます)、フェッチャーが拒否する先へ解決された場合は破棄します。
favicon は対象ページ自身の <link rel="icon"> から取り、無ければその origin の /favicon.ico へフォールバックします。サードパーティの favicon サービスへは接続しないので、カードを描画してもドキュメントページのリンク先が外部ホストへ伝わりません。
埋め込みを解決できない場合#
プロバイダは認識できる入力に対してのみカードを描画します。有効なプロバイダがタグを解決できない場合(対象外のホスト、知らないパス形状など)、タグは未知の要素としてページに残るのではなく、素のリンクへ降格します。
<a
class="ox-embed-fallback"
href="https://qiita.com/ubugeeei"
target="_blank"
rel="noopener noreferrer"
>https://qiita.com/ubugeeei</a
>
リンク文言はタグの本文、次に title、最後に URL の順で決まります。フォールバックの class にプロバイダ名は含めません。レンダラは「自分のものではない」ことだけを伝え、ホストが違うのかパスだけが違うのかを区別しないため、名前を付けると偽装ホストがそのプロバイダのスタイルを借りられてしまうからです。
リンクとして安全でない URL(HTTPS 以外のスキーム、埋め込み資格情報など)を持つタグは元のマークアップのまま残り、無効なプロバイダには一切手を触れません。
パッケージマネージャタブ#
embeds.pm は 1 つの npm 風コマンドを、vp(Vite+)、pnpm、bun、npm、yarn 向けのアクセシブルなタブグループへ展開します。
oxContent({
embeds: {
pm: true,
},
});
<pm>npm install -D @ox-content/vite-plugin @ox-content/theme-swiss</pm>
vp install -D @ox-content/vite-plugin @ox-content/theme-swisspnpm add -D @ox-content/vite-plugin @ox-content/theme-swissbun add -D @ox-content/vite-plugin @ox-content/theme-swissnpm install -D @ox-content/vite-plugin @ox-content/theme-swissyarn add -D @ox-content/vite-plugin @ox-content/theme-swissコマンド変換は Rust ネイティブです。npm install -D は vp install -D、pnpm add -D、bun add -D、yarn add -D になり、npx <bin> は vp exec -- <bin> になります。タブはクライアント側 JavaScript なしで動きます。選択は CSS :has() です。pm: { sync: true } をオプトインすると、ページ上のすべてのブロックで選んだパッケージマネージャを localStorage 経由で同期します。変換表の全体は Package Manager Tabs を見てください。
タブ#
汎用タブグループはパッケージマネージャタブと同じウィジェットで、SSG ビルドと dev preview では常に使えます。
<tabs>
<tab label="Install">
<pre><code>pnpm add -D @ox-content/vite-plugin
pnpm add -D @ox-content/theme-swiss</code></pre>
</tab>
<tab label="Config">
<pre><code>oxContent({ srcDir: "content", embeds: { pm: true } })</code></pre>
</tab>
<tab label="Markdown">
<pre><code>---
title: Install
---
好きなパッケージマネージャで Ox Content を入れます。
<pm>npm install -D @ox-content/vite-plugin</pm></code></pre>
</tab>
<tab label="Build">
<pre><code>pnpm vite build
pnpm vite preview</code></pre>
</tab>
</tabs>
pnpm add -D @ox-content/vite-plugin
pnpm add -D @ox-content/theme-swissoxContent({ srcDir: "content", embeds: { pm: true } })---
title: Install
---
好きなパッケージマネージャで Ox Content を入れます。
pnpm vite build
pnpm vite previewlabel 属性のない <tab> は Tab 1、Tab 2 のように落ちます。
隣り合うコード例は、手書きの <tabs> よりオプトインの ::: code-group を使ってください。コードグループ を見てください。
YouTube#
YouTube 埋め込みは SSG ビルドと dev preview で常に処理されます。iframe はプライバシー強化モード(youtube-nocookie.com)と遅延読み込みが既定です。
<YouTube id="Ny8pjacNIv8" title="An Evening with Ron Carter at Emmet’s Place" />
id、url、href 属性を受け付けます。youtu.be、watch?v=、shorts、embed の URL 形はどれも認識します。start は非負整数の秒で、iframe URL に ?start= を付けます。不正、負、小数、オーバーフロー、重複した値は無視します。start を省略すると、これまでの URL のままです。
<YouTube id="Ny8pjacNIv8" title="An Evening with Ron Carter at Emmet’s Place" start="4190" />
Twitter / X#
embeds.twitter は投稿を静的カードとして描画し、第三者ウィジェットのスクリプトは決して読みません。twitter: true のとき、埋め込みはプライバシーを意識したカードです。要素本文が投稿本文になり、任意の属性で作者、アバター、日時、リアクション数、元投稿リンクをネットワークなしで出せます。
<XPost
url="https://x.com/evanyou/status/1688035849638977536"
displayName="Evan You"
handle="evanyou"
dateLabel="Aug 6, 2023"
replies="134"
likes="6.2K"
>
Thank you JavaScript.
</XPost>


オブジェクト形式を使うと、ビルド時に本文、著者、アバター、写真、動画ポスターを取り、自分のオリジンから配信します。取ってきたカードには、日時、元投稿リンク、利用可能な返信/リポスト/引用/いいね/表示数、引用投稿の入れ子カード、「Replying to @…」リンクも含まれます。appearance: "full" は sveltweet / react-tweet 形の静的カードです。
oxContent({
embeds: {
twitter: {
fetch: true,
lang: "en",
appearance: "compact",
timeZone: "UTC",
mediaOutputDir: "public/ox-content/twitter",
mediaPublicPath: "/ox-content/twitter",
},
},
});
| オプション | 既定 | 目的 |
|---|---|---|
fetch |
false |
ビルド時に投稿本文を取る。 |
lang |
"en" |
syndication 言語と表示日付。 |
timeout |
10000 |
メタデータ要求のタイムアウト(ミリ秒)。 |
cache |
true |
メモリと永続 JSON キャッシュ。 |
cacheDir |
.cache/ox-content/twitter |
永続メタデータキャッシュディレクトリ。 |
mediaOutputDir |
public/ox-content/twitter |
アバター、写真、動画のローカルディレクトリ。 |
mediaPublicPath |
/ox-content/twitter |
ダウンロードしたメディアに出す URL プレフィックス。 |
downloadVideo |
false |
ビルド時に MP4 動画とアニメーション GIF を取る。 |
maxVideoBytes |
8388608 |
これより大きい動画はスキップする(8 MiB)。 |
appearance |
"compact" |
"full" で sveltweet 形の静的クロムを出す。 |
timeZone |
"UTC" |
フルカード日時の IANA タイムゾーン。 |
ダウンロードしたメディアは自分のサイトから出すので、厳しい img-src 'self' CSP も動き続けます。動画とアニメーション GIF は、downloadVideo をオンにしない限り自前のポスターと Watch on X パーマリンクを使い、生成 HTML に video.twimg.com は出しません。削除済みや非公開の投稿は、ビルドを落とさずリンクのみのカードに落ちます。引用投稿が欠けていても、元の投稿カードは残します。フルカード用 CSS は .ox-tweet--full を描画するページにだけ載ります。フルカードのクロムは MIT ライセンスの react-tweet と sveltweet の見た目の契約に従います。帰属は クレジット にあります。詳細は Twitter/X Embed を見てください。
組み込み SSG のページでは、フル Tweet カードがあると Copy link 用の progressive enhancement が自動で入ります。独自ホストで Ox Content の HTML を描画する場合は、同じ初期化関数を import できます。
import { initTweetCards } from "@ox-content/vite-plugin/twitter/client";
initTweetCards(document);
独自ホストは @ox-content/vite-plugin/styles/social.css を、appearance: "full"
なら styles/twitter-full.css も import します。記事の中に置く場合もこの2つで足ります。フルカードの CSS は、@tailwindcss/typography のような本文用スタイルシートが、カードの置き換えた要素に当てる規則を打ち消します。アバターやメディアへの画像マージン、引用投稿への引用符とその typography、カード自体への figure の余白などです。.prose .ox-tweet--full … のような上書きを下流で書く必要はありません。コンポーネント CSS を見てください。
Reddit#
embeds.reddit は Reddit 投稿を静的カードとして描画します。オプトインで、Reddit のウィジェットスクリプトは読みません。reddit: true ではビルド時に投稿 JSON を取り、Reddit が返す subreddit、作者、タイトル、本文抜粋、スコア、コメント数、日時、画像プレビュー、元リンクを出します。
oxContent({
embeds: {
reddit: true,
},
});
<Reddit url="https://www.reddit.com/r/webdev/comments/abc123/release_notes/" />
reddit.com/r/{subreddit}/comments/{id}/{slug} URL と redd.it/{id} 共有リンクは、出力前に https://www.reddit.com/... へ正規化します。新しい /r/{subreddit}/s/{share} 形式は、URL だけでは投稿 ID が分からないため、リンクのみのカードとして受け付けます。
| オプション | 既定 | 目的 |
|---|---|---|
fetch |
true |
ビルド時に投稿メタデータを取る。 |
timeout |
10000 |
メタデータ要求のタイムアウト(ミリ秒)。 |
cache |
true |
取得したメタデータをこのビルドのメモリに残す。 |
cacheTTL |
3600000 |
鮮度の窓(ミリ秒)。 |
userAgent |
ox-content-reddit-bot/1.0 ... |
Reddit JSON エンドポイントに送る User-Agent。 |
reddit: { fetch: false } にすると、ネットワークなしのリンクカードだけを描画します。削除済み、非公開、レート制限、その他の取得不能な投稿もビルドを落とさずリンクカードへ落ちます。未対応スキーム、認証情報付き URL、Reddit 以外のホスト、投稿ではないパスは href="#" のエラーカードになります。
Bluesky#
embeds.bluesky は静的カードを描画します。カードに出すテキストは要素本文なので、ネットワーク要求は一切要りません。
<Bluesky url="https://bsky.app/profile/danabra.mov/post/3mqzxmtfnxk2b">
the urge to fix everything incorrectly
</Bluesky>
the urge to fix everything incorrectly
プロバイダカード#
プロバイダカードは、地図、記事、package、playground、動画、デザインファイル、 スライド、コミュニティ投稿を静的な preview として描画します。第三者の widget スクリプトは一切読み込みません。カードは transform が出力した HTML そのもので、 値はビルド時に fetch したものか、属性で渡したもののどちらかです。
provider が embed URL を公開しているカードは embed 属性も受け取ります。渡すと
metadata の下に遅延読み込みの iframe が付き、リンクではなく現物がページに出ます。
embed は provider ごとに検証され、その provider 自身の embed host と path だけを
受け付けます。それ以外は描画せず捨てます。
以下のカードはすべて実際に描画されたものです。各カードの上にあるタグがその出力元です。
地図#
embeds.googleMaps は place と address から場所カードを描画します。Google Maps
の embed URL を embed に渡すと、地図そのものを載せたカードになります。
<GoogleMaps
url="https://www.google.com/maps/place/Tokyo+Station/"
place="東京駅"
address="東京都千代田区丸の内 1-9-1"
embed="https://www.google.com/maps/embed?pb=..."
/>
東京駅
東京都千代田区丸の内 1-9-1
embed を外すと同じタグがリンクのみのカードになります。閲覧時に Google へ
リクエストを飛ばしたくないページ向けです。
東京駅
東京都千代田区丸の内 1-9-1
embed として受け付けるのは https://www.google.com/maps/embed… だけです。場所 URL、
maps.app.goo.gl の短縮リンク、その他の host は無視され、上のリンクのみのカードに
フォールバックします。
記事#
embeds.qiita、embeds.zenn、embeds.note は既定でタイトル・著者・カウントを
fetch します。このサイトのように fetch: false にすると、カードは属性だけから
組み立てられます。ビルドはオフラインのままで、数値も書いた値に固定されます。
この3つはプロバイダカードの枠ではなくリンクプレビューカード(.ox-ogp-card、
修飾子は .ox-ogp-card--qiita など)として描画されます。OGP カードと並べても
見た目の言語が1つに揃います。著者・日付・カウントはカードの meta 行に入り、
fetch したサムネイルはカード画像になります。
<Qiita
url="https://qiita.com/ubugeeei/items/73a2416fd46cfe6311a8"
title="【日本語版】All we know about Vue 3’s Vapor Mode"
author="@ubugeeei"
tags="Vue.js, compiler, VaporMode"
likes="32"
dateTime="2023-12-17"
>
Vapor Mode は template を DOM 操作へ直接コンパイルします。
</Qiita>
パッケージレジストリ#
embeds.packageRegistry は npm、crates.io、PyPI、Docker Hub に対応し、provider が
持つ version / tag URL も扱えます。version、license、repository、downloads、
stars がメトリクスとして描画されます。downloads は pulls という綴りでも受け取り、
下の Docker Hub カードはそちらを渡しています。
レジストリカードは名前ではなくレジストリ自身のマークを、メトリクスはラベルではなく アイコンを先頭に置きます。語はスクリーンリーダー向けの不可視テキストとして markup に 残るので、読み上げは "Downloads 31M/week" のままです。
<NpmPackage
url="https://www.npmjs.com/package/vite"
version="7.1.0"
license="MIT"
downloads="31M/week"
/>
vite
次世代フロントエンドツーリング
serde
Rust のシリアライズフレームワーク
requests
HTTP for Humans
nginx
Nginx の公式ビルド
Playground#
embeds.playgrounds は CodePen、CodeSandbox、JSFiddle、Observable、Replit を
まとめて扱います。それぞれ自身の embed URL を受け取れるので、説明ではなく
動いている sandbox をそのまま見せられます。
<CodePen
url="https://codepen.io/miriamsuzanne/pen/BEvjbm"
title="Angled Background CSS-only Mixin"
author="@miriamsuzanne"
embed="https://codepen.io/miriamsuzanne/embed/BEvjbm"
/>
Angled Background CSS-only Mixin
棒グラフ
JSFiddle embedding example
CodeSandbox だけは何も fetch しません。カードは URL と渡した属性だけから組み立てる
ので、削除済みの sandbox でもビルドを落とさずカードを描画します。sandbox の
指定方法は 4 通りすべて受け付けます(/s/{id}、/p/sandbox/{id}、
/p/devbox/{id}、/embed/{id})。
React starter
Node.js
デザインファイルとスライド#
embeds.figma と embeds.googleSlides は provider の共有 URL を受け取ります。
Google Slides は /embed URL も受け取り、デッキをそのままページ内に描画します。
<GoogleSlides
url="https://docs.google.com/presentation/d/1EAYk.../edit"
title="Baby album"
slides="9"
embed="https://docs.google.com/presentation/d/1EAYk.../embed"
/>
Baby album
Figma は file、design、board、proto、slides と Community のリンクを
受け付けます。ファイルキーは種別の次のセグメントで、その後ろの人間向け slug は
無視されます。
Material 3 Design Kit
動画とターミナル録画#
embeds.vimeo、embeds.loom、embeds.asciinema、embeds.twitch は duration、
views、status をメトリクスに持つ動画カードを描画します。Vimeo、Loom、
asciinema は player URL を embed として受け取れます。
<Vimeo
url="https://vimeo.com/76979871"
title="The New Vimeo Player"
embed="https://player.vimeo.com/video/76979871"
/>
The New Vimeo Player (You Know, For Videos)
Star Wars: Episode IV
Loom product overview
Twitch だけは例外です。player は埋め込み先ドメインを宣言しないと読み込みを拒否する
ため、player URL は embeds.twitch.parent に安全なドメインを指定したときだけ生成
されます。指定がなければカードは静的なままなので、title、channel、duration、
status、views、image で見せる価値のあるカードにします。
TwitchDev
コミュニティと social post#
embeds.discord、embeds.fediverse、embeds.facebook、embeds.threads、
embeds.instagram は同じカード形状を共有します(著者、本文、時刻、リアクション数)。
<Fediverse>、<Mastodon>、<Misskey>、<Mixi2> は同じオプションで、instance は
URL から読み取ります。
<Mastodon
url="https://mastodon.social/@Mastodon/117117221397911074"
author="@Mastodon@mastodon.social"
reposts="622"
likes="954"
>
Mastodon 5.0 の最初のお披露目。
</Mastodon>
Mastodon post
Discovery Week の結果公開に続いて、Mastodon 5.0 を最初にお披露目します。
Vue Land
Vue とそのエコシステムのコミュニティサーバ。
著者・本文・カウントを渡すだけで、Facebook の SDK は読み込みません。
@instagram on Threads
Threads の投稿も同じカードで描画されます。
Instagram カードも静的なままで、embed スクリプトは読み込みません。
プロバイダのオプション#
| オプション | 既定値 | 用途 |
|---|---|---|
fetch |
true |
記事・package・playground・動画の metadata を取得 |
timeout |
10000 |
metadata リクエストのタイムアウト (ms) |
cache |
true |
このビルド中、metadata をメモリにキャッシュ |
cacheTTL |
3600000 |
鮮度のウィンドウ (ms) |
persistCache |
false |
ビルドをまたいで metadata をディスクに保持 |
cacheDir |
.cache/ox-content/providers |
永続キャッシュのディレクトリ |
iframe |
false |
playground / 動画の lazy iframe URL を付与 |
parent |
[] |
Twitch iframe の parent ドメイン |
iframe は 導出 される embed の話です。渡されたページ URL から provider が player
URL を組み立てられるようにします。明示的な embed 属性はどちらの設定でも効きます。
cache だけなら 1 ビルド分の寿命です。persistCache: true にすると metadata を
ディスクにも書くので、クリーンビルドや新しい CI ワーカーが前回の取得結果を再利用します。
見つからなかった lookup も記憶するため、落ちている provider をビルドのたびに embed の
数だけ再試行することはありません。壊れたエントリはビルドを落とさず破棄して取り直し、
ディレクトリは hash で鍵付けされるので、provider URL がその外へ出ることはありません。
未対応 scheme、認証情報つき URL、別 host の URL、取得できない metadata は、ビルドを
落とさず元のタグかリンクカードへフォールバックします。package metadata fetch の失敗時は、
status や error reason を含む [ox-content] warning も出します。Vimeo card は Vimeo の
public oEmbed endpoint から metadata を取得し、Twitch card は既定では認証 API を
呼びません。
Spotify#
embeds.spotify はトラック、アルバム、プレイリスト、エピソード、番組、アーティスト向けの公式 iframe プレーヤーを描画します。
<Spotify url="https://open.spotify.com/track/2VEQTuWiuEC7J8kkA7h7xq" />
出力は遅延読み込み付きで open.spotify.com/embed/... を指す <iframe> です。上の静的カードと違い、本物の第三者プレーヤーなのでオプトインのままです。
フレームには再生対象に応じた名前(Spotify track、Spotify playlist など)が付くので、スクリーンリーダーが「フレーム」より有用な読み上げをします。自分で名前を付けるには title を渡します。
<Spotify url="https://open.spotify.com/album/25Dgs9rR8ETpGCwD0wUv0q" title="Joel Ross — nublues" />
Apple Music#
embeds.appleMusic はアルバム、プレイリスト、曲、アーティスト、ミュージックビデオ向けの公式 iframe プレーヤーを描画します。
<AppleMusic url="https://music.apple.com/us/album/ummg-feat-taylor-eigsti/1769360313?i=1769360314" />
music.apple.com の共有 URL は embed.music.apple.com に書き換えられ、ストアフロントとパス、曲選択の i= クエリは残します。すでに埋め込み用の embed.music.apple.com URL も、同じホスト/パス検査のあと受け付けます。HTTPS でない URL、似せたホスト、認証情報、フラグメント、不正なパスは iframe にせず、書いたまま残します。
プレーヤーは第三者 iframe なので、オプションは既定でオフです。Content-Security-Policy を設定しているサイトでは、プレーヤーを読み込むために frame-src https://embed.music.apple.com(または同等の child-src)が必要です。書き方の詳細は Apple Music Embed を見てください。
Speaker Deck#
embeds.speakerDeck は、プレーヤー URL か oEmbed メタデータが解決できたとき遅延 iframe を描画し、取得や解析に失敗したときは安全なリンクカードに落とします。
<SpeakerDeck url="https://speakerdeck.com/jane/my-talk" title="My Talk" author="Jane Doe" />
上のデッキは存在しないため、この例はプレーヤーではなくリンクカードのフォールバックを示しています。
speakerdeck.com/{user}/{slug} の共有 URL はビルド時に oEmbed で title / author_name / プレーヤー ID / サムネイルを取ります。存在しない ID でもプロバイダ自身のエラーページを埋め込んでしまうため、例では共有 URL を使ってください。すでに埋め込み用の speakerdeck.com/player/{id} はネットワークなしで描画します。javascript: と data: URL は書いたまま残します。
oEmbed 取得やプレーヤー ID の解析に失敗したときは、元の HTTPS Speaker Deck URL を指すフォールバックリンクカードになります。iframe は遅延読み込みで、sandbox と referrerpolicy="strict-origin-when-cross-origin" を付けます。Content-Security-Policy を設定しているサイトでは frame-src https://speakerdeck.com が必要です。詳細は Speaker Deck Embed を見てください。
Audio / Video#
embeds.audio と embeds.video はネイティブの <audio> / <video> プレーヤーを描画します。既定はオフで、第三者 iframe は使いません。
oxContent({ embeds: { audio: true, video: true } });
<Audio
src="https://cdn.example.com/intro.mp3"
title="Episode intro"
transcript="/intro.txt"
download="/intro.mp3"
/>
<Video
src="/talk.mp4"
poster="/talk.jpg"
captions="/talk.en.vtt"
srclang="en"
label="English"
width="1280"
height="720"
title="Release talk"
/>
ソースは HTTPS か同一オリジンの相対パスだけです。javascript:、data:、http:、プロトコル相対 URL は書いたまま残します。入れ子の <track> で追加のキャプション/字幕を渡せます。ネイティブ controls は title(なければ Audio / Video)でラベルされます。width / height で動画のアスペクト比を確保し、レイアウトシフトを避けます。詳細は Audio and Video Embed を見てください。
StackBlitz#
embeds.stackBlitz は StackBlitz プロジェクト URL を、embed=1 を付けたサンドボックス iframe にします。
<StackBlitz url="https://stackblitz.com/edit/vitejs-vite"></StackBlitz>
WebContainer#
embeds.webContainer は、操作時に WebContainers を起動するサイト向けに、プロジェクトソースとクロスオリジン分離メタデータを持つ遅延プレースホルダを出します。プレースホルダ自体は完全に静的です。
<WebContainer entry="index.html" title="Demo">
npm install
npm run dev
</WebContainer>
index.htmlBoots on interactionnpm install
npm run dev分離要件は WebContainer Embed を見てください。
関連#
- Mermaid — 静的 SVG に描画する図フェンス。
- コンポーネント CSS — 独自ホスト向けの公式 CSS。
- 組み込み機能の一覧