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
## [__0.8.1__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.1)
Fixed list alignment bug in iOS12
## [__0.8.0__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.8.0)
Improved Paragraph layout
Improved List Item layout
Added paragraph sample
Fixed a typo issue with paragraph class
## [__0.7.9__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.9)
Fixed bug in GONMarkupParserUtils
## [__0.7.8__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.8)
GONMarkupParserUtils optimisation
## [__0.7.7__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.7)
Fixed sample Podfile
## [__0.7.6__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.6)
Fixed a bug on NSParagraphStyle mutability
## [__0.7.5__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.5)
Fixed a bug on lists heading alignment
Fixed a bug on lists, with subitems not aligned
Added support for strong tag (yoohoo \o/)
## [__0.7.4__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.4)
Fixed (again -_-) new line character bug on lists
## [__0.7.3__](https://github.com/nicolasgoutaland/GONMarkupParser/releases/tag/0.7.3)
Fixed new line character bug on lists
## [__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 "
//
// Example :
// Attribute | Supported
// -----------------------------------
// | YES
// | YES
// | NO
// | NO
// | YES
// | YES
// | YES
// | NO
// | YES
// | 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 aligned text>
// right aligned text>
// center aligned text>
// justified aligned text>
// 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
//
// Link 1>
// Link to apple.com>
// 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
//
// 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
//
// text>
// text>
// 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
//
// text>
// 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
//
// This text will use current font, set to 18>
// This text will use Helvetica as font, using current font size>
// This text will use Helvetica, set to 18>
// 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 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
//
//
//
//
#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
//
// text>
// 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
//
// 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 characters, generating a new line
//
// Example
//
//
#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
//
// underline text>
// underline text, only for words>
// underline text with dashdot pattern>
// underline text with dashdot pattern, only for words>
// strikethrough text>
// strikethrough text with dashdot pattern>
// 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
//
//
// first item>
// second item>
// 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; iFirst paragraph
//
#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 . 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 )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 )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 and 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 )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 )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 , 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 " entities
[attributeValue replaceCharactersInRange:NSMakeRange(attributeValue.length - 1, 1) withString:@""];
[attributeValue replaceCharactersInRange:NSMakeRange(0, 1) withString:@""];
[attributeValue replaceOccurrencesOfString:@""" 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 @""
#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 = @{
@""" : @"\"",
@"&" : @"&",
@"'" : @"'",
@"<" : @"<",
@">" : @">",
@" " : @"\u00A0",
@"¡" : @"\u00A1",
@"¢" : @"\u00A2",
@"£" : @"\u00A3",
@"¤" : @"\u00A4",
@"¥" : @"\u00A5",
@"¦" : @"\u00A6",
@"§" : @"\u00A7",
@"¨" : @"\u00A8",
@"©" : @"\u00A9",
@"ª" : @"\u00AA",
@"«" : @"\u00AB",
@"¬" : @"\u00AC",
@"" : @"\u00AD",
@"®" : @"\u00AE",
@"¯" : @"\u00AF",
@"°" : @"\u00B0",
@"±" : @"\u00B1",
@"²" : @"\u00B2",
@"³" : @"\u00B3",
@"´" : @"\u00B4",
@"µ" : @"\u00B5",
@"¶" : @"\u00B6",
@"·" : @"\u00B7",
@"¸" : @"\u00B8",
@"¹" : @"\u00B9",
@"º" : @"\u00BA",
@"»" : @"\u00BB",
@"¼" : @"\u00BC",
@"½" : @"\u00BD",
@"¾" : @"\u00BE",
@"¿" : @"\u00BF",
@"À" : @"\u00C0",
@"Á" : @"\u00C1",
@"Â" : @"\u00C2",
@"Ã" : @"\u00C3",
@"Ä" : @"\u00C4",
@"Å" : @"\u00C5",
@"Æ" : @"\u00C6",
@"Ç" : @"\u00C7",
@"È" : @"\u00C8",
@"É" : @"\u00C9",
@"Ê" : @"\u00CA",
@"Ë" : @"\u00CB",
@"Ì" : @"\u00CC",
@"Í" : @"\u00CD",
@"Î" : @"\u00CE",
@"Ï" : @"\u00CF",
@"Ð" : @"\u00D0",
@"Ñ" : @"\u00D1",
@"Ò" : @"\u00D2",
@"Ó" : @"\u00D3",
@"Ô" : @"\u00D4",
@"Õ" : @"\u00D5",
@"Ö" : @"\u00D6",
@"×" : @"\u00D7",
@"Ø" : @"\u00D8",
@"Ù" : @"\u00D9",
@"Ú" : @"\u00DA",
@"Û" : @"\u00DB",
@"Ü" : @"\u00DC",
@"Ý" : @"\u00DD",
@"Þ" : @"\u00DE",
@"ß" : @"\u00DF",
@"à" : @"\u00E0",
@"á" : @"\u00E1",
@"â" : @"\u00E2",
@"ã" : @"\u00E3",
@"ä" : @"\u00E4",
@"å" : @"\u00E5",
@"æ" : @"\u00E6",
@"ç" : @"\u00E7",
@"è" : @"\u00E8",
@"é" : @"\u00E9",
@"ê" : @"\u00EA",
@"ë" : @"\u00EB",
@"ì" : @"\u00EC",
@"í" : @"\u00ED",
@"î" : @"\u00EE",
@"ï" : @"\u00EF",
@"ð" : @"\u00F0",
@"ñ" : @"\u00F1",
@"ò" : @"\u00F2",
@"ó" : @"\u00F3",
@"ô" : @"\u00F4",
@"õ" : @"\u00F5",
@"ö" : @"\u00F6",
@"÷" : @"\u00F7",
@"ø" : @"\u00F8",
@"ù" : @"\u00F9",
@"ú" : @"\u00FA",
@"û" : @"\u00FB",
@"ü" : @"\u00FC",
@"ý" : @"\u00FD",
@"þ" : @"\u00FE",
@"ÿ" : @"\u00FF",
@"Œ" : @"\u0152",
@"œ" : @"\u0153",
@"Š" : @"\u0160",
@"š" : @"\u0161",
@"Ÿ" : @"\u0178",
@"ƒ" : @"\u0192",
@"ˆ" : @"\u02C6",
@"˜" : @"\u02DC",
@"Α" : @"\u0391",
@"Β" : @"\u0392",
@"Γ" : @"\u0393",
@"Δ" : @"\u0394",
@"Ε" : @"\u0395",
@"Ζ" : @"\u0396",
@"Η" : @"\u0397",
@"Θ" : @"\u0398",
@"Ι" : @"\u0399",
@"Κ" : @"\u039A",
@"Λ" : @"\u039B",
@"Μ" : @"\u039C",
@"Ν" : @"\u039D",
@"Ξ" : @"\u039E",
@"Ο" : @"\u039F",
@"Π" : @"\u03A0",
@"Ρ" : @"\u03A1",
@"Σ" : @"\u03A3",
@"Τ" : @"\u03A4",
@"Υ" : @"\u03A5",
@"Φ" : @"\u03A6",
@"Χ" : @"\u03A7",
@"Ψ" : @"\u03A8",
@"Ω" : @"\u03A9",
@"α" : @"\u03B1",
@"β" : @"\u03B2",
@"γ" : @"\u03B3",
@"δ" : @"\u03B4",
@"ε" : @"\u03B5",
@"ζ" : @"\u03B6",
@"η" : @"\u03B7",
@"θ" : @"\u03B8",
@"ι" : @"\u03B9",
@"κ" : @"\u03BA",
@"λ" : @"\u03BB",
@"μ" : @"\u03BC",
@"ν" : @"\u03BD",
@"ξ" : @"\u03BE",
@"ο" : @"\u03BF",
@"π" : @"\u03C0",
@"ρ" : @"\u03C1",
@"ς" : @"\u03C2",
@"σ" : @"\u03C3",
@"τ" : @"\u03C4",
@"υ" : @"\u03C5",
@"φ" : @"\u03C6",
@"χ" : @"\u03C7",
@"ψ" : @"\u03C8",
@"ω" : @"\u03C9",
@"ϑ" : @"\u03D1",
@"ϒ" : @"\u03D2",
@"ϖ" : @"\u03D6",
@" " : @"\u2002",
@" " : @"\u2003",
@" " : @"\u2009",
@"" : @"\u200C",
@"" : @"\u200D",
@"" : @"\u200E",
@"" : @"\u200F",
@"–" : @"\u2013",
@"—" : @"\u2014",
@"‘" : @"\u2018",
@"’" : @"\u2019",
@"‚" : @"\u201A",
@"“" : @"\u201C",
@"”" : @"\u201D",
@"„" : @"\u201E",
@"†" : @"\u2020",
@"‡" : @"\u2021",
@"•" : @"\u2022",
@"…" : @"\u2026",
@"‰" : @"\u2030",
@"′" : @"\u2032",
@"″" : @"\u2033",
@"‹" : @"\u2039",
@"›" : @"\u203A",
@"‾" : @"\u203E",
@"⁄" : @"\u2044",
@"€" : @"\u20AC",
@"ℑ" : @"\u2111",
@"℘" : @"\u2118",
@"ℜ" : @"\u211C",
@"™" : @"\u2122",
@"ℵ" : @"\u2135",
@"←" : @"\u2190",
@"↑" : @"\u2191",
@"→" : @"\u2192",
@"↓" : @"\u2193",
@"↔" : @"\u2194",
@"↵" : @"\u21B5",
@"⇐" : @"\u21D0",
@"⇑" : @"\u21D1",
@"⇒" : @"\u21D2",
@"⇓" : @"\u21D3",
@"⇔" : @"\u21D4",
@"∀" : @"\u2200",
@"∂" : @"\u2202",
@"∃" : @"\u2203",
@"∅" : @"\u2205",
@"∇" : @"\u2207",
@"∈" : @"\u2208",
@"∉" : @"\u2209",
@"∋" : @"\u220B",
@"∏" : @"\u220F",
@"∑" : @"\u2211",
@"−" : @"\u2212",
@"∗" : @"\u2217",
@"√" : @"\u221A",
@"∝" : @"\u221D",
@"∞" : @"\u221E",
@"∠" : @"\u2220",
@"∧" : @"\u2227",
@"∨" : @"\u2228",
@"∩" : @"\u2229",
@"∪" : @"\u222A",
@"∫" : @"\u222B",
@"∴" : @"\u2234",
@"∼" : @"\u223C",
@"≅" : @"\u2245",
@"≈" : @"\u2248",
@"≠" : @"\u2260",
@"≡" : @"\u2261",
@"≤" : @"\u2264",
@"≥" : @"\u2265",
@"⊂" : @"\u2282",
@"⊃" : @"\u2283",
@"⊄" : @"\u2284",
@"⊆" : @"\u2286",
@"⊇" : @"\u2287",
@"⊕" : @"\u2295",
@"⊗" : @"\u2297",
@"⊥" : @"\u22A5",
@"⋅" : @"\u22C5",
@"⋮" : @"\u22EE",
@"⌈" : @"\u2308",
@"⌉" : @"\u2309",
@"⌊" : @"\u230A",
@"⌋" : @"\u230B",
@"〈" : @"\u2329",
@"〉" : @"\u232A",
@"◊" : @"\u25CA",
@"♠" : @"\u2660",
@"♣" : @"\u2663",
@"♥" : @"\u2665",
@"♦" : @"\u2666",
@" " : @" ",
@"!" : @"!",
@""" : @"\"",
@"#" : @"#",
@"$" : @"$",
@"%" : @"%",
@"&" : @"&",
@"'" : @"'",
@"(" : @"(",
@")" : @")",
@"*" : @"*",
@"+" : @"+",
@"," : @",",
@"-" : @"-",
@"." : @".",
@"/" : @"/",
@"0" : @"0",
@"1" : @"1",
@"2" : @"2",
@"3" : @"3",
@"4" : @"4",
@"5" : @"5",
@"6" : @"6",
@"7" : @"7",
@"8" : @"8",
@"9" : @"9",
@":" : @":",
@";" : @";",
@"<" : @"<",
@"=" : @"=",
@">" : @">",
@"?" : @"?",
@"@" : @"@",
@"A" : @"A",
@"B" : @"B",
@"C" : @"C",
@"D" : @"D",
@"E" : @"E",
@"F" : @"F",
@"G" : @"G",
@"H" : @"H",
@"I" : @"I",
@"J" : @"J",
@"K" : @"K",
@"L" : @"L",
@"M" : @"M",
@"N" : @"N",
@"O" : @"O",
@"P" : @"P",
@"Q" : @"Q",
@"R" : @"R",
@"S" : @"S",
@"T" : @"T",
@"U" : @"U",
@"V" : @"V",
@"W" : @"W",
@"X" : @"X",
@"Y" : @"Y",
@"Z" : @"Z",
@"[" : @"[",
@"\" : @"\\",
@"]" : @"]",
@"^" : @"^",
@"_" : @"_",
@"`" : @"`",
@"a" : @"a",
@"b" : @"b",
@"c" : @"c",
@"d" : @"d",
@"e" : @"e",
@"f" : @"f",
@"g" : @"g",
@"h" : @"h",
@"i" : @"i",
@"j" : @"j",
@"k" : @"k",
@"l" : @"l",
@"m" : @"m",
@"n" : @"n",
@"o" : @"o",
@"p" : @"p",
@"q" : @"q",
@"r" : @"r",
@"s" : @"s",
@"t" : @"t",
@"u" : @"u",
@"v" : @"v",
@"w" : @"w",
@"x" : @"x",
@"y" : @"y",
@"z" : @"z",
@"{" : @"{",
@"|" : @"|",
@"}" : @"}",
@"~" : @"~",
@"" : @"\u0127",
@"" : @"\u0128",
@"" : @"\u0129",
@"" : @"\u0130",
@"" : @"\u0131",
@"" : @"\u0132",
@"
" : @"\u0133",
@"" : @"\u0134",
@"" : @"\u0135",
@"" : @"\u0136",
@"" : @"\u0137",
@"" : @"\u0138",
@"" : @"\u0139",
@"" : @"\u0140",
@"" : @"\u0141",
@"" : @"\u0142",
@"" : @"\u0143",
@"" : @"\u0144",
@"" : @"\u0145",
@"" : @"\u0146",
@"" : @"\u0147",
@"" : @"\u0148",
@"" : @"\u0149",
@"" : @"\u0150",
@"" : @"\u0151",
@"" : @"\u0152",
@"" : @"\u0153",
@"" : @"\u0154",
@"" : @"\u0155",
@"" : @"\u0156",
@"" : @"\u0157",
@"" : @"\u0158",
@"" : @"\u0159",
@" " : @"\u00A0",
@"¡" : @"\u00A1",
@"¢" : @"\u00A2",
@"£" : @"\u00A3",
@"¤" : @"\u00A4",
@"¥" : @"\u00A5",
@"¦" : @"\u00A6",
@"§" : @"\u00A7",
@"¨" : @"\u00A8",
@"©" : @"\u00A9",
@"ª" : @"\u00AA",
@"«" : @"\u00AB",
@"¬" : @"\u00AC",
@"" : @"\u00AD",
@"®" : @"\u00AE",
@"¯" : @"\u00AF",
@"°" : @"\u00B0",
@"±" : @"\u00B1",
@"²" : @"\u00B2",
@"³" : @"\u00B3",
@"´" : @"\u00B4",
@"µ" : @"\u00B5",
@"¶" : @"\u00B6",
@"·" : @"\u00B7",
@"¸" : @"\u00B8",
@"¹" : @"\u00B9",
@"º" : @"\u00BA",
@"»" : @"\u00BB",
@"¼" : @"\u00BC",
@"½" : @"\u00BD",
@"¾" : @"\u00BE",
@"¿" : @"\u00BF",
@"À" : @"\u00C0",
@"Á" : @"\u00C1",
@"Â" : @"\u00C2",
@"Ã" : @"\u00C3",
@"Ä" : @"\u00C4",
@"Å" : @"\u00C5",
@"Æ" : @"\u00C6",
@"Ç" : @"\u00C7",
@"È" : @"\u00C8",
@"É" : @"\u00C9",
@"Ê" : @"\u00CA",
@"Ë" : @"\u00CB",
@"Ì" : @"\u00CC",
@"Í" : @"\u00CD",
@"Î" : @"\u00CE",
@"Ï" : @"\u00CF",
@"Ð" : @"\u00D0",
@"Ñ" : @"\u00D1",
@"Ò" : @"\u00D2",
@"Ó" : @"\u00D3",
@"Ô" : @"\u00D4",
@"Õ" : @"\u00D5",
@"Ö" : @"\u00D6",
@"×" : @"\u00D7",
@"Ø" : @"\u00D8",
@"Ù" : @"\u00D9",
@"Ú" : @"\u00DA",
@"Û" : @"\u00DB",
@"Ü" : @"\u00DC",
@"Ý" : @"\u00DD",
@"Þ" : @"\u00DE",
@"ß" : @"\u00DF",
@"à" : @"\u00E0",
@"á" : @"\u00E1",
@"â" : @"\u00E2",
@"ã" : @"\u00E3",
@"ä" : @"\u00E4",
@"å" : @"\u00E5",
@"æ" : @"\u00E6",
@"ç" : @"\u00E7",
@"è" : @"\u00E8",
@"é" : @"\u00E9",
@"ê" : @"\u00EA",
@"ë" : @"\u00EB",
@"ì" : @"\u00EC",
@"í" : @"\u00ED",
@"î" : @"\u00EE",
@"ï" : @"\u00EF",
@"ð" : @"\u00F0",
@"ñ" : @"\u00F1",
@"ò" : @"\u00F2",
@"ó" : @"\u00F3",
@"ô" : @"\u00F4",
@"õ" : @"\u00F5",
@"ö" : @"\u00F6",
@"÷" : @"\u00F7",
@"ø" : @"\u00F8",
@"ù" : @"\u00F9",
@"ú" : @"\u00FA",
@"û" : @"\u00FB",
@"ü" : @"\u00FC",
@"ý" : @"\u00FD",
@"þ" : @"\u00FE",
@"ÿ" : @"\u00FF",
@"ƒ" : @"\u0192",
@"Α" : @"\u0391",
@"Β" : @"\u0392",
@"Γ" : @"\u0393",
@"Δ" : @"\u0394",
@"Ε" : @"\u0395",
@"Ζ" : @"\u0396",
@"Η" : @"\u0397",
@"Θ" : @"\u0398",
@"Ι" : @"\u0399",
@"Κ" : @"\u039A",
@"Λ" : @"\u039B",
@"Μ" : @"\u039C",
@"Ν" : @"\u039D",
@"Ξ" : @"\u039E",
@"Ο" : @"\u039F",
@"Π" : @"\u03A0",
@"Ρ" : @"\u03A1",
@"Σ" : @"\u03A3",
@"Τ" : @"\u03A4",
@"Υ" : @"\u03A5",
@"Φ" : @"\u03A6",
@"Χ" : @"\u03A7",
@"Ψ" : @"\u03A8",
@"Ω" : @"\u03A9",
@"α" : @"\u03B1",
@"β" : @"\u03B2",
@"γ" : @"\u03B3",
@"δ" : @"\u03B4",
@"ε" : @"\u03B5",
@"ζ" : @"\u03B6",
@"η" : @"\u03B7",
@"θ" : @"\u03B8",
@"ι" : @"\u03B9",
@"κ" : @"\u03BA",
@"λ" : @"\u03BB",
@"μ" : @"\u03BC",
@"ν" : @"\u03BD",
@"ξ" : @"\u03BE",
@"ο" : @"\u03BF",
@"π" : @"\u03C0",
@"ρ" : @"\u03C1",
@"ς" : @"\u03C2",
@"σ" : @"\u03C3",
@"τ" : @"\u03C4",
@"υ" : @"\u03C5",
@"φ" : @"\u03C6",
@"χ" : @"\u03C7",
@"ψ" : @"\u03C8",
@"ω" : @"\u03C9",
@"ϑ" : @"\u03D1",
@"ϒ" : @"\u03D2",
@"ϖ" : @"\u03D6",
@"•" : @"\u2022",
@"…" : @"\u2026",
@"′" : @"\u2032",
@"″" : @"\u2033",
@"‾" : @"\u203E",
@"⁄" : @"\u2044",
@"℘" : @"\u2118",
@"ℑ" : @"\u2111",
@"ℜ" : @"\u211C",
@"™" : @"\u2122",
@"ℵ" : @"\u2135",
@"←" : @"\u2190",
@"↑" : @"\u2191",
@"→" : @"\u2192",
@"↓" : @"\u2193",
@"↔" : @"\u2194",
@"↵" : @"\u21B5",
@"⇐" : @"\u21D0",
@"⇑" : @"\u21D1",
@"⇒" : @"\u21D2",
@"⇓" : @"\u21D3",
@"⇔" : @"\u21D4",
@"∀" : @"\u2200",
@"∂" : @"\u2202",
@"∃" : @"\u2203",
@"∅" : @"\u2205",
@"∇" : @"\u2207",
@"∈" : @"\u2208",
@"∉" : @"\u2209",
@"∋" : @"\u220B",
@"∏" : @"\u220F",
@"∑" : @"\u2211",
@"−" : @"\u2212",
@"∗" : @"\u2217",
@"√" : @"\u221A",
@"∝" : @"\u221D",
@"∞" : @"\u221E",
@"∠" : @"\u2220",
@"∧" : @"\u2227",
@"∨" : @"\u2228",
@"∩" : @"\u2229",
@"∪" : @"\u222A",
@"∫" : @"\u222B",
@"∴" : @"\u2234",
@"∼" : @"\u223C",
@"≅" : @"\u2245",
@"≈" : @"\u2248",
@"≠" : @"\u2260",
@"≡" : @"\u2261",
@"≤" : @"\u2264",
@"≥" : @"\u2265",
@"⊂" : @"\u2282",
@"⊃" : @"\u2283",
@"⊄" : @"\u2284",
@"⊆" : @"\u2286",
@"⊇" : @"\u2287",
@"⊕" : @"\u2295",
@"⊗" : @"\u2297",
@"⊥" : @"\u22A5",
@"⋅" : @"\u22C5",
@"⌈" : @"\u2308",
@"⌉" : @"\u2309",
@"⌊" : @"\u230A",
@"⌋" : @"\u230B",
@"〈" : @"\u2329",
@"〉" : @"\u232A",
@"◊" : @"\u25CA",
@"♠" : @"\u2660",
@"♣" : @"\u2663",
@"♥" : @"\u2665",
@"♦" : @"\u2666",
@" " : @" ",
@"!" : @"!",
@""" : @"\"",
@"#" : @"#",
@"$" : @"$",
@"%" : @"%",
@"&" : @"&",
@"'" : @"'",
@"(" : @"(",
@")" : @")",
@"*" : @"*",
@"+" : @"+",
@"," : @",",
@"-" : @"-",
@"." : @".",
@"/" : @"/",
@"0" : @"0",
@"1" : @"1",
@"2" : @"2",
@"3" : @"3",
@"4" : @"4",
@"5" : @"5",
@"6" : @"6",
@"7" : @"7",
@"8" : @"8",
@"9" : @"9",
@":" : @":",
@";" : @";",
@"<" : @"<",
@"=" : @"=",
@">" : @">",
@"?" : @"?",
@"@" : @"@",
@"A" : @"A",
@"B" : @"B",
@"C" : @"C",
@"D" : @"D",
@"E" : @"E",
@"F" : @"F",
@"G" : @"G",
@"H" : @"H",
@"I" : @"I",
@"J" : @"J",
@"K" : @"K",
@"L" : @"L",
@"M" : @"M",
@"N" : @"N",
@"O" : @"O",
@"P" : @"P",
@"Q" : @"Q",
@"R" : @"R",
@"S" : @"S",
@"T" : @"T",
@"U" : @"U",
@"V" : @"V",
@"W" : @"W",
@"X" : @"X",
@"Y" : @"Y",
@"Z" : @"Z",
@"[" : @"[",
@"\" : @"\\",
@"]" : @"]",
@"^" : @"^",
@"_" : @"_",
@"`" : @"`",
@"a" : @"a",
@"b" : @"b",
@"c" : @"c",
@"d" : @"d",
@"e" : @"e",
@"f" : @"f",
@"g" : @"g",
@"h" : @"h",
@"i" : @"i",
@"j" : @"j",
@"k" : @"k",
@"l" : @"l",
@"m" : @"m",
@"n" : @"n",
@"o" : @"o",
@"p" : @"p",
@"q" : @"q",
@"r" : @"r",
@"s" : @"s",
@"t" : @"t",
@"u" : @"u",
@"v" : @"v",
@"w" : @"w",
@"x" : @"x",
@"y" : @"y",
@"z" : @"z",
@"{" : @"{",
@"|" : @"|",
@"}" : @"}",
@"~" : @"~",
@"" : @"\u0127",
@"" : @"\u0128",
@"" : @"\u0129",
@"" : @"\u0130",
@"" : @"\u0131",
@"" : @"\u0132",
@"
" : @"\u0133",
@"" : @"\u0134",
@"" : @"\u0135",
@"" : @"\u0136",
@"" : @"\u0137",
@"" : @"\u0138",
@"" : @"\u0139",
@"" : @"\u0140",
@"" : @"\u0141",
@"" : @"\u0142",
@"" : @"\u0143",
@"" : @"\u0144",
@"" : @"\u0145",
@"" : @"\u0146",
@"" : @"\u0147",
@"" : @"\u0148",
@"" : @"\u0149",
@"" : @"\u0150",
@"" : @"\u0151",
@"" : @"\u0152",
@"" : @"\u0153",
@"" : @"\u0154",
@"" : @"\u0155",
@"" : @"\u0156",
@"" : @"\u0157",
@"" : @"\u0158",
@"" : @"\u0159",
@" " : @"\u00A0",
@"¡" : @"\u00A1",
@"¢" : @"\u00A2",
@"£" : @"\u00A3",
@"¤" : @"\u00A4",
@"¥" : @"\u00A5",
@"¦" : @"\u00A6",
@"§" : @"\u00A7",
@"¨" : @"\u00A8",
@"©" : @"\u00A9",
@"ª" : @"\u00AA",
@"«" : @"\u00AB",
@"¬" : @"\u00AC",
@"" : @"\u00AD",
@"®" : @"\u00AE",
@"¯" : @"\u00AF",
@"°" : @"\u00B0",
@"±" : @"\u00B1",
@"²" : @"\u00B2",
@"³" : @"\u00B3",
@"´" : @"\u00B4",
@"µ" : @"\u00B5",
@"¶" : @"\u00B6",
@"·" : @"\u00B7",
@"¸" : @"\u00B8",
@"¹" : @"\u00B9",
@"º" : @"\u00BA",
@"»" : @"\u00BB",
@"¼" : @"\u00BC",
@"½" : @"\u00BD",
@"¾" : @"\u00BE",
@"¿" : @"\u00BF",
@"À" : @"\u00C0",
@"Á" : @"\u00C1",
@"Â" : @"\u00C2",
@"Ã" : @"\u00C3",
@"Ä" : @"\u00C4",
@"Å" : @"\u00C5",
@"Æ" : @"\u00C6",
@"Ç" : @"\u00C7",
@"È" : @"\u00C8",
@"É" : @"\u00C9",
@"Ê" : @"\u00CA",
@"Ë" : @"\u00CB",
@"Ì" : @"\u00CC",
@"Í" : @"\u00CD",
@"Î" : @"\u00CE",
@"Ï" : @"\u00CF",
@"Ð" : @"\u00D0",
@"Ñ" : @"\u00D1",
@"Ò" : @"\u00D2",
@"Ó" : @"\u00D3",
@"Ô" : @"\u00D4",
@"Õ" : @"\u00D5",
@"Ö" : @"\u00D6",
@"×" : @"\u00D7",
@"Ø" : @"\u00D8",
@"Ù" : @"\u00D9",
@"Ú" : @"\u00DA",
@"Û" : @"\u00DB",
@"Ü" : @"\u00DC",
@"Ý" : @"\u00DD",
@"Þ" : @"\u00DE",
@"ß" : @"\u00DF",
@"à" : @"\u00E0",
@"á" : @"\u00E1",
@"â" : @"\u00E2",
@"ã" : @"\u00E3",
@"ä" : @"\u00E4",
@"å" : @"\u00E5",
@"æ" : @"\u00E6",
@"ç" : @"\u00E7",
@"è" : @"\u00E8",
@"é" : @"\u00E9",
@"ê" : @"\u00EA",
@"ë" : @"\u00EB",
@"ì" : @"\u00EC",
@"í" : @"\u00ED",
@"î" : @"\u00EE",
@"ï" : @"\u00EF",
@"ð" : @"\u00F0",
@"ñ" : @"\u00F1",
@"ò" : @"\u00F2",
@"ó" : @"\u00F3",
@"ô" : @"\u00F4",
@"õ" : @"\u00F5",
@"ö" : @"\u00F6",
@"÷" : @"\u00F7",
@"ø" : @"\u00F8",
@"ù" : @"\u00F9",
@"ú" : @"\u00FA",
@"û" : @"\u00FB",
@"ü" : @"\u00FC",
@"ý" : @"\u00FD",
@"þ" : @"\u00FE",
@"ÿ" : @"\u00FF",
@"ƒ" : @"\u0192",
@"Α" : @"\u0391",
@"Β" : @"\u0392",
@"Γ" : @"\u0393",
@"Δ" : @"\u0394",
@"Ε" : @"\u0395",
@"Ζ" : @"\u0396",
@"Η" : @"\u0397",
@"Θ" : @"\u0398",
@"Ι" : @"\u0399",
@"Κ" : @"\u039A",
@"Λ" : @"\u039B",
@"Μ" : @"\u039C",
@"Ν" : @"\u039D",
@"Ξ" : @"\u039E",
@"Ο" : @"\u039F",
@"Π" : @"\u03A0",
@"Ρ" : @"\u03A1",
@"Σ" : @"\u03A3",
@"Τ" : @"\u03A4",
@"Υ" : @"\u03A5",
@"Φ" : @"\u03A6",
@"Χ" : @"\u03A7",
@"Ψ" : @"\u03A8",
@"Ω" : @"\u03A9",
@"α" : @"\u03B1",
@"β" : @"\u03B2",
@"γ" : @"\u03B3",
@"δ" : @"\u03B4",
@"ε" : @"\u03B5",
@"ζ" : @"\u03B6",
@"η" : @"\u03B7",
@"θ" : @"\u03B8",
@"ι" : @"\u03B9",
@"κ" : @"\u03BA",
@"λ" : @"\u03BB",
@"μ" : @"\u03BC",
@"ν" : @"\u03BD",
@"ξ" : @"\u03BE",
@"ο" : @"\u03BF",
@"π" : @"\u03C0",
@"ρ" : @"\u03C1",
@"ς" : @"\u03C2",
@"σ" : @"\u03C3",
@"τ" : @"\u03C4",
@"υ" : @"\u03C5",
@"φ" : @"\u03C6",
@"χ" : @"\u03C7",
@"ψ" : @"\u03C8",
@"ω" : @"\u03C9",
@"ϑ" : @"\u03D1",
@"ϒ" : @"\u03D2",
@"ϖ" : @"\u03D6",
@"•" : @"\u2022",
@"…" : @"\u2026",
@"′" : @"\u2032",
@"″" : @"\u2033",
@"‾" : @"\u203E",
@"⁄" : @"\u2044",
@"℘" : @"\u2118",
@"ℑ" : @"\u2111",
@"ℜ" : @"\u211C",
@"™" : @"\u2122",
@"ℵ" : @"\u2135",
@"←" : @"\u2190",
@"↑" : @"\u2191",
@"→" : @"\u2192",
@"↓" : @"\u2193",
@"↔" : @"\u2194",
@"↵" : @"\u21B5",
@"⇐" : @"\u21D0",
@"⇑" : @"\u21D1",
@"⇒" : @"\u21D2",
@"⇓" : @"\u21D3",
@"⇔" : @"\u21D4",
@"∀" : @"\u2200",
@"∂" : @"\u2202",
@"∃" : @"\u2203",
@"∅" : @"\u2205",
@"∇" : @"\u2207",
@"∈" : @"\u2208",
@"∉" : @"\u2209",
@"∋" : @"\u220B",
@"∏" : @"\u220F",
@"∑" : @"\u2211",
@"−" : @"\u2212",
@"∗" : @"\u2217",
@"√" : @"\u221A",
@"∝" : @"\u221D",
@"∞" : @"\u221E",
@"∠" : @"\u2220",
@"∧" : @"\u2227",
@"∨" : @"\u2228",
@"∩" : @"\u2229",
@"∪" : @"\u222A",
@"∫" : @"\u222B",
@"∴" : @"\u2234",
@"∼" : @"\u223C",
@"≅" : @"\u2245",
@"≈" : @"\u2248",
@"≠" : @"\u2260",
@"≡" : @"\u2261",
@"≤" : @"\u2264",
@"≥" : @"\u2265",
@"⊂" : @"\u2282",
@"⊃" : @"\u2283",
@"⊄" : @"\u2284",
@"⊆" : @"\u2286",
@"⊇" : @"\u2287",
@"⊕" : @"\u2295",
@"⊗" : @"\u2297",
@"⊥" : @"\u22A5",
@"⋅" : @"\u22C5",
@"⌈" : @"\u2308",
@"⌉" : @"\u2309",
@"⌊" : @"\u230A",
@"⌋" : @"\u230B",
@"〈" : @"\u2329",
@"〉" : @"\u232A",
@"◊" : @"\u25CA",
@"♠" : @"\u2660",
@"♣" : @"\u2663",
@"♥" : @"\u2665",
@"♦" : @"\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 :
// this text is redred strong yellow default red strong 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
//
// 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
//
// superscripted text>
// 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
@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
@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 this text should be red small black small .
This one should be black
Using a new font, using its full name (Didot-Italic) >
yellow protected \o/ yell>ow/>
Let me add some Custom tag here>
Yep, that was big.
You can also change text alignment
Centered>
Left>
Right>
Justified paragraph Lorem ipsum dolor sit amet, consectetur adipiscing elit. In rhoncus diam nec sem consequat tincidunt. Etiam eu lacus a lorem cursus sodales et nec sapien. >
Natural>
Text size can also be incremented or decremented, 1 per 1, or specifying a value./>
This text will be written using a registered font on your parser, allowing to use it specifying a code, instead of its full name.>
Another Custom tag here, but with a full protected section , pretty cool huh ?>
And now, an unordered list
Item
very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item
very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item
very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong Item with a new line inside.....
Item
Item
and an ordered list
Item 1
Item 1
Item 1
Item 1 (New sub list)
Item 2
Item 3
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
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange>
method to handle user interaction.
Link example ;)/>
Finally, you can set bold text>, italic text> or both>>
Underline> and strikethrough> text is also available.
You can customize line pattern>, style> and limit style to words only>.
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
================================================
================================================
FILE: Example/GONMarkupParserSample/DefaultConfigurationViewController.h
================================================
//
// DefaultConfigurationViewController.h
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 19/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
@interface DefaultConfigurationViewController : UIViewController
@end
================================================
FILE: Example/GONMarkupParserSample/DefaultConfigurationViewController.m
================================================
//
// DefaultConfigurationViewController.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 19/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "DefaultConfigurationViewController.h"
@interface DefaultConfigurationViewController ()
// Outlets
@property (nonatomic, weak) IBOutlet UILabel *inputLabel;
@property (nonatomic, weak) IBOutlet UILabel *resultLabel;
@end
@implementation DefaultConfigurationViewController
#pragma mark - View management
- (void)viewDidLoad
{
[super viewDidLoad];
// Set a default configuration
_inputLabel.textColor = [@"red" representedColor];
_inputLabel.textAlignment = NSTextAlignmentRight;
_resultLabel.textColor = [@"red" representedColor];
_resultLabel.textAlignment = NSTextAlignmentRight;
// NSString
NSString *inputText = @"This label is red by default, and default text will be displayed red.>Text alignment is also set by label here.>This allows you to configure style in IB for example, without setting a default parser configuration.>";
// Configure labels
_inputLabel.text = inputText;
[_resultLabel setMarkedUpText:inputText
parser:[GONMarkupParser defaultMarkupParser]];
}
@end
================================================
FILE: Example/GONMarkupParserSample/DefaultConfigurationViewController.xib
================================================
================================================
FILE: Example/GONMarkupParserSample/GONMarkupParserSample-Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleDisplayName
${PRODUCT_NAME}
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1.0
LSRequiresIPhoneOS
NSMainNibFile
MainWindow
UIRequiredDeviceCapabilities
armv7
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
================================================
FILE: Example/GONMarkupParserSample/GONMarkupParserSample-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import
#import
#import "NSString+Color.h"
#import
#import "LazyProperty.h"
#import "GONMarkupParser_All.h"
#endif
================================================
FILE: Example/GONMarkupParserSample/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: Example/GONMarkupParserSample/Images.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "splash@2x.png",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "retina4",
"filename" : "splash@2x-1.png",
"minimum-system-version" : "7.0",
"orientation" : "portrait",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/GONMarkupParserSample/MainWindow.xib
================================================
================================================
FILE: Example/GONMarkupParserSample/PlaygroundViewController.h
================================================
//
// PlaygroundViewController.h
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
@interface PlaygroundViewController : UIViewController
@end
================================================
FILE: Example/GONMarkupParserSample/PlaygroundViewController.m
================================================
//
// PlaygroundViewController.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "PlaygroundViewController.h"
#import "ResultViewController.h"
@interface PlaygroundViewController ()
// View controllers
@property (nonatomic, strong) ResultViewController *resultViewController;
// Outlets
@property (nonatomic, weak ) IBOutlet UITextView *inputTextView;
@property (nonatomic, strong) IBOutlet UIBarButtonItem *validateButton;
@end
@implementation PlaygroundViewController
#pragma mark - View management
- (void)viewDidLoad
{
[super viewDidLoad];
// Title
self.title = @"Playground";
self.navigationItem.rightBarButtonItem = _validateButton;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_inputTextView becomeFirstResponder];
}
#pragma mark - UI Actions
- (IBAction)showResult
{
// Parse string
self.resultViewController.resultAttributedString = [[GONMarkupParserManager sharedParser] attributedStringFromString:_inputTextView.text];
// Show results
[self.navigationController pushViewController:self.resultViewController
animated:YES];
}
LAZY_PROPERTY(resultViewController);
@end
================================================
FILE: Example/GONMarkupParserSample/PlaygroundViewController.xib
================================================
================================================
FILE: Example/GONMarkupParserSample/ResultViewController.h
================================================
//
// ResultViewController.h
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 25/06/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
@interface ResultViewController : UIViewController
@property (nonatomic, strong) NSAttributedString *resultAttributedString;
@end
================================================
FILE: Example/GONMarkupParserSample/ResultViewController.m
================================================
//
// ResultViewController.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 25/06/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "ResultViewController.h"
@interface ResultViewController ()
// Outlets
@property (nonatomic, weak) IBOutlet UITextView *resultTextView;
@end
@implementation ResultViewController
#pragma mark - View management
- (void)viewDidLoad
{
[super viewDidLoad];
// Title
self.title = @"Result";
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Affect result string
_resultTextView.attributedText = _resultAttributedString;
}
#pragma mark - UITextViewDelegate methods
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
// Show link value
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Information"
message:[URL description]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
@end
================================================
FILE: Example/GONMarkupParserSample/ResultViewController.xib
================================================
Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.
================================================
FILE: Example/GONMarkupParserSample/RootViewController.h
================================================
//
// RootViewController.h
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
@interface RootViewController : UIViewController
@end
================================================
FILE: Example/GONMarkupParserSample/RootViewController.m
================================================
//
// RootViewController.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "RootViewController.h"
#import "SampleViewController.h"
#define SAMPLES_DATA_FILE @"samples"
#define TITLE_KEY @"title"
#define SAMPLE_KEY @"sample"
#define BACKGROUND_KEY @"background"
#define VIEW_CONTROLLER_KEY @"viewController"
@interface RootViewController ()
// Data
@property (nonatomic, strong) NSArray *samplesData;
@property (nonatomic, strong) NSMutableDictionary *viewControllerCache;
@end
@implementation RootViewController
#pragma mark - Constructor
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
self.title = @"Samples list";
}
return self;
}
#pragma mark - View management
- (void)viewDidLoad {
[super viewDidLoad];
// Load data
_samplesData = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:SAMPLES_DATA_FILE
ofType:@"plist"]];
}
#pragma mark - UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *sampleData = [_samplesData objectAtIndex:indexPath.row];
// Set sample title
cell.textLabel.text = [sampleData objectForKey:TITLE_KEY];
// Set sample cell background color
cell.backgroundColor = [[sampleData objectForKey:BACKGROUND_KEY] representedColor];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *viewController;
NSString *viewControllerClassName = [[_samplesData objectAtIndex:indexPath.row] objectForKey:VIEW_CONTROLLER_KEY];
if (viewControllerClassName.length)
{
// Check cache
viewController = [_viewControllerCache objectForKey:viewControllerClassName];
if (!viewController)
{
// Instantiate
viewController = [[NSClassFromString(viewControllerClassName) alloc] init];
// Hold reference for reuse
[_viewControllerCache setObject:viewController
forKey:viewControllerClassName];
}
}
else
{
// Configure sample view controller
SampleViewController *sampleViewController = [[SampleViewController alloc] init];
sampleViewController.sampleText = [[_samplesData objectAtIndex:indexPath.row] objectForKey:SAMPLE_KEY];
viewController = sampleViewController;
}
// Push associated view controller
[self.navigationController pushViewController:viewController
animated:YES];
// Deselect row
[tableView deselectRowAtIndexPath:indexPath
animated:YES];
}
#pragma mark - UITableViewDatasource methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[UITableViewCell description]];
if (!cell)
{
// Load cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:[UITableViewCell description]];
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _samplesData.count;
}
#pragma mark - Memory
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[_viewControllerCache removeAllObjects];
}
@end
================================================
FILE: Example/GONMarkupParserSample/RootViewController.xib
================================================
================================================
FILE: Example/GONMarkupParserSample/SampleViewController.h
================================================
//
// SampleViewController.h
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
@interface SampleViewController : UIViewController
@property (nonatomic, strong) NSString *sampleText;
@end
================================================
FILE: Example/GONMarkupParserSample/SampleViewController.m
================================================
//
// SampleViewController.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 10/11/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import "SampleViewController.h"
@interface SampleViewController ()
// Outlets
@property (nonatomic, weak) IBOutlet UITextView *inputTextView;
@property (nonatomic, weak) IBOutlet UITextView *resultTextView;
@end
@implementation SampleViewController
#pragma mark - View management
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Configure textviews
_inputTextView.text = _sampleText;
[_resultTextView setMarkedUpText:_sampleText
parser:[GONMarkupParser defaultMarkupParser]];
}
#pragma mark - UITextViewDelegate methods
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
// Show link value
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Information"
message:[URL description]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
@end
================================================
FILE: Example/GONMarkupParserSample/SampleViewController.xib
================================================
Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.
Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.
================================================
FILE: Example/GONMarkupParserSample/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: Example/GONMarkupParserSample/main.m
================================================
//
// main.m
// GONMarkupParserSample
//
// Created by Nicolas Goutaland on 25/06/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: Example/GONMarkupParserSample/samples.plist
================================================
title
Playground
viewController
PlaygroundViewController
background
eeeeee
title
Complex example
viewController
ComplexExampleViewController
background
eeeeee
title
Invalid format
sample
<br>><<body>This is expected string<font color=\">Color</xxxx></body><
background
D91E18
title
Anchor
sample
<a href="Hello">A simple link</>.
<a href="http://www.apple.com">An internet link</>.
background
ABB7B7
title
Bold, Italic, Strong, Sup, Sub
sample
This text is <b>in bold</><br/>This text is <i>in italic</><br/>This text is <strong>in strong</><br/>This text is <sup>superscripted</><br/>This text is <sub>subscripted</><br/><b><i>This text is bold italic<//>
background
ABB7B7
title
Color
sample
Default, <color value="red">red</>, <color value="blue">blue</>, <color value="magenta">magenta</>, <color value="FF5533">FF5533</>
background
ABB7B7
title
Default label configuration
viewController
DefaultConfigurationViewController
background
ABB7B7
title
Font
sample
Default<br/><font size="30">Size to 30</><br/><font name="Didot">font name Didot</><br/><font name="AmericanTypewriter" color="red" size="20">font name AmericanTypewriter, size 20, red</>
background
ABB7B7
title
Inc / Dec
sample
Default size, <inc>inc 1 <inc> inc 1 <inc value="10">inc 10<//> <dec>dec 1 <dec> dec 1 <dec value="10">dec 10<//>
background
ABB7B7
title
Ordered list
sample
This text is a list.<br/><ol><li>First item</li><li>Second <b>bold</> item </><ol><li>Second.first</><li>Second.second</><ol><li>Third</><ol><li>Fourth</li></></></><li>Third item</></>
background
ABB7B7
title
Paragraph
sample
No paragraph<p>first paragraph</p><p>second one</p><br/>Still no paragraph
background
ABB7B7
title
Reset
sample
<font size="20"><color value="red"><right>Reset tag allows you to<br/><reset><center>protect</></reset><br/> certains parts of your text, making it<br/><reset><color value="green"> easier</></><br/> to be reconfigured.<//>
background
ABB7B7
title
Strikethrough text
sample
<strike>Text strikethrough</>.
<strike word="true">Text strikethrough</>.
<strike word="true" pattern="dashdotdot" style="double" color="green">Text strikethrough</>.
background
ABB7B7
title
Text alignment
sample
<left>Left</><br/><center>center</><br/><right>Right</><br/><justified>Justified paragraph Lorem ipsum dolor sit amet, consectetur adipiscing elit. In<//>
<normal>Normal</>
background
ABB7B7
title
Underline text
sample
<u>Text underline</>.
<u word="true">Text underline</>.
<u word="true" pattern="dashdotdot" style="double" color="red">Text underline</>.
background
ABB7B7
title
Unordered list
sample
This text is a list.<br/><ul><li>First item</li><li>Second <b>bold</> item </><ul><li>Second.first</><li>Second.second</><ul><li>Third</><ul><li>Fourth</li></></></><li>Third item</></>
background
ABB7B7
================================================
FILE: Example/GONMarkupParserSample.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
401E32021B281142C6BABB70 /* libPods-defaults-GONMarkupParserSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E6D2CD1AD599D4565EAA3ED /* libPods-defaults-GONMarkupParserSample.a */; };
5C0790A81ED74D0B0011FF0E /* GONMarkupStrong.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C0790A71ED74D0B0011FF0E /* GONMarkupStrong.m */; };
5C1D1C2E19920D7100F7B642 /* GONMarkupParagraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C1D1C2D19920D7100F7B642 /* GONMarkupParagraph.m */; };
5C2E11E41B8A146D0065D29C /* UIButton+GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E11E31B8A146D0065D29C /* UIButton+GONMarkupParser.m */; };
5C396DD21A80D80800AC8E45 /* GONMarkupLineStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C396DD11A80D80800AC8E45 /* GONMarkupLineStyle.m */; };
5C396DD31A80D80800AC8E45 /* GONMarkupLineStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C396DD11A80D80800AC8E45 /* GONMarkupLineStyle.m */; };
5C404BCC1A1C9115007DCB2C /* DefaultConfigurationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C404BCB1A1C9115007DCB2C /* DefaultConfigurationViewController.m */; };
5C404BD01A1C951F007DCB2C /* DefaultConfigurationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C404BCF1A1C951F007DCB2C /* DefaultConfigurationViewController.xib */; };
5C4241B91C89995A00E5B289 /* lama.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C4241B81C89995A00E5B289 /* lama.png */; };
5C43EE491A8251920053A667 /* GONMarkupAnchor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C43EE481A8251920053A667 /* GONMarkupAnchor.m */; };
5C43EE4A1A8251920053A667 /* GONMarkupAnchor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C43EE481A8251920053A667 /* GONMarkupAnchor.m */; };
5C43EE511A8267D60053A667 /* UITextView+GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C43EE501A8267D60053A667 /* UITextView+GONMarkupParser.m */; };
5C43EE521A8267D60053A667 /* UITextView+GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C43EE501A8267D60053A667 /* UITextView+GONMarkupParser.m */; };
5C44A9D119D0690A00CF6957 /* GONMarkupFontTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C44A9D019D0690A00CF6957 /* GONMarkupFontTraits.m */; };
5C65F3EA1A1114EC005A76A3 /* GONMarkupInc.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F3E91A1114EC005A76A3 /* GONMarkupInc.m */; };
5C65F3ED1A11150A005A76A3 /* GONMarkupDec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F3EC1A11150A005A76A3 /* GONMarkupDec.m */; };
5C65F3F11A112231005A76A3 /* samples.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F3F01A112231005A76A3 /* samples.plist */; };
5C65F3F31A112EBE005A76A3 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F3F21A112EBE005A76A3 /* MainWindow.xib */; };
5C65F3F81A112F3A005A76A3 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F3F61A112F3A005A76A3 /* RootViewController.m */; };
5C65F3F91A112F3A005A76A3 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F3F71A112F3A005A76A3 /* RootViewController.xib */; };
5C65F3FE1A1133F8005A76A3 /* SampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F3FC1A1133F8005A76A3 /* SampleViewController.m */; };
5C65F3FF1A1133F8005A76A3 /* SampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F3FD1A1133F8005A76A3 /* SampleViewController.xib */; };
5C65F4041A1139CD005A76A3 /* PlaygroundViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F4021A1139CD005A76A3 /* PlaygroundViewController.m */; };
5C65F4051A1139CD005A76A3 /* PlaygroundViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F4031A1139CD005A76A3 /* PlaygroundViewController.xib */; };
5C65F4071A1153A2005A76A3 /* ResultViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F4061A1153A2005A76A3 /* ResultViewController.xib */; };
5C65F40B1A11FDB2005A76A3 /* ComplexExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F40A1A11FDB2005A76A3 /* ComplexExampleViewController.m */; };
5C65F40D1A11FFFE005A76A3 /* ComplexExampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C65F40C1A11FFFE005A76A3 /* ComplexExampleViewController.xib */; };
5C7C5B291994CB55003BE47A /* GONMarkupParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C5B281994CB55003BE47A /* GONMarkupParserUtils.m */; };
5C7C5B2A1994CB55003BE47A /* GONMarkupParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C5B281994CB55003BE47A /* GONMarkupParserUtils.m */; };
5CB1C580195B19C400590186 /* ResultViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C57F195B19C400590186 /* ResultViewController.m */; };
5CB1C58A195B1EE600590186 /* GONMarkupNamedColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C589195B1EE600590186 /* GONMarkupNamedColor.m */; };
5CB1C58E195B24F200590186 /* GONMarkupBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C58D195B24F200590186 /* GONMarkupBlock.m */; };
5CB1C58F195B250A00590186 /* GONMarkupBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C58D195B24F200590186 /* GONMarkupBlock.m */; };
5CB1C590195B250A00590186 /* GONMarkupNamedColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C589195B1EE600590186 /* GONMarkupNamedColor.m */; };
5CB1C591195B250A00590186 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27160195B11E0007FCF44 /* AppDelegate.m */; };
5CB1C593195B250A00590186 /* ResultViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C57F195B19C400590186 /* ResultViewController.m */; };
5CB1C594195B250A00590186 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2715C195B11E0007FCF44 /* main.m */; };
5CB1C59C195B25E800590186 /* GONMarkupReset.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C59B195B25E800590186 /* GONMarkupReset.m */; };
5CB1C59D195B25E800590186 /* GONMarkupReset.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C59B195B25E800590186 /* GONMarkupReset.m */; };
5CB1C5A0195B2B7700590186 /* GONMarkupNamedFont.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C59F195B2B7700590186 /* GONMarkupNamedFont.m */; };
5CB1C5A1195B2B7700590186 /* GONMarkupNamedFont.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C59F195B2B7700590186 /* GONMarkupNamedFont.m */; };
5CB1C5A4195B333700590186 /* GONMarkup+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5A3195B333700590186 /* GONMarkup+Private.m */; };
5CB1C5A5195B333700590186 /* GONMarkup+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5A3195B333700590186 /* GONMarkup+Private.m */; };
5CB1C5A8195B3B7400590186 /* ComplexExample in Resources */ = {isa = PBXBuildFile; fileRef = 5CB1C5A7195B3B7400590186 /* ComplexExample */; };
5CB1C5A9195B3B7400590186 /* ComplexExample in Resources */ = {isa = PBXBuildFile; fileRef = 5CB1C5A7195B3B7400590186 /* ComplexExample */; };
5CB1C5AD195B4FA000590186 /* GONMarkupList.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5AC195B4FA000590186 /* GONMarkupList.m */; };
5CB1C5AE195B4FA000590186 /* GONMarkupList.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5AC195B4FA000590186 /* GONMarkupList.m */; };
5CB1C5B5195B4FB600590186 /* GONMarkupListItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5B4195B4FB600590186 /* GONMarkupListItem.m */; };
5CB1C5B6195B4FB600590186 /* GONMarkupListItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5B4195B4FB600590186 /* GONMarkupListItem.m */; };
5CB1C5B9195B55BE00590186 /* GONMarkupLineBreak.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5B8195B55BE00590186 /* GONMarkupLineBreak.m */; };
5CB1C5BA195B55BE00590186 /* GONMarkupLineBreak.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB1C5B8195B55BE00590186 /* GONMarkupLineBreak.m */; };
5CB3106F19BE026C00B06D0D /* UILabel+GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB3106E19BE026C00B06D0D /* UILabel+GONMarkupParser.m */; };
5CB3107219BE027A00B06D0D /* UITextField+GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB3107119BE027A00B06D0D /* UITextField+GONMarkupParser.m */; };
5CC284B7197974870009D443 /* GONMarkupSimple.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CC284B6197974870009D443 /* GONMarkupSimple.m */; };
5CC43CD5197E616600E46A03 /* GONMarkupAlignment.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CC43CD4197E616600E46A03 /* GONMarkupAlignment.m */; };
5CD617E319828AA90001C3D9 /* GONMarkupParserManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CD617E219828AA90001C3D9 /* GONMarkupParserManager.m */; };
5CD617E719828B1C0001C3D9 /* GONMarkupTextStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CD617E619828B1C0001C3D9 /* GONMarkupTextStyle.m */; };
5CD617E919828B2E0001C3D9 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD617E819828B2E0001C3D9 /* CoreText.framework */; };
5CE1493A19CC2B6300B73518 /* GONMarkupItalic.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE1493919CC2B6300B73518 /* GONMarkupItalic.m */; };
5CE1493D19CC2B6900B73518 /* GONMarkupBold.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE1493C19CC2B6900B73518 /* GONMarkupBold.m */; };
5CE27151195B11E0007FCF44 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE27150195B11E0007FCF44 /* Foundation.framework */; };
5CE27153195B11E0007FCF44 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE27152195B11E0007FCF44 /* CoreGraphics.framework */; };
5CE27155195B11E0007FCF44 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE27154195B11E0007FCF44 /* UIKit.framework */; };
5CE2715B195B11E0007FCF44 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CE27159195B11E0007FCF44 /* InfoPlist.strings */; };
5CE2715D195B11E0007FCF44 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2715C195B11E0007FCF44 /* main.m */; };
5CE27161195B11E0007FCF44 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27160195B11E0007FCF44 /* AppDelegate.m */; };
5CE27169195B11E0007FCF44 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5CE27168195B11E0007FCF44 /* Images.xcassets */; };
5CE27170195B11E0007FCF44 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2716F195B11E0007FCF44 /* XCTest.framework */; };
5CE27171195B11E0007FCF44 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE27150195B11E0007FCF44 /* Foundation.framework */; };
5CE27172195B11E0007FCF44 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE27154195B11E0007FCF44 /* UIKit.framework */; };
5CE2717A195B11E0007FCF44 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CE27178195B11E0007FCF44 /* InfoPlist.strings */; };
5CE2717C195B11E0007FCF44 /* GONMarkupParserSampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2717B195B11E0007FCF44 /* GONMarkupParserSampleTests.m */; };
5CE27194195B1412007FCF44 /* GONMarkup.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2718D195B1412007FCF44 /* GONMarkup.m */; };
5CE27195195B1412007FCF44 /* GONMarkup.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2718D195B1412007FCF44 /* GONMarkup.m */; };
5CE27196195B1412007FCF44 /* GONMarkupColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2718F195B1412007FCF44 /* GONMarkupColor.m */; };
5CE27197195B1412007FCF44 /* GONMarkupColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE2718F195B1412007FCF44 /* GONMarkupColor.m */; };
5CE27198195B1412007FCF44 /* GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27191195B1412007FCF44 /* GONMarkupParser.m */; };
5CE27199195B1412007FCF44 /* GONMarkupParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27191195B1412007FCF44 /* GONMarkupParser.m */; };
5CE2719A195B1412007FCF44 /* GONMarkupFont.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27193195B1412007FCF44 /* GONMarkupFont.m */; };
5CE2719B195B1412007FCF44 /* GONMarkupFont.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CE27193195B1412007FCF44 /* GONMarkupFont.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
5CE27173195B11E0007FCF44 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5CE27145195B11E0007FCF44 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5CE2714C195B11E0007FCF44;
remoteInfo = GONMarkupParserSample;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
5C0790A61ED74D0B0011FF0E /* GONMarkupStrong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupStrong.h; path = ../Classes/GONMarkupStrong.h; sourceTree = ""; };
5C0790A71ED74D0B0011FF0E /* GONMarkupStrong.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupStrong.m; path = ../Classes/GONMarkupStrong.m; sourceTree = ""; };
5C1BA2E419BF45BD00E3D67C /* GONMarkupParser_Categories.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GONMarkupParser_Categories.h; path = ../Classes/GONMarkupParser_Categories.h; sourceTree = ""; };
5C1D1C2C19920D7100F7B642 /* GONMarkupParagraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupParagraph.h; path = ../Classes/GONMarkupParagraph.h; sourceTree = ""; };
5C1D1C2D19920D7100F7B642 /* GONMarkupParagraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupParagraph.m; path = ../Classes/GONMarkupParagraph.m; sourceTree = ""; };
5C2E11E21B8A146D0065D29C /* UIButton+GONMarkupParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIButton+GONMarkupParser.h"; path = "../Classes/UIButton+GONMarkupParser.h"; sourceTree = ""; };
5C2E11E31B8A146D0065D29C /* UIButton+GONMarkupParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIButton+GONMarkupParser.m"; path = "../Classes/UIButton+GONMarkupParser.m"; sourceTree = ""; };
5C2E11E51B8A175F0065D29C /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = ""; };
5C396DD01A80D80800AC8E45 /* GONMarkupLineStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupLineStyle.h; path = ../Classes/GONMarkupLineStyle.h; sourceTree = ""; };
5C396DD11A80D80800AC8E45 /* GONMarkupLineStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupLineStyle.m; path = ../Classes/GONMarkupLineStyle.m; sourceTree = ""; };
5C404BCA1A1C9115007DCB2C /* DefaultConfigurationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultConfigurationViewController.h; sourceTree = ""; };
5C404BCB1A1C9115007DCB2C /* DefaultConfigurationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DefaultConfigurationViewController.m; sourceTree = ""; };
5C404BCF1A1C951F007DCB2C /* DefaultConfigurationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DefaultConfigurationViewController.xib; sourceTree = ""; };
5C4241B51C89982000E5B289 /* GONMarkupImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupImage.h; path = ../Classes/GONMarkupImage.h; sourceTree = ""; };
5C4241B61C89982000E5B289 /* GONMarkupImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupImage.m; path = ../Classes/GONMarkupImage.m; sourceTree = ""; };
5C4241B81C89995A00E5B289 /* lama.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lama.png; sourceTree = ""; };
5C43EE471A8251920053A667 /* GONMarkupAnchor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupAnchor.h; path = ../Classes/GONMarkupAnchor.h; sourceTree = ""; };
5C43EE481A8251920053A667 /* GONMarkupAnchor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupAnchor.m; path = ../Classes/GONMarkupAnchor.m; sourceTree = ""; };
5C43EE4F1A8267D60053A667 /* UITextView+GONMarkupParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UITextView+GONMarkupParser.h"; path = "../Classes/UITextView+GONMarkupParser.h"; sourceTree = ""; };
5C43EE501A8267D60053A667 /* UITextView+GONMarkupParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UITextView+GONMarkupParser.m"; path = "../Classes/UITextView+GONMarkupParser.m"; sourceTree = ""; };
5C44A9CF19D0690A00CF6957 /* GONMarkupFontTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupFontTraits.h; path = ../Classes/GONMarkupFontTraits.h; sourceTree = ""; };
5C44A9D019D0690A00CF6957 /* GONMarkupFontTraits.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupFontTraits.m; path = ../Classes/GONMarkupFontTraits.m; sourceTree = ""; };
5C65F3E81A1114EC005A76A3 /* GONMarkupInc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupInc.h; path = ../Classes/GONMarkupInc.h; sourceTree = ""; };
5C65F3E91A1114EC005A76A3 /* GONMarkupInc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupInc.m; path = ../Classes/GONMarkupInc.m; sourceTree = ""; };
5C65F3EB1A11150A005A76A3 /* GONMarkupDec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupDec.h; path = ../Classes/GONMarkupDec.h; sourceTree = ""; };
5C65F3EC1A11150A005A76A3 /* GONMarkupDec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupDec.m; path = ../Classes/GONMarkupDec.m; sourceTree = ""; };
5C65F3F01A112231005A76A3 /* samples.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = samples.plist; sourceTree = ""; };
5C65F3F21A112EBE005A76A3 /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; };
5C65F3F51A112F3A005A76A3 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; };
5C65F3F61A112F3A005A76A3 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; };
5C65F3F71A112F3A005A76A3 /* RootViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; };
5C65F3FB1A1133F8005A76A3 /* SampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleViewController.h; sourceTree = ""; };
5C65F3FC1A1133F8005A76A3 /* SampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SampleViewController.m; sourceTree = ""; };
5C65F3FD1A1133F8005A76A3 /* SampleViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SampleViewController.xib; sourceTree = ""; };
5C65F4011A1139CD005A76A3 /* PlaygroundViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaygroundViewController.h; sourceTree = ""; };
5C65F4021A1139CD005A76A3 /* PlaygroundViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaygroundViewController.m; sourceTree = ""; };
5C65F4031A1139CD005A76A3 /* PlaygroundViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PlaygroundViewController.xib; sourceTree = ""; };
5C65F4061A1153A2005A76A3 /* ResultViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ResultViewController.xib; sourceTree = ""; };
5C65F4091A11FDB2005A76A3 /* ComplexExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexExampleViewController.h; sourceTree = ""; };
5C65F40A1A11FDB2005A76A3 /* ComplexExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ComplexExampleViewController.m; sourceTree = ""; };
5C65F40C1A11FFFE005A76A3 /* ComplexExampleViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ComplexExampleViewController.xib; sourceTree = ""; };
5C7C5B271994CB55003BE47A /* GONMarkupParserUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupParserUtils.h; path = ../Classes/GONMarkupParserUtils.h; sourceTree = ""; };
5C7C5B281994CB55003BE47A /* GONMarkupParserUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupParserUtils.m; path = ../Classes/GONMarkupParserUtils.m; sourceTree = ""; };
5CB1C57E195B19C400590186 /* ResultViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultViewController.h; sourceTree = ""; };
5CB1C57F195B19C400590186 /* ResultViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ResultViewController.m; sourceTree = ""; };
5CB1C582195B1A0100590186 /* GONMarkupDefaultMarkups.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GONMarkupDefaultMarkups.h; path = ../Classes/GONMarkupDefaultMarkups.h; sourceTree = ""; };
5CB1C588195B1EE600590186 /* GONMarkupNamedColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupNamedColor.h; path = ../Classes/GONMarkupNamedColor.h; sourceTree = ""; };
5CB1C589195B1EE600590186 /* GONMarkupNamedColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupNamedColor.m; path = ../Classes/GONMarkupNamedColor.m; sourceTree = ""; };
5CB1C58C195B24F200590186 /* GONMarkupBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupBlock.h; path = ../Classes/GONMarkupBlock.h; sourceTree = ""; };
5CB1C58D195B24F200590186 /* GONMarkupBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupBlock.m; path = ../Classes/GONMarkupBlock.m; sourceTree = ""; };
5CB1C59A195B25E800590186 /* GONMarkupReset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupReset.h; path = ../Classes/GONMarkupReset.h; sourceTree = ""; };
5CB1C59B195B25E800590186 /* GONMarkupReset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupReset.m; path = ../Classes/GONMarkupReset.m; sourceTree = ""; };
5CB1C59E195B2B7700590186 /* GONMarkupNamedFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupNamedFont.h; path = ../Classes/GONMarkupNamedFont.h; sourceTree = ""; };
5CB1C59F195B2B7700590186 /* GONMarkupNamedFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupNamedFont.m; path = ../Classes/GONMarkupNamedFont.m; sourceTree = ""; };
5CB1C5A2195B333700590186 /* GONMarkup+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GONMarkup+Private.h"; path = "../Classes/GONMarkup+Private.h"; sourceTree = ""; };
5CB1C5A3195B333700590186 /* GONMarkup+Private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GONMarkup+Private.m"; path = "../Classes/GONMarkup+Private.m"; sourceTree = ""; };
5CB1C5A7195B3B7400590186 /* ComplexExample */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ComplexExample; sourceTree = ""; };
5CB1C5AB195B4FA000590186 /* GONMarkupList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupList.h; path = ../Classes/GONMarkupList.h; sourceTree = ""; };
5CB1C5AC195B4FA000590186 /* GONMarkupList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupList.m; path = ../Classes/GONMarkupList.m; sourceTree = ""; };
5CB1C5B3195B4FB600590186 /* GONMarkupListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupListItem.h; path = ../Classes/GONMarkupListItem.h; sourceTree = ""; };
5CB1C5B4195B4FB600590186 /* GONMarkupListItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupListItem.m; path = ../Classes/GONMarkupListItem.m; sourceTree = ""; };
5CB1C5B7195B55BE00590186 /* GONMarkupLineBreak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupLineBreak.h; path = ../Classes/GONMarkupLineBreak.h; sourceTree = ""; };
5CB1C5B8195B55BE00590186 /* GONMarkupLineBreak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupLineBreak.m; path = ../Classes/GONMarkupLineBreak.m; sourceTree = ""; };
5CB3106D19BE026C00B06D0D /* UILabel+GONMarkupParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UILabel+GONMarkupParser.h"; path = "../Classes/UILabel+GONMarkupParser.h"; sourceTree = ""; };
5CB3106E19BE026C00B06D0D /* UILabel+GONMarkupParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UILabel+GONMarkupParser.m"; path = "../Classes/UILabel+GONMarkupParser.m"; sourceTree = ""; };
5CB3107019BE027A00B06D0D /* UITextField+GONMarkupParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UITextField+GONMarkupParser.h"; path = "../Classes/UITextField+GONMarkupParser.h"; sourceTree = ""; };
5CB3107119BE027A00B06D0D /* UITextField+GONMarkupParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UITextField+GONMarkupParser.m"; path = "../Classes/UITextField+GONMarkupParser.m"; sourceTree = ""; };
5CBDC0A0195C334D007279A0 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = ""; };
5CBDC0A1195C3356007279A0 /* GONMarkupParser.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; name = GONMarkupParser.podspec; path = ../GONMarkupParser.podspec; sourceTree = ""; };
5CC284B5197974870009D443 /* GONMarkupSimple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupSimple.h; path = ../Classes/GONMarkupSimple.h; sourceTree = ""; };
5CC284B6197974870009D443 /* GONMarkupSimple.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupSimple.m; path = ../Classes/GONMarkupSimple.m; sourceTree = ""; };
5CC43CD3197E616600E46A03 /* GONMarkupAlignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupAlignment.h; path = ../Classes/GONMarkupAlignment.h; sourceTree = ""; };
5CC43CD4197E616600E46A03 /* GONMarkupAlignment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupAlignment.m; path = ../Classes/GONMarkupAlignment.m; sourceTree = ""; };
5CD617E119828AA90001C3D9 /* GONMarkupParserManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupParserManager.h; path = ../Classes/GONMarkupParserManager.h; sourceTree = ""; };
5CD617E219828AA90001C3D9 /* GONMarkupParserManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupParserManager.m; path = ../Classes/GONMarkupParserManager.m; sourceTree = ""; };
5CD617E519828B1C0001C3D9 /* GONMarkupTextStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupTextStyle.h; path = ../Classes/GONMarkupTextStyle.h; sourceTree = ""; };
5CD617E619828B1C0001C3D9 /* GONMarkupTextStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupTextStyle.m; path = ../Classes/GONMarkupTextStyle.m; sourceTree = ""; };
5CD617E819828B2E0001C3D9 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
5CE1493619CC253600B73518 /* GONMarkupItalic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupItalic.h; path = ../Classes/GONMarkupItalic.h; sourceTree = ""; };
5CE1493919CC2B6300B73518 /* GONMarkupItalic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupItalic.m; path = ../Classes/GONMarkupItalic.m; sourceTree = ""; };
5CE1493B19CC2B6900B73518 /* GONMarkupBold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupBold.h; path = ../Classes/GONMarkupBold.h; sourceTree = ""; };
5CE1493C19CC2B6900B73518 /* GONMarkupBold.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupBold.m; path = ../Classes/GONMarkupBold.m; sourceTree = ""; };
5CE1493E19CC2BBC00B73518 /* GONMarkupParser_All.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GONMarkupParser_All.h; path = ../Classes/GONMarkupParser_All.h; sourceTree = ""; };
5CE2714D195B11E0007FCF44 /* GONMarkupParserSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GONMarkupParserSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
5CE27150195B11E0007FCF44 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
5CE27152195B11E0007FCF44 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
5CE27154195B11E0007FCF44 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
5CE27158195B11E0007FCF44 /* GONMarkupParserSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GONMarkupParserSample-Info.plist"; sourceTree = ""; };
5CE2715A195B11E0007FCF44 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
5CE2715C195B11E0007FCF44 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
5CE2715E195B11E0007FCF44 /* GONMarkupParserSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GONMarkupParserSample-Prefix.pch"; sourceTree = ""; };
5CE2715F195B11E0007FCF44 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
5CE27160195B11E0007FCF44 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
5CE27168195B11E0007FCF44 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
5CE2716E195B11E0007FCF44 /* GONMarkupParserSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GONMarkupParserSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5CE2716F195B11E0007FCF44 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
5CE27177195B11E0007FCF44 /* GONMarkupParserSampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GONMarkupParserSampleTests-Info.plist"; sourceTree = ""; };
5CE27179195B11E0007FCF44 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
5CE2717B195B11E0007FCF44 /* GONMarkupParserSampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GONMarkupParserSampleTests.m; sourceTree = ""; };
5CE2718A195B12E6007FCF44 /* PodFile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = PodFile; path = ../PodFile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
5CE2718C195B1412007FCF44 /* GONMarkup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkup.h; path = ../Classes/GONMarkup.h; sourceTree = ""; };
5CE2718D195B1412007FCF44 /* GONMarkup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkup.m; path = ../Classes/GONMarkup.m; sourceTree = ""; };
5CE2718E195B1412007FCF44 /* GONMarkupColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupColor.h; path = ../Classes/GONMarkupColor.h; sourceTree = ""; };
5CE2718F195B1412007FCF44 /* GONMarkupColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupColor.m; path = ../Classes/GONMarkupColor.m; sourceTree = ""; };
5CE27190195B1412007FCF44 /* GONMarkupParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupParser.h; path = ../Classes/GONMarkupParser.h; sourceTree = ""; };
5CE27191195B1412007FCF44 /* GONMarkupParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupParser.m; path = ../Classes/GONMarkupParser.m; sourceTree = ""; };
5CE27192195B1412007FCF44 /* GONMarkupFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GONMarkupFont.h; path = ../Classes/GONMarkupFont.h; sourceTree = ""; };
5CE27193195B1412007FCF44 /* GONMarkupFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GONMarkupFont.m; path = ../Classes/GONMarkupFont.m; sourceTree = ""; };
8E6D2CD1AD599D4565EAA3ED /* libPods-defaults-GONMarkupParserSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-GONMarkupParserSample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A11B08D3B67C671A7C1F41EB /* Pods-defaults-GONMarkupParserSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-GONMarkupParserSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-defaults-GONMarkupParserSample/Pods-defaults-GONMarkupParserSample.debug.xcconfig"; sourceTree = ""; };
CB19407DB2362C93C6FF1BC5 /* Pods-defaults-GONMarkupParserSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-GONMarkupParserSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-defaults-GONMarkupParserSample/Pods-defaults-GONMarkupParserSample.release.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5CE2714A195B11E0007FCF44 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CD617E919828B2E0001C3D9 /* CoreText.framework in Frameworks */,
5CE27153195B11E0007FCF44 /* CoreGraphics.framework in Frameworks */,
5CE27155195B11E0007FCF44 /* UIKit.framework in Frameworks */,
5CE27151195B11E0007FCF44 /* Foundation.framework in Frameworks */,
401E32021B281142C6BABB70 /* libPods-defaults-GONMarkupParserSample.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5CE2716B195B11E0007FCF44 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CE27170195B11E0007FCF44 /* XCTest.framework in Frameworks */,
5CE27172195B11E0007FCF44 /* UIKit.framework in Frameworks */,
5CE27171195B11E0007FCF44 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2686016DECE5E515511864F6 /* Pods */ = {
isa = PBXGroup;
children = (
A11B08D3B67C671A7C1F41EB /* Pods-defaults-GONMarkupParserSample.debug.xcconfig */,
CB19407DB2362C93C6FF1BC5 /* Pods-defaults-GONMarkupParserSample.release.xcconfig */,
);
name = Pods;
sourceTree = "";
};
5C404BC91A1C90E0007DCB2C /* DefaultConfiguration */ = {
isa = PBXGroup;
children = (
5C404BCA1A1C9115007DCB2C /* DefaultConfigurationViewController.h */,
5C404BCB1A1C9115007DCB2C /* DefaultConfigurationViewController.m */,
5C404BCF1A1C951F007DCB2C /* DefaultConfigurationViewController.xib */,
);
name = DefaultConfiguration;
sourceTree = "";
};
5C4241B41C8997F500E5B289 /* Image */ = {
isa = PBXGroup;
children = (
5C4241B51C89982000E5B289 /* GONMarkupImage.h */,
5C4241B61C89982000E5B289 /* GONMarkupImage.m */,
);
name = Image;
sourceTree = "";
};
5C43EE461A8251510053A667 /* Anchor */ = {
isa = PBXGroup;
children = (
5C43EE471A8251920053A667 /* GONMarkupAnchor.h */,
5C43EE481A8251920053A667 /* GONMarkupAnchor.m */,
);
name = Anchor;
sourceTree = "";
};
5C65F3DF1A111468005A76A3 /* TextSize */ = {
isa = PBXGroup;
children = (
5C65F3E81A1114EC005A76A3 /* GONMarkupInc.h */,
5C65F3E91A1114EC005A76A3 /* GONMarkupInc.m */,
5C65F3EB1A11150A005A76A3 /* GONMarkupDec.h */,
5C65F3EC1A11150A005A76A3 /* GONMarkupDec.m */,
);
name = TextSize;
sourceTree = "";
};
5C65F3F41A112F1E005A76A3 /* Root */ = {
isa = PBXGroup;
children = (
5C65F3F51A112F3A005A76A3 /* RootViewController.h */,
5C65F3F61A112F3A005A76A3 /* RootViewController.m */,
5C65F3F71A112F3A005A76A3 /* RootViewController.xib */,
);
name = Root;
sourceTree = "";
};
5C65F3FA1A1133E6005A76A3 /* Sample */ = {
isa = PBXGroup;
children = (
5C65F3FB1A1133F8005A76A3 /* SampleViewController.h */,
5C65F3FC1A1133F8005A76A3 /* SampleViewController.m */,
5C65F3FD1A1133F8005A76A3 /* SampleViewController.xib */,
);
name = Sample;
sourceTree = "";
};
5C65F4001A1139B5005A76A3 /* Playground */ = {
isa = PBXGroup;
children = (
5C65F4011A1139CD005A76A3 /* PlaygroundViewController.h */,
5C65F4021A1139CD005A76A3 /* PlaygroundViewController.m */,
5C65F4031A1139CD005A76A3 /* PlaygroundViewController.xib */,
);
name = Playground;
sourceTree = "";
};
5C65F4081A11FD87005A76A3 /* ComplexExample */ = {
isa = PBXGroup;
children = (
5C65F4091A11FDB2005A76A3 /* ComplexExampleViewController.h */,
5C65F40A1A11FDB2005A76A3 /* ComplexExampleViewController.m */,
5C65F40C1A11FFFE005A76A3 /* ComplexExampleViewController.xib */,
);
name = ComplexExample;
sourceTree = "";
};
5C7C5B221994CA3A003BE47A /* Utils */ = {
isa = PBXGroup;
children = (
5C7C5B271994CB55003BE47A /* GONMarkupParserUtils.h */,
5C7C5B281994CB55003BE47A /* GONMarkupParserUtils.m */,
);
name = Utils;
sourceTree = "";
};
5CB1C581195B19C800590186 /* Result */ = {
isa = PBXGroup;
children = (
5CB1C57E195B19C400590186 /* ResultViewController.h */,
5CB1C57F195B19C400590186 /* ResultViewController.m */,
5C65F4061A1153A2005A76A3 /* ResultViewController.xib */,
);
name = Result;
sourceTree = "";
};
5CB1C583195B1A3100590186 /* Color */ = {
isa = PBXGroup;
children = (
5CE2718E195B1412007FCF44 /* GONMarkupColor.h */,
5CE2718F195B1412007FCF44 /* GONMarkupColor.m */,
5CB1C588195B1EE600590186 /* GONMarkupNamedColor.h */,
5CB1C589195B1EE600590186 /* GONMarkupNamedColor.m */,
);
name = Color;
sourceTree = "";
};
5CB1C584195B1A3500590186 /* Font */ = {
isa = PBXGroup;
children = (
5CE27192195B1412007FCF44 /* GONMarkupFont.h */,
5CE27193195B1412007FCF44 /* GONMarkupFont.m */,
5CB1C59E195B2B7700590186 /* GONMarkupNamedFont.h */,
5CB1C59F195B2B7700590186 /* GONMarkupNamedFont.m */,
);
name = Font;
sourceTree = "";
};
5CB1C58B195B24DB00590186 /* Block */ = {
isa = PBXGroup;
children = (
5CB1C58C195B24F200590186 /* GONMarkupBlock.h */,
5CB1C58D195B24F200590186 /* GONMarkupBlock.m */,
);
name = Block;
sourceTree = "";
};
5CB1C599195B25A400590186 /* Special */ = {
isa = PBXGroup;
children = (
5CB1C59A195B25E800590186 /* GONMarkupReset.h */,
5CB1C59B195B25E800590186 /* GONMarkupReset.m */,
5CB1C5B7195B55BE00590186 /* GONMarkupLineBreak.h */,
5CB1C5B8195B55BE00590186 /* GONMarkupLineBreak.m */,
5C1D1C2C19920D7100F7B642 /* GONMarkupParagraph.h */,
5C1D1C2D19920D7100F7B642 /* GONMarkupParagraph.m */,
);
name = Special;
sourceTree = "";
};
5CB1C5A6195B333B00590186 /* Private */ = {
isa = PBXGroup;
children = (
5CB1C5A2195B333700590186 /* GONMarkup+Private.h */,
5CB1C5A3195B333700590186 /* GONMarkup+Private.m */,
);
name = Private;
sourceTree = "";
};
5CB1C5AA195B4F8900590186 /* List */ = {
isa = PBXGroup;
children = (
5CB1C5AB195B4FA000590186 /* GONMarkupList.h */,
5CB1C5AC195B4FA000590186 /* GONMarkupList.m */,
5CB1C5B3195B4FB600590186 /* GONMarkupListItem.h */,
5CB1C5B4195B4FB600590186 /* GONMarkupListItem.m */,
);
name = List;
sourceTree = "";
};
5CB3106919BE023300B06D0D /* Categories */ = {
isa = PBXGroup;
children = (
5C1BA2E419BF45BD00E3D67C /* GONMarkupParser_Categories.h */,
5C2E11E21B8A146D0065D29C /* UIButton+GONMarkupParser.h */,
5C2E11E31B8A146D0065D29C /* UIButton+GONMarkupParser.m */,
5CB3106D19BE026C00B06D0D /* UILabel+GONMarkupParser.h */,
5CB3106E19BE026C00B06D0D /* UILabel+GONMarkupParser.m */,
5CB3107019BE027A00B06D0D /* UITextField+GONMarkupParser.h */,
5CB3107119BE027A00B06D0D /* UITextField+GONMarkupParser.m */,
5C43EE4F1A8267D60053A667 /* UITextView+GONMarkupParser.h */,
5C43EE501A8267D60053A667 /* UITextView+GONMarkupParser.m */,
);
name = Categories;
sourceTree = "";
};
5CC284B41979746D0009D443 /* Simple */ = {
isa = PBXGroup;
children = (
5CC284B5197974870009D443 /* GONMarkupSimple.h */,
5CC284B6197974870009D443 /* GONMarkupSimple.m */,
);
name = Simple;
sourceTree = "";
};
5CC43CD2197E613800E46A03 /* Alignment */ = {
isa = PBXGroup;
children = (
5CC43CD3197E616600E46A03 /* GONMarkupAlignment.h */,
5CC43CD4197E616600E46A03 /* GONMarkupAlignment.m */,
);
name = Alignment;
sourceTree = "";
};
5CD617E419828AF50001C3D9 /* TextStyle */ = {
isa = PBXGroup;
children = (
5C44A9CF19D0690A00CF6957 /* GONMarkupFontTraits.h */,
5C44A9D019D0690A00CF6957 /* GONMarkupFontTraits.m */,
5CE1493B19CC2B6900B73518 /* GONMarkupBold.h */,
5CE1493C19CC2B6900B73518 /* GONMarkupBold.m */,
5CE1493619CC253600B73518 /* GONMarkupItalic.h */,
5CE1493919CC2B6300B73518 /* GONMarkupItalic.m */,
5C396DD01A80D80800AC8E45 /* GONMarkupLineStyle.h */,
5C396DD11A80D80800AC8E45 /* GONMarkupLineStyle.m */,
5CD617E519828B1C0001C3D9 /* GONMarkupTextStyle.h */,
5CD617E619828B1C0001C3D9 /* GONMarkupTextStyle.m */,
5C0790A61ED74D0B0011FF0E /* GONMarkupStrong.h */,
5C0790A71ED74D0B0011FF0E /* GONMarkupStrong.m */,
);
name = TextStyle;
sourceTree = "";
};
5CE27144195B11E0007FCF44 = {
isa = PBXGroup;
children = (
5C2E11E51B8A175F0065D29C /* CHANGELOG.md */,
5CBDC0A0195C334D007279A0 /* README.md */,
5CBDC0A1195C3356007279A0 /* GONMarkupParser.podspec */,
5CE27185195B1226007FCF44 /* Lib */,
5CE27156195B11E0007FCF44 /* GONMarkupParserSample */,
5CE27175195B11E0007FCF44 /* GONMarkupParserSampleTests */,
5CE2714F195B11E0007FCF44 /* Frameworks */,
5CE2714E195B11E0007FCF44 /* Products */,
2686016DECE5E515511864F6 /* Pods */,
);
sourceTree = "";
};
5CE2714E195B11E0007FCF44 /* Products */ = {
isa = PBXGroup;
children = (
5CE2714D195B11E0007FCF44 /* GONMarkupParserSample.app */,
5CE2716E195B11E0007FCF44 /* GONMarkupParserSampleTests.xctest */,
);
name = Products;
sourceTree = "";
};
5CE2714F195B11E0007FCF44 /* Frameworks */ = {
isa = PBXGroup;
children = (
5CD617E819828B2E0001C3D9 /* CoreText.framework */,
5CE27150195B11E0007FCF44 /* Foundation.framework */,
5CE27152195B11E0007FCF44 /* CoreGraphics.framework */,
5CE27154195B11E0007FCF44 /* UIKit.framework */,
5CE2716F195B11E0007FCF44 /* XCTest.framework */,
8E6D2CD1AD599D4565EAA3ED /* libPods-defaults-GONMarkupParserSample.a */,
);
name = Frameworks;
sourceTree = "";
};
5CE27156195B11E0007FCF44 /* GONMarkupParserSample */ = {
isa = PBXGroup;
children = (
5CE27186195B123A007FCF44 /* Classes */,
5CE27187195B1241007FCF44 /* Resources */,
5CE27157195B11E0007FCF44 /* Supporting Files */,
);
path = GONMarkupParserSample;
sourceTree = "";
};
5CE27157195B11E0007FCF44 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5CE27158195B11E0007FCF44 /* GONMarkupParserSample-Info.plist */,
5CE27159195B11E0007FCF44 /* InfoPlist.strings */,
5CE2715C195B11E0007FCF44 /* main.m */,
5CE2715E195B11E0007FCF44 /* GONMarkupParserSample-Prefix.pch */,
5C65F3F21A112EBE005A76A3 /* MainWindow.xib */,
);
name = "Supporting Files";
sourceTree = "";
};
5CE27175195B11E0007FCF44 /* GONMarkupParserSampleTests */ = {
isa = PBXGroup;
children = (
5CE2717B195B11E0007FCF44 /* GONMarkupParserSampleTests.m */,
5CE27176195B11E0007FCF44 /* Supporting Files */,
);
path = GONMarkupParserSampleTests;
sourceTree = "";
};
5CE27176195B11E0007FCF44 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5CE27177195B11E0007FCF44 /* GONMarkupParserSampleTests-Info.plist */,
5CE27178195B11E0007FCF44 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "";
};
5CE27185195B1226007FCF44 /* Lib */ = {
isa = PBXGroup;
children = (
5CE1493E19CC2BBC00B73518 /* GONMarkupParser_All.h */,
5CE27190195B1412007FCF44 /* GONMarkupParser.h */,
5CE27191195B1412007FCF44 /* GONMarkupParser.m */,
5CD617E119828AA90001C3D9 /* GONMarkupParserManager.h */,
5CD617E219828AA90001C3D9 /* GONMarkupParserManager.m */,
5CB3106919BE023300B06D0D /* Categories */,
5CE271A1195B1437007FCF44 /* DefaultMarkup */,
5CE2719C195B141A007FCF44 /* Markup */,
5C7C5B221994CA3A003BE47A /* Utils */,
);
name = Lib;
sourceTree = "";
};
5CE27186195B123A007FCF44 /* Classes */ = {
isa = PBXGroup;
children = (
5CE2715F195B11E0007FCF44 /* AppDelegate.h */,
5CE27160195B11E0007FCF44 /* AppDelegate.m */,
5CE27188195B126A007FCF44 /* ViewControllers */,
);
name = Classes;
sourceTree = "";
};
5CE27187195B1241007FCF44 /* Resources */ = {
isa = PBXGroup;
children = (
5C4241B81C89995A00E5B289 /* lama.png */,
5CE27168195B11E0007FCF44 /* Images.xcassets */,
5CE2718A195B12E6007FCF44 /* PodFile */,
5C65F3F01A112231005A76A3 /* samples.plist */,
5CB1C5A7195B3B7400590186 /* ComplexExample */,
);
name = Resources;
sourceTree = "";
};
5CE27188195B126A007FCF44 /* ViewControllers */ = {
isa = PBXGroup;
children = (
5C65F4081A11FD87005A76A3 /* ComplexExample */,
5C404BC91A1C90E0007DCB2C /* DefaultConfiguration */,
5C65F4001A1139B5005A76A3 /* Playground */,
5CB1C581195B19C800590186 /* Result */,
5C65F3F41A112F1E005A76A3 /* Root */,
5C65F3FA1A1133E6005A76A3 /* Sample */,
);
name = ViewControllers;
sourceTree = "";
};
5CE2719C195B141A007FCF44 /* Markup */ = {
isa = PBXGroup;
children = (
5CE2718C195B1412007FCF44 /* GONMarkup.h */,
5CE2718D195B1412007FCF44 /* GONMarkup.m */,
5CB1C5A6195B333B00590186 /* Private */,
);
name = Markup;
sourceTree = "";
};
5CE271A1195B1437007FCF44 /* DefaultMarkup */ = {
isa = PBXGroup;
children = (
5CB1C582195B1A0100590186 /* GONMarkupDefaultMarkups.h */,
5CC43CD2197E613800E46A03 /* Alignment */,
5C43EE461A8251510053A667 /* Anchor */,
5CB1C58B195B24DB00590186 /* Block */,
5CB1C583195B1A3100590186 /* Color */,
5CB1C584195B1A3500590186 /* Font */,
5CB1C5AA195B4F8900590186 /* List */,
5C4241B41C8997F500E5B289 /* Image */,
5CC284B41979746D0009D443 /* Simple */,
5CB1C599195B25A400590186 /* Special */,
5C65F3DF1A111468005A76A3 /* TextSize */,
5CD617E419828AF50001C3D9 /* TextStyle */,
);
name = DefaultMarkup;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
5CE2714C195B11E0007FCF44 /* GONMarkupParserSample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5CE2717F195B11E0007FCF44 /* Build configuration list for PBXNativeTarget "GONMarkupParserSample" */;
buildPhases = (
F5CFB22B9E5CC0864471E289 /* [CP] Check Pods Manifest.lock */,
5CE27149195B11E0007FCF44 /* Sources */,
5CE2714A195B11E0007FCF44 /* Frameworks */,
5CE2714B195B11E0007FCF44 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = GONMarkupParserSample;
productName = GONMarkupParserSample;
productReference = 5CE2714D195B11E0007FCF44 /* GONMarkupParserSample.app */;
productType = "com.apple.product-type.application";
};
5CE2716D195B11E0007FCF44 /* GONMarkupParserSampleTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5CE27182195B11E0007FCF44 /* Build configuration list for PBXNativeTarget "GONMarkupParserSampleTests" */;
buildPhases = (
5CE2716A195B11E0007FCF44 /* Sources */,
5CE2716B195B11E0007FCF44 /* Frameworks */,
5CE2716C195B11E0007FCF44 /* Resources */,
);
buildRules = (
);
dependencies = (
5CE27174195B11E0007FCF44 /* PBXTargetDependency */,
);
name = GONMarkupParserSampleTests;
productName = GONMarkupParserSampleTests;
productReference = 5CE2716E195B11E0007FCF44 /* GONMarkupParserSampleTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
5CE27145195B11E0007FCF44 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = "Nicolas Goutaland";
TargetAttributes = {
5CE2716D195B11E0007FCF44 = {
TestTargetID = 5CE2714C195B11E0007FCF44;
};
};
};
buildConfigurationList = 5CE27148195B11E0007FCF44 /* Build configuration list for PBXProject "GONMarkupParserSample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 5CE27144195B11E0007FCF44;
productRefGroup = 5CE2714E195B11E0007FCF44 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
5CE2714C195B11E0007FCF44 /* GONMarkupParserSample */,
5CE2716D195B11E0007FCF44 /* GONMarkupParserSampleTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
5CE2714B195B11E0007FCF44 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5CE27169195B11E0007FCF44 /* Images.xcassets in Resources */,
5C65F4051A1139CD005A76A3 /* PlaygroundViewController.xib in Resources */,
5C4241B91C89995A00E5B289 /* lama.png in Resources */,
5CB1C5A8195B3B7400590186 /* ComplexExample in Resources */,
5C65F3FF1A1133F8005A76A3 /* SampleViewController.xib in Resources */,
5C65F3F31A112EBE005A76A3 /* MainWindow.xib in Resources */,
5CE2715B195B11E0007FCF44 /* InfoPlist.strings in Resources */,
5C65F3F91A112F3A005A76A3 /* RootViewController.xib in Resources */,
5C404BD01A1C951F007DCB2C /* DefaultConfigurationViewController.xib in Resources */,
5C65F4071A1153A2005A76A3 /* ResultViewController.xib in Resources */,
5C65F40D1A11FFFE005A76A3 /* ComplexExampleViewController.xib in Resources */,
5C65F3F11A112231005A76A3 /* samples.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5CE2716C195B11E0007FCF44 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5CE2717A195B11E0007FCF44 /* InfoPlist.strings in Resources */,
5CB1C5A9195B3B7400590186 /* ComplexExample in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
F5CFB22B9E5CC0864471E289 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-defaults-GONMarkupParserSample-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5CE27149195B11E0007FCF44 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5CB1C5B9195B55BE00590186 /* GONMarkupLineBreak.m in Sources */,
5CE2719A195B1412007FCF44 /* GONMarkupFont.m in Sources */,
5CE1493D19CC2B6900B73518 /* GONMarkupBold.m in Sources */,
5CE27198195B1412007FCF44 /* GONMarkupParser.m in Sources */,
5C2E11E41B8A146D0065D29C /* UIButton+GONMarkupParser.m in Sources */,
5C396DD21A80D80800AC8E45 /* GONMarkupLineStyle.m in Sources */,
5CB1C5A0195B2B7700590186 /* GONMarkupNamedFont.m in Sources */,
5CB1C58E195B24F200590186 /* GONMarkupBlock.m in Sources */,
5C65F4041A1139CD005A76A3 /* PlaygroundViewController.m in Sources */,
5CB1C5B5195B4FB600590186 /* GONMarkupListItem.m in Sources */,
5C1D1C2E19920D7100F7B642 /* GONMarkupParagraph.m in Sources */,
5CC284B7197974870009D443 /* GONMarkupSimple.m in Sources */,
5CD617E719828B1C0001C3D9 /* GONMarkupTextStyle.m in Sources */,
5C404BCC1A1C9115007DCB2C /* DefaultConfigurationViewController.m in Sources */,
5C65F40B1A11FDB2005A76A3 /* ComplexExampleViewController.m in Sources */,
5C43EE491A8251920053A667 /* GONMarkupAnchor.m in Sources */,
5C44A9D119D0690A00CF6957 /* GONMarkupFontTraits.m in Sources */,
5CB3107219BE027A00B06D0D /* UITextField+GONMarkupParser.m in Sources */,
5C7C5B291994CB55003BE47A /* GONMarkupParserUtils.m in Sources */,
5CE1493A19CC2B6300B73518 /* GONMarkupItalic.m in Sources */,
5CB3106F19BE026C00B06D0D /* UILabel+GONMarkupParser.m in Sources */,
5CE27196195B1412007FCF44 /* GONMarkupColor.m in Sources */,
5C65F3F81A112F3A005A76A3 /* RootViewController.m in Sources */,
5CB1C59C195B25E800590186 /* GONMarkupReset.m in Sources */,
5C65F3EA1A1114EC005A76A3 /* GONMarkupInc.m in Sources */,
5CB1C58A195B1EE600590186 /* GONMarkupNamedColor.m in Sources */,
5CE27161195B11E0007FCF44 /* AppDelegate.m in Sources */,
5CB1C5AD195B4FA000590186 /* GONMarkupList.m in Sources */,
5CD617E319828AA90001C3D9 /* GONMarkupParserManager.m in Sources */,
5C65F3ED1A11150A005A76A3 /* GONMarkupDec.m in Sources */,
5C43EE511A8267D60053A667 /* UITextView+GONMarkupParser.m in Sources */,
5C0790A81ED74D0B0011FF0E /* GONMarkupStrong.m in Sources */,
5CE2715D195B11E0007FCF44 /* main.m in Sources */,
5CB1C5A4195B333700590186 /* GONMarkup+Private.m in Sources */,
5CE27194195B1412007FCF44 /* GONMarkup.m in Sources */,
5CC43CD5197E616600E46A03 /* GONMarkupAlignment.m in Sources */,
5CB1C580195B19C400590186 /* ResultViewController.m in Sources */,
5C65F3FE1A1133F8005A76A3 /* SampleViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5CE2716A195B11E0007FCF44 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5C43EE4A1A8251920053A667 /* GONMarkupAnchor.m in Sources */,
5CB1C590195B250A00590186 /* GONMarkupNamedColor.m in Sources */,
5CB1C5AE195B4FA000590186 /* GONMarkupList.m in Sources */,
5C396DD31A80D80800AC8E45 /* GONMarkupLineStyle.m in Sources */,
5CE2717C195B11E0007FCF44 /* GONMarkupParserSampleTests.m in Sources */,
5C43EE521A8267D60053A667 /* UITextView+GONMarkupParser.m in Sources */,
5CB1C591195B250A00590186 /* AppDelegate.m in Sources */,
5CB1C5A1195B2B7700590186 /* GONMarkupNamedFont.m in Sources */,
5C7C5B2A1994CB55003BE47A /* GONMarkupParserUtils.m in Sources */,
5CB1C593195B250A00590186 /* ResultViewController.m in Sources */,
5CB1C5B6195B4FB600590186 /* GONMarkupListItem.m in Sources */,
5CB1C5A5195B333700590186 /* GONMarkup+Private.m in Sources */,
5CE27195195B1412007FCF44 /* GONMarkup.m in Sources */,
5CB1C59D195B25E800590186 /* GONMarkupReset.m in Sources */,
5CE2719B195B1412007FCF44 /* GONMarkupFont.m in Sources */,
5CE27199195B1412007FCF44 /* GONMarkupParser.m in Sources */,
5CB1C5BA195B55BE00590186 /* GONMarkupLineBreak.m in Sources */,
5CE27197195B1412007FCF44 /* GONMarkupColor.m in Sources */,
5CB1C594195B250A00590186 /* main.m in Sources */,
5CB1C58F195B250A00590186 /* GONMarkupBlock.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
5CE27174195B11E0007FCF44 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5CE2714C195B11E0007FCF44 /* GONMarkupParserSample */;
targetProxy = 5CE27173195B11E0007FCF44 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
5CE27159195B11E0007FCF44 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
5CE2715A195B11E0007FCF44 /* en */,
);
name = InfoPlist.strings;
sourceTree = "";
};
5CE27178195B11E0007FCF44 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
5CE27179195B11E0007FCF44 /* en */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
5CE2717D195B11E0007FCF44 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
5CE2717E195B11E0007FCF44 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
5CE27180195B11E0007FCF44 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A11B08D3B67C671A7C1F41EB /* Pods-defaults-GONMarkupParserSample.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "GONMarkupParserSample/GONMarkupParserSample-Prefix.pch";
INFOPLIST_FILE = "GONMarkupParserSample/GONMarkupParserSample-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.nicolasgoutaland.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
5CE27181195B11E0007FCF44 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = CB19407DB2362C93C6FF1BC5 /* Pods-defaults-GONMarkupParserSample.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "GONMarkupParserSample/GONMarkupParserSample-Prefix.pch";
INFOPLIST_FILE = "GONMarkupParserSample/GONMarkupParserSample-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.nicolasgoutaland.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
5CE27183195B11E0007FCF44 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/GONMarkupParserSample.app/GONMarkupParserSample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "GONMarkupParserSample/GONMarkupParserSample-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "GONMarkupParserSampleTests/GONMarkupParserSampleTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.nicolasgoutaland.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
5CE27184195B11E0007FCF44 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/GONMarkupParserSample.app/GONMarkupParserSample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "GONMarkupParserSample/GONMarkupParserSample-Prefix.pch";
INFOPLIST_FILE = "GONMarkupParserSampleTests/GONMarkupParserSampleTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.nicolasgoutaland.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5CE27148195B11E0007FCF44 /* Build configuration list for PBXProject "GONMarkupParserSample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5CE2717D195B11E0007FCF44 /* Debug */,
5CE2717E195B11E0007FCF44 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5CE2717F195B11E0007FCF44 /* Build configuration list for PBXNativeTarget "GONMarkupParserSample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5CE27180195B11E0007FCF44 /* Debug */,
5CE27181195B11E0007FCF44 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5CE27182195B11E0007FCF44 /* Build configuration list for PBXNativeTarget "GONMarkupParserSampleTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5CE27183195B11E0007FCF44 /* Debug */,
5CE27184195B11E0007FCF44 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 5CE27145195B11E0007FCF44 /* Project object */;
}
================================================
FILE: Example/GONMarkupParserSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Example/GONMarkupParserSample.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Example/GONMarkupParserSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
IDEDidComputeMac32BitWarning
================================================
FILE: Example/GONMarkupParserSampleTests/GONMarkupParserSampleTests-Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: Example/GONMarkupParserSampleTests/GONMarkupParserSampleTests.m
================================================
//
// GONMarkupParserSampleTests.m
// GONMarkupParserSampleTests
//
// Created by Nicolas Goutaland on 25/06/14.
// Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
#import
@interface GONMarkupParserSampleTests : XCTestCase
@end
@implementation GONMarkupParserSampleTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
================================================
FILE: Example/GONMarkupParserSampleTests/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: Example/PodFile
================================================
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
abstract_target 'defaults' do
pod 'NSString+Color'
pod 'LazyProperty'
target 'GONMarkupParserSample'
end
================================================
FILE: GONMarkupParser.podspec
================================================
Pod::Spec.new do |s|
s.name = "GONMarkupParser"
s.version = "0.8.2"
s.summary = "NSAttributedString generation from NSString using XML, that can be easily extended."
s.platform = :ios, "7.0"
s.description = <<-DESC
Creating rich text under iOS can be cumbersome, needing a lot of code.
The main goal of GONMarkupParser is to provide an easy to use syntax, near XML/HTML, but more flexible.
Some others projects exists, allowing you to build NSAttributedString from HTML, but my main goal here was to focus on text semantic. In fact, the parser will detect registered markup and apply style on text.
The purpose of this was to be able to generate different outputs from the same input string, without editing its content, but editing the markups style.
GONMarkupParser is not an out of the box solution to parse HTML files.
ARC only
DESC
s.homepage = "https://github.com/nicolasgoutaland/GONMarkupParser"
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { "nicolasgoutaland" => "nicolas.goutaland@gmail.com" }
s.source = { :git => "https://github.com/nicolasgoutaland/GONMarkupParser.git", :tag => "#{s.version}" }
s.source_files = 'Classes', 'Classes/**/*.{h,m}'
s.exclude_files = 'Classes/Exclude'
s.requires_arc = true
s.dependency "NSString+Color"
s.framework = 'CoreText'
end
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 nicolasgoutaland
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# GONMarkupParser
Easily build NSAttributedString from XML/HTML like strings.
## Demo

## TL;DR;
```
NSString *inputText = @"Simple input text, using a preconfigured parser.\nThis text will be displayed in red>.\nThis one will be displayed in small>.\nNow a list:\nFirst item> Second item> Third blue item>>Fourth bold green item/>";
// No custom configuration, use default tags only
// Affect text to label
label.attributedText = [[GONMarkupParserManager sharedParser] attributedStringFromString:inputText
error:nil];
// You can also use [label setMarkedUpText:inputText];
````

Need a more complex example ?
```
NSString *inputText = @"Simple input text, using a preconfigured parser.\nThis text will be displayed in red>.\nThis one will be displayed in small>.\nThis one is a custom one, to demonstrate how easy it is to declare a new markup.>";
// Set your custom configuration here
#ifdef DEBUG
[GONMarkupParserManager sharedParser].logLevel = GONMarkupParserLogLevelAll; // Fuck yeah, error debugging
#endif
// Set default string configuration
[[GONMarkupParserManager sharedParser].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;
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupSimple simpleMarkup:@"pwet"
style:@{
NSParagraphStyleAttributeName : defaultParagraphStyle,
NSForegroundColorAttributeName : [@"pink" representedColor] // NSString+Color
}
mergingStrategy:GONMarkupSimpleMergingStrategyMergeAll]];
// Add add font markup, to display small text when encountered
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupNamedFont namedFontMarkup:[UIFont systemFontOfSize:12.0] forTag:@"small"]];
// Add a convenient tag for red color
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupNamedColor namedColorMarkup:[UIColor redColor]
forTag:@"red"]];
// Affect text to label
label.attributedText = [[GONMarkupParserManager sharedParser] attributedStringFromString:inputText
error:nil];
````

## Description
Creating rich text under iOS can be cumbersome, needing a lot of code.
The main goal of GONMarkupParser is to provide an easy to use syntax, near XML/HTML, but more flexible.
Some others projects exists, allowing you to build NSAttributedString from HTML, but my main goal here was to focus on text semantic. In fact, the parser will detect registered markups and apply style on text.
The purpose of this was to be able to generate different outputs from the same input string, without editing its content, but editing the markups style.
GONMarkupParser is **not** an out of the box solution to parse HTML files.
## Installation
__CocoaPods__:
`pod 'GONMarkupParser'`
__Manual__: Copy the __Classes__ folder in your project. You will also need to __manually__ install [NSString+Color](https://github.com/nicolasgoutaland/NSString-Color). Seriously, consider using [cocoapods](http://cocoapods.org) instead ;)
Import wanted headers in your project. .pch is a good place ;)
__GONMarkupParser_All.h__ will reference all library headers, whereas __GONMarkupDefaultMarkups.h__ only references default markup classes.
## Usage
- instantiate a new __GONMarkupParser__ or use the __+ GONMarkupParserManager sharedParser__ one.
- configure your parser adding supported tags, default ones, custom ones, etc...
- parse input string and retrieve result __NSMutableAttributedString__ using __- attributedStringFromString:error:__ method from __GONMarkupParser__
- you can also set text on __UILabel__ / __UITextField__ / __UITextView__ / __UIButton__ by using [__setMarkedUpText:__](#available-uikit-categories) methods
## How does it work ?

To fully understand how style will be applied to string, you have to imagine a [LIFO stack](http://en.wikipedia.org/wiki/LIFO_(computing)) composed of style description.
Each time a new markup is found, current style configuration will be saved then stacked. New configuration will be the previous one, updated by current markup configuration.
Each time a closing markup is found, current style configuration is popped out, and previous one restored.
## Syntax
Syntax is pretty easy. It's like XML, but non valid one, to be easier and faster to write.
- Each markup should be contained between __<__ and __>__ characters
- __<strong>__
- Like XML, closing markup should start with __/__ character. You can omit markup name in closing tag. If closing tag isn't matching currently opened one, an error will be generated, no crash will occur and generated text may not be be as expected
- __</strong>__, __>__
- You can also close all opened markup by using __/>__
### Examples
```
This is a valid string with some red bold text .
This is a valid>string with some red bold text>>.
This is a valid string with some red bold text. // Will work but generates an error
This is a valid> string with some red bold text/>.
```
## Parser
### Constructor
__GONMarkupParser__ class provide two class constructors.
- __+ defaultMarkupParser__ is a parser with all default tags registered (See [Default tags summary](#default-tags) for more information)
- __+ emptyMarkgiupParser__ is a parser without any registered tags
### Properties
A parser can have a pre / post processing block, that will be called prior and after parsing. This allows you to perform some string replace before parsing for example.
Parsers have two interesting properties :
- __replaceNewLineCharactersFromInputString__, is intended to strip all newlines characters from input string. Use __br__ markup to add new lines. Default is __NO__.
- __replaceHTMLCharactersFromOutputString__, is intended to replace all HTML entities contained in string, after parsing. Default is __YES__.
__defaultConfiguration__ will contains default style configuration for generated attributed string. Content should be valid attributes parameters, as you may pass to __- addAttributes:range:__ of __NSMutableAttributedString__ objects. For default text color, you can set __NSForegroundColorAttributeName__ for example.
For debugging purpose, you can configure __debugLevel__ property.
__assertOnError__ property is also available to generate an assert when an error is encountered.
### Configuration
A parser must have some registered markups to correctly handling strings.
Use __- addMarkup:__, __- addMarkups:__, __- removeMarkups:__ and __- removeAllMarkups__ methods for that purpose.
__A markup can be added to only one parser at a time.__
### Registered fonts
To simplify fonts uses, you can register then using __- registerFont:forKey:__ method, then referencing them using given key.
Very useful with __<font>__ markup, allowing you to directly use code instead of full font name. You can also use codes such as __mainFont__, __titleFont__ to easily update them later throught all your strings.
## GONMarkupParserManager
### sharedParser
A shared parser is available, so you don't have to create one and reference it throught all your application.
Shared parser is configured with all default markups.
### Parsers registration
You can register some parser to this class, allowing you to use them from different places in your application.
## Available UIKit Categories
__UILabel__/__UITextField__/__UITextView__
2 methods were added to UILabel, UITextField and UITextView, allowing you to easily update its attributed string using a markedup one.
- __- setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser__ will use given parser to handle string and generate attributed one.
- __- setMarkedUpText:(NSString *)text__ will use shared one, aka __[GONMarkupParserManager sharedParser]__
If no parser default configuration is set for __NSForegroundColorAttributeName__, __NSFontAttributeName__ and NSParagraphStyleAttributeName, components __textColor__, __textAlignment__ and __font__ properties will be used as default.
You are strongly encouraged to use these methods if you want to use your component style as default parser configuration.
## Anchor support
Anchor support is supported using __<a href="...">__ markup.
If __NSAttributedString__ is displayed in a UITextView, you can handle user clicks on it.
Be sure your UITextView is __non editable__, __selectable__ and have its __delegate__ set.
Then, in your delegate, implements
```- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange```
method.
Color style won't be applied to links. You have to use __linkTextAttributes__ attribute from your __UITextView__ to set it.
## Default tags
### Summary
| Tag | Class | Parameters | Effect |
|:-------------:|-------------| -----|---|
| **left** | GONMarkupAlignment | none | Force text alignment to left |
| **right** | GONMarkupAlignment | none | Force text alignment to right |
| **center** | GONMarkupAlignment | none | Force text alignment to center |
| **justified** | GONMarkupAlignment | none | Force text alignment to justified |
| **natural** | GONMarkupAlignment | none | Force text alignment to natural |
| **color** | GONMarkupColor | **value** | Set text color. For supported __value__ syntaxes, check [NSString+Color](https://github.com/nicolasgoutaland/NSString-Color) [__representedColor__](https://github.com/nicolasgoutaland/NSString-Color#example) method. |
| **N/A** | GONMarkupNamedColor | none | Set text color. Can be used to reset text color to parser default one if specified color is nil |
| **font** | GONMarkupFont | **size**, **name**, **color** | Set text font, text size or both. Can be used also to set text color |
| **N/A** | GONMarkupNamedFont | none | Set text font and size. Can be used to reset font to parser default one if specified font is nil |
| **br** | GONMarkupLineBreak | none | Add a new line |
| **ul** | GONMarkupList | none | Create an unordered list |
| **ol** | GONMarkupList | none | Create an ordered list |
| **li** | GONMarkupListItem | none | Add a list item to current list |
| **p** | GONMarkupParagraph | none | Specify a paragraph. A paragraph will automatically insert a new blanck line after it |
| **inc** | GONMarkupInc | **value** | Increment text font size. If __value__ is missing, font will be increased by one point |
| **dec** | GONMarkupDec | **value** | Decrement text font size. If __value__ is missing, font will be decreased by one point |
| **reset** | GONMarkupReset | **all** | All enclosed text will use default parser configuration |
| **N/A** | GONMarkupSimple | none | Apply a configuration to enclosed text |
| **b** | GONMarkupBold | none | Set text to bold. Allows user to define an override block overrideBlock to provide another font. Useful to provide a medium font instead of bold one for example.|
| **strong** | GONMarkupStrong | none | Set text to strong (bold). Allows user to define an override block overrideBlock to provide another font. Useful to provide a medium font instead of bold one for example.|
| **i** | GONMarkupItalic | none | Set text to italic. Allows user to define an override block overrideBlock to provide another font. Useful to provide a medium italic font instead of bold italic one for example.|
| **sup** | GONMarkupTextStyle | none | Set text to superscript |
| **sub** | GONMarkupTextStyle | none | Set text to subscript |
| **u** | GONMarkupLineStyle | __words__ to apply style only on words (true, **false**), __pattern__ (**solid**, dot, dash, dashdot, dashdotdot), __style__ (**single**, thick, double) and __color__ (Check [NSString+Color](https://github.com/nicolasgoutaland/NSString-Color) [__representedColor__](https://github.com/nicolasgoutaland/NSString-Color#example) method)| Underline text |
| **strike** | GONMarkupLineStyle | __words__ to apply style only on words (true, **false**), __pattern__ (**solid**, dot, dash, dashdot, dashdotdot), __style__ (**single**, thick, double) and __color__ (Check [NSString+Color](https://github.com/nicolasgoutaland/NSString-Color) [__representedColor__](https://github.com/nicolasgoutaland/NSString-Color#example) method)|strikethrough text |
| **a** | GONMarkupAnchor | __href__ link value | Support an anchor link. See [Anchor support](#anchor-support) for more information. |
| **N/A** | GONMarkupBlock | none | When encountered executes associated block |
### Reset
Reset is a special tag, allowing you to protect some parts of a string. You can also force markup to ignore default parser configuration by setting __all__ attribute.

## How to add new markup
You can add new markup in your application, to add new style, or to just add some semantic to your text, allowing you to update rendering, without changing input string.
There is 3 ways to do it.
### Adding a new simple marker
The simpler way to add a new markup in your application is to use one of theses 3 following classes :
- __GONMarkupNamedColor__, allows you to add a markup that updates text color
- __GONMarkupNamedFont__, allows you to add a markup that updates text font
- __GONMarkupSimple__, allows you to add a markup that updates all text attributes. Dictionary is intended to be the same as you may pass to configure an __NSMutableAttributedString__ using -setAttributes:range: method.
#### Example
```
// Retrieve shared parser
GONMarkupParser *parser = [GONMarkupParserManager sharedParser];
// Add a named color markup
[parser addMarkup:[GONMarkupNamedColor namedColorMarkup:[UIColor redColor]
forTag:@"red"]];
// Add a named font markup
[parser addMarkup:[GONMarkupNamedFont namedFontMarkup:[UIFont systemFontOfSize:12.0]
forTag:@"small"]];
// 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]];
````
### Adding a new block based marker
For more complexe markup, you can add __GONMarkupBlock__ instances.
It have blocks 5 parameters :
- __openingMarkupBlock__, called when markup opening is found. Used to pushed your custom configuration to stack
- __closingMarkupBlock__, called once markup is closed.
- __updatedContentStringBlock__, called right after __closingMarkupBlock__, allowing you to override returned string
- __prefixStringForContextBlock__, called right after __openingMarkupBlock__, allowing you to return a prefix
- __suffixStringForContextBlock__, called right after __openingMarkupBlock__, allowing you to return a suffix
#### Example
```
// Retrieve shared parser
GONMarkupParser *parser = [GONMarkupParserManager sharedParser];
// Custom markup, based on block
GONMarkupBlock *markupBlock = [GONMarkupBlock blockMarkup:@"custom"];
markupBlock.openingMarkupBlock = ^(NSMutableDictionary *configurationDictionary, NSString *tag, NSMutableDictionary *context, NSDictionary *attributes) {
// Update font size
[configurationDictionary setObject:[UIFont boldSystemFontOfSize:69.0]
forKey:NSFontAttributeName];
// Update text color
[configurationDictionary setObject:[@"brown" representedColor]
forKey:NSForegroundColorAttributeName];
};
[parser addMarkup:markupBlock];
````
### Creating a new GONMarkup subclass
You can add a custom markup by subclassing __GONMarkup__ class.
Adding a new markup by subclassing is useful if you want to reuse your markups between several projets, or to implement more complex behavior. When subclassing, you have access to a shared object, allowing you to persists data and share it between each markup handling.
For examples, have a look a currently defined markups ;)
See __GONMarkupList__ and __GONMarkupListItem__ for an implementation using shared context.
## Troubleshooting
### Some text is missing
Check that your markup is correctly registered and that your tags are right balanced.
### When using < / >, some text is missing
Use < and > in text.
### Text color is still applied after my tag is closed.
This is caused by __NSAttributedString__ internal behavior. Once a color is set, it is applied until a new one is set.
To prevent this problem, be sure to have set a default text color in your parser (__defaultConfiguration__ / __NSForegroundColorAttributeName__ key). You can use __setMarkedUpText:__ on __UILabel__ / __UITextField__ to use default component configuration.
### Text style isn't applied to my link
See [Anchor support](#anchor-support) for more information.
### I am encountering some crashes when using custom font
Be sure to use correct font name, or that font code you are using is correctly registered to your parser.
Want to dump all available fonts on your device and check real names ?
Have a look [at DUMP_FONT_LIST() here](https://github.com/nicolasgoutaland/GONMacros#gonutilsmacrosh)
### No new lines are inserted using __<br>__
*__<br>__* alone is not valid in __GONMarkupParser__. Be sure to use __<br/>__.
### Color isn't applied
Check that you color value synthax is correct.
For more information on supported synthax, have a look at [NSString+UIColor here](https://github.com/nicolasgoutaland/NSString-Color#nsstringcolor-), that is used to compute colors from your string values.
### Did Kim Kardashian broke the Internet ?
No, definitely not. I was still able to push to GitHub yesterday.
## Evolutions
- Allow indentation prefix in lists customisation
- Implement **NSCoder** in parser and Markers
- Allow **copy** on parsers / markers
- Improve closing tag
## Contributors
See the [Contributors page](https://github.com/nicolasgoutaland/GONMarkupParser/graphs/contributors) on github.
## Changelog
Changelog can be found [here](https://github.com/nicolasgoutaland/GONMarkupParser/blob/master/CHANGELOG.md)