Skip to content

Commit 26a8be0

Browse files
committed
Added the ability to set custom tags.
1 parent 0eb1490 commit 26a8be0

File tree

6 files changed

+113
-50
lines changed

6 files changed

+113
-50
lines changed

AttributedTextExample/AttributedTextExample.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@
283283
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
284284
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
285285
CODE_SIGN_STYLE = Automatic;
286-
CURRENT_PROJECT_VERSION = "1.1(1)";
286+
CURRENT_PROJECT_VERSION = "1.2(1)";
287287
DEVELOPMENT_ASSET_PATHS = "\"AttributedTextExample/Preview Content\"";
288288
ENABLE_PREVIEWS = YES;
289289
INFOPLIST_FILE = AttributedTextExample/Info.plist;
@@ -292,7 +292,7 @@
292292
"$(inherited)",
293293
"@executable_path/Frameworks",
294294
);
295-
MARKETING_VERSION = 1.1;
295+
MARKETING_VERSION = 1.2;
296296
PRODUCT_BUNDLE_IDENTIFIER = com.iaenhaall.AttributedTextExample;
297297
PRODUCT_NAME = "$(TARGET_NAME)";
298298
SWIFT_VERSION = 5.0;
@@ -306,7 +306,7 @@
306306
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
307307
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
308308
CODE_SIGN_STYLE = Automatic;
309-
CURRENT_PROJECT_VERSION = "1.1(1)";
309+
CURRENT_PROJECT_VERSION = "1.2(1)";
310310
DEVELOPMENT_ASSET_PATHS = "\"AttributedTextExample/Preview Content\"";
311311
ENABLE_PREVIEWS = YES;
312312
INFOPLIST_FILE = AttributedTextExample/Info.plist;
@@ -315,7 +315,7 @@
315315
"$(inherited)",
316316
"@executable_path/Frameworks",
317317
);
318-
MARKETING_VERSION = 1.1;
318+
MARKETING_VERSION = 1.2;
319319
PRODUCT_BUNDLE_IDENTIFIER = com.iaenhaall.AttributedTextExample;
320320
PRODUCT_NAME = "$(TARGET_NAME)";
321321
SWIFT_VERSION = 5.0;

AttributedTextExample/AttributedTextExample/AttributedTextExampleApp.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,21 @@
66
//
77

88
import SwiftUI
9+
import AttributedText
910

1011
@main
1112
struct AttributedTextExampleApp: App {
13+
init() {
14+
// Uncomment to override the default modifier values.
15+
// AttributedText.tags = [
16+
// "h1": { $0.font(.footnote) },
17+
// "i": { $0.foregroundColor(.gray) },
18+
// "u": { $0.foregroundColor(.blue) },
19+
// "b": { $0.foregroundColor(.green) },
20+
// "sup": { $0.baselineOffset(-10).font(.title) }
21+
// ]
22+
}
23+
1224
var body: some Scene {
1325
WindowGroup {
1426
ContentView()

AttributedTextExample/AttributedTextExample/ContentView.swift

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,36 @@ import SwiftUI
99
import AttributedText
1010

1111
struct ContentView: View {
12+
private let text: String = "<h1>A unit</h1> of <i>length</i> <unknown>equal to</unknown> <b>one hundred-millionth of a centimetre</b>, 10<sup>−10</sup> metre, used mainly to express <u>wavelengths and interatomic distances</u>."
13+
private let tags: Dictionary<String, (Text) -> (Text)> = [
14+
"h1": { $0.italic() },
15+
"i": { $0.foregroundColor(.orange) },
16+
"u": { $0.foregroundColor(.purple) },
17+
"b": { $0.foregroundColor(.yellow) },
18+
"sup": { $0.bold() }
19+
]
20+
1221
var body: some View {
13-
AttributedText("<h1>A unit</h1> of <i>length</i> <unknown>equal to</unknown> <b>one hundred-millionth of a centimetre</b>, 10<sup>−10</sup> metre, used mainly to express <u>wavelengths and interatomic distances</u>.")
14-
.foregroundColor(.red)
15-
.font(.title3)
16-
.padding()
22+
VStack(spacing: 20) {
23+
Group {
24+
// Uses the default values.
25+
AttributedText(text)
26+
27+
Divider()
28+
29+
// Uses the default values, augmented by the standard foregroundColor and font modifiers.
30+
AttributedText(text)
31+
.foregroundColor(.red)
32+
.font(.title3)
33+
34+
Divider()
35+
36+
// Uses its custom modifiers.
37+
AttributedText(text, tags: tags)
38+
}
39+
.fixedSize(horizontal: false, vertical: true)
40+
}
41+
.padding()
1742
}
1843
}
1944

README.md

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,39 @@ You can clone the repo and run the **AttributedTextExample** project to explore
2222

2323
These are the main points to pay attention to.
2424

25-
1. Basic modifiers can still be applied, such as changing the font and color of the text.
25+
1. You can define the tags you need or use the defaults.
26+
27+
You need to set the required tags and provide associated closures. Each closure must be a modifier that is applied to the **SwiftUI Text View** when a specific tag is encountered.
28+
29+
##### Override the default values, for example at application launch.
30+
31+
```swift
32+
@main
33+
struct ExampleApp: App {
34+
init() {
35+
AttributedText.tags = [
36+
"b": { $0.bold() },
37+
"i": { $0.italic() }
38+
]
39+
}
40+
}
41+
```
42+
43+
In this case only **\<b\>** and **\<i\>** tags will be processed. All other tags will be ignored or deleted.
44+
45+
##### Set the custom values for each instance.
46+
47+
```swift
48+
private let tags: Dictionary<String, (Text) -> (Text)> = [
49+
// Set the necessary values.
50+
]
51+
52+
var body: some View {
53+
AttributedText("Text", tags: tags)
54+
}
55+
```
56+
57+
2. Basic modifiers can still be applied, such as changing the font and color of the text.
2658

2759
**Code example:**
2860

@@ -36,7 +68,7 @@ These are the main points to pay attention to.
3668

3769
![1 feature](./Images/1%20feature.png)
3870

39-
2. Handles unopened/unclosed tags.
71+
3. Handles unopened/unclosed tags.
4072

4173
**Code example:**
4274

@@ -48,7 +80,7 @@ These are the main points to pay attention to.
4880

4981
![2 feature](./Images/2%20feature.png)
5082

51-
3. Supports overlapping tags.
83+
4. Supports overlapping tags.
5284

5385
**Code example:**
5486

@@ -60,7 +92,7 @@ These are the main points to pay attention to.
6092

6193
![3 feature](./Images/3%20feature.png)
6294

63-
4. Deletes tags that have no modifiers.
95+
5. Deletes tags that have no modifiers.
6496

6597
**Code example:**
6698

@@ -71,8 +103,8 @@ These are the main points to pay attention to.
71103
**Result:**
72104

73105
![4 feature](./Images/4%20feature.png)
74-
75-
5. Does **not** handle HTML characters such as `&amp;`.
106+
107+
6. Does **not** handle HTML characters such as `&amp;`.
76108

77109
**Code example:**
78110

@@ -83,8 +115,8 @@ These are the main points to pay attention to.
83115
**Result:**
84116

85117
![5 feature](./Images/5%20feature.png)
86-
87-
6. **Only single-word tags are supported**. Tags with more than one word or containing any characters besides **letters** or **numbers** are ignored and not removed.
118+
119+
7. **Only single-word tags are supported**. Tags with more than one word or containing any characters besides **letters** or **numbers** are ignored and not removed.
88120

89121
**Code example:**
90122

@@ -111,16 +143,4 @@ These are the main points to pay attention to.
111143

112144
1. Add **[AttributedText.swift](https://github.com/Iaenhaall/AttributedText/blob/master/Sources/AttributedText/AttributedText.swift)** and **[HTML2TextParser.swift](https://github.com/Iaenhaall/AttributedText/blob/master/Sources/AttributedText/HTML2TextParser.swift)** files to your project.
113145

114-
2. Modify or complement the **availableTags** dictionary in the **HTML2TextParser** class.
115-
116-
You need to add the required tags and provide associated closures. Each closure must be a modifier that is applied to the SwiftUI Text View when a specific tag is encountered. For example:
117-
118-
```swift
119-
private let availableTags: Dictionary<String, (Text) -> (Text)> = [
120-
"b": { $0.bold() },
121-
"i": { $0.italic() }
122-
]
123-
```
124-
125-
In this case only **\<b\>** and **\<i\>** tags will be processed. All other tags will be ignored or deleted.
126146

Sources/AttributedText/AttributedText.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,37 @@ import SwiftUI
2929
```
3030
*/
3131
public struct AttributedText: View {
32+
/// Set of supported tags and associated modifiers. This is used by default for all AttributedText
33+
/// instances except those for which this parameter is defined in the initializer.
34+
public static var tags: Dictionary<String, (Text) -> (Text)> = [
35+
// This modifier set is presented just for reference.
36+
// Set the necessary attributes and modifiers for your needs before use.
37+
"h1": { $0.font(.largeTitle) },
38+
"h2": { $0.font(.title) },
39+
"h3": { $0.font(.headline) },
40+
"h4": { $0.font(.subheadline) },
41+
"h5": { $0.font(.callout) },
42+
"h6": { $0.font(.caption) },
43+
44+
"i": { $0.italic() },
45+
"u": { $0.underline() },
46+
"s": { $0.strikethrough() },
47+
"b": { $0.fontWeight(.bold) },
48+
49+
"sup": { $0.baselineOffset(10).font(.footnote) },
50+
"sub": { $0.baselineOffset(-10).font(.footnote) }
51+
]
3252
/// Parser formatted text.
3353
private let text: Text
3454

3555
/**
3656
Creates a text view that displays formatted content.
3757

3858
- parameter htmlString: HTML-tagged string.
59+
- parameter tags: Set of supported tags and associated modifiers for a particular instance.
3960
*/
40-
public init(_ htmlString: String) {
41-
let parser = HTML2TextParser(htmlString)
61+
public init(_ htmlString: String, tags: Dictionary<String, (Text) -> (Text)>? = nil) {
62+
let parser = HTML2TextParser(htmlString, availableTags: tags == nil ? AttributedText.tags : tags!)
4263
parser.parse()
4364
text = parser.formattedText
4465
}

Sources/AttributedText/HTML2TextParser.swift

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import SwiftUI
1313
- warning: **Only single-word tags are supported**. Tags with more than one word or
1414
containing any characters besides **letters** or **numbers** are ignored and not removed.
1515

16-
# Notes: #
16+
# Notes:
1717
1. Handles unopened/unclosed tags.
1818
2. Deletes tags that have no modifiers.
1919
3. Does **not** handle HTML characters, for example `&lt;`.
@@ -26,32 +26,17 @@ internal class HTML2TextParser {
2626
/// Set of currently active tags.
2727
private var tags: Set<String> = []
2828
/// Set of supported tags and associated modifiers.
29-
private let availableTags: Dictionary<String, (Text) -> (Text)> = [
30-
// This modifier set is presented just for reference.
31-
// Set the necessary attributes and modifiers for your needs before use.
32-
"h1": { $0.font(.largeTitle) },
33-
"h2": { $0.font(.title) },
34-
"h3": { $0.font(.headline) },
35-
"h4": { $0.font(.subheadline) },
36-
"h5": { $0.font(.callout) },
37-
"h6": { $0.font(.caption) },
38-
39-
"i": { $0.italic() },
40-
"u": { $0.underline() },
41-
"s": { $0.strikethrough() },
42-
"b": { $0.fontWeight(.bold) },
43-
44-
"sup": { $0.baselineOffset(10).font(.footnote) },
45-
"sub": { $0.baselineOffset(-10).font(.footnote) }
46-
]
29+
private let availableTags: Dictionary<String, (Text) -> (Text)>
4730

4831
/**
4932
Creates a new parser instance.
5033

5134
- parameter htmlString: HTML-tagged string.
35+
- parameter availableTags: Set of supported tags and associated modifiers.
5236
*/
53-
internal init(_ htmlString: String) {
37+
internal init(_ htmlString: String, availableTags: Dictionary<String, (Text) -> (Text)>) {
5438
self.htmlString = htmlString
39+
self.availableTags = availableTags
5540
}
5641

5742
/// Starts the text parsing process. The results of this method will be placed in the `formattedText` variable.

0 commit comments

Comments
 (0)