Created
March 2, 2011 14:32
-
-
Save xslim/851018 to your computer and use it in GitHub Desktop.
HTML to NSAttributedString
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSAttributedString+fromHTML.m | |
// Berlingske | |
// | |
// Created by Taras Kalapun on 18.08.10. | |
// Copyright (c) 2010 Ciklum. All rights reserved. | |
// | |
#import "NSAttributedString+fromHTML.h" | |
@implementation NSAttributedString (fromHTML) | |
static BOOL underlineFlag = NO; | |
static BOOL boldFlag = NO; | |
static BOOL italicFlag = NO; | |
static CGFloat size = 18.0; | |
static NSString *linkString; | |
- (void)setCurrentAttributes:(NSMutableAttributedString *)attrString; | |
{ | |
UIFont *nFont = [UIFont fontWithName:@"LucidaBright" size:size]; | |
UIFont *bFont = [UIFont fontWithName:@"LucidaBright-Demi" size:size]; | |
UIFont *iFont = [UIFont fontWithName:@"LucidaBright-Demi" size:size]; | |
UIFont *biFont = [UIFont fontWithName:@"LucidaBright-Demi" size:size]; | |
NSRange range; | |
range.location = 0; | |
range.length = [attrString length]; | |
UIFont *font; | |
//NSLog(@"setting attributes - b:%d, i:%d, u:%d", boldFlag, italicFlag, underlineFlag); | |
if (boldFlag && italicFlag) { | |
font = biFont; | |
} else if (boldFlag) { | |
font = bFont; | |
} else if (italicFlag) { | |
font = iFont; | |
} else { | |
font = nFont; | |
} | |
//font = [font fontWithSize:size]; | |
CTFontRef ctFont = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL); | |
/* | |
[attrString addAttribute:(NSString *)kCTFontAttributeName | |
value:(id)ctFont | |
range:range]; | |
*/ | |
NSMutableDictionary *attrDict; | |
attrDict = [NSMutableDictionary dictionaryWithCapacity:0]; | |
[attrDict setObject:(id)ctFont forKey:(NSString *)kCTFontAttributeName]; | |
[attrDict setObject:[NSNumber numberWithBool:underlineFlag] forKey:(NSString *)kCTUnderlineStyleAttributeName]; | |
//if (linkString) [attrDict setObject:linkString forKey:NSLinkAttributeName]; | |
[attrString addAttributes:attrDict range:range]; | |
} | |
- (NSAttributedString *)initWithHTML:(NSString *)htmlString; | |
{ | |
//NSLog(@"initWithHTML: %@", htmlString); | |
NSMutableAttributedString *attributedString; | |
NSRange range; | |
NSScanner *htmlScanner; | |
NSMutableString *strippedString; | |
boldFlag = NO; | |
italicFlag = NO; | |
underlineFlag = NO; | |
NSDictionary *keywordDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: | |
@""", @"\"", | |
@"&", @"&", | |
@"<", @"<", | |
@">", @">", | |
nil]; | |
strippedString = [NSMutableString stringWithCapacity:[htmlString length]]; | |
htmlScanner = [NSScanner scannerWithString:htmlString]; | |
while (![htmlScanner isAtEnd]) { | |
NSString *token; | |
[htmlScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:&token]; | |
[htmlScanner scanCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:NULL]; | |
[strippedString appendFormat:@"%@ ", token]; | |
} | |
attributedString = [[[NSMutableAttributedString alloc] init] autorelease]; | |
htmlScanner = [NSScanner scannerWithString:strippedString]; | |
while (![htmlScanner isAtEnd]) { | |
NSString *firstPass, *tagString, *newString; | |
NSScanner *keywordScanner; | |
NSCharacterSet *openTagSet; | |
NSCharacterSet *closeTagSet; | |
NSMutableAttributedString *newAttributedString; | |
openTagSet = [NSCharacterSet characterSetWithCharactersInString:@"<"]; | |
closeTagSet = [NSCharacterSet characterSetWithCharactersInString:@">"]; | |
newAttributedString = [[[NSMutableAttributedString alloc] init] autorelease]; | |
if ([htmlScanner scanUpToCharactersFromSet:openTagSet intoString:&firstPass]) { | |
keywordScanner = [NSScanner scannerWithString:firstPass]; | |
while (![keywordScanner isAtEnd]) { | |
NSString *keyword = nil; | |
BOOL knownTag = NO; | |
NSCharacterSet *keywordTag; | |
NSEnumerator *keyEnum; | |
keywordTag = [NSCharacterSet characterSetWithCharactersInString:@"&"]; | |
keyEnum = [[keywordDictionary allKeys] objectEnumerator]; | |
[keywordScanner scanUpToCharactersFromSet:keywordTag intoString:&newString]; | |
[newAttributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:newString]autorelease]]; | |
while (![keywordScanner isAtEnd] && (keyword = [keyEnum nextObject])) | |
if ([keywordScanner scanString:keyword intoString:NULL]) { | |
[newAttributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:[keywordDictionary objectForKey:keyword]]autorelease]]; | |
knownTag = YES; | |
} | |
if (!knownTag && [keywordScanner scanCharactersFromSet:keywordTag intoString:&newString]) | |
[newAttributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:newString]autorelease]]; | |
} | |
[self setCurrentAttributes:newAttributedString]; | |
[attributedString appendAttributedString:newAttributedString]; | |
} | |
// Either we hit a '<' or we're at the end of the text. | |
if (![htmlScanner isAtEnd]) { | |
[htmlScanner scanCharactersFromSet:openTagSet intoString:NULL]; | |
[htmlScanner scanUpToCharactersFromSet:closeTagSet intoString:&tagString]; | |
[htmlScanner scanCharactersFromSet:closeTagSet intoString:NULL]; | |
tagString = [tagString lowercaseString]; | |
if ([tagString hasPrefix:@"a "]) { | |
range = [tagString rangeOfString:@"\""]; | |
if (range.length) { | |
tagString = [tagString substringFromIndex:NSMaxRange(range)]; | |
range = [tagString rangeOfString:@"\""]; | |
linkString = [tagString substringToIndex:range.location]; | |
} else if ((range = [tagString rangeOfString:@"="]).length) { | |
linkString = [tagString substringFromIndex:NSMaxRange(range)]; | |
} else | |
linkString = nil; | |
[linkString retain]; | |
} else if ([tagString isEqual:@"/a"]) { | |
[linkString release]; | |
linkString = nil; | |
} else if ([tagString isEqual:@"b"] || [tagString isEqual:@"strong"]) | |
boldFlag = YES; | |
else if ([tagString isEqual:@"/b"] || [tagString isEqual:@"/strong"]) | |
boldFlag = NO; | |
else if ([tagString isEqual:@"h2"] || [tagString isEqual:@"h3"]) { | |
boldFlag = YES; | |
[attributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n\n"]autorelease]]; | |
} else if ([tagString isEqual:@"/h2"] || [tagString isEqual:@"/h3"]) { | |
boldFlag = NO; | |
[attributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n\n"]autorelease]]; | |
} else if ([tagString isEqual:@"i"] || [tagString isEqual:@"em"] || [tagString isEqual:@"cite"]) | |
italicFlag = YES; | |
else if ([tagString isEqual:@"/i"] || [tagString isEqual:@"/em"] || [tagString isEqual:@"/cite"]) | |
italicFlag = NO; | |
else if ([tagString isEqual:@"u"]) | |
underlineFlag = YES; | |
else if ([tagString isEqual:@"/u"]) | |
underlineFlag = NO; | |
else if ([tagString isEqual:@"p"]) | |
[attributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n\n"]autorelease]]; | |
else if ([tagString isEqual:@"br"] || [tagString isEqual:@"br /"]) | |
[attributedString appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"]autorelease]]; | |
else if ([tagString isEqual:@"/font"]) | |
size = 12.0; | |
else if ([tagString hasPrefix:@"font size="] || [tagString hasPrefix:@"font size ="]) { | |
float foo; | |
if (sscanf([tagString UTF8String], "font size = +%f", &foo) == 1) | |
size += foo + 9; | |
else if (sscanf([tagString UTF8String], "font size = %f", &foo) == 1) | |
size = foo + 9; | |
} | |
} | |
} | |
range.location = 0; | |
range.length = [attributedString length]; | |
[keywordDictionary release]; | |
return [self initWithAttributedString:attributedString]; | |
//return attributedString; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment