master fc0277420964 cached
107 files
321.3 KB
88.7k tokens
2 symbols
1 requests
Download .txt
Showing preview only (349K chars total). Download the full file or copy to clipboard to get everything.
Repository: nicolasgoutaland/GONMarkupParser
Branch: master
Commit: fc0277420964
Files: 107
Total size: 321.3 KB

Directory structure:
gitextract_dlvgp0vj/

├── .gitignore
├── CHANGELOG.md
├── Classes/
│   ├── GONMarkup+Private.h
│   ├── GONMarkup+Private.m
│   ├── GONMarkup.h
│   ├── GONMarkup.m
│   ├── GONMarkupAlignment.h
│   ├── GONMarkupAlignment.m
│   ├── GONMarkupAnchor.h
│   ├── GONMarkupAnchor.m
│   ├── GONMarkupBlock.h
│   ├── GONMarkupBlock.m
│   ├── GONMarkupBold.h
│   ├── GONMarkupBold.m
│   ├── GONMarkupColor.h
│   ├── GONMarkupColor.m
│   ├── GONMarkupDec.h
│   ├── GONMarkupDec.m
│   ├── GONMarkupDefaultMarkups.h
│   ├── GONMarkupFont.h
│   ├── GONMarkupFont.m
│   ├── GONMarkupFontTraits.h
│   ├── GONMarkupFontTraits.m
│   ├── GONMarkupImage.h
│   ├── GONMarkupImage.m
│   ├── GONMarkupInc.h
│   ├── GONMarkupInc.m
│   ├── GONMarkupItalic.h
│   ├── GONMarkupItalic.m
│   ├── GONMarkupLineBreak.h
│   ├── GONMarkupLineBreak.m
│   ├── GONMarkupLineStyle.h
│   ├── GONMarkupLineStyle.m
│   ├── GONMarkupList.h
│   ├── GONMarkupList.m
│   ├── GONMarkupListItem.h
│   ├── GONMarkupListItem.m
│   ├── GONMarkupNamedColor.h
│   ├── GONMarkupNamedColor.m
│   ├── GONMarkupNamedFont.h
│   ├── GONMarkupNamedFont.m
│   ├── GONMarkupParagraph.h
│   ├── GONMarkupParagraph.m
│   ├── GONMarkupParser.h
│   ├── GONMarkupParser.m
│   ├── GONMarkupParserManager.h
│   ├── GONMarkupParserManager.m
│   ├── GONMarkupParserUtils.h
│   ├── GONMarkupParserUtils.m
│   ├── GONMarkupParser_All.h
│   ├── GONMarkupParser_Categories.h
│   ├── GONMarkupReset.h
│   ├── GONMarkupReset.m
│   ├── GONMarkupSimple.h
│   ├── GONMarkupSimple.m
│   ├── GONMarkupStrong.h
│   ├── GONMarkupStrong.m
│   ├── GONMarkupTextStyle.h
│   ├── GONMarkupTextStyle.m
│   ├── UIButton+GONMarkupParser.h
│   ├── UIButton+GONMarkupParser.m
│   ├── UILabel+GONMarkupParser.h
│   ├── UILabel+GONMarkupParser.m
│   ├── UITextField+GONMarkupParser.h
│   ├── UITextField+GONMarkupParser.m
│   ├── UITextView+GONMarkupParser.h
│   └── UITextView+GONMarkupParser.m
├── Example/
│   ├── GONMarkupParserSample/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── ComplexExample
│   │   ├── ComplexExampleViewController.h
│   │   ├── ComplexExampleViewController.m
│   │   ├── ComplexExampleViewController.xib
│   │   ├── DefaultConfigurationViewController.h
│   │   ├── DefaultConfigurationViewController.m
│   │   ├── DefaultConfigurationViewController.xib
│   │   ├── GONMarkupParserSample-Info.plist
│   │   ├── GONMarkupParserSample-Prefix.pch
│   │   ├── Images.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.launchimage/
│   │   │       └── Contents.json
│   │   ├── MainWindow.xib
│   │   ├── PlaygroundViewController.h
│   │   ├── PlaygroundViewController.m
│   │   ├── PlaygroundViewController.xib
│   │   ├── ResultViewController.h
│   │   ├── ResultViewController.m
│   │   ├── ResultViewController.xib
│   │   ├── RootViewController.h
│   │   ├── RootViewController.m
│   │   ├── RootViewController.xib
│   │   ├── SampleViewController.h
│   │   ├── SampleViewController.m
│   │   ├── SampleViewController.xib
│   │   ├── en.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── main.m
│   │   └── samples.plist
│   ├── GONMarkupParserSample.xcodeproj/
│   │   ├── project.pbxproj
│   │   └── project.xcworkspace/
│   │       └── contents.xcworkspacedata
│   ├── GONMarkupParserSample.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── IDEWorkspaceChecks.plist
│   ├── GONMarkupParserSampleTests/
│   │   ├── GONMarkupParserSampleTests-Info.plist
│   │   ├── GONMarkupParserSampleTests.m
│   │   └── en.lproj/
│   │       └── InfoPlist.strings
│   └── PodFile
├── GONMarkupParser.podspec
├── LICENSE
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Xcode
.DS_Store
*/build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
*.hmap
*.xccheckout
*.xcuserstate

#CocoaPods
Pods
/Example/GONMarkupParserSample.xcodeproj/project.xcworkspace/xcshareddata


================================================
FILE: CHANGELOG.md
================================================
# Change Log
## [__0.8.2__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.2)
Updated HTML entities replace code<br/>
## [__0.8.1__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.1)
Fixed list alignment bug in iOS12<br/>
## [__0.8.0__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.0)
Improved Paragraph layout<br/>
Improved List Item layout<br/>
Added paragraph sample<br/>
Fixed a typo issue with paragraph class<br/>
## [__0.7.9__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.9)
Fixed bug in GONMarkupParserUtils<br/>
## [__0.7.8__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.8)
GONMarkupParserUtils optimisation<br/>
## [__0.7.7__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.7)
Fixed sample Podfile<br/>
## [__0.7.6__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.6)
Fixed a bug on NSParagraphStyle mutability<br/>
## [__0.7.5__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.5)
Fixed a bug on lists heading alignment<br/>
Fixed a bug on lists, with subitems not aligned<br/>
Added support for strong tag (yoohoo \o/)<br/>
## [__0.7.4__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.4)
Fixed (again -_-) new line character bug on lists<br/>
## [__0.7.3__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.3)
Fixed new line character bug on lists<br/>
## [__0.7.2__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.2)
Fixed bug #21
## [__0.7.1__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.1)
Fixed warning #18
## [__0.7.0__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.0)
Fixed bug #15
## [__0.6.9__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.9)
Fixed bug #12
## [__0.6.8__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.8)
Fixed import problems with cocoa Pods 0.39
## [__0.6.7__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.7)
Added color attribute to font markup
## [__0.6.6__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.6)
Added UIButton+GONMarkupParser category
## [__0.6.5__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.5)
Updated HTML chars tables
## [__0.6.4__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.4)
Updated HTML chars tables
## [__0.6.3__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.3)
Fixed a bug in anchor support
## [__0.6.2__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.2)
Added anchor support
## [__0.6.1__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6.1)
Added support for underline and strikethrough color
## [__0.6__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.6)
Added support for underline / strikethrough text
## [__0.5__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.5)
Initial release


================================================
FILE: Classes/GONMarkup+Private.h
================================================
//
//  GONMarkup+Private.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkup.h"
#import "GONMarkupParser.h"

@interface GONMarkup (Private)
// Shared context configuration LIFO management
// These methods can be used to shared data between markers throught shared context.
/* Push a new configuration to shared context, under given key */
- (void)pushConfiguration:(id)configuration toContext:(NSMutableDictionary *)context forKey:(NSString *)key;

/* Return current available configuration in shared context for given key
 * May return nil if there is no configuration
 */
- (id)currentContextConfiguration:(NSString *)key fromContext:(NSMutableDictionary *)context;

/* Pop current configuration from shared context, and return it.
 * May return nil if there is no configuration */
- (id)popContextConfiguration:(NSString *)key fromContext:(NSMutableDictionary *)context;

@property (nonatomic, weak) GONMarkupParser *parser;
@end


================================================
FILE: Classes/GONMarkup+Private.m
================================================
//
//  GONMarkup+Private.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkup+Private.h"

@implementation GONMarkup (Private)
#pragma mark - LIFO shared context management
- (void)pushConfiguration:(id)configuration
                toContext:(NSMutableDictionary *)context
                   forKey:(NSString *)key
{
    // Retrieve FIFO
    NSMutableArray *configurationsLIFO = [context objectForKey:key];
    if (!configurationsLIFO)
    {
        // Create FIFO
        configurationsLIFO = [[NSMutableArray alloc] init];
        [context setObject:configurationsLIFO
                    forKey:key];
    }

    // Hold current configuration
    [configurationsLIFO addObject:configuration];
}

- (id)currentContextConfiguration:(NSString *)key
                      fromContext:(NSMutableDictionary *)context
{
    return [[context objectForKey:key] lastObject];
}

- (id)popContextConfiguration:(NSString *)key
                  fromContext:(NSMutableDictionary *)context
{
    // Retrieve LIFO
    NSMutableArray *configurationsLIFO = [context objectForKey:key];

    // Retrieve current configuration
    id currentConfiguration = [configurationsLIFO lastObject];

    // Remove last configuration
    [configurationsLIFO removeLastObject];

    // Check if list is empty
    if (!configurationsLIFO.count)
    {
        // Remove empty list
        [context removeObjectForKey:key];
    }

    return currentConfiguration;
}

@dynamic parser;
@end


================================================
FILE: Classes/GONMarkup.h
================================================
//
//  GONMarkup.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//
//  Simple class defining a markup
//  You can use it as it, or override it to add more configuration
//
//  Tag name will be stored lowercased, so be careful when using multiple tags
//
//  Markup lifecycle :
//  - Once a tag is found, openingMarkupFound:configuration:context: method will be called
//  - Before parser append extracted string to result, following methods will be called
//      - prefixStringForContext:attributes:resultString: will be called, allowing tag to generate a prefix
//      - updatedContentString:context:attributes:resultString: will be called, allowing tag to update its content string (without prefix included)
//      - suffixStringForContext:attributes:resultString: will be called, allowing tag to generate a suffix
//  - Once tag is closed, closingMarkupFound:configuration:context:resultString: method will be called
//
//  Attributes should be space separated, values affected using equal sign, and between quotes or double quotes. To escape quotes / double quotes, use \
//  Be careful,text heere is intended to be loaded from a file, not directly set in code. If so, do not forget to escape \.
//  You can also use &quot;
//
//  Example :
//  Attribute               | Supported
//  -----------------------------------
//  <color value="red">     | YES
//  <color value = "red">   | YES
//  <color value = red>     | NO
//  <color value = "re"d">  | NO
//  <color value = "re\"d"> | YES
//  <color value='red'>     | YES
//  <color value = 'red'>   | YES
//  <color value = red>     | NO
//  <color value = "re'd">  | YES
//  <color value = 're"d'>  | YES
//
//
//  Markup instance will be reused each time a matching tag is found. To persist data, use context parameter.

@class GONMarkupParser;

@interface GONMarkup : NSObject
/* Class constructor */
+ (instancetype)markupForTag:(NSString *)tag;

/* Default constructor */
- (id)initWithTag:(NSString *)tag;

/* This method will be called if markup is matching current opening tag.
 * Object is responsible to update attributed string parameters in "configurationDictionary"
 *
 * "tag" is matching tag, allowing you to extract parameters
 * "context" is a mutable dictionary used by marker to add contextual information. This dictionary is shared throught all markers in a parser and is reset each time a new parse is started
 * It is used for example by list markers to handle list type, tabulation index and count
 * "resultString" is currently built result string
 *
 * You should override this method to implement new behavior
 */
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString;

/* Allows marker to prefix its content string
 * This method is called right after opening markup
 */
- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttribute
                                  resultString:(NSAttributedString *)resultString;

/* This method will be called once current marker tag is closed
 * This allows marker to update string content
 * "context" is the same as in openingMarkupFound:configuration:fromTag:context:
 *
 * Default implementation return input string
 */
- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString;

/* Allows marker to suffix its content string
 * This method is called right after opening markup
 */
- (NSAttributedString *)suffixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString;

/* This method will be called if markup is matching current closing tag.
 * Object is responsible to update attributed string parameters in "configurationDictionary"
 *
 * "tag" is matching tag, allowing you to extract parameters
 * "context" is a mutable dictionary use by marker to add contextual information. This dictionary is shared throught all markers in a parser and is reset each time a new parse is started
 * It is used for example by list markers to handle list type, tabulation index and count
 *
 * You should override this method to implement new behavior
 */
- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString;

@property (nonatomic, copy, readonly) NSString *tag;            // Have to be unique. Used to speed up rules matching, when using tags without parameters
@property (nonatomic, weak, readonly) GONMarkupParser *parser;  // Parser the markup is attached to
@end


================================================
FILE: Classes/GONMarkup.m
================================================
//
//  GONMarkup.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//

#import "GONMarkup.h"
#import "GONMarkupParser.h"

@interface GONMarkup()
// Data
@property (nonatomic, copy) NSString *tag;
@property (nonatomic, copy) NSString *testedTag;

// Parser link
@property (nonatomic, weak) GONMarkupParser *parser;
@end

@implementation GONMarkup
#pragma mark - Constructors
+ (instancetype)markupForTag:(NSString *)tag
{
    return [[self alloc] initWithTag:tag];
}

- (id)initWithTag:(NSString *)tag
{
    if (self = [super init])
    {
        _tag = [[tag lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        _testedTag = [_tag stringByAppendingString:@" "];
    }

    return self;
}

- (id)init
{
    @throw @"Error, - init constructor is not allowed. Markup MUST have a tag";
}

#pragma mark - Test
- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString
{
    return [[NSAttributedString alloc] initWithString:string attributes:stringAttributes];
}

- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
{
    NSLog(@"WARNING : This method will be deleted in next release. Use updatedContentString:context:attributes:stringAttributes:resultString: instead");

    return [self updatedContentString:string
                              context:context
                           attributes:dicAttributes
                     stringAttributes:stringAttributes
                         resultString:nil];
}

- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    return [[NSAttributedString alloc] initWithString:@""];
}

- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
{
    NSLog(@"WARNING : This method will be deleted in next release. Use prefixStringForContext:attributes:stringAttributes:resultString: instead");
    
    return [self prefixStringForContext:context
                             attributes:dicAttributes
                       stringAttributes:stringAttributes
                           resultString:nil];
}

- (NSAttributedString *)suffixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
{
    NSLog(@"WARNING : This method will be deleted in next release. Use suffixStringForContext:attributes:stringAttributes:resultString: instead");

    return [self suffixStringForContext:context
                             attributes:dicAttributes
                       stringAttributes:stringAttributes
                           resultString:nil];
}

- (NSAttributedString *)suffixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    return [[NSAttributedString alloc] initWithString:@""];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString {}

- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes {

    NSLog(@"WARNING : This method will be deleted in next release. Use openingMarkupFound:configuration:context:attributes:resultString: instead");
    
    [self openingMarkupFound:tag
               configuration:configurationDictionary
                     context:context
                  attributes:dicAttributes
                resultString:nil];
}

- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes {

    NSLog(@"WARNING : This method will be deleted in next release. Use closingMarkupFound:configuration:context:attributes:resultString: instead");

    [self closingMarkupFound:tag
               configuration:configurationDictionary
                     context:context
                  attributes:dicAttributes
                resultString:nil];
}

- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString {}

@end
    


================================================
FILE: Classes/GONMarkupAlignment.h
================================================
//
//  GONMarkupAlignment.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 22/07/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//
//  Markup used to handle text alignment.
//  This markup will set a NSMutableParagraphStyle object under NSParagraphStyleAttributeName key.
//  Be sure to make a mutable copy of it before updating when adding new tags
//
//  Examples
//
//  <left>left aligned text</>
//  <right>right aligned text</>
//  <center>center aligned text</>
//  <justified>justified aligned text</>
//  <natural>natural aligned text</>

#import "GONMarkup.h"

// Tag
#define GONMarkupAlignment_left_TAG                 @"left"
#define GONMarkupAlignment_right_TAG                @"right"
#define GONMarkupAlignment_center_TAG               @"center"
#define GONMarkupAlignment_justified_TAG            @"justified"
#define GONMarkupAlignment_natural_TAG              @"natural"

@interface GONMarkupAlignment : GONMarkup
/* Return all alignment markups */
+ (NSArray *)allMarkups;

/* Default markup to add center text alignment support */
+ (instancetype)centerMarkup;

/* Default markup to add left text alignment support */
+ (instancetype)leftMarkup;

/* Default markup to add right text alignment support */
+ (instancetype)rightMarkup;

/* Default markup to add justified text alignment support */
+ (instancetype)justifiedMarkup;

/* Default markup to add natural text alignment support */
+ (instancetype)naturalMarkup;

@end


================================================
FILE: Classes/GONMarkupAlignment.m
================================================
//
//  GONMarkupAlignment.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 22/07/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupAlignment.h"

@interface GONMarkupAlignment ()
// Data
@property (nonatomic, assign) NSTextAlignment alignment;
@end

@implementation GONMarkupAlignment
#pragma mark - Markup list
+ (NSArray *)allMarkups
{
    return @[[self centerMarkup], [self leftMarkup], [self rightMarkup], [self justifiedMarkup], [self naturalMarkup]];
}

#pragma mark - Constructors
+ (instancetype)alignmentMarkup:(NSTextAlignment)alignment tag:(NSString *)tag
{
    GONMarkupAlignment *markupAlignment = [self markupForTag:tag];
    
    markupAlignment.alignment = alignment;
    
    return markupAlignment;
}

+ (instancetype)centerMarkup;
{
    return [self alignmentMarkup:NSTextAlignmentCenter tag:GONMarkupAlignment_center_TAG];
}

+ (instancetype)leftMarkup;
{
    return [self alignmentMarkup:NSTextAlignmentLeft tag:GONMarkupAlignment_left_TAG];
}

+ (instancetype)rightMarkup;
{
    return [self alignmentMarkup:NSTextAlignmentRight tag:GONMarkupAlignment_right_TAG];
}

+ (instancetype)justifiedMarkup;
{
    return [self alignmentMarkup:NSTextAlignmentJustified tag:GONMarkupAlignment_justified_TAG];
}

+ (instancetype)naturalMarkup;
{
    return [self alignmentMarkup:NSTextAlignmentNatural tag:GONMarkupAlignment_natural_TAG];
}

#pragma mark - Markup lifecycle
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    NSMutableParagraphStyle *style = [[configurationDictionary objectForKey:NSParagraphStyleAttributeName] mutableCopy];
    if (!style)
        style = [[NSMutableParagraphStyle alloc] init];

    // Hold new configuration
    [configurationDictionary setObject:style
                                 forKey:NSParagraphStyleAttributeName];

    // Update alignment
    style.alignment = _alignment;
}
@end


================================================
FILE: Classes/GONMarkupAnchor.h
================================================
//
//  GONMarkupAnchor.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//
//  Define a markup to add anchor support
//  You can specify link value with "value" attribute.
//
//  To detect user touch on link :
//  - display attributed string in a UITextView
//  - configure UITextView selectable property to YES and isEditable to NO
//  - set delegate
//  - implement "textView:shouldInteractWithURL:inRange:" method
//
//  Examples
//
//  <a href="#1">Link 1</>
//  <a href="http://www.apple.com">Link to apple.com</>
//  <a href="myscheme://myapp">Custom link</>

#import "GONMarkup.h"

// Tag
#define GONMarkupAnchor_TAG                 @"a"

// Attributes
#define GONMarkupAnchor_TAG_href_ATT       @"href"

@interface GONMarkupAnchor : GONMarkup
/* Default markup to add anchor support */
+ (instancetype)anchorMarkup;
@end


================================================
FILE: Classes/GONMarkupAnchor.m
================================================
//
//  GONMarkupAnchor.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupAnchor.h"

@interface GONMarkupAnchor ()
@end

@implementation GONMarkupAnchor
#pragma mark - Constructor
+ (instancetype)anchorMarkup
{
    return [self markupForTag:GONMarkupAnchor_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    NSString *value = [dicAttributes objectForKey:GONMarkupAnchor_TAG_href_ATT];
    if (value)
    {
        // Create URL based on value
        [configurationDictionary setObject:value
                                    forKey:NSLinkAttributeName];
    }
}

@end


================================================
FILE: Classes/GONMarkupBlock.h
================================================
//
//  GONMarkupBlock.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Markup using a block as parameters. Useful to add new markup without creating new subclasses


#import "GONMarkup.h"

@interface GONMarkupBlock : GONMarkup
/* Class contructor
 */
+ (instancetype)blockMarkup:(NSString *)tag;

@property (nonatomic, copy) void(^openingMarkupBlock)(NSMutableDictionary *configurationDictionary, NSString *tag, NSMutableDictionary *context, NSDictionary *dicAttributes, NSAttributedString *resultString);  // Called when opening tag is found
@property (nonatomic, copy) void(^closingMarkupBlock)(NSMutableDictionary *configurationDictionary, NSString *tag, NSMutableDictionary *context, NSDictionary *dicAttributes, NSAttributedString *resultString);  // Called when closing tag is found

@property (nonatomic, copy) NSAttributedString *(^prefixStringForContextBlock)(NSMutableDictionary *context, NSDictionary *dicAttributes, NSDictionary *stringAttributes, NSAttributedString *resultString);                 // Called to generate prefix
@property (nonatomic, copy) NSAttributedString *(^suffixStringForContextBlock)(NSMutableDictionary *context, NSDictionary *dicAttributes, NSDictionary *stringAttributes, NSAttributedString *resultString);                 // Called to generate suffix
@property (nonatomic, copy) NSAttributedString *(^updatedContentStringBlock)(NSString *string, NSMutableDictionary *context, NSDictionary *dicAttributes, NSDictionary *stringAttributes, NSAttributedString *resultString); // Called when extracted string is complete
@end


================================================
FILE: Classes/GONMarkupBlock.m
================================================
//
//  GONMarkupBlock.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupBlock.h"

@implementation GONMarkupBlock
#pragma mark - Constructor
+ (instancetype)blockMarkup:(NSString *)tag
{
    return [self markupForTag:tag];
}

#pragma mark - Configuration
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    if (_openingMarkupBlock)
        _openingMarkupBlock(configurationDictionary, tag, context, dicAttributes, resultString);
}

- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    if (_closingMarkupBlock)
        _closingMarkupBlock(configurationDictionary, tag, context, dicAttributes, resultString);
}

- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString
{
    if (_updatedContentStringBlock)
        return _updatedContentStringBlock(string, context, dicAttributes, stringAttributes, resultString);

    return [super updatedContentString:string
                               context:context
                            attributes:dicAttributes
                      stringAttributes:stringAttributes
                          resultString:resultString];
}

- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    if (_prefixStringForContextBlock)
        return _prefixStringForContextBlock(context, dicAttributes, stringAttributes, resultString);

    return [super prefixStringForContext:context
                              attributes:dicAttributes
                        stringAttributes:stringAttributes
                            resultString:resultString];
}

- (NSAttributedString *)suffixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    if (_suffixStringForContextBlock)
        return _suffixStringForContextBlock(context, dicAttributes, stringAttributes, resultString);

    return [super suffixStringForContext:context
                              attributes:dicAttributes
                        stringAttributes:stringAttributes
                            resultString:resultString];
}
@end


================================================
FILE: Classes/GONMarkupBold.h
================================================
//
//  GONMarkupBold.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 19/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Tag updating current font style to bold
//  This tag may not work if no bold version of current font is available.
//  overrideBlock (GONMarkupFontTraits) allows you to override font. For example, you can used it to return a medium font instead of bold one.
//  If overrideBlock is set, it will be called first. Is nil is returned, system will try to automatically resolve font
//
//  Examples
//
//  <b>bold text</>

#import "GONMarkupFontTraits.h"

#define GONMarkupBold_TAG                 @"b"

@interface GONMarkupBold : GONMarkupFontTraits

/* Default markup to add bold support */
+ (instancetype)boldMarkup;
@end


================================================
FILE: Classes/GONMarkupBold.m
================================================
//
//  GONMarkupBold.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 19/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupBold.h"

@implementation GONMarkupBold
#pragma mark - Constructor
+ (instancetype)boldMarkup
{
    return [super fontTraitsMarkup:GONMarkupBold_TAG
                            traits:UIFontDescriptorTraitBold];
}
@end


================================================
FILE: Classes/GONMarkupColor.h
================================================
//
//  GONMarkupColor.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//
//  Define a generic markup to add color
//  You can specify color value with "value" attribute.
//
//  Colors are handled via NSString+Color, using "representedColor" category method
//  Have a look at https://github.com/nicolasgoutaland/NSString-Color for more information
//
//  Examples
//
//  <color value="red">text</>
//  <color value="#FFEEAA">text</>
//  <color value="myCustomRegisteredColor">text</>

#import "GONMarkup.h"

// Tag
#define GONMarkupColor_TAG                 @"color"

// Attributes
#define GONMarkupColor_TAG_value_ATT       @"value"

@interface GONMarkupColor : GONMarkup
/* Default markup to add color support */
+ (instancetype)colorMarkup;
@end


================================================
FILE: Classes/GONMarkupColor.m
================================================
//
//  GONMarkupColor.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//

#import "GONMarkupColor.h"
#import "NSString+Color.h"

@implementation GONMarkupColor
#pragma mark - Constructor
+ (instancetype)colorMarkup
{
    return [self markupForTag:GONMarkupColor_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    UIColor *colorValue = [[dicAttributes objectForKey:GONMarkupColor_TAG_value_ATT] representedColor];
    if (colorValue)
    {
        [configurationDictionary setObject:colorValue
                                     forKey:NSForegroundColorAttributeName];
    }
}

@end


================================================
FILE: Classes/GONMarkupDec.h
================================================
//
//  GONMarkupDec.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 10/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Define a markup to decrement font size. By default, font is decreased by 1 point.
//  You can specify another decrement value with "value" attribute.
//
//  Examples
//
//  <dec>text</>
//  <dec value="5">text</>

#import "GONMarkup.h"

// Tag
#define GONMarkupDec_TAG                   @"dec"

// Attributes
#define GONMarkupDec_TAG_value_ATT       @"value"

@interface GONMarkupDec : GONMarkup
/* Default markup to add text size decrement support */
+ (instancetype)decMarkup;
@end


================================================
FILE: Classes/GONMarkupDec.m
================================================
//
//  GONMarkupDec.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 10/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupDec.h"

#define DEFAULT_DEC_VALUE   1

@implementation GONMarkupDec
#pragma mark - Constructor
+ (instancetype)decMarkup
{
    return [super markupForTag:GONMarkupDec_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    NSInteger incValue = [[dicAttributes objectForKey:GONMarkupDec_TAG_value_ATT] intValue];
    if (!incValue)
        incValue = DEFAULT_DEC_VALUE;

    // Look for current font
    UIFont *currentFont = [configurationDictionary objectForKey:NSFontAttributeName];
    if (!currentFont)
    {
        // No found defined, use default one with default size
        currentFont = [UIFont systemFontOfSize:[UIFont systemFontSize]];
    }

    // Update current font with new size
    [configurationDictionary setObject:[currentFont fontWithSize:MAX(currentFont.pointSize - incValue, 1)]
                                forKey:NSFontAttributeName];
}
@end


================================================
FILE: Classes/GONMarkupDefaultMarkups.h
================================================
//
//  GONMarkupDefaultMarkups.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupAlignment.h"
#import "GONMarkupAnchor.h"
#import "GONMarkupBold.h"
#import "GONMarkupBlock.h"
#import "GONMarkupColor.h"
#import "GONMarkupDec.h"
#import "GONMarkupFont.h"
// WIP
//#import "GONMarkupImage.h"
#import "GONMarkupInc.h"
#import "GONMarkupItalic.h"
#import "GONMarkupLineBreak.h"
#import "GONMarkupLineStyle.h"
#import "GONMarkupList.h"
#import "GONMarkupListItem.h"
#import "GONMarkupNamedColor.h"
#import "GONMarkupNamedFont.h"
#import "GONMarkupParagraph.h"
#import "GONMarkupReset.h"
#import "GONMarkupSimple.h"
#import "GONMarkupStrong.h"
#import "GONMarkupTextStyle.h"


================================================
FILE: Classes/GONMarkupFont.h
================================================
//
//  GONMarkupFont.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//
//  Define a generic markup to configure font
//  "color" is used to change text color
//       Colors are handled via NSString+Color, using "representedColor" category method
//       Have a look at https://github.com/nicolasgoutaland/NSString-Color for more information
//  "size" is used to define font size
//      If missing, current font size will be used. If not found is set, default system font size will be used
//  "name" define a registered font name or full font name
//      - Markup will first try to find a registeredFont with given name.
//      - If no font found, markup will try to load a font using given name
//  If "name" isn't set, current defined font will be used with new defined size. If no font is currently used, default system one will be used
//
//  If no attribute is set, current defined font will be removed (NSFontAttributeName), and default system one will be used instead
//
//  Examples
//
//  <font size="18">This text will use current font, set to 18</>
//  <font name="Helvetica">This text will use Helvetica as font, using current font size</>
//  <font name="Helvetica" size="18">This text will use Helvetica, set to 18</>
//  <font name="Helvetica" size="18" color="red">This text will use Helvetica, set to 18, in red</>

#import "GONMarkup.h"

// Tag
#define GONMarkupFont_TAG                @"font"

// Attributes
#define GONMarkupFont_TAG_size_ATT       @"size"                // Font size. If missing, will use default font size, or one previously set on stack
#define GONMarkupFont_TAG_color_ATT      @"color"               // Text color
#define GONMarkupFont_TAG_name_ATT       @"name"                // Full font name, including style

@interface GONMarkupFont : GONMarkup
/* Default markup to add font support */
+ (instancetype)fontMarkup;

@end


================================================
FILE: Classes/GONMarkupFont.m
================================================
//
//  GONMarkupFont.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//

#import "GONMarkupFont.h"
#import "GONMarkup+Private.h"
#import "NSString+Color.h"

@interface GONMarkupFont ()

@end

@implementation GONMarkupFont
#pragma mark - Constructor
+ (instancetype)fontMarkup
{
    return [self markupForTag:GONMarkupFont_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    NSString *value;
    BOOL resetFontAttribute = YES;

    // Text color
    value = [dicAttributes objectForKey:GONMarkupFont_TAG_color_ATT];
    if (value)
    {
        [configurationDictionary setObject:[value representedColor]
                                    forKey:NSForegroundColorAttributeName];
        resetFontAttribute = NO;
    }

    // Font name
    value = [dicAttributes objectForKey:GONMarkupFont_TAG_name_ATT];
    if (value)
    {
        // Look for size attribute
        CGFloat size;
        NSString *sizeValue = [dicAttributes objectForKey:GONMarkupFont_TAG_size_ATT];
        if (sizeValue)
        {
            size = [sizeValue floatValue];
        }
        else
        {
            UIFont *currentFont = [configurationDictionary objectForKey:NSFontAttributeName];
            if (currentFont)
                size = currentFont.pointSize;
            else
                size = [UIFont systemFontSize];
        }

        // Try to load font from registered ones
        UIFont *font = [self.parser fontForKey:value];
        if (!font)
        {
            // No matching font found, try to load it by name
            font = [UIFont fontWithName:value size:size];
        }
        else
        {
            // Font found, update its size
            font = [UIFont fontWithDescriptor:font.fontDescriptor size:[sizeValue floatValue]];
        }

        // Update configuration
        [configurationDictionary setObject:font
                                     forKey:NSFontAttributeName];

        resetFontAttribute = NO;
    }
    else
    {
        // Font size only
        value = [dicAttributes objectForKey:GONMarkupFont_TAG_size_ATT];
        if (value)
        {
            // Extract size
            CGFloat size = [value floatValue];
            
            // Look for current font
            UIFont *currentFont = [configurationDictionary objectForKey:NSFontAttributeName];
            if (currentFont)
            {
                // Current font found, so update it with new size
                currentFont = [UIFont fontWithDescriptor:currentFont.fontDescriptor
                                                    size:size];
            }
            else
            {
                // No found defined, use default one with defined size
                currentFont = [UIFont systemFontOfSize:size];
            }
            
            // Update configuration
            [configurationDictionary setObject:currentFont
                                        forKey:NSFontAttributeName];

            resetFontAttribute = NO;
        }
    }

    // Empty font parameter, reset configuration
    if (resetFontAttribute)
        [configurationDictionary removeObjectForKey:NSFontAttributeName];
}

@end


================================================
FILE: Classes/GONMarkupFontTraits.h
================================================
//
//  GONMarkupFontTraits.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 22/09/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//
//  Super class for markers updating font traits
//  overrideBlock allows you to override font. For example, you can used it to return a medium font instead of bold one.
//  If overrideBlock is set, it will be called first. Is nil is returned, sysytem will try to automatically resolve font
//  Also note that if an overrideBlock is set, it will be called even is current font have needed trait.
//
//  You may not need to use this class directly. Use subclasses instead (GONMarkupBold, GONMarkupItalic)

#import "GONMarkup.h"

@interface GONMarkupFontTraits : GONMarkup {
}

/* Class constructor */
+ (instancetype)fontTraitsMarkup:(NSString *)tag traits:(UIFontDescriptorSymbolicTraits )trait;

@property (nonatomic, copy) UIFont *(^overrideBlock)(UIFont *font);             // Should return a font. Markup will automatically update font to needed size.
@property (nonatomic, assign, readonly) UIFontDescriptorSymbolicTraits trait;
@end


================================================
FILE: Classes/GONMarkupFontTraits.m
================================================
//
//  GONMarkupFontTraits.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 22/09/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupFontTraits.h"
#import "GONMarkup+Private.h"

@interface GONMarkupFontTraits ()
// Data
@property (nonatomic, assign) UIFontDescriptorSymbolicTraits trait;
@end

@implementation GONMarkupFontTraits
#pragma mark - Constructor
+ (instancetype)fontTraitsMarkup:(NSString *)tag traits:(UIFontDescriptorSymbolicTraits )trait
{
    GONMarkupFontTraits *markup = [self markupForTag:tag];

    markup.trait = trait;

    return markup;
}


#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Look for current font
    UIFont *currentFont = [configurationDictionary objectForKey:NSFontAttributeName];
    if (!currentFont)
    {
        // No found defined, use default one with default size
        currentFont = [UIFont systemFontOfSize:[UIFont systemFontSize]];
    }

    UIFont *updatedFont = nil;

    // Check override block
    if (_overrideBlock)
    {
        // Try with override block
        updatedFont = _overrideBlock(currentFont);
    }

    // Check if font already has traits, and if override blocks didn't return a font
    if (!updatedFont)
    {
        // Update font to set trait
        UIFontDescriptor *fontDescriptor = currentFont.fontDescriptor;
        UIFontDescriptorSymbolicTraits fontTaits = fontDescriptor.symbolicTraits;

        if (!(fontTaits & _trait))
        {
            fontTaits |= _trait;
            updatedFont = [UIFont fontWithDescriptor:[fontDescriptor fontDescriptorWithSymbolicTraits:fontTaits]
                                                size:currentFont.pointSize];

            // Font may not exists, fallback
            // Note : In iOS7, if no fount is found, normal one will be returned. Since iOS8, nil will be returned
            if (!updatedFont || [currentFont isEqual:updatedFont])
            {
                if (self.parser.logLevel & GONMarkupParserLogLevelFonts)
                {
                    if (!_overrideBlock)
                        NSLog(@"%@ : No font found for <%@-%@> applying traits. Consider setting up <overrideBlock> to provide a font", [[self class] description], currentFont.familyName, currentFont.fontName);
                    else
                        NSLog(@"%@ : No font returned from overrideBlock for <%@-%@>. Consider seting up one", [[self class] description], currentFont.familyName, currentFont.fontName);
                }

                // Do not update font
                updatedFont = currentFont;
            }
        }
        else
        {
            // Font has already requested trait, so use it
            updatedFont = currentFont;
        }
    }

    // Check for font size
    if (updatedFont.pointSize != currentFont.pointSize)
    {
        // Build a new font with current size
        updatedFont = [UIFont fontWithDescriptor:[updatedFont fontDescriptor]
                                            size:currentFont.pointSize];
    }

    // Update configuration
    [configurationDictionary setObject:updatedFont
                                 forKey:NSFontAttributeName];
}

@end


================================================
FILE: Classes/GONMarkupImage.h
================================================
//
//  GONMarkupImage.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/03/16.
//  Copyright © 2016 Nicolas Goutaland. All rights reserved.
//
//
//  Define a generic markup to add images
//  You can specify image path with "value" attribute.
//
//  Examples
//
//  <image src="image.png"/>
//  <image src="#FFEEAA"/>
//  <image src="myCustomRegisteredColor"/>

#import "GONMarkup.h"

// Tag
#define GONMarkupImage_TAG                 @"image"

// Attributes
#define GONMarkupImage_TAG_value_ATT       @"src"

@interface GONMarkupImage : GONMarkup
/* Default markup to add image support */
+ (instancetype)imageMarkup;
@end


================================================
FILE: Classes/GONMarkupImage.m
================================================
//
//  GONMarkupImage.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/03/16.
//  Copyright © 2016 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupImage.h"

@implementation GONMarkupImage
+ (instancetype)imageMarkup
{
    return [self markupForTag:@"image"];
}

- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString
{
    UIImage *image = [UIImage imageNamed:[dicAttributes objectForKey:GONMarkupImage_TAG_value_ATT]];
    if (image)
    {
        CGFloat scale = [UIScreen mainScreen].scale;
        scale = 2;
        NSTextAttachment *attch = [[NSTextAttachment alloc] init];
        attch.image = image;
        attch.bounds = CGRectMake(0, 0, image.size.width/scale, image.size.height/scale);
        return [NSAttributedString attributedStringWithAttachment:attch];
    }

    return [super updatedContentString:string
                               context:context
                            attributes:dicAttributes
                      stringAttributes:stringAttributes
                          resultString:resultString];
}
@end


================================================
FILE: Classes/GONMarkupInc.h
================================================
//
//  GONMarkupInc.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 10/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Define a markup to increment font size. By default, font is increased by 1 point.
//  You can specify another increment value with "value" attribute.
//
//  Examples
//
//  <inc>text</>
//  <inc value="5">text</>

#import "GONMarkup.h"

// Tag
#define GONMarkupInc_TAG                 @"inc"

// Attributes
#define GONMarkupInc_TAG_value_ATT       @"value"

@interface GONMarkupInc : GONMarkup
/* Default markup to add text size increment support */
+ (instancetype)incMarkup;
@end


================================================
FILE: Classes/GONMarkupInc.m
================================================
//
//  GONMarkupInc.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 10/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupInc.h"

#define DEFAULT_INC_VALUE   1

@implementation GONMarkupInc
#pragma mark - Constructor
+ (instancetype)incMarkup
{
    return [super markupForTag:GONMarkupInc_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    NSInteger incValue = [[dicAttributes objectForKey:GONMarkupInc_TAG_value_ATT] intValue];
    if (!incValue)
        incValue = DEFAULT_INC_VALUE;

    // Look for current font
    UIFont *currentFont = [configurationDictionary objectForKey:NSFontAttributeName];
    if (!currentFont)
    {
        // No found defined, use default one with default size
        currentFont = [UIFont systemFontOfSize:[UIFont systemFontSize]];
    }

    // Update current font with new size
    [configurationDictionary setObject:[currentFont fontWithSize:currentFont.pointSize + incValue]
                                forKey:NSFontAttributeName];
}
@end


================================================
FILE: Classes/GONMarkupItalic.h
================================================
//
//  GONMarkupItalic.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 19/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Tag updating current font style to italic
//  This tag may not work if no italic version of current font is available.
//  overrideBlock (GONMarkupFontTraits) allows you to override font. For example, you can used it to return a medium italic font instead of bold italic one.
//  If overrideBlock is set, it will be called first. Is nil is returned, system will try to automatically resolve font
//
//  Examples
//
//  <i>italic text</>

#import "GONMarkupFontTraits.h"

#define GONMarkupItalic_TAG               @"i"

@interface GONMarkupItalic : GONMarkupFontTraits

/* Default markup to add italic support */
+ (instancetype)italicMarkup;
@end


================================================
FILE: Classes/GONMarkupItalic.m
================================================
//
//  GONMarkupItalic.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 19/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupItalic.h"
#import "GONMarkup+Private.h"

@implementation GONMarkupItalic
#pragma mark - Constructor
+ (instancetype)italicMarkup
{
    return [super fontTraitsMarkup:GONMarkupItalic_TAG
                            traits:UIFontDescriptorTraitItalic];
}
@end


================================================
FILE: Classes/GONMarkupLineBreak.h
================================================
//
//  GONMarkupLineBreak.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Markup to handle <br/> characters, generating a new line
//
//  Example
//
//  <br />

#import "GONMarkup.h"

// Tag
#define GONMarkupLineBreak_TAG                 @"br"

@interface GONMarkupLineBreak : GONMarkup
/* Class constructor */
+ (instancetype)lineBreakMarkup;
@end


================================================
FILE: Classes/GONMarkupLineBreak.m
================================================
//
//  GONMarkupLineBreak.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupLineBreak.h"
#import "GONMarkupList.h"

#define NEW_LINE            @"\n"
#define CARRIAGE_RETURN     @"\u2028"

@implementation GONMarkupLineBreak
#pragma mark - Constructor
+ (instancetype)lineBreakMarkup
{
    return [self markupForTag:GONMarkupLineBreak_TAG];
}

#pragma mark - Content update
- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString 
{
    // If in a list, no new lines
    if ([context objectForKey:GONMarkupList_CONFIGURATIONS_KEY])
        return [[NSAttributedString alloc] initWithString:CARRIAGE_RETURN attributes:stringAttributes];

    return [[NSAttributedString alloc] initWithString:NEW_LINE attributes:stringAttributes];
}

@end


================================================
FILE: Classes/GONMarkupLineStyle.h
================================================
//
//  GONMarkupLineStyle.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 03/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//
//
//  Tag used to set underline / strikethrough style.
//  Attribute "word" can be set to apply style only on words. Default is "false".
//  Attribute "style" can be used to configure line style (single | thick | double). Default is "single".
//  Attribute "pattern" can be used to configure pattern style (solid | dot | dash | dashdot | dashdotdot). Default is "solid".
//  Attribute "color" can be used to configure line color. Default is the same as text".
//
//  Colors are handled via NSString+Color, using "representedColor" category method
//  Have a look at https://github.com/nicolasgoutaland/NSString-Color for more information

//
//  Examples
//
//  <u>underline text</>
//  <u word="true">underline text, only for words</>
//  <u pattern="dashdot">underline text with dashdot pattern</>
//  <u pattern="dashdot" word="true">underline text with dashdot pattern, only for words</>
//  <strike>strikethrough text</>
//  <strike pattern="dashdot">strikethrough text with dashdot pattern</>
//  <strike pattern="dashdot" word="true">strikethrough text with dashdot pattern, only for words</>
//
#import "GONMarkup.h"

// Tag
#define GONMarkupLineStyle_Underline_TAG             @"u"
#define GONMarkupLineStyle_Strikethrough_TAG         @"strike"

// Attributes
#define GONMarkupLineStyle_TAG_word_ATT              @"word"
#define GONMarkupLineStyle_TAG_style_ATT             @"style"
#define GONMarkupLineStyle_TAG_pattern_ATT           @"pattern"
#define GONMarkupLineStyle_TAG_color_ATT             @"color"

@interface GONMarkupLineStyle : GONMarkup
/* Return all markups */
+ (NSArray *)allMarkups;

/* Default markup to add underline support */
+ (instancetype)underlineMarkup;

/* Default markup to add strikethrough support */
+ (instancetype)strikethroughMarkup;
@end


================================================
FILE: Classes/GONMarkupLineStyle.m
================================================
//
//  GONMarkupLineStyle.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 03/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupLineStyle.h"
#import "NSString+Color.h"

@interface GONMarkupLineStyle ()
// Data
@property (nonatomic, strong) NSString *configurationKey;
@property (nonatomic, strong) NSString *colorConfigurationKey;
@end

@implementation GONMarkupLineStyle
#pragma mark - Class initialization
static NSDictionary *dicStyles;
static NSDictionary *dicPatterns;
+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dicStyles = @{
                        @"single" : @(NSUnderlineStyleSingle),
                        @"double" : @(NSUnderlineStyleDouble),
                        @"thick"  : @(NSUnderlineStyleThick),
                     };

        dicPatterns = @{
                         @"solid"       : @(NSUnderlinePatternSolid),
                         @"dot"         : @(NSUnderlinePatternDot),
                         @"dash"        : @(NSUnderlinePatternDash),
                         @"dashdot"     : @(NSUnderlinePatternDashDot),
                         @"dashdotdot"  : @(NSUnderlinePatternDashDotDot)
                       };
    });
}

#pragma mark - Constructor
+ (NSArray *)allMarkups
{
    return @[[self underlineMarkup], [self strikethroughMarkup]];
}

+ (instancetype)underlineMarkup
{
    GONMarkupLineStyle *markup = [self markupForTag:GONMarkupLineStyle_Underline_TAG];

    markup.configurationKey      = NSUnderlineStyleAttributeName;
    markup.colorConfigurationKey = NSUnderlineColorAttributeName;

    return markup;
}

+ (instancetype)strikethroughMarkup
{
    GONMarkupLineStyle *markup = [self markupForTag:GONMarkupLineStyle_Strikethrough_TAG];

    markup.configurationKey      = NSStrikethroughStyleAttributeName;
    markup.colorConfigurationKey = NSStrikethroughColorAttributeName;

    return markup;
}

#pragma mark - Markup lifecycle
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Hold new configuration
    [configurationDictionary setObject:@([self extractStyleFromAttributes:dicAttributes])
                                forKey:_configurationKey];
    
    // Color
    UIColor *color = [[dicAttributes objectForKey:GONMarkupLineStyle_TAG_color_ATT] representedColor];
    if (color)
    {
        [configurationDictionary setObject:color
                                    forKey:_colorConfigurationKey];
    }
}

- (NSInteger)extractStyleFromAttributes:(NSDictionary *)dicAttributes
{
    NSNumber *tmp;
    NSInteger style = 0;

    // Word option
    if ([[dicAttributes objectForKey:GONMarkupLineStyle_TAG_word_ATT] boolValue])
        style |= NSUnderlineByWord;

    // Style option
    tmp = [dicStyles objectForKey:[[dicAttributes objectForKey:GONMarkupLineStyle_TAG_style_ATT] lowercaseString]];
    if (tmp)
        style |= [tmp integerValue];
    else
        style |= NSUnderlineStyleSingle;

    // Pattern option
    tmp = [dicPatterns objectForKey:[[dicAttributes objectForKey:GONMarkupLineStyle_TAG_pattern_ATT] lowercaseString]];
    if (tmp)
        style |= [tmp integerValue];
    else
        style |= NSUnderlinePatternSolid;

    return style;
}
@end


================================================
FILE: Classes/GONMarkupList.h
================================================
//
//  GONMarkupList.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Markup used to handle lists
//  You HAVE to add GONMarkupListItem support to handle list properly
//
//  Example
//
//  <ul>
//      <li>first item</>
//      <li>second item</>
//      <li>third item</>
//  </>

#import "GONMarkup.h"

// Tag
#define GONMarkupList_unordered_TAG                 @"ul"
#define GONMarkupList_ordered_TAG                   @"ol"

// Context
#define GONMarkupList_CONFIGURATIONS_KEY  @"GONMarkupList.configurations"   // References an array, holding automatically pushed / popped tags configurations

#define GONMarkupList_INDENTATION_KEY     @"GONMarkupList.indentation"
#define GONMarkupList_POSITION_KEY        @"GONMarkupList.position"
#define GONMarkupList_ORDERED_KEY         @"GONMarkupList.ordered"

@interface GONMarkupList : GONMarkup
/* Return all markups, including list item one */
+ (NSArray *)allMarkups;

/* Default markup to add lists support */
+ (instancetype)listMarkup;

/* Default markup to add ordered lists support */
+ (instancetype)orderedListMarkup;

@end


================================================
FILE: Classes/GONMarkupList.m
================================================
//
//  GONMarkupList.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupList.h"
#import "GONMarkupListItem.h"
#import "GONMarkup+Private.h"

@interface GONMarkupList ()
// Data
@property (nonatomic, assign) BOOL isOrdered;
@end

@implementation GONMarkupList
#pragma mark - Markup list
+ (NSArray *)allMarkups
{
    return @[[self listMarkup], [self orderedListMarkup], [GONMarkupListItem listItemMarkup]];
}

#pragma mark - Constructor
+ (instancetype)listMarkup
{
    GONMarkupList *markupList = [self markupForTag:GONMarkupList_unordered_TAG];

    markupList.isOrdered = NO;

    return markupList;
}

+ (instancetype)orderedListMarkup
{
    GONMarkupList *markupList = [self markupForTag:GONMarkupList_ordered_TAG];

    markupList.isOrdered =YES;

    return markupList;
}

#pragma mark - Markup lifecycle
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Compute indentation level
    NSInteger indentationLevel = 0;
    NSDictionary *currentConfiguration = [self currentContextConfiguration:GONMarkupList_CONFIGURATIONS_KEY
                                                               fromContext:context];
    if (currentConfiguration)
        indentationLevel = [[currentConfiguration objectForKey:GONMarkupList_INDENTATION_KEY] intValue] + 1;

    NSDictionary *configuration = [@{
                                     GONMarkupList_ORDERED_KEY       : @(_isOrdered),
                                     GONMarkupList_INDENTATION_KEY   : @(indentationLevel),
                                    } mutableCopy];

    [self pushConfiguration:configuration
                  toContext:context
                     forKey:GONMarkupList_CONFIGURATIONS_KEY];
}

- (NSAttributedString *)updatedContentString:(NSString *)string
                                     context:(NSMutableDictionary *)context
                                  attributes:(NSDictionary *)dicAttributes
                            stringAttributes:(NSDictionary *)stringAttributes
                                resultString:(NSAttributedString *)resultString
{
    return [[NSAttributedString alloc] initWithString:@""];
}

- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    [self popContextConfiguration:GONMarkupList_CONFIGURATIONS_KEY
                      fromContext:context];
}

@end


================================================
FILE: Classes/GONMarkupListItem.h
================================================
//
//  GONMarkupListItem.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Class describing a list item
//  You can subclass it and override methods to handle custom bullets behavior

#import "GONMarkup.h"

// Tag
#define GONMarkupListItem_TAG                 @"li"

@interface GONMarkupListItem : GONMarkup
/* Default markup to add list item support */
+ (instancetype)listItemMarkup;

/* Method used to compute list item prefix, in ORDERED lists
 * You can override this method in subclasses to change behavior
 *
 * indentationLevel : Current item indentation level in list, when list are nested
 * position          : Current item position in parent list.
 * listConfiguration : Parent list configuration
 * context           : Shared context
 *
 * This method is expected to return a string. You MUST NOT return nil
 */
- (NSString *)orderedListItemPrefixForIndentation:(NSInteger)indentationLevel position:(NSInteger)position listConfiguration:(NSDictionary *)listConfiguration context:(NSMutableDictionary *)context;

/* Method used to compute list item prefix, in NON ORDERED lists
 * You can override this method in subclasses to change behavior
 *
 * indentationLevel : Current item indentation level in list, when list are nested
 * position          : Current item position in parent list.
 * listConfiguration : Parent list configuration
 * context            : Shared context
 *
 * This method is expected to return a string. You MUST NOT return nil
 */
- (NSString *)unorderedListItemPrefixForIndentation:(NSInteger)indentationLevel position:(NSInteger)position listConfiguration:(NSDictionary *)listConfiguration context:(NSMutableDictionary *)context;

@end


================================================
FILE: Classes/GONMarkupListItem.m
================================================
//
//  GONMarkupListItem.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupListItem.h"
#import "GONMarkupList.h"
#import "GONMarkup+Private.h"

@implementation GONMarkupListItem
#pragma mark - Constructor
+ (instancetype)listItemMarkup
{
    return [self markupForTag:GONMarkupListItem_TAG];
}

#pragma mark - Internal configuration
+ (NSString *)bulletForIndentation:(NSInteger)anIndentation
{
    static NSArray *bullets = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        bullets = @[@"\u2022", @"\u25E6"];   // Next should be @"\u25A0", @"\u25A1", but they are displayed too big
    });
    
    return [bullets objectAtIndex:anIndentation % bullets.count];
}

- (NSString *)unorderedListItemPrefixForIndentation:(NSInteger)indentationLevel
                                           position:(NSInteger)position
                                  listConfiguration:(NSDictionary *)aListConfiguration
                                            context:(NSMutableDictionary *)context
{
    NSString *indentation = [self listItemIndentation:indentationLevel];
    NSString *bullet = [[self class] bulletForIndentation:indentationLevel];
    
    return [NSString stringWithFormat:@"%@%@ ", indentation, bullet];
}

- (NSString *)orderedListItemPrefixForIndentation:(NSInteger)indentationLevel
                                         position:(NSInteger)position
                                listConfiguration:(NSDictionary *)aListConfiguration
                                          context:(NSMutableDictionary *)context
{
    NSString *indentation = [self listItemIndentation:indentationLevel];
    NSString *bullet = [NSString stringWithFormat:@"%ld.", (long)position];
    
    return [NSString stringWithFormat:@"%@%@ ", indentation, bullet];
}

#pragma mark - Content update
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Retrieve indentation level
    NSMutableDictionary *currentConfiguration = [self currentContextConfiguration:GONMarkupList_CONFIGURATIONS_KEY
                                                                      fromContext:context];
    [currentConfiguration setObject:@([[currentConfiguration objectForKey:GONMarkupList_POSITION_KEY] intValue] + 1)
                             forKey:GONMarkupList_POSITION_KEY];
    
    // Retrieve and update paragraph style
    NSMutableParagraphStyle *paragraphStyle = [self paragraphStyle:configurationDictionary];
    
    // Generate prefix string
    NSAttributedString *prefixString = [self prefixStringForContext:context
                                                         attributes:dicAttributes
                                                   stringAttributes:configurationDictionary
                                                       resultString:resultString];
    
    // Compute prefix string width
    paragraphStyle.headIndent = CGRectGetWidth([prefixString boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
                                                                          options:NSStringDrawingUsesLineFragmentOrigin
                                                                          context:nil]);
}

- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    // Retrieve configuration
    NSDictionary *listConfiguration = [[context objectForKey:GONMarkupList_CONFIGURATIONS_KEY] lastObject];
    
    NSInteger indentation = [[listConfiguration objectForKey:GONMarkupList_INDENTATION_KEY] intValue];
    NSInteger position    = [[listConfiguration objectForKey:GONMarkupList_POSITION_KEY] intValue];
    BOOL isOrdered        = [[listConfiguration objectForKey:GONMarkupList_ORDERED_KEY] intValue];
    
    NSString *prefix;
    if (isOrdered)
    {
        prefix = [self orderedListItemPrefixForIndentation:indentation
                                                  position:position
                                         listConfiguration:listConfiguration
                                                   context:context];
    }
    else
    {    prefix = [self unorderedListItemPrefixForIndentation:indentation
                                                     position:position
                                            listConfiguration:listConfiguration
                                                      context:context];
    }
    
    // If starting a new list, we must have a blank line before previous text
    if (position == 1 && indentation == 0)
    {
        // If last char isn't a new line, add a new line
        if (resultString.string.length > 0 && ![[NSCharacterSet newlineCharacterSet] characterIsMember:[resultString.string characterAtIndex:resultString.string.length - 1]])
        {
            prefix = [@"\n\n" stringByAppendingString:prefix];
        } // Last char was a newline, so check if a blank line already exists before paragraph
        else if (resultString.string.length > 1 && ![[NSCharacterSet newlineCharacterSet] characterIsMember:[resultString.string characterAtIndex:resultString.string.length - 2]])
        {
            prefix = [@"\n" stringByAppendingString:prefix];
        }
    }
    else
    {
        prefix = [@"\n" stringByAppendingString:prefix];
    }
    
    return [[NSAttributedString alloc] initWithString:prefix attributes:stringAttributes];
}

#pragma mark - Utils
- (NSMutableParagraphStyle *)paragraphStyle:(NSMutableDictionary *)configurationDictionary
{
    NSMutableParagraphStyle *paragraphStyle = [[configurationDictionary objectForKey:NSParagraphStyleAttributeName] mutableCopy];
    if (!paragraphStyle)
        paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    
    // Hold updated paragraph style
    [configurationDictionary setObject:paragraphStyle
                                forKey:NSParagraphStyleAttributeName];
    
    return paragraphStyle;
}

- (NSString *)listItemIndentation:(NSInteger)anIndentation
{
    NSMutableString *indentString = [[NSMutableString alloc] init];
    
    for (NSInteger i=0; i<anIndentation; i++)
        [indentString appendString:@"\t"];
    
    return indentString;
}
@end


================================================
FILE: Classes/GONMarkupNamedColor.h
================================================
//
//  GONMarkupNamedColor.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Define a tag to set foreground text color
//  When encountered, contained text will use associated color
//

#import "GONMarkup.h"

@interface GONMarkupNamedColor : GONMarkup
/* Class constructor
 * If aColor is nil, so this tag will reset current color to parser default one
 */
+ (instancetype)namedColorMarkup:(UIColor *)aColor forTag:(NSString *)tag;

@property (nonatomic, strong, readonly) UIColor *color;
@end


================================================
FILE: Classes/GONMarkupNamedColor.m
================================================
//
//  GONMarkupNamedColor.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupNamedColor.h"
#import "GONMarkup+Private.h"

@interface GONMarkupNamedColor ()
// Data
@property (nonatomic, strong) UIColor *color;
@end

@implementation GONMarkupNamedColor
#pragma mark - Class constructor
+ (instancetype)namedColorMarkup:(UIColor *)aColor forTag:(NSString *)tag
{
    GONMarkupNamedColor *markup = [self markupForTag:tag];

    markup.color = aColor;

    return markup;
}

#pragma mark - Configuration
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    if (_color)
    {
        [configurationDictionary setObject:_color
                                     forKey:NSForegroundColorAttributeName];
    }
    else
    {
        UIColor *defaultColor = [[self.parser defaultConfiguration] objectForKey:NSForegroundColorAttributeName];
        if (defaultColor)
        {
            [configurationDictionary setObject:defaultColor
                                         forKey:NSForegroundColorAttributeName];
        }
        else
        {
            [configurationDictionary removeObjectForKey:NSForegroundColorAttributeName];
        }
    }
}

@end


================================================
FILE: Classes/GONMarkupNamedFont.h
================================================
//
//  GONMarkupNamedFont.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Define a tag to set font / remove font
//  When encountered, contained text will use associated font and color if set

#import "GONMarkup.h"

@interface GONMarkupNamedFont : GONMarkup
/* Class constructor 
 * If font is nil, so this tag will reset current font to parser default one
 */
+ (instancetype)namedFontMarkup:(UIFont *)font forTag:(NSString *)tag;

@property (nonatomic, strong, readonly) UIFont *font;
@end


================================================
FILE: Classes/GONMarkupNamedFont.m
================================================
//
//  GONMarkupNamedFont.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupNamedFont.h"
#import "GONMarkup+Private.h"

@interface GONMarkupNamedFont ()
// Data
@property (nonatomic, strong) UIFont *font;
@end

@implementation GONMarkupNamedFont
#pragma mark - Class constructor
+ (instancetype)namedFontMarkup:(UIFont *)font forTag:(NSString *)tag
{
    GONMarkupNamedFont *markup = [self markupForTag:tag];

    markup.font = font;
    
    return markup;
}

#pragma mark - Configuration
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    if (_font)
    {
        [configurationDictionary setObject:_font
                                     forKey:NSFontAttributeName];
    }
    else
    {
        UIFont *defaultfont = [[self.parser defaultConfiguration] objectForKey:NSFontAttributeName];
        if (defaultfont)
        {
            [configurationDictionary setObject:defaultfont
                                         forKey:NSFontAttributeName];
        }
        else
        {
            [configurationDictionary removeObjectForKey:NSFontAttributeName];
        }
    }
}
@end


================================================
FILE: Classes/GONMarkupParagraph.h
================================================
//
//  GONMarkupParagraph.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 06/08/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Markup to handle paragraphs
//  A paragraph will automatically insert a new line after text
//
//  Example
//
//  <p>First paragraph</p>
//
#import "GONMarkup.h"

// Tag
#define GONMarkupParagraph_TAG                 @"p"

@interface GONMarkupParagraph : GONMarkup
/* Class constructor */
+ (instancetype)paragraphMarkup;
@end


================================================
FILE: Classes/GONMarkupParagraph.m
================================================
//
//  GONMarkupParagraph.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 06/08/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
// Markup to handle <p>. A blank line will be inserted after the paragraph end (\n\n)

#import "GONMarkupParagraph.h"

@implementation GONMarkupParagraph
#pragma mark - Constructor
+ (instancetype)paragraphMarkup
{
    return [self markupForTag:GONMarkupParagraph_TAG];
}

#pragma mark - Content update
- (NSAttributedString *)prefixStringForContext:(NSMutableDictionary *)context
                                    attributes:(NSDictionary *)dicAttributes
                              stringAttributes:(NSDictionary *)stringAttributes
                                  resultString:(NSAttributedString *)resultString
{
    NSString *prefix = @"";
    
    // Check for previous newline
    if (resultString.string.length > 0)
    {
        // If last char isn't a new line, add a new line
        if (![[NSCharacterSet newlineCharacterSet] characterIsMember:[resultString.string characterAtIndex:resultString.string.length - 1]])
        {
            prefix = @"\n\n";
        } // Last char was a newline, so check if a blank line already exists before paragraph
        else if (resultString.string.length > 1 && ![[NSCharacterSet newlineCharacterSet] characterIsMember:[resultString.string characterAtIndex:resultString.string.length - 2]])
        {
            prefix = @"\n";
        }
    }
    
    return [[NSAttributedString alloc] initWithString:prefix attributes:stringAttributes];
}

@end


================================================
FILE: Classes/GONMarkupParser.h
================================================
//
//  GONMarkupParser.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//
//  A simple string parser, allowing string manipulation, usually used to parse HTML like string.
//  You have to define your own rules and ensure that tags are wellformed
//
//  To close a tag, you do not have to specity its name, </> is valid
//  <//> is also valid to close all previoulsy opened tags
//
// History
// -------
// 0.7.5 : Fixed bugs on lists, Added support for strong tag
// 0.7.4 : Fixed (again -_-) new line character bug on lists
// 0.7.3 : Fixed new line character bug on lists
// 0.7.2 : Fixed bug #21
// 0.7.1 : Fixed warning #18
// 0.7.0 : Fixed bug #15
// 0.6.9 : Fixed bug #12
// 0.6.8 : Fixed import problems with cocoa Pods 0.39
// 0.6.7 : Added color attribute to font markup
// 0.6.6 : Added UIButton+GONMarkupParser category
// 0.6.5 : Updated HTML chars tables
// 0.6.4 : Updated HTML chars tables
// 0.6.3 : Fixed a bug in anchor support
// 0.6.2 : Added anchor support
// 0.6.1 : Added support for underline and strikethrough color
// 0.6   : Added support for underline / strikethrough text
// 0.5   : Initial release

// Roadmap
// -------
// Evolution : Allow markup to be encoded (NSCoding)
// Evolution : Loading from PLIST file
// Evolution : Allow copy for parsers / markup

#import "GONMarkup.h"

#define GONMarkupParser_ERROR_DOMAIN                   @"error.markupParser"
#define GONMarkupParser_StringMalformed_ERROR_CODE     69
#define GONMarkupParser_incorrectClosingTag_KEY        @"incorrectClosingTag"

typedef enum : NSUInteger {
    GONMarkupParserLogLevelNone           = 0,              // No logs
    GONMarkupParserLogLevelUnbalancedTags = 0x01 << 0,      // Logs when unbalanced tags are found
    GONMarkupParserLogLevelUnknownTag     = 0x01 << 1,      // Logs when an unknow tag is found
    GONMarkupParserLogLevelWorkflow       = 0x01 << 2,      // Logs parser workflow (Very verbose)
    GONMarkupParserLogLevelFonts          = 0x01 << 3,      // Logs fonts errors (Very useful to detect missing bold / italic fonts)
    GONMarkupParserLogLevelAll            = 0xFF,           // Logs all
    GONMarkupParserLogLevelErrors         = GONMarkupParserLogLevelFonts | GONMarkupParserLogLevelUnknownTag | GONMarkupParserLogLevelUnbalancedTags
} GONMarkupParserLogLevel;

@interface GONMarkupParser : NSObject
// Constructors
/* Instanciate a new markup parser, configured to handle all default tags */
+ (GONMarkupParser *)defaultMarkupParser;

/* Instanciate a new empty markup parser. This parser won't have any configured tag
 * Same as [[GONMarkupParser alloc] init]
 */
+ (GONMarkupParser *)emptyMarkupParser;

/* Add a new markup to parser
 * A markup can be used in only one parser at a time
 * If you are trying to a markup already used by another parser, an exception willl be thrown
 */
- (void)addMarkup:(GONMarkup *)markup;

/* Add some markups */
- (void)addMarkups:(id <NSFastEnumeration>)markups;

/* Return a previously registered markup that can handle given tag */
- (GONMarkup *)markupForTag:(NSString *)tag;

/* Remove given markup from parser, if previously added */
- (void)removeMarkup:(GONMarkup *)markup;

/* Remove given markups from parser, if previously added */
- (void)removeMarkups:(id <NSFastEnumeration>)markups;

/* Remove all currently applied markups */
- (void)removeAllMarkups;

// Fonts management
/* Register given font */
- (void)registerFont:(UIFont *)font forKey:(NSString *)key;

/* Register given font */
- (UIFont *)fontForKey:(NSString *)key;

/* Register given font */
- (void)unregisterFontForKey:(NSString *)key;

/* Convert given string to an attributed string.
 * String will be parsed and updated according to stored markups
 * If nil is passed as parameter, an empty string will be returned
 *
 * anError may be set if input string seems malformed, but method will return a valid string. Only last error is returned.
 */
- (NSMutableAttributedString *)attributedStringFromString:(NSString *)string error:(NSError **)error;

/* Same as attributedStringFromString:string error:nil.
 * Because sometimes, you don't care about errors.
 */
- (NSMutableAttributedString *)attributedStringFromString:(NSString *)string;

@property (nonatomic, assign)           BOOL replaceNewLineCharactersFromInputString;                           // If YES, all [NSCharacterSet newlineCharacterSet] will be replaced by spaces from input string.
                                                                                                                // Replacing process will occur AFTER preprocessingBlock, BEFORE parsing.
                                                                                                                // Use <br/> and <p> to add new lines. Default is NO.

@property (nonatomic, assign)           BOOL replaceHTMLCharactersFromOutputString;                             // If YES, all HTML entities will be replaced in output string.
                                                                                                                // Replacing process will occur BEFORE postProcessingBlock, AFTER parsing.
                                                                                                                // Default is YES

@property (nonatomic, strong, readonly) NSMutableDictionary *defaultConfiguration;                              // Default attributed string configuration
@property (nonatomic, readonly)         NSArray *markups;                                                       // Retrieve all applied markups
@property (nonatomic, readonly)         NSDictionary *registeredFonts;                                          // Retrieve all applied markups
@property (nonatomic, copy)             void (^preProcessingBlock)(NSMutableString *inputString);               // Block automatically called to preprocess input string
@property (nonatomic, copy)             void (^postProcessingBlock)(NSMutableAttributedString *inputString);    // Block automatically called to postprocess result attributed string
@property (nonatomic, assign)           GONMarkupParserLogLevel logLevel;                                       // Bitmask to select displayed logs
@property (nonatomic, assign)           BOOL assertOnError;                                                     // Enables assert when an error is generated. Useful when debugging.
@end


================================================
FILE: Classes/GONMarkupParser.m
================================================
//
//  GONMarkupParser.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland All rights reserved.
//

#import "GONMarkupParser.h"
#import "GONMarkup+Private.h"
#import "GONMarkupDefaultMarkups.h"
#import "GONMarkupParserUtils.h"

#define MARKUP_REGEX                           @"(.*?)(<[^>]+>|\\Z)"
#define ATTRIBUTES_REGEX                       @"([^\\s=]+)\\s*=\\s*('(\\\\'|[^']*')|\"(\\\\\"|[^\"])*\")"
#define LOG_IF_DEBUG(level, msg, ...)          do {if (_logLevel & level) { NSLog(@"MarkupParser : %@", [NSString stringWithFormat:msg, ##__VA_ARGS__]); }} while(0)

@interface GONMarkupParser ()
// Style
@property (nonatomic, strong) NSMutableDictionary *defaultConfiguration;     // Default attributed string configuration

// Fonts
@property (nonatomic, strong) NSMutableDictionary *dicRegisteredFonts;       // Registered fonts

// Data
@property (nonatomic, strong) NSMutableDictionary *dicCurrentMarkup;         // Dictionary representation of markups
@property (nonatomic, strong) NSRegularExpression *markupRegex;              // Regular expression to extract tokens
@property (nonatomic, strong) NSRegularExpression *attributesRegex;          // Attributes regex

// Ephemeral internal data. Used to reduce parameters count in internal methods
@property (nonatomic, strong) NSMutableArray      *configurationsStack;      // Configurations stack
@property (nonatomic, strong) NSMutableArray      *markupsStack;             // Markups stack
@property (nonatomic, strong) NSMutableArray      *markupAttributesStack;    // Markups attributes stack
@property (nonatomic, strong) NSMutableDictionary *currentContext;           // Current context
@end

@implementation GONMarkupParser
#pragma mark - Constructor
+ (GONMarkupParser *)defaultMarkupParser
{
    GONMarkupParser *parser = [[GONMarkupParser alloc] init];

    // WIP
    // [parser addMarkup:[GONMarkupImage imageMarkup]];

    [parser addMarkup:[GONMarkupItalic italicMarkup]];
    [parser addMarkup:[GONMarkupBold boldMarkup]];
    [parser addMarkup:[GONMarkupStrong strongMarkup]];

    [parser addMarkup:[GONMarkupDec decMarkup]];
    [parser addMarkup:[GONMarkupInc incMarkup]];

    [parser addMarkup:[GONMarkupAnchor anchorMarkup]];
    [parser addMarkup:[GONMarkupFont fontMarkup]];
    [parser addMarkup:[GONMarkupColor colorMarkup]];
    [parser addMarkup:[GONMarkupLineBreak lineBreakMarkup]];
    [parser addMarkup:[GONMarkupReset resetMarkup]];
    [parser addMarkup:[GONMarkupParagraph paragraphMarkup]];

    [parser addMarkups:[GONMarkupLineStyle allMarkups]];
    [parser addMarkups:[GONMarkupTextStyle allMarkups]];
    [parser addMarkups:[GONMarkupList allMarkups]];
    [parser addMarkups:[GONMarkupAlignment allMarkups]];

    return parser;
}

+ (GONMarkupParser *)emptyMarkupParser
{
    return [[GONMarkupParser alloc] init];
}

- (id)init
{
    if (self = [super init])
    {
        _markupRegex = [[NSRegularExpression alloc] initWithPattern:MARKUP_REGEX
                                                            options:NSRegularExpressionDotMatchesLineSeparators
                                                              error:nil];

        _attributesRegex = [[NSRegularExpression alloc] initWithPattern:ATTRIBUTES_REGEX
                                                                options:NSRegularExpressionDotMatchesLineSeparators
                                                                  error:nil];

        _assertOnError           = NO;
        _logLevel                = GONMarkupParserLogLevelNone;
        _defaultConfiguration    = [[NSMutableDictionary alloc] init];
        _dicCurrentMarkup        = [[NSMutableDictionary alloc] init];
        _dicRegisteredFonts      = [[NSMutableDictionary alloc] init];

        _replaceNewLineCharactersFromInputString = NO;
        _replaceHTMLCharactersFromOutputString   = YES;
    }

    return self;
}

#pragma mark - Markup management
- (void)addMarkup:(GONMarkup *)markup
{
    // Nothing to do if already added to parser
    if (markup.parser == self)
        return;

    if (markup.parser != nil)
        @throw @"Error, a Markup can be used by only one parser at a time";

    // Bind to parser
    markup.parser = self;
    [_dicCurrentMarkup setObject:markup
                          forKey:markup.tag];
}

- (GONMarkup *)markupForTag:(NSString *)tag
{
    // Retrieve markup
    return [_dicCurrentMarkup objectForKey:tag];
}

- (void)addMarkups:(id <NSFastEnumeration>)markups
{
    for (GONMarkup *markup in markups)
        [self addMarkup:markup];
}

- (void)removeMarkup:(GONMarkup *)markup
{
    GONMarkup *currentMarkup = [_dicCurrentMarkup objectForKey:markup.tag];
    if (currentMarkup == markup)
    {
        // Remove parser link
        markup.parser = nil;
        [_dicCurrentMarkup removeObjectForKey:markup.tag];
    }
}

- (void)removeMarkups:(id <NSFastEnumeration>)markups
{
    for (GONMarkup *markup in markups)
        [self removeMarkup:markup];
}

- (void)removeAllMarkups
{
    for (GONMarkup *markup in [_dicCurrentMarkup allValues])
        markup.parser = nil;

    [_dicCurrentMarkup removeAllObjects];
}

#pragma mark - Parser
- (NSMutableAttributedString *)attributedStringFromString:(NSString *)string
{
    return [self attributedStringFromString:string
                                      error:nil];
}

- (NSMutableAttributedString *)attributedStringFromString:(NSString *)string error:(NSError **)error
{
    LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Input string :\n%@\n", string);

    // Check for nil values
    if (!string)
    {
        LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Input string was <nil>, returning empty string");
        return [[NSMutableAttributedString alloc] init];
    }

    // Make input string mutable
    NSMutableString *inputString = [string mutableCopy];

    // Handle pre processing
    LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Preprocessing string");
    if (_preProcessingBlock)
        _preProcessingBlock(inputString);

    // Replace new line characters
    if (_replaceNewLineCharactersFromInputString)
        inputString = [[[inputString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@" "] mutableCopy];

    // Parse input string
    NSMutableAttributedString *resString = [self parseString:inputString error:error];

    if (error)
        LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Parsing completed with an error <%@>", *error);
    else
        LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Parsing completed without error");

    // Replace html entities
    if (_replaceHTMLCharactersFromOutputString)
        [GONMarkupParserUtils cleanHTMLEntitiesFromString:resString.mutableString];

    // Handle post processing
    LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Postprocessing string");
    if (_postProcessingBlock)
        _postProcessingBlock(resString);

    LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Result string :\n%@\n", resString);

    return resString;
}

- (NSMutableAttributedString *)parseString:(NSString *)inputString error:(NSError **)error
{
    // Init stack
    _configurationsStack   = [[NSMutableArray alloc] init];
    _currentContext        = [[NSMutableDictionary alloc] init];
    _markupsStack          = [[NSMutableArray alloc] init];
    _markupAttributesStack = [[NSMutableArray alloc] init];

    // Parse string
    NSArray *results = [_markupRegex matchesInString:inputString
                                             options:0
                                               range:NSMakeRange(0, inputString.length)];

    // Prepare result string
    NSMutableAttributedString *resultString = [[NSMutableAttributedString alloc] init];

    // Browse chunks
    NSString *tag;
    BOOL autoclosingMarkup;
    @try
    {
        [resultString beginEditing];

        for (NSTextCheckingResult *result in results)
        {
            // Split string
            NSArray *parts = [[inputString substringWithRange:result.range] componentsSeparatedByString:@"<"];
            
            // Append extracted string
            [resultString appendAttributedString:[self computeFinalExtractedString:[parts firstObject]
                                                                      resultString:resultString]];
            
            // Check if a tag was found
            if (parts.count > 1)
            {
                // Extract tag and clean it
                tag = [parts objectAtIndex:1];
                tag = [tag substringToIndex:tag.length - 1]; // Remove final >
                tag = [tag stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                
                if ([tag rangeOfString:@"/"].location == 0)
                {
                    // Lowercase tag, trim closing character
                    tag = [[tag substringFromIndex:1] lowercaseString];
                    
                    // Trim potential remaining white spaces
                    tag = [tag stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                    
                    // Closing current tag, so append result string
                    [resultString appendAttributedString:[self computeSuffixString:resultString]];
                    [self handleClosingTag:tag
                              resultString:resultString
                                     error:error];
                }
                else
                {
                    // Check if autoclosing markup or not
                    autoclosingMarkup = [tag rangeOfString:@"/" options:NSBackwardsSearch].location == (tag.length - 1);
                    
                    // If autoclosing markup, trim last /
                    if (autoclosingMarkup)
                        tag = [tag substringToIndex:tag.length - 1];
                    
                    // Trim potential remaining white spaces
                    tag = [tag stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                    
                    // Split tag / attributes
                    tag = [self extractTagAndPushAttributesFromTag:tag];
                    
                    // Handle autoclosing markup
                    if (autoclosingMarkup)
                    {
                        // Opening tag
                        [self handleOpeningTag:tag
                                  resultString:resultString
                                         error:error];
                        
                        // Append an extracted empty string
                        [resultString appendAttributedString:[self computePrefixString:resultString]];
                        [resultString appendAttributedString:[self computeFinalExtractedString:@"" resultString:resultString]];
                        [resultString appendAttributedString:[self computeSuffixString:resultString]];
                        
                        // Close tag
                        [self handleClosingTag:tag
                                         resultString:resultString
                                         error:error];
                    }
                    else
                    {
                        // Opening tag
                        [self handleOpeningTag:tag
                                  resultString:resultString
                                         error:error];
                        [resultString appendAttributedString:[self computePrefixString:resultString]];
                    }
                }
            }
        }
        [resultString endEditing];

        if (_configurationsStack.count != 0)
        {
            LOG_IF_DEBUG(GONMarkupParserLogLevelUnbalancedTags, @"Parsing completed, but stack isn't empty, some closing tags seems missing :\nStack :%@\n", _configurationsStack);
            [self generateError:error tag:nil];
        }
    }
    @catch (NSException *exception)
    {
        LOG_IF_DEBUG(GONMarkupParserLogLevelErrors, @"An error did occur while parsing :%@\n", exception);
        LOG_IF_DEBUG(GONMarkupParserLogLevelErrors, @"Parsed string so for :\n%@\n", resultString.string);
        [self generateError:error tag:nil];
    }

    // Flush unuseful data
    _markupsStack          = nil;
    _configurationsStack   = nil;
    _currentContext        = nil;
    _markupAttributesStack = nil;

    return resultString;
}

#pragma mark - Utils
- (NSString *)extractTagAndPushAttributesFromTag:(NSString *)tag
{
    // Check for attributes
    NSRange range = [tag rangeOfString:@" "];
    NSDictionary *attributes = nil;
    NSString *extractedTag;
    if (range.location == NSNotFound)
    {
        // No attributed to extract, and tag is full string
        extractedTag = tag;
    }
    else
    {
        // There may be some attributes, so extract tag
        extractedTag = [tag substringToIndex:range.location];

        attributes = [self extractAttributesFromString:[tag substringFromIndex:range.location]];
    }

    // Check if some attributes were found
    [_markupAttributesStack addObject:(attributes.count ? attributes : [NSNull null])];

    return [extractedTag lowercaseString];
}

- (NSDictionary *)attributesForCurrentTag
{
    id attributes = [_markupAttributesStack lastObject];
    if (attributes == [NSNull null])
        return nil;

    return attributes;
}

- (NSDictionary *)extractAttributesFromString:(NSString *)string
{
    NSMutableDictionary *dicAttributes = [[NSMutableDictionary alloc] init];

    // Parse string
    NSArray *results = [_attributesRegex matchesInString:string
                                                 options:0
                                                   range:NSMakeRange(0, string.length)];

    // Browse chunks
    NSString *matchedString;
    NSRange range;
    NSString *attributeKey;
    NSMutableString *attributeValue;
    for (NSTextCheckingResult *result in results)
    {
        // Extract matched string
        matchedString = [string substringWithRange:result.range];
        
        // Look for character to split string
        range = [matchedString rangeOfString:@"="];

        // Extract key
        attributeKey    = [[matchedString substringToIndex:range.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        
        // Extract value
        attributeValue  = [[[matchedString substringFromIndex:range.location + 1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy];

        // Clean value, by trimming enclosing quotes / double quotes, cleaning potential &quot; entities
        [attributeValue replaceCharactersInRange:NSMakeRange(attributeValue.length - 1, 1) withString:@""];
        [attributeValue replaceCharactersInRange:NSMakeRange(0, 1)                         withString:@""];
        [attributeValue replaceOccurrencesOfString:@"&quot;" withString:@"\"" options:0 range:NSMakeRange(0, attributeValue.length)];

        // Clean pontential html entities in string
        [dicAttributes setObject:attributeValue
                          forKey:attributeKey];
    }

    return dicAttributes;
}

#pragma mark - Tag content managements
- (NSAttributedString *)computePrefixString:(NSAttributedString *)resultString
{
    GONMarkup *currentMarker = [_markupsStack lastObject];
    if (currentMarker && ![currentMarker isKindOfClass:[NSNull class]])
    {
        return [currentMarker prefixStringForContext:_currentContext
                                          attributes:[self attributesForCurrentTag]
                                    stringAttributes:[self currentConfiguration]
                                        resultString:resultString];

    }

    return [[NSAttributedString alloc] initWithString:@""];
}

- (NSAttributedString *)computeSuffixString:(NSAttributedString *)resultString
{
    GONMarkup *currentMarker = [_markupsStack lastObject];
    if (currentMarker && ![currentMarker isKindOfClass:[NSNull class]])
    {
        return [currentMarker suffixStringForContext:_currentContext
                                          attributes:[self attributesForCurrentTag]
                                    stringAttributes:[self currentConfiguration]
                                        resultString:resultString];

    }

    return [[NSAttributedString alloc] initWithString:@"" attributes:[self currentConfiguration]];
}

- (NSAttributedString *)computeFinalExtractedString:(NSString *)inputString
                                       resultString:(NSAttributedString *)resultString
{
    GONMarkup *currentMarker = [_markupsStack lastObject];
    if (currentMarker && ![currentMarker isKindOfClass:[NSNull class]])
    {
        return [currentMarker updatedContentString:inputString
                                           context:_currentContext
                                        attributes:[self attributesForCurrentTag]
                                  stringAttributes:[self currentConfiguration]
                                      resultString:resultString];
    }

    return [[NSAttributedString alloc] initWithString:inputString attributes:[self currentConfiguration]];
}

#pragma mark - Tag managements
- (BOOL)handleClosingTag:(NSString *)tag
            resultString:(NSAttributedString *)resultString
                   error:(NSError **)error
{
    // Hold error status
    BOOL errorGenerated = NO;

    // Look for full style closing tag, @"//"
    // Checking only for one /, because first one was trimmed
    if ([tag rangeOfString:@"/"].location == 0)
    {
        if (!_configurationsStack.count)
        {
            LOG_IF_DEBUG(GONMarkupParserLogLevelUnbalancedTags, @"Trying to close all tags, but stack is empty");
            errorGenerated = [self generateError:error tag:tag];
        }
        else
        {
            GONMarkup *markup;
            NSMutableDictionary *currentTagConfiguration;
            for (NSInteger i=_markupsStack.count - 1; i>=0; i--)
            {
                markup = [_markupsStack objectAtIndex:i];
                currentTagConfiguration = [_configurationsStack objectAtIndex:i];

                // If we are closing an unknown tag, skip it
                if (![markup isKindOfClass:[NSNull class]])
                {
                    [markup closingMarkupFound:tag
                                 configuration:currentTagConfiguration
                                       context:_currentContext
                                    attributes:([_markupAttributesStack objectAtIndex:i] == [NSNull null] ? nil : [_markupAttributesStack objectAtIndex:i])
                                  resultString:resultString];
                }
                else
                {
                    LOG_IF_DEBUG(GONMarkupParserLogLevelUnknownTag, @"Closing unkown found tag <%@>", tag);
                    errorGenerated = [self generateError:error tag:tag];
                }
            }

            [_configurationsStack removeAllObjects];
            [_markupsStack removeAllObjects];
            [_currentContext removeAllObjects];
            [_markupAttributesStack removeAllObjects];

            LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Closing all tags\nStack : %@\n", _configurationsStack);
        }
    }
    else
    {
        // Check if available tags
        if (!_configurationsStack.count)
        {
            // Closing a tag, but tags stack is empty
            LOG_IF_DEBUG(GONMarkupParserLogLevelUnbalancedTags, @"Trying to close last tag, but stack is empty");
            errorGenerated = [self generateError:error tag:tag];
        }
        else
        {
            
            // Extract current markup
            GONMarkup *markup = [_markupsStack lastObject];

            // Present error when closing an unkwnow markup
            if (markup && ![markup isKindOfClass:[NSNull class]])
            {
                // Check that closing that is matching opening one
                if (tag.length)
                {
                    if (![tag isEqualToString:markup.tag])
                    {
                        LOG_IF_DEBUG(GONMarkupParserLogLevelUnbalancedTags, @"Closing tag found <%@>, is not matching currently opened one <%@>", tag, markup.tag);
                        errorGenerated = [self generateError:error tag:tag];
                    }
                }

                [markup closingMarkupFound:tag
                             configuration:[_configurationsStack lastObject]
                                   context:_currentContext
                                attributes:[self attributesForCurrentTag]
                              resultString:resultString];
            }

            // Remove last tag objet
            [_configurationsStack removeLastObject];
            [_markupsStack removeLastObject];
            [_markupAttributesStack removeLastObject];

            LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Closing tag (%@)\nStack : %@\n", tag, _configurationsStack);
        }
    }

    return errorGenerated;
}

- (BOOL)handleOpeningTag:(NSString *)tag
            resultString:(NSAttributedString *)resultString
                   error:(NSError **)error
{
    // Hold error status
    BOOL errorGenerated = NO;

    // Prepare tag configuration
    NSMutableDictionary *currentTagConfiguration = [self mutableCurrentConfiguration];

    // Retrieve markup associated to tag
    GONMarkup *markup = [self markupForTag:tag];

    // Ensure a markup was found
    if (!markup)
    {
        LOG_IF_DEBUG(GONMarkupParserLogLevelUnknownTag, @"No markup found for tag <%@>\n", tag);
        errorGenerated = [self generateError:error
                                         tag:tag];

        [_markupsStack addObject:[NSNull null]];
    }
    else
    {
        [markup openingMarkupFound:tag
                     configuration:currentTagConfiguration
                           context:_currentContext
                        attributes:[self attributesForCurrentTag]
                      resultString:resultString];

        [_markupsStack addObject:markup];
    }

    // Hold configuration
    [_configurationsStack addObject:currentTagConfiguration];

    LOG_IF_DEBUG(GONMarkupParserLogLevelWorkflow, @"Opening tag (%@)\nStack : %@\n", tag, _configurationsStack);

    return errorGenerated;
}

- (NSDictionary *)currentConfiguration
{
    // Extract configuration on top of stack
    if (!_configurationsStack.count)
        return _defaultConfiguration;

    return [_configurationsStack lastObject];
}

- (NSMutableDictionary *)mutableCurrentConfiguration
{
    NSMutableDictionary *mutableConfiguration = [[self currentConfiguration] mutableCopy];

    // Force paragraph style mutability
    NSParagraphStyle *paragraphStyle = [mutableConfiguration objectForKey:NSParagraphStyleAttributeName];
    if (paragraphStyle)
    {
        [mutableConfiguration setObject:[paragraphStyle mutableCopy]
                                 forKey:NSParagraphStyleAttributeName];
    }

    return mutableConfiguration;
}

#pragma mark - Fonts management
- (void)registerFont:(UIFont *)font forKey:(NSString *)key
{
    [_dicRegisteredFonts setObject:font
                            forKey:key];
}

- (UIFont *)fontForKey:(NSString *)key
{
    return [_dicRegisteredFonts objectForKey:key];
}

- (void)unregisterFontForKey:(NSString *)key
{
    [_dicRegisteredFonts removeObjectForKey:key];
}

#pragma mark - Error handling
- (BOOL)generateError:(NSError **)error tag:(NSString *)tag
{
    // Assert only is requested
    if (_assertOnError)
        NSAssert1(NO, @"An error was generated parsing following text, found at markup <%@>", tag);

    if (error)
    {
        // Initialize user info
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:@"Input string is malformed. Output attributed string may not be displayed correctly"
                                                                           forKey:NSLocalizedDescriptionKey];

        // Add tag if avalaible
        if (tag)
        {
            [userInfo setObject:tag
                         forKey:GONMarkupParser_incorrectClosingTag_KEY];
        }

        // Build error
        *error = [NSError errorWithDomain:GONMarkupParser_ERROR_DOMAIN
                                     code:GONMarkupParser_StringMalformed_ERROR_CODE
                                 userInfo:userInfo];
        
        return YES;
    }

    return NO;
}

#pragma mark - Getters
- (NSArray *)markups
{
    return [[_dicCurrentMarkup allValues] copy];
}

- (NSDictionary *)registeredFonts
{
    return [_dicRegisteredFonts copy];
}

@end


================================================
FILE: Classes/GONMarkupParserManager.h
================================================
//
//  GONMarkupParserManager.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/07/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  This class helps you to manage shared parsers
//  It also provides a default shared parser for your application

#import "GONMarkupParser.h"

@interface GONMarkupParserManager : NSObject
// Shared parsers management
/* Return shared parser instance.
 * Shared parser is preconfigured to handle all default tags
 */
+ (GONMarkupParser *)sharedParser;

/* Retrieve a parser registered under given key
 * Return nil if not found
 */
+ (GONMarkupParser *)registeredMarkupParserForKey:(NSString *)key;

/* Register given parser under key
 * Use this method to be able to share a parser
 */
+ (void)registerMarkupParser:(GONMarkupParser *)parser forKey:(NSString *)key;

/* Unregister parser under given key */
+ (void)unregisterMarkupParserForKey:(NSString *)key;

@end


================================================
FILE: Classes/GONMarkupParserManager.m
================================================
//
//  GONMarkupParserManager.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/07/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupParserManager.h"
#import "GONMarkupDefaultMarkups.h"

@interface GONMarkupParserManager ()
// Data
@property (nonatomic, strong) NSMutableDictionary *registeredParsers;
@end

@implementation GONMarkupParserManager
#pragma mark - Shared manager
+ (instancetype)manager
{
    static GONMarkupParserManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

- (id)init
{
    if (self = [super init])
    {
        _registeredParsers = [[NSMutableDictionary alloc] init];
    }

    return self;
}

#pragma mark - Shared instance
+ (GONMarkupParser *)sharedParser
{
    static GONMarkupParser *sharedParser = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedParser = [GONMarkupParser defaultMarkupParser];
    });

    return sharedParser;
}

+ (GONMarkupParser *)registeredMarkupParserForKey:(NSString *)key
{
    return [[[self manager] registeredParsers] objectForKey:key];
}

+ (void)registerMarkupParser:(GONMarkupParser *)parser forKey:(NSString *)key
{
    [[[self manager] registeredParsers] setObject:parser
                                           forKey:key];
}

+ (void)unregisterMarkupParserForKey:(NSString *)key
{
    [[[self manager] registeredParsers] removeObjectForKey:key];
}

@end


================================================
FILE: Classes/GONMarkupParserUtils.h
================================================
//
//  GONMarkupParserUtils.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/08/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Utils
//  Why not using some categories Sir ? Because I'm pretty sure everyone already have a cleanHTMLEntities method on their strings,
//  and I don't want to conflict with existing methods, nor adding a pod dependency that will add tons of new methods
@class GONMarkupParser;

@interface GONMarkupParserUtils : NSObject
/* Clean HTML entities from string */
+ (void)cleanHTMLEntitiesFromString:(NSMutableString *)inputString;

/* Helper method to generate an attributed string from a parser, but allowing to set default text color, text alignment and font 
 * if they are not set in parser default configuration.
 * This mthod will update parser default configuration, generate string, then revert configuration back to previous state
 * Used in UILAbel+GONMarkupParser and UITextField+GONMarkupParser categories to prevent duplicated code
 * If parser is nil, [GONMarkupParserManager sharedParser] will be used
 */
+ (NSAttributedString *)attributedString:(GONMarkupParser *)parser
                              withString:(NSString *)inputString
                             defautColor:(UIColor *)defaultColor
                             defaultFont:(UIFont *)defaultFont
                        defaultAlignment:(NSTextAlignment)defaultAlignment;
@end


================================================
FILE: Classes/GONMarkupParserUtils.m
================================================
//
//  GONMarkupParserUtils.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/08/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  http://www.w3schools.com/charsets/ref_html_entities_4.asp

#import "GONMarkupParserUtils.h"
#import "GONMarkupParserManager.h"

#define HTML_ENTITY_REGEX               @"&#?[a-zA-Z0-9]+;"
#define HTML_ENTITY_256_PREFIX_SEARCH   @"&#0"
#define HTML_ENTITY_256_PREFIX_REPLACE  @"&#"
#define HTML_ENTITY_256_LENGTH          6

@implementation GONMarkupParserUtils
#pragma mark - Utils
+ (void)cleanHTMLEntitiesFromString:(NSMutableString *)inputString
{
    static NSRegularExpression *regex = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        regex = [NSRegularExpression regularExpressionWithPattern:HTML_ENTITY_REGEX
                                                          options:0
                                                            error:nil];
    });

    NSRange range                = NSMakeRange(0, inputString.length);
    NSTextCheckingResult *result = nil;
    NSString *entity             = nil;
    NSString * match             = nil;
    while ((result = [regex firstMatchInString:inputString options:0 range:range]) != nil) {

        // Check if entity is known
        match  = [inputString substringWithRange:result.range];
        entity = [dicEntities objectForKey:match];

        // If no entity found, try with alternate synthax
        if (!entity)
        {
            // Check only if
            if (match.length == HTML_ENTITY_256_LENGTH && [match rangeOfString:HTML_ENTITY_256_PREFIX_SEARCH].location == 0)
            {
                match = [match stringByReplacingOccurrencesOfString:HTML_ENTITY_256_PREFIX_SEARCH withString:HTML_ENTITY_256_PREFIX_REPLACE];

                // Look again for entity
                entity = [dicEntities objectForKey:match];
            }
        }

        if (entity)
            [inputString replaceCharactersInRange:result.range withString:entity];

        // Update range
        range = NSMakeRange(result.range.location + 1, inputString.length - result.range.location - 1);

        // Break if reaching end of string
        if (range.location + range.length > inputString.length)
            break;
    };
}

+ (NSAttributedString *)attributedString:(GONMarkupParser *)parser
                              withString:(NSString *)inputString
                             defautColor:(UIColor *)defaultColor
                             defaultFont:(UIFont *)defaultFont
                        defaultAlignment:(NSTextAlignment)defaultAlignment
{
    GONMarkupParser *selectedParser = parser;
    if (!selectedParser)
        selectedParser = [GONMarkupParserManager sharedParser];
    
    // Hold initial default configuration
    NSDictionary *defaultConfiguration = [selectedParser.defaultConfiguration copy];
    
    // Check if parser has default configuration for color / font / alignment. If not, use default configuration
    // Text color
    if (![selectedParser.defaultConfiguration objectForKey:NSForegroundColorAttributeName])
    {
        [selectedParser.defaultConfiguration setObject:(defaultColor ? defaultColor : [UIColor blackColor])
                                                forKey:NSForegroundColorAttributeName];
    }
    
    // Font
    if (![selectedParser.defaultConfiguration objectForKey:NSFontAttributeName] && defaultFont)
    {
        [selectedParser.defaultConfiguration setObject:defaultFont
                                                forKey:NSFontAttributeName];
    }
    
    // Alignment
    if (![selectedParser.defaultConfiguration objectForKey:NSParagraphStyleAttributeName])
    {
        NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
        paragraphStyle.alignment = defaultAlignment;
        [selectedParser.defaultConfiguration setObject:paragraphStyle
                                                forKey:NSParagraphStyleAttributeName];
    }
    
    // Compute attributed string
    NSAttributedString *attributedString = [selectedParser attributedStringFromString:inputString
                                                                                error:nil];
    
    // Reset default configuration
    [selectedParser.defaultConfiguration removeAllObjects];
    [selectedParser.defaultConfiguration addEntriesFromDictionary:defaultConfiguration];
    
    
    return attributedString;
}

#pragma mark - Config
static NSDictionary *dicEntities;
+ (void)initialize
{
    [super initialize];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        dicEntities = @{
                        @"&quot;" : @"\"",
                        @"&amp;" : @"&",
                        @"&apos;" : @"'",
                        @"&lt;" : @"<",
                        @"&gt;" : @">",
                        @"&nbsp;" : @"\u00A0",
                        @"&iexcl;" : @"\u00A1",
                        @"&cent;" : @"\u00A2",
                        @"&pound;" : @"\u00A3",
                        @"&curren;" : @"\u00A4",
                        @"&yen;" : @"\u00A5",
                        @"&brvbar;" : @"\u00A6",
                        @"&sect;" : @"\u00A7",
                        @"&uml;" : @"\u00A8",
                        @"&copy;" : @"\u00A9",
                        @"&ordf;" : @"\u00AA",
                        @"&laquo;" : @"\u00AB",
                        @"&not;" : @"\u00AC",
                        @"&shy;" : @"\u00AD",
                        @"&reg;" : @"\u00AE",
                        @"&macr;" : @"\u00AF",
                        @"&deg;" : @"\u00B0",
                        @"&plusmn;" : @"\u00B1",
                        @"&sup2;" : @"\u00B2",
                        @"&sup3;" : @"\u00B3",
                        @"&acute;" : @"\u00B4",
                        @"&micro;" : @"\u00B5",
                        @"&para;" : @"\u00B6",
                        @"&middot;" : @"\u00B7",
                        @"&cedil;" : @"\u00B8",
                        @"&sup1;" : @"\u00B9",
                        @"&ordm;" : @"\u00BA",
                        @"&raquo;" : @"\u00BB",
                        @"&frac14;" : @"\u00BC",
                        @"&frac12;" : @"\u00BD",
                        @"&frac34;" : @"\u00BE",
                        @"&iquest;" : @"\u00BF",
                        @"&Agrave;" : @"\u00C0",
                        @"&Aacute;" : @"\u00C1",
                        @"&Acirc;" : @"\u00C2",
                        @"&Atilde;" : @"\u00C3",
                        @"&Auml;" : @"\u00C4",
                        @"&Aring;" : @"\u00C5",
                        @"&AElig;" : @"\u00C6",
                        @"&Ccedil;" : @"\u00C7",
                        @"&Egrave;" : @"\u00C8",
                        @"&Eacute;" : @"\u00C9",
                        @"&Ecirc;" : @"\u00CA",
                        @"&Euml;" : @"\u00CB",
                        @"&Igrave;" : @"\u00CC",
                        @"&Iacute;" : @"\u00CD",
                        @"&Icirc;" : @"\u00CE",
                        @"&Iuml;" : @"\u00CF",
                        @"&ETH;" : @"\u00D0",
                        @"&Ntilde;" : @"\u00D1",
                        @"&Ograve;" : @"\u00D2",
                        @"&Oacute;" : @"\u00D3",
                        @"&Ocirc;" : @"\u00D4",
                        @"&Otilde;" : @"\u00D5",
                        @"&Ouml;" : @"\u00D6",
                        @"&times;" : @"\u00D7",
                        @"&Oslash;" : @"\u00D8",
                        @"&Ugrave;" : @"\u00D9",
                        @"&Uacute;" : @"\u00DA",
                        @"&Ucirc;" : @"\u00DB",
                        @"&Uuml;" : @"\u00DC",
                        @"&Yacute;" : @"\u00DD",
                        @"&THORN;" : @"\u00DE",
                        @"&szlig;" : @"\u00DF",
                        @"&agrave;" : @"\u00E0",
                        @"&aacute;" : @"\u00E1",
                        @"&acirc;" : @"\u00E2",
                        @"&atilde;" : @"\u00E3",
                        @"&auml;" : @"\u00E4",
                        @"&aring;" : @"\u00E5",
                        @"&aelig;" : @"\u00E6",
                        @"&ccedil;" : @"\u00E7",
                        @"&egrave;" : @"\u00E8",
                        @"&eacute;" : @"\u00E9",
                        @"&ecirc;" : @"\u00EA",
                        @"&euml;" : @"\u00EB",
                        @"&igrave;" : @"\u00EC",
                        @"&iacute;" : @"\u00ED",
                        @"&icirc;" : @"\u00EE",
                        @"&iuml;" : @"\u00EF",
                        @"&eth;" : @"\u00F0",
                        @"&ntilde;" : @"\u00F1",
                        @"&ograve;" : @"\u00F2",
                        @"&oacute;" : @"\u00F3",
                        @"&ocirc;" : @"\u00F4",
                        @"&otilde;" : @"\u00F5",
                        @"&ouml;" : @"\u00F6",
                        @"&divide;" : @"\u00F7",
                        @"&oslash;" : @"\u00F8",
                        @"&ugrave;" : @"\u00F9",
                        @"&uacute;" : @"\u00FA",
                        @"&ucirc;" : @"\u00FB",
                        @"&uuml;" : @"\u00FC",
                        @"&yacute;" : @"\u00FD",
                        @"&thorn;" : @"\u00FE",
                        @"&yuml;" : @"\u00FF",
                        @"&OElig;" : @"\u0152",
                        @"&oelig;" : @"\u0153",
                        @"&Scaron;" : @"\u0160",
                        @"&scaron;" : @"\u0161",
                        @"&Yuml;" : @"\u0178",
                        @"&fnof;" : @"\u0192",
                        @"&circ;" : @"\u02C6",
                        @"&tilde;" : @"\u02DC",
                        @"&Alpha;" : @"\u0391",
                        @"&Beta;" : @"\u0392",
                        @"&Gamma;" : @"\u0393",
                        @"&Delta;" : @"\u0394",
                        @"&Epsilon;" : @"\u0395",
                        @"&Zeta;" : @"\u0396",
                        @"&Eta;" : @"\u0397",
                        @"&Theta;" : @"\u0398",
                        @"&Iota;" : @"\u0399",
                        @"&Kappa;" : @"\u039A",
                        @"&Lambda;" : @"\u039B",
                        @"&Mu;" : @"\u039C",
                        @"&Nu;" : @"\u039D",
                        @"&Xi;" : @"\u039E",
                        @"&Omicron;" : @"\u039F",
                        @"&Pi;" : @"\u03A0",
                        @"&Rho;" : @"\u03A1",
                        @"&Sigma;" : @"\u03A3",
                        @"&Tau;" : @"\u03A4",
                        @"&Upsilon;" : @"\u03A5",
                        @"&Phi;" : @"\u03A6",
                        @"&Chi;" : @"\u03A7",
                        @"&Psi;" : @"\u03A8",
                        @"&Omega;" : @"\u03A9",
                        @"&alpha;" : @"\u03B1",
                        @"&beta;" : @"\u03B2",
                        @"&gamma;" : @"\u03B3",
                        @"&delta;" : @"\u03B4",
                        @"&epsilon;" : @"\u03B5",
                        @"&zeta;" : @"\u03B6",
                        @"&eta;" : @"\u03B7",
                        @"&theta;" : @"\u03B8",
                        @"&iota;" : @"\u03B9",
                        @"&kappa;" : @"\u03BA",
                        @"&lambda;" : @"\u03BB",
                        @"&mu;" : @"\u03BC",
                        @"&nu;" : @"\u03BD",
                        @"&xi;" : @"\u03BE",
                        @"&omicron;" : @"\u03BF",
                        @"&pi;" : @"\u03C0",
                        @"&rho;" : @"\u03C1",
                        @"&sigmaf;" : @"\u03C2",
                        @"&sigma;" : @"\u03C3",
                        @"&tau;" : @"\u03C4",
                        @"&upsilon;" : @"\u03C5",
                        @"&phi;" : @"\u03C6",
                        @"&chi;" : @"\u03C7",
                        @"&psi;" : @"\u03C8",
                        @"&omega;" : @"\u03C9",
                        @"&thetasym;" : @"\u03D1",
                        @"&upsih;" : @"\u03D2",
                        @"&piv;" : @"\u03D6",
                        @"&ensp;" : @"\u2002",
                        @"&emsp;" : @"\u2003",
                        @"&thinsp;" : @"\u2009",
                        @"&zwnj;" : @"\u200C",
                        @"&zwj;" : @"\u200D",
                        @"&lrm;" : @"\u200E",
                        @"&rlm;" : @"\u200F",
                        @"&ndash;" : @"\u2013",
                        @"&mdash;" : @"\u2014",
                        @"&lsquo;" : @"\u2018",
                        @"&rsquo;" : @"\u2019",
                        @"&sbquo;" : @"\u201A",
                        @"&ldquo;" : @"\u201C",
                        @"&rdquo;" : @"\u201D",
                        @"&bdquo;" : @"\u201E",
                        @"&dagger;" : @"\u2020",
                        @"&Dagger;" : @"\u2021",
                        @"&bull;" : @"\u2022",
                        @"&hellip;" : @"\u2026",
                        @"&permil;" : @"\u2030",
                        @"&prime;" : @"\u2032",
                        @"&Prime;" : @"\u2033",
                        @"&lsaquo;" : @"\u2039",
                        @"&rsaquo;" : @"\u203A",
                        @"&oline;" : @"\u203E",
                        @"&frasl;" : @"\u2044",
                        @"&euro;" : @"\u20AC",
                        @"&image;" : @"\u2111",
                        @"&weierp;" : @"\u2118",
                        @"&real;" : @"\u211C",
                        @"&trade;" : @"\u2122",
                        @"&alefsym;" : @"\u2135",
                        @"&larr;" : @"\u2190",
                        @"&uarr;" : @"\u2191",
                        @"&rarr;" : @"\u2192",
                        @"&darr;" : @"\u2193",
                        @"&harr;" : @"\u2194",
                        @"&crarr;" : @"\u21B5",
                        @"&lArr;" : @"\u21D0",
                        @"&uArr;" : @"\u21D1",
                        @"&rArr;" : @"\u21D2",
                        @"&dArr;" : @"\u21D3",
                        @"&hArr;" : @"\u21D4",
                        @"&forall;" : @"\u2200",
                        @"&part;" : @"\u2202",
                        @"&exist;" : @"\u2203",
                        @"&empty;" : @"\u2205",
                        @"&nabla;" : @"\u2207",
                        @"&isin;" : @"\u2208",
                        @"&notin;" : @"\u2209",
                        @"&ni;" : @"\u220B",
                        @"&prod;" : @"\u220F",
                        @"&sum;" : @"\u2211",
                        @"&minus;" : @"\u2212",
                        @"&lowast;" : @"\u2217",
                        @"&radic;" : @"\u221A",
                        @"&prop;" : @"\u221D",
                        @"&infin;" : @"\u221E",
                        @"&ang;" : @"\u2220",
                        @"&and;" : @"\u2227",
                        @"&or;" : @"\u2228",
                        @"&cap;" : @"\u2229",
                        @"&cup;" : @"\u222A",
                        @"&int;" : @"\u222B",
                        @"&there4;" : @"\u2234",
                        @"&sim;" : @"\u223C",
                        @"&cong;" : @"\u2245",
                        @"&asymp;" : @"\u2248",
                        @"&ne;" : @"\u2260",
                        @"&equiv;" : @"\u2261",
                        @"&le;" : @"\u2264",
                        @"&ge;" : @"\u2265",
                        @"&sub;" : @"\u2282",
                        @"&sup;" : @"\u2283",
                        @"&nsub;" : @"\u2284",
                        @"&sube;" : @"\u2286",
                        @"&supe;" : @"\u2287",
                        @"&oplus;" : @"\u2295",
                        @"&otimes;" : @"\u2297",
                        @"&perp;" : @"\u22A5",
                        @"&sdot;" : @"\u22C5",
                        @"&vellip;" : @"\u22EE",
                        @"&lceil;" : @"\u2308",
                        @"&rceil;" : @"\u2309",
                        @"&lfloor;" : @"\u230A",
                        @"&rfloor;" : @"\u230B",
                        @"&lang;" : @"\u2329",
                        @"&rang;" : @"\u232A",
                        @"&loz;" : @"\u25CA",
                        @"&spades;" : @"\u2660",
                        @"&clubs;" : @"\u2663",
                        @"&hearts;" : @"\u2665",
                        @"&diams;" : @"\u2666",
                        @"&#32;" : @" ",
                        @"&#33;" : @"!",
                        @"&#34;" : @"\"",
                        @"&#35;" : @"#",
                        @"&#36;" : @"$",
                        @"&#37;" : @"%",
                        @"&#38;" : @"&",
                        @"&#39;" : @"'",
                        @"&#40;" : @"(",
                        @"&#41;" : @")",
                        @"&#42;" : @"*",
                        @"&#43;" : @"+",
                        @"&#44;" : @",",
                        @"&#45;" : @"-",
                        @"&#46;" : @".",
                        @"&#47;" : @"/",
                        @"&#48;" : @"0",
                        @"&#49;" : @"1",
                        @"&#50;" : @"2",
                        @"&#51;" : @"3",
                        @"&#52;" : @"4",
                        @"&#53;" : @"5",
                        @"&#54;" : @"6",
                        @"&#55;" : @"7",
                        @"&#56;" : @"8",
                        @"&#57;" : @"9",
                        @"&#58;" : @":",
                        @"&#59;" : @";",
                        @"&#60;" : @"<",
                        @"&#61;" : @"=",
                        @"&#62;" : @">",
                        @"&#63;" : @"?",
                        @"&#64;" : @"@",
                        @"&#65;" : @"A",
                        @"&#66;" : @"B",
                        @"&#67;" : @"C",
                        @"&#68;" : @"D",
                        @"&#69;" : @"E",
                        @"&#70;" : @"F",
                        @"&#71;" : @"G",
                        @"&#72;" : @"H",
                        @"&#73;" : @"I",
                        @"&#74;" : @"J",
                        @"&#75;" : @"K",
                        @"&#76;" : @"L",
                        @"&#77;" : @"M",
                        @"&#78;" : @"N",
                        @"&#79;" : @"O",
                        @"&#80;" : @"P",
                        @"&#81;" : @"Q",
                        @"&#82;" : @"R",
                        @"&#83;" : @"S",
                        @"&#84;" : @"T",
                        @"&#85;" : @"U",
                        @"&#86;" : @"V",
                        @"&#87;" : @"W",
                        @"&#88;" : @"X",
                        @"&#89;" : @"Y",
                        @"&#90;" : @"Z",
                        @"&#91;" : @"[",
                        @"&#92;" : @"\\",
                        @"&#93;" : @"]",
                        @"&#94;" : @"^",
                        @"&#95;" : @"_",
                        @"&#96;" : @"`",
                        @"&#97;" : @"a",
                        @"&#98;" : @"b",
                        @"&#99;" : @"c",
                        @"&#100;" : @"d",
                        @"&#101;" : @"e",
                        @"&#102;" : @"f",
                        @"&#103;" : @"g",
                        @"&#104;" : @"h",
                        @"&#105;" : @"i",
                        @"&#106;" : @"j",
                        @"&#107;" : @"k",
                        @"&#108;" : @"l",
                        @"&#109;" : @"m",
                        @"&#110;" : @"n",
                        @"&#111;" : @"o",
                        @"&#112;" : @"p",
                        @"&#113;" : @"q",
                        @"&#114;" : @"r",
                        @"&#115;" : @"s",
                        @"&#116;" : @"t",
                        @"&#117;" : @"u",
                        @"&#118;" : @"v",
                        @"&#119;" : @"w",
                        @"&#120;" : @"x",
                        @"&#121;" : @"y",
                        @"&#122;" : @"z",
                        @"&#123;" : @"{",
                        @"&#124;" : @"|",
                        @"&#125;" : @"}",
                        @"&#126;" : @"~",
                        @"&#127;" : @"\u0127",
                        @"&#128;" : @"\u0128",
                        @"&#129;" : @"\u0129",
                        @"&#130;" : @"\u0130",
                        @"&#131;" : @"\u0131",
                        @"&#132;" : @"\u0132",
                        @"&#133;" : @"\u0133",
                        @"&#134;" : @"\u0134",
                        @"&#135;" : @"\u0135",
                        @"&#136;" : @"\u0136",
                        @"&#137;" : @"\u0137",
                        @"&#138;" : @"\u0138",
                        @"&#139;" : @"\u0139",
                        @"&#140;" : @"\u0140",
                        @"&#141;" : @"\u0141",
                        @"&#142;" : @"\u0142",
                        @"&#143;" : @"\u0143",
                        @"&#144;" : @"\u0144",
                        @"&#145;" : @"\u0145",
                        @"&#146;" : @"\u0146",
                        @"&#147;" : @"\u0147",
                        @"&#148;" : @"\u0148",
                        @"&#149;" : @"\u0149",
                        @"&#150;" : @"\u0150",
                        @"&#151;" : @"\u0151",
                        @"&#152;" : @"\u0152",
                        @"&#153;" : @"\u0153",
                        @"&#154;" : @"\u0154",
                        @"&#155;" : @"\u0155",
                        @"&#156;" : @"\u0156",
                        @"&#157;" : @"\u0157",
                        @"&#158;" : @"\u0158",
                        @"&#159;" : @"\u0159",
                        @"&#160;" : @"\u00A0",
                        @"&#161;" : @"\u00A1",
                        @"&#162;" : @"\u00A2",
                        @"&#163;" : @"\u00A3",
                        @"&#164;" : @"\u00A4",
                        @"&#165;" : @"\u00A5",
                        @"&#166;" : @"\u00A6",
                        @"&#167;" : @"\u00A7",
                        @"&#168;" : @"\u00A8",
                        @"&#169;" : @"\u00A9",
                        @"&#170;" : @"\u00AA",
                        @"&#171;" : @"\u00AB",
                        @"&#172;" : @"\u00AC",
                        @"&#173;" : @"\u00AD",
                        @"&#174;" : @"\u00AE",
                        @"&#175;" : @"\u00AF",
                        @"&#176;" : @"\u00B0",
                        @"&#177;" : @"\u00B1",
                        @"&#178;" : @"\u00B2",
                        @"&#179;" : @"\u00B3",
                        @"&#180;" : @"\u00B4",
                        @"&#181;" : @"\u00B5",
                        @"&#182;" : @"\u00B6",
                        @"&#183;" : @"\u00B7",
                        @"&#184;" : @"\u00B8",
                        @"&#185;" : @"\u00B9",
                        @"&#186;" : @"\u00BA",
                        @"&#187;" : @"\u00BB",
                        @"&#188;" : @"\u00BC",
                        @"&#189;" : @"\u00BD",
                        @"&#190;" : @"\u00BE",
                        @"&#191;" : @"\u00BF",
                        @"&#192;" : @"\u00C0",
                        @"&#193;" : @"\u00C1",
                        @"&#194;" : @"\u00C2",
                        @"&#195;" : @"\u00C3",
                        @"&#196;" : @"\u00C4",
                        @"&#197;" : @"\u00C5",
                        @"&#198;" : @"\u00C6",
                        @"&#199;" : @"\u00C7",
                        @"&#200;" : @"\u00C8",
                        @"&#201;" : @"\u00C9",
                        @"&#202;" : @"\u00CA",
                        @"&#203;" : @"\u00CB",
                        @"&#204;" : @"\u00CC",
                        @"&#205;" : @"\u00CD",
                        @"&#206;" : @"\u00CE",
                        @"&#207;" : @"\u00CF",
                        @"&#208;" : @"\u00D0",
                        @"&#209;" : @"\u00D1",
                        @"&#210;" : @"\u00D2",
                        @"&#211;" : @"\u00D3",
                        @"&#212;" : @"\u00D4",
                        @"&#213;" : @"\u00D5",
                        @"&#214;" : @"\u00D6",
                        @"&#215;" : @"\u00D7",
                        @"&#216;" : @"\u00D8",
                        @"&#217;" : @"\u00D9",
                        @"&#218;" : @"\u00DA",
                        @"&#219;" : @"\u00DB",
                        @"&#220;" : @"\u00DC",
                        @"&#221;" : @"\u00DD",
                        @"&#222;" : @"\u00DE",
                        @"&#223;" : @"\u00DF",
                        @"&#224;" : @"\u00E0",
                        @"&#225;" : @"\u00E1",
                        @"&#226;" : @"\u00E2",
                        @"&#227;" : @"\u00E3",
                        @"&#228;" : @"\u00E4",
                        @"&#229;" : @"\u00E5",
                        @"&#230;" : @"\u00E6",
                        @"&#231;" : @"\u00E7",
                        @"&#232;" : @"\u00E8",
                        @"&#233;" : @"\u00E9",
                        @"&#234;" : @"\u00EA",
                        @"&#235;" : @"\u00EB",
                        @"&#236;" : @"\u00EC",
                        @"&#237;" : @"\u00ED",
                        @"&#238;" : @"\u00EE",
                        @"&#239;" : @"\u00EF",
                        @"&#240;" : @"\u00F0",
                        @"&#241;" : @"\u00F1",
                        @"&#242;" : @"\u00F2",
                        @"&#243;" : @"\u00F3",
                        @"&#244;" : @"\u00F4",
                        @"&#245;" : @"\u00F5",
                        @"&#246;" : @"\u00F6",
                        @"&#247;" : @"\u00F7",
                        @"&#248;" : @"\u00F8",
                        @"&#249;" : @"\u00F9",
                        @"&#250;" : @"\u00FA",
                        @"&#251;" : @"\u00FB",
                        @"&#252;" : @"\u00FC",
                        @"&#253;" : @"\u00FD",
                        @"&#254;" : @"\u00FE",
                        @"&#255;" : @"\u00FF",
                        @"&#402;" : @"\u0192",
                        @"&#913;" : @"\u0391",
                        @"&#914;" : @"\u0392",
                        @"&#915;" : @"\u0393",
                        @"&#916;" : @"\u0394",
                        @"&#917;" : @"\u0395",
                        @"&#918;" : @"\u0396",
                        @"&#919;" : @"\u0397",
                        @"&#920;" : @"\u0398",
                        @"&#921;" : @"\u0399",
                        @"&#922;" : @"\u039A",
                        @"&#923;" : @"\u039B",
                        @"&#924;" : @"\u039C",
                        @"&#925;" : @"\u039D",
                        @"&#926;" : @"\u039E",
                        @"&#927;" : @"\u039F",
                        @"&#928;" : @"\u03A0",
                        @"&#929;" : @"\u03A1",
                        @"&#931;" : @"\u03A3",
                        @"&#932;" : @"\u03A4",
                        @"&#933;" : @"\u03A5",
                        @"&#934;" : @"\u03A6",
                        @"&#935;" : @"\u03A7",
                        @"&#936;" : @"\u03A8",
                        @"&#937;" : @"\u03A9",
                        @"&#945;" : @"\u03B1",
                        @"&#946;" : @"\u03B2",
                        @"&#947;" : @"\u03B3",
                        @"&#948;" : @"\u03B4",
                        @"&#949;" : @"\u03B5",
                        @"&#950;" : @"\u03B6",
                        @"&#951;" : @"\u03B7",
                        @"&#952;" : @"\u03B8",
                        @"&#953;" : @"\u03B9",
                        @"&#954;" : @"\u03BA",
                        @"&#955;" : @"\u03BB",
                        @"&#956;" : @"\u03BC",
                        @"&#957;" : @"\u03BD",
                        @"&#958;" : @"\u03BE",
                        @"&#959;" : @"\u03BF",
                        @"&#960;" : @"\u03C0",
                        @"&#961;" : @"\u03C1",
                        @"&#962;" : @"\u03C2",
                        @"&#963;" : @"\u03C3",
                        @"&#964;" : @"\u03C4",
                        @"&#965;" : @"\u03C5",
                        @"&#966;" : @"\u03C6",
                        @"&#967;" : @"\u03C7",
                        @"&#968;" : @"\u03C8",
                        @"&#969;" : @"\u03C9",
                        @"&#977;" : @"\u03D1",
                        @"&#978;" : @"\u03D2",
                        @"&#982;" : @"\u03D6",
                        @"&#8226;" : @"\u2022",
                        @"&#8230;" : @"\u2026",
                        @"&#8242;" : @"\u2032",
                        @"&#8243;" : @"\u2033",
                        @"&#8254;" : @"\u203E",
                        @"&#8260;" : @"\u2044",
                        @"&#8472;" : @"\u2118",
                        @"&#8465;" : @"\u2111",
                        @"&#8476;" : @"\u211C",
                        @"&#8482;" : @"\u2122",
                        @"&#8501;" : @"\u2135",
                        @"&#8592;" : @"\u2190",
                        @"&#8593;" : @"\u2191",
                        @"&#8594;" : @"\u2192",
                        @"&#8595;" : @"\u2193",
                        @"&#8596;" : @"\u2194",
                        @"&#8629;" : @"\u21B5",
                        @"&#8656;" : @"\u21D0",
                        @"&#8657;" : @"\u21D1",
                        @"&#8658;" : @"\u21D2",
                        @"&#8659;" : @"\u21D3",
                        @"&#8660;" : @"\u21D4",
                        @"&#8704;" : @"\u2200",
                        @"&#8706;" : @"\u2202",
                        @"&#8707;" : @"\u2203",
                        @"&#8709;" : @"\u2205",
                        @"&#8711;" : @"\u2207",
                        @"&#8712;" : @"\u2208",
                        @"&#8713;" : @"\u2209",
                        @"&#8715;" : @"\u220B",
                        @"&#8719;" : @"\u220F",
                        @"&#8721;" : @"\u2211",
                        @"&#8722;" : @"\u2212",
                        @"&#8727;" : @"\u2217",
                        @"&#8730;" : @"\u221A",
                        @"&#8733;" : @"\u221D",
                        @"&#8734;" : @"\u221E",
                        @"&#8736;" : @"\u2220",
                        @"&#8743;" : @"\u2227",
                        @"&#8744;" : @"\u2228",
                        @"&#8745;" : @"\u2229",
                        @"&#8746;" : @"\u222A",
                        @"&#8747;" : @"\u222B",
                        @"&#8756;" : @"\u2234",
                        @"&#8764;" : @"\u223C",
                        @"&#8773;" : @"\u2245",
                        @"&#8776;" : @"\u2248",
                        @"&#8800;" : @"\u2260",
                        @"&#8801;" : @"\u2261",
                        @"&#8804;" : @"\u2264",
                        @"&#8805;" : @"\u2265",
                        @"&#8834;" : @"\u2282",
                        @"&#8835;" : @"\u2283",
                        @"&#8836;" : @"\u2284",
                        @"&#8838;" : @"\u2286",
                        @"&#8839;" : @"\u2287",
                        @"&#8853;" : @"\u2295",
                        @"&#8855;" : @"\u2297",
                        @"&#8869;" : @"\u22A5",
                        @"&#8901;" : @"\u22C5",
                        @"&#8968;" : @"\u2308",
                        @"&#8969;" : @"\u2309",
                        @"&#8970;" : @"\u230A",
                        @"&#8971;" : @"\u230B",
                        @"&#9001;" : @"\u2329",
                        @"&#9002;" : @"\u232A",
                        @"&#9674;" : @"\u25CA",
                        @"&#9824;" : @"\u2660",
                        @"&#9827;" : @"\u2663",
                        @"&#9829;" : @"\u2665",
                        @"&#9830;" : @"\u2666",
                        @"&#x20;" : @" ",
                        @"&#x21;" : @"!",
                        @"&#x22;" : @"\"",
                        @"&#x23;" : @"#",
                        @"&#x24;" : @"$",
                        @"&#x25;" : @"%",
                        @"&#x26;" : @"&",
                        @"&#x27;" : @"'",
                        @"&#x28;" : @"(",
                        @"&#x29;" : @")",
                        @"&#x2A;" : @"*",
                        @"&#x2B;" : @"+",
                        @"&#x2C;" : @",",
                        @"&#x2D;" : @"-",
                        @"&#x2E;" : @".",
                        @"&#x2F;" : @"/",
                        @"&#x30;" : @"0",
                        @"&#x31;" : @"1",
                        @"&#x32;" : @"2",
                        @"&#x33;" : @"3",
                        @"&#x34;" : @"4",
                        @"&#x35;" : @"5",
                        @"&#x36;" : @"6",
                        @"&#x37;" : @"7",
                        @"&#x38;" : @"8",
                        @"&#x39;" : @"9",
                        @"&#x3A;" : @":",
                        @"&#x3B;" : @";",
                        @"&#x3C;" : @"<",
                        @"&#x3D;" : @"=",
                        @"&#x3E;" : @">",
                        @"&#x3F;" : @"?",
                        @"&#x40;" : @"@",
                        @"&#x41;" : @"A",
                        @"&#x42;" : @"B",
                        @"&#x43;" : @"C",
                        @"&#x44;" : @"D",
                        @"&#x45;" : @"E",
                        @"&#x46;" : @"F",
                        @"&#x47;" : @"G",
                        @"&#x48;" : @"H",
                        @"&#x49;" : @"I",
                        @"&#x4A;" : @"J",
                        @"&#x4B;" : @"K",
                        @"&#x4C;" : @"L",
                        @"&#x4D;" : @"M",
                        @"&#x4E;" : @"N",
                        @"&#x4F;" : @"O",
                        @"&#x50;" : @"P",
                        @"&#x51;" : @"Q",
                        @"&#x52;" : @"R",
                        @"&#x53;" : @"S",
                        @"&#x54;" : @"T",
                        @"&#x55;" : @"U",
                        @"&#x56;" : @"V",
                        @"&#x57;" : @"W",
                        @"&#x58;" : @"X",
                        @"&#x59;" : @"Y",
                        @"&#x5A;" : @"Z",
                        @"&#x5B;" : @"[",
                        @"&#x5C;" : @"\\",
                        @"&#x5D;" : @"]",
                        @"&#x5E;" : @"^",
                        @"&#x5F;" : @"_",
                        @"&#x60;" : @"`",
                        @"&#x61;" : @"a",
                        @"&#x62;" : @"b",
                        @"&#x63;" : @"c",
                        @"&#x64;" : @"d",
                        @"&#x65;" : @"e",
                        @"&#x66;" : @"f",
                        @"&#x67;" : @"g",
                        @"&#x68;" : @"h",
                        @"&#x69;" : @"i",
                        @"&#x6A;" : @"j",
                        @"&#x6B;" : @"k",
                        @"&#x6C;" : @"l",
                        @"&#x6D;" : @"m",
                        @"&#x6E;" : @"n",
                        @"&#x6F;" : @"o",
                        @"&#x70;" : @"p",
                        @"&#x71;" : @"q",
                        @"&#x72;" : @"r",
                        @"&#x73;" : @"s",
                        @"&#x74;" : @"t",
                        @"&#x75;" : @"u",
                        @"&#x76;" : @"v",
                        @"&#x77;" : @"w",
                        @"&#x78;" : @"x",
                        @"&#x79;" : @"y",
                        @"&#x7A;" : @"z",
                        @"&#x7B;" : @"{",
                        @"&#x7C;" : @"|",
                        @"&#x7D;" : @"}",
                        @"&#x7E;" : @"~",
                        @"&#x7F;" : @"\u0127",
                        @"&#x80;" : @"\u0128",
                        @"&#x81;" : @"\u0129",
                        @"&#x82;" : @"\u0130",
                        @"&#x83;" : @"\u0131",
                        @"&#x84;" : @"\u0132",
                        @"&#x85;" : @"\u0133",
                        @"&#x86;" : @"\u0134",
                        @"&#x87;" : @"\u0135",
                        @"&#x88;" : @"\u0136",
                        @"&#x89;" : @"\u0137",
                        @"&#x8A;" : @"\u0138",
                        @"&#x8B;" : @"\u0139",
                        @"&#x8C;" : @"\u0140",
                        @"&#x8D;" : @"\u0141",
                        @"&#x8E;" : @"\u0142",
                        @"&#x8F;" : @"\u0143",
                        @"&#x90;" : @"\u0144",
                        @"&#x91;" : @"\u0145",
                        @"&#x92;" : @"\u0146",
                        @"&#x93;" : @"\u0147",
                        @"&#x94;" : @"\u0148",
                        @"&#x95;" : @"\u0149",
                        @"&#x96;" : @"\u0150",
                        @"&#x97;" : @"\u0151",
                        @"&#x98;" : @"\u0152",
                        @"&#x99;" : @"\u0153",
                        @"&#x9A;" : @"\u0154",
                        @"&#x9B;" : @"\u0155",
                        @"&#x9C;" : @"\u0156",
                        @"&#x9D;" : @"\u0157",
                        @"&#x9E;" : @"\u0158",
                        @"&#x9F;" : @"\u0159",
                        @"&#xA0;" : @"\u00A0",
                        @"&#xA1;" : @"\u00A1",
                        @"&#xA2;" : @"\u00A2",
                        @"&#xA3;" : @"\u00A3",
                        @"&#xA4;" : @"\u00A4",
                        @"&#xA5;" : @"\u00A5",
                        @"&#xA6;" : @"\u00A6",
                        @"&#xA7;" : @"\u00A7",
                        @"&#xA8;" : @"\u00A8",
                        @"&#xA9;" : @"\u00A9",
                        @"&#xAA;" : @"\u00AA",
                        @"&#xAB;" : @"\u00AB",
                        @"&#xAC;" : @"\u00AC",
                        @"&#xAD;" : @"\u00AD",
                        @"&#xAE;" : @"\u00AE",
                        @"&#xAF;" : @"\u00AF",
                        @"&#xB0;" : @"\u00B0",
                        @"&#xB1;" : @"\u00B1",
                        @"&#xB2;" : @"\u00B2",
                        @"&#xB3;" : @"\u00B3",
                        @"&#xB4;" : @"\u00B4",
                        @"&#xB5;" : @"\u00B5",
                        @"&#xB6;" : @"\u00B6",
                        @"&#xB7;" : @"\u00B7",
                        @"&#xB8;" : @"\u00B8",
                        @"&#xB9;" : @"\u00B9",
                        @"&#xBA;" : @"\u00BA",
                        @"&#xBB;" : @"\u00BB",
                        @"&#xBC;" : @"\u00BC",
                        @"&#xBD;" : @"\u00BD",
                        @"&#xBE;" : @"\u00BE",
                        @"&#xBF;" : @"\u00BF",
                        @"&#xC0;" : @"\u00C0",
                        @"&#xC1;" : @"\u00C1",
                        @"&#xC2;" : @"\u00C2",
                        @"&#xC3;" : @"\u00C3",
                        @"&#xC4;" : @"\u00C4",
                        @"&#xC5;" : @"\u00C5",
                        @"&#xC6;" : @"\u00C6",
                        @"&#xC7;" : @"\u00C7",
                        @"&#xC8;" : @"\u00C8",
                        @"&#xC9;" : @"\u00C9",
                        @"&#xCA;" : @"\u00CA",
                        @"&#xCB;" : @"\u00CB",
                        @"&#xCC;" : @"\u00CC",
                        @"&#xCD;" : @"\u00CD",
                        @"&#xCE;" : @"\u00CE",
                        @"&#xCF;" : @"\u00CF",
                        @"&#xD0;" : @"\u00D0",
                        @"&#xD1;" : @"\u00D1",
                        @"&#xD2;" : @"\u00D2",
                        @"&#xD3;" : @"\u00D3",
                        @"&#xD4;" : @"\u00D4",
                        @"&#xD5;" : @"\u00D5",
                        @"&#xD6;" : @"\u00D6",
                        @"&#xD7;" : @"\u00D7",
                        @"&#xD8;" : @"\u00D8",
                        @"&#xD9;" : @"\u00D9",
                        @"&#xDA;" : @"\u00DA",
                        @"&#xDB;" : @"\u00DB",
                        @"&#xDC;" : @"\u00DC",
                        @"&#xDD;" : @"\u00DD",
                        @"&#xDE;" : @"\u00DE",
                        @"&#xDF;" : @"\u00DF",
                        @"&#xE0;" : @"\u00E0",
                        @"&#xE1;" : @"\u00E1",
                        @"&#xE2;" : @"\u00E2",
                        @"&#xE3;" : @"\u00E3",
                        @"&#xE4;" : @"\u00E4",
                        @"&#xE5;" : @"\u00E5",
                        @"&#xE6;" : @"\u00E6",
                        @"&#xE7;" : @"\u00E7",
                        @"&#xE8;" : @"\u00E8",
                        @"&#xE9;" : @"\u00E9",
                        @"&#xEA;" : @"\u00EA",
                        @"&#xEB;" : @"\u00EB",
                        @"&#xEC;" : @"\u00EC",
                        @"&#xED;" : @"\u00ED",
                        @"&#xEE;" : @"\u00EE",
                        @"&#xEF;" : @"\u00EF",
                        @"&#xF0;" : @"\u00F0",
                        @"&#xF1;" : @"\u00F1",
                        @"&#xF2;" : @"\u00F2",
                        @"&#xF3;" : @"\u00F3",
                        @"&#xF4;" : @"\u00F4",
                        @"&#xF5;" : @"\u00F5",
                        @"&#xF6;" : @"\u00F6",
                        @"&#xF7;" : @"\u00F7",
                        @"&#xF8;" : @"\u00F8",
                        @"&#xF9;" : @"\u00F9",
                        @"&#xFA;" : @"\u00FA",
                        @"&#xFB;" : @"\u00FB",
                        @"&#xFC;" : @"\u00FC",
                        @"&#xFD;" : @"\u00FD",
                        @"&#xFE;" : @"\u00FE",
                        @"&#xFF;" : @"\u00FF",
                        @"&#x192;" : @"\u0192",
                        @"&#x391;" : @"\u0391",
                        @"&#x392;" : @"\u0392",
                        @"&#x393;" : @"\u0393",
                        @"&#x394;" : @"\u0394",
                        @"&#x395;" : @"\u0395",
                        @"&#x396;" : @"\u0396",
                        @"&#x397;" : @"\u0397",
                        @"&#x398;" : @"\u0398",
                        @"&#x399;" : @"\u0399",
                        @"&#x39A;" : @"\u039A",
                        @"&#x39B;" : @"\u039B",
                        @"&#x39C;" : @"\u039C",
                        @"&#x39D;" : @"\u039D",
                        @"&#x39E;" : @"\u039E",
                        @"&#x39F;" : @"\u039F",
                        @"&#x3A0;" : @"\u03A0",
                        @"&#x3A1;" : @"\u03A1",
                        @"&#x3A3;" : @"\u03A3",
                        @"&#x3A4;" : @"\u03A4",
                        @"&#x3A5;" : @"\u03A5",
                        @"&#x3A6;" : @"\u03A6",
                        @"&#x3A7;" : @"\u03A7",
                        @"&#x3A8;" : @"\u03A8",
                        @"&#x3A9;" : @"\u03A9",
                        @"&#x3B1;" : @"\u03B1",
                        @"&#x3B2;" : @"\u03B2",
                        @"&#x3B3;" : @"\u03B3",
                        @"&#x3B4;" : @"\u03B4",
                        @"&#x3B5;" : @"\u03B5",
                        @"&#x3B6;" : @"\u03B6",
                        @"&#x3B7;" : @"\u03B7",
                        @"&#x3B8;" : @"\u03B8",
                        @"&#x3B9;" : @"\u03B9",
                        @"&#x3BA;" : @"\u03BA",
                        @"&#x3BB;" : @"\u03BB",
                        @"&#x3BC;" : @"\u03BC",
                        @"&#x3BD;" : @"\u03BD",
                        @"&#x3BE;" : @"\u03BE",
                        @"&#x3BF;" : @"\u03BF",
                        @"&#x3C0;" : @"\u03C0",
                        @"&#x3C1;" : @"\u03C1",
                        @"&#x3C2;" : @"\u03C2",
                        @"&#x3C3;" : @"\u03C3",
                        @"&#x3C4;" : @"\u03C4",
                        @"&#x3C5;" : @"\u03C5",
                        @"&#x3C6;" : @"\u03C6",
                        @"&#x3C7;" : @"\u03C7",
                        @"&#x3C8;" : @"\u03C8",
                        @"&#x3C9;" : @"\u03C9",
                        @"&#x3D1;" : @"\u03D1",
                        @"&#x3D2;" : @"\u03D2",
                        @"&#x3D6;" : @"\u03D6",
                        @"&#x2022;" : @"\u2022",
                        @"&#x2026;" : @"\u2026",
                        @"&#x2032;" : @"\u2032",
                        @"&#x2033;" : @"\u2033",
                        @"&#x203E;" : @"\u203E",
                        @"&#x2044;" : @"\u2044",
                        @"&#x2118;" : @"\u2118",
                        @"&#x2111;" : @"\u2111",
                        @"&#x211C;" : @"\u211C",
                        @"&#x2122;" : @"\u2122",
                        @"&#x2135;" : @"\u2135",
                        @"&#x2190;" : @"\u2190",
                        @"&#x2191;" : @"\u2191",
                        @"&#x2192;" : @"\u2192",
                        @"&#x2193;" : @"\u2193",
                        @"&#x2194;" : @"\u2194",
                        @"&#x21B5;" : @"\u21B5",
                        @"&#x21D0;" : @"\u21D0",
                        @"&#x21D1;" : @"\u21D1",
                        @"&#x21D2;" : @"\u21D2",
                        @"&#x21D3;" : @"\u21D3",
                        @"&#x21D4;" : @"\u21D4",
                        @"&#x2200;" : @"\u2200",
                        @"&#x2202;" : @"\u2202",
                        @"&#x2203;" : @"\u2203",
                        @"&#x2205;" : @"\u2205",
                        @"&#x2207;" : @"\u2207",
                        @"&#x2208;" : @"\u2208",
                        @"&#x2209;" : @"\u2209",
                        @"&#x220B;" : @"\u220B",
                        @"&#x220F;" : @"\u220F",
                        @"&#x2211;" : @"\u2211",
                        @"&#x2212;" : @"\u2212",
                        @"&#x2217;" : @"\u2217",
                        @"&#x221A;" : @"\u221A",
                        @"&#x221D;" : @"\u221D",
                        @"&#x221E;" : @"\u221E",
                        @"&#x2220;" : @"\u2220",
                        @"&#x2227;" : @"\u2227",
                        @"&#x2228;" : @"\u2228",
                        @"&#x2229;" : @"\u2229",
                        @"&#x222A;" : @"\u222A",
                        @"&#x222B;" : @"\u222B",
                        @"&#x2234;" : @"\u2234",
                        @"&#x223C;" : @"\u223C",
                        @"&#x2245;" : @"\u2245",
                        @"&#x2248;" : @"\u2248",
                        @"&#x2260;" : @"\u2260",
                        @"&#x2261;" : @"\u2261",
                        @"&#x2264;" : @"\u2264",
                        @"&#x2265;" : @"\u2265",
                        @"&#x2282;" : @"\u2282",
                        @"&#x2283;" : @"\u2283",
                        @"&#x2284;" : @"\u2284",
                        @"&#x2286;" : @"\u2286",
                        @"&#x2287;" : @"\u2287",
                        @"&#x2295;" : @"\u2295",
                        @"&#x2297;" : @"\u2297",
                        @"&#x22A5;" : @"\u22A5",
                        @"&#x22C5;" : @"\u22C5",
                        @"&#x2308;" : @"\u2308",
                        @"&#x2309;" : @"\u2309",
                        @"&#x230A;" : @"\u230A",
                        @"&#x230B;" : @"\u230B",
                        @"&#x2329;" : @"\u2329",
                        @"&#x232A;" : @"\u232A",
                        @"&#x25CA;" : @"\u25CA",
                        @"&#x2660;" : @"\u2660",
                        @"&#x2663;" : @"\u2663",
                        @"&#x2665;" : @"\u2665",
                        @"&#x2666;" : @"\u2666"
                        };
    });
}
@end


================================================
FILE: Classes/GONMarkupParser_All.h
================================================
//
//  GONMarkupParser_All.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 15/07/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "GONMarkupParser.h"
#import "GONMarkupParserManager.h"
#import "GONMarkupDefaultMarkups.h"
#import "GONMarkupParser_Categories.h"

================================================
FILE: Classes/GONMarkupParser_Categories.h
================================================
//
//  GONMarkupParser_Categories.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#ifndef GONMarkupParserSample_GONMarkupParser_Categories_h
#define GONMarkupParserSample_GONMarkupParser_Categories_h

#import "UIButton+GONMarkupParser.h"
#import "UILabel+GONMarkupParser.h"
#import "UITextField+GONMarkupParser.h"
#import "UITextView+GONMarkupParser.h"

#endif


================================================
FILE: Classes/GONMarkupReset.h
================================================
//
//  GONMarkupReset.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Reset tag is used to reset all current configuration, and use default one
//  It allows you to protect a string portion, for example :
//  <red>this text is red<strong>red strong <reset> <yellow> yellow default <yellow> </reset> red strong </strong> red </red>
//
//  "all" attribute can be used to also remove default configuration
//  sharedContext will also be reset

#import "GONMarkup.h"

// Context
#define GONMarkupReset_SAVED_CONTEXT_KEY  @"GONMarkupReset.savedContext"   // Saved context before reset, to be restored on tag end

// Tag
#define GONMarkupReset_TAG                 @"reset"

// Attributes
#define GONMarkupReset_TAG_all_ATT         @"all"   // If true default parser configuration won't be set, default is false.

@interface GONMarkupReset : GONMarkup
/* Class constructor */
+ (instancetype)resetMarkup;

@end


================================================
FILE: Classes/GONMarkupReset.m
================================================
//
//  GONMarkupReset.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupReset.h"
#import "GONMarkup+Private.h"

@implementation GONMarkupReset
#pragma mark - Constructor
+ (instancetype)resetMarkup
{
    return [self markupForTag:GONMarkupReset_TAG];
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Reset configuration
    [configurationDictionary removeAllObjects];

    // Set it back to default if allowed
    if (![[dicAttributes objectForKey:GONMarkupReset_TAG_all_ATT] boolValue])
        [configurationDictionary addEntriesFromDictionary:self.parser.defaultConfiguration];

    // Copy current context
    NSMutableDictionary *contextCopy = [context mutableCopy];

    // Reset it
    [context removeAllObjects];

    // Hold saved context
    [context setObject:contextCopy
                 forKey:GONMarkupReset_SAVED_CONTEXT_KEY];
}

- (void)closingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // Copy current context
    NSMutableDictionary *savedContext = [context objectForKey:GONMarkupReset_SAVED_CONTEXT_KEY];

    // Reset context
    [context removeAllObjects];

    // Reset current context to previously saved one
    [context addEntriesFromDictionary:savedContext];
}
@end


================================================
FILE: Classes/GONMarkupSimple.h
================================================
//
//  GONMarkupSimple.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 18/07/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//
//  Define a markup to automatically add attributes to current string
//  Content of style dictionary is added to current style dictionary
//  "style" dictionary is intended to be the same as you may pass to configure an NSMutableAttributedString using -setAttributes:range: method
//
//  If overriding NSParagraphStyleAttributeName, check merging strategy to use
//  - override (default)
//  - merge
//

#import "GONMarkup.h"

typedef NS_ENUM(NSInteger, GONMarkupSimpleMergingStrategy) {
    GONMarkupSimpleMergingStrategyMergeAll                      = -1,
    GONMarkupSimpleMergingStrategyOverride                      = 0,

    GONMarkupSimpleMergingStrategyMergeAlignment                = 1 << 0,
    GONMarkupSimpleMergingStrategyMergeFirstLineHeadIndent      = 1 << 1,
    GONMarkupSimpleMergingStrategyMergeHeadIndent               = 1 << 2,
    GONMarkupSimpleMergingStrategyMergeTailIndent               = 1 << 3,
    GONMarkupSimpleMergingStrategyMergeLineBreakMode            = 1 << 4,
    GONMarkupSimpleMergingStrategyMergeMaximumLineHeight        = 1 << 5,
    GONMarkupSimpleMergingStrategyMergeMinimumLineHeight        = 1 << 6,
    GONMarkupSimpleMergingStrategyMergeLineSpacing              = 1 << 7,
    GONMarkupSimpleMergingStrategyMergeParagraphSpacing         = 1 << 8,
    GONMarkupSimpleMergingStrategyMergeParagraphSpacingBefore   = 1 << 9,
    GONMarkupSimpleMergingStrategyMergeBaseWritingDirection     = 1 << 10,
    GONMarkupSimpleMergingStrategyMergeLineHeightMultiple       = 1 << 11,
    GONMarkupSimpleMergingStrategyMergeTabStops                 = 1 << 12,
    GONMarkupSimpleMergingStrategyMergeDefaultTabInterval       = 1 << 13,
    GONMarkupSimpleMergingStrategyMergeHyphenationFactor        = 1 << 14
};

@interface GONMarkupSimple : GONMarkup
/* Class contructor, allowing to specify a merging strategy.
 * Use this constructor if this markup will update NSParagraphStyleAttributeName key
 * strategy can be a combinaison of GONMarkupSimpleMergingStrategy values to define per attribute merging strategy
 * "style" dictionary is intended to be the same as you may pass to configure an NSMutableAttributedString using -setAttributes:range: method
 */
+ (instancetype)simpleMarkup:(NSString *)tag style:(NSDictionary *)style mergingStrategy:(GONMarkupSimpleMergingStrategy)strategy;

/* Default class contructor, using override as default merging strategy
 * Use this constructor is this markup won't update NSParagraphStyleAttributeName key, will throw an exception otherwise
 * "style" dictionary is intended to be the same as you may pass to configure an NSMutableAttributedString using -setAttributes:range: method
 */
+ (instancetype)simpleMarkup:(NSString *)tag style:(NSDictionary *)style;

@property (nonatomic, copy, readonly) NSDictionary *style;
@end


================================================
FILE: Classes/GONMarkupSimple.m
================================================
//
//  GONMarkupSimple.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 18/07/14.
//  Copyright 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupSimple.h"

#define MERGE_ATTRIBUTE(att) (_mergingStrategy == GONMarkupSimpleMergingStrategyMergeAll || _mergingStrategy | att)

@interface GONMarkupSimple ()
// Data
@property (nonatomic, copy)   NSDictionary *style;
@property (nonatomic, assign) GONMarkupSimpleMergingStrategy mergingStrategy;
@end

@implementation GONMarkupSimple
#pragma mark - Constructor
+ (instancetype)simpleMarkup:(NSString *)tag
                       style:(NSDictionary *)style
             mergingStrategy:(GONMarkupSimpleMergingStrategy)strategy
{
    GONMarkupSimple *markup = [self markupForTag:tag];

    markup.style = style;
    markup.mergingStrategy = strategy;

    return markup;
}

+ (instancetype)simpleMarkup:(NSString *)tag
                       style:(NSDictionary *)style
{
    if ([style objectForKey:NSParagraphStyleAttributeName])
        @throw @"Critical error. You cannot update NSParagraphStyleAttributeName without setting a merging strategy ";

    GONMarkupSimple *markup = [self markupForTag:tag];

    markup.style = style;

    return markup;
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    // No NSParagraphStyleAttributeName update, or set in only one dic, nothing to do
    if ((![_style objectForKey:NSParagraphStyleAttributeName] && ![configurationDictionary objectForKey:NSParagraphStyleAttributeName]) ||
        ( [_style objectForKey:NSParagraphStyleAttributeName] && ![configurationDictionary objectForKey:NSParagraphStyleAttributeName]) ||
        (![_style objectForKey:NSParagraphStyleAttributeName] &&  [configurationDictionary objectForKey:NSParagraphStyleAttributeName]))
    {
        [configurationDictionary addEntriesFromDictionary:_style];
        return;
    }

    // Should apply a defined strategy
    NSMutableDictionary *updatedStyleDic = [_style mutableCopy];
    [updatedStyleDic setObject:[self merge:[_style objectForKey:NSParagraphStyleAttributeName] into:[configurationDictionary objectForKey:NSParagraphStyleAttributeName]]
                        forKey:NSParagraphStyleAttributeName];

    [configurationDictionary addEntriesFromDictionary:_style];
}

- (NSParagraphStyle *)merge:(NSParagraphStyle *)sourceStyle
                       into:(NSParagraphStyle *)destStyle
{
    // On override, nothing to do
    if (_mergingStrategy == GONMarkupSimpleMergingStrategyOverride)
        return [sourceStyle mutableCopy];

    // Merge all strategy
    NSMutableParagraphStyle *mergedStyle = [destStyle mutableCopy];

    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeAlignment))              mergedStyle.alignment               = sourceStyle.alignment;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeFirstLineHeadIndent))    mergedStyle.firstLineHeadIndent     = sourceStyle.firstLineHeadIndent;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeHeadIndent))             mergedStyle.headIndent              = sourceStyle.headIndent;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeTailIndent))             mergedStyle.tailIndent              = sourceStyle.tailIndent;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeLineBreakMode))          mergedStyle.lineBreakMode           = sourceStyle.lineBreakMode;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeMaximumLineHeight))      mergedStyle.maximumLineHeight       = sourceStyle.maximumLineHeight;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeMinimumLineHeight))      mergedStyle.minimumLineHeight       = sourceStyle.minimumLineHeight;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeLineSpacing))            mergedStyle.lineSpacing             = sourceStyle.lineSpacing;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeParagraphSpacing))       mergedStyle.paragraphSpacing        = sourceStyle.paragraphSpacing;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeParagraphSpacingBefore)) mergedStyle.paragraphSpacingBefore  = sourceStyle.paragraphSpacingBefore;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeBaseWritingDirection))   mergedStyle.baseWritingDirection    = sourceStyle.baseWritingDirection;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeLineHeightMultiple))     mergedStyle.lineHeightMultiple      = sourceStyle.lineHeightMultiple;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeTabStops))               mergedStyle.tabStops                = sourceStyle.tabStops;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeDefaultTabInterval))     mergedStyle.defaultTabInterval      = sourceStyle.defaultTabInterval;
    if (MERGE_ATTRIBUTE(GONMarkupSimpleMergingStrategyMergeHyphenationFactor))      mergedStyle.hyphenationFactor       = sourceStyle.hyphenationFactor;

    return mergedStyle;
}
@end


================================================
FILE: Classes/GONMarkupStrong.h
================================================
//
//  GONMarkupStrong.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/05/2017.
//  Copyright 2017 Nicolas Goutaland. All rights reserved.
//
//  Same as b tag.
//  Subclassing b allowing users to override strong markup behavior
//
//  Examples
//
//  <strong>bold text</>

#import "GONMarkupBold.h"

#define GONMarkupStrong_TAG                 @"strong"

@interface GONMarkupStrong : GONMarkupBold
/* Default markup to add strong support */
+ (instancetype)strongMarkup;

@end


================================================
FILE: Classes/GONMarkupStrong.m
================================================
//
//  GONMarkupStrong.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/05/2017.
//  Copyright 2017 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupStrong.h"

@interface GONMarkupStrong ()
@end

@implementation GONMarkupStrong
#pragma mark - Constructor
+ (instancetype)strongMarkup
{
    return [super fontTraitsMarkup:GONMarkupStrong_TAG
                            traits:UIFontDescriptorTraitBold];
}

@end


================================================
FILE: Classes/GONMarkupTextStyle.h
================================================
//
//  GONMarkupTextStyle.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/07/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  Tag updating current font style (subscripted / superscripted).
//
//  Examples
//
//  <sup>superscripted text</>
//  <sub>subscripted text</>

#import "GONMarkup.h"

// Tag
#define GONMarkupTextStyle_Superscripted_TAG        @"sup"
#define GONMarkupTextStyle_Subscripted_TAG          @"sub"

@interface GONMarkupTextStyle : GONMarkup
/* Return all markups */
+ (NSArray *)allMarkups;

/* Default markup to add superscripted support */
+ (instancetype)superscriptedMarkup;

/* Default markup to add subscripted support */
+ (instancetype)subscriptedMarkup;
@end




================================================
FILE: Classes/GONMarkupTextStyle.m
================================================
//
//  GONMarkupTextStyle.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/07/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "GONMarkupTextStyle.h"
#import <CoreText/CoreText.h>

@interface GONMarkupTextStyle ()
// Data
@property (nonatomic, strong) NSNumber *superscriptValue;
@end

@implementation GONMarkupTextStyle
#pragma mark - Constructor
+ (NSArray *)allMarkups
{
    return @[[self superscriptedMarkup], [self subscriptedMarkup]];
}

+ (instancetype)superscriptedMarkup
{
    GONMarkupTextStyle *markup = [self markupForTag:GONMarkupTextStyle_Superscripted_TAG];

    markup.superscriptValue = @(1);

    return markup;
}

+ (instancetype)subscriptedMarkup
{
    GONMarkupTextStyle *markup = [self markupForTag:GONMarkupTextStyle_Subscripted_TAG];

    markup.superscriptValue = @(-1);

    return markup;
}

#pragma mark - Style
- (void)openingMarkupFound:(NSString *)tag
             configuration:(NSMutableDictionary *)configurationDictionary
                   context:(NSMutableDictionary *)context
                attributes:(NSDictionary *)dicAttributes
              resultString:(NSAttributedString *)resultString
{
    [configurationDictionary setObject:_superscriptValue
                                 forKey:(NSString *)kCTSuperscriptAttributeName];
}

@end


================================================
FILE: Classes/UIButton+GONMarkupParser.h
================================================
//
//  UIButton+GONMarkupParser.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 23/08/15.
//  Copyright (c) 2015 Nicolas Goutaland. All rights reserved.
//
#import "GONMarkupParser.h"

@interface UIButton (GONMarkupParser)
/* Update button label with given text, considering it as a marked up string.
 * Given parser will be used to parse string
 * If parser is nil, [GONMarkupParserManager sharedParser] will be used
 */
- (void)setMarkedUpTitle:(NSString *)title forState:(UIControlState)controlState parser:(GONMarkupParser *)parser;

/* Update button with given text, considering it as a marked up string.
 * [GONMarkupParserManager sharedParser] will be used to parse string
 */
- (void)setMarkedUpTitle:(NSString *)title forState:(UIControlState)controlState;
@end


================================================
FILE: Classes/UIButton+GONMarkupParser.m
================================================
//
//  UIButton+GONMarkupParser.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 23/08/15.
//  Copyright (c) 2015 Nicolas Goutaland. All rights reserved.
//

#import "UIButton+GONMarkupParser.h"
#import "GONMarkupParserUtils.h"

@implementation UIButton (GONMarkupParser)
#pragma mark - GONMarkupParser
- (void)setMarkedUpTitle:(NSString *)title forState:(UIControlState)controlState parser:(GONMarkupParser *)parser
{
    NSAttributedString *attributedText = [GONMarkupParserUtils attributedString:parser
                                                                     withString:title
                                                                    defautColor:[self titleColorForState:controlState]
                                                                    defaultFont:self.titleLabel.font
                                                               defaultAlignment:self.titleLabel.textAlignment];
    
    [self setAttributedTitle:attributedText
                    forState:controlState];
}

- (void)setMarkedUpTitle:(NSString *)title forState:(UIControlState)controlState
{
    [self setMarkedUpTitle:title
                  forState:UIControlStateNormal
                    parser:nil];
}

@end


================================================
FILE: Classes/UILabel+GONMarkupParser.h
================================================
//
//  UILabel+GONMarkupParser.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "GONMarkupParser.h"

@interface UILabel (GONMarkupParser)
/* Update label with given text, considering it as a marked up string.
 * Given parser will be used to parse string
 * If parser is nil, [GONMarkupParserManager sharedParser] will be used
 */
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser;

/* Update label with given text, considering it as a marked up string.
 * [GONMarkupParserManager sharedParser] will be used to parse string
 */
- (void)setMarkedUpText:(NSString *)text;
@end


================================================
FILE: Classes/UILabel+GONMarkupParser.m
================================================
//
//  UILabel+GONMarkupParser.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "UILabel+GONMarkupParser.h"
#import "GONMarkupParserManager.h"
#import "GONMarkupParserUtils.h"

@implementation UILabel (GONMarkupParser)
#pragma mark - GONMarkupParser
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser
{
    self.attributedText = [GONMarkupParserUtils attributedString:parser
                                                      withString:text
                                                     defautColor:self.textColor
                                                     defaultFont:self.font
                                                defaultAlignment:self.textAlignment];
}

- (void)setMarkedUpText:(NSString *)text
{
    [self setMarkedUpText:text
                   parser:nil];
}
@end


================================================
FILE: Classes/UITextField+GONMarkupParser.h
================================================
//
//  UITextField+GONMarkupParser.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "GONMarkupParser.h"

@interface UITextField (GONMarkupParser)
/* Update textfield with given text, considering it as a marked up string.
 * Given parser will be used to parse string
 * If parser is nil, [GONMarkupParserManager sharedParser] will be used
 */
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser;

/* Update textfield with given text, considering it as a marked up string.
 * [GONMarkupParserManager sharedParser] will be used to parse string
 */
- (void)setMarkedUpText:(NSString *)text;

@end


================================================
FILE: Classes/UITextField+GONMarkupParser.m
================================================
//
//  UITextField+GONMarkupParser.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/09/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "UITextField+GONMarkupParser.h"
#import "GONMarkupParserManager.h"
#import "GONMarkupParserUtils.h"

@implementation UITextField (GONMarkupParser)
#pragma mark - GONMarkupParser
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser
{
    self.attributedText = [GONMarkupParserUtils attributedString:parser
                                                      withString:text
                                                     defautColor:self.textColor
                                                     defaultFont:self.font
                                                defaultAlignment:self.textAlignment];
}

- (void)setMarkedUpText:(NSString *)text
{
    [self setMarkedUpText:text
                   parser:nil];
}
@end


================================================
FILE: Classes/UITextView+GONMarkupParser.h
================================================
//
//  UITextView+GONMarkupParser.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//
#import "GONMarkupParser.h"

@interface UITextView (GONMarkupParser)
/* Update textfield with given text, considering it as a marked up string.
 * Given parser will be used to parse string
 * If parser is nil, [GONMarkupParserManager sharedParser] will be used
 */
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser;

/* Update textfield with given text, considering it as a marked up string.
 * [GONMarkupParserManager sharedParser] will be used to parse string
 */
- (void)setMarkedUpText:(NSString *)text;

@end


================================================
FILE: Classes/UITextView+GONMarkupParser.m
================================================
//
//  UITextView+GONMarkupParser.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 04/02/15.
//  Copyright 2015 Nicolas Goutaland. All rights reserved.
//

#import "UITextView+GONMarkupParser.h"
#import "GONMarkupParserManager.h"
#import "GONMarkupParserUtils.h"

@implementation UITextView (GONMarkupParser)
#pragma mark - GONMarkupParser
- (void)setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser
{
    self.attributedText = [GONMarkupParserUtils attributedString:parser
                                                      withString:text
                                                     defautColor:self.textColor
                                                     defaultFont:self.font
                                                defaultAlignment:self.textAlignment];
}

- (void)setMarkedUpText:(NSString *)text
{
    [self setMarkedUpText:text
                   parser:nil];
}
@end

================================================
FILE: Example/GONMarkupParserSample/AppDelegate.h
================================================
//
//  AppDelegate.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) IBOutlet UIWindow *window;
@end


================================================
FILE: Example/GONMarkupParserSample/AppDelegate.m
================================================
//
//  AppDelegate.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 25/06/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "AppDelegate.h"
#import "GONMarkupParser_All.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Set your custom configuration here
#ifdef DEBUG
    [GONMarkupParserManager sharedParser].logLevel = GONMarkupParserLogLevelErrors; // Fuck yeah, error logging
#endif
    
    return YES;
}

@end


================================================
FILE: Example/GONMarkupParserSample/ComplexExample
================================================
default text here <red>this text should be red <small>small </small> </red><small>black small</small>.
This one should be black
<font name="Didot-Italic" size="12"> Using a new font, using its full name (Didot-Italic) </><br/><br/>
<color value="F4D03F">yellow <reset>protected \o/</reset>ye<font size="12">ll</>ow<//>
Let me add some <custom>Custom tag here</>
Yep, that was big.
You can also change text alignment
<center>Centered</>
<left>Left</>
<right>Right</>
<justified>Justified paragraph Lorem ipsum dolor sit amet, consectetur adipiscing elit. In <red>rhoncus diam nec sem consequat</red> tincidunt. Etiam eu lacus a lorem cursus sodales et nec sapien. </>
<natural>Natural</>
<inc>Text <inc>size <inc>can <inc>also <inc>be <inc>incremented <dec>or <dec>decremented<dec>, <dec>1 <dec>per <dec>1, <inc value="15">or specifying <dec value="10">a value.<//>

<font name="customfont">This text will be written using a registered font on your parser, allowing to use it specifying a code, instead of its full name.</>

<custom>Another Custom tag here, but with <reset all="true">a full protected section</reset>, pretty cool huh ?</>
And now, an unordered list
<ul>
<li>Item</li>
<ul>
<li>very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item</li>
<ul>
<li>very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item</li>
<li>very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item<br />with a new line inside.....</li>
</ul>
<ul>
<li>Item</li>
</ul>
</ul>
<li><red>Item</red></li>
<li>Item</li>
</ul>

and an ordered list
<ol>
<li>Item 1</li>
<ol>
<li>Item 1</li>
<ol>
<li>Item 1</li>
</ol>
<ol>
<li>Item 1 (New sub list)</li>
</ol>
</ol>
<li>Item 2</li>
<li>Item 3</li></ol>
<dec><dec><color value="gray">Anchor are also supported. If you are using a UITextView to display your attributed string, set it non editable, but selectionnable, set its delegate and implements
<b>- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange</>
method to handle user interaction.
<a href="https://github.com/nicolasgoutaland/GONMarkupParser">Link example ;)<//>


Finally, you can set <b>bold text</>, <i>italic text</> or <b><i>both</></>

<u>Underline</> and <strike>strikethrough</> text is also available.
You can customize line <u pattern="dash">pattern</>, <strike style="double">style</> and <u word="true">limit style to words only</>.
<strike pattern="dashdotdot" words="true"><u style="double">Ugly style is also available ;)</></>


================================================
FILE: Example/GONMarkupParserSample/ComplexExampleViewController.h
================================================
//
//  ComplexExampleViewController.h
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 11/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

@interface ComplexExampleViewController : UIViewController

@end


================================================
FILE: Example/GONMarkupParserSample/ComplexExampleViewController.m
================================================
//
//  ComplexExampleViewController.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 11/11/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//

#import "ComplexExampleViewController.h"
#import "ResultViewController.h"

#define COMPLEX_EXAMPLE_INPUT_FILE  @"ComplexExample"

@interface ComplexExampleViewController ()
// Data
@property (nonatomic, strong) GONMarkupParser *parser;

// View controllers
@property (nonatomic, strong) ResultViewController *resultViewController;

// Outlets
@property (nonatomic, weak  ) IBOutlet UITextView      *inputTextView;
@property (nonatomic, strong) IBOutlet UIBarButtonItem *validateButton;
@end

@implementation ComplexExampleViewController
#pragma mark - View management
- (void)viewDidLoad {
    [super viewDidLoad];

    // Validate button
    self.navigationItem.rightBarButtonItem = _validateButton;

    // Load default text for a complex example
    NSString *defaultString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:COMPLEX_EXAMPLE_INPUT_FILE ofType:nil]
                                                        encoding:NSUTF8StringEncoding error:nil];
    self.inputTextView.text = defaultString;

    [self configureParser];
}

#pragma mark - Parser configuration
- (void)configureParser
{
    // Create a new parser
    _parser = [GONMarkupParser defaultMarkupParser];

    // Set your custom configuration here
#ifdef DEBUG
    _parser.logLevel = GONMarkupParserLogLevelErrors; // Fuck yeah, error logging
#endif

    // Set default text configuration
    [_parser.defaultConfiguration setObject:[UIFont systemFontOfSize:25.0]
                                     forKey:NSFontAttributeName];

    // Add a custom markup, that will center text when used, and display it in pink.
    NSMutableParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    defaultParagraphStyle.alignment = NSTextAlignmentCenter;
    [_parser addMarkup:[GONMarkupSimple simpleMarkup:@"pwet"
                                               style:@{
                                                        NSParagraphStyleAttributeName : defaultParagraphStyle,
                                                        NSForegroundColorAttributeName : [@"pink" representedColor] // NSString+Color
                                                       }
                                     mergingStrategy:GONMarkupSimpleMergingStrategyMergeAll]];
    
    // Add add font markup, to display small text when encountered
    [_parser addMarkup:[GONMarkupNamedFont namedFontMarkup:[UIFont systemFontOfSize:12.0] forTag:@"small"]];

    // Add a convenient tag for red color
    [_parser addMarkup:[GONMarkupNamedColor namedColorMarkup:[UIColor redColor]
                                                      forTag:@"red"]];

    // Custom markup, based on block
    GONMarkupBlock *markupBlock = [GONMarkupBlock blockMarkup:@"custom"];
    markupBlock.openingMarkupBlock = ^(NSMutableDictionary *configurationDictionary, NSString *tag, NSMutableDictionary *context, NSDictionary *dicAttributes, NSAttributedString *resultString) {
        [configurationDictionary setObject:[UIFont boldSystemFontOfSize:69.0]
                                    forKey:NSFontAttributeName];
        [configurationDictionary setObject:[@"brown" representedColor]
                                    forKey:NSForegroundColorAttributeName];
    };

    [_parser addMarkup:markupBlock];

    // Finally registering a custom font. You can refer to it using its key
    [_parser registerFont:[UIFont fontWithName:@"AmericanTypewriter" size:22]
                   forKey:@"customfont"];
}

#pragma mark - UI Actions
- (IBAction)showResult
{
    // Parse string
    self.resultViewController.resultAttributedString = [_parser attributedStringFromString:_inputTextView.text];

    // Show results
    [self.navigationController pushViewController:self.resultViewController
                                         animated:YES];
}

LAZY_PROPERTY(resultViewController);
@end


================================================
FILE: Example/GONMarkupParserSample/ComplexExampleViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ComplexExampleViewController">
            <connections>
                <outlet property="inputTextView" destination="POq-EJ-nFs" id="tde-IK-RHB"/>
                <outlet property="validateButton" destination="eLD-U2-qOP" id="dM4-Fu-LKp"/>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
            <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
Download .txt
gitextract_dlvgp0vj/

├── .gitignore
├── CHANGELOG.md
├── Classes/
│   ├── GONMarkup+Private.h
│   ├── GONMarkup+Private.m
│   ├── GONMarkup.h
│   ├── GONMarkup.m
│   ├── GONMarkupAlignment.h
│   ├── GONMarkupAlignment.m
│   ├── GONMarkupAnchor.h
│   ├── GONMarkupAnchor.m
│   ├── GONMarkupBlock.h
│   ├── GONMarkupBlock.m
│   ├── GONMarkupBold.h
│   ├── GONMarkupBold.m
│   ├── GONMarkupColor.h
│   ├── GONMarkupColor.m
│   ├── GONMarkupDec.h
│   ├── GONMarkupDec.m
│   ├── GONMarkupDefaultMarkups.h
│   ├── GONMarkupFont.h
│   ├── GONMarkupFont.m
│   ├── GONMarkupFontTraits.h
│   ├── GONMarkupFontTraits.m
│   ├── GONMarkupImage.h
│   ├── GONMarkupImage.m
│   ├── GONMarkupInc.h
│   ├── GONMarkupInc.m
│   ├── GONMarkupItalic.h
│   ├── GONMarkupItalic.m
│   ├── GONMarkupLineBreak.h
│   ├── GONMarkupLineBreak.m
│   ├── GONMarkupLineStyle.h
│   ├── GONMarkupLineStyle.m
│   ├── GONMarkupList.h
│   ├── GONMarkupList.m
│   ├── GONMarkupListItem.h
│   ├── GONMarkupListItem.m
│   ├── GONMarkupNamedColor.h
│   ├── GONMarkupNamedColor.m
│   ├── GONMarkupNamedFont.h
│   ├── GONMarkupNamedFont.m
│   ├── GONMarkupParagraph.h
│   ├── GONMarkupParagraph.m
│   ├── GONMarkupParser.h
│   ├── GONMarkupParser.m
│   ├── GONMarkupParserManager.h
│   ├── GONMarkupParserManager.m
│   ├── GONMarkupParserUtils.h
│   ├── GONMarkupParserUtils.m
│   ├── GONMarkupParser_All.h
│   ├── GONMarkupParser_Categories.h
│   ├── GONMarkupReset.h
│   ├── GONMarkupReset.m
│   ├── GONMarkupSimple.h
│   ├── GONMarkupSimple.m
│   ├── GONMarkupStrong.h
│   ├── GONMarkupStrong.m
│   ├── GONMarkupTextStyle.h
│   ├── GONMarkupTextStyle.m
│   ├── UIButton+GONMarkupParser.h
│   ├── UIButton+GONMarkupParser.m
│   ├── UILabel+GONMarkupParser.h
│   ├── UILabel+GONMarkupParser.m
│   ├── UITextField+GONMarkupParser.h
│   ├── UITextField+GONMarkupParser.m
│   ├── UITextView+GONMarkupParser.h
│   └── UITextView+GONMarkupParser.m
├── Example/
│   ├── GONMarkupParserSample/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── ComplexExample
│   │   ├── ComplexExampleViewController.h
│   │   ├── ComplexExampleViewController.m
│   │   ├── ComplexExampleViewController.xib
│   │   ├── DefaultConfigurationViewController.h
│   │   ├── DefaultConfigurationViewController.m
│   │   ├── DefaultConfigurationViewController.xib
│   │   ├── GONMarkupParserSample-Info.plist
│   │   ├── GONMarkupParserSample-Prefix.pch
│   │   ├── Images.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.launchimage/
│   │   │       └── Contents.json
│   │   ├── MainWindow.xib
│   │   ├── PlaygroundViewController.h
│   │   ├── PlaygroundViewController.m
│   │   ├── PlaygroundViewController.xib
│   │   ├── ResultViewController.h
│   │   ├── ResultViewController.m
│   │   ├── ResultViewController.xib
│   │   ├── RootViewController.h
│   │   ├── RootViewController.m
│   │   ├── RootViewController.xib
│   │   ├── SampleViewController.h
│   │   ├── SampleViewController.m
│   │   ├── SampleViewController.xib
│   │   ├── en.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── main.m
│   │   └── samples.plist
│   ├── GONMarkupParserSample.xcodeproj/
│   │   ├── project.pbxproj
│   │   └── project.xcworkspace/
│   │       └── contents.xcworkspacedata
│   ├── GONMarkupParserSample.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── IDEWorkspaceChecks.plist
│   ├── GONMarkupParserSampleTests/
│   │   ├── GONMarkupParserSampleTests-Info.plist
│   │   ├── GONMarkupParserSampleTests.m
│   │   └── en.lproj/
│   │       └── InfoPlist.strings
│   └── PodFile
├── GONMarkupParser.podspec
├── LICENSE
└── README.md
Download .txt
SYMBOL INDEX (2 symbols across 2 files)

FILE: Classes/GONMarkupFontTraits.h
  function interface (line 17) | interface GONMarkupFontTraits : GONMarkup {

FILE: Classes/GONMarkupParser.h
  type GONMarkupParserLogLevel (line 46) | typedef enum : NSUInteger {
Condensed preview — 107 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (355K chars).
[
  {
    "path": ".gitignore",
    "chars": 325,
    "preview": "# Xcode\n.DS_Store\n*/build/*\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspecti"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 3101,
    "preview": "# Change Log\n## [__0.8.2__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.2)\nUpdated HTML entitie"
  },
  {
    "path": "Classes/GONMarkup+Private.h",
    "chars": 1044,
    "preview": "//\n//  GONMarkup+Private.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) "
  },
  {
    "path": "Classes/GONMarkup+Private.m",
    "chars": 1566,
    "preview": "//\n//  GONMarkup+Private.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) "
  },
  {
    "path": "Classes/GONMarkup.h",
    "chars": 5578,
    "preview": "//\n//  GONMarkup.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014 Nic"
  },
  {
    "path": "Classes/GONMarkup.m",
    "chars": 5874,
    "preview": "//\n//  GONMarkup.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014 Nic"
  },
  {
    "path": "Classes/GONMarkupAlignment.h",
    "chars": 1478,
    "preview": "//\n//  GONMarkupAlignment.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 22/07/14.\n//  Copyright 201"
  },
  {
    "path": "Classes/GONMarkupAlignment.m",
    "chars": 2141,
    "preview": "//\n//  GONMarkupAlignment.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 22/07/14.\n//  Copyright 201"
  },
  {
    "path": "Classes/GONMarkupAnchor.h",
    "chars": 916,
    "preview": "//\n//  GONMarkupAnchor.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/02/15.\n//  Copyright 2015 N"
  },
  {
    "path": "Classes/GONMarkupAnchor.m",
    "chars": 957,
    "preview": "//\n//  GONMarkupAnchor.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/02/15.\n//  Copyright 2015 N"
  },
  {
    "path": "Classes/GONMarkupBlock.h",
    "chars": 1658,
    "preview": "//\n//  GONMarkupBlock.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupBlock.m",
    "chars": 3358,
    "preview": "//\n//  GONMarkupBlock.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupBold.h",
    "chars": 789,
    "preview": "//\n//  GONMarkupBold.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/09/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupBold.m",
    "chars": 401,
    "preview": "//\n//  GONMarkupBold.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/09/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupColor.h",
    "chars": 840,
    "preview": "//\n//  GONMarkupColor.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupColor.m",
    "chars": 954,
    "preview": "//\n//  GONMarkupColor.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupDec.h",
    "chars": 651,
    "preview": "//\n//  GONMarkupDec.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c) 2014 "
  },
  {
    "path": "Classes/GONMarkupDec.m",
    "chars": 1328,
    "preview": "//\n//  GONMarkupDec.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c) 2014 "
  },
  {
    "path": "Classes/GONMarkupDefaultMarkups.h",
    "chars": 780,
    "preview": "//\n//  GONMarkupDefaultMarkups.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyrigh"
  },
  {
    "path": "Classes/GONMarkupFont.h",
    "chars": 1964,
    "preview": "//\n//  GONMarkupFont.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupFont.m",
    "chars": 3518,
    "preview": "//\n//  GONMarkupFont.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupFontTraits.h",
    "chars": 1105,
    "preview": "//\n//  GONMarkupFontTraits.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 22/09/14.\n//  Copyright 20"
  },
  {
    "path": "Classes/GONMarkupFontTraits.m",
    "chars": 3473,
    "preview": "//\n//  GONMarkupFontTraits.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 22/09/14.\n//  Copyright 20"
  },
  {
    "path": "Classes/GONMarkupImage.h",
    "chars": 644,
    "preview": "//\n//  GONMarkupImage.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/03/16.\n//  Copyright © 2016 "
  },
  {
    "path": "Classes/GONMarkupImage.m",
    "chars": 1396,
    "preview": "//\n//  GONMarkupImage.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/03/16.\n//  Copyright © 2016 "
  },
  {
    "path": "Classes/GONMarkupInc.h",
    "chars": 649,
    "preview": "//\n//  GONMarkupInc.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c) 2014 "
  },
  {
    "path": "Classes/GONMarkupInc.m",
    "chars": 1320,
    "preview": "//\n//  GONMarkupInc.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c) 2014 "
  },
  {
    "path": "Classes/GONMarkupItalic.h",
    "chars": 817,
    "preview": "//\n//  GONMarkupItalic.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/09/14.\n//  Copyright (c) 20"
  },
  {
    "path": "Classes/GONMarkupItalic.m",
    "chars": 443,
    "preview": "//\n//  GONMarkupItalic.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/09/14.\n//  Copyright (c) 20"
  },
  {
    "path": "Classes/GONMarkupLineBreak.h",
    "chars": 448,
    "preview": "//\n//  GONMarkupLineBreak.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupLineBreak.m",
    "chars": 1166,
    "preview": "//\n//  GONMarkupLineBreak.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupLineStyle.h",
    "chars": 1950,
    "preview": "//\n//  GONMarkupLineStyle.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 03/02/15.\n//  Copyright 201"
  },
  {
    "path": "Classes/GONMarkupLineStyle.m",
    "chars": 3495,
    "preview": "//\n//  GONMarkupLineStyle.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 03/02/15.\n//  Copyright 201"
  },
  {
    "path": "Classes/GONMarkupList.h",
    "chars": 1180,
    "preview": "//\n//  GONMarkupList.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupList.m",
    "chars": 2887,
    "preview": "//\n//  GONMarkupList.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014"
  },
  {
    "path": "Classes/GONMarkupListItem.h",
    "chars": 1772,
    "preview": "//\n//  GONMarkupListItem.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) "
  },
  {
    "path": "Classes/GONMarkupListItem.m",
    "chars": 6741,
    "preview": "//\n//  GONMarkupListItem.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) "
  },
  {
    "path": "Classes/GONMarkupNamedColor.h",
    "chars": 591,
    "preview": "//\n//  GONMarkupNamedColor.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c"
  },
  {
    "path": "Classes/GONMarkupNamedColor.m",
    "chars": 1515,
    "preview": "//\n//  GONMarkupNamedColor.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c"
  },
  {
    "path": "Classes/GONMarkupNamedFont.h",
    "chars": 591,
    "preview": "//\n//  GONMarkupNamedFont.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupNamedFont.m",
    "chars": 1454,
    "preview": "//\n//  GONMarkupNamedFont.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupParagraph.h",
    "chars": 500,
    "preview": "//\n//  GONMarkupParagraph.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 06/08/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupParagraph.m",
    "chars": 1575,
    "preview": "//\n//  GONMarkupParagraph.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 06/08/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupParser.h",
    "chars": 6476,
    "preview": "//\n//  GONMarkupParser.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 20"
  },
  {
    "path": "Classes/GONMarkupParser.m",
    "chars": 24888,
    "preview": "//\n//  GONMarkupParser.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 20"
  },
  {
    "path": "Classes/GONMarkupParserManager.h",
    "chars": 942,
    "preview": "//\n//  GONMarkupParserManager.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/07/14.\n//  Copyright"
  },
  {
    "path": "Classes/GONMarkupParserManager.m",
    "chars": 1561,
    "preview": "//\n//  GONMarkupParserManager.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/07/14.\n//  Copyright"
  },
  {
    "path": "Classes/GONMarkupParserUtils.h",
    "chars": 1435,
    "preview": "//\n//  GONMarkupParserUtils.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/08/14.\n//  Copyright ("
  },
  {
    "path": "Classes/GONMarkupParserUtils.m",
    "chars": 48798,
    "preview": "//\n//  GONMarkupParserUtils.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/08/14.\n//  Copyright ("
  },
  {
    "path": "Classes/GONMarkupParser_All.h",
    "chars": 307,
    "preview": "//\n//  GONMarkupParser_All.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 15/07/14.\n//  Copyright (c"
  },
  {
    "path": "Classes/GONMarkupParser_Categories.h",
    "chars": 457,
    "preview": "//\n//  GONMarkupParser_Categories.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/09/14.\n//  Copyr"
  },
  {
    "path": "Classes/GONMarkupReset.h",
    "chars": 1003,
    "preview": "//\n//  GONMarkupReset.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupReset.m",
    "chars": 1824,
    "preview": "//\n//  GONMarkupReset.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 201"
  },
  {
    "path": "Classes/GONMarkupSimple.h",
    "chars": 2965,
    "preview": "//\n//  GONMarkupSimple.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 18/07/14.\n//  Copyright 2014 N"
  },
  {
    "path": "Classes/GONMarkupSimple.m",
    "chars": 5211,
    "preview": "//\n//  GONMarkupSimple.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 18/07/14.\n//  Copyright 2014 N"
  },
  {
    "path": "Classes/GONMarkupStrong.h",
    "chars": 500,
    "preview": "//\n//  GONMarkupStrong.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/05/2017.\n//  Copyright 2017"
  },
  {
    "path": "Classes/GONMarkupStrong.m",
    "chars": 446,
    "preview": "//\n//  GONMarkupStrong.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/05/2017.\n//  Copyright 2017"
  },
  {
    "path": "Classes/GONMarkupTextStyle.h",
    "chars": 736,
    "preview": "//\n//  GONMarkupTextStyle.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/07/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/GONMarkupTextStyle.m",
    "chars": 1335,
    "preview": "//\n//  GONMarkupTextStyle.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/07/14.\n//  Copyright (c)"
  },
  {
    "path": "Classes/UIButton+GONMarkupParser.h",
    "chars": 790,
    "preview": "//\n//  UIButton+GONMarkupParser.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 23/08/15.\n//  Copyrig"
  },
  {
    "path": "Classes/UIButton+GONMarkupParser.m",
    "chars": 1243,
    "preview": "//\n//  UIButton+GONMarkupParser.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 23/08/15.\n//  Copyrig"
  },
  {
    "path": "Classes/UILabel+GONMarkupParser.h",
    "chars": 700,
    "preview": "//\n//  UILabel+GONMarkupParser.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/09/14.\n//  Copyrigh"
  },
  {
    "path": "Classes/UILabel+GONMarkupParser.m",
    "chars": 928,
    "preview": "//\n//  UILabel+GONMarkupParser.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/09/14.\n//  Copyrigh"
  },
  {
    "path": "Classes/UITextField+GONMarkupParser.h",
    "chars": 717,
    "preview": "//\n//  UITextField+GONMarkupParser.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/09/14.\n//  Copy"
  },
  {
    "path": "Classes/UITextField+GONMarkupParser.m",
    "chars": 940,
    "preview": "//\n//  UITextField+GONMarkupParser.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 08/09/14.\n//  Copy"
  },
  {
    "path": "Classes/UITextView+GONMarkupParser.h",
    "chars": 711,
    "preview": "//\n//  UITextView+GONMarkupParser.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/02/15.\n//  Copyr"
  },
  {
    "path": "Classes/UITextView+GONMarkupParser.m",
    "chars": 932,
    "preview": "//\n//  UITextView+GONMarkupParser.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 04/02/15.\n//  Copyr"
  },
  {
    "path": "Example/GONMarkupParserSample/AppDelegate.h",
    "chars": 287,
    "preview": "//\n//  AppDelegate.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014 N"
  },
  {
    "path": "Example/GONMarkupParserSample/AppDelegate.m",
    "chars": 563,
    "preview": "//\n//  AppDelegate.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014 N"
  },
  {
    "path": "Example/GONMarkupParserSample/ComplexExample",
    "chars": 2815,
    "preview": "default text here <red>this text should be red <small>small </small> </red><small>black small</small>.\nThis one should b"
  },
  {
    "path": "Example/GONMarkupParserSample/ComplexExampleViewController.h",
    "chars": 245,
    "preview": "//\n//  ComplexExampleViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 11/11/14.\n//  Cop"
  },
  {
    "path": "Example/GONMarkupParserSample/ComplexExampleViewController.m",
    "chars": 4083,
    "preview": "//\n//  ComplexExampleViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 11/11/14.\n//  Cop"
  },
  {
    "path": "Example/GONMarkupParserSample/ComplexExampleViewController.xib",
    "chars": 2907,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/DefaultConfigurationViewController.h",
    "chars": 256,
    "preview": "//\n//  DefaultConfigurationViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/11/14.\n/"
  },
  {
    "path": "Example/GONMarkupParserSample/DefaultConfigurationViewController.m",
    "chars": 1336,
    "preview": "//\n//  DefaultConfigurationViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 19/11/14.\n/"
  },
  {
    "path": "Example/GONMarkupParserSample/DefaultConfigurationViewController.xib",
    "chars": 5018,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/GONMarkupParserSample-Info.plist",
    "chars": 1206,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Example/GONMarkupParserSample/GONMarkupParserSample-Prefix.pch",
    "chars": 474,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "Example/GONMarkupParserSample/Images.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 849,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "Example/GONMarkupParserSample/Images.xcassets/LaunchImage.launchimage/Contents.json",
    "chars": 516,
    "preview": "{\n  \"images\" : [\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"splash@2x.png\",\n "
  },
  {
    "path": "Example/GONMarkupParserSample/MainWindow.xib",
    "chars": 2265,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/PlaygroundViewController.h",
    "chars": 237,
    "preview": "//\n//  PlaygroundViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyrig"
  },
  {
    "path": "Example/GONMarkupParserSample/PlaygroundViewController.m",
    "chars": 1306,
    "preview": "//\n//  PlaygroundViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyrig"
  },
  {
    "path": "Example/GONMarkupParserSample/PlaygroundViewController.xib",
    "chars": 3208,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/ResultViewController.h",
    "chars": 323,
    "preview": "//\n//  ResultViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright ("
  },
  {
    "path": "Example/GONMarkupParserSample/ResultViewController.m",
    "chars": 1225,
    "preview": "//\n//  ResultViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright ("
  },
  {
    "path": "Example/GONMarkupParserSample/ResultViewController.xib",
    "chars": 3307,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/RootViewController.h",
    "chars": 270,
    "preview": "//\n//  RootViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c)"
  },
  {
    "path": "Example/GONMarkupParserSample/RootViewController.m",
    "chars": 3767,
    "preview": "//\n//  RootViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright (c)"
  },
  {
    "path": "Example/GONMarkupParserSample/RootViewController.xib",
    "chars": 3161,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/SampleViewController.h",
    "chars": 301,
    "preview": "//\n//  SampleViewController.h\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright ("
  },
  {
    "path": "Example/GONMarkupParserSample/SampleViewController.m",
    "chars": 1309,
    "preview": "//\n//  SampleViewController.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 10/11/14.\n//  Copyright ("
  },
  {
    "path": "Example/GONMarkupParserSample/SampleViewController.xib",
    "chars": 6217,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Example/GONMarkupParserSample/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Example/GONMarkupParserSample/main.m",
    "chars": 364,
    "preview": "//\n//  main.m\n//  GONMarkupParserSample\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  Copyright (c) 2014 Nicolas "
  },
  {
    "path": "Example/GONMarkupParserSample/samples.plist",
    "chars": 5945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Example/GONMarkupParserSample.xcodeproj/project.pbxproj",
    "chars": 69201,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Example/GONMarkupParserSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 166,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:GONMarkupParser"
  },
  {
    "path": "Example/GONMarkupParserSample.xcworkspace/contents.xcworkspacedata",
    "chars": 181,
    "preview": "<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:GONMarkupParserSample.xcodeproj'"
  },
  {
    "path": "Example/GONMarkupParserSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Example/GONMarkupParserSampleTests/GONMarkupParserSampleTests-Info.plist",
    "chars": 674,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Example/GONMarkupParserSampleTests/GONMarkupParserSampleTests.m",
    "chars": 705,
    "preview": "//\n//  GONMarkupParserSampleTests.m\n//  GONMarkupParserSampleTests\n//\n//  Created by Nicolas Goutaland on 25/06/14.\n//  "
  },
  {
    "path": "Example/GONMarkupParserSampleTests/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Example/PodFile",
    "chars": 183,
    "preview": "source 'https://github.com/CocoaPods/Specs.git'\n\nplatform :ios, '7.0'\n\nabstract_target 'defaults' do\n\tpod 'NSString+Colo"
  },
  {
    "path": "GONMarkupParser.podspec",
    "chars": 1413,
    "preview": "Pod::Spec.new do |s|\n  s.name         = \"GONMarkupParser\"\n  s.version      = \"0.8.2\"\n  s.summary      = \"NSAttributedStr"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 nicolasgoutaland\n\nPermission is hereby granted, free of charge, to any person "
  },
  {
    "path": "README.md",
    "chars": 20508,
    "preview": "# GONMarkupParser\nEasily build NSAttributedString from XML/HTML like strings.\n\n## Demo\n![ScreenShot](https://github.com/"
  }
]

About this extraction

This page contains the full source code of the nicolasgoutaland/GONMarkupParser GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 107 files (321.3 KB), approximately 88.7k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!