Skip to content

Commit d2b602d

Browse files
committed
Merge branch 'master' into swift-3
2 parents 7d5e89b + 3fdcb84 commit d2b602d

File tree

9 files changed

+209
-115
lines changed

9 files changed

+209
-115
lines changed

ActiveLabel.podspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'ActiveLabel'
3-
s.version = '0.6.0'
3+
s.version = '0.6.2'
44

55
s.author = { 'Optonaut' => '[email protected]' }
66
s.homepage = 'https://github.com/optonaut/ActiveLabel.swift'
@@ -16,6 +16,7 @@ Pod::Spec.new do |s|
1616
* Default support for Hashtags, Mentions, Links
1717
* Support for custom types via regex
1818
* Ability to enable highlighting only for the desired types
19+
* Ability to trim urls
1920
* Super easy to use and lightweight
2021
* Works as UILabel drop-in replacement
2122
* Well tested and documented

ActiveLabel.xcodeproj/project.pbxproj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
8F0249CD1B998A66005D8035 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8F0249CB1B998A66005D8035 /* LaunchScreen.storyboard */; };
1818
8F0249D31B998C00005D8035 /* ActiveLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0249D21B998C00005D8035 /* ActiveLabel.swift */; };
1919
8F0249D51B998D21005D8035 /* ActiveType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0249D41B998D21005D8035 /* ActiveType.swift */; };
20+
C1D15C791D7C9B610041D119 /* StringTrimExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D15C781D7C9B610041D119 /* StringTrimExtension.swift */; };
21+
C1D15C7B1D7C9B7E0041D119 /* ActiveBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D15C7A1D7C9B7E0041D119 /* ActiveBuilder.swift */; };
2022
C1E867D61C3D7AEA00FD687A /* RegexParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E867D51C3D7AEA00FD687A /* RegexParser.swift */; };
2123
/* End PBXBuildFile section */
2224

@@ -46,6 +48,8 @@
4648
8F0249CE1B998A66005D8035 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4749
8F0249D21B998C00005D8035 /* ActiveLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveLabel.swift; sourceTree = "<group>"; };
4850
8F0249D41B998D21005D8035 /* ActiveType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveType.swift; sourceTree = "<group>"; };
51+
C1D15C781D7C9B610041D119 /* StringTrimExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTrimExtension.swift; sourceTree = "<group>"; };
52+
C1D15C7A1D7C9B7E0041D119 /* ActiveBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveBuilder.swift; sourceTree = "<group>"; };
4953
C1E867D51C3D7AEA00FD687A /* RegexParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegexParser.swift; sourceTree = "<group>"; };
5054
/* End PBXFileReference section */
5155

@@ -99,9 +103,11 @@
99103
isa = PBXGroup;
100104
children = (
101105
8F0249A51B9989B1005D8035 /* ActiveLabel.h */,
102-
8F0249D21B998C00005D8035 /* ActiveLabel.swift */,
103106
8F0249D41B998D21005D8035 /* ActiveType.swift */,
107+
8F0249D21B998C00005D8035 /* ActiveLabel.swift */,
108+
C1D15C7A1D7C9B7E0041D119 /* ActiveBuilder.swift */,
104109
C1E867D51C3D7AEA00FD687A /* RegexParser.swift */,
110+
C1D15C781D7C9B610041D119 /* StringTrimExtension.swift */,
105111
8F0249A71B9989B1005D8035 /* Info.plist */,
106112
);
107113
path = ActiveLabel;
@@ -271,8 +277,10 @@
271277
isa = PBXSourcesBuildPhase;
272278
buildActionMask = 2147483647;
273279
files = (
280+
C1D15C791D7C9B610041D119 /* StringTrimExtension.swift in Sources */,
274281
8F0249D31B998C00005D8035 /* ActiveLabel.swift in Sources */,
275282
8F0249D51B998D21005D8035 /* ActiveType.swift in Sources */,
283+
C1D15C7B1D7C9B7E0041D119 /* ActiveBuilder.swift in Sources */,
276284
C1E867D61C3D7AEA00FD687A /* RegexParser.swift in Sources */,
277285
);
278286
runOnlyForDeploymentPostprocessing = 0;

ActiveLabel/ActiveBuilder.swift

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// ActiveBuilder.swift
3+
// ActiveLabel
4+
//
5+
// Created by Pol Quintana on 04/09/16.
6+
// Copyright © 2016 Optonaut. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
typealias ActiveFilterPredicate = ((String) -> Bool)
12+
13+
struct ActiveBuilder {
14+
15+
static func createElements(type: ActiveType, from text: String, range: NSRange, filterPredicate: ActiveFilterPredicate?) -> [ElementTuple] {
16+
switch type {
17+
case .mention, .hashtag:
18+
return createElementsIgnoringFirstCharacter(from: text, for: type, range: range, filterPredicate: filterPredicate)
19+
case .url:
20+
return createElements(from: text, for: type, range: range, filterPredicate: filterPredicate)
21+
case .custom:
22+
return createElements(from: text, for: type, range: range, minLength: 1, filterPredicate: filterPredicate)
23+
}
24+
}
25+
26+
static func createURLElements(from text: String, range: NSRange, maxChar: Int?) -> ([ElementTuple], String) {
27+
let type = ActiveType.url
28+
var text = text
29+
let matches = RegexParser.getElements(from: text, with: type.pattern, range: range)
30+
let nsstring = text as NSString
31+
var elements: [ElementTuple] = []
32+
33+
for match in matches where match.range.length > 2 {
34+
let word = nsstring.substring(with: match.range)
35+
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
36+
37+
guard let maxChar = maxChar, word.characters.count > maxChar else {
38+
let element = ActiveElement.create(with: type, text: word)
39+
elements.append((match.range, element, type))
40+
continue
41+
}
42+
43+
let trimmedWord = word.trim(to: maxChar)
44+
text = text.replacingOccurrences(of: word, with: trimmedWord)
45+
let element = ActiveElement.url(original: word, trimmed: trimmedWord)
46+
47+
let newRange = NSRange(location: match.range.location, length: trimmedWord.characters.count + 1)
48+
elements.append((newRange, element, type))
49+
}
50+
return (elements, text)
51+
}
52+
53+
private static func createElements(from text: String,
54+
for type: ActiveType,
55+
range: NSRange,
56+
minLength: Int = 2,
57+
filterPredicate: ActiveFilterPredicate?) -> [ElementTuple] {
58+
59+
let matches = RegexParser.getElements(from: text, with: type.pattern, range: range)
60+
let nsstring = text as NSString
61+
var elements: [ElementTuple] = []
62+
63+
for match in matches where match.range.length > minLength {
64+
let word = nsstring.substring(with: match.range)
65+
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
66+
if filterPredicate?(word) ?? true {
67+
let element = ActiveElement.create(with: type, text: word)
68+
elements.append((match.range, element, type))
69+
}
70+
}
71+
return elements
72+
}
73+
74+
private static func createElementsIgnoringFirstCharacter(from text: String,
75+
for type: ActiveType,
76+
range: NSRange,
77+
filterPredicate: ActiveFilterPredicate?) -> [ElementTuple] {
78+
let matches = RegexParser.getElements(from: text, with: type.pattern, range: range)
79+
let nsstring = text as NSString
80+
var elements: [ElementTuple] = []
81+
82+
for match in matches where match.range.length > 2 {
83+
let range = NSRange(location: match.range.location + 1, length: match.range.length - 1)
84+
var word = nsstring.substring(with: range)
85+
if word.hasPrefix("@") {
86+
word.remove(at: word.startIndex)
87+
}
88+
else if word.hasPrefix("#") {
89+
word.remove(at: word.startIndex)
90+
}
91+
92+
if filterPredicate?(word) ?? true {
93+
let element = ActiveElement.create(with: type, text: word)
94+
elements.append((match.range, element, type))
95+
}
96+
}
97+
return elements
98+
}
99+
}

0 commit comments

Comments
 (0)