From e97f5112fe007280db9e78908b62ba4a9e5306cb Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Thu, 27 Sep 2012 01:01:25 +0200 Subject: [PATCH] Added some basic HTML and markup tag support to make the creation of an NSAttributedString easier (request #88) --- .../BasicDemo/BasicDemoViewController.h | 2 + .../BasicDemo/BasicDemoViewController.m | 11 ++ .../BasicDemo/BasicDemoViewController.xib | 164 ++++++++++++++---- .../project.pbxproj | 44 ++++- .../TagParsers/OHASTagParserBase.h | 59 +++++++ .../TagParsers/OHASTagParserBase.m | 114 ++++++++++++ .../TagParsers/OHASTagParserBasicMarkup.h | 22 +++ .../TagParsers/OHASTagParserBasicMarkup.m | 52 ++++++ .../TagParsers/OHASTagParserHTML.h | 24 +++ .../TagParsers/OHASTagParserHTML.m | 67 +++++++ 10 files changed, 526 insertions(+), 33 deletions(-) create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserBase.h create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserBase.m create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.h create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.m create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserHTML.h create mode 100644 OHAttributedLabel/TagParsers/OHASTagParserHTML.m diff --git a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.h b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.h index 954729d..086828a 100644 --- a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.h +++ b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.h @@ -12,6 +12,8 @@ @interface BasicDemoViewController : UIViewController @property(nonatomic, retain) IBOutlet OHAttributedLabel* demoLabel; +@property(retain, nonatomic) IBOutlet OHAttributedLabel* htmlLabel; +@property(retain, nonatomic) IBOutlet OHAttributedLabel* basicMarkupLabel; -(IBAction)fillDemoLabel; -(IBAction)changeHAlignment; diff --git a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m index 324d419..1c527fd 100644 --- a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m +++ b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m @@ -9,6 +9,8 @@ #import "BasicDemoViewController.h" #import "NSAttributedString+Attributes.h" #import "UIAlertView+Commodity.h" +#import "OHASTagParserHTML.h" +#import "OHASTagParserBasicMarkup.h" @interface BasicDemoViewController () @property(nonatomic, retain) NSMutableSet* visitedLinks; @@ -16,6 +18,8 @@ @interface BasicDemoViewController () @implementation BasicDemoViewController @synthesize demoLabel = _demoLabel; +@synthesize htmlLabel = _htmlLabel; +@synthesize basicMarkupLabel = _basicMarkupLabel; @synthesize visitedLinks = _visitedLinks; ///////////////////////////////////////////////////////////////////////////// @@ -38,6 +42,8 @@ -(void)dealloc { [_visitedLinks release]; [_demoLabel release]; + [_htmlLabel release]; + [_basicMarkupLabel release]; [super dealloc]; } #endif @@ -45,12 +51,16 @@ -(void)dealloc -(void)viewDidLoad { [self fillDemoLabel]; + self.htmlLabel.attributedText = [OHASTagParserHTML attributedStringByReplacingTagsInAttributedString:self.htmlLabel.attributedText]; + self.basicMarkupLabel.attributedText = [OHASTagParserBasicMarkup attributedStringByReplacingTagsInAttributedString:self.basicMarkupLabel.attributedText]; [super viewDidLoad]; } -(void)viewDidUnload { [super viewDidUnload]; + self.htmlLabel = nil; + self.basicMarkupLabel = nil; self.demoLabel = nil; } @@ -68,6 +78,7 @@ -(IBAction)fillDemoLabel /**(1)** Build the NSAttributedString *******/ NSMutableAttributedString* attrStr = [self.demoLabel.attributedText mutableCopy]; + [attrStr setTextAlignment:kCTCenterTextAlignment lineBreakMode:kCTLineBreakByWordWrapping]; // and only change the color of "Hello" [attrStr setTextColor:[UIColor redColor] range:NSMakeRange(26,5)]; diff --git a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.xib b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.xib index 4eeb8ac..22abdc8 100644 --- a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.xib +++ b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.xib @@ -1,14 +1,14 @@ - 1296 - 12B19 - 2549 - 1187 - 624.00 + 1536 + 12C54 + 2840 + 1187.34 + 625.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1498 + 1926 IBProxyObject @@ -39,7 +39,7 @@ 292 - {{10, 54}, {300, 130}} + {{10, 20}, {300, 130}} @@ -58,6 +58,7 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 1 MCAwIDAAA + darkTextColor 3 @@ -79,11 +80,12 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 16 NO + 300 292 - {{10, 214}, {64, 37}} + {{10, 158}, {64, 37}} @@ -117,7 +119,7 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 292 - {{82, 214}, {75, 37}} + {{82, 158}, {75, 37}} @@ -139,10 +141,10 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 292 - {{248, 214}, {62, 37}} + {{248, 158}, {62, 37}} - + NO IBCocoaTouchFramework 0 @@ -161,7 +163,7 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 292 - {{165, 214}, {75, 37}} + {{165, 158}, {75, 37}} @@ -183,7 +185,7 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 292 - {{10, 290}, {300, 45}} + {{10, 320}, {300, 45}} @@ -209,11 +211,12 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 12 16 + 300 292 - {{10, 335}, {300, 27}} + {{10, 365}, {300, 27}} NO @@ -234,12 +237,71 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 0 12 - + Helvetica 12 16 + + + 292 + {{10, 202}, {300, 72}} + + + + _NS:9 + + 1 + MSAxIDAuODAzNTg0OTI5NAA + + NO + YES + 7 + NO + IBCocoaTouchFramework + Some <b>basic</b> <font name="Courier" size="14">HTML</font> support is provided for <u>convenience</u> too. <font color="red">You can add your own parsers easily</font> by subclassing <font name="Courier" size="14">OHASTagParserBase</font> if needed. + + + 0 + 0 + 0 + + 1 + 12 + + + NO + 300 + + + + 292 + {{10, 282}, {300, 41}} + + + + _NS:9 + + 1 + MSAxIDAuOAA + + NO + YES + 7 + NO + IBCocoaTouchFramework + Some *basic* `Markup` is _also_ provided. {red|cool, isn't it?} {#80c|Enjoy}! + + + 0 + 0 + 0 + + + NO + 300 + {{0, 20}, {320, 411}} @@ -276,6 +338,22 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 21 + + + htmlLabel + + + + 23 + + + + basicMarkupLabel + + + + 25 + resetVisitedLinks @@ -353,13 +431,15 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 3 - - - - - + + + + + + + @@ -398,6 +478,16 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 + + 22 + + + + + 24 + + + @@ -407,6 +497,10 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 com.apple.InterfaceBuilder.IBCocoaTouchPlugin OHAttributedLabel com.apple.InterfaceBuilder.IBCocoaTouchPlugin + OHAttributedLabel + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + OHAttributedLabel + com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -419,7 +513,7 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 - 21 + 25 @@ -455,17 +549,25 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 id - - demoLabel - OHAttributedLabel - - - demoLabel - + + OHAttributedLabel + OHAttributedLabel + OHAttributedLabel + + + + basicMarkupLabel + OHAttributedLabel + + demoLabel OHAttributedLabel - + + htmlLabel + OHAttributedLabel + + IBProjectSource ./Classes/BasicDemoViewController.h @@ -496,10 +598,10 @@ cm5pYSAoKzEgNDA4LTk5Ni0xMDEwKSBuZXh0IHN1bmRheS4 IBCocoaTouchFramework com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - + YES 3 - 1498 + 1926 diff --git a/OHAttributedLabel/OHAttributedLabel.xcodeproj/project.pbxproj b/OHAttributedLabel/OHAttributedLabel.xcodeproj/project.pbxproj index c5f2b92..e7f48bc 100644 --- a/OHAttributedLabel/OHAttributedLabel.xcodeproj/project.pbxproj +++ b/OHAttributedLabel/OHAttributedLabel.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 09793558161393F2006DB5D5 /* OHASTagParserBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 09793556161393F2006DB5D5 /* OHASTagParserBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 09793559161393F2006DB5D5 /* OHASTagParserBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 09793557161393F2006DB5D5 /* OHASTagParserBase.m */; }; + 0979355C1613A5AE006DB5D5 /* OHASTagParserHTML.h in Headers */ = {isa = PBXBuildFile; fileRef = 0979355A1613A5AE006DB5D5 /* OHASTagParserHTML.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0979355D1613A5AE006DB5D5 /* OHASTagParserHTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 0979355B1613A5AE006DB5D5 /* OHASTagParserHTML.m */; }; + 097935601613B276006DB5D5 /* OHASTagParserBasicMarkup.h in Headers */ = {isa = PBXBuildFile; fileRef = 0979355E1613B276006DB5D5 /* OHASTagParserBasicMarkup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 097935611613B276006DB5D5 /* OHASTagParserBasicMarkup.m in Sources */ = {isa = PBXBuildFile; fileRef = 0979355F1613B276006DB5D5 /* OHASTagParserBasicMarkup.m */; }; 09E159EC160F573A003025B4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09E159EB160F573A003025B4 /* Foundation.framework */; }; 09E159FE160F57AB003025B4 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09E159FD160F57AB003025B4 /* CoreText.framework */; }; 09E15A04160F57E2003025B4 /* NSAttributedString+Attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E15A01160F57E2003025B4 /* NSAttributedString+Attributes.m */; }; @@ -21,6 +27,12 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 09793556161393F2006DB5D5 /* OHASTagParserBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OHASTagParserBase.h; sourceTree = ""; }; + 09793557161393F2006DB5D5 /* OHASTagParserBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OHASTagParserBase.m; sourceTree = ""; }; + 0979355A1613A5AE006DB5D5 /* OHASTagParserHTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OHASTagParserHTML.h; sourceTree = ""; }; + 0979355B1613A5AE006DB5D5 /* OHASTagParserHTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OHASTagParserHTML.m; sourceTree = ""; }; + 0979355E1613B276006DB5D5 /* OHASTagParserBasicMarkup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OHASTagParserBasicMarkup.h; sourceTree = ""; }; + 0979355F1613B276006DB5D5 /* OHASTagParserBasicMarkup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OHASTagParserBasicMarkup.m; sourceTree = ""; }; 09E159E8160F573A003025B4 /* libOHAttributedLabel.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOHAttributedLabel.a; sourceTree = BUILT_PRODUCTS_DIR; }; 09E159EB160F573A003025B4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 09E159FD160F57AB003025B4 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; @@ -51,6 +63,28 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 09793554161393AE006DB5D5 /* TagParsers */ = { + isa = PBXGroup; + children = ( + 09793556161393F2006DB5D5 /* OHASTagParserBase.h */, + 09793557161393F2006DB5D5 /* OHASTagParserBase.m */, + 0979355A1613A5AE006DB5D5 /* OHASTagParserHTML.h */, + 0979355B1613A5AE006DB5D5 /* OHASTagParserHTML.m */, + 0979355E1613B276006DB5D5 /* OHASTagParserBasicMarkup.h */, + 0979355F1613B276006DB5D5 /* OHASTagParserBasicMarkup.m */, + ); + path = TagParsers; + sourceTree = ""; + }; + 097935621613B419006DB5D5 /* Private Utilities */ = { + isa = PBXGroup; + children = ( + 09E15A23160F63DE003025B4 /* CoreTextUtils.h */, + 09E15A24160F63DE003025B4 /* CoreTextUtils.m */, + ); + name = "Private Utilities"; + sourceTree = ""; + }; 09E159DD160F573A003025B4 = { isa = PBXGroup; children = ( @@ -83,14 +117,14 @@ 09E159FF160F57D5003025B4 /* Source */ = { isa = PBXGroup; children = ( + 09793554161393AE006DB5D5 /* TagParsers */, 09E15A02160F57E2003025B4 /* OHAttributedLabel.h */, 09E15A03160F57E2003025B4 /* OHAttributedLabel.m */, 09E15A00160F57E2003025B4 /* NSAttributedString+Attributes.h */, 09E15A01160F57E2003025B4 /* NSAttributedString+Attributes.m */, 09E15A27160F640D003025B4 /* NSTextCheckingResult+ExtendedURL.h */, 09E15A28160F640D003025B4 /* NSTextCheckingResult+ExtendedURL.m */, - 09E15A23160F63DE003025B4 /* CoreTextUtils.h */, - 09E15A24160F63DE003025B4 /* CoreTextUtils.m */, + 097935621613B419006DB5D5 /* Private Utilities */, ); name = Source; sourceTree = ""; @@ -106,6 +140,9 @@ 09E15A22160F5DAF003025B4 /* OHAttributedLabel.h in Headers */, 09E15A25160F63DE003025B4 /* CoreTextUtils.h in Headers */, 09E15A29160F640D003025B4 /* NSTextCheckingResult+ExtendedURL.h in Headers */, + 09793558161393F2006DB5D5 /* OHASTagParserBase.h in Headers */, + 0979355C1613A5AE006DB5D5 /* OHASTagParserHTML.h in Headers */, + 097935601613B276006DB5D5 /* OHASTagParserBasicMarkup.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -164,6 +201,9 @@ 09E15A05160F57E2003025B4 /* OHAttributedLabel.m in Sources */, 09E15A26160F63DE003025B4 /* CoreTextUtils.m in Sources */, 09E15A2A160F640D003025B4 /* NSTextCheckingResult+ExtendedURL.m in Sources */, + 09793559161393F2006DB5D5 /* OHASTagParserBase.m in Sources */, + 0979355D1613A5AE006DB5D5 /* OHASTagParserHTML.m in Sources */, + 097935611613B276006DB5D5 /* OHASTagParserBasicMarkup.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/OHAttributedLabel/TagParsers/OHASTagParserBase.h b/OHAttributedLabel/TagParsers/OHASTagParserBase.h new file mode 100644 index 0000000..3493598 --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserBase.h @@ -0,0 +1,59 @@ +// +// TagParser.h +// OHAttributedLabel +// +// Created by Olivier Halligon on 26/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import +#import + +typedef NSAttributedString*(^TagProcessorBlockType)(NSAttributedString*, NSTextCheckingResult*); + +/*! + * @class OHASTagParserBase + * This is an Abstract class to be used for Tag parsers subclasses + * + * ## Subclassing notes ## + * + * Subclasses have to override the -(NSDictionary*)tagMappings method that + * has to return a dictionary whose keys are regular expression patterns + * and values are TagProcessorBlockType blocks (see typedef above). + * + * The blocks takes the unprocessed string and the regex match as input parameters + * and should return the attributedString to use as the replacement for the match. + * + * For example for the key @"(.*?)" we can have a block that return the text corresponding to + * the substring with range [match rangeAtIndex:1] (i.e. the text matched inside the parenthesis) + * with its font attribute changed to the bold font variant. + * + * @see OHASTagParserHTML implementation for an example + */ + +@interface OHASTagParserBase : NSObject + +/*! + * Call this on concrete subclasses to process tags in an NSMutableAttributedString + * and apply them (by changing the corresponding attributes) + * + * e.g. attrStr = [OHASTagParserHTML replacTagsInAttributedString:mutAttrStr]; + */ ++(void)replaceTagsInAttributedString:(NSMutableAttributedString*)mutAttrString; + +/*! + * Call this on concrete subclasses to get a parsed NSAttributedString with its attributes + * changed according to the tags in the original attributed string. + * + * Note: this convenience method simply create a mutableCopy of string and use it to call "replaceTagsInAttributedString:". + */ + ++(NSAttributedString*)attributedStringByReplacingTagsInAttributedString:(NSAttributedString*)string; + +@end + +/*! Useful common function to convert strings to colors + * Support "#rgb", "#rgba", "#rrggbb" and "#rrggbbaa" hexadecimal representations (e.g. "#ffcc00") + * Support also named colors exposed by UIColor class commodity "xxxColor" constructors, namely "red", "green", "blue", etc + */ +UIColor* UIColorFromString(NSString* colorString); diff --git a/OHAttributedLabel/TagParsers/OHASTagParserBase.m b/OHAttributedLabel/TagParsers/OHASTagParserBase.m new file mode 100644 index 0000000..4ba0364 --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserBase.m @@ -0,0 +1,114 @@ +// +// TagParser.m +// OHAttributedLabel +// +// Created by Olivier Halligon on 26/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import "OHASTagParserBase.h" + +@interface OHASTagParserBase () ++(NSDictionary*)tagMappings; // To be overloaded by subclasses +@end + +@implementation OHASTagParserBase + ++(NSDictionary*)tagMappings +{ + [NSException raise:@"OHASTagParserBase" format:@"This method should be overridden in sublcasses"]; + return nil; +} + ++(void)replaceTagsInAttributedString:(NSMutableAttributedString*)mutAttrString +{ + NSDictionary* mappings = [self tagMappings]; + + NSRegularExpressionOptions options = NSRegularExpressionAnchorsMatchLines; + [mappings enumerateKeysAndObjectsUsingBlock:^(id pattern, id obj, BOOL *stop1) + { + TagProcessorBlockType block = (TagProcessorBlockType)obj; + NSRegularExpression* regEx = [NSRegularExpression regularExpressionWithPattern:pattern options:options error:nil]; + + NSAttributedString* processedString = [mutAttrString copy]; + __block NSUInteger offset = 0; + NSRange range = NSMakeRange(0, processedString.length); + [regEx enumerateMatchesInString:processedString.string options:0 range:range + usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop2) + { + NSAttributedString* repl = block(processedString, result); + NSRange offsetRange = NSMakeRange(result.range.location - offset, result.range.length); + [mutAttrString replaceCharactersInRange:offsetRange withAttributedString:repl]; + offset += result.range.length - repl.length; + }]; + [processedString release]; + }]; + +} + ++(NSAttributedString*)attributedStringByReplacingTagsInAttributedString:(NSAttributedString*)attrString +{ + __block NSMutableAttributedString* mutAttrString = [attrString mutableCopy]; + [self replaceTagsInAttributedString:mutAttrString]; + return [mutAttrString autorelease]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - String to Color function + +UIColor* UIColorFromString(NSString* colorString) +{ + UIColor* color = nil; + if ([colorString hasPrefix:@"#"]) + { + NSScanner * hexScanner = [NSScanner scannerWithString:colorString]; + [hexScanner setScanLocation:1]; + unsigned int rgba; + [hexScanner scanHexInt:&rgba]; + switch(colorString.length) + { + case 4: // #rgb + color = [UIColor colorWithRed:((rgba>> 8)&0x0F)/15. + green:((rgba>> 4)&0x0F)/15. + blue:((rgba )&0x0F)/15. + alpha:1.0]; + break; + case 5: // #rgba + color = [UIColor colorWithRed:((rgba>>12)&0x0F)/15. + green:((rgba>> 8)&0x0F)/15. + blue:((rgba>> 4)&0x0F)/15. + alpha:((rgba )&0x0F)/15.]; + break; + case 7: // #rrggbb + color = [UIColor colorWithRed:((rgba>>16)&0xFF)/255. + green:((rgba>> 8)&0xFF)/255. + blue:((rgba )&0xFF)/255. + alpha:1.0]; + break; + case 9: // #rrggbbaa + color = [UIColor colorWithRed:((rgba>>24)&0xFF)/255. + green:((rgba>>16)&0xFF)/255. + blue:((rgba>> 8)&0xFF)/255. + alpha:((rgba )&0xFF)/255.]; + break; + } + } + else + { + // Allow "red", "green", "blue", etc… and use the corresponding redColor, greenColor, blueColor, etc… class methods of UIColor + NSString* selectorName = [NSString stringWithFormat:@"%@Color", colorString.lowercaseString]; + SEL selector = NSSelectorFromString(selectorName); + NSMethodSignature* sign = [UIColor.class methodSignatureForSelector:selector]; + // Check that the selector exists and return an NSObject/id, so that we can call it and retrieve the return value + if ([UIColor.class respondsToSelector:selector] && (0 == strcmp([sign methodReturnType],"@")) ) + { + id clr = [UIColor.class performSelector:selector]; + // Check that the returned object is really an UIColor, just in case + color = ([clr isKindOfClass:UIColor.class]) ? clr : nil; + } + } + + return color; +} diff --git a/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.h b/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.h new file mode 100644 index 0000000..921009e --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.h @@ -0,0 +1,22 @@ +// +// OHASTagParserMarkdown.h +// OHAttributedLabel +// +// Created by Olivier Halligon on 27/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import "OHASTagParserBase.h" + +/*! + * Supported tags: + * "*bold*" + * "_underline_" + * "`typewritter font`" + * Colors: + * - use "{color|text}" like in "{#fc0|some purple text}" and "{#00ff00|some green text}" + * - It also support named colors like in "{red|some red text}" "{green|some green text}", "{blue|some blue text}" + */ +@interface OHASTagParserBasicMarkup : OHASTagParserBase + +@end diff --git a/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.m b/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.m new file mode 100644 index 0000000..a6db963 --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserBasicMarkup.m @@ -0,0 +1,52 @@ +// +// OHASTagParserMarkdown.m +// OHAttributedLabel +// +// Created by Olivier Halligon on 27/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import "OHASTagParserBasicMarkup.h" +#import "NSAttributedString+Attributes.h" + +@implementation OHASTagParserBasicMarkup + ++(NSDictionary*)tagMappings +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSRange textRange = [match rangeAtIndex:1]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextBold:YES range:NSMakeRange(0,textRange.length)]; + return [foundString autorelease]; + }, @"\\*(.*?)\\*", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSRange textRange = [match rangeAtIndex:1]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextIsUnderlined:YES]; + return [foundString autorelease]; + }, @"_(.*?)_", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSRange textRange = [match rangeAtIndex:1]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + CTFontRef font = [str fontAtIndex:textRange.location effectiveRange:NULL]; + [foundString setFontName:@"Courier" size:CTFontGetSize(font)]; + return [foundString autorelease]; + }, @"`(.*?)`", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSString* colorName = [str attributedSubstringFromRange:[match rangeAtIndex:1]].string; + UIColor* color = UIColorFromString(colorName); + NSRange textRange = [match rangeAtIndex:2]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextColor:color]; + return [foundString autorelease]; + }, @"\\{(.*?)\\|(.*?)\\}", + + nil]; +} + +@end diff --git a/OHAttributedLabel/TagParsers/OHASTagParserHTML.h b/OHAttributedLabel/TagParsers/OHASTagParserHTML.h new file mode 100644 index 0000000..0c20df2 --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserHTML.h @@ -0,0 +1,24 @@ +// +// AttributedStringHTMLTagParser.h +// OHAttributedLabel +// +// Created by Olivier Halligon on 26/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import "OHASTagParserBase.h" + +/*! + * Supported tags: + * "bold text" + * "underline text" + * "some text" + * note that you have to specify both "name" and "size" attributes and in that exact order + * "some text" + * where color can be an hexadecimal color of the form "#rgb", "#rgba", "#rrggbb" or "#rrggbbaa" + * or a color name like "red" "green" "blue", "purple"… + * (the supported names correspond to the [UIColor xxxColor] commodity constructors of the UIColor class) + */ +@interface OHASTagParserHTML : OHASTagParserBase + +@end diff --git a/OHAttributedLabel/TagParsers/OHASTagParserHTML.m b/OHAttributedLabel/TagParsers/OHASTagParserHTML.m new file mode 100644 index 0000000..219fc8b --- /dev/null +++ b/OHAttributedLabel/TagParsers/OHASTagParserHTML.m @@ -0,0 +1,67 @@ +// +// AttributedStringHTMLTagParser.m +// OHAttributedLabel +// +// Created by Olivier Halligon on 26/09/12. +// Copyright (c) 2012 AliSoftware. All rights reserved. +// + +#import "OHASTagParserHTML.h" +#import "NSAttributedString+Attributes.h" + +@implementation OHASTagParserHTML + ++(NSDictionary*)tagMappings +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSRange textRange = [match rangeAtIndex:1]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextBold:YES range:NSMakeRange(0,textRange.length)]; + return [foundString autorelease]; + }, @"(.*?)", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSRange textRange = [match rangeAtIndex:1]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextIsUnderlined:YES]; + return [foundString autorelease]; + }, @"(.*?)", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSString* fontName = [str attributedSubstringFromRange:[match rangeAtIndex:2]].string; + CGFloat fontSize = [str attributedSubstringFromRange:[match rangeAtIndex:4]].string.floatValue; + NSRange textRange = [match rangeAtIndex:5]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setFontName:fontName size:fontSize]; + return [foundString autorelease]; + }, @"(.*?)", + + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSString* colorName = [str attributedSubstringFromRange:[match rangeAtIndex:2]].string; + UIColor* color = UIColorFromString(colorName); + NSRange textRange = [match rangeAtIndex:3]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString setTextColor:color]; + return [foundString autorelease]; + }, @"(.*?)", + + /* + // Disabled for now as there is no official CoreText attribute name to define links. + // To be able to do this, we have implement a custom attribute ourselves and add support for it in OHAttributedLabel + ^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match) { + NSString* link = [str attributedSubstringFromRange:[match rangeAtIndex:1]].string; + NSRange textRange = [match rangeAtIndex:2]; + NSMutableAttributedString* foundString = [[str attributedSubstringFromRange:textRange] mutableCopy]; + [foundString addAttribute:@"NSLinkAttributeName" value:link range:NSMakeRange(0,textRange.length)]; + return [foundString autorelease]; + }, @"(.*?)", + */ + + nil]; +} + +@end + +