mirror of
https://github.com/zadam/trilium.git
synced 2025-12-06 07:24:25 +01:00
docs: add comprehensive development workflow documentation
Copilot Integration: - Streamlined instructions (70% shorter than original) - Task templates for common operations - Three-tier usage strategy (free/strategic/manual) - Optimized for GitHub Copilot Basic tier limits Development Resources: - Common task workflows with time estimates - Feature parity checklist with priorities - Debugging and troubleshooting guides - Testing scenarios and checklists - Code quality standards Workflow Optimization: - Efficient Copilot task budgeting - Real-world implementation examples - Performance and success metrics - Project completion roadmap Reduces repetitive context in prompts. Maximizes limited Copilot task budget.
This commit is contained in:
parent
57c155ea3f
commit
1f444ebc69
176
apps/web-clipper-manifestv3/.github/copilot-instructions.md
vendored
Normal file
176
apps/web-clipper-manifestv3/.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# GitHub Copilot Instructions - Trilium Web Clipper MV3
|
||||||
|
|
||||||
|
## Project Identity
|
||||||
|
**Working Directory**: `apps/web-clipper-manifestv3/` (active development)
|
||||||
|
**Reference Directory**: `apps/web-clipper/` (MV2 legacy - reference only)
|
||||||
|
**Goal**: Feature-complete MV3 migration with architectural improvements
|
||||||
|
|
||||||
|
## Quick Context Links
|
||||||
|
- Architecture & Systems: See `docs/ARCHITECTURE.md`
|
||||||
|
- Feature Status: See `docs/FEATURE-PARITY-CHECKLIST.md`
|
||||||
|
- Development Patterns: See `docs/DEVELOPMENT-GUIDE.md`
|
||||||
|
- Migration Patterns: See `docs/MIGRATION-PATTERNS.md`
|
||||||
|
|
||||||
|
## Critical Rules
|
||||||
|
|
||||||
|
### Workspace Boundaries
|
||||||
|
- ✅ Work ONLY in `apps/web-clipper-manifestv3/`
|
||||||
|
- ✅ Reference `apps/web-clipper/` for feature understanding
|
||||||
|
- ❌ DO NOT suggest patterns from other monorepo projects
|
||||||
|
- ❌ DO NOT copy MV2 code directly
|
||||||
|
|
||||||
|
### Code Standards (Non-Negotiable)
|
||||||
|
1. **No Emojis in Code**: Never use emojis in `.ts`, `.js`, `.json` files, string literals, or code comments
|
||||||
|
2. **Use Centralized Logging**: `const logger = Logger.create('ComponentName', 'background')`
|
||||||
|
3. **Use Theme System**: Import `theme.css`, use CSS variables `var(--color-*)`, call `ThemeManager.initialize()`
|
||||||
|
4. **TypeScript Everything**: Full type safety, no `any` types
|
||||||
|
5. **Error Handling**: Always wrap async operations in try-catch with proper logging
|
||||||
|
|
||||||
|
### Development Mode
|
||||||
|
- **Current Phase**: Active development (use `npm run dev`)
|
||||||
|
- **Build**: Watch mode with live reload
|
||||||
|
- **Focus**: Debugging, rapid iteration, feature implementation
|
||||||
|
- ⚠️ Only use `npm run build` for final validation
|
||||||
|
|
||||||
|
## Essential Patterns
|
||||||
|
|
||||||
|
### Message Passing Template
|
||||||
|
```typescript
|
||||||
|
// Background service worker
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const result = await handleMessage(message);
|
||||||
|
sendResponse({ success: true, data: result });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Handler error', error);
|
||||||
|
sendResponse({ success: false, error: error.message });
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return true; // Required for async
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Storage Pattern
|
||||||
|
```typescript
|
||||||
|
// Use chrome.storage, NEVER localStorage in service workers
|
||||||
|
await chrome.storage.local.set({ key: value });
|
||||||
|
const { key } = await chrome.storage.local.get(['key']);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component Structure
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
import { ThemeManager } from '@/shared/theme';
|
||||||
|
|
||||||
|
const logger = Logger.create('ComponentName', 'background');
|
||||||
|
|
||||||
|
async function initialize() {
|
||||||
|
await ThemeManager.initialize();
|
||||||
|
logger.info('Component initialized');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## When Suggesting Code
|
||||||
|
|
||||||
|
### Checklist for Every Response
|
||||||
|
1. [ ] Verify API usage against `reference/chrome_extension_docs/`
|
||||||
|
2. [ ] Include proper error handling with centralized logging
|
||||||
|
3. [ ] Use TypeScript with full type annotations
|
||||||
|
4. [ ] If UI code: integrate theme system
|
||||||
|
5. [ ] Reference legacy code for functionality, not implementation
|
||||||
|
6. [ ] Explain MV2→MV3 changes if applicable
|
||||||
|
|
||||||
|
### Response Format
|
||||||
|
```
|
||||||
|
**Task**: [What we're implementing]
|
||||||
|
**Legacy Pattern** (if migrating): [Brief description]
|
||||||
|
**Modern Approach**: [Show TypeScript implementation]
|
||||||
|
**Files Modified**: [List affected files]
|
||||||
|
**Testing**: [How to verify it works]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common MV3 Patterns
|
||||||
|
|
||||||
|
### Service Worker Persistence
|
||||||
|
```typescript
|
||||||
|
// State must be stored, not kept in memory
|
||||||
|
const getState = async () => {
|
||||||
|
const { state } = await chrome.storage.local.get(['state']);
|
||||||
|
return state || defaultState;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Content Script Communication
|
||||||
|
```typescript
|
||||||
|
// Inject scripts programmatically
|
||||||
|
await chrome.scripting.executeScript({
|
||||||
|
target: { tabId },
|
||||||
|
files: ['content.js']
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manifest V3 APIs
|
||||||
|
- `chrome.action` (not browserAction)
|
||||||
|
- `chrome.storage` (not localStorage)
|
||||||
|
- `chrome.alarms` (not setTimeout in service worker)
|
||||||
|
- `declarativeNetRequest` (not webRequest blocking)
|
||||||
|
|
||||||
|
## Feature Development Workflow
|
||||||
|
|
||||||
|
### Before Starting Work
|
||||||
|
1. Check `docs/FEATURE-PARITY-CHECKLIST.md` for feature status
|
||||||
|
2. Review legacy implementation in `apps/web-clipper/`
|
||||||
|
3. Check if feature needs manifest permissions
|
||||||
|
4. Plan which files will be modified
|
||||||
|
|
||||||
|
### During Development
|
||||||
|
1. Use centralized logging liberally for debugging
|
||||||
|
2. Test frequently with `npm run dev` + Chrome reload
|
||||||
|
3. Check console in both popup and service worker contexts
|
||||||
|
4. Update feature checklist when complete
|
||||||
|
|
||||||
|
### Before Committing
|
||||||
|
1. Run `npm run type-check`
|
||||||
|
2. Test all related functionality
|
||||||
|
3. Verify no console errors
|
||||||
|
4. Update `FEATURE-PARITY-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Current Development Focus
|
||||||
|
|
||||||
|
**Phase**: Screenshot Features (see FEATURE-PARITY-CHECKLIST.md)
|
||||||
|
**Next Priority**: Screenshot cropping implementation
|
||||||
|
**Key Files**:
|
||||||
|
- `src/background/index.ts` (capture handlers)
|
||||||
|
- `src/content/` (selection UI)
|
||||||
|
- `src/shared/` (utilities)
|
||||||
|
|
||||||
|
## What NOT to Include in Suggestions
|
||||||
|
|
||||||
|
❌ Long explanations of basic TypeScript concepts
|
||||||
|
❌ Generic Chrome extension tutorials
|
||||||
|
❌ Detailed history of MV2→MV3 migration
|
||||||
|
❌ Code from other monorepo projects
|
||||||
|
❌ Placeholder/TODO comments without implementation
|
||||||
|
❌ Overly defensive coding for edge cases not in legacy version
|
||||||
|
|
||||||
|
## What TO Focus On
|
||||||
|
|
||||||
|
✅ Concrete, working code that solves the task
|
||||||
|
✅ Feature parity with legacy extension
|
||||||
|
✅ Modern TypeScript patterns
|
||||||
|
✅ Proper error handling and logging
|
||||||
|
✅ Clear migration explanations when relevant
|
||||||
|
✅ Specific file paths and line references
|
||||||
|
✅ Testing instructions
|
||||||
|
|
||||||
|
## Documentation References
|
||||||
|
|
||||||
|
- **Chrome APIs**: `reference/chrome_extension_docs/`
|
||||||
|
- **Readability**: `reference/Mozilla_Readability_docs/`
|
||||||
|
- **DOMPurify**: `reference/cure53_DOMPurify_docs/`
|
||||||
|
- **Cheerio**: `reference/cheerio_docs/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: This is an active development project in an existing codebase. Be specific, be practical, and focus on getting features working efficiently. When in doubt, check the architecture docs first.
|
||||||
377
apps/web-clipper-manifestv3/WORKING-STATUS.md
Normal file
377
apps/web-clipper-manifestv3/WORKING-STATUS.md
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
# <20> Trilium Web Clipper MV3 - Working Status
|
||||||
|
|
||||||
|
**Extension Status:** ✅ CORE FUNCTIONALITY WORKING
|
||||||
|
**Last Updated:** October 17, 2025
|
||||||
|
**Build System:** esbuild + IIFE
|
||||||
|
**Target:** Manifest V3 (Chrome/Edge/Brave)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make sure you are in the correct working directory
|
||||||
|
cd apps/web-clipper-manifestv3
|
||||||
|
|
||||||
|
# Build
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Load in Chrome
|
||||||
|
chrome://extensions/ → Load unpacked → Select dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Implemented & Working
|
||||||
|
|
||||||
|
### Core Functionality
|
||||||
|
- ✅ **Content script injection** (declarative)
|
||||||
|
- ✅ **Save Selection** to Trilium
|
||||||
|
- ✅ **Save Page** to Trilium (with Readability + DOMPurify + Cheerio pipeline)
|
||||||
|
- ✅ **Save Link** (basic - URL + title only)
|
||||||
|
- ✅ **Save Screenshot** (full page capture, metadata stored)
|
||||||
|
- ✅ **Duplicate note detection** with user choice (new/update/cancel)
|
||||||
|
- ✅ **HTML/Markdown/Both** save formats
|
||||||
|
- ✅ **Context menus** (Save Selection, Save Page, Save Link, Save Screenshot, Save Image)
|
||||||
|
- ✅ **Keyboard shortcuts** (Ctrl+Shift+S for save, Ctrl+Shift+A for screenshot)
|
||||||
|
|
||||||
|
### UI Components
|
||||||
|
- ✅ **Popup UI** with theming (light/dark/auto)
|
||||||
|
- ✅ **Settings page** with Trilium connection config
|
||||||
|
- ✅ **Logs page** with filtering
|
||||||
|
- ✅ **Toast notifications** (basic success/error)
|
||||||
|
- ✅ **Connection status** indicator
|
||||||
|
- ✅ **System theme detection**
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
- ✅ **esbuild** bundling (IIFE format)
|
||||||
|
- ✅ **TypeScript** compilation
|
||||||
|
- ✅ **HTML transformation** (script refs fixed)
|
||||||
|
- ✅ **Asset copying** (CSS, icons, manifest)
|
||||||
|
- ✅ **Type checking** (`npm run type-check`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 Missing Features (vs MV2)
|
||||||
|
|
||||||
|
### High Priority
|
||||||
|
|
||||||
|
#### 1. **Screenshot Cropping** 🎯 NEXT UP
|
||||||
|
- **MV2:** `cropImage()` function crops screenshot to selected area
|
||||||
|
- **MV3:** Crop rectangle stored in metadata but NOT applied to image
|
||||||
|
- **Impact:** Users get full-page screenshot instead of selected area
|
||||||
|
- **Solution:** Use OffscreenCanvas API or content script canvas
|
||||||
|
- **Files:** `src/background/index.ts:504-560`, need crop implementation
|
||||||
|
|
||||||
|
#### 2. **Image Processing (Full Page)**
|
||||||
|
- **MV2:** Downloads all external images, converts to base64, embeds in note
|
||||||
|
- **MV3:** Only processes images for **selection saves**, not full page
|
||||||
|
- **Impact:** External images in full-page clips may break/disappear
|
||||||
|
- **Solution:** Apply `postProcessImages()` to all capture types
|
||||||
|
- **Files:** `src/background/index.ts:668-740`
|
||||||
|
|
||||||
|
#### 3. **Screenshot Selection UI Verification**
|
||||||
|
- **MV2:** Overlay with drag-to-select, Escape to cancel, visual feedback
|
||||||
|
- **MV3:** Likely exists in content script but needs testing against MV2
|
||||||
|
- **Impact:** Unknown - need to verify feature parity
|
||||||
|
- **Files:** Check `src/content/` against `apps/web-clipper/content.js:66-193`
|
||||||
|
|
||||||
|
### Medium Priority
|
||||||
|
|
||||||
|
#### 4. **Save Tabs (Bulk Save)**
|
||||||
|
- **MV2:** "Save tabs" context menu saves all open tabs as single note with links
|
||||||
|
- **MV3:** Not implemented
|
||||||
|
- **Impact:** Users can't bulk-save research sessions
|
||||||
|
- **Solution:** Add context menu + background handler
|
||||||
|
- **Files:** Reference `apps/web-clipper/background.js:302-326`
|
||||||
|
|
||||||
|
#### 5. **"Already Visited" Popup Detection**
|
||||||
|
- **MV2:** Popup shows if page already clipped, with link to existing note
|
||||||
|
- **MV3:** Background has `checkForExistingNote()` but popup doesn't use it
|
||||||
|
- **Impact:** Users don't know if they've already saved a page
|
||||||
|
- **Solution:** Call `checkForExistingNote()` on popup open, show banner
|
||||||
|
- **Files:** `src/popup/`, reference `apps/web-clipper/popup/popup.js`
|
||||||
|
|
||||||
|
### Low Priority (Quality of Life)
|
||||||
|
|
||||||
|
#### 6. **Link with Custom Note**
|
||||||
|
- **MV2:** Save link with custom text entry (textarea in popup)
|
||||||
|
- **MV3:** Only saves URL + page title
|
||||||
|
- **Impact:** Can't add context/thoughts when saving links
|
||||||
|
- **Solution:** Add textarea to popup for "Save Link" action
|
||||||
|
- **Files:** `src/popup/index.ts`, `src/background/index.ts:562-592`
|
||||||
|
|
||||||
|
#### 7. **Date Metadata Extraction**
|
||||||
|
- **MV2:** Extracts `publishedDate`/`modifiedDate` from meta tags
|
||||||
|
- **MV3:** Not implemented
|
||||||
|
- **Impact:** Lost temporal metadata for articles
|
||||||
|
- **Solution:** Add meta tag parsing to content script
|
||||||
|
- **Files:** Add to content script, reference `apps/web-clipper/content.js:44-65`
|
||||||
|
|
||||||
|
#### 8. **Interactive Toast Notifications**
|
||||||
|
- **MV2:** Toasts have "Open in Trilium" and "Close Tabs" buttons
|
||||||
|
- **MV3:** Basic toasts with text only
|
||||||
|
- **Impact:** Extra step to open saved notes
|
||||||
|
- **Solution:** Add button elements to toast HTML
|
||||||
|
- **Files:** `src/content/toast.ts`, reference `apps/web-clipper/content.js:253-291`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Partially Implemented
|
||||||
|
|
||||||
|
| Feature | Status | Gap |
|
||||||
|
|---------|--------|-----|
|
||||||
|
| Screenshot capture | ✅ Working | No cropping applied |
|
||||||
|
| Image processing | ⚠️ Selection only | Full page clips missing |
|
||||||
|
| Save link | ✅ Basic | No custom note text |
|
||||||
|
| Toast notifications | ✅ Basic | No interactive buttons |
|
||||||
|
| Duplicate detection | ✅ Working | Not shown in popup proactively |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Feature Comparison Matrix
|
||||||
|
|
||||||
|
| Feature | MV2 | MV3 | Priority |
|
||||||
|
|---------|-----|-----|----------|
|
||||||
|
| **Content Capture** ||||
|
||||||
|
| Save Selection | ✅ | ✅ | - |
|
||||||
|
| Save Full Page | ✅ | ✅ | - |
|
||||||
|
| Save Link | ✅ | ⚠️ Basic | LOW |
|
||||||
|
| Save Screenshot | ✅ | ⚠️ No crop | **HIGH** |
|
||||||
|
| Save Image | ✅ | ✅ | - |
|
||||||
|
| Save Tabs | ✅ | ❌ | MED |
|
||||||
|
| **Content Processing** ||||
|
||||||
|
| Readability extraction | ✅ | ✅ | - |
|
||||||
|
| DOMPurify sanitization | ✅ | ✅ | - |
|
||||||
|
| Cheerio cleanup | ✅ | ✅ | - |
|
||||||
|
| Image downloading | ✅ | ⚠️ Partial | **HIGH** |
|
||||||
|
| Date metadata | ✅ | ❌ | LOW |
|
||||||
|
| Screenshot cropping | ✅ | ❌ | **HIGH** |
|
||||||
|
| **Save Formats** ||||
|
||||||
|
| HTML | ✅ | ✅ | - |
|
||||||
|
| Markdown | ✅ | ✅ | - |
|
||||||
|
| Both (parent/child) | ✅ | ✅ | - |
|
||||||
|
| **UI Features** ||||
|
||||||
|
| Popup | ✅ | ✅ | - |
|
||||||
|
| Settings page | ✅ | ✅ | - |
|
||||||
|
| Logs page | ✅ | ✅ | - |
|
||||||
|
| Context menus | ✅ | ✅ | - |
|
||||||
|
| Keyboard shortcuts | ✅ | ✅ | - |
|
||||||
|
| Toast notifications | ✅ | ⚠️ Basic | LOW |
|
||||||
|
| Already visited banner | ✅ | ❌ | MED |
|
||||||
|
| Screenshot selection UI | ✅ | ❓ Unknown | **HIGH** |
|
||||||
|
| **Connection** ||||
|
||||||
|
| HTTP/HTTPS servers | ✅ | ✅ | - |
|
||||||
|
| Desktop app mode | ✅ | ✅ | - |
|
||||||
|
| Connection testing | ✅ | ✅ | - |
|
||||||
|
| Auto-reconnect | ✅ | ✅ | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Current Development Phase
|
||||||
|
|
||||||
|
### Phase 1: Critical Features ✅ COMPLETE
|
||||||
|
- ✅ Build system working
|
||||||
|
- ✅ Content script injection
|
||||||
|
- ✅ Basic save functionality
|
||||||
|
- ✅ Settings & logs UI
|
||||||
|
|
||||||
|
### Phase 2: Screenshot Features 🔄 IN PROGRESS
|
||||||
|
- ⏳ **Task 2.1:** Verify screenshot selection UI
|
||||||
|
- ⏳ **Task 2.2:** Implement screenshot cropping
|
||||||
|
- ⏳ **Task 2.3:** Test crop workflow end-to-end
|
||||||
|
|
||||||
|
### Phase 3: Image Processing (Planned)
|
||||||
|
- ⏸️ Apply image processing to full page captures
|
||||||
|
- ⏸️ Test with various image formats
|
||||||
|
- ⏸️ Handle CORS edge cases
|
||||||
|
|
||||||
|
### Phase 4: Quality of Life (Planned)
|
||||||
|
- ⏸️ Save tabs feature
|
||||||
|
- ⏸️ Already visited detection
|
||||||
|
- ⏸️ Link with custom note
|
||||||
|
- ⏸️ Date metadata extraction
|
||||||
|
- ⏸️ Interactive toasts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Build System
|
||||||
|
|
||||||
|
**Source:** `src/` (TypeScript)
|
||||||
|
**Output:** `dist/` (IIFE JavaScript)
|
||||||
|
**Config:** `build.mjs`
|
||||||
|
|
||||||
|
### Key Transformations
|
||||||
|
- `.ts` → `.js` (IIFE bundled)
|
||||||
|
- HTML script refs fixed (`.ts` → `.js`)
|
||||||
|
- Paths rewritten for flat structure
|
||||||
|
- CSS + icons copied
|
||||||
|
- manifest.json validated
|
||||||
|
|
||||||
|
### Common Commands
|
||||||
|
```bash
|
||||||
|
# Build for production
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
npm run type-check
|
||||||
|
|
||||||
|
# Clean build
|
||||||
|
npm run clean && npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
dist/
|
||||||
|
├── background.js # Service worker (IIFE)
|
||||||
|
├── content.js # Content script (IIFE)
|
||||||
|
├── popup.js # Popup UI logic (IIFE)
|
||||||
|
├── options.js # Settings page (IIFE)
|
||||||
|
├── logs.js # Logs page (IIFE)
|
||||||
|
├── *.html # HTML files (script refs fixed)
|
||||||
|
├── *.css # Styles (includes theme.css)
|
||||||
|
├── icons/ # Extension icons
|
||||||
|
├── shared/ # Shared assets (theme.css)
|
||||||
|
└── manifest.json # Chrome extension manifest
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Testing Checklist
|
||||||
|
|
||||||
|
### Before Each Build
|
||||||
|
- [ ] `npm run type-check` passes
|
||||||
|
- [ ] `npm run build` completes without errors
|
||||||
|
- [ ] No console errors in background service worker
|
||||||
|
- [ ] No console errors in content script
|
||||||
|
|
||||||
|
### Core Functionality
|
||||||
|
- [ ] Popup displays correctly
|
||||||
|
- [ ] Settings page accessible
|
||||||
|
- [ ] Logs page accessible
|
||||||
|
- [ ] Connection status shows correctly
|
||||||
|
- [ ] Theme switching works (light/dark/auto)
|
||||||
|
|
||||||
|
### Save Operations
|
||||||
|
- [ ] Save Selection works
|
||||||
|
- [ ] Save Page works
|
||||||
|
- [ ] Save Link works
|
||||||
|
- [ ] Save Screenshot works (full page)
|
||||||
|
- [ ] Save Image works
|
||||||
|
- [ ] Context menu items appear
|
||||||
|
- [ ] Keyboard shortcuts work
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- [ ] Invalid Trilium URL shows error
|
||||||
|
- [ ] Network errors handled gracefully
|
||||||
|
- [ ] Restricted URLs (chrome://) blocked properly
|
||||||
|
- [ ] Duplicate note dialog works
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
### Immediate (This Session)
|
||||||
|
1. **Verify screenshot selection UI** exists and works
|
||||||
|
2. **Implement screenshot cropping** using OffscreenCanvas
|
||||||
|
3. **Test end-to-end** screenshot workflow
|
||||||
|
|
||||||
|
### Short Term (Next Session)
|
||||||
|
4. Fix image processing for full page captures
|
||||||
|
5. Add "already visited" detection to popup
|
||||||
|
6. Implement "save tabs" feature
|
||||||
|
|
||||||
|
### Long Term
|
||||||
|
7. Add custom note text for links
|
||||||
|
8. Extract date metadata
|
||||||
|
9. Add interactive toast buttons
|
||||||
|
10. Performance optimization
|
||||||
|
11. Cross-browser testing (Firefox, Edge)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- `BUILD-MIGRATION-SUMMARY.md` - Build system details
|
||||||
|
- `reference/dev_notes/TOAST-NOTIFICATION-IMPLEMENTATION.md` - Toast system
|
||||||
|
- `reference/chrome_extension_docs/` - Chrome API docs
|
||||||
|
- `reference/Mozilla_Readability_docs/` - Readability docs
|
||||||
|
- `reference/cure53_DOMPurify_docs/` - DOMPurify docs
|
||||||
|
- `reference/cheerio_docs/` - Cheerio docs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Known Issues
|
||||||
|
|
||||||
|
1. **Screenshot cropping not applied** - Crop rect stored but image not cropped
|
||||||
|
2. **Images not embedded in full page** - Only works for selections
|
||||||
|
3. **No "already visited" indicator** - Backend exists, UI doesn't use it
|
||||||
|
4. **Screenshot selection UI untested** - Need to verify against MV2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Support
|
||||||
|
|
||||||
|
**Issue:** Extension not loading?
|
||||||
|
**Fix:** Check `chrome://extensions/` errors, rebuild with `npm run build`
|
||||||
|
|
||||||
|
**Issue:** Buttons not working?
|
||||||
|
**Fix:** Open DevTools, check console for errors, verify script paths in HTML
|
||||||
|
|
||||||
|
**Issue:** Missing styles?
|
||||||
|
**Fix:** Check `dist/shared/theme.css` exists after build
|
||||||
|
|
||||||
|
**Issue:** Content script not injecting?
|
||||||
|
**Fix:** Check URL isn't restricted (chrome://, about:, file://)
|
||||||
|
|
||||||
|
**Issue:** Can't connect to Trilium?
|
||||||
|
**Fix:** Verify URL in settings, check CORS headers, test with curl
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Architecture Notes
|
||||||
|
|
||||||
|
### Content Processing Pipeline
|
||||||
|
```
|
||||||
|
Raw HTML
|
||||||
|
↓
|
||||||
|
Phase 1: Readability (article extraction)
|
||||||
|
↓
|
||||||
|
Phase 2: DOMPurify (security sanitization)
|
||||||
|
↓
|
||||||
|
Phase 3: Cheerio (final polish)
|
||||||
|
↓
|
||||||
|
Clean HTML → Trilium
|
||||||
|
```
|
||||||
|
|
||||||
|
### Save Format Options
|
||||||
|
- **HTML:** Human-readable, rich formatting (default)
|
||||||
|
- **Markdown:** AI/LLM-friendly, plain text with structure
|
||||||
|
- **Both:** HTML parent note + Markdown child note
|
||||||
|
|
||||||
|
### Message Flow
|
||||||
|
```
|
||||||
|
Content Script → Background → Trilium Server
|
||||||
|
↑ ↓
|
||||||
|
Toast Storage/State
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 Security
|
||||||
|
|
||||||
|
- ✅ DOMPurify sanitization on all HTML
|
||||||
|
- ✅ CSP compliant (no inline scripts/eval)
|
||||||
|
- ✅ Restricted URL blocking
|
||||||
|
- ✅ HTTPS recommended for Trilium connection
|
||||||
|
- ⚠️ Auth token stored in chrome.storage.local (encrypted by browser)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status:** 🟢 Ready for Phase 2 Development
|
||||||
|
**Next Task:** Screenshot Selection UI Verification & Cropping Implementation
|
||||||
|
|
||||||
|
Ready to build! 🚀
|
||||||
264
apps/web-clipper-manifestv3/docs/FEATURE-PARITY-CHECKLIST.md
Normal file
264
apps/web-clipper-manifestv3/docs/FEATURE-PARITY-CHECKLIST.md
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
# Feature Parity Checklist - MV2 to MV3 Migration
|
||||||
|
|
||||||
|
**Last Updated**: October 18, 2025
|
||||||
|
**Current Phase**: Screenshot Features
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status Legend
|
||||||
|
- ✅ **Complete** - Fully implemented and tested
|
||||||
|
- 🚧 **In Progress** - Currently being worked on
|
||||||
|
- ⚠️ **Partial** - Working but missing features
|
||||||
|
- ❌ **Missing** - Not yet implemented
|
||||||
|
- ❓ **Unknown** - Needs verification
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Capture Features
|
||||||
|
|
||||||
|
| Feature | Status | Notes | Priority |
|
||||||
|
|---------|--------|-------|----------|
|
||||||
|
| Save Selection | ✅ | Working with image processing | - |
|
||||||
|
| Save Full Page | ✅ | Readability + DOMPurify + Cheerio | - |
|
||||||
|
| Save Link | ⚠️ | Basic (URL + title only) | LOW |
|
||||||
|
| Save Screenshot | ⚠️ | No cropping applied | **HIGH** |
|
||||||
|
| Save Image | ✅ | Downloads and embeds | - |
|
||||||
|
| Save Tabs (Bulk) | ❌ | Not implemented | MED |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Content Processing
|
||||||
|
|
||||||
|
| Feature | Status | Notes | Files |
|
||||||
|
|---------|--------|-------|-------|
|
||||||
|
| Readability extraction | ✅ | Working | `background/index.ts:608-630` |
|
||||||
|
| DOMPurify sanitization | ✅ | Working | `background/index.ts:631-653` |
|
||||||
|
| Cheerio cleanup | ✅ | Working | `background/index.ts:654-666` |
|
||||||
|
| Image downloading | ⚠️ | Selection only | `background/index.ts:668-740` |
|
||||||
|
| Screenshot cropping | ❌ | Rect stored, not applied | `background/index.ts:504-560` |
|
||||||
|
| Date metadata extraction | ❌ | Not implemented | - |
|
||||||
|
|
||||||
|
### Priority Issues:
|
||||||
|
|
||||||
|
#### 1. Screenshot Cropping (HIGH)
|
||||||
|
**Problem**: Full-page screenshot captured, crop rectangle stored in metadata, but crop NOT applied to image.
|
||||||
|
|
||||||
|
**MV2 Implementation**: `apps/web-clipper/background.js:393-427` (cropImage function)
|
||||||
|
|
||||||
|
**What's Needed**:
|
||||||
|
- Implement `cropImage()` function in background
|
||||||
|
- Use OffscreenCanvas API or send to content script
|
||||||
|
- Apply crop before saving to Trilium
|
||||||
|
- Test with various screen sizes
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- `src/background/index.ts` (add crop function)
|
||||||
|
- Possibly `src/content/screenshot.ts` (if canvas needed)
|
||||||
|
|
||||||
|
#### 2. Image Processing for Full Page (HIGH)
|
||||||
|
**Problem**: `postProcessImages()` only runs for selection saves, not full page captures.
|
||||||
|
|
||||||
|
**MV2 Implementation**: `apps/web-clipper/background.js:293-301` (downloads all images)
|
||||||
|
|
||||||
|
**What's Needed**:
|
||||||
|
- Call `postProcessImages()` for all capture types
|
||||||
|
- Handle CORS errors gracefully
|
||||||
|
- Test with various image formats
|
||||||
|
- Consider performance for image-heavy pages
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- `src/background/index.ts:608-630` (processContent function)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## UI Features
|
||||||
|
|
||||||
|
| Feature | Status | Notes | Priority |
|
||||||
|
|---------|--------|-------|----------|
|
||||||
|
| Popup interface | ✅ | With theme support | - |
|
||||||
|
| Settings page | ✅ | Connection config | - |
|
||||||
|
| Logs viewer | ✅ | Filter/search/export | - |
|
||||||
|
| Context menus | ✅ | All save types | - |
|
||||||
|
| Keyboard shortcuts | ✅ | Save (Ctrl+Shift+S), Screenshot (Ctrl+Shift+A) | - |
|
||||||
|
| Toast notifications | ⚠️ | Basic only | LOW |
|
||||||
|
| Already visited banner | ❌ | Backend exists, UI doesn't use | MED |
|
||||||
|
| Screenshot selection UI | ❓ | Needs verification | **HIGH** |
|
||||||
|
|
||||||
|
### Priority Issues:
|
||||||
|
|
||||||
|
#### 3. Screenshot Selection UI Verification (HIGH)
|
||||||
|
**Problem**: Unknown if MV3 version has feature parity with MV2 overlay UI.
|
||||||
|
|
||||||
|
**MV2 Implementation**: `apps/web-clipper/content.js:66-193`
|
||||||
|
- Drag-to-select with visual overlay
|
||||||
|
- Escape key to cancel
|
||||||
|
- Visual feedback during selection
|
||||||
|
- Crosshair cursor
|
||||||
|
|
||||||
|
**What's Needed**:
|
||||||
|
- Test MV3 screenshot selection workflow
|
||||||
|
- Compare UI/UX with MV2 version
|
||||||
|
- Verify all keyboard shortcuts work
|
||||||
|
- Check visual styling matches
|
||||||
|
|
||||||
|
**Files to Check**:
|
||||||
|
- `src/content/screenshot.ts`
|
||||||
|
- `src/content/index.ts`
|
||||||
|
|
||||||
|
#### 4. Already Visited Detection (MED)
|
||||||
|
**Problem**: Popup doesn't show if page was already clipped.
|
||||||
|
|
||||||
|
**MV2 Implementation**: `apps/web-clipper/popup/popup.js` (checks on open)
|
||||||
|
|
||||||
|
**What's Needed**:
|
||||||
|
- Call `checkForExistingNote()` when popup opens
|
||||||
|
- Show banner with link to existing note
|
||||||
|
- Allow user to still save (update or new note)
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- `src/popup/index.ts`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Save Format Options
|
||||||
|
|
||||||
|
| Format | Status | Notes |
|
||||||
|
|--------|--------|-------|
|
||||||
|
| HTML | ✅ | Rich formatting preserved |
|
||||||
|
| Markdown | ✅ | AI/LLM-friendly |
|
||||||
|
| Both (parent/child) | ✅ | HTML parent + MD child |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Trilium Integration
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| HTTP/HTTPS connection | ✅ | Working |
|
||||||
|
| Desktop app mode | ✅ | Working |
|
||||||
|
| Connection testing | ✅ | Working |
|
||||||
|
| Auto-reconnect | ✅ | Working |
|
||||||
|
| Duplicate detection | ✅ | User choice dialog |
|
||||||
|
| Parent note selection | ✅ | Working |
|
||||||
|
| Note attributes | ✅ | Labels and relations |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quality of Life Features
|
||||||
|
|
||||||
|
| Feature | Status | Notes | Priority |
|
||||||
|
|---------|--------|-------|----------|
|
||||||
|
| Link with custom note | ❌ | Only URL + title | LOW |
|
||||||
|
| Date metadata | ❌ | publishedDate, modifiedDate | LOW |
|
||||||
|
| Interactive toasts | ⚠️ | No "Open in Trilium" button | LOW |
|
||||||
|
| Save tabs feature | ❌ | Bulk save all tabs | MED |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Current Development Phase
|
||||||
|
|
||||||
|
### Phase 1: Core Functionality ✅ COMPLETE
|
||||||
|
- [x] Build system working
|
||||||
|
- [x] Content script injection
|
||||||
|
- [x] Basic save operations
|
||||||
|
- [x] Settings and logs UI
|
||||||
|
- [x] Theme system
|
||||||
|
- [x] Centralized logging
|
||||||
|
|
||||||
|
### Phase 2: Screenshot Features 🚧 IN PROGRESS
|
||||||
|
- [ ] **Task 2.1**: Verify screenshot selection UI against MV2
|
||||||
|
- [ ] **Task 2.2**: Implement screenshot cropping function
|
||||||
|
- [ ] **Task 2.3**: Test end-to-end screenshot workflow
|
||||||
|
- [ ] **Task 2.4**: Handle edge cases (very large/small crops)
|
||||||
|
|
||||||
|
**Current Task**: Screenshot selection UI verification
|
||||||
|
|
||||||
|
### Phase 3: Image Processing (PLANNED)
|
||||||
|
- [ ] Apply image processing to full page captures
|
||||||
|
- [ ] Test with various image formats (PNG, JPG, WebP, SVG)
|
||||||
|
- [ ] Handle CORS edge cases
|
||||||
|
- [ ] Performance testing with image-heavy pages
|
||||||
|
|
||||||
|
### Phase 4: Quality of Life (PLANNED)
|
||||||
|
- [ ] Implement "save tabs" feature
|
||||||
|
- [ ] Add "already visited" detection to popup
|
||||||
|
- [ ] Add custom note text for links
|
||||||
|
- [ ] Extract date metadata from pages
|
||||||
|
- [ ] Add interactive toast buttons
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Checklist
|
||||||
|
|
||||||
|
### Before Each Session
|
||||||
|
- [ ] `npm run type-check` passes
|
||||||
|
- [ ] `npm run dev` running successfully
|
||||||
|
- [ ] No console errors in service worker
|
||||||
|
- [ ] No console errors in content script
|
||||||
|
|
||||||
|
### Feature Testing
|
||||||
|
- [ ] Test on regular article pages
|
||||||
|
- [ ] Test on image-heavy pages
|
||||||
|
- [ ] Test on dynamic/SPA pages
|
||||||
|
- [ ] Test on restricted URLs (chrome://)
|
||||||
|
- [ ] Test with slow network
|
||||||
|
- [ ] Test with Trilium server down
|
||||||
|
|
||||||
|
### Edge Cases
|
||||||
|
- [ ] Very long pages
|
||||||
|
- [ ] Pages with many images
|
||||||
|
- [ ] Pages with embedded media
|
||||||
|
- [ ] Pages with complex layouts
|
||||||
|
- [ ] Mobile-responsive pages
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
### Critical (Blocking)
|
||||||
|
1. **Screenshot cropping not applied** - Full image saved instead of selection
|
||||||
|
2. **Images not embedded in full page** - Only works for selection saves
|
||||||
|
|
||||||
|
### Important (Should fix)
|
||||||
|
3. **Screenshot selection UI untested** - Need to verify against MV2
|
||||||
|
4. **No "already visited" indicator** - Backend function exists but unused
|
||||||
|
|
||||||
|
### Nice to Have
|
||||||
|
5. **No custom note text for links** - Only saves URL and title
|
||||||
|
6. **No date metadata extraction** - Loses temporal context
|
||||||
|
7. **Basic toast notifications** - No interactive buttons
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference: Where Features Live
|
||||||
|
|
||||||
|
### Capture Handlers
|
||||||
|
- **Background**: `src/background/index.ts:390-850`
|
||||||
|
- **Content Script**: `src/content/index.ts:1-200`
|
||||||
|
- **Screenshot UI**: `src/content/screenshot.ts`
|
||||||
|
|
||||||
|
### UI Components
|
||||||
|
- **Popup**: `src/popup/`
|
||||||
|
- **Options**: `src/options/`
|
||||||
|
- **Logs**: `src/logs/`
|
||||||
|
|
||||||
|
### Shared Systems
|
||||||
|
- **Logging**: `src/shared/utils.ts`
|
||||||
|
- **Theme**: `src/shared/theme.ts` + `src/shared/theme.css`
|
||||||
|
- **Types**: `src/shared/types.ts`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migration Reference
|
||||||
|
|
||||||
|
When implementing missing features, compare against MV2:
|
||||||
|
|
||||||
|
```
|
||||||
|
apps/web-clipper/
|
||||||
|
├── background.js # Service worker logic
|
||||||
|
├── content.js # Content script logic
|
||||||
|
└── popup/
|
||||||
|
└── popup.js # Popup UI logic
|
||||||
|
```
|
||||||
|
|
||||||
|
**Remember**: Reference for functionality, not implementation. Use modern TypeScript patterns.
|
||||||
548
apps/web-clipper-manifestv3/docs/MIGRATION-PATTERNS.md
Normal file
548
apps/web-clipper-manifestv3/docs/MIGRATION-PATTERNS.md
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
# MV2 to MV3 Migration Patterns
|
||||||
|
|
||||||
|
Quick reference for common migration scenarios when implementing features from the legacy extension.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 1: Background Page → Service Worker
|
||||||
|
|
||||||
|
### MV2 (Don't Use)
|
||||||
|
```javascript
|
||||||
|
// Persistent background page with global state
|
||||||
|
let cachedData = {};
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||||
|
cachedData[msg.id] = msg.data;
|
||||||
|
sendResponse({success: true});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 (Use This)
|
||||||
|
```typescript
|
||||||
|
// Stateless service worker with chrome.storage
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('BackgroundHandler', 'background');
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
// Store in chrome.storage, not memory
|
||||||
|
await chrome.storage.local.set({ [msg.id]: msg.data });
|
||||||
|
logger.info('Data stored', { id: msg.id });
|
||||||
|
sendResponse({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Storage failed', error);
|
||||||
|
sendResponse({ success: false, error: error.message });
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return true; // Required for async sendResponse
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- No global state (service worker can terminate)
|
||||||
|
- Use `chrome.storage` for persistence
|
||||||
|
- Always return `true` for async handlers
|
||||||
|
- Centralized logging for debugging
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 2: Content Script DOM Manipulation
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
// Simple DOM access
|
||||||
|
const content = document.body.innerHTML;
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern (Same, but with error handling)
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('ContentExtractor', 'content');
|
||||||
|
|
||||||
|
function extractContent(): string {
|
||||||
|
try {
|
||||||
|
if (!document.body) {
|
||||||
|
logger.warn('Document body not available');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = document.body.innerHTML;
|
||||||
|
logger.debug('Content extracted', { length: content.length });
|
||||||
|
return content;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Content extraction failed', error);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Add null checks for DOM elements
|
||||||
|
- Use centralized logging
|
||||||
|
- Handle errors gracefully
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 3: Screenshot Capture
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
chrome.tabs.captureVisibleTab(null, {format: 'png'}, (dataUrl) => {
|
||||||
|
// Crop using canvas
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
// ... cropping logic
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('ScreenshotCapture', 'background');
|
||||||
|
|
||||||
|
async function captureAndCrop(
|
||||||
|
tabId: number,
|
||||||
|
cropRect: { x: number; y: number; width: number; height: number }
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
// Step 1: Capture full tab
|
||||||
|
const dataUrl = await chrome.tabs.captureVisibleTab(null, {
|
||||||
|
format: 'png'
|
||||||
|
});
|
||||||
|
logger.info('Screenshot captured', { tabId });
|
||||||
|
|
||||||
|
// Step 2: Crop using OffscreenCanvas (MV3 service worker compatible)
|
||||||
|
const response = await fetch(dataUrl);
|
||||||
|
const blob = await response.blob();
|
||||||
|
const bitmap = await createImageBitmap(blob);
|
||||||
|
|
||||||
|
const offscreen = new OffscreenCanvas(cropRect.width, cropRect.height);
|
||||||
|
const ctx = offscreen.getContext('2d');
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
throw new Error('Could not get canvas context');
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(
|
||||||
|
bitmap,
|
||||||
|
cropRect.x, cropRect.y, cropRect.width, cropRect.height,
|
||||||
|
0, 0, cropRect.width, cropRect.height
|
||||||
|
);
|
||||||
|
|
||||||
|
const croppedBlob = await offscreen.convertToBlob({ type: 'image/png' });
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
reader.onloadend = () => resolve(reader.result as string);
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(croppedBlob);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Screenshot crop failed', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Use `OffscreenCanvas` (available in service workers)
|
||||||
|
- No DOM canvas manipulation in background
|
||||||
|
- Full async/await pattern
|
||||||
|
- Comprehensive error handling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 4: Image Processing
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
// Download image and convert to base64
|
||||||
|
function processImage(imgSrc) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', imgSrc);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
xhr.onload = () => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => resolve(reader.result);
|
||||||
|
reader.readAsDataURL(xhr.response);
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('ImageProcessor', 'background');
|
||||||
|
|
||||||
|
async function downloadAndEncodeImage(
|
||||||
|
imgSrc: string,
|
||||||
|
baseUrl: string
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
// Resolve relative URLs
|
||||||
|
const absoluteUrl = new URL(imgSrc, baseUrl).href;
|
||||||
|
logger.debug('Downloading image', { url: absoluteUrl });
|
||||||
|
|
||||||
|
// Use fetch API (modern, async)
|
||||||
|
const response = await fetch(absoluteUrl);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = await response.blob();
|
||||||
|
|
||||||
|
// Convert to base64
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => resolve(reader.result as string);
|
||||||
|
reader.onerror = () => reject(new Error('FileReader failed'));
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn('Image download failed', { url: imgSrc, error });
|
||||||
|
// Return original URL as fallback
|
||||||
|
return imgSrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Use `fetch()` instead of `XMLHttpRequest`
|
||||||
|
- Handle CORS errors gracefully
|
||||||
|
- Return original URL on failure (don't break the note)
|
||||||
|
- Resolve relative URLs properly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 5: Context Menu Creation
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
chrome.contextMenus.create({
|
||||||
|
id: "save-selection",
|
||||||
|
title: "Save to Trilium",
|
||||||
|
contexts: ["selection"]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern (Same API, better structure)
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('ContextMenu', 'background');
|
||||||
|
|
||||||
|
interface MenuConfig {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
contexts: chrome.contextMenus.ContextType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const MENU_ITEMS: MenuConfig[] = [
|
||||||
|
{ id: 'save-selection', title: 'Save Selection to Trilium', contexts: ['selection'] },
|
||||||
|
{ id: 'save-page', title: 'Save Page to Trilium', contexts: ['page'] },
|
||||||
|
{ id: 'save-link', title: 'Save Link to Trilium', contexts: ['link'] },
|
||||||
|
{ id: 'save-image', title: 'Save Image to Trilium', contexts: ['image'] },
|
||||||
|
{ id: 'save-screenshot', title: 'Save Screenshot to Trilium', contexts: ['page'] }
|
||||||
|
];
|
||||||
|
|
||||||
|
async function setupContextMenus(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Remove existing menus
|
||||||
|
await chrome.contextMenus.removeAll();
|
||||||
|
|
||||||
|
// Create all menu items
|
||||||
|
for (const item of MENU_ITEMS) {
|
||||||
|
await chrome.contextMenus.create(item);
|
||||||
|
logger.debug('Context menu created', { id: item.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info('Context menus initialized', { count: MENU_ITEMS.length });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Context menu setup failed', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call during service worker initialization
|
||||||
|
chrome.runtime.onInstalled.addListener(() => {
|
||||||
|
setupContextMenus();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Centralized menu configuration
|
||||||
|
- Clear typing with interfaces
|
||||||
|
- Proper error handling
|
||||||
|
- Logging for debugging
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 6: Sending Messages from Content to Background
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
chrome.runtime.sendMessage({type: 'SAVE', data: content}, (response) => {
|
||||||
|
console.log('Saved:', response);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('ContentScript', 'content');
|
||||||
|
|
||||||
|
interface SaveMessage {
|
||||||
|
type: 'SAVE_SELECTION' | 'SAVE_PAGE' | 'SAVE_LINK';
|
||||||
|
data: {
|
||||||
|
content: string;
|
||||||
|
metadata: {
|
||||||
|
title: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SaveResponse {
|
||||||
|
success: boolean;
|
||||||
|
noteId?: string;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendToBackground(message: SaveMessage): Promise<SaveResponse> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.runtime.sendMessage(message, (response: SaveResponse) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
logger.error('Message send failed', chrome.runtime.lastError);
|
||||||
|
reject(new Error(chrome.runtime.lastError.message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
logger.warn('Background operation failed', { error: response.error });
|
||||||
|
reject(new Error(response.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info('Message handled successfully', { noteId: response.noteId });
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
try {
|
||||||
|
const result = await sendToBackground({
|
||||||
|
type: 'SAVE_SELECTION',
|
||||||
|
data: {
|
||||||
|
content: selectedHtml,
|
||||||
|
metadata: {
|
||||||
|
title: document.title,
|
||||||
|
url: window.location.href
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
showToast(`Saved to Trilium: ${result.noteId}`);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Save failed', error);
|
||||||
|
showToast('Failed to save to Trilium', 'error');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Strong typing for messages and responses
|
||||||
|
- Promise wrapper for callback API
|
||||||
|
- Always check `chrome.runtime.lastError`
|
||||||
|
- Handle errors at both send and response levels
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 7: Storage Operations
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
// Mix of localStorage and chrome.storage
|
||||||
|
localStorage.setItem('setting', value);
|
||||||
|
chrome.storage.local.get(['data'], (result) => {
|
||||||
|
console.log(result.data);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('StorageManager', 'background');
|
||||||
|
|
||||||
|
// NEVER use localStorage in service workers - it doesn't exist
|
||||||
|
|
||||||
|
interface StorageData {
|
||||||
|
settings: {
|
||||||
|
triliumUrl: string;
|
||||||
|
authToken: string;
|
||||||
|
saveFormat: 'html' | 'markdown' | 'both';
|
||||||
|
};
|
||||||
|
cache: {
|
||||||
|
lastSync: number;
|
||||||
|
noteIds: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadSettings(): Promise<StorageData['settings']> {
|
||||||
|
try {
|
||||||
|
const { settings } = await chrome.storage.local.get(['settings']);
|
||||||
|
logger.debug('Settings loaded', { hasToken: !!settings?.authToken });
|
||||||
|
return settings || getDefaultSettings();
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Settings load failed', error);
|
||||||
|
return getDefaultSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSettings(settings: Partial<StorageData['settings']>): Promise<void> {
|
||||||
|
try {
|
||||||
|
const current = await loadSettings();
|
||||||
|
const updated = { ...current, ...settings };
|
||||||
|
await chrome.storage.local.set({ settings: updated });
|
||||||
|
logger.info('Settings saved', { keys: Object.keys(settings) });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Settings save failed', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultSettings(): StorageData['settings'] {
|
||||||
|
return {
|
||||||
|
triliumUrl: '',
|
||||||
|
authToken: '',
|
||||||
|
saveFormat: 'html'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- NEVER use `localStorage` (not available in service workers)
|
||||||
|
- Use `chrome.storage.local` for all data
|
||||||
|
- Use `chrome.storage.sync` for user preferences (sync across devices)
|
||||||
|
- Full TypeScript typing for stored data
|
||||||
|
- Default values for missing data
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 8: Trilium API Communication
|
||||||
|
|
||||||
|
### MV2 Pattern
|
||||||
|
```javascript
|
||||||
|
function saveToTrilium(content, metadata) {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('POST', triliumUrl + '/api/notes');
|
||||||
|
xhr.setRequestHeader('Authorization', token);
|
||||||
|
xhr.send(JSON.stringify({content, metadata}));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### MV3 Pattern
|
||||||
|
```typescript
|
||||||
|
import { Logger } from '@/shared/utils';
|
||||||
|
const logger = Logger.create('TriliumAPI', 'background');
|
||||||
|
|
||||||
|
interface TriliumNote {
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
type: 'text';
|
||||||
|
mime: 'text/html' | 'text/markdown';
|
||||||
|
parentNoteId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TriliumResponse {
|
||||||
|
note: {
|
||||||
|
noteId: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNote(
|
||||||
|
note: TriliumNote,
|
||||||
|
triliumUrl: string,
|
||||||
|
authToken: string
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
const url = `${triliumUrl}/api/create-note`;
|
||||||
|
|
||||||
|
logger.debug('Creating note in Trilium', {
|
||||||
|
title: note.title,
|
||||||
|
contentLength: note.content.length
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': authToken,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(note)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: TriliumResponse = await response.json();
|
||||||
|
logger.info('Note created successfully', { noteId: data.note.noteId });
|
||||||
|
|
||||||
|
return data.note.noteId;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Note creation failed', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Changes:**
|
||||||
|
- Use `fetch()` API (modern, promise-based)
|
||||||
|
- Full TypeScript typing for requests/responses
|
||||||
|
- Comprehensive error handling
|
||||||
|
- Detailed logging for debugging
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference: When to Use Each Pattern
|
||||||
|
|
||||||
|
| Task | Pattern | Files Typically Modified |
|
||||||
|
|------|---------|-------------------------|
|
||||||
|
| Add capture feature | Pattern 1, 6, 8 | `background/index.ts`, `content/index.ts` |
|
||||||
|
| Process images | Pattern 4 | `background/index.ts` |
|
||||||
|
| Add context menu | Pattern 5 | `background/index.ts` |
|
||||||
|
| Screenshot with crop | Pattern 3 | `background/index.ts`, possibly `content/screenshot.ts` |
|
||||||
|
| Settings management | Pattern 7 | `options/index.ts`, `background/index.ts` |
|
||||||
|
| Trilium communication | Pattern 8 | `background/index.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Gotchas
|
||||||
|
|
||||||
|
1. **Service Worker Termination**
|
||||||
|
- Don't store state in global variables
|
||||||
|
- Use `chrome.storage` or `chrome.alarms`
|
||||||
|
|
||||||
|
2. **Async Message Handlers**
|
||||||
|
- Always return `true` in listener
|
||||||
|
- Always check `chrome.runtime.lastError`
|
||||||
|
|
||||||
|
3. **Canvas in Service Workers**
|
||||||
|
- Use `OffscreenCanvas`, not regular `<canvas>`
|
||||||
|
- No DOM access in background scripts
|
||||||
|
|
||||||
|
4. **CORS Issues**
|
||||||
|
- Handle fetch failures gracefully
|
||||||
|
- Provide fallbacks for external resources
|
||||||
|
|
||||||
|
5. **Type Safety**
|
||||||
|
- Define interfaces for all messages
|
||||||
|
- Type all chrome.storage data structures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Usage**: When implementing a feature, find the relevant pattern above and adapt it. Don't copy MV2 code directly—use these proven MV3 patterns instead.
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
## For Feature Implementation:
|
||||||
|
Implement [FEATURE_NAME] from FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
Legacy reference: apps/web-clipper/[FILE]:[LINES]
|
||||||
|
Target files: src/[FILES]
|
||||||
|
|
||||||
|
Use centralized logging and theme system. Update checklist when done.
|
||||||
|
|
||||||
|
## For Bug Fixes:
|
||||||
|
Fix [ISSUE] in src/[FILE].
|
||||||
|
|
||||||
|
Expected behavior: [DESCRIBE]
|
||||||
|
Current behavior: [DESCRIBE]
|
||||||
|
Error logs: [IF ANY]
|
||||||
|
|
||||||
|
## For Code Understanding:
|
||||||
|
Explain the [FEATURE] implementation in apps/web-clipper/[FILE].
|
||||||
|
|
||||||
|
I need to replicate this in MV3. What's the core logic and data flow?
|
||||||
|
|
||||||
|
## For Architecture Questions:
|
||||||
|
[QUESTION ABOUT SYSTEM DESIGN]
|
||||||
|
|
||||||
|
See docs/ARCHITECTURE.md for context on logging/theme systems.
|
||||||
438
apps/web-clipper-manifestv3/reference/copilot_task_templates.md
Normal file
438
apps/web-clipper-manifestv3/reference/copilot_task_templates.md
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
# Copilot Task Templates
|
||||||
|
|
||||||
|
Quick copy-paste templates for common Copilot tasks. Fill in the blanks and paste into Copilot Agent mode.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 1: Implement Feature from Checklist
|
||||||
|
|
||||||
|
```
|
||||||
|
Implement [FEATURE_NAME] from docs/FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
**Legacy Reference**: apps/web-clipper/[FILE]:[LINE_RANGE]
|
||||||
|
|
||||||
|
**Target Files**:
|
||||||
|
- src/[FILE_1]
|
||||||
|
- src/[FILE_2]
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Use centralized logging (Logger.create)
|
||||||
|
- Use theme system if UI component
|
||||||
|
- Follow patterns from docs/MIGRATION-PATTERNS.md
|
||||||
|
- Handle all errors gracefully
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Test on [SCENARIO_1]
|
||||||
|
- Test on [SCENARIO_2]
|
||||||
|
- Verify no console errors
|
||||||
|
|
||||||
|
**Update**:
|
||||||
|
- Mark feature complete in docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
Implement screenshot cropping from docs/FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
**Legacy Reference**: apps/web-clipper/background.js:393-427
|
||||||
|
|
||||||
|
**Target Files**:
|
||||||
|
- src/background/index.ts (add cropImage function)
|
||||||
|
- src/background/index.ts (update captureScreenshot handler)
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Use OffscreenCanvas API (Pattern 3 from docs/MIGRATION-PATTERNS.md)
|
||||||
|
- Use centralized logging (Logger.create)
|
||||||
|
- Handle edge cases (crop outside bounds, zero-size crop)
|
||||||
|
- Handle all errors gracefully
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Test small crop (100x100)
|
||||||
|
- Test large crop (full page)
|
||||||
|
- Test edge crops (near borders)
|
||||||
|
- Verify cropped dimensions correct
|
||||||
|
|
||||||
|
**Update**:
|
||||||
|
- Mark screenshot cropping complete in docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 2: Fix Bug
|
||||||
|
|
||||||
|
```
|
||||||
|
Fix [BUG_DESCRIPTION] in src/[FILE].
|
||||||
|
|
||||||
|
**Problem**: [WHAT'S BROKEN]
|
||||||
|
|
||||||
|
**Expected Behavior**: [WHAT SHOULD HAPPEN]
|
||||||
|
|
||||||
|
**Current Behavior**: [WHAT ACTUALLY HAPPENS]
|
||||||
|
|
||||||
|
**Error Logs** (if any):
|
||||||
|
```
|
||||||
|
[PASTE ERROR FROM LOGS]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Root Cause** (if known): [HYPOTHESIS]
|
||||||
|
|
||||||
|
**Solution Approach**: [HOW TO FIX]
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Reproduce bug before fix
|
||||||
|
- Verify fix resolves issue
|
||||||
|
- Test edge cases
|
||||||
|
- Check for regressions
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
Fix image processing not running on full page captures in src/background/index.ts.
|
||||||
|
|
||||||
|
**Problem**: Images not being downloaded and embedded for full-page saves
|
||||||
|
|
||||||
|
**Expected Behavior**: All images should be converted to base64 and embedded in the note
|
||||||
|
|
||||||
|
**Current Behavior**: Only works for selection saves, full page keeps external URLs
|
||||||
|
|
||||||
|
**Root Cause**: postProcessImages() only called in saveSelection handler, not in savePage handler
|
||||||
|
|
||||||
|
**Solution Approach**:
|
||||||
|
1. Call postProcessImages() in processContent function (line ~608)
|
||||||
|
2. Ensure it runs for all capture types
|
||||||
|
3. Handle CORS errors gracefully
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Save full page with multiple images
|
||||||
|
- Save page with CORS-restricted images
|
||||||
|
- Verify embedded images display in Trilium
|
||||||
|
- Check external images still work as fallback
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 3: Add UI Component
|
||||||
|
|
||||||
|
```
|
||||||
|
Add [COMPONENT_NAME] to [PAGE].
|
||||||
|
|
||||||
|
**Purpose**: [WHAT IT DOES]
|
||||||
|
|
||||||
|
**Visual Design**:
|
||||||
|
- [DESCRIBE LAYOUT]
|
||||||
|
- [LIST UI ELEMENTS]
|
||||||
|
|
||||||
|
**Data Source**: [WHERE DATA COMES FROM]
|
||||||
|
|
||||||
|
**Interactions**:
|
||||||
|
- [USER ACTION 1] → [RESULT]
|
||||||
|
- [USER ACTION 2] → [RESULT]
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- src/[PAGE]/[PAGE].html (markup)
|
||||||
|
- src/[PAGE]/[PAGE].css (styles with theme variables)
|
||||||
|
- src/[PAGE]/index.ts (logic with logging)
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Import and use theme.css
|
||||||
|
- Initialize ThemeManager
|
||||||
|
- Use centralized logging
|
||||||
|
- Handle empty/error states
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Test in light mode
|
||||||
|
- Test in dark mode
|
||||||
|
- Test with no data
|
||||||
|
- Test with error condition
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
Add "Recent Notes" section to popup.
|
||||||
|
|
||||||
|
**Purpose**: Show last 5 saved notes with links to open in Trilium
|
||||||
|
|
||||||
|
**Visual Design**:
|
||||||
|
- Card/panel below main action buttons
|
||||||
|
- Heading "Recently Saved"
|
||||||
|
- List of note titles (clickable links)
|
||||||
|
- If empty, show "No recent notes"
|
||||||
|
|
||||||
|
**Data Source**:
|
||||||
|
- chrome.storage.local.recentNotes array
|
||||||
|
- Populated by background when saving notes
|
||||||
|
|
||||||
|
**Interactions**:
|
||||||
|
- Click note title → Opens note in Trilium (new tab)
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- src/popup/popup.html (add <div> for recent notes)
|
||||||
|
- src/popup/popup.css (styles with theme variables)
|
||||||
|
- src/popup/index.ts (load and display recent notes)
|
||||||
|
- src/background/index.ts (store recent notes on save)
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Import and use theme.css with CSS variables
|
||||||
|
- Initialize ThemeManager
|
||||||
|
- Use centralized logging
|
||||||
|
- Handle empty state (no recent notes)
|
||||||
|
- Escape HTML in note titles
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Test in light mode
|
||||||
|
- Test in dark mode
|
||||||
|
- Test with no recent notes
|
||||||
|
- Test with 1 note, 5 notes, 10+ notes
|
||||||
|
- Test note title with special characters
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 4: Refactor Code
|
||||||
|
|
||||||
|
```
|
||||||
|
Refactor [FUNCTION/MODULE] in src/[FILE].
|
||||||
|
|
||||||
|
**Current Issues**:
|
||||||
|
- [PROBLEM 1]
|
||||||
|
- [PROBLEM 2]
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- [IMPROVEMENT 1]
|
||||||
|
- [IMPROVEMENT 2]
|
||||||
|
|
||||||
|
**Approach**:
|
||||||
|
- [STEP 1]
|
||||||
|
- [STEP 2]
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Maintain existing functionality (no behavior changes)
|
||||||
|
- Improve type safety
|
||||||
|
- Add/improve logging
|
||||||
|
- Add error handling if missing
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Verify all existing functionality still works
|
||||||
|
- Check no regressions
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 5: Investigate Issue
|
||||||
|
|
||||||
|
```
|
||||||
|
Investigate [ISSUE_DESCRIPTION].
|
||||||
|
|
||||||
|
**Symptoms**:
|
||||||
|
- [WHAT USER SEES]
|
||||||
|
|
||||||
|
**Context**:
|
||||||
|
- Happens when [SCENARIO]
|
||||||
|
- Doesn't happen when [SCENARIO]
|
||||||
|
|
||||||
|
**What to Check**:
|
||||||
|
1. Review relevant code in [FILE]
|
||||||
|
2. Check logs for errors
|
||||||
|
3. Check storage state
|
||||||
|
4. Compare with MV2 implementation (apps/web-clipper/[FILE])
|
||||||
|
|
||||||
|
**Expected Output**:
|
||||||
|
- Root cause analysis
|
||||||
|
- Proposed solution
|
||||||
|
- Code changes needed (if applicable)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 6: Optimize Performance
|
||||||
|
|
||||||
|
```
|
||||||
|
Optimize performance of [FEATURE] in src/[FILE].
|
||||||
|
|
||||||
|
**Current Performance**: [METRICS]
|
||||||
|
|
||||||
|
**Target Performance**: [GOAL]
|
||||||
|
|
||||||
|
**Bottlenecks** (if known):
|
||||||
|
- [ISSUE 1]
|
||||||
|
- [ISSUE 2]
|
||||||
|
|
||||||
|
**Approach**:
|
||||||
|
- [OPTIMIZATION 1]
|
||||||
|
- [OPTIMIZATION 2]
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Measure before/after with performance.now()
|
||||||
|
- Log performance metrics
|
||||||
|
- Don't break existing functionality
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Test with small dataset
|
||||||
|
- Test with large dataset
|
||||||
|
- Verify functionality unchanged
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template 7: Update Documentation
|
||||||
|
|
||||||
|
```
|
||||||
|
Update [DOCUMENTATION_FILE].
|
||||||
|
|
||||||
|
**Changes Needed**:
|
||||||
|
- [CHANGE 1]
|
||||||
|
- [CHANGE 2]
|
||||||
|
|
||||||
|
**Reason**: [WHY UPDATING]
|
||||||
|
|
||||||
|
**Files**:
|
||||||
|
- docs/[FILE]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Copilot Commands
|
||||||
|
|
||||||
|
### For Understanding Legacy Code
|
||||||
|
```
|
||||||
|
Explain the [FEATURE] implementation in apps/web-clipper/[FILE]:[LINES].
|
||||||
|
|
||||||
|
Focus on:
|
||||||
|
- Core logic and data flow
|
||||||
|
- Key functions and their purpose
|
||||||
|
- Data structures used
|
||||||
|
- Edge cases handled
|
||||||
|
|
||||||
|
I need to replicate this in MV3 with modern patterns.
|
||||||
|
```
|
||||||
|
|
||||||
|
### For Code Review
|
||||||
|
```
|
||||||
|
Review the implementation in src/[FILE].
|
||||||
|
|
||||||
|
Check for:
|
||||||
|
- Proper error handling
|
||||||
|
- Centralized logging usage
|
||||||
|
- Theme system integration (if UI)
|
||||||
|
- Type safety (no 'any' types)
|
||||||
|
- Edge cases handled
|
||||||
|
- Performance concerns
|
||||||
|
|
||||||
|
Suggest improvements if any.
|
||||||
|
```
|
||||||
|
|
||||||
|
### For Pattern Guidance
|
||||||
|
```
|
||||||
|
What's the best MV3 pattern for [TASK]?
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
- Must work in service worker (no DOM)
|
||||||
|
- Need to handle [EDGE_CASE]
|
||||||
|
- Should follow docs/MIGRATION-PATTERNS.md
|
||||||
|
|
||||||
|
Show example implementation.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Copilot Chat Shortcuts
|
||||||
|
|
||||||
|
### Quick Questions (Use Chat Pane - Free)
|
||||||
|
|
||||||
|
```
|
||||||
|
# Understand code
|
||||||
|
What does this function do?
|
||||||
|
|
||||||
|
# Check compatibility
|
||||||
|
Is this MV3 compatible?
|
||||||
|
|
||||||
|
# Get suggestions
|
||||||
|
How can I improve this?
|
||||||
|
|
||||||
|
# Find examples
|
||||||
|
Show example of [PATTERN]
|
||||||
|
|
||||||
|
# Explain error
|
||||||
|
Why is TypeScript showing this error?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inline Fixes (Use Ctrl+I - Free)
|
||||||
|
|
||||||
|
```
|
||||||
|
# Fix error
|
||||||
|
Fix this TypeScript error
|
||||||
|
|
||||||
|
# Add types
|
||||||
|
Add proper TypeScript types
|
||||||
|
|
||||||
|
# Improve logging
|
||||||
|
Add centralized logging
|
||||||
|
|
||||||
|
# Format code
|
||||||
|
Format this properly
|
||||||
|
|
||||||
|
# Add comments
|
||||||
|
Add explanatory comment
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Tips
|
||||||
|
|
||||||
|
### When to Use Templates
|
||||||
|
|
||||||
|
1. **Use Template** when:
|
||||||
|
- Implementing planned feature
|
||||||
|
- Bug has clear reproduction steps
|
||||||
|
- Adding designed UI component
|
||||||
|
- Following established pattern
|
||||||
|
|
||||||
|
2. **Ask for Guidance First** when:
|
||||||
|
- Unclear how to approach problem
|
||||||
|
- Need to understand legacy code
|
||||||
|
- Choosing between approaches
|
||||||
|
- Architectural decision needed
|
||||||
|
|
||||||
|
3. **Use Inline Chat** when:
|
||||||
|
- Fixing TypeScript errors
|
||||||
|
- Adding missing imports
|
||||||
|
- Formatting code
|
||||||
|
- Quick refactoring
|
||||||
|
|
||||||
|
### Maximizing Copilot Efficiency
|
||||||
|
|
||||||
|
**Before Using Agent Mode (Task)**:
|
||||||
|
1. Understand the problem clearly
|
||||||
|
2. Review legacy code if migrating
|
||||||
|
3. Check docs/MIGRATION-PATTERNS.md for relevant pattern
|
||||||
|
4. Plan which files need changes
|
||||||
|
5. Fill out template completely
|
||||||
|
|
||||||
|
**During Agent Mode**:
|
||||||
|
1. Let it work uninterrupted
|
||||||
|
2. Review generated code carefully
|
||||||
|
3. Test immediately
|
||||||
|
4. Use inline chat for small fixes
|
||||||
|
|
||||||
|
**After Task**:
|
||||||
|
1. Update feature checklist
|
||||||
|
2. Commit with good message
|
||||||
|
3. Document any decisions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context File Quick Reference
|
||||||
|
|
||||||
|
Point Copilot to these when needed:
|
||||||
|
|
||||||
|
```
|
||||||
|
See docs/ARCHITECTURE.md for system overview
|
||||||
|
See docs/MIGRATION-PATTERNS.md for coding patterns
|
||||||
|
See docs/DEVELOPMENT-GUIDE.md for workflow guidance
|
||||||
|
See docs/FEATURE-PARITY-CHECKLIST.md for current status
|
||||||
|
See apps/web-clipper/[FILE] for MV2 reference
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: Well-prepared prompts = better results + fewer task retries = more efficient Copilot usage!
|
||||||
2
apps/web-clipper-manifestv3/reference/end_of_session.md
Normal file
2
apps/web-clipper-manifestv3/reference/end_of_session.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
git add .
|
||||||
|
git commit -m "feat: [FEATURE_NAME] - [BRIEF_DESCRIPTION]"
|
||||||
@ -0,0 +1,780 @@
|
|||||||
|
# Optimized Copilot Workflow Guide
|
||||||
|
|
||||||
|
Complete guide for efficient development with GitHub Copilot Basic tier.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
apps/web-clipper-manifestv3/
|
||||||
|
├── .github/
|
||||||
|
│ └── copilot-instructions.md # Auto-loaded by Copilot (streamlined)
|
||||||
|
├── .vscode/
|
||||||
|
│ └── settings.json # VS Code + Copilot config
|
||||||
|
├── docs/
|
||||||
|
│ ├── ARCHITECTURE.md # One-time reference (systems)
|
||||||
|
│ ├── FEATURE-PARITY-CHECKLIST.md # Working status + TODO
|
||||||
|
│ ├── DEVELOPMENT-GUIDE.md # Common tasks + workflows
|
||||||
|
│ └── MIGRATION-PATTERNS.md # MV2→MV3 code patterns
|
||||||
|
├── COPILOT-TASK-TEMPLATES.md # Quick copy-paste prompts
|
||||||
|
├── src/ # Source code
|
||||||
|
├── reference/ # API documentation
|
||||||
|
└── dist/ # Build output (gitignored)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step-by-Step Setup
|
||||||
|
|
||||||
|
### 1. Reorganize Your Documentation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd apps/web-clipper-manifestv3
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
mkdir -p .github docs .vscode
|
||||||
|
|
||||||
|
# Move existing file
|
||||||
|
mv WORKING-STATUS.md docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
|
||||||
|
# Create new files from artifacts I provided
|
||||||
|
# (Copy content from the artifacts above)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Files to create**:
|
||||||
|
1. `.github/copilot-instructions.md` - Streamlined instructions
|
||||||
|
2. `docs/ARCHITECTURE.md` - System overview
|
||||||
|
3. `docs/MIGRATION-PATTERNS.md` - Code patterns
|
||||||
|
4. `docs/DEVELOPMENT-GUIDE.md` - Practical workflows
|
||||||
|
5. `COPILOT-TASK-TEMPLATES.md` - Quick prompts
|
||||||
|
6. `.vscode/settings.json` - Editor config
|
||||||
|
|
||||||
|
### 2. Update Your Existing Files
|
||||||
|
|
||||||
|
**Keep but review**:
|
||||||
|
- `BUILD-MIGRATION-SUMMARY.md` - Still useful reference
|
||||||
|
- `reference/` directory - API documentation
|
||||||
|
|
||||||
|
**Archive** (move to `docs/archive/` if needed):
|
||||||
|
- Old verbose documentation
|
||||||
|
- Duplicate information
|
||||||
|
- Outdated notes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Three-Tier Copilot Usage Strategy
|
||||||
|
|
||||||
|
### Tier 1: Free Operations (Unlimited)
|
||||||
|
|
||||||
|
**Use For**: Quick fixes, small changes, understanding code
|
||||||
|
|
||||||
|
**Tools**:
|
||||||
|
- **Inline Chat** (Ctrl+I): Fix errors, add types, format
|
||||||
|
- **Chat Pane** (Ctrl+Alt+I): Ask questions, get explanations
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
```
|
||||||
|
# Inline Chat (Ctrl+I)
|
||||||
|
"Fix this TypeScript error"
|
||||||
|
"Add proper logging"
|
||||||
|
"Extract this to a function"
|
||||||
|
|
||||||
|
# Chat Pane (Ctrl+Alt+I)
|
||||||
|
"Explain this function"
|
||||||
|
"What's the MV3 equivalent of chrome.webRequest?"
|
||||||
|
"How should I structure this component?"
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to Use**:
|
||||||
|
- Fixing TypeScript errors after implementation
|
||||||
|
- Understanding unfamiliar code
|
||||||
|
- Planning before using Agent mode
|
||||||
|
- Quick refactoring
|
||||||
|
|
||||||
|
### Tier 2: Strategic Agent Mode (Limited - Use Wisely)
|
||||||
|
|
||||||
|
**Use For**: Multi-file changes, feature implementation, complex logic
|
||||||
|
|
||||||
|
**Tool**:
|
||||||
|
- **Copilot Agent** (from chat pane): Cross-file coordination
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
```
|
||||||
|
# Copy from COPILOT-TASK-TEMPLATES.md, fill in, paste:
|
||||||
|
|
||||||
|
Implement screenshot cropping from docs/FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
Legacy Reference: apps/web-clipper/background.js:393-427
|
||||||
|
Target Files: src/background/index.ts
|
||||||
|
|
||||||
|
Use OffscreenCanvas API (Pattern 3 from docs/MIGRATION-PATTERNS.md).
|
||||||
|
Use centralized logging.
|
||||||
|
Update checklist when done.
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to Use**:
|
||||||
|
- Implementing features from checklist
|
||||||
|
- Complex multi-file refactoring
|
||||||
|
- Bug fixes requiring multiple changes
|
||||||
|
|
||||||
|
**How to Maximize Value**:
|
||||||
|
1. **Prepare thoroughly** using Chat Pane first
|
||||||
|
2. **Use templates** from COPILOT-TASK-TEMPLATES.md
|
||||||
|
3. **Be specific** about files, patterns, requirements
|
||||||
|
4. **Let it run** without interruption
|
||||||
|
5. **Use Inline Chat** for cleanup after
|
||||||
|
|
||||||
|
### Tier 3: Manual Development (When Appropriate)
|
||||||
|
|
||||||
|
**Use For**: Simple changes, learning opportunities, debugging
|
||||||
|
|
||||||
|
**When to Use**:
|
||||||
|
- Adding a single line of code
|
||||||
|
- Fixing obvious typos
|
||||||
|
- Adjusting CSS values
|
||||||
|
- Learning the codebase
|
||||||
|
- Quick experiments
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Optimal Daily Workflow
|
||||||
|
|
||||||
|
### Session Start (5 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Navigate and start build
|
||||||
|
cd apps/web-clipper-manifestv3
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# 2. Open VS Code
|
||||||
|
code .
|
||||||
|
|
||||||
|
# 3. Check current task
|
||||||
|
# Open: docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
# Find next priority item
|
||||||
|
```
|
||||||
|
|
||||||
|
### Planning Phase (10-15 minutes - Free)
|
||||||
|
|
||||||
|
**Use Chat Pane** (Ctrl+Alt+I):
|
||||||
|
|
||||||
|
```
|
||||||
|
1. "Looking at feature [X] in docs/FEATURE-PARITY-CHECKLIST.md,
|
||||||
|
what's the implementation approach?"
|
||||||
|
|
||||||
|
2. "Review the MV2 code in apps/web-clipper/[FILE]:[LINES].
|
||||||
|
What's the core logic?"
|
||||||
|
|
||||||
|
3. "What's the best MV3 pattern for this?
|
||||||
|
See docs/MIGRATION-PATTERNS.md for our patterns."
|
||||||
|
|
||||||
|
4. "What files need to be modified?"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output**: Clear plan before using Agent mode
|
||||||
|
|
||||||
|
### Implementation Phase (Uses 1 Task)
|
||||||
|
|
||||||
|
**Use Agent Mode**:
|
||||||
|
|
||||||
|
1. Open `COPILOT-TASK-TEMPLATES.md`
|
||||||
|
2. Copy appropriate template
|
||||||
|
3. Fill in all blanks
|
||||||
|
4. Paste into Copilot Agent
|
||||||
|
5. Let it work
|
||||||
|
6. Review generated code
|
||||||
|
|
||||||
|
**Example Session**:
|
||||||
|
```
|
||||||
|
# You paste (from template):
|
||||||
|
Implement screenshot cropping from docs/FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
Legacy Reference: apps/web-clipper/background.js:393-427
|
||||||
|
Target Files:
|
||||||
|
- src/background/index.ts (add cropImage function)
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- Use OffscreenCanvas API (Pattern 3)
|
||||||
|
- Use centralized logging
|
||||||
|
- Handle edge cases
|
||||||
|
|
||||||
|
Testing:
|
||||||
|
- Small crops, large crops, edge crops
|
||||||
|
- Verify dimensions correct
|
||||||
|
|
||||||
|
Update: docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cleanup Phase (Free)
|
||||||
|
|
||||||
|
**Use Inline Chat** (Ctrl+I):
|
||||||
|
|
||||||
|
1. Fix any TypeScript errors
|
||||||
|
2. Add missing imports
|
||||||
|
3. Improve logging
|
||||||
|
4. Format code
|
||||||
|
|
||||||
|
```
|
||||||
|
# Select code, press Ctrl+I:
|
||||||
|
"Fix TypeScript errors"
|
||||||
|
"Add better error handling"
|
||||||
|
"Add logging statement"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Phase (Manual)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Reload extension in Chrome
|
||||||
|
chrome://extensions/ → Reload button
|
||||||
|
|
||||||
|
# 2. Test functionality
|
||||||
|
# - Happy path
|
||||||
|
# - Error cases
|
||||||
|
# - Edge cases
|
||||||
|
|
||||||
|
# 3. Check logs
|
||||||
|
# - Open extension logs page
|
||||||
|
# - Filter by component
|
||||||
|
# - Verify no errors
|
||||||
|
|
||||||
|
# 4. Check consoles
|
||||||
|
# - Service worker console
|
||||||
|
# - Popup console (if UI)
|
||||||
|
# - Page console (if content script)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Phase (Manual)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Update checklist
|
||||||
|
# Edit: docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
# Mark feature as ✅ complete
|
||||||
|
|
||||||
|
# 2. Commit changes
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: implement screenshot cropping"
|
||||||
|
|
||||||
|
# 3. Push (when ready)
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task Budgeting Strategy
|
||||||
|
|
||||||
|
**With Copilot Basic**: You have limited Agent mode tasks per month.
|
||||||
|
|
||||||
|
### Prioritize Tasks For:
|
||||||
|
|
||||||
|
**HIGH VALUE (Use Agent Mode)**:
|
||||||
|
1. ✅ Implementing missing features from checklist
|
||||||
|
2. ✅ Complex multi-file refactoring
|
||||||
|
3. ✅ Bug fixes requiring investigation
|
||||||
|
4. ✅ New component creation with UI
|
||||||
|
|
||||||
|
**LOW VALUE (Use Free Tools Instead)**:
|
||||||
|
1. ❌ Fixing simple TypeScript errors → Use Inline Chat
|
||||||
|
2. ❌ Understanding code → Use Chat Pane
|
||||||
|
3. ❌ Small CSS adjustments → Do manually
|
||||||
|
4. ❌ Adding comments → Use Inline Chat
|
||||||
|
5. ❌ Renaming variables → Do manually or use VS Code refactor
|
||||||
|
6. ❌ Formatting code → Use Prettier (Shift+Alt+F)
|
||||||
|
|
||||||
|
### Monthly Task Planning
|
||||||
|
|
||||||
|
**Estimate your tasks per month**: ~20-30 tasks (varies by plan)
|
||||||
|
|
||||||
|
**For this project** (Phase 2 - Screenshot Features):
|
||||||
|
- Task 1: Screenshot cropping implementation
|
||||||
|
- Task 2: Image processing for full page
|
||||||
|
- Task 3: Screenshot selection UI improvements
|
||||||
|
- **Total**: 3 tasks for Phase 2
|
||||||
|
|
||||||
|
**For Phase 3** (Image Processing):
|
||||||
|
- Task 4: Apply image processing to all capture types
|
||||||
|
- Task 5: CORS error handling improvements
|
||||||
|
- **Total**: 2 tasks for Phase 3
|
||||||
|
|
||||||
|
**For Phase 4** (Quality of Life):
|
||||||
|
- Task 6: Save tabs feature
|
||||||
|
- Task 7: Already visited detection
|
||||||
|
- Task 8: Custom note text for links
|
||||||
|
- **Total**: 3 tasks for Phase 4
|
||||||
|
|
||||||
|
**Total for project completion**: ~8-10 Agent mode tasks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Real-World Example: Implementing Screenshot Cropping
|
||||||
|
|
||||||
|
Let's walk through a complete feature implementation using the optimized workflow.
|
||||||
|
|
||||||
|
### Phase 1: Planning (Free - Chat Pane)
|
||||||
|
|
||||||
|
**You ask**:
|
||||||
|
```
|
||||||
|
I need to implement screenshot cropping for the extension. The current
|
||||||
|
implementation captures full-page screenshots but doesn't apply the crop
|
||||||
|
rectangle that's stored in metadata.
|
||||||
|
|
||||||
|
MV2 implementation: apps/web-clipper/background.js:393-427
|
||||||
|
|
||||||
|
Questions:
|
||||||
|
1. Can I use regular Canvas in a service worker, or do I need OffscreenCanvas?
|
||||||
|
2. What's the best way to crop the image?
|
||||||
|
3. How should I handle errors?
|
||||||
|
|
||||||
|
See docs/MIGRATION-PATTERNS.md Pattern 3 for reference.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Copilot responds** (paraphrased):
|
||||||
|
```
|
||||||
|
1. Must use OffscreenCanvas - regular Canvas requires DOM
|
||||||
|
2. Best approach:
|
||||||
|
- Convert dataURL to Blob
|
||||||
|
- Create ImageBitmap from Blob
|
||||||
|
- Draw cropped section to OffscreenCanvas
|
||||||
|
- Convert back to dataURL
|
||||||
|
3. Handle errors:
|
||||||
|
- Invalid crop dimensions (width/height <= 0)
|
||||||
|
- Crop outside image bounds
|
||||||
|
- Canvas context creation failure
|
||||||
|
|
||||||
|
Here's the basic structure:
|
||||||
|
[Shows code structure]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output**: Clear implementation plan, no task used.
|
||||||
|
|
||||||
|
### Phase 2: Implementation (Uses 1 Task)
|
||||||
|
|
||||||
|
**You prepare the prompt** (from template):
|
||||||
|
```
|
||||||
|
Implement screenshot cropping from docs/FEATURE-PARITY-CHECKLIST.md.
|
||||||
|
|
||||||
|
**Legacy Reference**: apps/web-clipper/background.js:393-427
|
||||||
|
|
||||||
|
**Target Files**:
|
||||||
|
- src/background/index.ts (add cropImage function around line 500)
|
||||||
|
- src/background/index.ts (update captureScreenshot handler to call cropImage)
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Use OffscreenCanvas API (service worker compatible)
|
||||||
|
- Follow Pattern 3 from docs/MIGRATION-PATTERNS.md
|
||||||
|
- Use centralized logging (Logger.create('ScreenshotCrop', 'background'))
|
||||||
|
- Handle edge cases:
|
||||||
|
- Crop dimensions <= 0 (return error)
|
||||||
|
- Crop outside image bounds (clamp to bounds)
|
||||||
|
- Canvas context creation failure (log and throw)
|
||||||
|
- Return cropped image as base64 dataURL
|
||||||
|
|
||||||
|
**Implementation Details**:
|
||||||
|
1. Create async function `cropImage(dataUrl: string, cropRect: CropRect): Promise<string>`
|
||||||
|
2. Convert dataURL to Blob using fetch
|
||||||
|
3. Create ImageBitmap from Blob
|
||||||
|
4. Create OffscreenCanvas with crop dimensions
|
||||||
|
5. Draw cropped section using drawImage with source/dest rects
|
||||||
|
6. Convert to Blob, then back to dataURL
|
||||||
|
7. Log success with final dimensions
|
||||||
|
|
||||||
|
**Testing**:
|
||||||
|
- Small crop (100x100px)
|
||||||
|
- Large crop (full viewport)
|
||||||
|
- Edge crop (near image borders)
|
||||||
|
- Invalid crop (negative dimensions) - should error
|
||||||
|
- Verify cropped image dimensions match crop rect
|
||||||
|
|
||||||
|
**Update**:
|
||||||
|
- Mark "Screenshot cropping" as ✅ in docs/FEATURE-PARITY-CHECKLIST.md
|
||||||
|
- Add comment about implementation in checklist
|
||||||
|
```
|
||||||
|
|
||||||
|
**Copilot implements**: Multiple files, full feature.
|
||||||
|
|
||||||
|
### Phase 3: Cleanup (Free - Inline Chat)
|
||||||
|
|
||||||
|
**You notice**: Some TypeScript errors, missing null checks.
|
||||||
|
|
||||||
|
**You do** (Ctrl+I on error):
|
||||||
|
```
|
||||||
|
"Fix this TypeScript error"
|
||||||
|
"Add null check for canvas context"
|
||||||
|
"Improve error message"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Result**: Clean, type-safe code.
|
||||||
|
|
||||||
|
### Phase 4: Testing (Manual)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Reload extension
|
||||||
|
chrome://extensions/ → Reload
|
||||||
|
|
||||||
|
# Test cases
|
||||||
|
1. Visit any webpage
|
||||||
|
2. Press Ctrl+Shift+A (screenshot shortcut)
|
||||||
|
3. Drag to select small area
|
||||||
|
4. Save to Trilium
|
||||||
|
5. Check image in Trilium - should be cropped
|
||||||
|
|
||||||
|
# Check logs
|
||||||
|
- Open extension Logs page
|
||||||
|
- Search "crop"
|
||||||
|
- Should see "Screenshot cropped" with dimensions
|
||||||
|
- Should see "Screenshot captured" with dimensions
|
||||||
|
- No errors
|
||||||
|
|
||||||
|
# Test edge cases
|
||||||
|
- Try very small crop (10x10)
|
||||||
|
- Try very large crop (full page)
|
||||||
|
- Try crop at page edge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 5: Documentation (Manual)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update checklist
|
||||||
|
# In docs/FEATURE-PARITY-CHECKLIST.md:
|
||||||
|
## Content Processing
|
||||||
|
| Screenshot cropping | ✅ | Using OffscreenCanvas | - |
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git add docs/FEATURE-PARITY-CHECKLIST.md src/background/index.ts
|
||||||
|
git commit -m "feat: implement screenshot cropping with OffscreenCanvas
|
||||||
|
|
||||||
|
- Add cropImage function using OffscreenCanvas API
|
||||||
|
- Update captureScreenshot handler to apply crop
|
||||||
|
- Handle edge cases (invalid dimensions, out of bounds)
|
||||||
|
- Add comprehensive logging and error handling
|
||||||
|
- Tested with various crop sizes and positions
|
||||||
|
|
||||||
|
Closes #XX (if issue exists)"
|
||||||
|
|
||||||
|
# Push when ready
|
||||||
|
git push origin feature/screenshot-cropping
|
||||||
|
```
|
||||||
|
|
||||||
|
**Total Time**:
|
||||||
|
- Planning: 10 min (free)
|
||||||
|
- Implementation: 5 min (1 task)
|
||||||
|
- Cleanup: 5 min (free)
|
||||||
|
- Testing: 15 min (manual)
|
||||||
|
- Documentation: 5 min (manual)
|
||||||
|
- **Total**: ~40 minutes, 1 task used
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting Copilot Issues
|
||||||
|
|
||||||
|
### Issue: Copilot Not Using copilot-instructions.md
|
||||||
|
|
||||||
|
**Check**:
|
||||||
|
1. File must be at `.github/copilot-instructions.md`
|
||||||
|
2. VS Code setting must reference it
|
||||||
|
3. Restart VS Code after creating file
|
||||||
|
|
||||||
|
**Fix**:
|
||||||
|
```json
|
||||||
|
// In .vscode/settings.json
|
||||||
|
{
|
||||||
|
"github.copilot.chat.codeGeneration.instructions": [
|
||||||
|
{
|
||||||
|
"file": ".github/copilot-instructions.md"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Copilot Suggests Wrong Patterns
|
||||||
|
|
||||||
|
**Cause**: Instructions too vague or missing context
|
||||||
|
|
||||||
|
**Fix**: Be more specific in prompts
|
||||||
|
```
|
||||||
|
# ❌ Vague
|
||||||
|
"Add screenshot feature"
|
||||||
|
|
||||||
|
# ✅ Specific
|
||||||
|
"Implement screenshot cropping using OffscreenCanvas API.
|
||||||
|
See Pattern 3 in docs/MIGRATION-PATTERNS.md.
|
||||||
|
Target file: src/background/index.ts around line 500."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Copilot Runs Out of Context
|
||||||
|
|
||||||
|
**Cause**: Trying to process too many files at once
|
||||||
|
|
||||||
|
**Fix**: Break into smaller tasks
|
||||||
|
```
|
||||||
|
# ❌ Too broad
|
||||||
|
"Implement all screenshot features"
|
||||||
|
|
||||||
|
# ✅ Focused
|
||||||
|
"Implement screenshot cropping in src/background/index.ts"
|
||||||
|
[Then in next task]
|
||||||
|
"Add screenshot selection UI improvements in src/content/screenshot.ts"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Generated Code Doesn't Follow Project Patterns
|
||||||
|
|
||||||
|
**Cause**: Copilot didn't read migration patterns
|
||||||
|
|
||||||
|
**Fix**: Reference specific patterns
|
||||||
|
```
|
||||||
|
"Implement X using Pattern Y from docs/MIGRATION-PATTERNS.md.
|
||||||
|
Use centralized logging (Logger.create).
|
||||||
|
Use theme system for UI."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced Tips
|
||||||
|
|
||||||
|
### Tip 1: Pre-Load Context in Chat
|
||||||
|
|
||||||
|
Before using Agent mode, load context in Chat Pane:
|
||||||
|
|
||||||
|
```
|
||||||
|
# In Chat Pane (free):
|
||||||
|
"Review docs/MIGRATION-PATTERNS.md Pattern 3"
|
||||||
|
"Review apps/web-clipper/background.js:393-427"
|
||||||
|
"Review docs/FEATURE-PARITY-CHECKLIST.md screenshot section"
|
||||||
|
|
||||||
|
# Then use Agent mode with:
|
||||||
|
"Now implement screenshot cropping as discussed"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefit**: Copilot has context loaded, better results.
|
||||||
|
|
||||||
|
### Tip 2: Use Multi-Turn Conversations
|
||||||
|
|
||||||
|
Instead of one complex prompt, break into conversation:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Turn 1 (Chat Pane):
|
||||||
|
"What's the best way to crop screenshots in MV3 service worker?"
|
||||||
|
|
||||||
|
# Turn 2:
|
||||||
|
"Show me example code using OffscreenCanvas"
|
||||||
|
|
||||||
|
# Turn 3:
|
||||||
|
"Now adapt that for our project structure.
|
||||||
|
Target: src/background/index.ts, use our Logger"
|
||||||
|
|
||||||
|
# Turn 4 (Agent Mode):
|
||||||
|
"Implement this in the project"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefit**: Iterative refinement, only uses 1 task at the end.
|
||||||
|
|
||||||
|
### Tip 3: Create Code Snippets for Common Patterns
|
||||||
|
|
||||||
|
In VS Code, create snippets (File → Preferences → User Snippets):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Message Handler": {
|
||||||
|
"prefix": "msg-handler",
|
||||||
|
"body": [
|
||||||
|
"chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {",
|
||||||
|
" (async () => {",
|
||||||
|
" try {",
|
||||||
|
" const result = await handle${1:Action}(message);",
|
||||||
|
" sendResponse({ success: true, data: result });",
|
||||||
|
" } catch (error) {",
|
||||||
|
" logger.error('${1:Action} handler error', error);",
|
||||||
|
" sendResponse({ success: false, error: error.message });",
|
||||||
|
" }",
|
||||||
|
" })();",
|
||||||
|
" return true;",
|
||||||
|
"});"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefit**: Common patterns without using any Copilot resources.
|
||||||
|
|
||||||
|
### Tip 4: Batch Similar Tasks
|
||||||
|
|
||||||
|
When implementing multiple similar features:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Instead of 3 separate Agent tasks:
|
||||||
|
Task 1: Add "Save Tabs" context menu
|
||||||
|
Task 2: Add "Save Tabs" handler
|
||||||
|
Task 3: Add "Save Tabs" to manifest
|
||||||
|
|
||||||
|
# Do in 1 Agent task:
|
||||||
|
"Implement complete 'Save Tabs' feature:
|
||||||
|
- Add context menu item
|
||||||
|
- Add message handler in background
|
||||||
|
- Update manifest permissions
|
||||||
|
- Add to docs/FEATURE-PARITY-CHECKLIST.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefit**: 3x fewer tasks used.
|
||||||
|
|
||||||
|
### Tip 5: Use Git Diffs for Review
|
||||||
|
|
||||||
|
Before committing, review with Copilot:
|
||||||
|
|
||||||
|
```
|
||||||
|
# In Chat Pane (free):
|
||||||
|
"Review my changes in src/background/index.ts.
|
||||||
|
Check for:
|
||||||
|
- Proper error handling
|
||||||
|
- Centralized logging
|
||||||
|
- Type safety
|
||||||
|
- Edge cases"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefit**: Code review without using a task.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Measuring Success
|
||||||
|
|
||||||
|
Track these metrics to optimize your workflow:
|
||||||
|
|
||||||
|
### Time Metrics
|
||||||
|
- **Planning time**: How long to prepare a good prompt
|
||||||
|
- **Implementation time**: How long Copilot takes
|
||||||
|
- **Cleanup time**: How much fixing needed after
|
||||||
|
- **Testing time**: How long to verify functionality
|
||||||
|
|
||||||
|
**Goal**: Minimize cleanup time through better prompts.
|
||||||
|
|
||||||
|
### Quality Metrics
|
||||||
|
- **First-time success rate**: Does implementation work immediately?
|
||||||
|
- **Error count**: How many TypeScript/runtime errors?
|
||||||
|
- **Test pass rate**: Does it work in all test scenarios?
|
||||||
|
|
||||||
|
**Goal**: >80% first-time success rate.
|
||||||
|
|
||||||
|
### Efficiency Metrics
|
||||||
|
- **Tasks used per feature**: How many Agent mode tasks?
|
||||||
|
- **Rework count**: How many times did you need to fix?
|
||||||
|
- **Documentation accuracy**: Are docs up to date?
|
||||||
|
|
||||||
|
**Goal**: <2 tasks per feature on average.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Completion Roadmap
|
||||||
|
|
||||||
|
Using this workflow, here's your path to completion:
|
||||||
|
|
||||||
|
### Phase 2: Screenshot Features (Current)
|
||||||
|
- [ ] Task 1: Implement screenshot cropping (~40 min, 1 task)
|
||||||
|
- [ ] Task 2: Verify/improve screenshot selection UI (~30 min, 1 task)
|
||||||
|
- [ ] Manual: Update documentation and testing (~20 min)
|
||||||
|
- **Total**: ~90 minutes, 2 tasks
|
||||||
|
|
||||||
|
### Phase 3: Image Processing
|
||||||
|
- [ ] Task 3: Apply image processing to all captures (~45 min, 1 task)
|
||||||
|
- [ ] Manual: Test with various image types (~30 min)
|
||||||
|
- [ ] Manual: Update documentation (~15 min)
|
||||||
|
- **Total**: ~90 minutes, 1 task
|
||||||
|
|
||||||
|
### Phase 4: Quality of Life Features
|
||||||
|
- [ ] Task 4: Implement "Save Tabs" (~40 min, 1 task)
|
||||||
|
- [ ] Task 5: Add "Already Visited" detection (~35 min, 1 task)
|
||||||
|
- [ ] Task 6: Add custom note text for links (~30 min, 1 task)
|
||||||
|
- [ ] Manual: Comprehensive testing (~60 min)
|
||||||
|
- [ ] Manual: Final documentation (~30 min)
|
||||||
|
- **Total**: ~3 hours, 3 tasks
|
||||||
|
|
||||||
|
### Phase 5: Polish & PR
|
||||||
|
- [ ] Manual: Full feature testing (~2 hours)
|
||||||
|
- [ ] Task 7: Final refactoring (if needed) (~30 min, 1 task)
|
||||||
|
- [ ] Manual: Write PR description (~30 min)
|
||||||
|
- [ ] Manual: Address review comments (varies)
|
||||||
|
- **Total**: ~3+ hours, 1 task
|
||||||
|
|
||||||
|
**Grand Total**:
|
||||||
|
- ~7-8 hours of development
|
||||||
|
- ~8 Agent mode tasks
|
||||||
|
- Ready for production PR
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Card
|
||||||
|
|
||||||
|
Print or keep open while developing:
|
||||||
|
|
||||||
|
```
|
||||||
|
╔════════════════════════════════════════════════════╗
|
||||||
|
║ COPILOT WORKFLOW QUICK REFERENCE ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ PLANNING (Free) ║
|
||||||
|
║ • Ctrl+Alt+I → Ask questions ║
|
||||||
|
║ • Review legacy code in chat ║
|
||||||
|
║ • Check docs/MIGRATION-PATTERNS.md ║
|
||||||
|
║ • Plan which files to modify ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ IMPLEMENTING (Uses Task) ║
|
||||||
|
║ • Copy template from COPILOT-TASK-TEMPLATES.md ║
|
||||||
|
║ • Fill in all blanks ║
|
||||||
|
║ • Paste to Agent mode ║
|
||||||
|
║ • Let it work ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ CLEANUP (Free) ║
|
||||||
|
║ • Ctrl+I → Fix TypeScript errors ║
|
||||||
|
║ • Ctrl+I → Add logging/types ║
|
||||||
|
║ • Shift+Alt+F → Format code ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ TESTING (Manual) ║
|
||||||
|
║ • chrome://extensions/ → Reload ║
|
||||||
|
║ • Test happy path + edge cases ║
|
||||||
|
║ • Check Logs page ║
|
||||||
|
║ • Verify consoles (SW, popup, content) ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ DOCUMENTING (Manual) ║
|
||||||
|
║ • Update docs/FEATURE-PARITY-CHECKLIST.md ║
|
||||||
|
║ • git commit -m "feat: description" ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ KEY FILES ║
|
||||||
|
║ • .github/copilot-instructions.md (auto-loaded) ║
|
||||||
|
║ • docs/FEATURE-PARITY-CHECKLIST.md (status) ║
|
||||||
|
║ • docs/MIGRATION-PATTERNS.md (code patterns) ║
|
||||||
|
║ • COPILOT-TASK-TEMPLATES.md (copy-paste) ║
|
||||||
|
╠════════════════════════════════════════════════════╣
|
||||||
|
║ ALWAYS INCLUDE IN PROMPTS ║
|
||||||
|
║ • Target files with line numbers ║
|
||||||
|
║ • Reference to relevant pattern/docs ║
|
||||||
|
║ • "Use centralized logging" ║
|
||||||
|
║ • "Update FEATURE-PARITY-CHECKLIST.md" ║
|
||||||
|
╚════════════════════════════════════════════════════╝
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Right Now**:
|
||||||
|
- Create the new file structure
|
||||||
|
- Copy content from artifacts to new files
|
||||||
|
- Review and understand the workflow
|
||||||
|
|
||||||
|
2. **Today**:
|
||||||
|
- Implement one small feature using the workflow
|
||||||
|
- Get comfortable with the templates
|
||||||
|
- Measure your time and task usage
|
||||||
|
|
||||||
|
3. **This Week**:
|
||||||
|
- Complete Phase 2 (Screenshot Features)
|
||||||
|
- Refine your prompts based on results
|
||||||
|
- Update templates if needed
|
||||||
|
|
||||||
|
4. **This Month**:
|
||||||
|
- Complete Phases 3-4
|
||||||
|
- Prepare pull request
|
||||||
|
- Document any workflow improvements
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: The goal is to work smarter, not harder. Good preparation = better results = fewer tasks used = faster completion!
|
||||||
|
|
||||||
|
Ready to implement! 🚀
|
||||||
Loading…
x
Reference in New Issue
Block a user