{"id":13998299,"url":"https://github.com/colinc86/LaTeXSwiftUI","last_synced_at":"2025-07-23T06:31:07.845Z","repository":{"id":91603780,"uuid":"573606592","full_name":"colinc86/LaTeXSwiftUI","owner":"colinc86","description":"A SwiftUI view that renders LaTeX.","archived":false,"fork":false,"pushed_at":"2024-03-26T03:24:41.000Z","size":746,"stargazers_count":122,"open_issues_count":7,"forks_count":20,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-04-26T23:40:32.163Z","etag":null,"topics":["latex","mathematics","mathjax","swift","swiftui","tex"],"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/colinc86.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2022-12-02T22:02:14.000Z","updated_at":"2024-06-29T12:52:20.562Z","dependencies_parsed_at":"2024-03-26T04:27:59.826Z","dependency_job_id":"f92a3c91-00ec-458f-8081-d112e2501e75","html_url":"https://github.com/colinc86/LaTeXSwiftUI","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinc86%2FLaTeXSwiftUI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinc86%2FLaTeXSwiftUI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinc86%2FLaTeXSwiftUI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinc86%2FLaTeXSwiftUI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/colinc86","download_url":"https://codeload.github.com/colinc86/LaTeXSwiftUI/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227245148,"owners_count":17753239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["latex","mathematics","mathjax","swift","swiftui","tex"],"created_at":"2024-08-09T19:01:33.496Z","updated_at":"2025-07-23T06:31:07.816Z","avatar_url":"https://github.com/colinc86.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# LaTeXSwiftUI\n\nA SwiftUI view that renders LaTeX equations.\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcolinc86%2FLaTeXSwiftUI%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/colinc86/LaTeXSwiftUI) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcolinc86%2FLaTeXSwiftUI%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/colinc86/LaTeXSwiftUI) [![Unit Tests](https://github.com/colinc86/LaTeXSwiftUI/actions/workflows/swift.yml/badge.svg)](https://github.com/colinc86/LaTeXSwiftUI/actions/workflows/swift.yml)\n\n\u003ccenter\u003e\u003cimg src=\"./assets/images/device.png\" width=\"362\"\u003e\u003c/center\u003e\n\n## 📖 Contents\n\n- [ℹ️ About](#about)\n- [📦 Installation](#installation)\n- [⌨️ Usage](#usage)\n  - [🔤 Fonts](#fonts)\n  - [⚙️ Modifiers](#modifiers)\n    - [🔤 Parsing Mode](#parsing-mode)\n    - [🌄 Image Rendering Mode](#image-rendering-mode)\n    - [🚨 Error Mode](#error-mode)\n    - [🧱Block Rendering Mode](#block-rendering-mode)\n    - [🔢 Numbered Block Equations](#numbered-block-equations)\n      - [Equation Number Mode](#equation-number-mode)\n      - [Equation Number Start](#equation-number-start)\n      - [Equation Number Offset](#equation-number-offset)\n      - [Format Equation Number](#format-equation-number)\n    - [🔗 Unencode HTML](#unencode-html)\n    - [📄 Ignore String Formatting](#ignore-string-formatting)\n    - [🕶️ Rendering Style](#rendering-style)\n    - [🪩 Rendering Animation](#rendering-animation)\n  - [🪮 Styles](#styles)\n  - [🗄️ Caching](#caching)\n  - [🏃‍♀️ Preloading](#preloading)\n  \n## About\n\n`LaTexSwiftUI` is a package that exposes a view named `LaTeX` that can parse and render TeX and LaTeX equations which contain math-mode macros.\n\nThe view utilizes the [MathJaxSwift](https://www.github.com/colinc86/MathJaxSwift) package to render equations with [MathJax](https://www.mathjax.org). Thus, the limitations of the view are heavily influenced by the [limitations](https://docs.mathjax.org/en/v2.7-latest/tex.html#differences) of MathJax.\n\nIt will\n- render TeX and LaTeX equations (math-mode macros),\n- render the `\\text{}` macro within equations,\n- attempt to render block equations as a TeX or LaTeX engine would,\n- and number block equations (if desired).\n\nIt won't\n- render TeX and LaTeX documents (text-mode macros, with the exception of the rule above).\n\n## Installation\n\nAdd the dependency to your package manifest file.\n\n```swift\n.package(url: \"https://github.com/colinc86/LaTeXSwiftUI\", from: \"1.5.0\")\n```\n\n## Usage\n\nImport the package and use the view.\n\n```swift\nimport LaTeXSwiftUI\n\nstruct MyView: View {\n\n  var body: some View {\n    LaTeX(\"Hello, $\\\\LaTeX$!\")\n  }\n\n}\n```\n\n\u003e \u003cimg src=\"./assets/images/hello.png\" width=\"85\" height=\"21.5\"\u003e\n\n### Fonts\n\nThe view needs to be able to measure the current font's x-height to correctly size the characters inside of the rendered LaTeX SVG. To do that, the view must use the `UIFont`/`NSFont` classes and do its best to convert SwiftUI's `Font` structure into the correct `UIFont` instance. Currently, the view's functionality is limited to SwiftUI's static largeTitle, title, title1, headline, etc fonts, or by using `UIFont`/`NSFont` types directly.\n\nThe `font` modifier has been overloaded so that you can give the `LaTeX` view `UIFont` and `NSFont` types directly. The following examples will render the size of the LaTeX correctly.\n\n```swift\n// SwiftUI perferred fonts\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(.title)\n\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(.caption)\n\n// Any UIFont/NSFont - note that they should be passed directly to the view\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(UIFont.systemFont(ofSize: 30))\n\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(UIFont(name: \"Avenir\", size: 25)!)\n```\n\nThe following examples will _not_ render the size of the LaTeX correctly.\n\n```swift\n// SwiftUI Font type, but not a preferred font\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(.custom(name: \"Avenir\", size: 25))\n\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(.system(size: 25))\n\n// Wrapping UIFont/NSFont in a SwiftUI Font type\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .font(Font(UIFont.systemFont(ofSize: 30)))\n```\n\n### Modifiers\n\nThe `LaTeX` view's body is built up of `Text` views so feel free to use any of the supported modifiers.\n\n```swift\nLaTeX(\"Hello, $\\\\LaTeX$!\")\n  .fontDesign(.serif)\n  .foregroundColor(.blue)\n```\n\n\u003e \u003cimg src=\"./assets/images/hello_blue.png\" width=\"87\" height=\"21.5\"\u003e\n\nAlong with supporting the built-in SwiftUI modifies, `LaTeXSwiftUI` defines more to let you configure the view.\n\n#### Parsing Mode\n\nText input can either be completely rendered, or the view can search for top-level equations delimited by the following terminators.\n\n| Terminators |\n|-------------|\n| `$...$` |\n| `$$...$$` |\n| `\\(...\\)` |\n| `\\[...\\]` |\n| `\\begin{equation}...\\end{equation}` |\n| `\\begin{equation*}...\\end{equation*}` |\n\n The default behavior is to only render equations with `onlyEquations`. Use the `parsingMode` modifier to change the default behavior.\n\n```swift\n// Only parse equations (default)\nLaTeX(\"Euler's identity is $e^{i\\\\pi}+1=0$.\")\n  .font(.system(size: 18))\n  .parsingMode(.onlyEquations)\n\n// Parse the entire input\nLaTeX(\"\\\\text{Euler's identity is } e^{i\\\\pi}+1=0\\\\text{.}\")\n  .parsingMode(.all)\n```\n\n\u003e \u003cimg src=\"./assets/images/euler.png\" width=\"293\" height=\"80\"\u003e\n\n#### Image Rendering Mode\n\nYou can specify the rendering mode of the rendered equations so that they either take on the style of the surrounding text or display the style rendered by MathJax. The default behavior is to use the `template` rendering mode so that images match surrounding text.\n\n```swift\n// Render images to match the surrounding text\nLaTeX(\"Hello, $\\\\color{red}\\\\LaTeX$!\")\n  .imageRenderingMode(.template)\n\n// Display the original rendered image\nLaTeX(\"Hello, ${\\\\color{red} \\\\LaTeX}$!\")\n  .imageRenderingMode(.original)\n```\n\n\u003e \u003cimg src=\"./assets/images/rendering_mode.png\" width=\"84.5\" height=\"43\"\u003e\n\n#### Error Mode\n\nWhen an error occurs while parsing the input the view will display the original LaTeX. You can change this behavior by modifying the view's `errorMode`.\n\n\u003e Note: when the `rendered` mode is used, MathJax is instructed to load the `noerrors` and `noundefined` packages. In the other two modes, `original` and `error`, these packages are not loaded by MathJax and errors are either displayed in the view, or caught and replaced with the original text.\n\n```swift\n// Display the original text instead of the equation\nLaTeX(\"$\\\\asdf$\")\n  .errorMode(.original)\n\n// Display the error text instead of the equation\nLaTeX(\"$\\\\asdf$\")\n  .errorMode(.error)\n\n// Display the rendered image (if available)\nLaTeX(\"$\\\\asdf$\")\n  .errorMode(.rendered)\n```\n\n\u003e \u003cimg src=\"./assets/images/errors.png\" width=\"199.5\" height=\"55\"\u003e\n\n#### Block Rendering Mode\n\nThe typical \"LaTeX-ish\" way to render the input is with `blockViews`. This mode renders text as usual, and block equations as... blocks; on their own line and centered. MathJax 3 does not support line breaking, so the view places block equations in horizontal scroll views in case the width of the equation is more than the width of the view.\n\nIn the case that you want to force block equations as inline, you can use the `alwaysInline` mode. You can also keep block styling with `blockText`, but the blocks will not be centered in their views. These modes can be helpful if you have a lengthy input string and need to only display it on a single or few lines.\n\n```swift\n/// The default block mode \nLaTeX(\"The quadratic formula is $$x=\\\\frac{-b\\\\pm\\\\sqrt{b^2-4ac}}{2a}$$ and it has zeros at the roots of $f(x)=ax^2+bx+c$.\")\n  .blockMode(.blockViews)\n\nDivider()\n\n/// Force blocks to render as inline\nLaTeX(\"The quadratic formula is $$x=\\\\frac{-b\\\\pm\\\\sqrt{b^2-4ac}}{2a}$$ and it has zeros at the roots of $f(x)=ax^2+bx+c$.\")\n  .blockMode(.alwaysInline)\n\nDivider()\n\n/// Force blocks to render as text with newlines\nLaTeX(\"The quadratic formula is $$x=\\\\frac{-b\\\\pm\\\\sqrt{b^2-4ac}}{2a}$$ and it has zeros at the roots of $f(x)=ax^2+bx+c$.\")\n  .blockMode(.blockText)\n```\n\n\u003e \u003cimg src=\"./assets/images/blocks.png\" width=\"430\" height=\"350\"\u003e\n\n#### Numbered Block Equations\n\nThe `LaTeX` view can do simple numbering of block equations with the `blockViews` block mode.\n\n##### Equation Number Mode\n\nUse the `equationNumberMode` modifier to change between `left`, `right` and `none`.\n\n##### Equation Number Start\n\nThe default starting number is `1`, but if you need to start at a different value, you can specify it with the `equationNumberStart` modifier.\n\n##### Equation Number Offset\n\nTo change the left or right offset of the equation number, use the `equationNumberOffset` modifier.\n\n##### Format Equation Number\n\nYou can set a closure on the view to do your own custom formatting. The `formatEquationNumber` modifier takes a closure that is passed the equation number and returns a string.\n\n```swift\nLaTeX(\"$$E = mc^2$$\")\n  .equationNumberMode(.right)\n  .equationNumberOffset(10)\n  .padding([.bottom])\n\nLaTeX(\"$$E = mc^2$$ $$E = mc^2$$\")\n  .equationNumberMode(.right)\n  .equationNumberOffset(10)\n  .equationNumberStart(2)\n  .formatEquationNumber { n in\n    return \"~[\\(n)]~\"\n  }\n```\n\n\u003e \u003cimg src=\"./assets/images/numbers.png\" width=\"433\" height=\"153\"\u003e\n\n#### Unencode HTML\n\nInput may contain HTML entities such as `\u0026lt;` which will not be parsed by LaTeX as anything meaningful. In this case, you may use the `unencoded` modifier.\n\n```swift\nLaTeX(\"$x^2\u0026lt;1$\")\n  .errorMode(.error)\n\n// Replace \"\u0026lt;\" with \"\u003c\"\nLaTeX(\"$x^2\u0026lt;1$\")\n  .unencoded()\n```\n\n\u003e \u003cimg src=\"./assets/images/unencoded.png\" width=\"72.5\" height=\"34\"\u003e\n\n#### Ignore String Formatting\n\nThe `LaTeX` view will render the following markdown synatax.\n\n| Syntax | Description |\n|-------------|-------------|\n| `*...*` | Italic |\n| `**...**` | Bold |\n| `***...***` | Bold \u0026 Italic |\n| `~~...~~` | Strikethrough |\n| `` `...` `` | Monospaced |\n| `[...](...)` | Links |\n\nIf you don't want markdown rendered, then you may use the `ignoreStringFormatting` modifier.\n\n```swift\nLaTeX(input)\n  .ignoreStringFormatting()\n```\n\n##### Escaped Characters\n\nThe characeters `\u0026`, `%`, `$`, `#`, `_`, `{`, `}`, `~`, `^`, and `\\` are reserved characters in LaTeX and may appear in a document with an escape characeter preceeding them.\n\nThe view will look for these characters preceeded by an escape, and replace them with the non-escaped version. If you would like to prevent this replacement, then you may use the `ignoreStringFormatting` modifier.\n\n#### Rendering Style\n\nThe view has four rendering styles. The `wait` style is the default style, and loads the view synchronously on the main queue. To get better performance and move SVG rendering off of the main queue, use any of the other three styles.\n\n| Style      | Asynchronous | Description                                                              |\n|:-----------|:-------------|:-------------------------------------------------------------------------|\n| `empty`    | Yes          | The view remains empty until it's finished rendering.                     |\n| `original` | Yes          | The view displays the input text until it's finished rendering.           |\n| `redactedOriginal` | Yes  | The view displays a redacted version of the view until it's finished rendering |\n| `progress` | Yes          | The view displays a progress view until it's finished rendering.          |\n| `wait`     | No           | *(default)* The view blocks the main queue until it's finished rendering. |\n\n\n#### Rendering Animation\n\nWhen using the asynchronous rendering styles `empty`, `original`, or `progress`, use this modifier to determine the animation applied to the transition between views. The default value is `none`.\n\n```swift\nLaTeX(input)\n  .renderingStyle(.original)\n  .renderingAnimation(.easeIn)\n```\n\n\u003e In the above example, the input text will be displayed until the SVGs have been rendered at which point the rendered views will animate in to view.\n\n### Styles (Deprecated)\n\nYou can use the provided view styles or create your own.\n\n```swift\n// The default view style.\nLaTeX(input)\n  .latexStyle(.automatic)\n\n// A \"standard\" style with HTML elements unencoded and block equations numbered.\nLaTeX(input)\n  .latexStyle(.standard)  \n```\n\nTo create your own style, conform to the `LaTeXStyle` protocol. Its `makeBody(content:)` method takes a `LaTeX` view and returns a stylized version of the view.\n\nThe following would create a style for the first title used at the [top](#latexswiftui) of this README.\n\n```swift\n@available(iOS 16.1, *)\npublic struct TitleLaTeXStyle: LaTeXStyle {\n  \n  public func makeBody(content: LaTeX) -\u003e some View {\n    content\n      .fontDesign(.serif)\n      .font(.largeTitle)\n      .foregroundStyle(\n          LinearGradient(\n            colors: [.red, .orange, .yellow, .green, .blue, .indigo, .purple],\n            startPoint: .leading,\n            endPoint: .trailing\n          )\n        )\n  }\n  \n}\n```\n\n### Caching\n\n`LaTeXSwiftUI` caches its SVG responses from MathJax and the images rendered as a result of the view's environment. If you want to control the cache, then you can access the static `dataCache` and `imageCache` properties.\n\n```swift\n// Clear the SVG data cache.\nLaTeX.dataCache.removeAllObjects()\n\n// Clear the rendered image cache.\nLaTeX.imageCache.removeAllObjects()\n```\n\n### Preloading\n\nSVGs and images are rendered and cached on demand, but there may be situations where you want to preload the data so that there is minimal lag when the view appears.\n\n```swift\nVStack {\n  ForEach(expressions, id: \\.self) { expression in\n    LaTeX(expression)\n      .font(.caption2)\n      .foregroundColor(.green)\n      .unencoded()\n      .errorMode(.error)\n      .processEscapes()\n      .preload()\n  }\n}\n```\n\nSVGs and images are rendered as a result of the view's environment, so it is important to call the `preload` method last in the view's modifier chain if you use it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolinc86%2FLaTeXSwiftUI","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcolinc86%2FLaTeXSwiftUI","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolinc86%2FLaTeXSwiftUI/lists"}