Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
858 changes: 858 additions & 0 deletions docs/superpowers/plans/2026-07-07-mdp-pr-comments.md

Large diffs are not rendered by default.

1,185 changes: 1,185 additions & 0 deletions docs/superpowers/plans/2026-07-16-mdp-post-comments.md

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions docs/superpowers/plans/2026-08-04-mdp-gdocs-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# mdp Google Docs 風レイアウト Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** コメントを右マージンカラムへ、Outline を左へ、ファイルを上部タブへ移すレイアウト刷新。

**Architecture:** `buildPage` の構造を「header → タブバー → [toc | 本文 | gutter]」に変更。gutter 内のカード配置は共有クライアント JS(GUTTER_JS)が `window.mdpGutter = { add, remove, layout }` として提供し、COMMENTS_JS(既存スレッド)と POST_JS(投稿フォーム)がそれを使う。サーバー・API・マーカー形式は変更なし。

**Tech Stack:** 既存どおり(Bun + TS、クライアント JS は文字列定数)。

Spec: `docs/superpowers/specs/2026-08-04-mdp-gdocs-layout-design.md`

注: クライアント JS はユニットテスト対象外(既存方針どおり)のため、本プランは構造・テスト変更を規定し、JS 本文は実装時に書く。

## Global Constraints

- 依存追加なし。`bun test` + `tsc --noEmit` green を維持
- 挙動の詳細(配置・再配置トリガ・狭い画面)は spec に従う

---

### Task 1: buildPage 構造と CSS(タブバー / toc 左 / gutter)

**Files:**
- Modify: `src/template.ts`, `mdp.ts`
- Test: `src/template.test.ts`

**Steps:**
- [ ] template.test.ts を更新: files→`mdp-tabs`(タブバー、layout より前)、toc は article より前、gutter は comments/postDoc 指定時のみ `id="mdp-gutter"`。実行して FAIL 確認
- [ ] template.ts: `.mdp-files*` CSS を `.mdp-tabs` に置換、`.mdp-toc` を border-right の左カラムに、`.mdp-gutter`/`.mdp-card`/`.mdp-anchor-hover`/`.mdp-gutter-divider` CSS 追加、本文 max-width 900px、media query を 1280px(toc)/1000px(gutter+ボタン)に変更。buildPage の HTML を「header → tabs → layout(toc, article, gutter)」に変更
- [ ] mdp.ts: `filesNav` を `<a>` タブ列に変更し、`docs.length > 1` のときだけ渡す
- [ ] `bun test src/template.test.ts` PASS → commit "feat(mdp): tabs-top / outline-left / comments-gutter layout"

### Task 2: GUTTER_JS と COMMENTS_JS の gutter 対応

**Files:**
- Modify: `src/template.ts`

**Steps:**
- [ ] GUTTER_JS 追加(comments || postDoc のとき COMMENTS_JS/POST_JS より前に挿入): カード管理・アンカー整列(重なりは押し下げ)・loose カードの「Other comments」区切り・ホバーで `.mdp-anchor-hover`・クリックでアンカーへスクロール・resize/load/テーマ切替で再レイアウト
- [ ] COMMENTS_JS: インライン挿入(insertAfter・rest セクション)を廃止し `mdpGutter.add(build(t), anchorFor(t))` に。resolved 開閉時に `mdpGutter.layout()`
- [ ] `bun test` PASS → commit "feat(mdp): place review threads in the margin gutter"

### Task 3: POST_JS の gutter 対応

**Files:**
- Modify: `src/template.ts`

**Steps:**
- [ ] フォームを `mdpGutter.add(form, block)` で右欄に出す。Cancel/Esc/空で外側クリック → `mdpGutter.remove`。textarea input で layout()。成功時はフォーム要素をカード内容に書き換えて layout()。`blockOf` は `.mdp-gutter` 内を除外
- [ ] `bun test` + `tsc --noEmit` PASS → commit "feat(mdp): post form lives in the margin gutter"

### Task 4: E2E・README

**Steps:**
- [ ] 実 PR でタブ・左 Outline・右コメント欄・投稿フォームの配置を確認(投稿はしない)。非 PR 入力で gutter/タブが出ないこと
- [ ] README のレイアウト説明を更新(top tabs / left Outline / right margin comments)
- [ ] commit "docs(mdp): describe the gdocs-style layout"
117 changes: 117 additions & 0 deletions docs/superpowers/specs/2026-06-23-mdp-markdown-preview-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# mdp — GitHub Markdown Preview (design)

Date: 2026-06-23

## 目的

GitHub からダウンロードした (あるいはローカルの) Markdown を、GitHub と同じ見た目でブラウザにプレビューする CLI ツール。主用途はパイプ入力:

```sh
curl -sL https://raw.githubusercontent.com/owner/repo/main/README.md | mdp -
```

カスタム CSS で見た目を上書きできる:

```sh
mdp README.md --css 'h1 { color: red }' --css '.markdown-body { max-width: 1000px }'
```

## 配置

既存ツールと同じく `tools/mdp/` に bun CLI として置く。`package.json` の `bin` で `mdp` を公開。

```
tools/mdp/
mdp.ts # エントリ: argパース → 入力 → render → serve → open
src/
input.ts # stdin / file / URL から { markdown, base } を解決
render.ts # GitHub API /markdown に POST して HTML を得る
template.ts # github-markdown-css + 注入CSS でHTMLページ組み立て
server.ts # Bun.serve でページ + 相対アセット配信、openで起動
package.json
tsconfig.json
```

## コンポーネント

### input.ts — 入力解決

`resolveInput(arg?: string): Promise<{ markdown: string; base: Base }>`

分岐ルール:

1. `arg === "-"`、または `arg` が無く stdin が非 TTY → **stdin** を全部読む。base なし
2. `arg` が `http://` / `https://` で始まる → **URL**。`fetch` で取得。
- GitHub の `blob` URL (`github.com/o/r/blob/ref/path`) は raw (`raw.githubusercontent.com/o/r/ref/path`) に正規化してから取得
- base = 取得元の raw ディレクトリ URL (相対画像解決用)
3. それ以外 → **ローカルファイル**。読み込み、base = ファイルの親ディレクトリ (絶対パス)

`Base` は `{ kind: "none" } | { kind: "url"; dir: string } | { kind: "file"; dir: string }`。

### render.ts — GitHub API でレンダリング

`renderMarkdown(markdown: string): Promise<string>` (HTML 断片を返す)

- `POST https://api.github.com/markdown`、body `{ text, mode: "gfm" }`、`Accept: application/vnd.github+json`
- `GITHUB_TOKEN` または `GH_TOKEN` 環境変数があれば `Authorization: Bearer <token>` を付与 (未認証 60 req/h → 認証 5000 req/h)
- 失敗時 (401/403/429/5xx/ネットワーク) は status と短い理由を添えて throw。レート制限超過は分かりやすいメッセージにする

### template.ts — HTML ページ組み立て

`buildPage(htmlFragment: string, customCss: string[]): string`

- `github-markdown-css` の CSS を `<head>` にインライン (依存として bundle、オフラインでも動くように)
- 本文を `<article class="markdown-body">…</article>` でラップ
- `github-markdown-css` の **後ろ** に `--css` の生 CSS 群を順に `<style>` で注入 → ユーザー指定が後勝ちで上書きできる
- light/dark は `prefers-color-scheme` 対応版を使う (github-markdown-css の auto)

### server.ts — 配信 + ブラウザ起動

`serve(page: string, base: Base): Promise<void>`

- `Bun.serve({ port: 0 })` で空きポートに起動
- `GET /` → `page` (HTML) を返す
- それ以外のパス → base に応じて相対アセットを解決
- `file` base → 親ディレクトリ配下のファイルを静的配信 (ディレクトリ外への traversal は拒否)
- `url` base → `<dir>/<path>` の GitHub raw URL へ 302 リダイレクト
- `none` base → 404
- 起動後 `open http://localhost:<port>` (macOS) でブラウザを開く
- フォアグラウンドで待機し、Ctrl-C (SIGINT) で終了

## 引数

```
mdp [input] [--css <raw-css>]...

input:
- stdin から読む (省略時 stdin が非TTYならこれ)
<path> ローカル Markdown ファイル
<url> http(s) の Markdown / GitHub blob URL

--css <css> 本文に注入する生CSS。複数回指定可 (後ろほど優先)
-h, --help 使い方表示
```

## エラーハンドリング

- 入力が空 (stdin も引数も無し) → usage を表示して exit 1
- ファイルが存在しない / 読めない → パス付きエラーで exit 1
- URL fetch 失敗 (非 2xx) → status 付きエラーで exit 1
- GitHub API エラー → status と理由 (レート制限など) を表示して exit 1
- それ以外の例外は最上位で catch し message を表示して exit 1

## テスト

`bun test` で純粋ロジックを中心に:

- `input.ts`: blob→raw 正規化、URL/ファイル/stdin の分岐判定、base の算出
- `template.ts`: `--css` が github-markdown-css より後ろに入る (後勝ち)、複数 `--css` の順序、本文ラップ
- `render.ts`: token 有無でヘッダが変わる / エラー時に例外 (fetch をモック)
- `server.ts`: パス解決ロジック (traversal 拒否、url base の raw リダイレクト URL 生成) を関数として切り出して単体テスト

## スコープ外 (YAGNI)

- ファイル監視によるライブリロード (主用途がパイプ一発のため。サーバー構成は将来追加しやすく保つ)
- ローカル Markdown ライブラリへのフォールバック (今回は GitHub API 一本)
- CSS のファイルパス / JSON オブジェクト指定 (生 CSS 文字列のみ)
- macOS 以外の `open` 相当コマンド対応 (必要になれば後で)
89 changes: 89 additions & 0 deletions docs/superpowers/specs/2026-07-07-mdp-pr-comments-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# mdp: PR の既存インラインレビューコメント表示

2026-07-07

## 目的

`mdp <PR>` で PR の markdown ファイルをプレビューするとき、その PR に
すでについているインラインレビューコメントを本文中の該当位置に GitHub 風に
表示する。レビュー内容を GitHub を開かずに文書と一緒に読めるようにする。

## スコープ

- 対象: PR のインラインレビューコメント(reviewThreads)のうち、
プレビュー対象の markdown ファイルに紐づくもの
- 対象外:
- PR 会話タブのコメント(issue コメント)・レビュー本文
- コメントの新規投稿・返信・resolve 操作(表示のみ)
- リアルタイム更新(起動時に 1 回取得のみ)
- markdown 以外のファイルへのコメント

## データ取得(新規 `src/comments.ts`)

- `loadPrDocs` と同様に `RunGh` 注入スタイルで実装する
- `gh api graphql` で PR の `reviewThreads`(first 100)を取得する。
取得フィールド: `path`, `line`, `originalLine`, `isResolved`,
`isOutdated`, `diffSide`, comments(first 100)の
`author.login`, `body`, `createdAt`, `url`
- 100 件を超えるスレッドは切り捨てる(ページングしない)。
切り捨てが起きた場合は stderr に warning を出す
- プレビュー対象の markdown ファイル(`PrDoc.name`)に `path` が一致する
スレッドのみ残す
- アンカーテキストの決定(純関数として切り出す):
1. `line` が非 null → head の raw markdown(`PrDoc.markdown`)の
その行のテキスト
2. `line` が null(outdated)→ `diffHunk` の最終行から `+`/`-`/` `
プレフィックスを除いたテキスト
3. どちらも空行・空白のみになった場合はアンカーなし(末尾セクション行き)
- コメント本文は markdown なので、既存の `renderMarkdown`(GitHub
`/markdown` API)で各コメントを並列レンダリングする
- `gh` の graphql 呼び出しやレンダリングが失敗した場合は stderr に
warning を出し、コメントなしで通常のプレビューを続行する
(プレビュー本体は死なせない)

## ページへの埋め込み(`template.ts` 拡張)

- `PageOptions` に `comments?: string`(スレッドデータの JSON)を追加
- スレッドデータを `<script type="application/json" id="mdp-comments">`
としてページに埋め込む。1 スレッドあたり:
`anchorText`, `isResolved`, `isOutdated`, `url`,
comments 配列(`author`, `createdAt`, `bodyHtml`)
- クライアント JS(`COMMENTS_JS`):
- `.markdown-body` 配下のブロック要素(p, li, tr, pre, h1–h6 など)を
文書順に走査し、空白正規化(連続空白を 1 つに・トリム)したテキストに
アンカーテキスト(同じく正規化)を含む**最初の**要素を探す
- 見つかったらその直後にスレッドボックスを挿入する。同一要素に複数
スレッドがマッチした場合は `line` 順に並べて挿入する
- マッチしなかったスレッド(アンカーなし含む)は本文末尾に
「Comments」セクションとしてまとめて表示する(取りこぼしゼロ)
- 表示:
- スレッドボックスは GitHub 風(枠線・角丸・author と相対日時の
ヘッダ・本文)。ヘッダの日時は GitHub の該当コメントへのリンク
- resolved スレッドはグレーの 1 行ヘッダ(`Resolved` バッジ +
最初のコメントの author)に折りたたみ、クリックで展開/再折りたたみ
- outdated スレッドには `Outdated` バッジを付ける
- light / dark 両テーマに対応(既存の `[data-theme="dark"]` パターン)

## データフロー

1. `mdp.ts`: PR 入力のとき `loadPrDocs` に続けて `loadPrComments` を呼ぶ
2. 各 `PrDoc` のページ生成時に、そのファイルのスレッド JSON を
`buildPage` に渡す
3. ブラウザで `COMMENTS_JS` がテキストマッチして DOM に挿入する

## テスト

- `src/comments.test.ts`:
- graphql レスポンス処理(`RunGh` モック、既存 `pr.test.ts` と同様)
- アンカーテキスト抽出: line あり / outdated(diffHunk フォールバック)/
空白のみでアンカーなし
- テキスト正規化・マッチ判定の純関数
- クライアント側のマッチロジックは、TS 側の純関数と同じ正規化仕様を
JS 文字列内に複製する(既存 `CONTROLS_JS` と同じ方式)。仕様の一致は
純関数側のテストで担保する

## 既知の制限

- 同一テキストが複数箇所にある場合、最初の出現位置に挿入される
(位置がずれうる)。ずれてもコメント自体は必ずどこかに表示される
- reviewThreads / comments とも first 100 まで
Loading