Skip to content

Commit 069496c

Browse files
authored
Merge pull request #54 from colinc86/better-formatting
Better formatting
2 parents f44bf35 + 5d619ad commit 069496c

File tree

12 files changed

+149
-250
lines changed

12 files changed

+149
-250
lines changed

README.md

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,28 @@ A SwiftUI view that renders LaTeX equations.
88

99
## 📖 Contents
1010

11-
- [About](#ℹ️-about)
12-
- [Installation](#📦-installation)
13-
- [Usage](#⌨️-usage)
14-
- [Modifiers](#⚙️-modifiers)
15-
- [Parsing Mode](#🔤-parsing-mode)
16-
- [Image Rendering Mode](#🌄-image-rendering-mode)
17-
- [Error Mode](#🚨-error-mode)
18-
- [Block Rendering Mode](#🧱-block-rendering-mode)
19-
- [Numbered Block Equations](#🔢-numbered-block-equations)
11+
- [ℹ️ About](#about)
12+
- [📦 Installation](#installation)
13+
- [⌨️ Usage](#usage)
14+
- [⚙️ Modifiers](#modifiers)
15+
- [🔤 Parsing Mode](#parsing-mode)
16+
- [🌄 Image Rendering Mode](#image-rendering-mode)
17+
- [🚨 Error Mode](#error-mode)
18+
- [🧱Block Rendering Mode](#block-rendering-mode)
19+
- [🔢 Numbered Block Equations](#numbered-block-equations)
2020
- [Equation Number Mode](#equation-number-mode)
2121
- [Equation Number Start](#equation-number-start)
2222
- [Equation Number Offset](#equation-number-offset)
2323
- [Format Equation Number](#format-equation-number)
24-
- [Unencode HTML](#🔗-unencode-html)
25-
- [Rendering Style](#🕶️-rendering-style)
26-
- [Rendering Animation](#🪩-animated)
27-
- [Styles](#🪮-styles)
28-
- [Caching](#🗄️-caching)
29-
- [Preloading](#🏃‍♀️-preloading)
24+
- [🔗 Unencode HTML](#unencode-html)
25+
- [📄 Ignore String Formatting](#ignore-string-formatting)
26+
- [🕶️ Rendering Style](#rendering-style)
27+
- [🪩 Rendering Animation](#rendering-animation)
28+
- [🪮 Styles](#styles)
29+
- [🗄️ Caching](#caching)
30+
- [🏃‍♀️ Preloading](#preloading)
3031

31-
## ℹ️ About
32+
## About
3233

3334
`LaTexSwiftUI` is a package that exposes a view named `LaTeX` that can parse and render TeX and LaTeX equations which contain math-mode marcos.
3435

@@ -43,15 +44,15 @@ It will
4344
It won't
4445
- render TeX and LaTeX documents (text-mode macros, with the exception of the rule above).
4546

46-
## 📦 Installation
47+
## Installation
4748

4849
Add the dependency to your package manifest file.
4950

5051
```swift
5152
.package(url: "https://github.com/colinc86/LaTeXSwiftUI", from: "1.3.2")
5253
```
5354

54-
## ⌨️ Usage
55+
## Usage
5556

5657
Import the package and use the view.
5758

@@ -69,7 +70,7 @@ struct MyView: View {
6970

7071
> <img src="./assets/images/hello.png" width="85" height="21.5">
7172
72-
### ⚙️ Modifiers
73+
### Modifiers
7374

7475
The `LaTeX` view's body is built up of `Text` views so feel free to use any of the supported modifiers.
7576

@@ -83,14 +84,15 @@ LaTeX("Hello, $\\LaTeX$!")
8384
8485
Along with supporting the built-in SwiftUI modifies, `LaTeXSwiftUI` defines more to let you configure the view.
8586

86-
#### 🔤 Parsing Mode
87+
#### Parsing Mode
8788

8889
Text input can either be completely rendered, or the view can search for top-level equations delimited by the following terminators.
8990

9091
| Terminators |
9192
|-------------|
9293
| `$...$` |
9394
| `$$...$$` |
95+
| `\(...\)` |
9496
| `\[...\]` |
9597
| `\begin{equation}...\end{equation}` |
9698
| `\begin{equation*}...\end{equation*}` |
@@ -110,7 +112,7 @@ LaTeX("\\text{Euler's identity is } e^{i\\pi}+1=0\\text{.}")
110112

111113
> <img src="./assets/images/euler.png" width="293" height="80">
112114
113-
#### 🌄 Image Rendering Mode
115+
#### Image Rendering Mode
114116

115117
You 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.
116118

@@ -126,7 +128,7 @@ LaTeX("Hello, ${\\color{red} \\LaTeX}$!")
126128

127129
> <img src="./assets/images/rendering_mode.png" width="84.5" height="43">
128130
129-
#### 🚨 Error Mode
131+
#### Error Mode
130132

131133
When 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`.
132134

@@ -148,7 +150,7 @@ LaTeX("$\\asdf$")
148150

149151
> <img src="./assets/images/errors.png" width="199.5" height="55">
150152
151-
#### 🧱 Block Rendering Mode
153+
#### Block Rendering Mode
152154

153155
The 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.
154156

@@ -174,7 +176,7 @@ LaTeX("The quadratic formula is $$x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}$$ and it h
174176

175177
> <img src="./assets/images/blocks.png" width="430" height="350">
176178
177-
#### 🔢 Numbered Block Equations
179+
#### Numbered Block Equations
178180

179181
The `LaTeX` view can do simple numbering of block equations with the `blockViews` block mode.
180182

@@ -211,7 +213,7 @@ LaTeX("$$E = mc^2$$ $$E = mc^2$$")
211213

212214
> <img src="./assets/images/numbers.png" width="433" height="153">
213215
214-
#### 🔗 Unencode HTML
216+
#### Unencode HTML
215217

216218
Input may contain HTML entities such as `&lt;` which will not be parsed by LaTeX as anything meaningful. In this case, you may use the `unencoded` modifier.
217219

@@ -226,19 +228,46 @@ LaTeX("$x^2&lt;1$")
226228

227229
> <img src="./assets/images/unencoded.png" width="72.5" height="34">
228230
229-
#### 🕶️ Rendering Style
231+
#### Ignore String Formatting
232+
233+
The `LaTeX` view will render the following markdown synatax.
234+
235+
| Syntax | Description |
236+
|-------------|-------------|
237+
| `*...*` | Italic |
238+
| `**...**` | Bold |
239+
| `***...***` | Bold & Italic |
240+
| `~~...~~` | Strikethrough |
241+
| `` `...` `` | Monospaced |
242+
| `[...](...)` | Links |
243+
244+
If you don't want markdown rendered, then you may use the `ignoreStringFormatting` modifier.
245+
246+
```swift
247+
LaTeX(input)
248+
.ignoreStringFormatting()
249+
```
250+
251+
##### Escaped Characters
252+
253+
The characeters `&`, `%`, `$`, `#`, `_`, `{`, `}`, `~`, `^`, and `\` are reserved characters in LaTeX and may appear in a document with an escape characeter preceeding them.
254+
255+
The 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.
256+
257+
#### Rendering Style
230258

231259
The 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.
232260

233261
| Style | Asynchronous | Description |
234262
|:-----------|:-------------|:-------------------------------------------------------------------------|
235-
| `empty` | Yes | The view remains empty until its finished rendering. |
236-
| `original` | Yes | The view displays the input text until its finished rendering. |
237-
| `progress` | Yes | The view displays a progress view until its finished rendering. |
238-
| `wait` | No | *(default)* The view blocks the main queue until its finished rendering. |
263+
| `empty` | Yes | The view remains empty until it's finished rendering. |
264+
| `original` | Yes | The view displays the input text until it's finished rendering. |
265+
| `redactedOriginal` | Yes | The view displays a redacted version of the view until it's finished rendering |
266+
| `progress` | Yes | The view displays a progress view until it's finished rendering. |
267+
| `wait` | No | *(default)* The view blocks the main queue until it's finished rendering. |
239268

240269

241-
#### 🪩 Rendering Animation
270+
#### Rendering Animation
242271

243272
When 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`.
244273

@@ -250,7 +279,7 @@ LaTeX(input)
250279

251280
> 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.
252281
253-
### 🪮 Styles
282+
### Styles
254283

255284
You can use the provided view styles or create your own.
256285

@@ -288,7 +317,7 @@ public struct TitleLaTeXStyle: LaTeXStyle {
288317
}
289318
```
290319

291-
### 🗄️ Caching
320+
### Caching
292321

293322
`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.
294323

@@ -300,7 +329,7 @@ LaTeX.dataCache.removeAllObjects()
300329
LaTeX.imageCache.removeAllObjects()
301330
```
302331

303-
### 🏃‍♀️ Preloading
332+
### Preloading
304333

305334
SVGs 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.
306335

Sources/LaTeXSwiftUI/Extensions/EnvironmentValues+Extensions.swift

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,7 @@ private struct RenderingAnimationKey: EnvironmentKey {
7474
static let defaultValue: Animation? = .none
7575
}
7676

77-
private struct IgnoreEscapedCharactersKey: EnvironmentKey {
78-
static let defaultValue: Bool = false
79-
}
80-
81-
private struct IgnoreMarkdownKey: EnvironmentKey {
77+
private struct IgnoreSringFormatting: EnvironmentKey {
8278
static let defaultValue: Bool = false
8379
}
8480

@@ -156,16 +152,10 @@ extension EnvironmentValues {
156152
set { self[RenderingAnimationKey.self] = newValue }
157153
}
158154

159-
/// Whether escaped characeters should be ignored or replaced.
160-
var ignoreEscapedCharacters: Bool {
161-
get { self[IgnoreEscapedCharactersKey.self] }
162-
set { self[IgnoreEscapedCharactersKey.self] = newValue }
163-
}
164-
165-
/// Whether markdown should be ignored or rendered.
166-
var ignoreMarkdown: Bool {
167-
get { self[IgnoreMarkdownKey.self] }
168-
set { self[IgnoreMarkdownKey.self] = newValue }
155+
/// Whether string formatting such as markdown should be ignored or rendered.
156+
var ignoreStringFormatting: Bool {
157+
get { self[IgnoreSringFormatting.self] }
158+
set { self[IgnoreSringFormatting.self] = newValue }
169159
}
170160

171161
}

Sources/LaTeXSwiftUI/Extensions/View+Extensions.swift

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -162,45 +162,12 @@ public extension View {
162162
environment(\.renderingAnimation, animation)
163163
}
164164

165-
/// Sets whether the view should ignore escaped characters or replace them.
165+
/// Whether string formatting such as markdown should be ignored or rendered.
166166
///
167-
/// The characeters `&`, `%`, `$`, `#`, `_`, `{`, `}`, `~`, `^`, and `\` are
168-
/// reserved characters in LaTeX and may appear in a document with an escape
169-
/// characeter preceeding them.
170-
///
171-
/// Set this environment variable to `true` to render the escape and the
172-
/// character, or to `false` to have the view replace the escaped characeter
173-
/// with itself.
174-
///
175-
/// For example
176-
///
177-
/// ```
178-
/// LaTeX("Bob has \$5.00")
179-
/// ```
180-
///
181-
/// will display `Bob has $5.00`.
182-
///
183-
/// Whereas
184-
///
185-
/// ```
186-
/// LaTeX("Bob has $5.00")
187-
/// .ignoreEscapedCharacters()
188-
/// ```
189-
///
190-
/// will display `Bob has \$5.00`.
191-
///
192-
/// - Parameter ignore: Whether to ignore escaped characters.
193-
/// - Returns: A view that ignores or replaces escaped characters.
194-
func ignoreEscapedCharacters(_ ignore: Bool = true) -> some View {
195-
environment(\.ignoreEscapedCharacters, ignore)
196-
}
197-
198-
/// Whether markdown should be ignored or rendered.
199-
///
200-
/// - Parameter ignore: Ignore markdown.
201-
/// - Returns: A view that ignores or renders markdown.
202-
func ignoreMarkdown(_ ignore: Bool = true) -> some View {
203-
environment(\.ignoreMarkdown, ignore)
167+
/// - Parameter ignore: Ignore string formatting.
168+
/// - Returns: A view that ignores or renders string formatting.
169+
func ignoreStringFormatting(_ ignore: Bool = true) -> some View {
170+
environment(\.ignoreStringFormatting, ignore)
204171
}
205172

206173
}

Sources/LaTeXSwiftUI/LaTeX.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,8 @@ public struct LaTeX: View {
157157
/// The animation the view should apply to its rendered images.
158158
@Environment(\.renderingAnimation) private var renderingAnimation
159159

160-
/// Whether escaped characters should be ignored or replaced.
161-
@Environment(\.ignoreEscapedCharacters) private var ignoreEscapedCharacters
162-
163-
/// Whether markdown should be ignored or rendered.
164-
@Environment(\.ignoreMarkdown) private var ignoreMarkdown
160+
/// Whether string formatting such as markdown should be ignored or rendered.
161+
@Environment(\.ignoreStringFormatting) private var ignoreStringFormatting
165162

166163
/// The view's current display scale.
167164
@Environment(\.displayScale) private var displayScale

Sources/LaTeXSwiftUI/Models/Component.swift

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,8 @@ extension Component {
198198
/// - errorMode: The error handling mode.
199199
/// - blockRenderingModel: The rendering mode of the block.
200200
/// - isInEquationBlock: Whether this block is in an equation block.
201-
/// - ignoreEscapedCharacters: Whether escaped characters should be ignored
202-
/// or replaced.
203-
/// - ignoreMarkdown: Whether markdown should be ignored or rendered.
201+
/// - ignoreStringFormatting: Whether string formatting such as markdown
202+
/// should be ignored or rendered.
204203
/// - Returns: A text view.
205204
func convertToText(
206205
font: Font,
@@ -209,8 +208,7 @@ extension Component {
209208
errorMode: LaTeX.ErrorMode,
210209
blockRenderingMode: LaTeX.BlockMode,
211210
isInEquationBlock: Bool,
212-
ignoreEscapedCharacters: Bool,
213-
ignoreMarkdown: Bool
211+
ignoreStringFormatting: Bool
214212
) -> Text {
215213
// Get the component's text
216214
let text: Text
@@ -238,30 +236,38 @@ extension Component {
238236
}
239237
}
240238
else if blockRenderingMode == .alwaysInline {
241-
let input = replaceEscapedCharacters(in: originalTextTrimmingNewlines, ignoreEscapedCharacters: ignoreEscapedCharacters)
242-
if ignoreMarkdown { text = Text(input) }
243-
else { text = Text(LocalizedStringKey(input)) }
239+
text = formattedText(input: originalTextTrimmingNewlines, ignoreStringFormatting: ignoreStringFormatting)
244240
}
245241
else {
246-
let input = replaceEscapedCharacters(in: originalText, ignoreEscapedCharacters: ignoreEscapedCharacters)
247-
if ignoreMarkdown { text = Text(input) }
248-
else { text = Text(LocalizedStringKey(input)) }
242+
text = formattedText(input: originalText, ignoreStringFormatting: ignoreStringFormatting)
249243
}
250244

251245
return text
252246
}
253247

254-
/// Replaces the escaped characters in the input text if the component type is
255-
/// `text` and ignore escaped characters is false.
248+
/// Formats the input text and returns a text view.
256249
///
257250
/// - Parameters:
258-
/// - text: The text to replace.
259-
/// - ignoreEscapedCharacters: Whether escaped characters should be ingored
260-
/// or replaced.
261-
/// - Returns: The replaced text.
262-
func replaceEscapedCharacters(in text: String, ignoreEscapedCharacters: Bool) -> String {
263-
guard type == .text && !ignoreEscapedCharacters else { return text }
264-
return Replacer.replace(text)
251+
/// - input: The plaintext to format.
252+
/// - ignoreStringFormatting: Whether the method should ignore formatting.
253+
/// - Returns: A text view.
254+
func formattedText(input: String, ignoreStringFormatting: Bool) -> Text {
255+
if ignoreStringFormatting {
256+
return Text(input)
257+
}
258+
else {
259+
do {
260+
return Text(try AttributedString(
261+
markdown: input,
262+
options: AttributedString.MarkdownParsingOptions(
263+
allowsExtendedAttributes: true,
264+
interpretedSyntax: .inlineOnlyPreservingWhitespace,
265+
failurePolicy: .returnPartiallyParsedIfPossible)))
266+
}
267+
catch {
268+
return Text(input)
269+
}
270+
}
265271
}
266272

267273
}

0 commit comments

Comments
 (0)