hadley / roxygen3

23 stars 6 forks source link

Support markdown formatting #5

Open hadley opened 12 years ago

hadley commented 11 years ago

Call sequence:

An rmd_renderer is defined as:

struct rmd_renderer {
   char *name;
   Rboolean (*render)(struct buf *,struct buf *, SEXP, SEXP);
};

or maybe

struct rmd_renderer {
   char *name;
   Rboolean (*render)(struct buf *,struct buf *, SEXP, SEXP);
   char *output_type;
};

depending on whether you're looking in include/markdown_rstubs.h or src/markdown.h. It looks like you can register your own rendered with rmd_register_renderer, but that doesn't seem to be used anywhere in the source. Instead the default html rendered is set in rmd_init_renderer_list:

   /* Add HTML renderer */
   html = &RENDERERS[0];
   html->name = "HTML";
   html->render = render_to_html;
   html->output_type = "character";

Thus the key function is render_to_html. That function parses extensions and options, then the key code seems to be:

   sdhtml_renderer(&callbacks, &renderopt, options);

   markdown = sd_markdown_new(exts,16,&callbacks,(void *)&renderopt);
   sd_markdown_render(htmlbuf, ib->data, ib->size, markdown);

   sd_markdown_free(markdown);

sdhtml_renderer takes a pointer to a callback struct and fills it in with functions called rndr_*, which look like (e.g.)

static void
rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque)
{
    if (ob->size) bufputc(ob, '\n');
    BUFPUTSL(ob, "<blockquote>\n");
    if (text) bufput(ob, text->data, text->size);
    BUFPUTSL(ob, "</blockquote>\n");
} 

The possible call backs are enumerated in sd_callbacks:

struct sd_callbacks {
    /* block level callbacks - NULL skips the block */
    void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
    void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);
    void (*blockhtml)(struct buf *ob,const  struct buf *text, void *opaque);
    void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque);
    void (*hrule)(struct buf *ob, void *opaque);
    void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque);
    void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque);
    void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque);
    void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque);
    void (*table_row)(struct buf *ob, const struct buf *text, void *opaque);
    void (*table_cell)(struct buf *ob, const struct buf *text, int flags, void *opaque);

    /* span level callbacks - NULL or return 0 prints the span verbatim */
    int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque);
    int (*codespan)(struct buf *ob, const struct buf *text, void *opaque);
    int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
    int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);
    int (*image)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque);
    int (*linebreak)(struct buf *ob, void *opaque);
    int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque);
    int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque);
    int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
    int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque);
    int (*superscript)(struct buf *ob, const struct buf *text, void *opaque);

    /* low level callbacks - NULL copies input directly into the output */
    void (*entity)(struct buf *ob, const struct buf *entity, void *opaque);
    void (*normal_text)(struct buf *ob, const struct buf *text, void *opaque);

    /* header and footer */
    void (*doc_header)(struct buf *ob, void *opaque);
    void (*doc_footer)(struct buf *ob, void *opaque);
};

Probably easiest to proceed by creating way of mapping from R functions into this call back structure - that way I can write more effectively in R.

hadley commented 11 years ago

Some notes on customising redcarpet (ruby bindings for sundown): http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html. Example of custom man page renderer: https://github.com/vmg/redcarpet/blob/master/lib/redcarpet/render_man.rb. More hints on callbacks from python binding: http://misaka.61924.nl/manual/#toc_14

Potential mapping between mark and Rd:

Should probably autolink any function calls in R code.

Also need some way of including literal Rd tags.

hadley commented 11 years ago

Creating a custom renderer from R: