Skip to content

Commit f56f060

Browse files
authored
Merge pull request #11 from colinc86/develop
Fix block equation whitespace.
2 parents edc4c2d + 45ccfcf commit f56f060

File tree

4 files changed

+141
-51
lines changed

4 files changed

+141
-51
lines changed

Sources/LaTeXSwiftUI/Extensions/CGRect+Extensions.swift

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
//
2525

2626
import Foundation
27+
import CoreGraphics
2728

2829
extension CGRect: Hashable {
2930

Sources/LaTeXSwiftUI/Models/Parser.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,28 @@ internal struct Parser {
4949

5050
/// An TeX-style block equation component.
5151
static let tex = EquationComponent(
52-
regex: #/\$\$(.*?)\$\$/#,
52+
regex: #/\$\$\s*(.*?)\s*\$\$/#,
5353
terminatingRegex: #/\$\$/#,
5454
equation: .texEquation,
5555
supportsRecursion: false)
5656

5757
/// A block equation.
5858
static let block = EquationComponent(
59-
regex: #/\\\[(.*?)\\\]/#,
59+
regex: #/\\\[\s*(.*?)\s*\\\]/#,
6060
terminatingRegex: #/\\\]/#,
6161
equation: .blockEquation,
6262
supportsRecursion: false)
6363

6464
/// A named equation component.
6565
static let named = EquationComponent(
66-
regex: #/\\begin{equation}(.*?)\\end{equation}/#,
66+
regex: #/\\begin{equation}\s*(.*?)\s*\\end{equation}/#,
6767
terminatingRegex: #/\\end{equation}/#,
6868
equation: .namedEquation,
6969
supportsRecursion: true)
7070

7171
/// A named no number equation component.
7272
static let namedNoNumber = EquationComponent(
73-
regex: #/\\begin{equation\*}(.*?)\\end{equation\*}/#,
73+
regex: #/\\begin{equation\*}\s*(.*?)\s*\\end{equation\*}/#,
7474
terminatingRegex: #/\\end{equation\*}/#,
7575
equation: .namedNoNumberEquation,
7676
supportsRecursion: true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import MathJaxSwift
2+
import XCTest
3+
@testable import LaTeXSwiftUI
4+
5+
final class GeometryTests: XCTestCase {
6+
7+
func testSVGGeometry_parseAlignment() {
8+
let input = "\"vertical-align: -1.602ex;\""
9+
let value = SVGGeometry.parseAlignment(from: input)
10+
XCTAssertEqual(value, -1.602)
11+
}
12+
13+
func testSVGGeometry_parseAlignmentZero() {
14+
let input = "\"vertical-align: 0;\""
15+
let value = SVGGeometry.parseAlignment(from: input)
16+
XCTAssertEqual(value, 0)
17+
}
18+
19+
func testSVGGeometry_parseXHeight() {
20+
let input = "\"-1.602ex\""
21+
let value = SVGGeometry.parseXHeight(from: input)
22+
XCTAssertEqual(value, -1.602)
23+
}
24+
25+
func testSVGGeometry_parseViewBox() {
26+
let input = "\"0 -1342 940 2050\""
27+
let value = SVGGeometry.parseViewBox(from: input)
28+
XCTAssertEqual(value, CGRect(x: 0, y: -1342, width: 940, height: 2050))
29+
}
30+
31+
func testSVGGeometry() throws {
32+
let input = """
33+
<svg style="vertical-align: -1.602ex;" xmlns="http://www.w3.org/2000/svg" width="2.127ex" height="4.638ex" role="img" focusable="false" viewBox="0 -1342 940 2050" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="MJX-1-MM-N-32" d="M449 174L424 174C419 144 412 100 402 85C395 77 329 77 307 77L127 77L233 180C389 318 449 372 449 472C449 586 359 666 237 666C124 666 50 574 50 485C50 429 100 429 103 429C120 429 155 441 155 482C155 508 137 534 102 534C94 534 92 534 89 533C112 598 166 635 224 635C315 635 358 554 358 472C358 392 308 313 253 251L61 37C50 26 50 24 50 0L421 0Z"></path><path id="MJX-1-MM-N-33" d="M457 171C457 253 394 331 290 352C372 379 430 449 430 528C430 610 342 666 246 666C145 666 69 606 69 530C69 497 91 478 120 478C151 478 171 500 171 529C171 579 124 579 109 579C140 628 206 641 242 641C283 641 338 619 338 529C338 517 336 459 310 415C280 367 246 364 221 363C213 362 189 360 182 360C174 359 167 358 167 348C167 337 174 337 191 337L235 337C317 337 354 269 354 171C354 35 285 6 241 6C198 6 123 23 88 82C123 77 154 99 154 137C154 173 127 193 98 193C74 193 42 179 42 135C42 44 135-22 244-22C366-22 457 69 457 171Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><use data-c="32" xlink:href="#MJX-1-MM-N-32"></use></g><g data-mml-node="mn" transform="translate(220,-686)"><use data-c="33" xlink:href="#MJX-1-MM-N-33"></use></g><rect width="700" height="60" x="120" y="220"></rect></g></g></g></svg>
34+
"""
35+
let geometry = try SVGGeometry(svg: input)
36+
XCTAssertNoThrow(geometry)
37+
XCTAssertEqual(geometry.verticalAlignment, -1.602)
38+
XCTAssertEqual(geometry.width, 2.127)
39+
XCTAssertEqual(geometry.height, 4.638)
40+
XCTAssertEqual(geometry.frame, CGRect(x: 0, y: -1342, width: 940, height: 2050))
41+
}
42+
43+
}

Tests/LaTeXSwiftUITests/LaTeXSwiftUITests.swift Tests/LaTeXSwiftUITests/ParserTests.swift

+93-47
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
//
2+
// ParserTests.swift
3+
//
4+
//
5+
// Created by Colin Campbell on 5/29/23.
6+
//
7+
18
import MathJaxSwift
29
import XCTest
310
@testable import LaTeXSwiftUI
411

5-
final class LaTeXSwiftUITests: XCTestCase {
6-
12+
final class ParserTests: XCTestCase {
13+
714
func assertComponent(_ components: [Component], _ index: Int, _ text: String, _ type: Component.ComponentType, file: StaticString = #file, line: UInt = #line) {
815
guard index < components.count else {
916
XCTFail()
@@ -85,6 +92,30 @@ final class LaTeXSwiftUITests: XCTestCase {
8592
assertComponent(components, 0, input, .text)
8693
}
8794

95+
func testParseDoubleDollarOnly_LeadingLineBreak() {
96+
let equation = "\nf(x)=5x+2"
97+
let input = "$$\(equation)$$"
98+
let components = Parser.parse(input)
99+
XCTAssertEqual(components.count, 1)
100+
assertComponent(components, 0, equation, .texEquation)
101+
}
102+
103+
func testParseDoubleDollarOnly_TrailingLineBreak() {
104+
let equation = "f(x)=5x+2\n"
105+
let input = "$$\(equation)$$"
106+
let components = Parser.parse(input)
107+
XCTAssertEqual(components.count, 1)
108+
assertComponent(components, 0, equation, .texEquation)
109+
}
110+
111+
func testParseDoubleDollarOnly_Whitespace() {
112+
let equation = " \nf(x)=5x+2\n "
113+
let input = "$$\(equation)$$"
114+
let components = Parser.parse(input)
115+
XCTAssertEqual(components.count, 1)
116+
assertComponent(components, 0, equation, .texEquation)
117+
}
118+
88119
func testParseBracketsOnly() {
89120
let input = "\\[\\TeX\\]"
90121
let components = Parser.parse(input)
@@ -115,11 +146,28 @@ final class LaTeXSwiftUITests: XCTestCase {
115146
assertComponent(components, 0, input, .text)
116147
}
117148

118-
func testParseBracketsOnly_LineBreak() {
119-
let input = "Hello, \\[\\TeX\n\\\\]!"
149+
func testParseBracketsOnly_LeadingLineBreak() {
150+
let equation = "\n\\TeX"
151+
let input = "Hello, \\[\(equation)\\]!"
120152
let components = Parser.parse(input)
121-
XCTAssertEqual(components.count, 1)
122-
assertComponent(components, 0, input, .text)
153+
XCTAssertEqual(components.count, 3)
154+
assertComponent(components, 1, equation, .blockEquation)
155+
}
156+
157+
func testParseBracketsOnly_TrailingLineBreak() {
158+
let equation = "\\TeX\n"
159+
let input = "Hello, \\[\(equation)\\]!"
160+
let components = Parser.parse(input)
161+
XCTAssertEqual(components.count, 3)
162+
assertComponent(components, 1, equation, .blockEquation)
163+
}
164+
165+
func testParseBracketsOnly_Whitespace() {
166+
let equation = " \n\\TeX\n "
167+
let input = "Hello, \\[\(equation)\\]!"
168+
let components = Parser.parse(input)
169+
XCTAssertEqual(components.count, 3)
170+
assertComponent(components, 1, equation, .blockEquation)
123171
}
124172

125173
func testParseBeginEndOnly() {
@@ -152,11 +200,28 @@ final class LaTeXSwiftUITests: XCTestCase {
152200
assertComponent(components, 0, input, .text)
153201
}
154202

155-
func testParseBeginEndOnly_LineBreak() {
156-
let input = "Hello, \\begin{equation}\\TeX\n\\\\end{equation}!"
203+
func testParseBeginEndOnly_LeadingLineBreak() {
204+
let equation = "\n\\TeX"
205+
let input = "Hello, \\begin{equation}\(equation)\\end{equation}!"
157206
let components = Parser.parse(input)
158-
XCTAssertEqual(components.count, 1)
159-
assertComponent(components, 0, input, .text)
207+
XCTAssertEqual(components.count, 3)
208+
assertComponent(components, 1, equation, .namedEquation)
209+
}
210+
211+
func testParseBeginEndOnly_TrailingLineBreak() {
212+
let equation = "\\TeX\n"
213+
let input = "Hello, \\begin{equation}\(equation)\\end{equation}!"
214+
let components = Parser.parse(input)
215+
XCTAssertEqual(components.count, 3)
216+
assertComponent(components, 1, equation, .namedEquation)
217+
}
218+
219+
func testParseBeginEndOnly_Whitespace() {
220+
let equation = " \n\\TeX\n "
221+
let input = "Hello, \\begin{equation}\(equation)\\end{equation}!"
222+
let components = Parser.parse(input)
223+
XCTAssertEqual(components.count, 3)
224+
assertComponent(components, 1, equation, .namedEquation)
160225
}
161226

162227
func testParseBeginEndStarOnly() {
@@ -189,47 +254,28 @@ final class LaTeXSwiftUITests: XCTestCase {
189254
assertComponent(components, 0, input, .text)
190255
}
191256

192-
func testParseBeginEndStarOnly_LineBreak() {
193-
let input = "Hello, \\begin{equation*}\\TeX\n\\\\end{equation*}!"
257+
func testParseBeginEndStarOnly_LeadingLineBreak() {
258+
let equation = "\n\\TeX"
259+
let input = "Hello, \\begin{equation*}\(equation)\\end{equation*}!"
194260
let components = Parser.parse(input)
195-
XCTAssertEqual(components.count, 1)
196-
assertComponent(components, 0, input, .text)
197-
}
198-
199-
func testSVGGeometry_parseAlignment() {
200-
let input = "\"vertical-align: -1.602ex;\""
201-
let value = SVGGeometry.parseAlignment(from: input)
202-
XCTAssertEqual(value, -1.602)
203-
}
204-
205-
func testSVGGeometry_parseAlignmentZero() {
206-
let input = "\"vertical-align: 0;\""
207-
let value = SVGGeometry.parseAlignment(from: input)
208-
XCTAssertEqual(value, 0)
209-
}
210-
211-
func testSVGGeometry_parseXHeight() {
212-
let input = "\"-1.602ex\""
213-
let value = SVGGeometry.parseXHeight(from: input)
214-
XCTAssertEqual(value, -1.602)
261+
XCTAssertEqual(components.count, 3)
262+
assertComponent(components, 1, equation, .namedNoNumberEquation)
215263
}
216264

217-
func testSVGGeometry_parseViewBox() {
218-
let input = "\"0 -1342 940 2050\""
219-
let value = SVGGeometry.parseViewBox(from: input)
220-
XCTAssertEqual(value, CGRect(x: 0, y: -1342, width: 940, height: 2050))
265+
func testParseBeginEndStarOnly_TrailingLineBreak() {
266+
let equation = "\\TeX\n"
267+
let input = "Hello, \\begin{equation*}\(equation)\\end{equation*}!"
268+
let components = Parser.parse(input)
269+
XCTAssertEqual(components.count, 3)
270+
assertComponent(components, 1, equation, .namedNoNumberEquation)
221271
}
222272

223-
func testSVGGeometry() throws {
224-
let input = """
225-
<svg style="vertical-align: -1.602ex;" xmlns="http://www.w3.org/2000/svg" width="2.127ex" height="4.638ex" role="img" focusable="false" viewBox="0 -1342 940 2050" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="MJX-1-MM-N-32" d="M449 174L424 174C419 144 412 100 402 85C395 77 329 77 307 77L127 77L233 180C389 318 449 372 449 472C449 586 359 666 237 666C124 666 50 574 50 485C50 429 100 429 103 429C120 429 155 441 155 482C155 508 137 534 102 534C94 534 92 534 89 533C112 598 166 635 224 635C315 635 358 554 358 472C358 392 308 313 253 251L61 37C50 26 50 24 50 0L421 0Z"></path><path id="MJX-1-MM-N-33" d="M457 171C457 253 394 331 290 352C372 379 430 449 430 528C430 610 342 666 246 666C145 666 69 606 69 530C69 497 91 478 120 478C151 478 171 500 171 529C171 579 124 579 109 579C140 628 206 641 242 641C283 641 338 619 338 529C338 517 336 459 310 415C280 367 246 364 221 363C213 362 189 360 182 360C174 359 167 358 167 348C167 337 174 337 191 337L235 337C317 337 354 269 354 171C354 35 285 6 241 6C198 6 123 23 88 82C123 77 154 99 154 137C154 173 127 193 98 193C74 193 42 179 42 135C42 44 135-22 244-22C366-22 457 69 457 171Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><use data-c="32" xlink:href="#MJX-1-MM-N-32"></use></g><g data-mml-node="mn" transform="translate(220,-686)"><use data-c="33" xlink:href="#MJX-1-MM-N-33"></use></g><rect width="700" height="60" x="120" y="220"></rect></g></g></g></svg>
226-
"""
227-
let geometry = try SVGGeometry(svg: input)
228-
XCTAssertNoThrow(geometry)
229-
XCTAssertEqual(geometry.verticalAlignment, -1.602)
230-
XCTAssertEqual(geometry.width, 2.127)
231-
XCTAssertEqual(geometry.height, 4.638)
232-
XCTAssertEqual(geometry.frame, CGRect(x: 0, y: -1342, width: 940, height: 2050))
273+
func testParseBeginEndStarOnly_Whitespace() {
274+
let equation = " \n\\TeX\n "
275+
let input = "Hello, \\begin{equation*}\(equation)\\end{equation*}!"
276+
let components = Parser.parse(input)
277+
XCTAssertEqual(components.count, 3)
278+
assertComponent(components, 1, equation, .namedNoNumberEquation)
233279
}
234-
280+
235281
}

0 commit comments

Comments
 (0)