Some checks failed
Build and Test YT2AI Bookmarklet / build-and-test (16.x) (push) Has been cancelled
Build and Test YT2AI Bookmarklet / build-and-test (18.x) (push) Has been cancelled
Build and Test YT2AI Bookmarklet / build-and-test (20.x) (push) Has been cancelled
Build and Test YT2AI Bookmarklet / release (push) Has been cancelled
Build and Test YT2AI Bookmarklet / security-scan (push) Has been cancelled
Add project structure with package.json, source code, tests, documentation, and GitHub workflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
557 lines
15 KiB
Markdown
557 lines
15 KiB
Markdown
# YT2AI Developer Guide
|
|
|
|
## Development Setup
|
|
|
|
### Prerequisites
|
|
- **Node.js 16+** - For build tools and testing
|
|
- **npm 7+** - Package management
|
|
- **Android device** with Chrome 90+ - For testing
|
|
- **Text editor** with JavaScript support (VS Code recommended)
|
|
|
|
### Initial Setup
|
|
```bash
|
|
# Clone repository
|
|
git clone https://github.com/yt2ai/yt2ai-bookmarklet.git
|
|
cd yt2ai-bookmarklet
|
|
|
|
# Install dependencies
|
|
npm install
|
|
|
|
# Verify setup
|
|
npm run verify
|
|
```
|
|
|
|
### Development Workflow
|
|
|
|
#### 1. Code Development
|
|
```bash
|
|
# Start file watching for continuous builds
|
|
npm run build:watch
|
|
|
|
# Run tests in watch mode
|
|
npm run test:watch
|
|
|
|
# Check code quality
|
|
npm run lint
|
|
npm run format:check
|
|
```
|
|
|
|
#### 2. Testing Cycle
|
|
```bash
|
|
# Run all tests
|
|
npm test
|
|
|
|
# Run with coverage
|
|
npm run test:coverage
|
|
|
|
# Build development version
|
|
npm run build:dev
|
|
|
|
# Test manually on device using dist/bookmarklet-debug.js
|
|
```
|
|
|
|
#### 3. Production Build
|
|
```bash
|
|
# Full verification pipeline
|
|
npm run verify
|
|
|
|
# Production build
|
|
npm run build
|
|
|
|
# Verify output in dist/bookmarklet.min.js
|
|
```
|
|
|
|
## Project Architecture
|
|
|
|
### Directory Structure
|
|
```
|
|
yt2ai-bookmarklet/
|
|
├── src/
|
|
│ ├── bookmarklet.js # Main entry point (all code currently here)
|
|
│ ├── core/ # Future: Core functionality modules
|
|
│ ├── ui/ # Future: UI components
|
|
│ └── utils/ # Future: Utility modules
|
|
├── build/
|
|
│ ├── webpack.config.js # Build configuration
|
|
│ └── README.md # Build system docs
|
|
├── tests/
|
|
│ ├── unit/core/ # Unit tests
|
|
│ ├── integration/ # Integration tests
|
|
│ ├── manual/ # Manual test protocols
|
|
│ └── setup.js # Jest configuration
|
|
├── docs/ # Documentation
|
|
├── dist/ # Build outputs
|
|
└── .github/workflows/ # CI/CD configuration
|
|
```
|
|
|
|
### Current Implementation
|
|
All functionality is currently implemented in `src/bookmarklet.js` as a single file. This monolithic approach is intentional for the bookmarklet format, but the architecture supports future modularization.
|
|
|
|
## Code Architecture
|
|
|
|
### Main Components
|
|
|
|
#### Environment Detection
|
|
```javascript
|
|
const environment = {
|
|
isDevelopment: boolean, // Debug mode detection
|
|
isMobile: boolean, // Mobile device detection
|
|
isAndroid: boolean, // Android specific detection
|
|
isChrome: boolean // Chrome browser detection
|
|
};
|
|
```
|
|
|
|
#### YouTube Context Validation
|
|
```javascript
|
|
function validateYouTubeContext() {
|
|
// Validates hostname and extracts video ID
|
|
// Supports: youtube.com/watch, youtu.be, shorts, embed
|
|
// Returns: { videoId, url }
|
|
}
|
|
```
|
|
|
|
#### Mobile Overlay System
|
|
```javascript
|
|
class MobileOverlay {
|
|
// Mobile-optimized modal dialogs
|
|
// Features: 44px touch targets, responsive design
|
|
// Types: loading, error, success, info
|
|
}
|
|
```
|
|
|
|
#### Error Handling Framework
|
|
```javascript
|
|
class BookmarkletError extends Error {
|
|
// Enhanced error with context and recovery info
|
|
// Types: network, api, parsing, captcha, validation
|
|
// Severity: low, medium, high, critical
|
|
}
|
|
```
|
|
|
|
#### State Management
|
|
```javascript
|
|
const stateManager = {
|
|
// Module pattern for state management
|
|
// Tracks: initialization, processing, video context
|
|
// No persistence - stateless operation
|
|
}
|
|
```
|
|
|
|
## Coding Standards
|
|
|
|
### JavaScript Guidelines
|
|
|
|
#### Universal Rules
|
|
1. **Always use `const` by default, `let` when reassignment needed**
|
|
```javascript
|
|
const videoId = extractVideoId(url); // ✅ Preferred
|
|
let retryCount = 0; // ✅ When reassignment needed
|
|
var oldStyle = 'avoid'; // ❌ Avoid var
|
|
```
|
|
|
|
2. **Prefix all CSS classes with `yt2ai-`**
|
|
```javascript
|
|
element.className = 'yt2ai-overlay yt2ai-loading'; // ✅ Correct
|
|
element.className = 'overlay loading'; // ❌ Conflicts possible
|
|
```
|
|
|
|
3. **Use `z-index: 999999` or higher for overlays**
|
|
```javascript
|
|
const styles = `
|
|
.yt2ai-overlay {
|
|
z-index: 999999; /* ✅ Above YouTube's interface */
|
|
}
|
|
`;
|
|
```
|
|
|
|
4. **Handle all async operations with try/catch**
|
|
```javascript
|
|
// ✅ Proper error handling
|
|
try {
|
|
const result = await apiCall();
|
|
return result;
|
|
} catch (error) {
|
|
errorReporter.report(error, 'api-call');
|
|
throw new BookmarkletError('API call failed', 'network', true);
|
|
}
|
|
```
|
|
|
|
#### Mobile-Specific Rules
|
|
1. **All touch targets must be minimum 44px**
|
|
```javascript
|
|
const styles = `
|
|
.yt2ai-close-btn {
|
|
min-width: 44px; /* ✅ WCAG AA compliance */
|
|
min-height: 44px;
|
|
}
|
|
`;
|
|
```
|
|
|
|
2. **Use `touchend` events, not `click` for mobile optimization**
|
|
```javascript
|
|
const eventType = environment.isMobile ? 'touchend' : 'click';
|
|
button.addEventListener(eventType, handler);
|
|
```
|
|
|
|
3. **Always prevent body scroll when showing modals**
|
|
```javascript
|
|
show() {
|
|
document.body.appendChild(this.element);
|
|
document.body.style.overflow = 'hidden'; // ✅ Prevent scroll
|
|
}
|
|
```
|
|
|
|
#### Bookmarklet-Specific Rules
|
|
1. **Never rely on external dependencies in production**
|
|
```javascript
|
|
// ✅ Self-contained
|
|
const helper = (function() {
|
|
// All code inline
|
|
})();
|
|
|
|
// ❌ External dependency
|
|
import { helper } from 'external-lib';
|
|
```
|
|
|
|
2. **Always namespace global variables with `__YT2AI_`**
|
|
```javascript
|
|
window.__YT2AI_INITIALIZED__ = true; // ✅ Namespaced
|
|
window.__YT2AI_VERSION__ = '1.0.0'; // ✅ Namespaced
|
|
window.initialized = true; // ❌ Generic name
|
|
```
|
|
|
|
3. **Always validate YouTube context before execution**
|
|
```javascript
|
|
function initialize() {
|
|
if (!window.location.hostname.includes('youtube.com')) {
|
|
throw new BookmarkletError('YouTube page required');
|
|
}
|
|
}
|
|
```
|
|
|
|
## Testing Guidelines
|
|
|
|
### Unit Testing
|
|
|
|
#### Test Structure (Arrange-Act-Assert)
|
|
```javascript
|
|
test('should extract video ID from YouTube URL', () => {
|
|
// Arrange
|
|
const testUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
|
|
|
|
// Act
|
|
const videoId = extractVideoId(testUrl);
|
|
|
|
// Assert
|
|
expect(videoId).toBe('dQw4w9WgXcQ');
|
|
});
|
|
```
|
|
|
|
#### Mobile Environment Mocking
|
|
```javascript
|
|
const mockMobileEnvironment = () => {
|
|
Object.defineProperty(navigator, 'userAgent', {
|
|
value: 'Mozilla/5.0 (Linux; Android 10; SM-G975F) Chrome/91.0'
|
|
});
|
|
Object.defineProperty(window, 'innerWidth', { value: 375 });
|
|
};
|
|
```
|
|
|
|
#### YouTube Context Mocking
|
|
```javascript
|
|
const mockYouTubeUrl = (videoId = 'dQw4w9WgXcQ') => {
|
|
Object.defineProperty(window, 'location', {
|
|
value: {
|
|
href: `https://www.youtube.com/watch?v=${videoId}`,
|
|
hostname: 'youtube.com'
|
|
}
|
|
});
|
|
};
|
|
```
|
|
|
|
### Integration Testing
|
|
- Test real YouTube URLs with various formats
|
|
- Verify API integration with external services
|
|
- Test mobile device compatibility
|
|
|
|
### Manual Testing Protocol
|
|
1. **Device Testing:**
|
|
- Test on actual Android devices
|
|
- Various Chrome versions (90+)
|
|
- Different screen sizes and orientations
|
|
|
|
2. **Scenario Testing:**
|
|
- Different video types (regular, shorts, embedded)
|
|
- Various network conditions (3G, 4G, WiFi)
|
|
- Error scenarios (no subtitles, API down, CAPTCHA)
|
|
|
|
## Mobile Development
|
|
|
|
### Responsive Design Principles
|
|
```javascript
|
|
// Mobile-first CSS approach
|
|
const mobileStyles = `
|
|
.yt2ai-component {
|
|
/* Mobile base styles */
|
|
font-size: 14px;
|
|
padding: 12px;
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
.yt2ai-component {
|
|
/* Desktop enhancements */
|
|
font-size: 16px;
|
|
padding: 16px;
|
|
}
|
|
}
|
|
`;
|
|
```
|
|
|
|
### Touch Optimization
|
|
```javascript
|
|
// Touch-friendly event handling
|
|
const handleTouch = (e) => {
|
|
e.preventDefault(); // Prevent scroll bounce
|
|
e.stopPropagation(); // Prevent event bubbling
|
|
};
|
|
|
|
element.addEventListener('touchend', handleTouch, { passive: false });
|
|
```
|
|
|
|
### Mobile Network Handling
|
|
```javascript
|
|
// Adaptive timeouts for mobile networks
|
|
const timeout = environment.isMobile ? 30000 : 15000;
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
```
|
|
|
|
## Build System
|
|
|
|
### Webpack Configuration
|
|
The build system transforms modular development code into single-file bookmarklet distribution:
|
|
|
|
```javascript
|
|
// webpack.config.js highlights
|
|
module.exports = {
|
|
entry: 'src/bookmarklet.js',
|
|
output: {
|
|
path: 'dist/',
|
|
filename: isProduction ? '[name].min.js' : '[name].debug.js'
|
|
},
|
|
plugins: [
|
|
new BookmarkletPlugin(), // Wraps in javascript:(function(){...})()
|
|
new InlineCSSPlugin() // Inlines all CSS
|
|
]
|
|
};
|
|
```
|
|
|
|
### Custom Build Plugins
|
|
|
|
#### BookmarkletPlugin
|
|
- Wraps output in `javascript:(function(){code})()` format
|
|
- Creates both prefixed and readable versions
|
|
- Handles IIFE execution context properly
|
|
|
|
#### InlineCSSPlugin
|
|
- Ensures no separate CSS files
|
|
- All styles embedded as JavaScript template literals
|
|
- Maintains mobile-optimized CSS structure
|
|
|
|
### Build Outputs
|
|
```bash
|
|
dist/
|
|
├── bookmarklet.min.js # Production (8.7KB) - ready for distribution
|
|
├── bookmarklet-readable.js # Production readable version
|
|
├── bookmarklet-debug.js # Development (13.6KB) - with debugging
|
|
└── bookmarklet-debug-readable.js # Development readable version
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### Error Classification System
|
|
```javascript
|
|
const ErrorTypes = {
|
|
NETWORK: 'network', // Connection issues
|
|
API: 'api', // External service errors
|
|
PARSING: 'parsing', // Data processing errors
|
|
CAPTCHA: 'captcha', // Human verification required
|
|
VALIDATION: 'validation', // Input validation failures
|
|
UNKNOWN: 'unknown' // Unclassified errors
|
|
};
|
|
|
|
const ErrorSeverity = {
|
|
LOW: 'low', // Recoverable, minimal impact
|
|
MEDIUM: 'medium', // May affect functionality
|
|
HIGH: 'high', // Significant impact
|
|
CRITICAL: 'critical' // System-breaking
|
|
};
|
|
```
|
|
|
|
### Error Reporting Pattern
|
|
```javascript
|
|
try {
|
|
stateManager.advanceToStep('subtitle-extraction');
|
|
const result = await apiService.extractSubtitles(videoId);
|
|
stateManager.completeStep('subtitle-extraction');
|
|
return result.data;
|
|
} catch (error) {
|
|
const bookmarkletError = new BookmarkletError(
|
|
error.message,
|
|
ErrorTypes.API,
|
|
true, // recoverable
|
|
ErrorSeverity.MEDIUM
|
|
);
|
|
|
|
stateManager.failStep('subtitle-extraction', bookmarkletError);
|
|
errorReporter.report(bookmarkletError, 'subtitle-extraction');
|
|
throw bookmarkletError;
|
|
}
|
|
```
|
|
|
|
## Performance Optimization
|
|
|
|
### Memory Management
|
|
```javascript
|
|
// Always cleanup resources
|
|
function cleanup() {
|
|
// Remove DOM elements
|
|
document.querySelectorAll('.yt2ai-overlay').forEach(el => el.remove());
|
|
|
|
// Clear event listeners (handled by element removal)
|
|
|
|
// Reset global state
|
|
stateManager.reset();
|
|
|
|
// Clear initialization flag
|
|
window.__YT2AI_INITIALIZED__ = false;
|
|
}
|
|
```
|
|
|
|
### Network Optimization
|
|
```javascript
|
|
// Adaptive timeout based on device and connection
|
|
const getTimeout = () => {
|
|
const base = environment.isMobile ? 30000 : 15000;
|
|
const connection = navigator.connection;
|
|
|
|
if (connection && connection.effectiveType === 'slow-2g') {
|
|
return base * 2;
|
|
}
|
|
|
|
return base;
|
|
};
|
|
```
|
|
|
|
### Bundle Size Optimization
|
|
- **Tree shaking:** Webpack eliminates unused code
|
|
- **Minification:** Terser with mobile-optimized settings
|
|
- **No polyfills:** Target modern Chrome 90+ features
|
|
- **Inline everything:** No external resources
|
|
|
|
## Debugging
|
|
|
|
### Development Mode
|
|
Add `?debug=true` to any YouTube URL:
|
|
```
|
|
https://www.youtube.com/watch?v=VIDEO_ID&debug=true
|
|
```
|
|
|
|
This enables:
|
|
- Detailed console logging
|
|
- Performance monitoring
|
|
- Error stack traces
|
|
- Memory usage tracking
|
|
- Network request logging
|
|
|
|
### Debug Utilities
|
|
```javascript
|
|
// Available in development mode
|
|
window.__YT2AI__ = {
|
|
initialize, // Manual initialization
|
|
cleanup, // Manual cleanup
|
|
stateManager, // State inspection
|
|
environment, // Environment info
|
|
logger, // Logging controls
|
|
MobileOverlay // UI testing
|
|
};
|
|
```
|
|
|
|
### Console Logging Levels
|
|
```javascript
|
|
const logger = {
|
|
debug: environment.isDevelopment ? console.log : () => {},
|
|
info: console.info.bind(console, '[YT2AI:INFO]'),
|
|
warn: console.warn.bind(console, '[YT2AI:WARN]'),
|
|
error: console.error.bind(console, '[YT2AI:ERROR]')
|
|
};
|
|
```
|
|
|
|
## Deployment
|
|
|
|
### Release Process
|
|
1. **Version bump** in package.json
|
|
2. **Full verification** with `npm run verify`
|
|
3. **Create GitHub release** with build artifacts
|
|
4. **Update documentation** for any breaking changes
|
|
5. **Test on actual devices** before public announcement
|
|
|
|
### CI/CD Pipeline
|
|
GitHub Actions automatically:
|
|
- **Runs tests** on Node.js 16, 18, 20
|
|
- **Builds production version**
|
|
- **Validates bundle size** (<10KB limit)
|
|
- **Checks bookmarklet format** (javascript: prefix)
|
|
- **Creates releases** for main branch pushes
|
|
- **Security scanning** with CodeQL
|
|
|
|
### Distribution
|
|
- **GitHub Releases:** Primary distribution channel
|
|
- **Documentation site:** Installation guides and tutorials
|
|
- **QR codes:** Mobile-friendly installation method
|
|
|
|
## Common Issues
|
|
|
|
### Build Issues
|
|
1. **"Cannot resolve module"** - Check import paths and file existence
|
|
2. **"Bundle too large"** - Review imports and webpack config
|
|
3. **"Babel transformation failed"** - Check target browser compatibility
|
|
|
|
### Runtime Issues
|
|
1. **"Bookmarklet not working"** - Verify javascript: prefix installation
|
|
2. **"YouTube not detected"** - Check URL format and hostname validation
|
|
3. **"Network timeout"** - Review mobile network handling and retry logic
|
|
|
|
### Testing Issues
|
|
1. **"Jest environment errors"** - Check jsdom setup and mocks
|
|
2. **"Mobile tests failing"** - Verify environment mocking
|
|
3. **"Async test timeouts"** - Increase Jest timeout for slow operations
|
|
|
|
## Contributing
|
|
|
|
### Code Review Checklist
|
|
- [ ] **Mobile compatibility** tested on actual devices
|
|
- [ ] **Error handling** comprehensive with proper types
|
|
- [ ] **Performance impact** measured and within limits
|
|
- [ ] **Test coverage** maintained at 80%+ for new code
|
|
- [ ] **Documentation** updated for user-facing changes
|
|
- [ ] **Build size** impact acceptable (<10KB limit)
|
|
|
|
### Pull Request Process
|
|
1. **Create feature branch** from main
|
|
2. **Implement changes** following coding standards
|
|
3. **Add/update tests** maintaining coverage
|
|
4. **Update documentation** for any user-facing changes
|
|
5. **Test on mobile devices** - Android Chrome priority
|
|
6. **Submit PR** with detailed description
|
|
|
|
### Development Tips
|
|
- **Test early and often** on real mobile devices
|
|
- **Keep bundle size in mind** - every byte matters for mobile
|
|
- **Prioritize error handling** - mobile networks are unreliable
|
|
- **Think mobile-first** - desktop is secondary consideration
|
|
- **Document edge cases** - mobile browsers have unique behaviors
|
|
|
|
---
|
|
|
|
For questions or clarification, please open a GitHub issue or discussion. |