Re-arrange source code and tests
This commit is contained in:
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Accent.swift
Normal file
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Accent.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Accent: Atom {
|
||||
var innerList: AtomList?
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let accent = finalized as? Accent {
|
||||
accent.innerList = accent.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ accent: Accent) {
|
||||
self.innerList = accent.innerList.map { AtomList($0) }
|
||||
super.init(accent)
|
||||
}
|
||||
|
||||
init(value: String = "", innerList: AtomList? = nil) {
|
||||
self.innerList = innerList
|
||||
super.init(type: .accent, nucleus: value)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/Color.swift
Normal file
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/Color.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Color: Atom {
|
||||
var colorString: String
|
||||
var innerList: AtomList?
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
"\\color",
|
||||
"{\(colorString)}",
|
||||
innerList.map { "{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let color = finalized as? Color {
|
||||
color.innerList = color.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ color: Color) {
|
||||
self.colorString = color.colorString
|
||||
self.innerList = color.innerList.map { AtomList($0) }
|
||||
|
||||
super.init(color)
|
||||
}
|
||||
|
||||
init(colorString: String = "", innerList: AtomList? = nil) {
|
||||
self.colorString = colorString
|
||||
self.innerList = innerList
|
||||
super.init(type: .color)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/ColorBox.swift
Normal file
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/ColorBox.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class ColorBox: Atom {
|
||||
var colorString: String
|
||||
var innerList: AtomList?
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
"\\colorbox",
|
||||
"{\(colorString)}",
|
||||
innerList.map { "{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let colorBox = finalized as? ColorBox {
|
||||
colorBox.innerList = colorBox.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ colorBox: ColorBox) {
|
||||
self.colorString = colorBox.colorString
|
||||
self.innerList = colorBox.innerList.map { AtomList($0) }
|
||||
|
||||
super.init(colorBox)
|
||||
}
|
||||
|
||||
init(colorString: String = "", innerList: AtomList? = nil) {
|
||||
self.colorString = colorString
|
||||
self.innerList = innerList
|
||||
super.init(type: .colorBox)
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Sources/SwiftUIMath/Internal/Syntax/Atoms/Fraction.swift
Normal file
71
Sources/SwiftUIMath/Internal/Syntax/Atoms/Fraction.swift
Normal file
@@ -0,0 +1,71 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Fraction: Atom {
|
||||
var hasRule: Bool
|
||||
var leftDelimiter: String
|
||||
var rightDelimiter: String
|
||||
var numerator: AtomList?
|
||||
var denominator: AtomList?
|
||||
|
||||
var isContinuedFraction: Bool = false
|
||||
var alignment: String // "l", "r", "c" for left, right, center
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
hasRule ? "\\frac" : "\\atop",
|
||||
leftDelimiter.isEmpty ? nil : "[\(leftDelimiter)]",
|
||||
rightDelimiter.isEmpty ? nil : "[\(rightDelimiter)]",
|
||||
"{\(numerator?.description ?? "placeholder")}",
|
||||
"{\(denominator?.description ?? "placeholder")}",
|
||||
superscript.map { "^{\($0)}" },
|
||||
`subscript`.map { "_{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let fraction = finalized as? Fraction {
|
||||
fraction.numerator = fraction.numerator?.finalized
|
||||
fraction.denominator = fraction.denominator?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ fraction: Fraction) {
|
||||
self.hasRule = fraction.hasRule
|
||||
self.leftDelimiter = fraction.leftDelimiter
|
||||
self.rightDelimiter = fraction.rightDelimiter
|
||||
self.numerator = fraction.numerator.map { AtomList($0) }
|
||||
self.denominator = fraction.denominator.map { AtomList($0) }
|
||||
self.isContinuedFraction = fraction.isContinuedFraction
|
||||
self.alignment = fraction.alignment
|
||||
|
||||
super.init(fraction)
|
||||
}
|
||||
|
||||
init(
|
||||
hasRule: Bool = true,
|
||||
leftDelimiter: String = "",
|
||||
rightDelimiter: String = "",
|
||||
numerator: AtomList? = nil,
|
||||
denominator: AtomList? = nil,
|
||||
isContinuedFraction: Bool = false,
|
||||
alignment: String = "c"
|
||||
) {
|
||||
self.hasRule = hasRule
|
||||
self.leftDelimiter = leftDelimiter
|
||||
self.rightDelimiter = rightDelimiter
|
||||
self.numerator = numerator
|
||||
self.denominator = denominator
|
||||
self.isContinuedFraction = isContinuedFraction
|
||||
self.alignment = alignment
|
||||
|
||||
super.init(type: .fraction)
|
||||
}
|
||||
}
|
||||
}
|
||||
68
Sources/SwiftUIMath/Internal/Syntax/Atoms/Inner.swift
Normal file
68
Sources/SwiftUIMath/Internal/Syntax/Atoms/Inner.swift
Normal file
@@ -0,0 +1,68 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Inner: Atom {
|
||||
var innerList: AtomList?
|
||||
|
||||
var leftBoundary: Atom? {
|
||||
didSet {
|
||||
if let leftBoundary, leftBoundary.type != .boundary {
|
||||
assertionFailure("Left boundary must be of type 'boundary'")
|
||||
self.leftBoundary = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rightBoundary: Atom? {
|
||||
didSet {
|
||||
if let rightBoundary, rightBoundary.type != .boundary {
|
||||
assertionFailure("Right boundary must be of type 'boundary'")
|
||||
self.rightBoundary = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
"\\inner",
|
||||
leftBoundary.map { "[\($0.nucleus)]" },
|
||||
innerList.map { "{\($0)}" },
|
||||
rightBoundary.map { "[\($0.nucleus)]" },
|
||||
superscript.map { "^{\($0)}" },
|
||||
`subscript`.map { "_{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let inner = finalized as? Inner {
|
||||
inner.innerList = inner.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ inner: Inner) {
|
||||
self.innerList = inner.innerList.map { AtomList($0) }
|
||||
self.leftBoundary = inner.leftBoundary.map { $0.copy() }
|
||||
self.rightBoundary = inner.rightBoundary.map { $0.copy() }
|
||||
|
||||
super.init(inner)
|
||||
}
|
||||
|
||||
init(
|
||||
innerList: AtomList? = nil,
|
||||
leftBoundary: Atom? = nil,
|
||||
rightBoundary: Atom? = nil
|
||||
) {
|
||||
self.innerList = innerList
|
||||
self.leftBoundary = leftBoundary
|
||||
self.rightBoundary = rightBoundary
|
||||
|
||||
super.init(type: .inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class LargeOperator: Atom {
|
||||
var limits: Bool
|
||||
|
||||
init(_ largeOperator: LargeOperator) {
|
||||
self.limits = largeOperator.limits
|
||||
super.init(largeOperator)
|
||||
}
|
||||
|
||||
init(limits: Bool = false) {
|
||||
self.limits = limits
|
||||
super.init(type: .largeOperator)
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Overline.swift
Normal file
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Overline.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Overline: Atom {
|
||||
var innerList: AtomList?
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let overline = finalized as? Overline {
|
||||
overline.innerList = overline.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ overline: Overline) {
|
||||
self.innerList = overline.innerList.map { AtomList($0) }
|
||||
super.init(overline)
|
||||
}
|
||||
|
||||
init(innerList: AtomList? = nil) {
|
||||
self.innerList = innerList
|
||||
super.init(type: .overline)
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Sources/SwiftUIMath/Internal/Syntax/Atoms/Radical.swift
Normal file
45
Sources/SwiftUIMath/Internal/Syntax/Atoms/Radical.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Radical: Atom {
|
||||
var radicand: AtomList?
|
||||
var degree: AtomList?
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
"\\sqrt",
|
||||
degree.map { "[\($0)]" },
|
||||
"{\(radicand?.description ?? "placeholder")}",
|
||||
superscript.map { "^{\($0)}" },
|
||||
`subscript`.map { "_{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let radical = finalized as? Radical {
|
||||
radical.radicand = radical.radicand?.finalized
|
||||
radical.degree = radical.degree?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ radical: Radical) {
|
||||
self.radicand = radical.radicand.map { AtomList($0) }
|
||||
self.degree = radical.degree.map { AtomList($0) }
|
||||
|
||||
super.init(radical)
|
||||
}
|
||||
|
||||
init(radicand: AtomList? = nil, degree: AtomList? = nil) {
|
||||
self.radicand = radicand
|
||||
self.degree = degree
|
||||
|
||||
super.init(type: .radical)
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Sources/SwiftUIMath/Internal/Syntax/Atoms/Space.swift
Normal file
17
Sources/SwiftUIMath/Internal/Syntax/Atoms/Space.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Space: Atom {
|
||||
var amount: CGFloat
|
||||
|
||||
init(_ space: Space) {
|
||||
self.amount = space.amount
|
||||
super.init(space)
|
||||
}
|
||||
|
||||
init(amount: CGFloat = 0) {
|
||||
self.amount = amount
|
||||
super.init(type: .space)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/Style.swift
Normal file
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/Style.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Style: Atom {
|
||||
enum Level: Int {
|
||||
case display
|
||||
case text
|
||||
case script
|
||||
case scriptOfScript
|
||||
|
||||
var isScript: Bool {
|
||||
switch self {
|
||||
case .script, .scriptOfScript:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var isNotScript: Bool {
|
||||
!isScript
|
||||
}
|
||||
|
||||
func next() -> Level {
|
||||
Level(rawValue: rawValue + 1) ?? .display
|
||||
}
|
||||
}
|
||||
|
||||
var level: Level
|
||||
|
||||
init(_ style: Style) {
|
||||
self.level = style.level
|
||||
super.init(style)
|
||||
}
|
||||
|
||||
init(level: Level = .display) {
|
||||
self.level = level
|
||||
super.init(type: .style)
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Sources/SwiftUIMath/Internal/Syntax/Atoms/Table.swift
Normal file
101
Sources/SwiftUIMath/Internal/Syntax/Atoms/Table.swift
Normal file
@@ -0,0 +1,101 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Table: Atom {
|
||||
enum ColumnAlignment {
|
||||
case left
|
||||
case center
|
||||
case right
|
||||
}
|
||||
|
||||
var alignments: [ColumnAlignment]
|
||||
var cells: [[AtomList]]
|
||||
var environment: String
|
||||
var interColumnSpacing: CGFloat
|
||||
var interRowAdditionalSpacing: CGFloat
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let table = finalized as? Table {
|
||||
table.cells = table.cells.map { row in
|
||||
row.map { $0.finalized }
|
||||
}
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ table: Table) {
|
||||
self.alignments = table.alignments
|
||||
self.cells = table.cells.map { row in
|
||||
row.map { AtomList($0) }
|
||||
}
|
||||
self.environment = table.environment
|
||||
self.interColumnSpacing = table.interColumnSpacing
|
||||
self.interRowAdditionalSpacing = table.interRowAdditionalSpacing
|
||||
|
||||
super.init(table)
|
||||
}
|
||||
|
||||
init(
|
||||
alignments: [ColumnAlignment] = [],
|
||||
cells: [[AtomList]] = [],
|
||||
environment: String = "",
|
||||
interColumnSpacing: CGFloat = 0,
|
||||
interRowAdditionalSpacing: CGFloat = 0
|
||||
) {
|
||||
self.alignments = alignments
|
||||
self.cells = cells
|
||||
self.environment = environment
|
||||
self.interColumnSpacing = interColumnSpacing
|
||||
self.interRowAdditionalSpacing = interRowAdditionalSpacing
|
||||
super.init(type: .table)
|
||||
}
|
||||
|
||||
func setCell(_ cell: AtomList, forRow row: Int, column: Int) {
|
||||
if cells.count <= row {
|
||||
for _ in cells.count...row {
|
||||
cells.append([])
|
||||
}
|
||||
}
|
||||
|
||||
if cells[row].count <= column {
|
||||
for _ in cells[row].count...column {
|
||||
cells[row].append(AtomList())
|
||||
}
|
||||
}
|
||||
|
||||
cells[row][column] = cell
|
||||
}
|
||||
|
||||
func setAlignment(_ alignment: ColumnAlignment, forColumn column: Int) {
|
||||
if alignments.count <= column {
|
||||
for _ in alignments.count...column {
|
||||
alignments.append(.center)
|
||||
}
|
||||
}
|
||||
|
||||
alignments[column] = alignment
|
||||
}
|
||||
|
||||
func alignment(forColumn column: Int) -> ColumnAlignment {
|
||||
if alignments.count <= column {
|
||||
return .center
|
||||
}
|
||||
return alignments[column]
|
||||
}
|
||||
|
||||
var numberOfColumns: Int {
|
||||
var count = 0
|
||||
for row in cells {
|
||||
count = max(count, row.count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
var numberOfRows: Int {
|
||||
cells.count
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/TextColor.swift
Normal file
41
Sources/SwiftUIMath/Internal/Syntax/Atoms/TextColor.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class TextColor: Atom {
|
||||
var colorString: String
|
||||
var innerList: AtomList?
|
||||
|
||||
override var description: String {
|
||||
[
|
||||
"\\textcolor",
|
||||
"{\(colorString)}",
|
||||
innerList.map { "{\($0)}" },
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined()
|
||||
}
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let textColor = finalized as? TextColor {
|
||||
textColor.innerList = textColor.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ textColor: TextColor) {
|
||||
self.colorString = textColor.colorString
|
||||
self.innerList = textColor.innerList.map { AtomList($0) }
|
||||
|
||||
super.init(textColor)
|
||||
}
|
||||
|
||||
init(colorString: String = "", innerList: AtomList? = nil) {
|
||||
self.colorString = colorString
|
||||
self.innerList = innerList
|
||||
super.init(type: .textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Underline.swift
Normal file
27
Sources/SwiftUIMath/Internal/Syntax/Atoms/Underline.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
extension Math {
|
||||
final class Underline: Atom {
|
||||
var innerList: AtomList?
|
||||
|
||||
override var finalized: Math.Atom {
|
||||
let finalized = super.finalized
|
||||
|
||||
if let underline = finalized as? Underline {
|
||||
underline.innerList = underline.innerList?.finalized
|
||||
}
|
||||
|
||||
return finalized
|
||||
}
|
||||
|
||||
init(_ underline: Underline) {
|
||||
self.innerList = underline.innerList.map { AtomList($0) }
|
||||
super.init(underline)
|
||||
}
|
||||
|
||||
init(innerList: AtomList? = nil) {
|
||||
self.innerList = innerList
|
||||
super.init(type: .underline)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user