WeChat/BAQMUIDemo/BALib/MLLabel/Category/NSAttributedString+MLLabel.m
//
//  NSAttributedString+MLLabel.m
//  Pods
//
//  Created by molon on 15/6/13.
//
//

#import "NSAttributedString+MLLabel.h"

@implementation NSAttributedString (MLLabel)

+ (instancetype)attributedStringWithHTML:(NSString*)htmlString
{
    NSData* htmlData = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
    if (htmlData) {
        __block id attributedString = nil;
        dispatch_block_t block = ^{
            attributedString = [[self alloc] initWithData:htmlData
                                                  options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                            NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
                                       documentAttributes:nil
                                                    error:NULL];
        };
        
        //这个解析必须在主线程执行，文档上要求的
        if ([NSThread isMainThread]) {
            block();
        }else{
            dispatch_sync(dispatch_get_main_queue(), block);
        }
        
        return attributedString;
    }
    
    return nil;
}

- (NSAttributedString*)linkAttributedStringWithLinkRegex:(NSRegularExpression*)linkRegex groupIndexForDisplay:(NSInteger)groupIndexForDisplay groupIndexForValue:(NSInteger)groupIndexForValue {
    NSParameterAssert(linkRegex);
    NSAssert(groupIndexForDisplay>0&&groupIndexForValue>0, @"groupIndexForDisplay and groupIndexForValue must >0!");
    
    NSInteger length = [self length];
    if (length<=0) {
        return self;
    }
    
    NSMutableAttributedString *resultAttributedString = [NSMutableAttributedString new];
    
    //正则匹配所有内容
    NSArray *results = [linkRegex matchesInString:self.string
                                          options:NSMatchingWithTransparentBounds
                                            range:NSMakeRange(0, length)];
    
    //遍历结果，找到结果中被()包裹的区域作为显示内容
    NSUInteger location = 0;
    for (NSTextCheckingResult *result in results) {
        NSAssert([result numberOfRanges]>1&&[result numberOfRanges]>groupIndexForDisplay&&[result numberOfRanges]>groupIndexForValue, @"Please ensure that group sign `()` in the linkRegex is correct!");
        NSRange range = [result rangeAtIndex:0];
        
        //把前面的非匹配出来的区域加进来
        NSAttributedString *subAttrStr = [self attributedSubstringFromRange:NSMakeRange(location, range.location - location)];
        [resultAttributedString appendAttributedString:subAttrStr];
        //下次循环从当前匹配区域的下一个位置开始
        location = NSMaxRange(range);
        
        //找到要显示的区域内容加上
        NSRange rangeForDisplay = [result rangeAtIndex:groupIndexForDisplay];
        NSMutableAttributedString *displayStr = [[self attributedSubstringFromRange:rangeForDisplay]mutableCopy];
        //对其添加link属性
        NSString *linkValue = nil;
        if (groupIndexForValue==groupIndexForDisplay) {
            linkValue = displayStr.string;
        }else{
            NSRange rangeForValue = [result rangeAtIndex:groupIndexForValue];
            linkValue = [self attributedSubstringFromRange:rangeForValue].string;
        }
        [displayStr addAttribute:NSLinkAttributeName value:linkValue range:NSMakeRange(0, displayStr.length)];
        
        [resultAttributedString appendAttributedString:displayStr];
    }
    
    if (location < length) {
        //到这说明最后面还有非表情字符串
        NSRange range = NSMakeRange(location, length - location);
        NSAttributedString *subAttrStr = [self attributedSubstringFromRange:range];
        [resultAttributedString appendAttributedString:subAttrStr];
    }
    
    return resultAttributedString;
}

@end
