<div markdown="1">
  <sup>Using <a href="https://wangchujiang.com/#/app" target="_blank">my app</a> is also a way to <a href="https://wangchujiang.com/#/sponsor" target="_blank">support</a> me:</sup>
  <br>
  <a target="_blank" href="https://wangchujiang.com/dock-lift/" title="DockLift: Windows, Here"><img alt="DockLift: Windows, Here" height="52" src="https://wangchujiang.com/appicon/dock-lift.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6766860898" title="Zipora: Zip/RAR/7Z Unarchiver"><img alt="Zipora: Zip/RAR/7Z Unarchiver" height="52" src="https://wangchujiang.com/appicon/zipora.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6758053530" title="Scap: Screenshot & Markup Edit for macOS"><img alt="Scap: Screenshot & Markup Edit" height="52" src="https://wangchujiang.com/appicon/scap.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6757317079" title="Screen Test for macOS"><img alt="Screen Test" height="52" src="https://wangchujiang.com/appicon/screen-test.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6755948110" title="Deskmark for macOS"><img alt="Deskmark" height="52" src="https://wangchujiang.com/appicon/deskmark.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6500434773" title="Keyzer for macOS"><img alt="Keyzer" height="52" src="https://wangchujiang.com/appicon/keyzer.png"></a>
  <a target="_blank" href="https://github.com/jaywcjlove/vidwall-hub" title="Vidwall Hub for macOS"><img alt="Vidwall Hub" height="52" src="https://wangchujiang.com/appicon/vidwall-hub.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6752624705" title="VidCrop for macOS"><img alt="VidCrop" height="52" src="https://wangchujiang.com/appicon/vidcrop.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6747587746" title="Vidwall for macOS"><img alt="Vidwall" height="52" src="https://wangchujiang.com/appicon/vidwall.png"></a>
  <a target="_blank" href="https://wangchujiang.com/mousio-hint/" title="Mousio Hint for macOS"><img alt="Mousio Hint" height="52" src="https://wangchujiang.com/appicon/mousio-hint.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6746747327" title="Mousio for macOS"><img alt="Mousio" height="52" src="https://wangchujiang.com/appicon/mousio.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6745227444" title="Musicer for macOS"><img alt="Musicer" height="52" src="https://wangchujiang.com/appicon/musicer.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6743841447" title="Audioer for macOS"><img alt="Audioer" height="52" src="https://wangchujiang.com/appicon/audioer.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6744690194" title="FileSentinel for macOS"><img alt="FileSentinel" height="52" src="https://wangchujiang.com/appicon/file-sentinel.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6743495172" title="FocusCursor for macOS"><img alt="FocusCursor" height="52" src="https://wangchujiang.com/appicon/focus-cursor.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6742680573" title="Videoer for macOS"><img alt="Videoer" height="52" src="https://wangchujiang.com/appicon/videoer.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6740425504" title="KeyClicker for macOS"><img alt="KeyClicker" height="52" src="https://wangchujiang.com/appicon/key-clicker.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6739052447" title="DayBar for macOS"><img alt="DayBar" height="52" src="https://wangchujiang.com/appicon/daybar.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6739444407" title="Iconed for macOS"><img alt="Iconed" height="52" src="https://wangchujiang.com/appicon/iconed.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6737160756" title="Menuist for macOS"><img alt="Menuist" height="52" src="https://wangchujiang.com/appicon/rightmenu-master.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6723903021" title="Paste Quick for macOS"><img alt="Quick RSS" height="52" src="https://wangchujiang.com/appicon/paste-quick.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6670696072&platform=mac" title="Quick RSS for macOS/iOS"><img alt="Quick RSS" height="52" src="https://wangchujiang.com/appicon/quick-rss.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6670167443" title="Web Serve for macOS"><img alt="Web Serve" height="52" src="https://wangchujiang.com/appicon/web-serve.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6503953628&platform=mac" title="Copybook Generator for macOS/iOS"><img alt="Copybook Generator" height="52" src="https://wangchujiang.com/appicon/copybook-generator.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6471227008&platform=mac" title="DevTutor for macOS/iOS"><img alt="DevTutor for SwiftUI" height="52" src="https://wangchujiang.com/appicon/devtutor.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6479819388&platform=mac" title="RegexMate for macOS/iOS"><img alt="RegexMate" height="52" src="https://wangchujiang.com/appicon/regex-mate.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6479194014&platform=mac" title="Time Passage for macOS/iOS"><img alt="Time Passage" height="52" src="https://wangchujiang.com/appicon/time-passage.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6478772538" title="IconizeFolder for macOS"><img alt="Iconize Folder" height="52" src="https://wangchujiang.com/appicon/iconize-folder.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6478511402&platform=mac" title="Textsound Saver for macOS/iOS"><img alt="Textsound Saver" height="52" src="https://wangchujiang.com/appicon/textsound-saver.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6476924627" title="Create Custom Symbols for macOS"><img alt="Create Custom Symbols" height="52" src="https://wangchujiang.com/appicon/create-custom-symbols.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6476452351" title="DevHub for macOS"><img alt="DevHub" height="52" src="https://wangchujiang.com/appicon/devhub.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6476400184" title="Resume Revise for macOS"><img alt="Resume Revise" height="52" src="https://wangchujiang.com/appicon/resume-revise.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6472593276" title="Palette Genius for macOS"><img alt="Palette Genius" height="52" src="https://wangchujiang.com/appicon/palette-genius.png"></a>
  <a target="_blank" href="https://jaywcjlove.github.io/maslink/?id=6470879005" title="Symbol Scribe for macOS"><img alt="Symbol Scribe" height="52" src="https://wangchujiang.com/appicon/symbol-scribe.png"></a>
</div>
<hr>

rehype-video
===

[![Buy me a coffee](https://img.shields.io/badge/Buy_Me_a_Coffee-ffdd00?logo=buy-me-a-coffee&logoColor=black)](https://jaywcjlove.github.io/#/sponsor)
[![Follow On X](https://img.shields.io/badge/Follow%20on%20X-333333?logo=x&logoColor=white)](https://x.com/jaywcjlove)
[![Downloads](https://img.shields.io/npm/dm/rehype-video.svg?style=flat)](https://www.npmjs.com/package/rehype-video)
[![NPM version](https://img.shields.io/npm/v/rehype-video.svg?style=flat)](https://npmjs.org/package/rehype-video)
[![Build](https://github.com/jaywcjlove/rehype-video/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/rehype-video/actions/workflows/ci.yml)
[![Coverage Status](https://jaywcjlove.github.io/rehype-video/badges.svg)](https://jaywcjlove.github.io/rehype-video/lcov-report/)
[![Repo Dependents](https://badgen.net/github/dependents-repo/jaywcjlove/rehype-video)](https://github.com/jaywcjlove/rehype-video/network/dependents)

Add improved video syntax: links to `.mp4` and `.mov` turn into videos. like [`github video`](https://github.blog/2021-05-13-video-uploads-available-github/) features.

The following is a sample test of the video preview in GitHub:

https://user-images.githubusercontent.com/1680273/138299599-88547edd-859c-44c9-8b52-2cc06f7f2dd3.mov?!#title=Example%20Display

## Installation

This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): Node 12+ is needed to use it and it must be import instead of require.

```bash
npm install rehype-video
```

## Usage

```js
import { unified } from 'unified';
import remark2rehype from 'remark-rehype';
import remarkParse from 'remark-parse';
import rehypeVideo from 'rehype-video';
import stringify from 'rehype-stringify';

const string = `
https://files.github.com/001.mp4 hi!

https://files.github.com/002.mp4

Good \`idea\`!!

https://github.com/002.mp4?!#title=Custom%20Title
`;

const htmlStr = unified()
  .use(remarkParse)
  .use(remark2rehype, { allowDangerousHtml: true })
  .use(rehypeVideo)
  .use(stringify)
  .processSync(string)
  .toString();
```

Output:

```html
<p>https://files.github.com/001.mp4 hi!</p>
<details open>
  <summary>
    <svg aria-hidden height="16" width="16" viewBox="0 0 16 16" version="1.1" class="octicon octicon-device-camera-video"><path fill-rule="evenodd" d="M16 3.75a.75.75 0 00-1.136-.643L11 5.425V4.75A1.75 1.75 0 009.25 3h-7.5A1.75 1.75 0 000 4.75v6.5C0 12.216.784 13 1.75 13h7.5A1.75 1.75 0 0011 11.25v-.675l3.864 2.318A.75.75 0 0016 12.25v-8.5zm-5 5.075l3.5 2.1v-5.85l-3.5 2.1v1.65zM9.5 6.75v-2a.25.25 0 00-.25-.25h-7.5a.25.25 0 00-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-4.5z"></path></svg>
    <span aria-label="Video description 002.mp4">002.mp4</span>
    <span class="dropdown-caret"></span>
  </summary>
  <video muted controls style="max-height:640px;" src="https://github.com/002.mp4"></video>
</details>
<p>Good <code>idea</code>!!</p>
<details open>
  <summary>
    <svg aria-hidden height="16" width="16" viewBox="0 0 16 16" version="1.1" class="octicon octicon-device-camera-video"><path fill-rule="evenodd" d="M16 3.75a.75.75 0 00-1.136-.643L11 5.425V4.75A1.75 1.75 0 009.25 3h-7.5A1.75 1.75 0 000 4.75v6.5C0 12.216.784 13 1.75 13h7.5A1.75 1.75 0 0011 11.25v-.675l3.864 2.318A.75.75 0 0016 12.25v-8.5zm-5 5.075l3.5 2.1v-5.85l-3.5 2.1v1.65zM9.5 6.75v-2a.25.25 0 00-.25-.25h-7.5a.25.25 0 00-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-4.5z"></path></svg>
    <span aria-label="Video description Custom Title">Custom Title</span>
    <span class="dropdown-caret"></span>
  </summary>
  <video muted controls style="max-height:640px;" src="https://github.com/002.mp4"></video>
</details>
```

### Example 1

```js
import { rehype } from 'rehype';
import rehypeVideo from 'rehype-video';

const mrkStr = `<p>https://github.com/004.mp4</p>`;
const htmlStr = rehype()
  .data('settings', { fragment: true })
  .use(rehypeVideo, { details: false })
  .processSync(mrkStr)
  .toString();
```

Output:

```html
<video muted controls style="max-height:640px;" src="https://github.com/004.mp4"></video>
```

### Example 2

```js
import { rehype } from 'rehype';
import rehypeVideo from 'rehype-video';

const mrkStr = `<p><a href="https://github.com/004.mp4">https://github.com/004.mp4</a></p`;
const htmlStr = rehype()
  .data('settings', { fragment: true })
  .use(rehypeVideo, { details: false })
  .processSync(mrkStr)
  .toString();
```

Output:

```html
<video muted controls style="max-height:640px;" src="https://github.com/004.mp4"></video>
```

### Example 3

```js
import remarkParse from 'remark-parse';
import rehypeVideo from 'rehype-video';
import { unified } from 'unified';
import remark2rehype from 'remark-rehype';
import remarkParse from 'remark-parse';
import stringify from 'rehype-stringify';

const mrkStr = 'https://github.com/user-attachments/assets/0d808e2e-84c7-46ca-a220-440fa9f34118?title=rehype-video&rehype=video'

const htmlStr = unified()
  .use(remarkParse)
  .use(remark2rehype, { allowDangerousHtml: true })
  .use(rehypeVideo, {
    test: (url) => {
      return /\.(mp4|mov)|[?&]rehype=video/i.test(url);
    }
  })
  .use(stringify)
  .processSync(mrkStr)
  .toString();
```

Output:

```html
<details open class="octicon octicon-video">
  <summary>
    <svg aria-hidden height="16" width="16" viewBox="0 0 16 16" version="1.1" data-view-component class="octicon octicon-device-camera-video"><path fill-rule="evenodd" d="M16 3.75a.75.75 0 00-1.136-.643L11 5.425V4.75A1.75 1.75 0 009.25 3h-7.5A1.75 1.75 0 000 4.75v6.5C0 12.216.784 13 1.75 13h7.5A1.75 1.75 0 0011 11.25v-.675l3.864 2.318A.75.75 0 0016 12.25v-8.5zm-5 5.075l3.5 2.1v-5.85l-3.5 2.1v1.65zM9.5 6.75v-2a.25.25 0 00-.25-.25h-7.5a.25.25 0 00-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-4.5z"></path></svg>
    <span aria-label="Video description rehype-video">rehype-video</span><span class="dropdown-caret"></span>
  </summary>
  <video muted controls style="max-height:640px;" src="https://github.com/user-attachments/assets/0d808e2e-84c7-46ca-a220-440fa9f34118?title=rehype-video&#x26;rehype=video">
</video>
</details>
```

## Custom Title

Define custom title parameter(E.g: `title=RehypeVideo`) with hash route:

```js
const string = `https://github.com/002.mp4?!#title=Custom%20Title`;
const htmlStr = unified()
  .use(remarkParse)
  .use(remark2rehype, { allowDangerousHtml: true })
  .use(rehypeVideo)
  .use(stringify)
  .processSync(string)
  .toString();
```

Output:

```html
<details open>
  <summary>
    <svg aria-hidden height="16" width="16" viewBox="0 0 16 16" version="1.1" class="octicon octicon-device-camera-video"><path fill-rule="evenodd" d="M16 3.75a.75.75 0 00-1.136-.643L11 5.425V4.75A1.75 1.75 0 009.25 3h-7.5A1.75 1.75 0 000 4.75v6.5C0 12.216.784 13 1.75 13h7.5A1.75 1.75 0 0011 11.25v-.675l3.864 2.318A.75.75 0 0016 12.25v-8.5zm-5 5.075l3.5 2.1v-5.85l-3.5 2.1v1.65zM9.5 6.75v-2a.25.25 0 00-.25-.25h-7.5a.25.25 0 00-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-4.5z"></path></svg>
    <span aria-label="Video description Custom Title">Custom Title</span>
    <span class="dropdown-caret"></span>
  </summary>
  <video muted controls style="max-height:640px;" src="https://github.com/002.mp4"></video>
</details>
```

## \<track>

We will reference all two of the relevant VTT files by adding [\<track>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track) elements inside our HTML [\<video>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) element:

```js
const mrkStr = `https://github.com/sintel-short.mp4?!#track['en']=captions/vtt/sintel-en.vtt&track['en:label']=English&track['en:kind']=subtitles&track['en:default']=true&track['de']=captions/vtt/sintel-de.vtt&track['de:label']=Deutsch&track['de:kind']=subtitles`;
const htmlStr = unified()
  .use(remarkParse)
  .use(remark2rehype, { allowDangerousHtml: true })
  .use(rehypeVideo, { })
  .use(stringify)
  .processSync(mrkStr)
  .toString();
```

Output:

```html
<details open class="octicon octicon-video">
  <summary>
    <svg aria-hidden height="16" width="16" viewBox="0 0 16 16" version="1.1" data-view-component class="octicon octicon-device-camera-video">
      <path fill-rule="evenodd" d="M16 3.75a.75.75 0 00-1.136-.643L11 5.425V4.75A1.75 1.75 0 009.25 3h-7.5A1.75 1.75 0 000 4.75v6.5C0 12.216.784 13 1.75 13h7.5A1.75 1.75 0 0011 11.25v-.675l3.864 2.318A.75.75 0 0016 12.25v-8.5zm-5 5.075l3.5 2.1v-5.85l-3.5 2.1v1.65zM9.5 6.75v-2a.25.25 0 00-.25-.25h-7.5a.25.25 0 00-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-4.5z"></path>
    </svg>
    <span aria-label="Video description sintel-short.mp4">sintel-short.mp4</span>
    <span class="dropdown-caret"></span>
  </summary>
  <video muted controls style="max-height:640px;" src="https://github.com/sintel-short.mp4?!#track[&#x27;en&#x27;]=captions/vtt/sintel-en.vtt&#x26;track[&#x27;en:label&#x27;]=English&#x26;track[&#x27;en:kind&#x27;]=subtitles&#x26;track[&#x27;en:default&#x27;]=true&#x26;track[&#x27;de&#x27;]=captions/vtt/sintel-de.vtt&#x26;track[&#x27;de:label&#x27;]=Deutsch&#x26;track[&#x27;de:kind&#x27;]=subtitles">
    <track kind="subtitles" src="captions/vtt/sintel-en.vtt" label="English" default>
    <track kind="subtitles" src="captions/vtt/sintel-de.vtt" label="Deutsch">
  </video>
</details>
```

## Options

```ts
export declare type RehypeVideoOptions = {
  /**
   * URL suffix verification.
   * @default /\/(.*)(.mp4|.mov)$/
   */
  test?: RegExp;
  /**
   * Support `<details>` tag to wrap <video>.
   * @default true
   */
  details?: boolean;
  /**
   * Support `<track>` tag to wrap <video>.
   * @default true
   */
  track?: boolean;
};
```

## Related

- [`rehype-attr`](https://github.com/jaywcjlove/rehype-attr) New syntax to add attributes to Markdown.
- [`rehype-rewrite`](https://github.com/jaywcjlove/rehype-rewrite) Rewrite element with rehype.
- [`rehype-ignore`](https://github.com/jaywcjlove/rehype-ignore) Ignore content display via HTML comments, Shown in GitHub readme, excluded in HTML.
- [`remark-github-blockquote-alert`](https://github.com/jaywcjlove/remark-github-blockquote-alert) Remark plugin to add support for [GitHub Alert](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)

## License

MIT © [Kenny Wong](https://github.com/jaywcjlove)
