Skip to content

Instantly share code, notes, and snippets.

@xslim
Created March 2, 2011 14:32
Show Gist options
  • Select an option

  • Save xslim/851018 to your computer and use it in GitHub Desktop.

Select an option

Save xslim/851018 to your computer and use it in GitHub Desktop.

Revisions

  1. xslim created this gist Mar 2, 2011.
    205 changes: 205 additions & 0 deletions gistfile1.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,205 @@
    //
    // 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:
    @"&quot", @"\"",
    @"&amp", @"&",
    @"&lt", @"<",
    @"&gt", @">",
    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