Convert text with HTML tags, links, hashtags, mentions into NSAttributedString. Make them clickable with UILabel drop-in replacement.

Overview


Language: Swift CocoaPods Carthage

Atributika is an easy and painless way to build NSAttributedString. It is able to detect HTML-like tags, links, phone numbers, hashtags, any regex or even standard ios data detectors and style them with various attributes like font, color, etc. Atributika comes with drop-in label replacement AttributedLabel which is able to make any detection clickable

Intro

NSAttributedString is really powerful but still a low level API which requires a lot of work to setup things. It is especially painful if string is template and real content is known only in runtime. If you are dealing with localizations, it is also not easy to build NSAttributedString.

Oh wait, but you can use Atributika!

let b = Style("b").font(.boldSystemFont(ofSize: 20)).foregroundColor(.red)
        
label.attributedText = "Hello <b>World</b>!!!".style(tags: b).attributedString

Yeah, that's much better. Atributika is easy, declarative, flexible and covers all the raw edges for you.

Features

  • NEW! AttributedLabel is a drop-in label replacement which makes detections clickable and style them dynamically for normal/highlighted/disabled states.
  • detect and style HTML-like tags using custom speedy parser
  • detect and style hashtags and mentions (i.e. #something and @someone)
  • detect and style links and phone numbers
  • detect and style regex and NSDataDetector patterns
  • style whole string or just particular ranges
  • ... and you can chain all above to parse some uber strings!
  • clean and expressive api to build styles
  • separate set of detection utils, in case you want to use just them
  • + operator to concatenate NSAttributedString with other attributed or regular strings
  • works on iOS, tvOS, watchOS, macOS

Examples

Detect and style tags, provide base style for the rest of string, don't forget about special html symbols

let redColor = UIColor(red:(0xD0 / 255.0), green: (0x02 / 255.0), blue:(0x1B / 255.0), alpha:1.0)
let a = Style("a").foregroundColor(redColor)

let font = UIFont(name: "AvenirNext-Regular", size: 24)!
let grayColor = UIColor(white: 0x66 / 255.0, alpha: 1)
let all = Style.font(font).foregroundColor(grayColor)

let str = "<a>&lt;a&gt;</a>tributik<a>&lt;/a&gt;</a>"
    .style(tags: a)
    .styleAll(all)
    .attributedString

Detect and style hashtags and mentions

let str = "#Hello @World!!!"
    .styleHashtags(Style.font(.boldSystemFont(ofSize: 45)))
    .styleMentions(Style.foregroundColor(.red))
    .attributedString

Detect and style links

let str = "Check this website http://google.com"
    .styleLinks(Style.foregroundColor(.blue))
    .attributedString

Detect and style phone numbers

let str = "Call me (888)555-5512"
    .stylePhoneNumbers(Style.foregroundColor(.red))
    .attributedString

Uber String

    let links = Style.foregroundColor(.blue)
    let phoneNumbers = Style.backgroundColor(.yellow)
    let mentions = Style.font(.italicSystemFont(ofSize: 12)).foregroundColor(.black)
    let b = Style("b").font(.boldSystemFont(ofSize: 12))
    let u = Style("u").underlineStyle(.styleSingle)
    let all = Style.font(.systemFont(ofSize: 12)).foregroundColor(.gray)
    
    let str = "@all I found <u>really</u> nice framework to manage attributed strings. It is called <b>Atributika</b>. Call me if you want to know more (123)456-7890 #swift #nsattributedstring https://github.com/psharanda/Atributika"
        .style(tags: u, b)
        .styleMentions(mentions)
        .styleHashtags(links)
        .styleLinks(links)
        .stylePhoneNumbers(phoneNumbers)
        .styleAll(all)
        .attributedString

AttributedText

Atributika APIs styleXXX produce AttributedText which can be converted into NSAttributedString. Basically AttributedText just contains string, base style and all the detections.

AttributedLabel

AttributedLabel is able to display AttributedText and makes detections clickable if style contains any attributes for .highlighted

let tweetLabel = AttributedLabel()

tweetLabel.numberOfLines = 0

let all = Style.font(.systemFont(ofSize: 20))
let link = Style("a")
    .foregroundColor(.blue, .normal)
    .foregroundColor(.brown, .highlighted) // <-- detections with this style will be clickable now

tweetLabel.attributedText = "@e2F If only Bradley's arm was longer. Best photo ever.😊 #oscars https://pic.twitter.com/C9U5NOtGap<br>Check this <a href=\"https://github.com/psharanda/Atributika\">link</a>"
    .style(tags: link)
    .styleHashtags(link)
    .styleMentions(link)
    .styleLinks(link)
    .styleAll(all)

tweetLabel.onClick = { label, detection in
            switch detection.type {
            case .hashtag(let tag):
                if let url = URL(string: "https://twitter.com/hashtag/\(tag)") {
                    UIApplication.shared.openURL(url)
                }
            case .mention(let name):
                if let url = URL(string: "https://twitter.com/\(name)") {
                    UIApplication.shared.openURL(url)
                }
            case .link(let url):
                UIApplication.shared.openURL(url)
            case .tag(let tag):
                if tag.name == "a", let href = tag.attributes["href"], let url = URL(string: href) {
                    UIApplication.shared.openURL(url)
                }
            default:
                break
            }
        }

view.addSubview(tweetLabel)

Requirements

Current version is compatible with:

  • Swift 4.0+ (for Swift 3.2 use swift-3.2 branch)
  • iOS 8.0 or later
  • tvOS 9.0 or later
  • watchOS 2.0 or later
  • macOS 10.10 or later

Note: AttributedLabel works only on iOS

Why does Atributika have one 't' in its name?

Because in Belarusian/Russian we have one letter 't' (атрыбутыка/атрибутика). So basically it is transcription, not real word.

Integration

Carthage

Add github "psharanda/Atributika" to your Cartfile

CocoaPods

Atributika is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "Atributika"

Manual

  1. Add Atributika to you project as a submodule using git submodule add https://github.com/psharanda/Atributika.git
  2. Open the Atributika folder & drag Atributika.xcodeproj into your project tree
  3. Add Atributika.framework to your target's Link Binary with Libraries Build Phase
  4. Import Atributika with import Atributika and you're ready to go

License

Atributika is available under the MIT license. See the LICENSE file for more info.

Comments
  • 4.4.0 And missing Symbols

    4.4.0 And missing Symbols

    Just pod install'd 4.4.0 and am getting the following:

    Undefined symbols for architecture arm64:
      "protocol witness table for __C.NSAttributedStringKey : Swift.Hashable in Foundation", referenced from:
          function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Dead> of generic specialization <preserving fragile attribute, Atributika.StyleType, [__C.NSAttributedStringKey : Any]> of static (extension in Swift):Swift._NativeDictionaryBuffer< where A: Swift.Hashable>.fromArray([(A, B)]) -> Swift._NativeDictionaryBuffer<A, B> in RegulationDetailController.o
    ld: symbol(s) not found for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    I'm not sure this is actually Atributika's problem yet but it's in the error so I thought I"d put it here while I try to track down what is going on. Anyone else see this?

    opened by rblalock 17
  • Detection Button frame issue when using custom font

    Detection Button frame issue when using custom font

    I have integrated this in tableview cells with automatic layout. Text is displayed properly, however button frame for touch detection appears to be incorrect. PFA the log and the xcode view debugger image. You can check 3 butons frame's. Frame for the 5 points is completely off the track.

    button issue

    points1.txt

    bug 
    opened by Ankish 11
  • A-Tags

    A-Tags

    Hey! I'm trying to figure out how to convert <a> Tags into clickable links. I tried .style(links:) but that wouldn't work. Do I miss something very obvious?

    opened by 343max 10
  • Style.swift Crash

    Style.swift Crash

    Hi , Style.Swift line 84 and AttributedText.swift line 99 crash , swift 4.1 , Xcode 9 latest version , ios 11 , just copy pasted your "link" and "all" code and crashesh without doing anything else here's the code : `let tweetLabel = AttributedLabel()

        let all = Style.font(.systemFont(ofSize: 20))
        let link = Style
            .foregroundColor(.blue, .normal)
    
    
        tweetLabel.attributedText = "@Hey"
            .styleHashtags(link)
            .styleMentions(link)
            .styleLinks(link)
            .styleAll(all)`
    

    adding .foregroundColor(.brown, .highlighted) to link will result. style.swift to crash o.w AttributeText.swift does

    opened by Mahan3340 10
  • styleMentions returning wrong array detection when used with Korean tags

    styleMentions returning wrong array detection when used with Korean tags

    I have used Atributika Pod in achieving one of the task in my project. I have attributed textview in which mentions, links, hashtags are used. While resetting the attributes of the textview and sending it over the web service I need to extract all the attributed text of the textview which I do using styleMentions(which returns detections array) of Atributika. When mentions are in english it returns one detection for one mention but when Korean mentions are there it returns multiple detections sometimes. Please find textfile attached of the array detections. If you search for the key "mention" you will get 5 results whereas I should have only two one for each mention.

    I have used these two lines of code to extract the detections: let attArray = self.textviewEditMode?.attributedText.styleMentions(.backgroundColor(Fp_s29.color)) let detections = attArray?.detections whereas, textviewEditMode- is my UITextview Fp_s29.color- is my predefined color

    Please let me know if something needs to be done. Thank you!

    mentionsDetection.zip

    opened by manisingh41 9
  • Handling unavailable fonts/font trait combinations (styles)

    Handling unavailable fonts/font trait combinations (styles)

    Hi there!

    I've been trying out Atributika to see if it could be a fit for my project to replace the current (and slow) implementation with plain NSAttributedString (from HTML).

    I've got it working ~90%. An issue I have been facing since implementing this feature, even with the NSAttributedString implementation, is that I (currently) do not own the font we use in all different combinations of bold, italic, underlined, etc. Though the one we are currently mostly facing is bold + italic.

    In our current implementation we used the following code snippet to basically fall back to a similarly looking free font in such cases:

    extension NSMutableAttributedString {
        func setBaseFont(baseFont: UIFont, preserveFontSizes: Bool = false) {
            let baseDescriptor = baseFont.fontDescriptor
            let wholeRange = NSRange(location: 0, length: length)
            let fallbackFont = UIFont(name: "HelveticaNeue-Light", size: 15)!
    
            beginEditing()
            enumerateAttribute(.font, in: wholeRange, options: []) { object, range, _ in
                guard let font = object as? UIFont else { return }
                var descriptor: UIFontDescriptor
                var newSize: CGFloat
                let traits = font.fontDescriptor.symbolicTraits
    
                if traits.contains(.traitItalic) {
                    descriptor = fallbackFont.fontDescriptor.withSymbolicTraits(traits)!
                    newSize = descriptor.pointSize
                } else if traits.contains(.traitBold) {
                    descriptor = baseDescriptor.withSymbolicTraits(traits)!
                    newSize = preserveFontSizes ? descriptor.pointSize : baseDescriptor.pointSize
                } else {
                    descriptor = baseDescriptor
                    newSize = preserveFontSizes ? descriptor.pointSize : baseDescriptor.pointSize
                }
    
                let newFont = UIFont(descriptor: descriptor, size: newSize)
                self.removeAttribute(.font, range: range)
                self.addAttribute(.font, value: newFont, range: range)
            }
            endEditing()
        }
    }
    

    Is there something similar to achieve this in Atributika? I know that the easiest way would be to buy the missing combos, but I currently do not have the budget for that.

    Could this be done using the tuner: variant of .style(...)?

    I hope you could help me out with this.

    Happy holidays!

    enhancement 
    opened by philhinco 7
  • Index out of bounds on Add Detection button for strings with emoji and link

    Index out of bounds on Add Detection button for strings with emoji and link

    I don't know if it's only me. But text with emoji causes a crash on addDetectionAreaButton:

    Here's how a similar one was solved 😄 \nhttps://medium.com/@narcelio/solving-decred-mockingbird-puzzle-5366efeaeed7\n
    
    opened by denniskeithgaso 7
  • Tags at start of text apply throughout text.

    Tags at start of text apply throughout text.

    Starting text with a tag applies that tag throughout, even though there is a matching end tag.

    "Save $1.00 on any order!" comes out all bold.

    "Save $1.00 on any order!" correctly bolds only the two sections.

    With this call:

                let desc = Atributika(text: text,
                                      styles: [
                                        "b" : [.font( UIFont.boldSystemFont(ofSize: 14))]
                    ],
                                      baseStyle: [
                                        .font( UIFont.systemFont(ofSize: 14)), .foregroundColor(UIColor.red)
                    ])
                    .buildAttributedString()
    
    opened by graham-perks-snap 6
  • Emoji Support

    Emoji Support

    I'm currently working with Atributika and my use-case specifically applies to the hashtag functionality. I have noticed that the parser doesn't seem to include emojis in the tag and I was wondering if any of you have a fix/workaround for this?

    To just give you all an example, let's say the hashtag I'm working with is #Atributika❤️, but the parser will only parse up to #Atributika and ignores the emoji.

    let font = Style.font(UIFont.init(name: "OpenSans", size: 12)!).foregroundColor(UIColor.lightGray)
    
    let contentStyling = Style("a")
        .foregroundColor(UIColor.lightGray, .normal)
        .foregroundColor(UIColor.white, .highlighted)
    
    label.lineBreakMode = .byWordWrapping
    label.numberOfLines = 0
    label.attributedText = #Atributika❤️
        .style(tags: contentStyling)
        .styleHashtags(contentStyling)
        .styleMentions(contentStyling)
        .styleLinks(contentStyling)
        .styleAll(font)
    
    label.frame = CGRect(x: 185, y: 140, width: 165, height: 90)
    
    label.onClick = { label, detection in
                switch detection.type {
                case .hashtag(let tag):
                    var passTag = ["tag":"#\(tag)"]
                    self.tapTag = true
                    self.dismiss(animated: true, completion: nil)
                    SVProgressHUD.show(withStatus: "Loading projects")
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "NotificationID"), object: nil, userInfo: passTag as [AnyHashable : Any])
    
                case .mention( _): break
                case .link( _): break
                case .tag( _): break
                default: break
                }
            }
    
    view.addSubview(label)
    
    
    opened by qxtaiba 5
  • Paragraph tag (<p>) doesn't start from new line

    Paragraph tag (

    ) doesn't start from new line

    The below text with paragraph tags doesn't start from new line on every

    tag.

    <p> The first line of the text.</p><p>This second line should start a new paragraph. but it doesn't</p>

    How can I get it working?

    opened by tarun-personatech 5
  • Missing libSwiftCoreGraphics.tbd in project's

    Missing libSwiftCoreGraphics.tbd in project's

    When I upgrade my Xcode to 14, my app crashed and Get an error message: dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib

    It's only happen on devices with iOS version below 13,like iOS 12/11.

    opened by zoloyy 0
  • Fix infinite loop when using `<` or `&` characters with diacritic

    Fix infinite loop when using `<` or `&` characters with diacritic

    The infinite loop problem is caused by different diacritic handling policies. NSScanner.scanUpToCharacters(from:) is not diacritic sensitive but `NSScanner.scanString(_:) is diacritic sensitive.

    opened by wplong11 0
  • Not support SwiftUI

    Not support SwiftUI

    I used Atributika and it is not supported SwiftUI and text is not showing.

    func makeUIView(context: UIViewRepresentableContext) -> UIView { let view = UIView(frame: .zero) view.backgroundColor = .yellow let label = AttributedLabel() label.numberOfLines = 0 label.backgroundColor = .red label.lineBreakMode = .byWordWrapping label.font = type.font label.attributedText = text .attributedText(for: type, alignment: alignment, textColor: textColor, linkColor: linkColor) label.clipsToBounds = true label.sizeToFit() view.addSubview(label)
    label.translatesAutoresizingMaskIntoConstraints = false label.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true label.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true return view }

    func updateUIView(_ label: UIView, context: UIViewRepresentableContext<AtributikaView>) {
    
    }
    
    opened by sharvanksapient 0
  • tag a has problem when set title tag a like url

    tag a has problem when set title tag a like url

    when string tag a is <a href="https://food.trueid.net/detail/WeX36y1rkg7J">www.food.trueid.net Atributika detect title not url in href

    opened by sk-chanch 1
Releases(4.10.1)
Owner
Pavel Sharanda
iOS Developer
Pavel Sharanda
A drop-in replacement for UILabel that supports attributes, data detectors, links, and more

TTTAttributedLabel A drop-in replacement for UILabel that supports attributes, data detectors, links, and more TTTAttributedLabel is a drop-in replace

TTTAttributedLabel 8.8k Dec 30, 2022
UILabel replacement with fine-grain appear/disappear animation

ZCAnimatedLabel UILabel-like view with easy to extend appear/disappear animation Features Rich text support (with NSAttributedString) Group aniamtion

Chen 2.3k Dec 5, 2022
KDEDateLabel is an UILabel subclass that updates itself to make time ago's format easier.

KDEDateLabel KDEDateLabel is an UILabel subclass that saves you from refreshing it when using 'time ago' format. Installation You have multiple choice

Kevin Delannoy 117 May 16, 2022
UILabel subclass, which additionally allows shadow blur, inner shadow, stroke text and fill gradient.

THLabel THLabel is a subclass of UILabel, which additionally allows shadow blur, inner shadow, stroke text and fill gradient. Requirements iOS 4.0 or

Tobias Hagemann 654 Nov 27, 2022
Simple countdown UILabel with morphing animation, and some useful function.

CountdownLabel Simple countdown UILabel with morphing animation, and some useful function. features Simple creation Easily get status of countdown fro

keishi suzuki 903 Dec 29, 2022
Glitching UILabel for iOS 📺

Glitching UILabel for iOS ?? Created by Lee Sun-Hyoup. Try the sample $ pod try GlitchLabel Requirements iOS 8.0+ Swift 3 Xcode 8 Installation CocoaP

Lee Sun-Hyoup 1k Dec 14, 2022
Incrementable UILabel for iOS and tvOS

IncrementableLabel IncrementableLabel is the easiest way to have incrementable numbers in an UILabel! Usage let myIncrementableLabel = IncrementableLa

Tom Baranes 81 Feb 4, 2022
A morphing UILabel subclass written in Swift.

LTMorphingLabel A morphing UILabel subclass written in Swift. The .Scale effect mimicked Apple's QuickType animation of iOS 8 of WWDC 2014. New morphi

Lex Tang 7.9k Jan 4, 2023
UILabel with image placed from left or right

SMIconLabel UILabel with possibility to place small icon on the left or on the right side. Take a look at preview image or build sample app to see how

Anatoliy Voropay 94 Apr 27, 2022
A handy class for iOS to use UILabel as a countdown timer or stopwatch just like in Apple Clock App.

MZTimerLabel Purpose MZTimerLabel is a UILabel subclass, which is a handy way to use UILabel as a countdown timer or stopwatch just like that in Apple

Mines Chan 1.6k Dec 14, 2022
MTLLinkLabel is linkable UILabel. Written in Swift.

# MTLLinkLabel is linkable UILabel. Written in Swift. Requirements iOS 8.0+ Xcode 7.3+ Installation Carthage You can install Carthage with Homebrew. $

Recruit Holdings. Media Technology Lab 74 Jul 1, 2022
Adds animated counting support to UILabel.

UICountingLabel Adds animated counting support to UILabel. CocoaPods UICountingLabel is available on CocoaPods. Add this to your Podfile: pod 'UICount

Tim Gostony 1.9k Dec 1, 2022
A simple designable subclass on UILabel with extra IBDesignable and Blinking features.

JSLabel Demo pod try JSLabel ...or clone this repo and build and run/test the JSLabel project in Xcode to see JSLabel in action. If you don't have Coc

Jogendra 6 May 9, 2022
Swift TTTAttributedLabel replacement

Nantes ?? This library is a Swift port/fork of the popular Objective-C library TTTAttributedLabel. Much ❤️ and credit goes to Mattt for creating such

Instacart 1k Dec 22, 2022
Lightweight library to set an Image as text background. Written in swift.

Simple and light weight UIView that animate text with an image.

Lucas Ortis 552 Sep 9, 2022
Configurable morphing transitions between text values of a label.

TOMSMorphingLabel Configurable morphing transitions between text values of a label. Triggering the animation is as easy as setting the labels text pro

Tom König 1.9k Nov 20, 2022
Secret app like text animation

RQShineLabel A UILabel subclass that lets you animate text similar to Secret app. Installation CocoaPods RQShineLabel is available through CocoaPods,

gk 2k Dec 6, 2022
Custom Label to apply animations on whole text or letters.

Ophiuchus Custom Label to apply animations on whole text or letters. Check an article on our blog Inspired by this project on Dribble Installation Coc

Yalantis 885 Dec 2, 2022
Swift UIView for sliding text with page indicator

SlidingText for Swift Requirements Requires iOS 8 or later and Xcode 6.1+ Installation SlidingText is available through CocoaPods. To install it, simp

Dionysis Karatzas 53 Mar 1, 2022