{"id":50801768,"url":"https://github.com/mgriebling/SwiftMath","last_synced_at":"2026-06-30T03:00:36.945Z","repository":{"id":67642181,"uuid":"586241296","full_name":"mgriebling/SwiftMath","owner":"mgriebling","description":"SwiftMath provides a full Swift implementation of iosMath for displaying beautifully rendered math equations in iOS and MacOS applications. It typesets formulae written using LaTeX math mode in a UILabel equivalent class.","archived":false,"fork":false,"pushed_at":"2026-06-29T11:29:42.000Z","size":6117,"stargazers_count":380,"open_issues_count":10,"forks_count":73,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-06-29T13:22:40.986Z","etag":null,"topics":["ios","iosmath","latex","mac","math","swift","typeset"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mgriebling.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-07T12:53:12.000Z","updated_at":"2026-06-29T11:29:47.000Z","dependencies_parsed_at":"2023-03-15T01:05:32.175Z","dependency_job_id":"a3b9e7e0-f94e-4c90-bad0-113a9ce87e1b","html_url":"https://github.com/mgriebling/SwiftMath","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/mgriebling/SwiftMath","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgriebling%2FSwiftMath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgriebling%2FSwiftMath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgriebling%2FSwiftMath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgriebling%2FSwiftMath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mgriebling","download_url":"https://codeload.github.com/mgriebling/SwiftMath/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgriebling%2FSwiftMath/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34950330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","iosmath","latex","mac","math","swift","typeset"],"created_at":"2026-06-12T21:00:28.531Z","updated_at":"2026-06-30T03:00:36.936Z","avatar_url":"https://github.com/mgriebling.png","language":"Swift","funding_links":[],"categories":["Utilities and Extensions"],"sub_categories":[],"readme":"# SwiftMath\n\n`SwiftMath` provides a full Swift implementation of [iosMath](https://travis-ci.org/kostub/iosMath) \nfor displaying beautifully rendered math equations in iOS and MacOS applications. It typesets formulae written \nusing LaTeX in a `UILabel` equivalent class. It uses the same typesetting rules as LaTeX and\nso the equations are rendered exactly as LaTeX would render them.\n\nPlease also check out [SwiftMathDemo](https://github.com/mgriebling/SwiftMathDemo.git) for examples of how to use `SwiftMath`\nfrom SwiftUI.  \n\n`SwiftMath` is similar to [MathJax](https://www.mathjax.org) or\n[KaTeX](https://github.com/Khan/KaTeX) for the web but for native iOS or MacOS\napplications without having to use a `UIWebView` and Javascript. More\nimportantly, it is significantly faster than using a `UIWebView`.\n\n`SwiftMath` is a Swift translation of the latest `iosMath` v0.9.5 release but includes bug fixes\nand enhancements like a new \\lbar (lambda bar) character and cyrillic alphabet support.\nThe original `iosMath` test suites have also been translated to Swift and run without errors.\nNote: Error test conditions are ignored to avoid tagging everything with silly `throw`s.\nPlease let me know of any bugs or bug fixes that you find. \n\n`SwiftMath` prepackages everything needed for direct access via the Swift Package Manager.\n\n## Examples\nHere are screenshots of some formulae that were rendered with this library:\n\n```LaTeX\nx = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}\n```\n\n![Quadratic Formula](img/quadratic-light.png#gh-light-mode-only) \n![Quadratic Formula](img/quadratic-dark.png#gh-dark-mode-only) \n\n```LaTeX\nf(x) = \\int\\limits_{-\\infty}^\\infty\\!\\hat f(\\xi)\\,e^{2 \\pi i \\xi x}\\,\\mathrm{d}\\xi\n```\n\n![Calculus](img/calculus-light.png#gh-light-mode-only) \n![Calculus](img/calculus-dark.png#gh-dark-mode-only) \n\n```LaTeX\n\\frac{1}{n}\\sum_{i=1}^{n}x_i \\geq \\sqrt[n]{\\prod_{i=1}^{n}x_i}\n```\n\n![AM-GM](img/amgm-light.png#gh-light-mode-only) \n![AM-GM](img/amgm-dark.png#gh-dark-mode-only) \n\n```LaTex\n\\frac{1}{\\left(\\sqrt{\\phi \\sqrt{5}}-\\phi\\\\right) e^{\\frac25 \\pi}}\n= 1+\\frac{e^{-2\\pi}} {1 +\\frac{e^{-4\\pi}} {1+\\frac{e^{-6\\pi}} {1+\\frac{e^{-8\\pi}} {1+\\cdots} } } }\n```\n\n![Ramanujan Identity](img/ramanujan-light.png#gh-light-mode-only) \n![Ramanujan Identity](img/ramanujan-dark.png#gh-dark-mode-only) \n\nMore examples are included in [EXAMPLES](EXAMPLES.md)\n\n## Fonts\nHere are previews of the included fonts:\n\n![](img/FontsPreview.png#gh-dark-mode-only) \n![](img/FontsPreviewLight.png#gh-light-mode-only) \n \n## Requirements\n`SwiftMath` works on iOS 11+ or MacOS 12+. It depends\non the following Apple frameworks:\n\n* Foundation.framework\n* CoreGraphics.framework\n* QuartzCore.framework\n* CoreText.framework\n\nAdditionally for iOS it requires:\n* UIKit.framework\n\nAdditionally for MacOS it requires:\n* AppKit.framework\n\n## Installation\n\n### Swift Package\n\n`SwiftMath` is available from [SwiftMath](https://github.com/mgriebling/SwiftMath.git). \nTo use it in your code, just add the https://github.com/mgriebling/SwiftMath.git path to\nXCode's package manager.\n\n## Usage\n\nThe library provides a class `MTMathUILabel` which is a `UIView` that\nsupports rendering math equations. To display an equation simply create\nan `MTMathUILabel` as follows:\n\n```swift\n\nimport SwiftMath\n\nlet label = MTMathUILabel()\nlabel.latex = \"x = \\\\frac{-b \\\\pm \\\\sqrt{b^2-4ac}}{2a}\"\n\n```\nAdding `MTMathUILabel` as a sub-view of your `UIView` will render the\nquadratic formula example shown above.\n\nThe following code creates a SwiftUI component called `MathView` encapsulating the MTMathUILabel:\n\n```swift\nimport SwiftUI\nimport SwiftMath\n\nstruct MathView: UIViewRepresentable {\n    var equation: String\n    var font: MathFont = .latinModernFont\n    var textAlignment: MTTextAlignment = .center\n    var fontSize: CGFloat = 30\n    var labelMode: MTMathUILabelMode = .text\n    var insets: MTEdgeInsets = MTEdgeInsets()\n\n    func makeUIView(context: Context) -\u003e MTMathUILabel {\n        let view = MTMathUILabel()\n        view.setContentHuggingPriority(.required, for: .vertical)\n        view.setContentCompressionResistancePriority(.required, for: .vertical)\n        return view\n    }\n\n    func updateUIView(_ view: MTMathUILabel, context: Context) {\n        view.latex = equation\n        let font = MTFontManager().font(withName: font.rawValue, size: fontSize)\n        font?.fallbackFont = UIFont.systemFont(ofSize: fontSize)\n        view.font = font\n        view.textAlignment = textAlignment\n        view.labelMode = labelMode\n        view.textColor = MTColor(Color.primary)\n        view.contentInsets = insets\n        view.invalidateIntrinsicContentSize()\n    }\n\n    func sizeThatFits(_ proposal: ProposedViewSize, uiView: MTMathUILabel, context: Context) -\u003e CGSize? {\n        // Enable line wrapping by passing proposed width to the label\n        if let width = proposal.width, width.isFinite, width \u003e 0 {\n            uiView.preferredMaxLayoutWidth = width\n            let size = uiView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))\n            return size\n        }\n        return nil\n    }\n}\n```\n\nFor code that works with SwiftUI running natively under MacOS use the following:\n\n```swift\nimport SwiftUI\nimport SwiftMath\n\nstruct MathView: NSViewRepresentable {\n    var equation: String\n    var font: MathFont = .latinModernFont\n    var textAlignment: MTTextAlignment = .center\n    var fontSize: CGFloat = 30\n    var labelMode: MTMathUILabelMode = .text\n    var insets: MTEdgeInsets = MTEdgeInsets()\n\n    func makeNSView(context: Context) -\u003e MTMathUILabel {\n        let view = MTMathUILabel()\n        view.setContentHuggingPriority(.required, for: .vertical)\n        view.setContentCompressionResistancePriority(.required, for: .vertical)\n        return view\n    }\n\n    func updateNSView(_ view: MTMathUILabel, context: Context) {\n        view.latex = equation\n        let font = MTFontManager().font(withName: font.rawValue, size: fontSize)\n        font?.fallbackFont = NSFont.systemFont(ofSize: fontSize)\n        view.font = font\n        view.textAlignment = textAlignment\n        view.labelMode = labelMode\n        view.textColor = MTColor(Color.primary)\n        view.contentInsets = insets\n        view.invalidateIntrinsicContentSize()\n    }\n\n    func sizeThatFits(_ proposal: ProposedViewSize, nsView: MTMathUILabel, context: Context) -\u003e CGSize? {\n        // Enable line wrapping by passing proposed width to the label\n        if let width = proposal.width, width.isFinite, width \u003e 0 {\n            nsView.preferredMaxLayoutWidth = width\n            let size = nsView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))\n            return size\n        }\n        return nil\n    }\n}\n```\n\n### Automatic Line Wrapping\n\n`SwiftMath` supports automatic line wrapping (multiline display) for mathematical content. The implementation uses **interatom line breaking** which breaks equations at atom boundaries (between mathematical elements) rather than within them, preserving the semantic structure of the mathematics.\n\n#### Using Line Wrapping with UIKit/AppKit\n\nFor direct `MTMathUILabel` usage, set the `preferredMaxLayoutWidth` property:\n\n```swift\nlet label = MTMathUILabel()\nlabel.latex = \"\\\\text{Calculer le discriminant }\\\\Delta=b^{2}-4ac\\\\text{ avec }a=1\\\\text{, }b=-1\\\\text{, }c=-5\"\nlabel.font = MTFontManager.fontManager.defaultFont\n\n// Enable line wrapping by setting a maximum width\nlabel.preferredMaxLayoutWidth = 235\n```\n\nYou can also use `sizeThatFits` to calculate the size with a width constraint:\n\n```swift\nlet constrainedSize = label.sizeThatFits(CGSize(width: 235, height: .greatestFiniteMagnitude))\n```\n\n#### Using Line Wrapping with SwiftUI\n\nThe `MathView` examples above include `sizeThatFits()` which automatically enables line wrapping when SwiftUI proposes a width constraint. No additional configuration is needed:\n\n```swift\nVStack(alignment: .leading, spacing: 8) {\n    MathView(\n        equation: \"\\\\text{Calculer le discriminant }\\\\Delta=b^{2}-4ac\\\\text{ avec }a=1\\\\text{, }b=-1\\\\text{, }c=-5\",\n        fontSize: 17,\n        labelMode: .text\n    )\n}\n.frame(maxWidth: 235)  // The equation will break across multiple lines\n```\n\n#### Line Wrapping Behavior and Capabilities\n\nSwiftMath implements **two complementary line breaking mechanisms**:\n\n##### 1. Interatom Line Breaking (Primary)\nBreaks equations **between atoms** (mathematical elements) when content exceeds the width constraint. This is the preferred method as it maintains semantic integrity.\n\n##### 2. Universal Line Breaking (Fallback)\nFor very long text within single atoms, breaks at Unicode word boundaries using Core Text with number protection (prevents splitting numbers like \"3.14\").\n\nSee `MULTILINE_IMPLEMENTATION_NOTES.md` for implementation details and recent changes.\n\n#### Fully Supported Cases\n\nThese atom types work perfectly with interatom line breaking:\n\n**✅ Variables and ordinary text:**\n```swift\nlabel.latex = \"a b c d e f g h i j k l m n o p\"\nlabel.preferredMaxLayoutWidth = 150\n// Breaks between individual variables at natural boundaries\n```\n\n**✅ Binary operators (+, -, ×, ÷):**\n```swift\nlabel.latex = \"a+b+c+d+e+f+g+h\"\nlabel.preferredMaxLayoutWidth = 100\n// Breaks cleanly: \"a+b+c+d+\"\n//                 \"e+f+g+h\"\n```\n\n**✅ Relations (=, \u003c, \u003e, ≤, ≥, etc.):**\n```swift\nlabel.latex = \"a=1, b=2, c=3, d=4, e=5\"\nlabel.preferredMaxLayoutWidth = 120\n// Breaks after commas and operators\n```\n\n**✅ Mixed text and simple math:**\n```swift\nlabel.latex = \"\\\\text{Calculer }\\\\Delta=b^{2}-4ac\\\\text{ avec }a=1\\\\text{, }b=-1\"\nlabel.preferredMaxLayoutWidth = 200\n// Breaks between text and math atoms naturally\n```\n\n**✅ Punctuation (commas, periods):**\n```swift\nlabel.latex = \"\\\\text{First, second, third, fourth, fifth}\"\nlabel.preferredMaxLayoutWidth = 150\n// Breaks at commas and spaces\n```\n\n**✅ Brackets and parentheses (simple):**\n```swift\nlabel.latex = \"(a+b)+(c+d)+(e+f)\"\nlabel.preferredMaxLayoutWidth = 120\n// Breaks between parenthesized groups\n```\n\n**✅ Greek letters and symbols:**\n```swift\nlabel.latex = \"\\\\alpha+\\\\beta+\\\\gamma+\\\\delta+\\\\epsilon+\\\\zeta\"\nlabel.preferredMaxLayoutWidth = 150\n// Breaks between Greek letters\n```\n\n**✅ Fractions (NEW!):**\n```swift\nlabel.latex = \"a+\\\\frac{1}{2}+b+\\\\frac{3}{4}+c\"\nlabel.preferredMaxLayoutWidth = 150\n// Fractions stay inline if they fit, break to new line only when needed\n// Example: \"a + ½ + b\" stays on one line if it fits\n```\n\n**✅ Radicals/Square roots (NEW!):**\n```swift\nlabel.latex = \"x+\\\\sqrt{2}+y+\\\\sqrt{3}+z\"\nlabel.preferredMaxLayoutWidth = 150\n// Radicals stay inline if they fit, break to new line only when needed\n// Example: \"x + √2 + y\" stays on one line if it fits\n```\n\n**✅ Mixed fractions and radicals (NEW!):**\n```swift\nlabel.latex = \"a+\\\\frac{1}{2}+\\\\sqrt{3}+b\"\nlabel.preferredMaxLayoutWidth = 200\n// Breaks between complex mathematical elements\n```\n\n#### Limited Support Cases\n\nThese cases work but with some constraints:\n\n**✅ Large operators (NEW!):**\n```swift\nlabel.latex = \"a + \\\\sum_{i=1}^{n} x_i + \\\\int_{0}^{1} f(x)dx + b\"\nlabel.preferredMaxLayoutWidth = 200\n// Large operators stay inline when they fit!\n// Includes height checking for operators with limits\n```\n\n**✅ Delimited expressions (NEW!):**\n```swift\nlabel.latex = \"(a+b) + \\\\left(\\\\frac{c}{d}\\\\right) + e\"\nlabel.preferredMaxLayoutWidth = 200\n// Delimiters stay inline when they fit!\n// Inner content respects width constraints and wraps naturally\n```\n\n**✅ Colored expressions (NEW!):**\n```swift\nlabel.latex = \"a + \\\\color{red}{b + c + d} + e\"\nlabel.preferredMaxLayoutWidth = 200\n// Colored sections stay inline when they fit!\n// Inner content respects width constraints and wraps properly\n```\n\n**✅ Matrices/tables (NEW!):**\n```swift\nlabel.latex = \"A = \\\\begin{pmatrix} 1 \u0026 2 \\\\end{pmatrix} + B\"\nlabel.preferredMaxLayoutWidth = 200\n// Small matrices stay inline when they fit!\n```\n\n**✅ Atoms with superscripts/subscripts (IMPROVED!):**\n```swift\nlabel.latex = \"a^{2}+b^{2}+c^{2}+d^{2}+e^{2}\"\nlabel.preferredMaxLayoutWidth = 150\n// Now works with width-based breaking!\n// Scripted atoms participate in smart line breaking decisions\n```\n\n**✅ Math accents:**\n```swift\nlabel.latex = \"\\\\hat{x} + \\\\tilde{y} + \\\\bar{z} + \\\\vec{w}\"\nlabel.preferredMaxLayoutWidth = 150\n// Common accents (\\hat, \\tilde, \\bar, \\vec) work well\n// Vector arrows (\\overrightarrow, etc.) supported with stretching\n```\n\n**⚠️ Very long single text atoms:**\n```swift\nlabel.latex = \"\\\\text{This is an extremely long piece of text within a single text command}\"\nlabel.preferredMaxLayoutWidth = 200\n// Uses Unicode word boundary breaking with Core Text\n// Protects numbers from being split (e.g., \"3.14\" stays together)\n```\n**Note**: Breaks within the text atom rather than between atoms, which is expected behavior for very long continuous text.\n\n#### Best Practices\n\n**DO:**\n- Use interatom breaking for simple equations with operators and relations\n- Use for mixed text and math where you want natural breaks\n- Use for long sequences of variables, numbers, and operators\n- Set appropriate `preferredMaxLayoutWidth` based on your layout needs\n\n**DON'T:**\n- Expect natural breaking in expressions with large operators (∑, ∫, etc. - not yet optimized)\n- Expect natural breaking in expressions with \\left...\\right delimiters (not yet optimized)\n- Use extremely narrow widths (less than ~80pt) which may cause poor breaks\n\n#### Examples\n\n**Excellent use case (discriminant formula):**\n```swift\nlabel.latex = \"\\\\text{Calculer le discriminant }\\\\Delta=b^{2}-4ac\\\\text{ avec }a=1\\\\text{, }b=-1\\\\text{, }c=-5\"\nlabel.preferredMaxLayoutWidth = 235\n// ✅ Breaks naturally at good points between atoms\n```\n\n**Good use case (simple arithmetic):**\n```swift\nlabel.latex = \"5+10+15+20+25+30+35+40+45+50\"\nlabel.preferredMaxLayoutWidth = 150\n// ✅ Breaks between operators cleanly\n```\n\n**Excellent use case (fractions inline - NEW!):**\n```swift\nlabel.latex = \"a+\\\\frac{1}{2}+b+\\\\frac{3}{4}+c\"\nlabel.preferredMaxLayoutWidth = 200\n// ✅ Fractions stay inline when they fit!\n// Breaks: \"a + ½ + b\" on line 1, \"+ ¾ + c\" on line 2\n```\n\n**Excellent use case (radicals inline - NEW!):**\n```swift\nlabel.latex = \"x+\\\\sqrt{2}+y+\\\\sqrt{3}+z\"\nlabel.preferredMaxLayoutWidth = 150\n// ✅ Radicals stay inline when they fit!\n// Example: \"x + √2 + y\" on line 1, \"+ √3 + z\" on line 2\n```\n\n**Alternative for complex expressions:**\n```swift\n// Instead of trying to break this:\nlabel.latex = \"x = \\\\frac{-b \\\\pm \\\\sqrt{b^2-4ac}}{2a}\"\n// Consider it as a single display equation without width constraint\nlabel.preferredMaxLayoutWidth = 0  // No breaking\n```\n\n#### Technical Details\n\n- **Line spacing**: Dynamic line height based on actual content (tall fractions get more space, regular content stays compact)\n- **Breaking algorithm**: Greedy with look-ahead and break quality scoring - prefers breaking after operators over other positions\n- **Width calculation**: Includes inter-element spacing according to TeX spacing rules\n- **Number protection**: Numbers in patterns like \"3.14\", \"1,000\", etc. are kept intact\n- **Supports locales**: English, French, Swiss number formats\n- **Advanced features**: Tokenization infrastructure with phase-based processing (preprocessing → tokenization → line fitting → display generation)\n\nFor complete implementation details including recent improvements (dynamic line height, break quality scoring, early exit optimization), see [MULTILINE_IMPLEMENTATION_NOTES.md](MULTILINE_IMPLEMENTATION_NOTES.md).\n\n### Included Features\nThis is a list of formula types that the library currently supports:\n\n* Simple algebraic equations\n* Fractions and continued fractions (including `\\frac`, `\\dfrac`, `\\tfrac`, `\\cfrac`)\n* Exponents and subscripts\n* Trigonometric formulae (including inverse hyperbolic: `\\arcsinh`, `\\arccosh`, etc.)\n* Square roots and n-th roots\n* Calculus symbols - limits, derivatives, integrals (including `\\iint`, `\\iiint`, `\\iiiint`)\n* Big operators (e.g. product, sum)\n* Big delimiters (using `\\left` and `\\right`)\n* Manual delimiter sizing (`\\big`, `\\Big`, `\\bigg`, `\\Bigg` and variants)\n* Greek alphabet\n* Bold Greek symbols (`\\boldsymbol`)\n* Combinatorics (`\\binom`, `\\choose` etc.)\n* Geometry symbols (e.g. angle, congruence etc.)\n* Ratios, proportions, percentages\n* Math spacing\n* Overline and underline\n* Math accents (including `\\hat`, `\\tilde`, `\\bar`, `\\vec`, `\\dot`, `\\ddot`, etc.)\n* Vector arrows (`\\vec`, `\\overrightarrow`, `\\overleftarrow`, `\\overleftrightarrow` with automatic stretching)\n* Wide accents (`\\widehat`, `\\widetilde`)\n* Operator names (`\\operatorname{name}`)\n* Matrices (including `\\smallmatrix` and starred variants like `pmatrix*` with alignment)\n* Multi-line subscripts and limits (`\\substack`)\n* Equation alignment\n* Change bold, roman, caligraphic and other font styles (`\\bf`, `\\text`, etc.)\n* Style commands (`\\displaystyle`, `\\textstyle`)\n* Custom operators (`\\operatorname`, `\\operatorname*`)\n* Dirac notation (`\\bra`, `\\ket`, `\\braket`)\n* Most commonly used math symbols\n* Colors for both text and background\n* **Inline and display math mode delimiters** (see below)\n* **Automatic line wrapping** (see Automatic Line Wrapping section)\n\n### LaTeX Math Delimiters\n\n`SwiftMath` now supports all standard LaTeX math delimiters for both inline and display modes. The parser automatically detects and handles these delimiters:\n\n#### Inline Math (Text Style)\nUse these delimiters for inline math within text, which renders more compactly:\n\n```swift\n// Dollar signs (TeX style)\nlabel.latex = \"$E = mc^2$\"\n\n// Parentheses (LaTeX style)\nlabel.latex = \"\\\\(\\\\sum_{i=1}^{n} x_i\\\\)\"\n\n// Cases environment in inline mode\nlabel.latex = \"\\\\(\\\\begin{cases} x + y = 5 \\\\\\\\ 2x - y = 1 \\\\end{cases}\\\\)\"\n```\n\n#### Display Math (Display Style)\nUse these delimiters for standalone equations with larger operators and limits:\n\n```swift\n// Double dollar signs (TeX style)\nlabel.latex = \"$$\\\\int_{0}^{\\\\infty} e^{-x^2} dx = \\\\frac{\\\\sqrt{\\\\pi}}{2}$$\"\n\n// Square brackets (LaTeX style)\nlabel.latex = \"\\\\[\\\\sum_{k=1}^{n} k^2 = \\\\frac{n(n+1)(2n+1)}{6}\\\\]\"\n\n// Equation environment\nlabel.latex = \"\\\\begin{equation} x^2 + y^2 = z^2 \\\\end{equation}\"\n\n// Cases environment in display mode\nlabel.latex = \"\\\\begin{cases} x + y = 5 \\\\\\\\ 2x - y = 1 \\\\end{cases}\"\n```\n\n**Note:** The difference between inline and display modes:\n- **Inline mode** (`$...$` or `\\(...\\)`) renders compactly, suitable for math within text\n- **Display mode** (`$$...$$`, `\\[...\\]`, or environments) renders with larger operators and limits positioned above/below\n\nAll delimiters are automatically stripped during parsing, and the math mode is set appropriately. No additional configuration is needed!\n\n#### Backward Compatibility\nEquations without explicit delimiters continue to work as before, defaulting to display mode:\n\n```swift\nlabel.latex = \"x = \\\\frac{-b \\\\pm \\\\sqrt{b^2-4ac}}{2a}\"  // Works as always\n```\n\n#### Programmatic API\nFor advanced use cases where you need to parse LaTeX and determine the detected style programmatically, use the `buildWithStyle` method:\n\n```swift\n// Parse LaTeX and get both the math list and detected style\nlet (mathList, style) = MTMathListBuilder.buildWithStyle(fromString: \"\\\\[x^2 + y^2 = z^2\\\\]\")\n\n// style will be .display for \\[...\\] or $$...$$\n// style will be .text for \\(...\\) or $...$\n\n// Create a display with the detected style\nif let mathList = mathList {\n    let display = MTTypesetter.createLineForMathList(mathList, font: myFont, style: style)\n    // Use the display for rendering\n}\n```\n\nThis is particularly useful when building custom renderers or when you need to respect the user's choice of delimiter style.\n\nNote: SwiftMath only supports the commands in LaTeX's math mode. There is\nalso no language support for other than west European langugages and some\nCyrillic characters. There would be two ways to support more languages:\n\n1) Find a math font compatible with `SwiftMath` that contains all the glyphs\nfor that language.\n2) Add support to `SwiftMath` for standard Unicode fonts that contain all\nlangauge glyphs.\n\nOf these two, the first is much easier.  However, if you want a challenge,\ntry to tackle the second option.\n\n### Example\n\nThe [SwiftMathDemo](https://github.com/mgriebling/SwiftMathDemo) is a SwiftUI version\nof the Objective-C demo included in `iosMath` that uses `SwiftMath` as a Swift package dependency.\n\n### Advanced configuration\n\n`MTMathUILabel` supports some advanced configuration options:\n\n##### Math mode\n\nYou can change the mode of the `MTMathUILabel` between Display Mode\n(equivalent to `$$` or `\\[` in LaTeX) and Text Mode (equivalent to `$`\nor `\\(` in LaTeX). The default style is Display. To switch to Text\nsimply:\n\n```swift\nlabel.labelMode = .text\n```\n\n##### Text Alignment\nThe default alignment of the equations is left. This can be changed to\ncenter or right as follows:\n\n```swift\nlabel.textAlignment = .center\n```\n\n##### Font size\nThe default font-size is 30pt. You can change it as follows:\n\n```swift\nlabel.fontSize = 25\n```\n##### Font\nThe default font is *Latin Modern Math*. This can be changed as:\n\n```swift\nlabel.font = MTFontManager.fontmanager.termesFont(withSize:20)\n```\n\nThis project has 12 fonts bundled with it, but you can use any OTF math\nfont. A python script is included that generates the `.plist` files \nrequired for an `.otf` font to work with `SwiftMath`.  If you generate\n(and test) any other fonts please contribute them back to this project for\nothers to benefit.\n\n\n\nNote: The `KpMath-Light`, `KpMath-Sans`, `Asana` fonts currently incorrectly\nrender very large radicals. It appears that the font files do\nnot properly define the offsets required to typeset these glyphs.  If\nanyone can fix this, it would be greatly appreciated.\n\n##### Text Color\nThe default color of the rendered equation is black. You can change\nit to any other color as follows:\n\n```swift\nlabel.textColor = .red\n```\n\nIt is also possible to set different colors for different parts of the\nequation. Just access the `displayList` field and set the `textColor`\nof the underlying displays of which you want to change the color. \n\n##### Fallback Font for Unicode Text\nBy default, math fonts only support a limited set of characters (Latin, Greek, common math symbols).\nTo display other Unicode characters like Chinese, Japanese, Korean, emoji, or other scripts in `\\text{}`\ncommands, you can configure a fallback font:\n\n```swift\nlet mathFont = MTFontManager().font(withName: MathFont.latinModernFont.rawValue, size: 30)\n\n// Set a fallback font for unsupported characters (defaults to nil)\n#if os(iOS) || os(visionOS)\nlet systemFont = UIFont.systemFont(ofSize: 30)\nmathFont?.fallbackFont = CTFontCreateWithName(systemFont.fontName as CFString, 30, nil)\n#elseif os(macOS)\nlet systemFont = NSFont.systemFont(ofSize: 30)\nmathFont?.fallbackFont = CTFontCreateWithName(systemFont.fontName as CFString, 30, nil)\n#endif\n\nlabel.font = mathFont\nlabel.latex = \"\\\\text{Hello 世界 🌍}\"  // English, Chinese, and emoji\n```\n\nWhen the main math font doesn't contain a glyph for a character, the fallback font will be used automatically.\nThis is particularly useful for:\n- Chinese text: `\\text{中文}`\n- Japanese text: `\\text{日本語}`\n- Korean text: `\\text{한국어}`\n- Emoji: `\\text{Math is fun! 🎉📐}`\n- Mixed scripts: `\\text{Equation: 方程式}`\n\n**Note**: The fallback font only applies to characters within `\\text{}` commands, not regular math mode.\n\n##### Custom Commands\nYou can define your own commands that are not already predefined. This is\nsimilar to macros is LaTeX. To define your own command use:\n\n```swift\nMTMathAtomFactory.addLatexSymbol(\"lcm\", value: MTMathAtomFactory.operator(withName: \"lcm\", limits: false))\n```\n\nThis creates an `\\lcm` command that can be used in the LaTeX.\n\n##### Content Insets\nThe `MTMathUILabel` has `contentInsets` for finer control of placement of the\nequation in relation to the view.\n\nIf you need to set it you can do as follows:\n\n```swift\nlabel.contentInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 20)\n```\n\n##### Error handling\n\nIf the LaTeX text given to `MTMathUILabel` is\ninvalid or if it contains commands that aren't currently supported then\nan error message will be displayed instead of the label.\n\nThis error can be programmatically retrieved as `label.error`. If you\nprefer not to display anything then set:\n\n```swift\nlabel.displayErrorInline = true\n```\n\n## Future Enhancements\n\nNote this is not a complete implementation of LaTeX math mode. There are\nsome pieces that are missing and may be included in future updates:\n\n* `\\middle` delimiter for use between `\\left` and `\\right`\n* Some fine spacing commands (`\\:`, `\\;`, `\\!` - note that `\\,` works)\n\nFor a complete list of features and their implementation status, see [MISSING_FEATURES.md](MISSING_FEATURES.md).\n\n## License\n\n`SwiftMath` is available under the MIT license. See the [LICENSE](./LICENSE)\nfile for more info.\n\n### Fonts\nThis distribution contains the following fonts. These fonts are\nlicensed as follows:\n* Latin Modern Math: \n    [GUST Font License](GUST-FONT-LICENSE.txt)\n* Tex Gyre Termes:\n    [GUST Font License](GUST-FONT-LICENSE.txt)\n* [XITS Math](https://github.com/khaledhosny/xits-math):\n    [Open Font License](OFL.txt)\n* [KpMath Light/KpMath Sans](http://scripts.sil.org/OFL):\n    [SIL Open Font License](OFL.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgriebling%2FSwiftMath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmgriebling%2FSwiftMath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgriebling%2FSwiftMath/lists"}