Skip to content

Commit

Permalink
Added the ability to set custom tags.
Browse files Browse the repository at this point in the history
  • Loading branch information
Iaenhaall committed May 11, 2021
1 parent 0eb1490 commit 26a8be0
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "1.1(1)";
CURRENT_PROJECT_VERSION = "1.2(1)";
DEVELOPMENT_ASSET_PATHS = "\"AttributedTextExample/Preview Content\"";
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = AttributedTextExample/Info.plist;
Expand All @@ -292,7 +292,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = com.iaenhaall.AttributedTextExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -306,7 +306,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "1.1(1)";
CURRENT_PROJECT_VERSION = "1.2(1)";
DEVELOPMENT_ASSET_PATHS = "\"AttributedTextExample/Preview Content\"";
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = AttributedTextExample/Info.plist;
Expand All @@ -315,7 +315,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = com.iaenhaall.AttributedTextExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,21 @@
//

import SwiftUI
import AttributedText

@main
struct AttributedTextExampleApp: App {
init() {
// Uncomment to override the default modifier values.
// AttributedText.tags = [
// "h1": { $0.font(.footnote) },
// "i": { $0.foregroundColor(.gray) },
// "u": { $0.foregroundColor(.blue) },
// "b": { $0.foregroundColor(.green) },
// "sup": { $0.baselineOffset(-10).font(.title) }
// ]
}

var body: some Scene {
WindowGroup {
ContentView()
Expand Down
33 changes: 29 additions & 4 deletions AttributedTextExample/AttributedTextExample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,36 @@ import SwiftUI
import AttributedText

struct ContentView: View {
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>."
private let tags: Dictionary<String, (Text) -> (Text)> = [
"h1": { $0.italic() },
"i": { $0.foregroundColor(.orange) },
"u": { $0.foregroundColor(.purple) },
"b": { $0.foregroundColor(.yellow) },
"sup": { $0.bold() }
]

var body: some View {
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>.")
.foregroundColor(.red)
.font(.title3)
.padding()
VStack(spacing: 20) {
Group {
// Uses the default values.
AttributedText(text)

Divider()

// Uses the default values, augmented by the standard foregroundColor and font modifiers.
AttributedText(text)
.foregroundColor(.red)
.font(.title3)

Divider()

// Uses its custom modifiers.
AttributedText(text, tags: tags)
}
.fixedSize(horizontal: false, vertical: true)
}
.padding()
}
}

Expand Down
60 changes: 40 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,39 @@ You can clone the repo and run the **AttributedTextExample** project to explore

These are the main points to pay attention to.

1. Basic modifiers can still be applied, such as changing the font and color of the text.
1. You can define the tags you need or use the defaults.

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.

##### Override the default values, for example at application launch.

```swift
@main
struct ExampleApp: App {
init() {
AttributedText.tags = [
"b": { $0.bold() },
"i": { $0.italic() }
]
}
}
```

In this case only **\<b\>** and **\<i\>** tags will be processed. All other tags will be ignored or deleted.

##### Set the custom values for each instance.

```swift
private let tags: Dictionary<String, (Text) -> (Text)> = [
// Set the necessary values.
]

var body: some View {
AttributedText("Text", tags: tags)
}
```

2. Basic modifiers can still be applied, such as changing the font and color of the text.

**Code example:**

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

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

2. Handles unopened/unclosed tags.
3. Handles unopened/unclosed tags.

**Code example:**

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

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

3. Supports overlapping tags.
4. Supports overlapping tags.

**Code example:**

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

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

4. Deletes tags that have no modifiers.
5. Deletes tags that have no modifiers.

**Code example:**

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

![4 feature](./Images/4%20feature.png)
5. Does **not** handle HTML characters such as `&amp;`.

6. Does **not** handle HTML characters such as `&amp;`.

**Code example:**

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

![5 feature](./Images/5%20feature.png)
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.

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.

**Code example:**

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

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.

2. Modify or complement the **availableTags** dictionary in the **HTML2TextParser** class.

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:

```swift
private let availableTags: Dictionary<String, (Text) -> (Text)> = [
"b": { $0.bold() },
"i": { $0.italic() }
]
```

In this case only **\<b\>** and **\<i\>** tags will be processed. All other tags will be ignored or deleted.

25 changes: 23 additions & 2 deletions Sources/AttributedText/AttributedText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,37 @@ import SwiftUI
```
*/
public struct AttributedText: View {
/// Set of supported tags and associated modifiers. This is used by default for all AttributedText
/// instances except those for which this parameter is defined in the initializer.
public static var tags: Dictionary<String, (Text) -> (Text)> = [
// This modifier set is presented just for reference.
// Set the necessary attributes and modifiers for your needs before use.
"h1": { $0.font(.largeTitle) },
"h2": { $0.font(.title) },
"h3": { $0.font(.headline) },
"h4": { $0.font(.subheadline) },
"h5": { $0.font(.callout) },
"h6": { $0.font(.caption) },

"i": { $0.italic() },
"u": { $0.underline() },
"s": { $0.strikethrough() },
"b": { $0.fontWeight(.bold) },

"sup": { $0.baselineOffset(10).font(.footnote) },
"sub": { $0.baselineOffset(-10).font(.footnote) }
]
/// Parser formatted text.
private let text: Text

/**
Creates a text view that displays formatted content.
- parameter htmlString: HTML-tagged string.
- parameter tags: Set of supported tags and associated modifiers for a particular instance.
*/
public init(_ htmlString: String) {
let parser = HTML2TextParser(htmlString)
public init(_ htmlString: String, tags: Dictionary<String, (Text) -> (Text)>? = nil) {
let parser = HTML2TextParser(htmlString, availableTags: tags == nil ? AttributedText.tags : tags!)
parser.parse()
text = parser.formattedText
}
Expand Down
25 changes: 5 additions & 20 deletions Sources/AttributedText/HTML2TextParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import SwiftUI
- warning: **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.
# Notes: #
# Notes:
1. Handles unopened/unclosed tags.
2. Deletes tags that have no modifiers.
3. Does **not** handle HTML characters, for example `&lt;`.
Expand All @@ -26,32 +26,17 @@ internal class HTML2TextParser {
/// Set of currently active tags.
private var tags: Set<String> = []
/// Set of supported tags and associated modifiers.
private let availableTags: Dictionary<String, (Text) -> (Text)> = [
// This modifier set is presented just for reference.
// Set the necessary attributes and modifiers for your needs before use.
"h1": { $0.font(.largeTitle) },
"h2": { $0.font(.title) },
"h3": { $0.font(.headline) },
"h4": { $0.font(.subheadline) },
"h5": { $0.font(.callout) },
"h6": { $0.font(.caption) },

"i": { $0.italic() },
"u": { $0.underline() },
"s": { $0.strikethrough() },
"b": { $0.fontWeight(.bold) },

"sup": { $0.baselineOffset(10).font(.footnote) },
"sub": { $0.baselineOffset(-10).font(.footnote) }
]
private let availableTags: Dictionary<String, (Text) -> (Text)>

/**
Creates a new parser instance.
- parameter htmlString: HTML-tagged string.
- parameter availableTags: Set of supported tags and associated modifiers.
*/
internal init(_ htmlString: String) {
internal init(_ htmlString: String, availableTags: Dictionary<String, (Text) -> (Text)>) {
self.htmlString = htmlString
self.availableTags = availableTags
}

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

0 comments on commit 26a8be0

Please sign in to comment.