This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Philosophy: This is a fork intended for upstream contribution. Changes must blend seamlessly with the existing codebase.
Implementation implications:
- Follow existing naming conventions, formatting, and code style exactly
- Add new symbols to
supportedLatexSymbolsusing the same pattern as existing entries - Use existing atom types (
.relation,.binaryOperator,.ordinary,.variable) appropriately - Maintain thread-safety patterns (use
NSLockwhere existing code does) - Do not refactor existing code unless absolutely required for a feature
- Preserve all existing tests and ensure they continue to pass
Philosophy: Each feature should be a self-contained, reviewable unit ready for upstream PR.
Implementation implications:
- Work on one logical feature at a time (e.g., "add slanted inequalities", "add Greek variants")
- Each feature must include: code changes, unit tests, documentation updates
- Update
MISSING_FEATURES.mdwhen implementing features listed there - Update
README.mdwhen adding user-facing capabilities - Create atomic commits for each logical change
- Create PRs that can be reviewed and merged independently
Philosophy: PRs target the upstream repository for contribution back to the main project.
Implementation implications:
- PRs must target
mgriebling/SwiftMath(upstream), not our own fork - PRs are created from the
devbranch, NOT from feature branches - PR body must use plain markdown only - NO ANSI escape codes or terminal formatting
- ALWAYS use --body-file with a clean markdown file, never use --body with heredoc/string
- After creating upstream PR, merge dev to main locally to keep fork in sync
- Continue development on dev branch for next feature
- Verify PR content is clean before finishing (use
gh pr view --json body)
PR Creation Process:
- Merge feature branch to dev
- Write PR body to a temporary file (tmp/pr_body.md)
- Verify file contains only plain markdown
- Create PR:
gh pr create --repo mgriebling/SwiftMath --base main --head ChrisGVE:dev --title "..." --body-file tmp/pr_body.md - Verify PR:
gh pr view <number> --repo mgriebling/SwiftMath --json body - Delete temporary file
- Merge dev to main locally and push
Philosophy: The fork uses a distinct package name on main for independent publishing, while keeping the original name on development branches for upstream compatibility.
Implementation implications:
- main branch: Package.swift uses
name: "ExtendedSwiftMath"(for publishing the fork) - dev and feature branches: Package.swift uses
name: "SwiftMath"(for upstream compatibility) - The library/product name remains
SwiftMathon all branches for drop-in compatibility - When merging to main, the Package.swift name change is part of the main-branch-only configuration
- PRs to upstream use the dev branch which has
name: "SwiftMath"matching upstream
# Build the package
swift build
# Run all tests
swift test
# Run a single test class
swift test --filter MTMathListBuilderTests
# Run a specific test method
swift test --filter MTMathListBuilderTests.testBuilderExtendedSwiftMath is a Swift implementation of LaTeX math rendering for iOS (11+) and macOS (12+). The package name is ExtendedSwiftMath on main (for fork publishing) but SwiftMath on dev/feature branches (for upstream compatibility). The product/module is always SwiftMath for drop-in compatibility.
LaTeX String → MTMathList → MTDisplay → Rendered Output
-
MTMathListBuilder (
MathRender/MTMathListBuilder.swift) - Parses LaTeX strings into an abstract syntax tree (MTMathList). Handles math delimiters ($...$,$$...$$,\(...\),\[...\]), commands, environments. -
MTMathList (
MathRender/MTMathList.swift) - The AST representation. ContainsMTMathAtomobjects representing mathematical elements (variables, operators, fractions, radicals, etc.). Each atom has aMTMathAtomTypethat determines rendering and spacing. -
MTTypesetter (
MathRender/MTTypesetter.swift) - ConvertsMTMathListtoMTDisplaytree using TeX typesetting rules. Handles inter-element spacing, script positioning, and line breaking. -
MTDisplay (
MathRender/MTMathListDisplay.swift) - The display tree that knows how to draw itself via CoreText/CoreGraphics. -
MTMathUILabel (
MathRender/MTMathUILabel.swift) - The UIView/NSView that hosts the rendered math. Entry point for most usage.
Located in MathBundle/:
- MathFont (
MathFont.swift) - Enum of 12 bundled OTF math fonts with thread-safe loading viaBundleManager - MTFont (
MathRender/MTFont.swift) - Font wrapper with math metrics access - MTFontMathTable (
MathRender/MTFontMathTable.swift) - Parses OpenType MATH table data from.plistfiles
Each font has a .otf file and a companion .plist containing math metrics (generated via included Python script).
- MTMathAtomFactory (
MathRender/MTMathAtomFactory.swift) - Factory for creating atoms, includes command mappings (aliases,delimiters,accents,supportedLatexSymbols) - MTFontManager (
MathRender/MTFontManager.swift) - Manages font instances and defaults
Cross-platform types defined in MathRender/:
MTBezierPath- UIBezierPath/NSBezierPathMTColor- UIColor/NSColorMTView- UIView/NSView (via#if os(iOS)conditionals)
The typesetter supports automatic line breaking via preferredMaxLayoutWidth on MTMathUILabel. Uses interatom breaking (breaks between atoms) as primary mechanism, with Unicode word boundary breaking as fallback.
Import Task Master's development workflow commands and guidelines, treat as if import is in the main CLAUDE.md file. @./.taskmaster/CLAUDE.md