From f8f668f6491c74d4a6c5ea3831723c7e7db3d511 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:31:52 +0000 Subject: [PATCH 01/10] Add array environment parsing Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- .../Internal/Syntax/AtomFactory.swift | 36 +++++- .../Internal/Syntax/Atoms/Table.swift | 4 + .../SwiftUIMath/Internal/Syntax/Parser.swift | 117 +++++++++++++++++- .../Internal/Syntax/ParserTests.swift | 37 ++++++ 4 files changed, 188 insertions(+), 6 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift index 4561ffc..4c71b22 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift @@ -658,10 +658,12 @@ extension Math { static func table( withEnvironment env: String?, alignment: Table.ColumnAlignment? = nil, + columnAlignments: [Table.ColumnAlignment]? = nil, + columnFormat: String? = nil, rows: [[AtomList]], error: inout ParserError? ) -> Atom? { - let table = Table(environment: env ?? "") + let table = Table(environment: env ?? "", columnFormat: columnFormat) for i in 0.. columnAlignments.count { + let message = "array environment has more columns than alignment specifiers" + if error == nil { + error = ParserError(code: .invalidNumberOfColumns, message: message) + } + return nil + } + + table.interRowAdditionalSpacing = 0 + table.interColumnSpacing = 18 + + let style = Style(level: .text) + for i in 0..= 1 && cell.atoms[0].type == Math.AtomType.style { // remove first atom cell.atoms.removeFirst() @@ -797,7 +809,30 @@ extension Math { if env == nil { return nil } - let table = self.buildTable(environment: env, firstList: nil, isRow: false) + var alignment: Table.ColumnAlignment? = nil + var columnAlignments: [Table.ColumnAlignment]? = nil + var columnFormat: String? = nil + if let env { + if env.hasSuffix("*") { + alignment = self.readOptionalAlignment() + if self.error != nil { + return nil + } + } else if env == "array" { + (columnAlignments, columnFormat) = self.readArrayColumnFormat() + if self.error != nil { + return nil + } + } + } + let table = self.buildTable( + environment: env, + alignment: alignment, + columnAlignments: columnAlignments, + columnFormat: columnFormat, + firstList: nil, + isRow: false + ) return table } else if command == "color" { // A color command has 2 arguments @@ -1156,16 +1191,25 @@ extension Math { if let env = self.readEnvironment() { // Check if this is a starred matrix environment and read optional alignment var alignment: Table.ColumnAlignment? = nil + var columnAlignments: [Table.ColumnAlignment]? = nil + var columnFormat: String? = nil if env.hasSuffix("*") { alignment = self.readOptionalAlignment() if self.error != nil { return nil } + } else if env == "array" { + (columnAlignments, columnFormat) = self.readArrayColumnFormat() + if self.error != nil { + return nil + } } let table = self.buildTable( environment: env, alignment: alignment, + columnAlignments: columnAlignments, + columnFormat: columnFormat, firstList: nil, isRow: false ) @@ -1254,6 +1298,59 @@ extension Math { return alignment } + mutating func readArrayColumnFormat() -> ([Table.ColumnAlignment]?, String?) { + guard self.expectCharacter("{") else { + self.setError(.characterNotFound, message: "Missing { after \\begin{array}") + return (nil, nil) + } + + self.skipSpaces() + + var columnAlignments = [Table.ColumnAlignment]() + var format = "" + var foundClosingBrace = false + + while self.hasCharacters { + let char = self.nextCharacter() + if char == "}" { + foundClosingBrace = true + break + } + + switch char { + case "l": + columnAlignments.append(.left) + format.append(char) + case "c": + columnAlignments.append(.center) + format.append(char) + case "r": + columnAlignments.append(.right) + format.append(char) + case "|": + format.append(char) + case " ": + continue + default: + self.setError( + .invalidEnvironment, + message: "Unsupported array column format specifier: \(char)" + ) + return (nil, nil) + } + } + + if self.error == nil && !foundClosingBrace { + self.setError(.characterNotFound, message: "Missing } after array column format") + } + + if self.error == nil && columnAlignments.isEmpty { + self.setError(.invalidEnvironment, message: "array environment requires column alignment specifiers") + } + + return self.error == nil ? (columnAlignments, format) : (nil, nil) + } + func assertNotSpace(_ ch: Character) { assert(ch >= "\u{21}" && ch <= "\u{7E}", "Expected non-space character \(ch)") } @@ -1261,13 +1358,20 @@ extension Math { mutating func buildTable( environment: String?, alignment: Table.ColumnAlignment? = nil, + columnAlignments: [Table.ColumnAlignment]? = nil, + columnFormat: String? = nil, firstList: AtomList?, isRow: Bool ) -> Atom? { // Save the current env till an new one gets built. let oldEnv = self.currentEnvironment - currentEnvironment = Environment(name: environment, alignment: alignment) + currentEnvironment = Environment( + name: environment, + alignment: alignment, + columnAlignments: columnAlignments, + columnFormat: columnFormat + ) var currentRow = 0 var currentCol = 0 @@ -1306,7 +1410,10 @@ extension Math { var error: ParserError? = self.error let table = AtomFactory.table( - withEnvironment: currentEnvironment?.name, alignment: currentEnvironment?.alignment, + withEnvironment: currentEnvironment?.name, + alignment: currentEnvironment?.alignment, + columnAlignments: currentEnvironment?.columnAlignments, + columnFormat: currentEnvironment?.columnFormat, rows: rows, error: &error) if table == nil && self.error == nil { self.error = error diff --git a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift index c9dfb58..7f96821 100644 --- a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift +++ b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift @@ -1052,6 +1052,43 @@ struct ParserTests { #expect(latex == "\\left( \\begin{matrix}x&y\\\\ z&w\\end{matrix}\\right) ") } + @Test + func array() throws { + let str = "\\left\\{\\begin{array}{ll}1,&|x|\\leq1,\\\\0,&|x|>1,\\end{array}\\right." + let list = try #require(Math.Parser.build(fromString: str)) + #expect(list.atoms.count == 1) + + let inner = try #require(list.atoms[0] as? Math.Inner) + let leftBoundary = try #require(inner.leftBoundary) + #expect(leftBoundary.type == .boundary) + #expect(leftBoundary.nucleus == "{") + #expect(inner.rightBoundary == nil) + + let innerList = try #require(inner.innerList) + #expect(innerList.atoms.count == 1) + + let table = try #require(innerList.atoms[0] as? Math.Table) + #expect(table.environment == "array") + #expect(table.columnFormat == "ll") + #expect(table.interRowAdditionalSpacing == 0) + #expect(table.interColumnSpacing == 18) + #expect(table.numberOfRows == 2) + #expect(table.numberOfColumns == 2) + #expect(table.alignment(forColumn: 0) == .left) + #expect(table.alignment(forColumn: 1) == .left) + + for row in 0.. Date: Mon, 6 Apr 2026 15:32:54 +0000 Subject: [PATCH 02/10] Format array parser changes Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- Sources/SwiftUIMath/Internal/Syntax/Parser.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index 821c3cd..2c2c86e 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -1345,7 +1345,8 @@ extension Math { } if self.error == nil && columnAlignments.isEmpty { - self.setError(.invalidEnvironment, message: "array environment requires column alignment specifiers") + self.setError( + .invalidEnvironment, message: "array environment requires column alignment specifiers") } return self.error == nil ? (columnAlignments, format) : (nil, nil) From e86cf33070c3e696a33ad51482cf9ef3b8c015f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:33:37 +0000 Subject: [PATCH 03/10] Refine array format validation Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- Sources/SwiftUIMath/Internal/Syntax/Parser.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index 2c2c86e..0ee2f4e 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -1329,7 +1329,7 @@ extension Math { format.append(char) case "|": format.append(char) - case " ": + case _ where char.isWhitespace: continue default: self.setError( @@ -1346,7 +1346,9 @@ extension Math { if self.error == nil && columnAlignments.isEmpty { self.setError( - .invalidEnvironment, message: "array environment requires column alignment specifiers") + .invalidEnvironment, + message: "array environment requires at least one column alignment specifier (l, c, or r)" + ) } return self.error == nil ? (columnAlignments, format) : (nil, nil) From 82be1cd96104ef1c89f0e0c54f3e1575f538d568 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:34:19 +0000 Subject: [PATCH 04/10] Refactor environment option parsing Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- .../SwiftUIMath/Internal/Syntax/Parser.swift | 66 +++++++++---------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index 0ee2f4e..4babbcd 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -809,27 +809,17 @@ extension Math { if env == nil { return nil } - var alignment: Table.ColumnAlignment? = nil - var columnAlignments: [Table.ColumnAlignment]? = nil - var columnFormat: String? = nil - if let env { - if env.hasSuffix("*") { - alignment = self.readOptionalAlignment() - if self.error != nil { - return nil - } - } else if env == "array" { - (columnAlignments, columnFormat) = self.readArrayColumnFormat() - if self.error != nil { - return nil - } - } + guard let env else { + return nil + } + guard let environmentOptions = self.readEnvironmentOptions(for: env) else { + return nil } let table = self.buildTable( environment: env, - alignment: alignment, - columnAlignments: columnAlignments, - columnFormat: columnFormat, + alignment: environmentOptions.alignment, + columnAlignments: environmentOptions.columnAlignments, + columnFormat: environmentOptions.columnFormat, firstList: nil, isRow: false ) @@ -1189,27 +1179,15 @@ extension Math { return under } else if command == "begin" { if let env = self.readEnvironment() { - // Check if this is a starred matrix environment and read optional alignment - var alignment: Table.ColumnAlignment? = nil - var columnAlignments: [Table.ColumnAlignment]? = nil - var columnFormat: String? = nil - if env.hasSuffix("*") { - alignment = self.readOptionalAlignment() - if self.error != nil { - return nil - } - } else if env == "array" { - (columnAlignments, columnFormat) = self.readArrayColumnFormat() - if self.error != nil { - return nil - } + guard let environmentOptions = self.readEnvironmentOptions(for: env) else { + return nil } let table = self.buildTable( environment: env, - alignment: alignment, - columnAlignments: columnAlignments, - columnFormat: columnFormat, + alignment: environmentOptions.alignment, + columnAlignments: environmentOptions.columnAlignments, + columnFormat: environmentOptions.columnFormat, firstList: nil, isRow: false ) @@ -1298,6 +1276,24 @@ extension Math { return alignment } + mutating func readEnvironmentOptions(for env: String) -> ( + alignment: Table.ColumnAlignment?, + columnAlignments: [Table.ColumnAlignment]?, + columnFormat: String? + )? { + if env.hasSuffix("*") { + let alignment = self.readOptionalAlignment() + return self.error == nil ? (alignment, nil, nil) : nil + } + + if env == "array" { + let (columnAlignments, columnFormat) = self.readArrayColumnFormat() + return self.error == nil ? (nil, columnAlignments, columnFormat) : nil + } + + return (nil, nil, nil) + } + mutating func readArrayColumnFormat() -> ([Table.ColumnAlignment]?, String?) { guard self.expectCharacter("{") else { self.setError(.characterNotFound, message: "Missing { after \\begin{array}") From f82f9e9cea89eaf4a42e7cbde49c9ffb2579283c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:34:55 +0000 Subject: [PATCH 05/10] Simplify begin environment parsing Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- Sources/SwiftUIMath/Internal/Syntax/Parser.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index 4babbcd..12596a8 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -805,11 +805,7 @@ extension Math { return table } else if command == "begin" { - let env = self.readEnvironment() - if env == nil { - return nil - } - guard let env else { + guard let env = self.readEnvironment() else { return nil } guard let environmentOptions = self.readEnvironmentOptions(for: env) else { From 1091e9c83d65ab4a549aa31ac169016adcce08ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:35:49 +0000 Subject: [PATCH 06/10] Add array parser error tests Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- .../Internal/Syntax/ParserTests.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift index 7f96821..cb37f17 100644 --- a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift +++ b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift @@ -1089,6 +1089,28 @@ struct ParserTests { #expect(latex.contains("\\right.")) } + @Test + func arrayRejectsInvalidColumnFormat() throws { + let str = "\\begin{array}{xyz}a\\end{array}" + var error: Math.ParserError? = nil + + let list = Math.Parser.build(fromString: str, error: &error) + + #expect(list == nil) + #expect(error?.code == .invalidEnvironment) + } + + @Test + func arrayRejectsTooFewColumnSpecifiers() throws { + let str = "\\begin{array}{l}a&b\\end{array}" + var error: Math.ParserError? = nil + + let list = Math.Parser.build(fromString: str, error: &error) + + #expect(list == nil) + #expect(error?.code == .invalidNumberOfColumns) + } + @Test func defaultTable() throws { let str = "x \\\\ y" From 77d6794b26184feb9ea7a757cf0fb557badc0542 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:36:51 +0000 Subject: [PATCH 07/10] Tidy array validation flow Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift | 2 +- Sources/SwiftUIMath/Internal/Syntax/Parser.swift | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift index 4c71b22..8314929 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift @@ -712,7 +712,7 @@ extension Math { return table } } else if env == "array" { - guard let columnAlignments, !columnAlignments.isEmpty else { + guard let columnAlignments else { let message = "array environment requires at least 1 column alignment" if error == nil { error = ParserError(code: .invalidEnvironment, message: message) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index 12596a8..aa9cb1b 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -1332,18 +1332,22 @@ extension Math { } } - if self.error == nil && !foundClosingBrace { + if !foundClosingBrace { self.setError(.characterNotFound, message: "Missing } after array column format") } - if self.error == nil && columnAlignments.isEmpty { + if columnAlignments.isEmpty { self.setError( .invalidEnvironment, message: "array environment requires at least one column alignment specifier (l, c, or r)" ) } - return self.error == nil ? (columnAlignments, format) : (nil, nil) + if self.error != nil { + return (nil, nil) + } + + return (columnAlignments, format) } func assertNotSpace(_ ch: Character) { From 3d7db623dce3e2effe81a0ceda1d53cb90e962ee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:37:36 +0000 Subject: [PATCH 08/10] Remove duplicate array validation Agent-Logs-Url: https://github.com/wesleyel/swiftui-math/sessions/56436444-e15b-4dd0-8a70-c87df1e3dc4e Co-authored-by: wesleyel <48174882+wesleyel@users.noreply.github.com> --- Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift index 8314929..9b21291 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/AtomFactory.swift @@ -712,13 +712,7 @@ extension Math { return table } } else if env == "array" { - guard let columnAlignments else { - let message = "array environment requires at least 1 column alignment" - if error == nil { - error = ParserError(code: .invalidEnvironment, message: message) - } - return nil - } + let columnAlignments = columnAlignments ?? [] if table.numberOfColumns > columnAlignments.count { let message = "array environment has more columns than alignment specifiers" From 2a6cb0cb4c7c212151addc677e3707655f40222b Mon Sep 17 00:00:00 2001 From: wesleyel <48174882+wesleyel@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:04:11 +0800 Subject: [PATCH 09/10] Fix boundary handling in Parser and update tests for empty cases --- .../SwiftUIMath/Internal/Syntax/Parser.swift | 12 +++++++++++ .../Internal/Syntax/ParserTests.swift | 20 +++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift index aa9cb1b..af01f93 100644 --- a/Sources/SwiftUIMath/Internal/Syntax/Parser.swift +++ b/Sources/SwiftUIMath/Internal/Syntax/Parser.swift @@ -764,6 +764,12 @@ extension Math { // reinstate the old inner atom. let newInner = currentInnerAtom currentInnerAtom = oldInner + if newInner?.leftBoundary?.nucleus.isEmpty == true { + newInner?.leftBoundary = nil + } + if newInner?.rightBoundary?.nucleus.isEmpty == true { + newInner?.rightBoundary = nil + } return newInner } else if command == "overline" { // The overline command has 1 arguments @@ -1162,6 +1168,12 @@ extension Math { } let newInner = self.currentInnerAtom currentInnerAtom = oldInner + if newInner?.leftBoundary?.nucleus.isEmpty == true { + newInner?.leftBoundary = nil + } + if newInner?.rightBoundary?.nucleus.isEmpty == true { + newInner?.rightBoundary = nil + } return newInner } else if command == "overline" { let over = Overline() diff --git a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift index cb37f17..2aa782a 100644 --- a/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift +++ b/Tests/SwiftUIMathTests/Internal/Syntax/ParserTests.swift @@ -594,13 +594,21 @@ struct ParserTests { let innerList = try #require(inner.innerList) checkAtomTypes(innerList, types: testCase.type2) - let leftBoundary = try #require(inner.leftBoundary) - #expect(leftBoundary.type == .boundary) - #expect(leftBoundary.nucleus == testCase.left) + if testCase.left.isEmpty { + #expect(inner.leftBoundary == nil) + } else { + let leftBoundary = try #require(inner.leftBoundary) + #expect(leftBoundary.type == .boundary) + #expect(leftBoundary.nucleus == testCase.left) + } - let rightBoundary = try #require(inner.rightBoundary) - #expect(rightBoundary.type == .boundary) - #expect(rightBoundary.nucleus == testCase.right) + if testCase.right.isEmpty { + #expect(inner.rightBoundary == nil) + } else { + let rightBoundary = try #require(inner.rightBoundary) + #expect(rightBoundary.type == .boundary) + #expect(rightBoundary.nucleus == testCase.right) + } // convert it back to latex let latex = Math.Parser.atomListToString(list) From 70066e80433cf79169d4fff9278e8d4cd0b350e8 Mon Sep 17 00:00:00 2001 From: wesleyel <48174882+wesleyel@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:35:20 +0800 Subject: [PATCH 10/10] Handle invalid inter-element spaces to prevent crashes in debug builds --- Sources/SwiftUIMath/Internal/Display/Typesetter.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftUIMath/Internal/Display/Typesetter.swift b/Sources/SwiftUIMath/Internal/Display/Typesetter.swift index d87eec6..b13f502 100644 --- a/Sources/SwiftUIMath/Internal/Display/Typesetter.swift +++ b/Sources/SwiftUIMath/Internal/Display/Typesetter.swift @@ -1846,7 +1846,11 @@ extension Math { let spaceArray = getInterElementSpaces()[Int(leftIndex)] let spaceTypeObj = spaceArray[Int(rightIndex)] let spaceType = spaceTypeObj - assert(spaceType != .invalid, "Invalid space between \(left) and \(right)") + // Keep malformed LaTeX from crashing debug builds. Propagating NaN lets callers + // detect the failed layout and surface it as a validation issue instead. + if spaceType == .invalid { + return .nan + } let spaceMultipler = self.getSpacingInMu(spaceType) if spaceMultipler > 0 {