* Replace /api/v1/resources with /api/v1/attachments for image uploads
* Upload attachments as JSON with base64-encoded content field
* After memo creation, link each attachment via PATCH /api/v1/attachments/{id}
* Rewrite markdown image URLs to use /file/attachments/{id} pattern
* Fix XSS: sanitize marked.parse output with a DOM-based allowlist sanitizer
* Fix SSRF: validate img.src scheme (http/https only) before fetching
* Fix stack overflow: use chunked base64 encoding for large images
* Update CLAUDE.md to document new attachment flow
79 lines
3.0 KiB
Markdown
79 lines
3.0 KiB
Markdown
# CLAUDE.md
|
|
|
|
## Project Overview
|
|
|
|
**Memos Clipper** is a Chrome Extension (Manifest V3) that clips web pages or text selections and saves them to a [Memos](https://usememos.com) instance in Markdown format.
|
|
|
|
## Architecture
|
|
|
|
Three-part Chrome extension:
|
|
|
|
- **`src/content.js`** — Content script injected into pages; extracts HTML and converts it to Markdown
|
|
- **`src/popup.html` / `src/popup.js`** — Main popup UI: editor, preview, image gallery, send button
|
|
- **`src/settings.html` / `src/settings.js`** — Options page: Memos URL, API token, defaults
|
|
- **`src/background.js`** — Service worker (minimal; onInstalled listener only)
|
|
|
|
## Tech Stack
|
|
|
|
- **Runtime**: Chrome MV3 (Manifest V3)
|
|
- **Language**: Vanilla JavaScript (ES6+), no frontend framework
|
|
- **Styling**: Tailwind CSS v4 + PostCSS + Autoprefixer; CSS variables for theming; dark mode via `prefers-color-scheme`
|
|
- **Markdown**: Custom HTML→Markdown converter in `content.js`; `marked.min.js` for preview rendering
|
|
- **Build**: Vite v8 with `vite-plugin-static-copy`
|
|
|
|
## Build & Development
|
|
|
|
```bash
|
|
npm install # Install dependencies
|
|
npm run dev # Dev server with hot reload
|
|
npm run build # Production build → dist/
|
|
npm run preview # Preview built output
|
|
```
|
|
|
|
Load the extension in Chrome: **Extensions → Load unpacked → select `dist/`**
|
|
|
|
## Key Implementation Details
|
|
|
|
### API Integration
|
|
- Memos API v1: `/api/v1/memos`, `/api/v1/attachments`
|
|
- Requires Memos v0.22+
|
|
- Bearer token auth via `chrome.storage.sync`
|
|
- Attachment flow: upload via `POST /api/v1/attachments` (JSON + base64 `content`), create memo, then link each attachment to the memo via `PATCH /api/v1/attachments/{id}` with `{ memo: "memos/{id}" }`
|
|
|
|
### Content Extraction
|
|
- Removes boilerplate: nav, ads, sidebars, cookie banners (45+ selectors)
|
|
- Supports full-page and selection-only modes
|
|
- Converts: headings, lists, tables, code blocks, links, images, blockquotes
|
|
|
|
### Image Handling
|
|
- Filters images smaller than 32px (icons/tracking pixels)
|
|
- Deduplicates images
|
|
- Supports data URIs
|
|
- Uploads images as attachments (`POST /api/v1/attachments`) with base64-encoded content
|
|
- After memo creation, links each attachment to the memo via `PATCH /api/v1/attachments/{id}`
|
|
- Attachment file URL pattern: `{memosUrl}/file/attachments/{id}`
|
|
|
|
### Storage
|
|
- `chrome.storage.sync` for cross-device settings (URL, token, defaults)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
src/
|
|
├── manifest.json # MV3 config (permissions, entry points)
|
|
├── popup.html/.js/.css # Main extension popup
|
|
├── settings.html/.js/.css # Options page
|
|
├── content.js # Page content extractor
|
|
├── background.js # Service worker
|
|
├── marked.min.js # Bundled Markdown renderer
|
|
└── icons/ # 16, 32, 48, 128px PNG icons
|
|
dist/ # Build output (gitignored)
|
|
vite.config.js
|
|
package.json
|
|
```
|
|
|
|
## Permissions
|
|
|
|
- `activeTab`, `scripting`, `storage`
|
|
- Host permissions: `<all_urls>` (needed for cross-origin image fetching and API calls)
|