Skip to content

Commit

Permalink
swift 4 update
Browse files Browse the repository at this point in the history
  • Loading branch information
daltoniam committed Oct 6, 2017
1 parent d7e2fc9 commit 842fb80
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 583 deletions.
388 changes: 33 additions & 355 deletions BumbleBee.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
`BumbleBee` adheres to [Semantic Versioning](http://semver.org/).

#### [2.0.0](https://github.com/daltoniam/bumblebee/tree/2.0.0)

Complete refactor. Updated for Swift 4.

#### [1.0.1](https://github.com/daltoniam/bumblebee/tree/1.0.1)

addresses [#1](https://github.com/daltoniam/bumblebee/issues/1), [#2](https://github.com/daltoniam/bumblebee/issues/2), [#11](https://github.com/daltoniam/bumblebee/issues/11), [#12](https://github.com/daltoniam/bumblebee/issues/12), [#13](https://github.com/daltoniam/bumblebee/issues/13)
Expand Down
2 changes: 1 addition & 1 deletion Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
25 changes: 25 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Package.Swift
// SwiftHTTP
//
// Created by Dalton Cherry on 5/16/15.
// Copyright (c) 2014-2015 Dalton Cherry.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import PackageDescription

let package = Package(
name: "Bumblebee"
)
149 changes: 94 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
![bumblebee](http://idigitalcitizen.files.wordpress.com/2009/07/1920x1200-bumblebee88.jpg)


Bumblebee is an abstract text processing and pattern matching engine in Swift for iOS and OSX. This provides support for things like markdown and basic HTML tags to be properly converted from raw text to expected style using NSAttributedString. Example markdown engine is included.
Bumblebee is an abstract text processing and pattern matching engine in Swift (using regular expressions). This provides support for things like basic markdown tags or highlight user names, links, emails, etc. It takes a string and converts it to a NSAttributedString. Several common patterns are include to make implementation easy and quick.

## Features

- Abstract and simple. Creating patterns is simple, yet flexible.
- Fast. Only one pass is make through the raw string to minimize parse time.
- Simple concise codebase at just a few hundred LOC.

## Examples
Expand All @@ -20,58 +19,43 @@ import Bumblebee
This is a simple code example, but showcases a powerful use case.

```swift
//first we create our label to show our text
let label = UILabel(frame: CGRectMake(0, 65, view.frame.size.width, 400))
//add the label to the view
let label = UILabel(frame: CGRect(x: 0, y: 65, width: view.frame.size.width, height: 400))
label.numberOfLines = 0
view.addSubview(label)

//we create this textAttachment to show our embedded image
var textAttachment = NSTextAttachment(data: nil, ofType: nil)

//the raw text we have.
let rawText = "Hello I am *red* and I am _bold_. Here is an image: ![](http://vluxe.io/assets/images/logo.png)"
let rawText = "Hello I am *red* and I am __bold__. [link here](http://vluxe.io/) Here is an image: ![](http://imgs.xkcd.com/comics/encoding.png). This is a second link: [Apple](https://apple.com). I like *turtles*"
parser.add(pattern: MDLinkPattern()) { (str, attributes) in
let link = attributes![MDLinkPattern.linkAttribute]!
return MatchedResponse(string: str, attributes: [NSAttributedStringKey.foregroundColor: UIColor.blue,
NSAttributedStringKey.link: URL(string: link)!])
}

//create our BumbleBee object.
let bee = BumbleBee()
parser.add(pattern: MDImagePattern()) { (str, attributes) in
let link = attributes![MDImagePattern.linkAttribute]!
let textAttachment = NSTextAttachment(data: nil, ofType: nil)
HTTP.GET(link) { (response) in
let img = UIImage(data: response.data)!
textAttachment.image = UIImage(data: response.data)
textAttachment.bounds = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
DispatchQueue.main.async {
label.setNeedsDisplay() //tell our label to redraw now that we have our image
}
}
return MatchedResponse(string: str, attributes: [NSAttributedStringKey.attachment: textAttachment])
}

//our red text pattern
bee.add("*?*", recursive: false) { (pattern: String, text: String, start: Int) -> (String, [NSObject : AnyObject]?) in
let replace = pattern[advancedBy(pattern.startIndex, 1)...advancedBy(pattern.endIndex, -2)]
return (replace,[NSForegroundColorAttributeName: UIColor.redColor()])
parser.add(pattern: MDBoldPattern()) { (str, attributes) in
return MatchedResponse(string: str, attributes: [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 17)])
}
//the bold pattern
bee.add("_?_", recursive: false) { (pattern: String, text: String, start: Int) -> (String, [NSObject : AnyObject]?) in
let replace = pattern[pattern.startIndex.advancedBy(1)...pattern.endIndex.advancedBy(-2)]
return (replace,[NSFontAttributeName: UIFont.boldSystemFontOfSize(17)])

parser.add(pattern: MDEmphasisPattern()) { (str, attributes) in
return MatchedResponse(string: str, attributes: [NSAttributedStringKey.foregroundColor: UIColor.red])
}
//the image pattern
bee.add("![?](?)", recursive: false, matched: { (pattern: String, text: String, start: Int) in
let range = pattern.rangeOfString("]")
if let end = range {
let findRange = pattern.rangeOfString("(")
if let startRange = findRange {
let url = pattern[startRange.startIndex.advancedBy(1)..< pattern.endIndex.advancedBy(-1)]
//using a remote image library or your choice (ImageLibrary isn't real!), we can easily fetch the remote image
ImageLibrary.fetch(url, completion: { (data: NSData) in
let img = UIImage(data: data)
textAttachment.image = img
textAttachment.bounds = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
label.setNeedsDisplay() //tell our label to redraw now that we have our image
})
}
return (bee.attachmentString,[NSAttachmentAttributeName: textAttachment]) // embed an attachment
}
return ("",nil) //don't change anything, not a match
})
//header pattern
bee.add("##?\n", recursive: false) { (pattern: String, text: String, start: Int) -> (String, [NSObject : AnyObject]?) in
let replace = pattern[pattern.startIndex.advancedBy(2)...pattern.endIndex.advancedBy(-2)]
return (replace,[NSFontAttributeName: UIFont.systemFontOfSize(24)]) //whatever your large font is

parser.process(text: rawText) { (attrString) in
label.attributedText = attrString
}
//now that we have our patterns, we call process and get the NSAttributedString
let defaultAttrs = [NSFontAttributeName: UIFont.systemFontOfSize(18)] //default attributes to apply
let attrString = bee.process(rawText,attributes: defaultAttrs) //attributes can be omited if unneeded
label.attributedText = attrString
```

Which looks like:
Expand All @@ -80,13 +64,70 @@ Which looks like:

## Details

The `?` is the wildcard. It is simply means that any character between these opening and closing characters could be a match.
The patterns are processed with regular expressions. Creating custom patterns is accomplished be implementing the `Pattern` protocol.

```swift
//Matches URLs. e.g. (http://domain.com/url/etc)
public struct LinkPattern : Pattern {
public init() {} //only need to allow public initialization
public func regex() throws -> NSRegularExpression {
return try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
}
}

//Matches typical user name patterns from social platforms like twitter. (@daltoniam, etc)
public struct UserNamePattern : Pattern {
public init() {} //only need to allow public initialization
public func regex() throws -> NSRegularExpression {
//twitter requires between 4 and 15 char for a user name, but hightlights the user name at one char...
//so I'm using {1,15} instead of {4,15}, but could be easily changed depending on requirements
return try NSRegularExpression(pattern: "(?<=\\s|^)@[a-zA-Z0-9_]{1,15}\\b", options: .caseInsensitive)
}
}

//Matches hex strings to convert them to their proper unicode version.
public struct UnicodePattern : Pattern {
public init() {} //only need to allow public initialization
public func regex() throws -> NSRegularExpression {
return try NSRegularExpression(pattern: "(?<=\\s|^)U\\+[a-zA-Z0-9]{2,6}\\b", options: .caseInsensitive)
}

//The transform method allows a pattern to do pre processing on the text before it shows up in the matched closure.
//convert the hex to its proper Unicode scalar. e.g. (U+1F602 to 😂)
public func transform(text: String) -> (text: String, attributes: [String: String]?) {
let offset = text.index(text.startIndex, offsetBy: 2)
let hex = String(text[offset..<text.endIndex])
if let i = Int(hex, radix: 16) {
let scalar = UnicodeScalar(i)
if let scalar = scalar {
return (text: String(Character(scalar)), attributes: nil)
}
}
return (text: text, attributes: nil)
}
}

//your custom pattern!
public struct MyCustomPattern : Pattern {
public init() {} //only need to allow public initialization
public func regex() throws -> NSRegularExpression {
return try NSDataDetector(types: NSTextCheckingResult.CheckingType.address.rawValue)
}
}
```

Then just call:

```swift
//your custom pattern here!
parser.add(pattern: MyCustomPattern()) { (str, attributes) in
return MatchedResponse(string: str, attributes: [NSAttributedStringKey.foregroundColor: UIColor.purple])
}
```

##
See more examples at the bottom of the `bumblebee.swift` file.

## Requirements

Bumblebee requires at least iOS 7/OSX 10.10 or above.

## Installation

Expand All @@ -97,10 +138,10 @@ Check out [Get Started](http://cocoapods.org/) tab on [cocoapods.org](http://coc
To use Bumblebee in your project add the following 'Podfile' to your project

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
platform :ios, '10.0'
use_frameworks!

pod 'Bumblebee', '~> 1.0.1'
pod 'Bumblebee', '~> 2.0.0'

Then run:

Expand Down Expand Up @@ -136,9 +177,7 @@ If you are running this in an OSX app or on a physical iOS device you will need

## TODOs

- [ ] Complete Docs
- [ ] Add Unit Tests
- [ ] Create full markdown engine example.
- [ ] Finish Unit Tests

## License

Expand Down
Loading

0 comments on commit 842fb80

Please sign in to comment.