Permalink
Browse files

Added rudimentary support for rendering MarkDown as well as HTML

  • Loading branch information...
1 parent e44181c commit 8cf70b2f2f19edb687a52b63b3f03c5eae38fabb @ocrickard committed Mar 21, 2012
@@ -17,6 +17,19 @@
B10FF5711516E22C0063355F /* OCViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B10FF56F1516E22C0063355F /* OCViewController.xib */; };
B10FF5791516E2710063355F /* OCPDFGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = B10FF5781516E2710063355F /* OCPDFGenerator.m */; };
B10FF57B1516E2E40063355F /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B10FF57A1516E2E40063355F /* CoreText.framework */; };
+ B1302334151A5212008FD765 /* test2.md in Resources */ = {isa = PBXBuildFile; fileRef = B1302333151A5212008FD765 /* test2.md */; };
+ B1302335151A52B9008FD765 /* setup.c in Sources */ = {isa = PBXBuildFile; fileRef = B1302326151A515A008FD765 /* setup.c */; };
+ B1302336151A52B9008FD765 /* tags.c in Sources */ = {isa = PBXBuildFile; fileRef = B1302328151A515A008FD765 /* tags.c */; };
+ B1302337151A52B9008FD765 /* html5.c in Sources */ = {isa = PBXBuildFile; fileRef = B1302329151A515A008FD765 /* html5.c */; };
+ B1302338151A52B9008FD765 /* emmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232A151A515A008FD765 /* emmatch.c */; };
+ B1302339151A52B9008FD765 /* Csio.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232B151A515A008FD765 /* Csio.c */; };
+ B130233A151A52B9008FD765 /* xml.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232C151A515A008FD765 /* xml.c */; };
+ B130233B151A52B9008FD765 /* resource.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232D151A515A008FD765 /* resource.c */; };
+ B130233C151A52B9008FD765 /* generate.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232E151A515A008FD765 /* generate.c */; };
+ B130233D151A52B9008FD765 /* markdown.c in Sources */ = {isa = PBXBuildFile; fileRef = B130232F151A515A008FD765 /* markdown.c */; };
+ B130233E151A52B9008FD765 /* mkdio.c in Sources */ = {isa = PBXBuildFile; fileRef = B1302331151A515A008FD765 /* mkdio.c */; };
+ B130233F151A52B9008FD765 /* NSString+GHMarkdownParser.m in Sources */ = {isa = PBXBuildFile; fileRef = B1302320151A514B008FD765 /* NSString+GHMarkdownParser.m */; };
+ B1302340151A52B9008FD765 /* GHMarkdownParser.m in Sources */ = {isa = PBXBuildFile; fileRef = B1302322151A514B008FD765 /* GHMarkdownParser.m */; };
B1D66A501516E61F00623D3C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1D66A4F1516E61F00623D3C /* QuartzCore.framework */; };
B1D66AAD1516EBF400623D3C /* CGUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D66A5F1516EBF400623D3C /* CGUtils.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
B1D66AAE1516EBF400623D3C /* default.css in Resources */ = {isa = PBXBuildFile; fileRef = B1D66A601516EBF400623D3C /* default.css */; };
@@ -94,6 +107,29 @@
B10FF5771516E2710063355F /* OCPDFGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCPDFGenerator.h; sourceTree = "<group>"; };
B10FF5781516E2710063355F /* OCPDFGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCPDFGenerator.m; sourceTree = "<group>"; };
B10FF57A1516E2E40063355F /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
+ B130231F151A514B008FD765 /* NSString+GHMarkdownParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+GHMarkdownParser.h"; sourceTree = "<group>"; };
+ B1302320151A514B008FD765 /* NSString+GHMarkdownParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+GHMarkdownParser.m"; sourceTree = "<group>"; };
+ B1302321151A514B008FD765 /* GHMarkdownParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHMarkdownParser.h; sourceTree = "<group>"; };
+ B1302322151A514B008FD765 /* GHMarkdownParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHMarkdownParser.m; sourceTree = "<group>"; };
+ B1302324151A515A008FD765 /* blocktags */ = {isa = PBXFileReference; lastKnownFileType = text; path = blocktags; sourceTree = "<group>"; };
+ B1302325151A515A008FD765 /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+ B1302326151A515A008FD765 /* setup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = setup.c; sourceTree = "<group>"; };
+ B1302327151A515A008FD765 /* tags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tags.h; sourceTree = "<group>"; };
+ B1302328151A515A008FD765 /* tags.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tags.c; sourceTree = "<group>"; };
+ B1302329151A515A008FD765 /* html5.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = html5.c; sourceTree = "<group>"; };
+ B130232A151A515A008FD765 /* emmatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = emmatch.c; sourceTree = "<group>"; };
+ B130232B151A515A008FD765 /* Csio.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Csio.c; sourceTree = "<group>"; };
+ B130232C151A515A008FD765 /* xml.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = xml.c; sourceTree = "<group>"; };
+ B130232D151A515A008FD765 /* resource.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = resource.c; sourceTree = "<group>"; };
+ B130232E151A515A008FD765 /* generate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = generate.c; sourceTree = "<group>"; };
+ B130232F151A515A008FD765 /* markdown.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = markdown.c; sourceTree = "<group>"; };
+ B1302330151A515A008FD765 /* markdown.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = markdown.h; sourceTree = "<group>"; };
+ B1302331151A515A008FD765 /* mkdio.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mkdio.c; sourceTree = "<group>"; };
+ B1302332151A515A008FD765 /* mkdio.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mkdio.h; sourceTree = "<group>"; };
+ B1302333151A5212008FD765 /* test2.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = test2.md; sourceTree = "<group>"; };
+ B1302341151A52F9008FD765 /* cstring.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cstring.h; sourceTree = "<group>"; };
+ B1302342151A530E008FD765 /* amalloc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = amalloc.c; sourceTree = "<group>"; };
+ B1302343151A530E008FD765 /* amalloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = amalloc.h; sourceTree = "<group>"; };
B1D66A4F1516E61F00623D3C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
B1D66A5E1516EBF400623D3C /* CGUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGUtils.h; sourceTree = "<group>"; };
B1D66A5F1516EBF400623D3C /* CGUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGUtils.m; sourceTree = "<group>"; };
@@ -237,8 +273,9 @@
B10FF56D1516E22C0063355F /* OCViewController.m */,
B10FF5771516E2710063355F /* OCPDFGenerator.h */,
B10FF5781516E2710063355F /* OCPDFGenerator.m */,
- B1D66A5D1516EBF400623D3C /* DTCoreText */,
B10FF56F1516E22C0063355F /* OCViewController.xib */,
+ B130231E151A512D008FD765 /* GHMarkdownParser */,
+ B1D66A5D1516EBF400623D3C /* DTCoreText */,
B10FF5611516E22C0063355F /* Supporting Files */,
);
path = OCPDFGen;
@@ -247,6 +284,7 @@
B10FF5611516E22C0063355F /* Supporting Files */ = {
isa = PBXGroup;
children = (
+ B1302333151A5212008FD765 /* test2.md */,
B1D66AD91516ECC500623D3C /* test.html */,
B10FF5621516E22C0063355F /* OCPDFGen-Info.plist */,
B10FF5631516E22C0063355F /* InfoPlist.strings */,
@@ -256,6 +294,43 @@
name = "Supporting Files";
sourceTree = "<group>";
};
+ B130231E151A512D008FD765 /* GHMarkdownParser */ = {
+ isa = PBXGroup;
+ children = (
+ B1302323151A514E008FD765 /* discount */,
+ B130231F151A514B008FD765 /* NSString+GHMarkdownParser.h */,
+ B1302320151A514B008FD765 /* NSString+GHMarkdownParser.m */,
+ B1302321151A514B008FD765 /* GHMarkdownParser.h */,
+ B1302322151A514B008FD765 /* GHMarkdownParser.m */,
+ );
+ name = GHMarkdownParser;
+ sourceTree = "<group>";
+ };
+ B1302323151A514E008FD765 /* discount */ = {
+ isa = PBXGroup;
+ children = (
+ B1302324151A515A008FD765 /* blocktags */,
+ B1302342151A530E008FD765 /* amalloc.c */,
+ B1302343151A530E008FD765 /* amalloc.h */,
+ B1302325151A515A008FD765 /* config.h */,
+ B1302326151A515A008FD765 /* setup.c */,
+ B1302327151A515A008FD765 /* tags.h */,
+ B1302328151A515A008FD765 /* tags.c */,
+ B1302341151A52F9008FD765 /* cstring.h */,
+ B1302329151A515A008FD765 /* html5.c */,
+ B130232A151A515A008FD765 /* emmatch.c */,
+ B130232B151A515A008FD765 /* Csio.c */,
+ B130232C151A515A008FD765 /* xml.c */,
+ B130232D151A515A008FD765 /* resource.c */,
+ B130232E151A515A008FD765 /* generate.c */,
+ B130232F151A515A008FD765 /* markdown.c */,
+ B1302330151A515A008FD765 /* markdown.h */,
+ B1302331151A515A008FD765 /* mkdio.c */,
+ B1302332151A515A008FD765 /* mkdio.h */,
+ );
+ name = discount;
+ sourceTree = "<group>";
+ };
B1D66A5D1516EBF400623D3C /* DTCoreText */ = {
isa = PBXGroup;
children = (
@@ -399,6 +474,7 @@
B10FF5711516E22C0063355F /* OCViewController.xib in Resources */,
B1D66AAE1516EBF400623D3C /* default.css in Resources */,
B1D66ADA1516ECC500623D3C /* test.html in Resources */,
+ B1302334151A5212008FD765 /* test2.md in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -409,6 +485,18 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ B1302335151A52B9008FD765 /* setup.c in Sources */,
+ B1302336151A52B9008FD765 /* tags.c in Sources */,
+ B1302337151A52B9008FD765 /* html5.c in Sources */,
+ B1302338151A52B9008FD765 /* emmatch.c in Sources */,
+ B1302339151A52B9008FD765 /* Csio.c in Sources */,
+ B130233A151A52B9008FD765 /* xml.c in Sources */,
+ B130233B151A52B9008FD765 /* resource.c in Sources */,
+ B130233C151A52B9008FD765 /* generate.c in Sources */,
+ B130233D151A52B9008FD765 /* markdown.c in Sources */,
+ B130233E151A52B9008FD765 /* mkdio.c in Sources */,
+ B130233F151A52B9008FD765 /* NSString+GHMarkdownParser.m in Sources */,
+ B1302340151A52B9008FD765 /* GHMarkdownParser.m in Sources */,
B1D66AE21516F0B500623D3C /* default.css in Sources */,
B10FF5671516E22C0063355F /* main.m in Sources */,
B10FF56B1516E22C0063355F /* OCAppDelegate.m in Sources */,
View
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "cstring.h"
+#include "markdown.h"
+#include "amalloc.h"
+
+
+/* putc() into a cstring
+ */
+void
+Csputc(int c, Cstring *iot)
+{
+ EXPAND(*iot) = c;
+}
+
+
+/* printf() into a cstring
+ */
+int
+Csprintf(Cstring *iot, char *fmt, ...)
+{
+ va_list ptr;
+ int siz=100;
+
+ do {
+ RESERVE(*iot, siz);
+ va_start(ptr, fmt);
+ siz = vsnprintf(T(*iot)+S(*iot), ALLOCATED(*iot)-S(*iot), fmt, ptr);
+ va_end(ptr);
+ } while ( siz > (ALLOCATED(*iot)-S(*iot)) );
+
+ S(*iot) += siz;
+ return siz;
+}
+
+
+/* write() into a cstring
+ */
+int
+Cswrite(Cstring *iot, char *bfr, int size)
+{
+ RESERVE(*iot, size);
+ memcpy(T(*iot)+S(*iot), bfr, size);
+ S(*iot) += size;
+ return size;
+}
+
+
+/* reparse() into a cstring
+ */
+void
+Csreparse(Cstring *iot, char *buf, int size, int flags)
+{
+ MMIOT f;
+ ___mkd_initmmiot(&f, 0);
+ ___mkd_reparse(buf, size, 0, &f);
+ ___mkd_emblock(&f);
+ SUFFIX(*iot, T(f.out), S(f.out));
+ ___mkd_freemmiot(&f, 0);
+}
@@ -0,0 +1,17 @@
+//
+// GHMarkdownParser.h
+// GHMarkdownParser
+//
+// Created by Oliver Letterer on 01.08.11.
+// Copyright 2011 Home. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "NSString+GHMarkdownParser.h"
+
+@interface GHMarkdownParser : NSObject
+
++ (NSString *)HTMLStringFromMarkdownString:(NSString *)markdownString;
++ (NSString *)flavoredHTMLStringFromMarkdownString:(NSString *)markdownString;
+
+@end
@@ -0,0 +1,53 @@
+//
+// GHMarkdownParser.m
+// GHMarkdownParser
+//
+// Created by Oliver Letterer on 01.08.11.
+// Copyright 2011 Home. All rights reserved.
+//
+
+#import "GHMarkdownParser.h"
+#import "markdown.h"
+
+@implementation GHMarkdownParser
+
++ (NSString *)HTMLStringFromMarkdownString:(NSString *)markdownString {
+ NSString *HTMLString = nil;
+
+ char *markdownUTF8 = (char*)markdownString.UTF8String;
+ Document *document = mkd_string(markdownUTF8, strlen(markdownUTF8), 0);
+ if (document && mkd_compile(document, 0)) {
+ char *HTMLUTF8 = NULL;
+ int length = mkd_document(document, &HTMLUTF8);
+ if (length != EOF) {
+ HTMLString = [[NSString alloc] initWithBytes:HTMLUTF8
+ length:length
+ encoding:NSUTF8StringEncoding];
+ }
+ mkd_cleanup(document);
+ }
+
+ return HTMLString;
+}
+
++ (NSString *)flavoredHTMLStringFromMarkdownString:(NSString *)markdownString {
+ NSMutableString *fixedMarkdown = [NSMutableString stringWithCapacity:markdownString.length];
+ __block BOOL isCodeBlock = NO;
+ [markdownString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
+ if ([line rangeOfString:@"```"].location != NSNotFound) {
+ isCodeBlock = !isCodeBlock;
+ } else {
+ if (isCodeBlock) {
+ [fixedMarkdown appendFormat:@" %@\n", line];
+ } else {
+ [fixedMarkdown appendFormat:@"%@\n", line];
+ }
+ }
+ }];
+
+ NSString *HTML = [self HTMLStringFromMarkdownString:fixedMarkdown];
+
+ return HTML;
+}
+
+@end
@@ -0,0 +1,17 @@
+//
+// NSString+GHMarkdownParser.h
+// GHMarkdownParser
+//
+// Created by Oliver Letterer on 01.08.11.
+// Copyright 2011 Home. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSString (GHMarkdownParser)
+
+@property (nonatomic, readonly) NSString *HTMLStringFromMarkdown;
+@property (nonatomic, readonly) NSString *flavoredHTMLStringFromMarkdown;
+
+@end
@@ -0,0 +1,22 @@
+//
+// NSString+GHMarkdownParser.m
+// GHMarkdownParser
+//
+// Created by Oliver Letterer on 01.08.11.
+// Copyright 2011 Home. All rights reserved.
+//
+
+#import "NSString+GHMarkdownParser.h"
+#import "GHMarkdownParser.h"
+
+@implementation NSString (GHMarkdownParser)
+
+- (NSString *)HTMLStringFromMarkdown {
+ return [GHMarkdownParser HTMLStringFromMarkdownString:self];
+}
+
+- (NSString *)flavoredHTMLStringFromMarkdown {
+ return [GHMarkdownParser flavoredHTMLStringFromMarkdownString:self];
+}
+
+@end
@@ -13,5 +13,6 @@
+(NSString *)generatePDFFromAttributedString:(NSAttributedString *)str;
+(NSString *)generatePDFFromNSString:(NSString *)str;
+(NSString *)generatePDFFromHTMLString:(NSString *)str;
++(NSString *)generatePDFFromMarkDownString:(NSString *)md;
@end
View
@@ -9,6 +9,7 @@
#import "OCPDFGenerator.h"
#import <CoreText/CoreText.h>
#import "DTCoreText/DTCoreText.h"
+#import "NSString+GHMarkdownParser.h"
@implementation OCPDFGenerator
@@ -42,6 +43,7 @@ +(NSString *)generatePDFFromAttributedString:(NSAttributedString *)str {
int CURRENT_TOP_MARGIN = TOP_MARGIN;
+ //You can make the first page have a different top margin to place headers, etc.
int FIRST_PAGE_TOP_MARGIN = TOP_MARGIN;
CGRect a4Page = CGRectMake(0, 0, DOC_WIDTH, DOC_HEIGHT);
@@ -63,9 +65,7 @@ +(NSString *)generatePDFFromAttributedString:(NSAttributedString *)str {
CGContextSelectFont (context, [font cStringUsingEncoding:NSUTF8StringEncoding], fontSize, kCGEncodingMacRoman);
CGContextSetFillColorWithColor(context, [color CGColor]);
// Initialize an attributed string.
-// CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringRef attrString = (CFAttributedStringRef)str;
-// CFAttributedStringReplaceString (attrString, currentRange, (CFStringRef)content);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
@@ -140,7 +140,12 @@ +(NSString *)generatePDFFromHTMLString:(NSString *)html {
NSAttributedString *string = [[NSAttributedString alloc] initWithHTML:data options:options documentAttributes:NULL];
- return [self generatePDFFromAttributedString:string];
+ return [self generatePDFFromAttributedString:[string autorelease]];
+}
+
++(NSString *)generatePDFFromMarkDownString:(NSString *)md {
+ NSString *html = md.HTMLStringFromMarkdown;
+ return [self generatePDFFromHTMLString:html];
}
@end
@@ -23,10 +23,17 @@ - (void)loadView {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
- NSString *readmePath = [[NSBundle mainBundle] pathForResource:@"test.html" ofType:nil];
- NSString *html = [NSString stringWithContentsOfFile:readmePath encoding:NSUTF8StringEncoding error:NULL];
+ //Use the below code for HTML
+// NSString *readmePath = [[NSBundle mainBundle] pathForResource:@"test.html" ofType:nil];
+// NSString *html = [NSString stringWithContentsOfFile:readmePath encoding:NSUTF8StringEncoding error:NULL];
+//
+// NSString *path = [OCPDFGenerator generatePDFFromHTMLString:html];
- NSString *path = [OCPDFGenerator generatePDFFromHTMLString:html];
+ //This is for Markdown
+ NSString *readmePath = [[NSBundle mainBundle] pathForResource:@"test2.md" ofType:nil];
+ NSString *md = [NSString stringWithContentsOfFile:readmePath encoding:NSUTF8StringEncoding error:NULL];
+
+ NSString *path = [OCPDFGenerator generatePDFFromMarkDownString:md];
NSLog(@"FileExists:%d", [[NSFileManager defaultManager] fileExistsAtPath:path]);
Oops, something went wrong.

0 comments on commit 8cf70b2

Please sign in to comment.