% Discount -- a C implementation of the Markdown markup language
% Jessica L. Parsons (orc@pell.portland.or.us)
%
#Discount
>%class:tincup%
>Discount is free software released under the terms of a
>[BSD-style](COPYRIGHT.html) license.
>
>If you find it useful, please consider
>making a contribution to help support onward development.
>
>[donate?](https://www.paypal.com/donate/?hosted_button_id=E9G5WQXEFNA8U)
>
##download
[Discount 2.2.7d](discount-2.2.7d.tar.bz2), released 22-Aug-2023
##description
This is my implementation of [John Gruber][]'s [Markdown][] text to html
language. There's not much here that differentiates it from any of
the existing Markdown implementations except that it's written in
C instead of one of the vast flock of scripting languages that are
fighting it out for the Perl crown.
**Markdown** provides a library that gives you formatting functions
suitable for marking down entire documents or lines of text, a
command-line program that you can use to mark down documents interactively
or from a script, and a tiny (3 programs so far) suite of example
programs that show how to fully utilize the markdown library.
My markdown also does, by default, various [smartypants][]-style
substitutions.
###The program
The `markdown` program is a trivial compiler that reads in a markdown
file and writes out a html document or -- if you use the `-d` flag --
an outline showing the parse tree. It does have a few options;
`-d`
: is, as previously mentioned, the flag that makes markdown
produce a parse tree instead of a html document.
`-F `
: sets various [flags](#flags) that change
how markdown works. The flags argument is a somewhat less
than obvious bitmask -- for example, `-F 0x4` tells `markdown`
to **not** do the [smartypants][] translations on the output.
(there are cases -- like running the [test suite][] -- where
this is a useful feature.)
`-f `
: sets various [flags](#flags) that change how markdown works.
Unlike `-F`, these are the names of the flags (you can get
a list of the supported flags with the `-f?` option; supported
flags + synonyms with `-Vf?` ) optionally
prefixed with `no` or `-` to turn them off.
To reuse the example to disable [smartypants][], you'd do `-f nopants`
("pants" is a synonym for "smarty" == smartypants.)
`-o file`
: tells markdown to write the output to *`file`*
`-V`
: tells you a markdown version number and how the package
was configured. For example
$ markdown -V
markdown: discount 2.2.2 TAB=8 DEBUG
tells you that this is markdown 2.2.2, and that the package
was configured with support for sensible tabs & debugging
malloc.
`-VV`
: is like `-V`, except it also returns the current values of many
of the flags that can be set with `-f` or `-F`.
###The library
There are 17 public functions in the [markdown][] library, broken
into three categories:
####Input functions
1. `MMIOT *mkd_in(FILE *f, int flags)` reads a markdown input file
and returns a MMIOT containing the preprocessed document.
(which is then fed to `markdown()` for final formatting.)
2. `MMIOT *mkd_string(char *bfr, int size, int flags)` reads the
markdown input file that's been written into `bfr` and
returns a preprocessed blob suitable for feeding to `markdown()`.
This function exists because [annotations][] uses `mmap()` to
access message files instead of traditional file i/o. (If
you're going to port Markdown to an AS/400, this function *is*
the droid you've been looking for.)
####"Big Picture"-style processing functions
1. `int markdown(MMIOT *doc, FILE *out, int flags)` formats a document
(created with `mkd_in()` or `mkd_string()`) and writes the
resulting HTML document to `out`.
2. `int mkd_line(char *bfr, int size, char **out, int flags)` allocates a
buffer, then formats the text string into that buffer.
text string, allocates a buffer,
The differences from `markdown()` are it doesn't support quoting,
footnotes ("reference links",) multiple paragraphs, lists, code
sections, or pure html sections.
3. `int mkd_generateline(char*bfr, int size, FILE *out, int flags)`
formats the text string and writes the resulting HTML fragment to `out`.
It is exactly like `mkd_line()` except that it writes the output to
a `FILE*`.
####Fine-grained access to the internals
1. `int mkd_compile(MMIOT *doc, int flags)` takes a document created by
`mkd_in()` or `mkd_string()` and compiles it into a tree of block
elements.
2. `int mkd_generatehtml(MMIOT *doc, FILE *out)` generates html from
a compiled document.
2. `int mkd_document(MMIOT *doc, char **text)` returns (in `text`) a
pointer to the compiled html document, and (in the return code)
the size of that document.
2. `int mkd_css(MMIOT *doc, char **out)` allocates a buffer and populates
it with any style blocks found in the document.
2. `int mkd_generatecss(MMIOT *doc, FILE *out)` prints any style blocks in
the document.
3. `int mkd_toc(MMIOT *doc, char **out)` allocates a buffer, populates it
with a table of contents, assigns it to out, and returns the length of
the buffer.
To get a table of contents, you must `compile()` the document
with the `MKD_TOC` flag (described below)
3. `int mkd_generatetoc(MMIOT *doc, FILE *out)` writes a table of contents
to _out_; other than writing to a `FILE*`, it operates exactly like
`mkd_toc()`
3. `int mkd_dump(MMIOT *doc, FILE *f, int flags, char *title)` prints
a block structure diagram of a compiled document.
4. `void mkd_cleanup(MMIOT *doc)` releases the MMIOT allocated for the
document.
####[Document header](id:document-header) access functions
1. `char *mkd_doc_title(MMIOT *doc)` returns the `% title` line.
2. `char *mkd_doc_author(MMIOT *doc)` returns the `% author(s)` line.
3. `char *mkd_doc_date(MMIOT *doc)` returns the `% date` line.
####[Url callback](id:callback) functions
1. `void mkd_e_url(MMIOT*, char* (callback)(char*,int,void*))`
sets up a callback function that is called whenever [discount]
processes a `[]()` or `` construct. The callback function
is passed a pointer to the url, the size of the url, and a data
pointer (null or supplied by `mkd_e_data()`)
2. `void mkd_e_flags(MMIOT*, char *(callback)(char*,int,void*))`
sets up a callback to provide additional arguments to the tags
generated by `[]()` and `` constructs. If, for instance,
you wanted to add `target="_blank"` to every generated url, you
could just make a callback function that returned that string.
3. `void mkd_e_code(MMIOT*, char *(callback)(char*,int,void*))'
sets up a callback to format the contents of a code block.
3. `void mkd_e_free(char *, void*)` is called to free any allocated
memory returned by the url or flags callbacks.
4. `void mkd_e_data(MMIOT*, void*)` assigns a
callback data area to the url & flags callbacks.
[The flags argument](id:flags) in
`markdown()`, `mkd_text()`, `mkd_in()`,
`mkd_string()`, `mkd_compile()`, and
`mkd_generatehtml()` is a mask of the following flag bits:
[Flag](id:mkd_flags) | Action
------------------------|------------------------------------------
MKD_NOLINKS | Don't do link processing, block `` tags
MKD_NOIMAGE | Don't do image processing, block ``
MKD_NOPANTS | Don't run `smartypants()`
MKD_NOHTML | Don't allow raw html through **AT ALL**
MKD_STRICT | Disable `SUPERSCRIPT`, `RELAXED_EMPHASIS`
MKD_TAGTEXT | Process text to go inside an html tag; no emphasis or html expansion & embedded html will be stripped out.
MKD_NO_EXT | Don't allow pseudo-protocols
MKD_CDATA | Generate code for xml `![CDATA[...]]`
MKD_NOSUPERSCRIPT | No `A^B`
MKD_NORELAXED | Emphasis happens _everywhere_
MKD_NOTABLES | Don't process [PHP Markdown Extra] tables.
MKD_NOSTRIKETHROUGH | Forbid `~~strikethrough~~`
MKD_TOC | Do table-of-contents processing
MKD_1_COMPAT | Compatability with MarkdownTest_1.0
MKD_AUTOLINK | Make `http://foo.com` a link even without `<>`s
MKD_SAFELINK | Paranoid check for link protocol
MKD_NOHEADER | Don't process document headers
MKD_TABSTOP | Expand tabs to 4 spaces
MKD_NODIVQUOTE | Forbid `>%class%` blocks
MKD_NOALPHALIST | Forbid alphabetic lists
MKD_NODLIST | Forbid definition lists
MKD_EXTRA_FOOTNOTE | Enable [PHP Markdown Extra]-style [footnotes] (warning: not the later version of multiple-paragraph ones.)
MKD_NOSTYLE | Don't extract `` blocks and set them aside for printing
via `mkd_style()`.
[Class blocks](id:classblock)
: A blockquote with a first line of `> %class%` will become
`