Thank you for your interest in contributing to TableCapture! This guide will help you get started with development.
- Getting Started
- Development Setup
- Running Tests
- Building a Release
- macOS Security & Permissions
- Architecture & Design Notes
- Submitting Changes
- macOS 12.3+ (Monterey or later)
- Xcode 14+ with Swift 5.5+
- Apple Silicon Mac (arm64)
git clone https://github.com/psenger/TableCapture.git
cd TableCaptureopen TableCapture.xcodeproj- Open
TableCapture.xcodeprojin Xcode - Select the
TableCapturescheme - Build and run (
⌘R) - Grant Screen Recording permission when prompted (System Settings > Privacy & Security > Screen Recording)
- Run all tests:
⌘U - Run a single test: Click the diamond icon next to the test function
xcodebuild test -project TableCapture.xcodeproj -scheme TableCapture -destination 'platform=macOS,arch=arm64'xcodebuild test -project TableCapture.xcodeproj -scheme TableCapture -destination 'platform=macOS,arch=arm64' -only-testing:TableCaptureTests/ComplexLayoutMultiColMultiRowTestsxcodebuild test -project TableCapture.xcodeproj -scheme TableCapture -destination 'platform=macOS,arch=arm64' -only-testing:TableCaptureTests/ComplexLayoutMultiColMultiRowTests/debugComplexLayoutxcodebuild test -project TableCapture.xcodeproj -scheme TableCapture -destination 'platform=macOS,arch=arm64' -only-testing:TableCaptureTests/ComplexLayoutMultiColMultiRowTests/testComplexLayoutMarkdown| Type | Framework | Location | Purpose |
|---|---|---|---|
| Unit Tests | Swift Testing | TableCaptureTests/ |
Test functions, logic, data transformations |
| UI Tests | XCTest + XCUITest | TableCaptureUITests/ |
Test user interactions and full app behavior |
For detailed testing documentation, see TESTING.md.
-
Build for Release in Xcode
- Select Product → Archive from the menu
- Wait for the archive to complete
- In the Organizer window, click Distribute App
- Choose Custom → Copy App and save to a location (e.g., Desktop)
-
Locate the .app Bundle
- Find
TableCapture.appin the exported location
- Find
-
Create a Professional DMG Installer (with drag-to-Applications)
# Navigate to the folder containing TableCapture.app cd /path/to/exported/app # Create Applications symlink next to your app ln -s /Applications Applications # Create the DMG containing both the app and Applications link hdiutil create -volname "TableCapture" \ -srcfolder . \ -ov -format UDZO \ ../TableCapture.dmg # Clean up the symlink rm Applications
-
Create a GitHub Release
- Go to your repository → Releases
- Click Draft a new release
- Create a new tag (e.g.,
v1.0.0) - Add release notes
- Upload the
TableCapture.dmgfile - Publish the release
When you rebuild the app, macOS often treats it as a "different" application:
- Code Signature Changes: Each build gets a new signature, and macOS ties permissions (like Screen Recording) to that signature
- Cached Permissions: The old permission is still registered but for the "old" app signature
- macOS Gets Confused: It sees your app as brand new and blocks it
# 1. Kill the app completely
killall TableCapture
# 2. Reset Screen Recording permissions for your app
tccutil reset ScreenCapture com.philipasenger.TableCapture
# 3. Rebuild and run in Xcode
# You'll need to re-grant permission in System Settings → Privacy & Security → Screen RecordingSet a stable code signing identity in Xcode:
- Go to your project settings → Signing & Capabilities
- Enable Automatically manage signing
- Make sure you have a consistent Team selected
- Ensure your Bundle Identifier never changes (e.g.,
com.yourname.TableCapture)
# Reset ALL TCC (privacy) permissions for your app - use carefully!
tccutil reset All com.philipasenger.TableCaptureNote: You'll need to re-grant Screen Recording permission after each rebuild during development. This is annoying but normal for macOS security.
When ready to distribute:
- Sign with a Developer ID certificate
- Notarize the app with Apple
This makes the signature consistent and permissions stick between launches for users.
TableCapture uses a dual OCR approach:
- No external dependencies
- Fast and accurate for most tables
- Uses
VNRecognizeTextRequestfor text recognition - Custom logic groups text by Y coordinate to detect rows
// Simplified flow:
1. Load image as CGImage
2. Create VNRecognizeTextRequest
3. Group VNRecognizedTextObservation by Y coordinate (rows)
4. Sort cells within each row by X coordinate (columns)
5. Convert to CSV/Markdown format- Used for challenging cases (e.g., single letters)
- Integrated via Tesseract-macOS wrapper
- See ACKNOWLEDGMENTS.md for library details
While img2table is specifically designed for table extraction, it was not chosen due to:
- External Python dependency
- Harder to install and bundle
- Would require shipping Python runtime
# Example of what img2table usage would look like:
from img2table.document import Image
from img2table.ocr import TesseractOCR
ocr = TesseractOCR(n_threads=1, lang="eng")
doc = Image(src=image_path)
tables = doc.extract_tables(ocr=ocr, implicit_rows=True, borderless_tables=True)- Fork the repository and create your branch from
main - Write tests for any new functionality
- Run all tests to ensure nothing is broken
- Update documentation if you've changed APIs or added features
- Submit a pull request with a clear description of changes
- Follow Swift best practices and existing code patterns
- Use meaningful variable and function names
- Add comments for complex logic
- Keep functions focused and small
- Use clear, descriptive commit messages
- Start with a verb (Add, Fix, Update, Remove, etc.)
- Reference issues when applicable (e.g., "Fix #123: ...")
If you have questions or need help:
- Open an issue on GitHub
- Check existing issues for similar questions
Thank you for contributing!