Skip to content

Instantly share code, notes, and snippets.

@NSExceptional
Last active September 20, 2016 07:37
Show Gist options
  • Save NSExceptional/70fc2d3ef52641b634f7038ebd3cfb8d to your computer and use it in GitHub Desktop.
Save NSExceptional/70fc2d3ef52641b634f7038ebd3cfb8d to your computer and use it in GitHub Desktop.
Snudown → NSAttributedString
@import Foundation;
@interface NSString (Markdown)
@property (nonatomic, readonly) NSAttributedString *attributedStringFromRawMarkdown;
@property (nonatomic, readonly) NSString *HTMLFromRawMarkdown;
@end
// From https://github.com/reddit/snudown
// Installation: copy /snudown to your project,
// delete everything but the html and src folders,
// and the html_block_names.txt and snudown.def files.
#include "markdown.h"
#include "html.h"
// DTCoreText is used to convert HTML into an attributed string
#import "DTCoreText.h"
// CCHLinkTextView is favored over UITextView beacuse
// it can be configured to handle the tapping of /r/subreddit autolinks.
// Not necessary, see lines 47-49.
#import "CCHLinkTextView.h"
@implementation NSString (Markdown)
- (NSAttributedString *)attributedStringFromRawMarkdown {
if (self.isEmpty) {
return [NSAttributedString new];
}
// Get HTML
NSString *html = self.HTMLFromRawMarkdown;
if (html.isEmpty) {
return [NSAttributedString new];
}
// Convert to data, gather conversion options
NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *options = @{DTDefaultFontName: @"HelveticaNeue",
DTDefaultFontFamily: @"Helvetica Neue",
DTUseiOS6Attributes: @YES,
DTDefaultFontSize: @([UIFont systemFontSize])};
// Convert to attributed string
NSMutableAttributedString *htmlToAttributedBody = [[NSMutableAttributedString alloc] initWithHTMLData:data options:options documentAttributes:nil];
// Trim trailing whitespace, set foreground text color
//
// You will have to set the foreground color of the text
// like this if the text color ever needs to change on-screen
UIColor *foregroundTextColor = [UIColor whateverYouWant];
CFStringTrimWhitespace((CFMutableStringRef)htmlToAttributedBody.mutableString);
[htmlToAttributedBody addAttribute:NSForegroundColorAttributeName
value:foregroundTextColor
range:NSMakeRange(0, htmlToAttributedBody.length)];
// Replace NSLinkAttributeName with CCHLinkAttributeName
// Unnecessary unless you're using CCHLinkTextView (which I reccomend to allow tapping of /r/subreddit autolinks)
// Remove this method call if you're not using CCHLinkTextView
[htmlToAttributedBody enumerateAttributesInRange:NSMakeRange(0, htmlToAttributedBody.length) options:NSAttributedStringEnumerationReverse usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
id linkval = attrs[NSLinkAttributeName];
if (linkval) {
[htmlToAttributedBody removeAttribute:NSLinkAttributeName range:range];
[htmlToAttributedBody addAttribute:CCHLinkAttributeName value:linkval range:range];
}
}];
return htmlToAttributedBody.copy;
}
- (NSString *)HTMLFromRawMarkdown {
if (self.isEmpty) {
return self;
}
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
struct sd_callbacks callbacks;
struct html_renderopt options;
struct sd_markdown *markdown = NULL;
// performing markdown parsing
struct buf *ob = bufnew(data.length);
sdhtml_renderer(&callbacks, &options, 0);
markdown = sd_markdown_new(1023, 16, 2, &callbacks, &options);
sd_markdown_render(ob, data.bytes, data.length, markdown);
sd_markdown_free(markdown);
NSString *html;
if (ob->size == 0) {
html = @"";
} else {
html = [[NSString alloc] initWithBytes:ob->data length:ob->size encoding:NSUTF8StringEncoding];
}
bufrelease(ob);
return html;
}
@end
// In the implementation of whatever class implements the CCHLinkTextViewDelegate protocol
- (void)linkTextView:(CCHLinkTextView *)linkTextView didTapLinkWithValue:(id)value {
if ([value isKindOfClass:[NSURL class]])
value = [value absoluteString];
NSString urlString = (id)value;
// Handle value as NSString, ie "/r/subreddit" I think
// ...
}
- (void)linkTextView:(CCHLinkTextView *)linkTextView didLongPressLinkWithValue:(id)value {
if ([value isKindOfClass:[NSURL class]])
value = [value absoluteString];
NSString urlString = (id)value;
// Handle value as NSString, ie "/r/subreddit" I think
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment