- fix_path_env() now adds ~/.pyenv/shims (with PYENV_ROOT) before Homebrew paths so pyenv-managed yt-dlp (with pip-installed plugins) takes priority over Homebrew's bare yt-dlp binary - Also handles ~/.nvm, ~/.deno/bin, ~/.cargo/bin for broader coverage - check_pot_plugin uses lightweight 'yt-dlp -v' instead of network simulation for reliable plugin detection - Bump version to 0.1.1 Co-authored-by: Cursor <cursoragent@cursor.com>
4.8 KiB
Build Cleanup & Release Packaging
Date: 2026-09-22 Status: Approved
Overview
Resolve all build warnings and errors across the frontend (svelte-check, Vite) and backend (cargo), fix the failing test, and implement a release build script that produces a distributable GUI Video Clipper.app bundle.
Scope
Two workstreams:
- Warning/Error Cleanup — zero warnings from
npm run check,cargo build, andnpm test - Release Build Packaging —
scripts/build-release.shthat produces a signed.appindist/release/
1. TypeScript Errors (4)
All in vite.config.ts:
| Error | Root Cause | Fix |
|---|---|---|
Cannot find node:path |
Missing @types/node |
npm install -D @types/node, add "types": ["node"] to tsconfig.json |
Cannot find node:process |
Same | Same |
Cannot find node:url |
Same | Same |
test not in UserConfigExport |
defineConfig from vite doesn't know vitest's test field |
Import defineConfig from vitest/config instead |
2. Svelte A11y Warnings (19)
2a. Labels not associated with controls (9 in CaptionSettingsPanel.svelte)
Labels are siblings of their controls rather than wrapping them. Fix by either:
- Wrapping the
<input>/<select>inside the<label>element, or - Adding
idto the control andforto the label
Prefer the wrapping approach where layout allows.
2b. Dialog divs missing tabindex (4 files)
Add tabindex="-1" to <div role="dialog"> in PreferencesPanel, ExportDialog, AboutDialog, and <div role="listbox"> in ClipList. Makes them programmatically focusable without entering the tab order.
2c. Click handlers without key handlers (4 files)
Dialog overlay onclick={onClose} divs need corresponding onkeydown handlers. Add Escape key handling on the overlay. For ClipList's listbox container, add an onkeydown handler mirroring the container click logic.
2d. <video> without <track> (1 in VideoPlayer.svelte)
Add an empty <track kind="captions" default /> to the <video> element. Our custom caption overlay handles actual rendering.
2e. Resize handle (1 in App.svelte)
The resize handle <div> with role="separator" and onmousedown needs:
tabindex="0"for keyboard focusabilityonkeydownhandler for arrow key resizingaria-valuenow,aria-valuemin,aria-valuemaxattributes
3. Rust Dead Code Warnings (6)
Add #[allow(dead_code)] with explanatory comments:
| Warning | Location | Annotation Rationale |
|---|---|---|
ExportEvent::Error unused |
commands/export.rs:23 |
Reserved for future error-channel reporting |
DownloadEvent::Error unused |
commands/video.rs:23 |
Reserved for future error-channel reporting |
sanitize_vtt_for_ffmpeg unused |
clip_exporter.rs:10 |
Scaffolded for caption burn-in pipeline |
opacity_to_ass_back_colour unused |
clip_exporter.rs:204 |
Scaffolded for caption burn-in pipeline |
caption_style_to_force_style unused |
clip_exporter.rs:210 |
Scaffolded for caption burn-in pipeline |
SubtitleFormat.ext/.url unread |
video_resolver.rs:8-9 |
Fields required for serde deserialization |
4. Test Fix
File: tests/lib/stores/clips.test.ts
Test: "updates selected clip start when I is pressed"
The test calls markInPoint(5) on a clip spanning 10–20. With EDIT_TOLERANCE of 0.5s, time 5 is outside the clip boundary (needs ≥ 9.5). The test was written before the tolerance check existed.
Fix: Change markInPoint(5) to markInPoint(12) (inside the clip, within tolerance). Update the assertion to expect(getClips()[0].startTime).toBe(12). This verifies the edit actually changes the start time (unlike markInPoint(10) which would pass trivially since start is already 10).
After fix: 31/31 tests pass.
5. Release Build Script
5a. scripts/build-release.sh
A shell script that:
- Reads
VERSIONfrom the project root - Runs
npm install - Runs
npx tauri build(builds frontend + Rust + bundles .app and .dmg) - Ad-hoc code signs the
.app:codesign --force --deep -s - <path> - Copies
.app(and.dmgif built) todist/release/ - Prints summary: version, output path, bundle size
5b. Configuration changes
tauri.conf.json: Change"targets": "all"to"targets": ["app", "dmg"].gitignore: Adddist/package.json: Add"release": "bash scripts/build-release.sh"
5c. README update
Add a "Release Build" section documenting npm run release and its outputs.
Verification
After all changes:
npm run checkexits 0 with 0 errors, 0 warningscargo build 2>&1 | grep warningreturns nothingnpm testshows 31/31 passnpm run releaseproducesdist/release/GUI Video Clipper.app- The
.applaunches without the Gatekeeper right-click workaround