|
9 | 9 | #import "TSMarkdownParser.h" |
10 | 10 | #if TARGET_OS_IPHONE |
11 | 11 | #import <UIKit/UIKit.h> |
| 12 | +@implementation UIColor (ts) |
| 13 | +/// code compatibility layer for macOS 10.7 and 10.8 |
| 14 | ++ (UIColor *)colorWithSRGBRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { |
| 15 | + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; |
| 16 | +} |
| 17 | +@end |
12 | 18 | #else |
13 | 19 | #import <AppKit/AppKit.h> |
14 | 20 | typedef NSColor UIColor; |
@@ -47,24 +53,26 @@ - (instancetype)init { |
47 | 53 | @{ NSFontAttributeName: [UIFont boldSystemFontOfSize:13] } ]; |
48 | 54 | #endif |
49 | 55 |
|
| 56 | +#if TARGET_OS_IPHONE |
| 57 | + _emphasisAttributes = @{ NSFontAttributeName: [UIFont italicSystemFontOfSize:defaultSize] }; |
| 58 | +#else |
| 59 | + _emphasisAttributes = @{ NSFontAttributeName: [[NSFontManager sharedFontManager] convertFont:[UIFont systemFontOfSize:defaultSize] toHaveTrait:NSItalicFontMask] }; |
| 60 | +#endif |
| 61 | + |
50 | 62 | _listAttributes = @[]; |
51 | | - _quoteAttributes = @[@{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Italic" size:defaultSize]}]; |
| 63 | + // #69: avoiding crash if font is missing |
| 64 | + _quoteAttributes = @[@{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Italic" size:defaultSize] ?: [_emphasisAttributes objectForKey:NSFontAttributeName]}]; |
52 | 65 |
|
53 | 66 | _imageAttributes = @{}; |
54 | 67 | _linkAttributes = @{ NSForegroundColorAttributeName: [UIColor blueColor], |
55 | 68 | NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) }; |
56 | 69 |
|
57 | 70 | // Courier New and Courier are the only monospace fonts compatible with watchOS 2 |
58 | | - _monospaceAttributes = @{ NSFontAttributeName: [UIFont fontWithName:@"Courier New" size:defaultSize], |
59 | | - NSForegroundColorAttributeName: [UIColor colorWithRed:0.95 green:0.54 blue:0.55 alpha:1] }; |
| 71 | + // #69: avoiding crash if font is missing |
| 72 | + _monospaceAttributes = @{ NSFontAttributeName: [UIFont fontWithName:@"Courier New" size:defaultSize] ?: [UIFont fontWithName:@"Courier" size:defaultSize] ?: [UIFont systemFontOfSize:defaultSize], |
| 73 | + NSForegroundColorAttributeName: [UIColor colorWithSRGBRed:0.95 green:0.54 blue:0.55 alpha:1] }; |
60 | 74 | _strongAttributes = @{ NSFontAttributeName: [UIFont boldSystemFontOfSize:defaultSize] }; |
61 | 75 |
|
62 | | -#if TARGET_OS_IPHONE |
63 | | - _emphasisAttributes = @{ NSFontAttributeName: [UIFont italicSystemFontOfSize:defaultSize] }; |
64 | | -#else |
65 | | - _emphasisAttributes = @{ NSFontAttributeName: [[NSFontManager sharedFontManager] convertFont:[UIFont systemFontOfSize:defaultSize] toHaveTrait:NSItalicFontMask] }; |
66 | | -#endif |
67 | | - |
68 | 76 | return self; |
69 | 77 | } |
70 | 78 |
|
@@ -109,25 +117,39 @@ + (instancetype)standardParser { |
109 | 117 | /* bracket parsing */ |
110 | 118 |
|
111 | 119 | [defaultParser addImageParsingWithLinkFormattingBlock:^(NSMutableAttributedString *attributedString, NSRange range, NSString * _Nullable link) { |
112 | | - UIImage *image = [UIImage imageNamed:link]; |
113 | | - if (image) { |
114 | | - NSTextAttachment *imageAttachment = [NSTextAttachment new]; |
115 | | - imageAttachment.image = image; |
116 | | - imageAttachment.bounds = CGRectMake(0, -5, image.size.width, image.size.height); |
117 | | - NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:imageAttachment]; |
118 | | - [attributedString replaceCharactersInRange:range withAttributedString:imgStr]; |
119 | | - } else { |
120 | | - if (!weakParser.skipLinkAttribute) { |
121 | | - NSURL *url = [NSURL URLWithString:link] ?: [NSURL URLWithString: |
122 | | - [link stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; |
123 | | - if (url.scheme) { |
124 | | - [attributedString addAttribute:NSLinkAttributeName |
125 | | - value:url |
126 | | - range:range]; |
127 | | - } |
| 120 | +#if !TARGET_OS_IPHONE |
| 121 | +#if defined(__MAC_10_13) |
| 122 | + // macOS 10.11+ test compatible with Xcode 9+ |
| 123 | + // NSTextAttachment works on macOS 10.10 but is tricky for image support |
| 124 | + if (@available(macOS 10.11, iOS 7.0, watchOS 2.0, tvOS 9.0, *)) { |
| 125 | +#else |
| 126 | + // macOS 10.11+ test compatible with Xcode 8- |
| 127 | + // NSTextAttachment works on macOS 10.10 but is tricky for image support |
| 128 | + if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_10_Max) { |
| 129 | +#endif |
| 130 | +#else |
| 131 | + { |
| 132 | +#endif |
| 133 | + UIImage *image = [UIImage imageNamed:link]; |
| 134 | + if (image) { |
| 135 | + NSTextAttachment *imageAttachment = [NSTextAttachment new]; |
| 136 | + imageAttachment.image = image; |
| 137 | + imageAttachment.bounds = CGRectMake(0, -5, image.size.width, image.size.height); |
| 138 | + NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:imageAttachment]; |
| 139 | + [attributedString replaceCharactersInRange:range withAttributedString:imgStr]; |
| 140 | + return; |
| 141 | + } |
| 142 | + } |
| 143 | + if (!weakParser.skipLinkAttribute) { |
| 144 | + NSURL *url = [NSURL URLWithString:link] ?: [NSURL URLWithString: |
| 145 | + [link stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; |
| 146 | + if (url.scheme) { |
| 147 | + [attributedString addAttribute:NSLinkAttributeName |
| 148 | + value:url |
| 149 | + range:range]; |
128 | 150 | } |
129 | | - [attributedString addAttributes:weakParser.imageAttributes range:range]; |
130 | 151 | } |
| 152 | + [attributedString addAttributes:weakParser.imageAttributes range:range]; |
131 | 153 | }]; |
132 | 154 |
|
133 | 155 | [defaultParser addLinkParsingWithLinkFormattingBlock:^(NSMutableAttributedString *attributedString, NSRange range, NSString * _Nullable link) { |
@@ -197,7 +219,8 @@ + (void)addAttributes:(NSArray<NSDictionary<NSString *, id> *> *)attributesArray |
197 | 219 | { |
198 | 220 | if (!attributesArray.count) |
199 | 221 | return; |
200 | | - NSDictionary<NSString *, id> *attributes = level < attributesArray.count ? attributesArray[level] : attributesArray.lastObject; |
| 222 | + // 'objectAtIndexedSubscript:' is only available on macOS 10.8 or newer |
| 223 | + NSDictionary<NSString *, id> *attributes = level < attributesArray.count ? [attributesArray objectAtIndex:level] : attributesArray.lastObject; |
201 | 224 | [attributedString addAttributes:attributes range:range]; |
202 | 225 | } |
203 | 226 |
|
@@ -298,25 +321,39 @@ - (void)addImageParsingWithImageFormattingBlock:(TSMarkdownParserFormattingBlock |
298 | 321 | NSUInteger imagePathStart = [attributedString.string rangeOfString:@"(" options:(NSStringCompareOptions)0 range:match.range].location; |
299 | 322 | NSRange linkRange = NSMakeRange(imagePathStart, match.range.length + match.range.location - imagePathStart - 1); |
300 | 323 | NSString *imagePath = [attributedString.string substringWithRange:NSMakeRange(linkRange.location + 1, linkRange.length - 1)]; |
301 | | - UIImage *image = [UIImage imageNamed:imagePath]; |
302 | | - if (image) { |
303 | | - NSTextAttachment *imageAttachment = [NSTextAttachment new]; |
304 | | - imageAttachment.image = image; |
305 | | - imageAttachment.bounds = CGRectMake(0, -5, image.size.width, image.size.height); |
306 | | - NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:imageAttachment]; |
307 | | - [attributedString replaceCharactersInRange:match.range withAttributedString:imgStr]; |
308 | | - if (formattingBlock) { |
309 | | - formattingBlock(attributedString, NSMakeRange(match.range.location, imgStr.length)); |
310 | | - } |
311 | | - } else { |
312 | | - NSUInteger linkTextEndLocation = [attributedString.string rangeOfString:@"]" options:(NSStringCompareOptions)0 range:match.range].location; |
313 | | - NSRange linkTextRange = NSMakeRange(match.range.location + 2, linkTextEndLocation - match.range.location - 2); |
314 | | - NSString *alternativeText = [attributedString.string substringWithRange:linkTextRange]; |
315 | | - [attributedString replaceCharactersInRange:match.range withString:alternativeText]; |
316 | | - if (alternativeFormattingBlock) { |
317 | | - alternativeFormattingBlock(attributedString, NSMakeRange(match.range.location, alternativeText.length)); |
| 324 | +#if !TARGET_OS_IPHONE |
| 325 | +#if defined(__MAC_10_13) |
| 326 | + // macOS 10.11+ test compatible with Xcode 9+ |
| 327 | + // NSTextAttachment works on macOS 10.10 but is tricky for image support |
| 328 | + if (@available(macOS 10.11, iOS 7.0, watchOS 2.0, tvOS 9.0, *)) { |
| 329 | +#else |
| 330 | + // macOS 10.11+ test compatible with Xcode 8- |
| 331 | + // NSTextAttachment works on macOS 10.10 but is tricky for image support |
| 332 | + if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_10_Max) { |
| 333 | +#endif |
| 334 | +#else |
| 335 | + { |
| 336 | +#endif |
| 337 | + UIImage *image = [UIImage imageNamed:imagePath]; |
| 338 | + if (image) { |
| 339 | + NSTextAttachment *imageAttachment = [NSTextAttachment new]; |
| 340 | + imageAttachment.image = image; |
| 341 | + imageAttachment.bounds = CGRectMake(0, -5, image.size.width, image.size.height); |
| 342 | + NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:imageAttachment]; |
| 343 | + [attributedString replaceCharactersInRange:match.range withAttributedString:imgStr]; |
| 344 | + if (formattingBlock) { |
| 345 | + formattingBlock(attributedString, NSMakeRange(match.range.location, imgStr.length)); |
| 346 | + } |
| 347 | + return; |
318 | 348 | } |
319 | 349 | } |
| 350 | + NSUInteger linkTextEndLocation = [attributedString.string rangeOfString:@"]" options:(NSStringCompareOptions)0 range:match.range].location; |
| 351 | + NSRange linkTextRange = NSMakeRange(match.range.location + 2, linkTextEndLocation - match.range.location - 2); |
| 352 | + NSString *alternativeText = [attributedString.string substringWithRange:linkTextRange]; |
| 353 | + [attributedString replaceCharactersInRange:match.range withString:alternativeText]; |
| 354 | + if (alternativeFormattingBlock) { |
| 355 | + alternativeFormattingBlock(attributedString, NSMakeRange(match.range.location, alternativeText.length)); |
| 356 | + } |
320 | 357 | }]; |
321 | 358 | } |
322 | 359 |
|
|
0 commit comments