mdv-live 0.5.17 → 0.5.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,71 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.19] - 2026-05-16
9
+
10
+ ### Fixed — Marp `![bg]` background images
11
+
12
+ Marp の `![bg](画像)` 背景画像構文を含むスライドが mdv で真っ白になっていた
13
+ バグを修正。NotebookLM 製の図解 13 枚を `![bg]` で全面配置したプレゼンが mdv
14
+ で全スライド空白になり発覚(157_イディアコーポレーション案件)。
15
+
16
+ - 原因: marp-core は `![bg]` を `<img>` ではなく
17
+ `<figure style="background-image:url(&quot;パス&quot;)">` として出力する。
18
+ `rewriteMediaPaths` は `<img>/<video>/<audio>/<source>` の `src` 属性しか
19
+ `/raw/` に書き換えず、CSS の `background-image:url(...)` を素通ししていた。
20
+ 結果、相対パスが SPA の現在 URL 基準で誤解決され 404 → CSS 背景画像のため
21
+ コンソールエラーも出ず真っ白になっていた
22
+ - `rewriteMediaPaths` に `background-image:url(...)` 書き換えルールを追加。
23
+ marp-core が HTML エンコードするクォート(`&quot;`)に対応
24
+ - quoted URL は **対応する閉じクォートまで** を URL として読む。最初の `)` で
25
+ 切らないため、`cover (1).png` のような括弧入りファイル名
26
+ (Marp 出力 `url(&quot;cover%20(1).png&quot;)`)も壊れない
27
+ - 絶対 URL・data URI・空 URL は書き換えない
28
+ - 既知の制約: 1 つの `background-image:` 宣言に複数 `url()` がある場合は先頭
29
+ のみ書き換わる。`![bg]` は 1 枚ごとに別 `<figure>` になるため影響なし。
30
+ カンマ区切りの `backgroundImage:` ディレクティブのみのエッジケース
31
+
32
+ ### Verified
33
+
34
+ - 278 テスト 全 PASS(既存 272 + 新規 6: `![bg]` 相対/サブディレクトリ/括弧/
35
+ エンコード空白/空/絶対 URL)
36
+ - Playwright dogfood(`docs/dogfood_20260516/`): 全面 bg / bg fit / split bg /
37
+ インライン画像 / 絶対 URL bg / サブディレクトリ解決の 6 ケースを実機目視、
38
+ コンソールエラー 0
39
+ - Codex review 3 round(codex-loop)で収束。round 1 [P2] 括弧切れ修正、
40
+ round 2 [P3] 空 URL ガード、round 3 [P3] 複数 url 制約を文書化
41
+
42
+ ## [0.5.18] - 2026-05-12
43
+
44
+ ### Fixed — Offline operation
45
+
46
+ ビューワがネットワーク接続なしでも完全に動くようになった。これまで
47
+ `index.html` が 5 つの CDN (highlight.js / Mermaid / html2pdf.js / Tailwind /
48
+ hljs テーマ CSS) を直接読み込んでいたため、Wi-Fi 切断時はシンタックスハイ
49
+ ライト・図表・PDF 出力・全 UI スタイルが死ぬ状態だった。
50
+
51
+ - `src/static/vendor/` に各ライブラリのオフライン版を同梱
52
+ - `scripts/sync-vendor.js` でメンテナが version bump 時に node_modules /
53
+ Tailwind Play CDN から再生成 (`node scripts/sync-vendor.js`)
54
+ - Tailwind は v3.4.17 で pin (v4 系は `tailwind.config` 構文が変わるため)
55
+ - `index.html` と `app.js` (`HLJS_THEMES`) の CDN URL を `/static/vendor/...`
56
+ に置換
57
+ - 各ライブラリのライセンス本文を `vendor/licenses/` に同梱、
58
+ html2pdf bundle が名指しする `html2pdf.bundle.min.js.LICENSE.txt` も sidecar 配置
59
+ - `@highlightjs/cdn-assets` / `mermaid` / `html2pdf.js` は **devDependencies**
60
+ (vendor 元、runtime では使わないので global install 時にダウンロードされない)
61
+ - `tests/test-offline-assets.js` で「served HTML/JS に外部 CDN URL がない」
62
+ 「必須 vendor ファイル / license 一式が揃う」「vendor-only パッケージが
63
+ dependencies に逆流していない」を 14 件の assert で常時保証
64
+
65
+ ### Verified
66
+
67
+ - 272 テスト 全 PASS (既存 258 + 新規 14)
68
+ - Playwright dogfood (`docs/dogfood-offline-2026-05-11/`): 非 localhost への
69
+ リクエスト 0 件、code highlight / mermaid / Tailwind / edit autosave /
70
+ theme 切替 / Marp split layout / inline notes すべて回帰なし
71
+ - Codex review 2 round で「No actionable regressions」収束
72
+
8
73
  ## [0.5.17] - 2026-05-10
9
74
 
10
75
  ### Added — Edit-mode Autosave
package/README.md CHANGED
@@ -11,11 +11,13 @@
11
11
  - 📄 Markdownをリアルタイムレンダリング
12
12
  - 🎬 **Marp完全対応**(公式テーマ・ディレクティブ・数式)
13
13
  - 🎤 **Presenter View**(スピーカーノート別ウィンドウ・自動保存・タイマー) — `P` キーで起動
14
+ - 🪟 **PowerPoint 風 Split Layout** — 上にスライド / 下にスピーカーノート、間にドラッグハンドルでサイズ変更(0.5.16+)
15
+ - 📝 **Inline Speaker Notes Editor** — メイン画面で直接ノート編集 → 800ms デバウンスで自動保存(0.5.16+)
14
16
  - 🔄 ファイル更新時に自動リロード(WebSocket)
15
17
  - 🎨 シンタックスハイライト(highlight.js)
16
18
  - 📊 Mermaid図のレンダリング
17
19
  - 🌙 ダーク/ライトテーマ切り替え
18
- - ✏️ インラインエディタ(Cmd+E
20
+ - ✏️ **インラインエディタ + 自動保存** — `Cmd+E` で編集モード、入力 → 1500ms で自動保存(0.5.17+)
19
21
  - ✅ タスクリスト(チェックボックス)対応
20
22
  - 📥 PDF出力(Cmd+P / CLI convert)
21
23
  - 🎛️ PDF用CSS・PDF options指定(CLI / Web UI)
@@ -216,6 +218,23 @@ paginate: true
216
218
  - **数式**: KaTeX対応(インライン `$...$`、ブロック `$$...$$`)
217
219
  - **スピーカーノート**: HTML コメント (`<!-- ... -->`) で記述
218
220
 
221
+ ## Inline Speaker Notes (PowerPoint-style Split Layout)
222
+
223
+ Marp ファイルを開くとメイン画面が **上下 2 ペイン** に分かれます。上がスライド、下がスピーカーノートエディタ、間に **ドラッグ可能な仕切り**。Presenter View を別ウィンドウで開かなくても、その場でノート編集できます。
224
+
225
+ ### 使い方
226
+
227
+ - **仕切りをドラッグ**: スライド / ノートの比率を変更
228
+ - **仕切りをダブルクリック**: 240px (デフォルト) にリセット
229
+ - **完全に閉じる**: 仕切りを画面下まで → ノート 0px (リロードしても復元)
230
+ - **ノートをクリックして入力**: 800ms デバウンスで自動保存。マークダウンソースの `<!-- ... -->` コメントが書き換わります
231
+ - **保存ステータス**: 編集中… / 保存中… / 保存済み / 失敗 (パネル右上に表示)
232
+ - **スライド切替で連動**: ナビ ←/→ または `Space` で active スライドが切り替わるとノートも対応スライドのものに
233
+
234
+ ### Presenter View との関係
235
+
236
+ 別ウィンドウの Presenter View (`P` キー) と **同じノートを共有**します。両方同時に開いて編集することも可能ですが、ETag 楽観ロックで **STALE 検出** されます (片方が STALE になったら後勝ちで上書きせず、ローカルストレージに退避)。
237
+
219
238
  ## Presenter View
220
239
 
221
240
  Marp ファイルを開いた状態で **`P` キー** を押すと、別ウィンドウで登壇者ビューが起動します。
@@ -259,13 +278,25 @@ Marp ファイルを開いた状態で **`P` キー** を押すと、別ウィ
259
278
  | `Space / PageDown` | 次のスライド |
260
279
  | `Home / End` | 最初 / 最後のスライド |
261
280
 
281
+ ## Editor (Edit モード)
282
+
283
+ `Cmd+E` で **編集モード** に入ると textarea が開きます。**入力 → 1500ms で自動保存**するので、`Cmd+S` を押し忘れて変更が消える心配はありません。
284
+
285
+ ### 自動保存の挙動
286
+
287
+ - **入力 → 1500ms debounce → POST `/api/file`** → ステータスバー: `Modified → Saving... → Saved! → Ready`
288
+ - **`Cmd+S`** は引き続き使えます。押すと **debounce を待たず即時 flush**
289
+ - **View 切替 / タブ切替 / 別ファイル open** 時に **flush + await** — 保存完了するまで遷移しません
290
+ - **保存失敗時** (ネットワーク断など) はエディタを閉じず Edit モードに留まります。`Error: ...` が表示されたらリトライしてください
291
+ - **Discard-on-close** (✕ で未保存タブを閉じる): 確認ダイアログが出ます。サーバーが既にリクエストを受信した直後の race window では、その時点までの内容がファイルに残る可能性があります(ダイアログに注記あり)
292
+
262
293
  ## Keyboard Shortcuts
263
294
 
264
295
  | ショートカット | 機能 |
265
296
  |---------------|------|
266
297
  | Cmd/Ctrl + B | サイドバー表示切替 |
267
- | Cmd/Ctrl + E | 編集モード切替 |
268
- | Cmd/Ctrl + S | 保存(編集モード時) |
298
+ | Cmd/Ctrl + E | 編集モード切替 (open: textarea / close: flush + 再 fetch + render) |
299
+ | Cmd/Ctrl + S | **保存を即時 flush** (編集モード時。autosave debounce 中なら待たずに POST) |
269
300
  | Cmd/Ctrl + P | PDF出力 |
270
301
  | Cmd/Ctrl + W | タブを閉じる |
271
302
  | ← / → | スライド移動(Marp時) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdv-live",
3
- "version": "0.5.17",
3
+ "version": "0.5.19",
4
4
  "description": "Markdown Viewer - File tree + Live preview + Marp support + Hot reload",
5
5
  "main": "src/server.js",
6
6
  "bin": {
@@ -59,5 +59,10 @@
59
59
  "optionalDependencies": {
60
60
  "@marp-team/marp-cli": "^4.0.3",
61
61
  "md-to-pdf": "^5.2.5"
62
+ },
63
+ "devDependencies": {
64
+ "@highlightjs/cdn-assets": "^11.11.1",
65
+ "html2pdf.js": "^0.14.0",
66
+ "mermaid": "^11.15.0"
62
67
  }
63
68
  }
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ // Populates src/static/vendor/ with offline copies of the libraries that
3
+ // index.html used to load from CDN. Run manually when bumping versions.
4
+ //
5
+ // node scripts/sync-vendor.js
6
+ //
7
+ // Source map files are skipped to keep the npm tarball small.
8
+
9
+ import { cp, mkdir, rm, writeFile } from 'node:fs/promises';
10
+ import { existsSync } from 'node:fs';
11
+ import { dirname, resolve } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import https from 'node:https';
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const repoRoot = resolve(__dirname, '..');
17
+ const vendorDir = resolve(repoRoot, 'src/static/vendor');
18
+
19
+ const TAILWIND_VERSION = '3.4.17';
20
+ const TAILWIND_URL = `https://cdn.tailwindcss.com/${TAILWIND_VERSION}`;
21
+ const TAILWIND_LICENSE_URL = `https://raw.githubusercontent.com/tailwindlabs/tailwindcss/v${TAILWIND_VERSION}/LICENSE`;
22
+
23
+ async function copyFromNodeModules(relSource, relDest) {
24
+ const src = resolve(repoRoot, 'node_modules', relSource);
25
+ const dest = resolve(vendorDir, relDest);
26
+ if (!existsSync(src)) {
27
+ throw new Error(`Missing source file: ${src} (did you run npm install?)`);
28
+ }
29
+ await mkdir(dirname(dest), { recursive: true });
30
+ await cp(src, dest);
31
+ console.log(`copied ${relSource} -> vendor/${relDest}`);
32
+ }
33
+
34
+ function downloadToString(url) {
35
+ return new Promise((resolveDownload, rejectDownload) => {
36
+ https.get(url, { headers: { 'User-Agent': 'mdv-live sync-vendor' } }, (res) => {
37
+ if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
38
+ res.resume();
39
+ resolveDownload(downloadToString(res.headers.location));
40
+ return;
41
+ }
42
+ if (res.statusCode !== 200) {
43
+ rejectDownload(new Error(`GET ${url} -> ${res.statusCode}`));
44
+ res.resume();
45
+ return;
46
+ }
47
+ const chunks = [];
48
+ res.on('data', (c) => chunks.push(c));
49
+ res.on('end', () => resolveDownload(Buffer.concat(chunks)));
50
+ res.on('error', rejectDownload);
51
+ }).on('error', rejectDownload);
52
+ });
53
+ }
54
+
55
+ async function downloadTailwind() {
56
+ const dest = resolve(vendorDir, 'tailwind.min.js');
57
+ const body = await downloadToString(TAILWIND_URL);
58
+ const header = `/*! Tailwind CSS Play CDN ${TAILWIND_VERSION} - downloaded from ${TAILWIND_URL} */\n`;
59
+ await mkdir(dirname(dest), { recursive: true });
60
+ await writeFile(dest, header + body.toString('utf8'));
61
+ console.log(`downloaded tailwind ${TAILWIND_VERSION} -> vendor/tailwind.min.js (${body.length} bytes)`);
62
+ }
63
+
64
+ async function downloadTailwindLicense() {
65
+ const dest = resolve(vendorDir, 'licenses/tailwindcss.LICENSE');
66
+ const body = await downloadToString(TAILWIND_LICENSE_URL);
67
+ await mkdir(dirname(dest), { recursive: true });
68
+ await writeFile(dest, body);
69
+ console.log(`downloaded tailwind LICENSE -> vendor/licenses/tailwindcss.LICENSE (${body.length} bytes)`);
70
+ }
71
+
72
+ async function main() {
73
+ if (existsSync(vendorDir)) {
74
+ await rm(vendorDir, { recursive: true, force: true });
75
+ }
76
+ await mkdir(vendorDir, { recursive: true });
77
+
78
+ await copyFromNodeModules('@highlightjs/cdn-assets/highlight.min.js', 'highlight.min.js');
79
+ await copyFromNodeModules('@highlightjs/cdn-assets/styles/github.min.css', 'highlight/github.min.css');
80
+ await copyFromNodeModules('@highlightjs/cdn-assets/styles/github-dark.min.css', 'highlight/github-dark.min.css');
81
+ await copyFromNodeModules('mermaid/dist/mermaid.min.js', 'mermaid.min.js');
82
+ await copyFromNodeModules('html2pdf.js/dist/html2pdf.bundle.min.js', 'html2pdf.bundle.min.js');
83
+
84
+ // Third-party license notices. html2pdf.bundle.min.js has an inline pointer
85
+ // ("For license information please see html2pdf.bundle.min.js.LICENSE.txt")
86
+ // that would otherwise dangle once the bundle ships in src/static/vendor/.
87
+ await copyFromNodeModules(
88
+ 'html2pdf.js/dist/html2pdf.bundle.min.js.LICENSE.txt',
89
+ 'html2pdf.bundle.min.js.LICENSE.txt',
90
+ );
91
+ await copyFromNodeModules('html2pdf.js/LICENSE', 'licenses/html2pdf.js.LICENSE');
92
+ await copyFromNodeModules('mermaid/LICENSE', 'licenses/mermaid.LICENSE');
93
+ await copyFromNodeModules('@highlightjs/cdn-assets/LICENSE', 'licenses/highlight.js.LICENSE');
94
+
95
+ await downloadTailwind();
96
+ await downloadTailwindLicense();
97
+
98
+ const readme = `# vendor/
99
+
100
+ This directory holds offline copies of third-party browser libraries that
101
+ index.html used to load from CDN. Regenerate it with:
102
+
103
+ node scripts/sync-vendor.js
104
+
105
+ Sources and licenses (full text in vendor/licenses/):
106
+ - highlight.min.js / highlight/*.css — @highlightjs/cdn-assets (BSD-3-Clause)
107
+ - mermaid.min.js — mermaid (MIT)
108
+ - html2pdf.bundle.min.js — html2pdf.js (MIT); see also
109
+ html2pdf.bundle.min.js.LICENSE.txt for embedded notices
110
+ - tailwind.min.js — Tailwind CSS Play CDN ${TAILWIND_VERSION} (MIT)
111
+ `;
112
+ await writeFile(resolve(vendorDir, 'README.md'), readme);
113
+ console.log('wrote vendor/README.md');
114
+ }
115
+
116
+ main().catch((err) => {
117
+ console.error(err);
118
+ process.exit(1);
119
+ });
@@ -54,7 +54,7 @@ function renderText(content) {
54
54
  */
55
55
  function rewriteMediaPaths(html, relativeDir) {
56
56
  // Match src="..." that are not absolute URLs or data URIs
57
- return html.replace(
57
+ let out = html.replace(
58
58
  /(<(?:img|video|audio|source)\s[^>]*?\bsrc=")([^"]+)(")/gi,
59
59
  (match, before, src, after) => {
60
60
  if (/^(https?:\/\/|data:|\/raw\/|\/)/.test(src)) return match;
@@ -62,6 +62,34 @@ function rewriteMediaPaths(html, relativeDir) {
62
62
  return `${before}/raw/${resolved}${after}`;
63
63
  }
64
64
  );
65
+
66
+ // Marp `![bg](...)` renders as <figure style="background-image:url(...)">,
67
+ // never as an <img>, so the rule above never sees it. marp-core HTML-encodes
68
+ // the surrounding quotes (&quot;). For the quoted form the URL runs to the
69
+ // matching closing quote — not the first `)` — so filenames containing
70
+ // parentheses (e.g. "cover (1).png", which Marp emits as
71
+ // url(&quot;cover%20(1).png&quot;)) survive intact.
72
+ //
73
+ // Known limitation: only the first url() of a `background-image:` declaration
74
+ // is rewritten. Every `![bg]` produces its own <figure> with a single-url
75
+ // declaration, so this never affects `![bg]`; it only leaves later urls of a
76
+ // comma-separated `backgroundImage:` directive (a rare hand-authored case)
77
+ // SPA-relative. Bounding the declaration is unreliable because the encoded
78
+ // quote `&quot;` itself contains the `;` that would delimit it.
79
+ out = out.replace(
80
+ /background-image:\s*url\(\s*(?:(&quot;|"|')([\s\S]*?)\1|([^)\s'"]+))\s*\)/gi,
81
+ (match, quote, quotedSrc, bareSrc) => {
82
+ const src = quote ? quotedSrc : bareSrc;
83
+ // Empty quoted URL (url(&quot;&quot;)) — leave it alone, as the old
84
+ // pattern did; rewriting it to /raw/ would invent a bogus request.
85
+ if (!src || /^(https?:\/\/|data:|\/raw\/|\/)/.test(src)) return match;
86
+ const resolved = relativeDir ? `${relativeDir}/${src}` : src;
87
+ const q = quote || '';
88
+ return `background-image:url(${q}/raw/${resolved}${q})`;
89
+ }
90
+ );
91
+
92
+ return out;
65
93
  }
66
94
 
67
95
  /**
package/src/static/app.js CHANGED
@@ -25,8 +25,8 @@
25
25
  const SLIDE_ROW_MIN_PX = 80;
26
26
 
27
27
  const HLJS_THEMES = {
28
- light: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css',
29
- dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css'
28
+ light: '/static/vendor/highlight/github.min.css',
29
+ dark: '/static/vendor/highlight/github-dark.min.css'
30
30
  };
31
31
 
32
32
  const MERMAID_THEMES = {
@@ -12,7 +12,7 @@
12
12
  <link rel="apple-touch-icon" sizes="128x128" href="/static/images/icon-128.png">
13
13
 
14
14
  <!-- Stylesheets -->
15
- <link id="hljs-theme" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
15
+ <link id="hljs-theme" rel="stylesheet" href="/static/vendor/highlight/github-dark.min.css">
16
16
  <link rel="stylesheet" href="/static/styles.css">
17
17
 
18
18
  <!-- Theme initialization (FOUC prevention) -->
@@ -24,13 +24,13 @@
24
24
  })();
25
25
  </script>
26
26
 
27
- <!-- External libraries -->
28
- <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
29
- <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
30
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
27
+ <!-- External libraries (offline, served from src/static/vendor/) -->
28
+ <script src="/static/vendor/highlight.min.js"></script>
29
+ <script src="/static/vendor/mermaid.min.js"></script>
30
+ <script src="/static/vendor/html2pdf.bundle.min.js"></script>
31
31
 
32
32
  <!-- Tailwind CSS (for Marp slides) -->
33
- <script src="https://cdn.tailwindcss.com"></script>
33
+ <script src="/static/vendor/tailwind.min.js"></script>
34
34
  <script>
35
35
  tailwind.config = {
36
36
  corePlugins: { preflight: false, container: false },
@@ -0,0 +1,13 @@
1
+ # vendor/
2
+
3
+ This directory holds offline copies of third-party browser libraries that
4
+ index.html used to load from CDN. Regenerate it with:
5
+
6
+ node scripts/sync-vendor.js
7
+
8
+ Sources and licenses (full text in vendor/licenses/):
9
+ - highlight.min.js / highlight/*.css — @highlightjs/cdn-assets (BSD-3-Clause)
10
+ - mermaid.min.js — mermaid (MIT)
11
+ - html2pdf.bundle.min.js — html2pdf.js (MIT); see also
12
+ html2pdf.bundle.min.js.LICENSE.txt for embedded notices
13
+ - tailwind.min.js — Tailwind CSS Play CDN 3.4.17 (MIT)
@@ -0,0 +1,10 @@
1
+ pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
2
+ Theme: GitHub Dark
3
+ Description: Dark theme as seen on github.com
4
+ Author: github.com
5
+ Maintainer: @Hirse
6
+ Updated: 2021-05-15
7
+
8
+ Outdated base version: https://github.com/primer/github-syntax-dark
9
+ Current colors taken from GitHub's CSS
10
+ */.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
@@ -0,0 +1,10 @@
1
+ pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
2
+ Theme: GitHub
3
+ Description: Light theme as seen on github.com
4
+ Author: github.com
5
+ Maintainer: @Hirse
6
+ Updated: 2021-05-15
7
+
8
+ Outdated base version: https://github.com/primer/github-syntax-light
9
+ Current colors taken from GitHub's CSS
10
+ */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}