25

I'm writing a Cocoa application in Objective-C, and I would like to be able to incorporate Markdown. The user will enter text in Markdown syntax, click an "export" button, and the program will output a file of XHTML.

It seems like there are a lot of options, though. I could use one of the C/C++ implementations, I could run the Perl script as a resource to my Cocoa app, I assume could use the Python implementation and the PyObjC bridge or the Perl implementation and the CamelBones or PerlObjC bridges. What would be the simplest and easiest solution? I'm not doing anything complicated like a real-time rendered preview that would require threading.

Community
  • 1
  • 1
Ellie P.
  • 4,133
  • 3
  • 30
  • 30

6 Answers6

32

I had a look at the various options, and in the end found libsoldout, a very small C implementation that's quite easy to integrate. You just need to include array.[ch], buffer.[ch], markdown.[ch], and renderers.[ch] in your Xcode project, then you can convert an NSString from markdown to HTML like so:

NSString *rawMarkdown;
const char * prose = [rawMarkdown UTF8String];  
struct buf *ib, *ob;       

int length = rawMarkdown.length + 1;

ib = bufnew(length);
bufgrow(ib, length);
memcpy(ib->data, prose, length);
ib->size = length;

ob = bufnew(64);
markdown(ob, ib, &mkd_xhtml);

NSString *shinyNewHTML = [NSString stringWithUTF8String: ob->data];
NSLog(@"%@", shinyNewHTML);

bufrelease(ib);
bufrelease(ob);
Demitri
  • 13,134
  • 4
  • 40
  • 41
Michael
  • 1,355
  • 2
  • 12
  • 15
  • Thanks. This solution is easy to implement and works incredibly well. – Chris Samuels May 23 '11 at 10:56
  • Sorry to come back to this almost a year later, but any idea why this would not get the last tag or two? With this code exactly, it always leaves off the last xhtml tag... weird! – Marshall Moutenot Jul 31 '12 at 05:29
  • 1
    I have the same issue as @MarshallMoutenot, last tag is disappearing. It seems like sundown inserts '\0' char before the last tag, because '\0' char appears at the end of original string. After I replaced 'int length = rawMarkdown.length + 1;' with 'int length = rawMarkdown.length;' the problem disappeared. – Andrew Kurinnyi Jan 20 '13 at 05:44
  • It looks like important addition for UTF content, it should be: `long length = [rawMarkdown lengthOfBytesUsingEncoding:NSUTF8StringEncoding];` instead of `int length = rawMarkdown.length + 1;` Because we need to know number of bytes in string instead of number of symbols. – Maks Feb 11 '17 at 11:15
19

I just used the Sundown implementation which includes SmartyPants support, in an iPad app with great success. Took about 15 minutes to build a test app.

Assume you have a UITextView *textView (which you setDelegate:self) and also a UIWebView *webView in which to display the results:

- (void) textViewDidEndEditing:(UITextView *)textView
{
    NSString *rawMarkdown = [textView text];
    const char * prose = [rawMarkdown UTF8String];  
    struct buf *ib, *ob;       

    int length = [rawMarkdown lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;

    ib = bufnew(length);
    bufgrow(ib, length);
    memcpy(ib->data, prose, length);
    ib->size = length;

    ob = bufnew(64);

    struct sd_callbacks callbacks;
    struct html_renderopt options;
    struct sd_markdown *markdown;


    sdhtml_renderer(&callbacks, &options, 0);
    markdown = sd_markdown_new(0, 16, &callbacks, &options);

    sd_markdown_render(ob, ib->data, ib->size, markdown);
    sd_markdown_free(markdown);


    NSString *shinyNewHTML = [NSString stringWithUTF8String: ob->data];
    [webView loadHTMLString:shinyNewHTML baseURL:[[NSURL alloc] initWithString:@""]];

    bufrelease(ib);
    bufrelease(ob);
}
fabian789
  • 8,348
  • 4
  • 45
  • 91
DreamTimeStudioZ
  • 576
  • 5
  • 12
  • Looks like the link is no longer valid. – bloudraak Nov 22 '12 at 20:01
  • Note that sundown is derived from upskirt (now soldout) – Vervious Jan 07 '13 at 04:52
  • 1
    This seems to cut off the last tag, e.g. `test` becomes `

    test`.

    – Jason Feb 08 '13 at 15:11
  • To fix the missing last tag problem. You can remove the +1 at the end of `int length`, then add `bufcstr(ob);` after `sd_markdown_free(markdown);` This is something about the zero-terminated string. For details pls refer to the README of [Libsoldout](http://fossil.instinctive.eu/libsoldout/index), which is the original codebase of Sundown. – Kelvin Dec 02 '14 at 03:33
16

You may want to check out the open-source app Macdown which I wrote (or alternatively rentzsch's Markdownlive), which incorporate this functionality as the sole purpose of the two apps.

masukomi
  • 10,313
  • 10
  • 40
  • 49
Steven
  • 916
  • 10
  • 19
  • Thank you--those are extremely helpful and simple examples. – Ellie P. Sep 17 '09 at 19:41
  • For anyone who is interested, I decided to run the Perl script as a resource in the bundle like you do in Macdown. I found that to be the simplest and easiest solution. It works for what I want to do. I assume this requires Perl to be installed on the system (which it is out of the box, I believe.) – Ellie P. Sep 20 '09 at 22:03
7

I found problems with processing large amounts of markdown with these C-based libraries.

There's a very simple Obj-C library that worked for me here:

https://github.com/mdiep/MMMarkdown


Steps to use MMMarkdown:

  1. Build the OS X or iOS target

  2. Copy include/MMMarkdown.h and either lib/libMMMarkdown-Mac.a or lib/libMMMarkdown-iOS.a into your project

  3. Then the code is:

#import "MMMarkdown.h"

NSError  *error;
NSString *markdown   = @"# Example\nWhat a library!";
NSString *htmlString = [MMMarkdown HTMLStringWithMarkdown:markdown error:&error];
// Returns @"<h1>Example</h1>\n<p>What a library!</p>"
Diggory
  • 635
  • 9
  • 20
  • It's a little buggy and does weird things in mid-edits, but as long as your Markdown syntax is good, it does a good and fast job. – uchuugaka Jan 31 '15 at 15:22
1

I've used peg-markdown, it's much faster than the original perl and can handle a few syntax extensions if you enable them.

Arthur
  • 136
  • 3
0
  1. Oliver Letterer's GHMarkdownParser translate markdown to HTML.
  2. Phil Toland's QLMarkdown QuickLook generator for markdown files.
Cfr
  • 5,092
  • 1
  • 33
  • 50