Initial project setup
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
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>
This commit is contained in:
557
docs/DEVELOPER.md
Normal file
557
docs/DEVELOPER.md
Normal file
@@ -0,0 +1,557 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user