SkillAgentSearch skills...

SwiftRichString

👩‍🎨 Elegant Attributed String composition in Swift sauce

Install / Use

/learn @malcommac/SwiftRichString

README

<p align="center" > <img src="banner.png" width=300px alt="SwiftLocation" title="SwiftLocation"> </p> <p align="center"><strong> Elegant Attributed String composition in Swift sauce</strong></p>

SwiftRichString is a lightweight library which allows to create and manipulate attributed strings easily both in iOS, macOS, tvOS and even watchOS. It provides convenient way to store styles you can reuse in your app's UI elements, allows complex tag-based strings rendering and also includes integration with Interface Builder.

Main Features

| | Features Highlights | |--- |--------------------------------------------------------------------------------- | | 🦄 | Easy styling and typography managment with coincise declarative syntax | | 🏞 | Attach local images (lazy/static) and remote images inside text | | 🧬 | Fast & high customizable XML/HTML tagged string rendering | | 🌟 | Apply text transforms within styles | | 📐 | Native support for iOS 11 Dynamic Type | | 🖇 | Support for Swift 5.1's function builder to compose strings | | ⏱ | Compact code base with no external dependencies. | | 🐦 | Fully made in Swift 5 from Swift ❥ lovers |

Easy Styling

let style = Style {
	$0.font = SystemFonts.AmericanTypewriter.font(size: 25) // just pass a string, one of the SystemFonts or an UIFont
	$0.color = "#0433FF" // you can use UIColor or HEX string!
	$0.underline = (.patternDot, UIColor.red)
	$0.alignment = .center
}
let attributedText = "Hello World!".set(style: style) // et voilà!

XML/HTML tag based rendering

SwiftRichString allows you to render complex strings by parsing text's tags: each style will be identified by an unique name (used inside the tag) and you can create a StyleXML (was StyleGroup) which allows you to encapsulate all of them and reuse as you need (clearly you can register it globally).

// Create your own styles

let normal = Style {
	$0.font = SystemFonts.Helvetica_Light.font(size: 15)
}
		
let bold = Style {
	$0.font = SystemFonts.Helvetica_Bold.font(size: 20)
	$0.color = UIColor.red
	$0.backColor = UIColor.yellow
}
		
let italic = normal.byAdding {
	$0.traitVariants = .italic
}

let myGroup = StyleXML(base: normal, ["bold": bold, "italic": italic])
let str = "Hello <bold>Daniele!</bold>. You're ready to <italic>play with us!</italic>"
self.label?.attributedText = str.set(style: myGroup)

That's the result!

<img src="Documentation_Assests/image_2.png" alt="" width=400px/>

Documentation

Other info:

<a name="styleStyleXML"/>

Introduction to Style, StyleXML, StyleRegEx

The main concept behind SwiftRichString is the use of StyleProtocol as generic container of the attributes you can apply to both String and NSMutableAttributedString. Concrete classes derivated by StyleProtocol are: Style, StyleXML and StyleRegEx.

Each of these classes can be used as source for styles you can apply to a string, substring or attributed string.

Style: apply style to strings or attributed strings

A Style is a class which encapsulate all the attributes you can apply to a string. The vast majority of the attributes of both AppKit/UIKit are currently available via type-safe properties by this class.

Creating a Style instance is pretty simple; using a builder pattern approach the init class require a callback where the self instance is passed and allows you to configure your properties by keeping the code clean and readable:

let style = Style {
	$0.font = SystemFonts.Helvetica_Bold.font(size: 20)
	$0.color = UIColor.green
	// ... set any other attribute
}

let attrString = "Some text".set(style: style) // attributed string

StyleXML: Apply styles for tag-based complex string

Style instances are anonymous; if you want to use a style instance to render a tag-based plain string you need to include it inside a StyleXML. You can consider a StyleXML as a container of Styles (but, in fact, thanks to the conformance to a common StyleProtocol's protocol your group may contains other sub-groups too).

let bodyStyle: Style = ...
let h1Style: Style = ...
let h2Style: Style = ...
let group = StyleXML(base: bodyStyle, ["h1": h1Style, "h2": h2Style])

let attrString = "Some <h1>text</h1>, <h2>welcome here</h2>".set(style: group)

The following code defines a group where:

  • we have defined a base style. Base style is the style applied to the entire string and can be used to provide a base ground of styles you want to apply to the string.
  • we have defined two other styles named h1 and h2; these styles are applied to the source string when parser encounter some text enclosed by these tags.

StyleRegEx: Apply styles via regular expressions

StyleRegEx allows you to define a style which is applied when certain regular expression is matched inside the target string/attributed string.

let emailPattern = "([A-Za-z0-9_\\-\\.\\+])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]+)"
let style = StyleRegEx(pattern: emailPattern) {
	$0.color = UIColor.red
	$0.backColor = UIColor.yellow
}
		
let attrString = "My email is hello@danielemargutti.com and my website is http://www.danielemargutti.com".(style: style!)

The result is this:

<img src="Documentation_Assests/image_4.png" alt="" width=500px/> <a name="concatenation"/>

String & Attributed String concatenation

SwiftRichString allows you to simplify string concatenation by providing custom + operator between String,AttributedString (typealias of NSMutableAttributedString) and Style.

This a an example:

let body: Style = Style { ... }
let big: Style = Style { ... }
let attributed: AttributedString = "hello ".set(style: body)

// the following code produce an attributed string by
// concatenating an attributed string and two plain string
// (one styled and another plain).
let attStr = attributed + "\(username)!".set(style:big) + ". You are welcome!"

You can also use + operator to add a style to a plain or attributed string:

// This produce an attributed string concatenating a plain
// string with an attributed string created via + operator
// between a plain string and a style
let attStr = "Hello" + ("\(username)" + big)

Finally you can concatente strings using function builders:

let bold = Style { ... }
let italic = Style { ... }
        
let attributedString = AttributedString.composing {
  "hello".set(style: bold)
  "world".set(style: italic)
}
<a name="manualstyling"/>

Apply styles to String & Attributed String

Both String and Attributed String (aka NSMutableAttributedString) has a come convenience methods you can use to create an manipulate attributed text easily via code:

Strings Instance Methods

  • set(style: String, range: NSRange? = nil): apply a globally registered style to the string (or a substring) by producing an attributed string.
  • set(styles: [String], range: NSRange? = nil): apply an ordered sequence of globally registered styles to the string (or a substring) by producing an attributed string.
  • set(style: StyleProtocol, range: NSRange? = nil): apply an instance of Style or StyleXML (to render tag-based text) to the string (or a substring) by producting an attributed string.
  • set(styles: [StyleProtocol], range: NSRange? = nil): apply a sequence of Style/StyleXML instance in order to produce a single attributes collection which will be applied to the string (or substring) to produce an attributed string.

Some examples:

// apply a globally registered style named MyStyle to the entire string
let a1: AttributedString = "Hello world".set(style: "MyStyle")

// apply a style group to the entire string
// commonStyle will be applied to the entire string as base style
// styleH1 and styleH2 will be applied only for text inside that tags.
let styleH1: Style = ...
let styleH2: Style = ...
let StyleXML = StyleXML(base: commonStyle, ["h1" : styleH1, "h2" : styleH2])
let a2: AttributedString = "Hello <h1>world</h1>, <h2>welcome here</h2>".set(style: StyleXML)

// Apply a style defined via closure to a portion of the string
let a3 = "Hello Guys!".set(Style({ $0.font = SystemFonts.Helvetica_Bold.font(size: 20) }), range: NSMakeRange(0,4))

AttributedString Instance Methods

Similar methods are also available to attributed strings.

There are three categories of methods:

  • set methods replace any existing attributes already set on target.
  • add add attributes defined by style/styles list to the target
  • remove remove attributes defined from the receiver string.

Each of this method alter the receiver instance of the attributed string and also return the same instance in output (so chaining is allowed).

Add

  • add(style: String, range: NSRange? = nil): add to existing style of string/substring a globally registered style with given name.
  • add(styles: [String], range: NSRange? = nil): add to the existing style of string/substring a style which is the sum of ordered sequences of globally registered styles with given name
View on GitHub
GitHub Stars3.2k
CategoryDevelopment
Updated7d ago
Forks210

Languages

Swift

Security Score

100/100

Audited on Mar 31, 2026

No findings