Skip to content
Merged
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
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,73 @@ A tool to help you explore the kinds of data available when you paste something

[https://evercoder.github.io/clipboard-inspector/](https://evercoder.github.io/clipboard-inspector/)

## Features

- Inspect clipboard contents from `paste`, drag-and-drop, and the Async Clipboard API
- Preview text, images, and other binary payloads
- **Download as Markdown** — a single `.md` file that is easy to paste into an AI assistant for diagnosis
- **Download as ZIP** — a structured archive containing text, binary files, and manifests, suitable for bug reports and offline analysis

## Project layout

```
clipboard-inspector/
├── src/ # Source code (edit here)
│ ├── index.jsx # App entry point: render + event bindings
│ ├── ClipboardInspector.jsx # Main React component
│ ├── extract-data.js # Clipboard data extraction (DataTransfer / ClipboardItem)
│ ├── mdn-urls.js # MDN reference URLs used in the UI
│ └── download/
│ ├── utils.js # Shared helpers (MIME, filenames, download trigger)
│ ├── markdown.js # Markdown export
│ └── zip.js # ZIP export (JSZip)
├── index.html # GitHub Pages entry (loads ./index.js)
├── index.js # Build artifact, generated from src/ via esbuild
├── style.css # Styles
├── package.json
└── README.md
```

> `index.js` is a committed build artifact so that GitHub Pages (which serves the repo root)
> can load it directly. Do not edit it by hand — run `npm run build` instead.

## Getting started

The project requires Node and npm to run locally. After cloning the repo, run `npm install` in the project folder to install all dependencies.

A few scripts are available:

- `npm run start` starts a local server on [127.0.0.1:8000](http://127.0.0.1:8000/)
- `npm run build` builds the project
- `npm run deploy` deploys the project by building it and pushing to the `gh-pages` Git branch, where GitHub Pages is set up to run.
- `npm run build` bundles `src/index.jsx` into `index.js`
- `npm run deploy` builds the project and pushes to the `gh-pages` Git branch, where GitHub Pages is set up to run

## Exports

### Markdown export

A single `.md` file with:

- Header (timestamp, source kind, counts)
- One section per clipboard entry (`DataTransfer` / `ClipboardItem`)
- Tables for `.types` / `.items` / `.files`
- Text payloads rendered in fenced code blocks with a language hint inferred from the MIME type
- Binary payloads described by `name`, `type`, and human-readable size

This format is designed to be pasted directly into a chat with an AI assistant.

### ZIP export

A structured archive:

```
clipboard-data-<timestamp>.zip
├── README.txt
├── metadata.json
└── data-<n>/
├── types/ # one file per MIME type
├── items/ # string items + files, with manifest.json
└── files/ # dropped/pasted files, with manifest.json
```

Binary payloads are preserved as-is, which makes the archive useful for sharing
reproducible bug reports.
190 changes: 190 additions & 0 deletions docs/refactor-2026-04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# 2026-04 重构:`src/` 目录化 + Markdown / ZIP 导出

> 本次改造基于 [Evercoder/clipboard-inspector#16](https://github.com/Evercoder/clipboard-inspector/pull/16) 的 ZIP 导出思路,在此之上新增 Markdown 导出并完成工程结构规范化。

## 一、问题复述

原仓库在使用中有三点不便:

1. 遇到有趣的剪贴板结构时,想把"当前页面看到的全部信息"一键丢给 AI 协助分析,但工具只做展示、不做导出。
2. 同样地,没有办法把剪贴板内容(含二进制文件)打包带走做离线分析或 bug 上报。
3. 工程结构不规范:根目录同时存放源码 `index.jsx`、构建产物 `index.js`、静态资源,源码和产物混在一起容易误编辑。

## 二、目标

| # | 诉求 | 验收标准 |
| --- | ------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| 1 | 新增 **Markdown 下载**(优先级最高,直接贴给 AI) | 导出单个 `.md` 文件,结构化呈现 types / items / files,文本用代码块渲染、二进制给描述信息 |
| 2 | 新增 **ZIP 下载** | 借鉴 PR #16,保留 text + binary 原始比特 |
| 3 | **工程规范化** | 源码挪到 `src/`;构建产物独立;README 更新;不破坏 `gh-pages -d .` 部署 |

## 三、方案选择

### 方案对比

| 方案 | 描述 | 优点 | 缺点 | 推荐度 |
| ---- | ---------------------------------------- | ---------------------- | -------------------- | ---------- |
| A ✅ | `src/` + 模块化 + md / zip 独立文件 | 真正模块化;不破坏部署 | 改动面中等 | ⭐⭐⭐⭐⭐ |
| B | 单文件追加(照搬 PR #16 风格) | 最小改动 | 不满足规范化诉求 | ⭐⭐ |
| C | 激进改造(`public/` + `src/` + `dist/`) | 最标准 | 破坏 `gh-pages -d .` | ⭐⭐ |

**选定方案 A**。核心权衡是:`npm run deploy` 依赖 `gh-pages -d .`(整个仓库根作为 Pages 根),所以构建产物 `index.js`、`index.html`、`style.css` 必须留在仓库根;只把"人类编辑的源码"收敛到 `src/`。

### 审查结论

四维度评估(解决有效性 / 副作用 / 可行性 / 代码规范)全部通过,无阻断问题,一轮过。

## 四、最终结构

```
clipboard-inspector/
├── src/ # 源码(唯一需要编辑的地方)
│ ├── index.jsx # 入口:render + paste/dragover/drop 事件
│ ├── ClipboardInspector.jsx # 主 React 组件(action-buttons + 三段渲染)
│ ├── extract-data.js # extractData(): DataTransfer / ClipboardItem → 纯对象
│ ├── mdn-urls.js # MDN 链接常量
│ └── download/
│ ├── utils.js # sanitizeFilename / isTextMimeType / getFileExtension / fetchBlobFromObjectURL / timestampForFilename / triggerBrowserDownload / mimeToMarkdownLang
│ ├── markdown.js # buildMarkdown + downloadAsMarkdown
│ └── zip.js # downloadAsZip(借鉴 PR #16 + data-<n>/ 隔离)
├── index.html # Pages 入口(未改动)
├── index.js # 构建产物,来自 src/(banner 标注)
├── style.css # 追加 .action-buttons / .download-button 样式
├── package.json # scripts 入口指向 src/index.jsx;新增 jszip ^3.10.1
├── README.md # 重写目录结构与导出说明
└── docs/
└── refactor-2026-04.md # 本文档
```

## 五、关键设计

### 5.1 Markdown 导出(全新)

**设计目标**:一个 `.md` 文件就能把剪贴板全部信息交给 AI。

**结构**:

````markdown
# Clipboard Data Export

- **Export date**: 2026-04-22T07:08:55.010Z
- **Source**: `clipboardData`
- **Entries**: 1
- **Total types / items / files**: 4 / 2 / 1

> Generated by [Clipboard Inspector](...).

---

## Entry 0: `DataTransfer`

### `.types` (4)

| # | type |
| --- | ------------ |
| 0 | `text/plain` |
| 1 | `text/html` |
| ... |

#### types[0] — `text/plain`

​`
Hello world
​`

#### types[1] — `text/html`

​```html

<p>Hi</p>
​```

#### types[3] — `image/png`

**Binary file**: name: `screenshot.png`, type: `image/png`, size: 12.1 KB
````

**关键实现点**:

- **MIME → 语言提示**:`mimeToMarkdownLang()` 把 `text/html` 映射到 ` ```html `、`application/json` / `+json` 到 ` ```json `、`text/css` / `text/markdown` 各自对应
- **Fence 动态升级**:若内容里本身含有 ` ``` `,自动用 ` ```` ` 或更长的围栏包裹,避免截断
- **二进制文件**:不内嵌 base64(避免 `.md` 文件爆炸),给 `name / type / human-readable size` 的描述行
- **单测**:14 个断言覆盖头部元数据、各段落、MIME 推断、极端 fence 情况

### 5.2 ZIP 导出(借鉴 PR #16 + 修正)

**沿用 PR #16 的结构**:`README.txt` + `metadata.json` + `types/` + `items/` + `files/` + manifest。

**本次改进**:

- PR #16 原实现:多个 `DataTransfer` entry 时,`types/` / `items/` / `files/` 三个子目录会相互覆盖
- 本次修正:顶层加 `data-<index>/` 子目录隔离,结构更清晰且健壮

```
clipboard-data-2026-04-22_070855.zip
├── README.txt
├── metadata.json
└── data-0/
├── types/
│ ├── text-plain.txt
│ ├── text-html.txt
│ └── screenshot.png
├── items/
│ ├── item-0-string-text-plain.txt
│ └── manifest.json
└── files/
├── report.pdf
└── manifest.json
```

### 5.3 组件解耦

原 `index.jsx` 中 `ClipboardInspector` 直接引用全局 `render()`,重构时改为通过 props 注入:

```jsx
<ClipboardInspector
data={extracted_data}
label={label}
onReset={() => render()}
onPasteFromClipboard={() =>
navigator.clipboard.read().then(d => render(d, 'ClipboardItems'))
}
/>
```

组件自包含,便于单独测试和复用。

### 5.4 附带修复

原代码中的两个 JSX 属性拼写问题:`class="cb-copy"` / `class="cb-entry"` 应为 `className`,迁移时顺手修正,消除 React devtools warning。

## 六、验证

| 项目 | 结果 |
| -------------------------- | ------------------------------------- |
| `npm install` | ✅ 新增 94 包(含 jszip) |
| `npm run build` | ✅ `index.js` 449.8kb |
| `npm run start` | ✅ dev server 127.0.0.1:8000 正常响应 |
| `buildMarkdown` 单元测试 | ✅ 14/14 通过 |
| Lint | ✅ 无错误 |
| `gh-pages -d .` 部署兼容性 | ✅ 产物仍在仓库根 |

## 七、对调用者的影响

- **最终用户**:面板上多出「Download as Markdown」(蓝色)和「Download as ZIP」(绿色)两个按钮,均有 `loading` / `success` 状态反馈
- **源码编辑者**:**只编辑 `src/` 下的文件**;根目录 `index.js` 是构建产物
- **部署者**:`npm run deploy` 命令不变

## 八、遗留项

| 项 | 说明 | 处置 |
| --------------------------- | ------------------------------------------------------------ | ----------------------------------------------- |
| `npm audit` 5 个漏洞 | 来自既有 `gh-pages → email-addresses` 依赖链,与本次改动无关 | 单独跟进 |
| 未建立 test 脚本 | 项目当前没有测试基础设施;本次单测为临时脚本 | 后续可加 `vitest` 并把 `buildMarkdown` 测试固化 |
| bundle 体积 260KB → 449.8KB | jszip 引入 | 可接受 |

## 九、后续可选增强

- Markdown 导出支持内嵌小图(<50KB base64 `data:` URL),让 AI 直接"看到"图片
- 增加「Copy Markdown to clipboard」按钮,不走文件下载
- 把临时单测脚本迁为 `vitest`,加入 CI
Loading