![]() |
Nilorea Library
C utilities for networking, threading, graphics
|
Parse a SAFE, strict subset of Markdown into a block / styled-span model. More...
#include <stddef.h>Go to the source code of this file.
Data Structures | |
| struct | n_markdown_block |
| One block. More... | |
| struct | n_markdown_doc |
| A parsed document: an owned array of blocks. More... | |
| struct | n_markdown_inline |
| One flow of inline runs (a paragraph, a quote, or one list item). More... | |
| struct | n_markdown_span |
| One inline run: visible text, a style bitmask, and (for a link) an already-http(s)-validated url. More... | |
Macros | |
| #define | N_MARKDOWN_ALIGN_CENTER 1 |
| what "|:---:|" asks for. | |
| #define | N_MARKDOWN_ALIGN_LEFT 0 |
| table column alignment: the default, and what "|:---|" asks for. | |
| #define | N_MARKDOWN_ALIGN_RIGHT 2 |
| what "|---:|" asks for. | |
| #define | N_MARKDOWN_ALL (N_MARKDOWN_HEADINGS | N_MARKDOWN_TABLES) |
| every block kind this parser knows. | |
| #define | N_MARKDOWN_AUTOLINKS (1u << 2) |
| n_markdown_parse_ex flag: a bare http(s) URL, or one in <angle brackets>, is a link whose text is the URL. | |
| #define | N_MARKDOWN_BOLD (1u << 0) |
| bold inline style flag | |
| #define | N_MARKDOWN_CODE (1u << 2) |
| inline code style flag (carries no emphasis) | |
| #define | N_MARKDOWN_ESCAPES (1u << 4) |
| n_markdown_parse_ex flag: a backslash before ASCII punctuation makes that character literal ("\\*not italic\\*"); before anything else it stays. | |
| #define | N_MARKDOWN_HEADINGS (1u << 0) |
| n_markdown_parse_ex flag: recognise "# " to "###### " headings. | |
| #define | N_MARKDOWN_INLINE_ALL (N_MARKDOWN_AUTOLINKS | N_MARKDOWN_STRIKETHROUGH | N_MARKDOWN_ESCAPES) |
| every inline option: autolinks, strikethrough and escapes. | |
| #define | N_MARKDOWN_ITALIC (1u << 1) |
| italic inline style flag | |
| #define | N_MARKDOWN_LINK (1u << 3) |
| [text](http(s)://url) style flag; url is set only when this is present | |
| #define | N_MARKDOWN_STRIKE (1u << 4) |
| #define | N_MARKDOWN_STRIKETHROUGH (1u << 3) |
| n_markdown_parse_ex flag: "~~text~~" carries N_MARKDOWN_STRIKE. | |
| #define | N_MARKDOWN_TABLES (1u << 1) |
| n_markdown_parse_ex flag: recognise GitHub-style pipe tables. | |
Enumerations | |
| enum | n_markdown_block_kind { N_MARKDOWN_PARA = 0 , N_MARKDOWN_QUOTE , N_MARKDOWN_CODE_BLOCK , N_MARKDOWN_UL , N_MARKDOWN_OL , N_MARKDOWN_HEADING , N_MARKDOWN_TABLE } |
| Block kinds. More... | |
Functions | |
| void | n_markdown_free (n_markdown_doc *doc) |
| free everything a n_markdown_doc owns and zero it | |
| int | n_markdown_has_markup (const char *text, size_t len) |
| 1 if text contains any renderable markup, else 0 | |
| int | n_markdown_has_markup_ex (const char *text, size_t len, unsigned flags) |
| 1 if text contains any markup the given flags would render, else 0 | |
| void | n_markdown_parse (const char *text, size_t len, n_markdown_doc *out) |
| parse text (len bytes, plain UTF-8) into out | |
| void | n_markdown_parse_ex (const char *text, size_t len, unsigned flags, n_markdown_doc *out) |
| parse text into out, choosing which optional block kinds to recognise | |
Parse a SAFE, strict subset of Markdown into a block / styled-span model.
A renderer-agnostic parser for a small, safe subset of Markdown, suitable for chat / message text. It emits a flat, renderer-friendly model rather than a DOM: each inline run carries a style bitmask (bold / italic / code / link) so a caller can turn it into styled glyph runs / DOM nodes / ANSI, etc. The recursive nesting of the source (bold containing italic) is flattened into per-span flags.
It faces hostile input, so it is bounded and safe: a pathological input truncates (caps on blocks / spans / list-items and on bold/italic recursion depth) rather than exploding, and an allocation failure keeps what it has. Unknown markup is left as literal text.
Subset: inline bold / bold, italic / italic, code, text (a non-http(s) scheme renders literally) block paragraphs, ``` fenced code blocks, > blockquotes, "- " / "* " unordered lists, "1. " ordered lists
Three inline options are available the same way: bare and <angle> http(s) autolinks, strikethrough and backslash escapes (N_MARKDOWN_INLINE_ALL).
Two more block kinds are available on request, through n_markdown_parse_ex() and its flags: "# " to "###### " headings, and GitHub-style pipe tables. They are opt-in because the default subset is what a chat message is parsed with, where a line beginning with a # is a hash tag far more often than a heading, and where a line of pipes is a line of pipes. A document parsed without a flag sees those lines as ordinary text, exactly as it did before the flags existed.
Definition in file n_markdown.h.
| struct n_markdown_block |
One block.
inl holds spans for PARA/QUOTE/HEADING; code holds the raw text for CODE_BLOCK (owned, NUL-terminated, else NULL); items holds the list rows for UL/OL and the cells for TABLE (else NULL).
A TABLE's cells are stored in items row by row, n_cols to a row, so cell (r, c) is items[r * n_cols + c] and there are n_items / n_cols rows. The first row is the header. align has one entry per column. Two arrays and no nested type: it is the same flat model the spans use, and n_markdown_free already knew how to release items.
Definition at line 138 of file n_markdown.h.
| Data Fields | ||
|---|---|---|
| unsigned char * | align |
TABLE: N_MARKDOWN_ALIGN_* per column, n_cols entries, owned. NULL for every other kind. |
| char * | code | |
| n_markdown_inline | inl | |
| n_markdown_inline * | items | |
| int | kind | enum n_markdown_block_kind |
| int | level |
HEADING: 1 to 6. Zero for every other kind. |
| size_t | n_cols |
TABLE: cells per row, always at least 1. Zero for every other kind. |
| size_t | n_items | |
| struct n_markdown_doc |
A parsed document: an owned array of blocks.
Definition at line 154 of file n_markdown.h.
| Data Fields | ||
|---|---|---|
| n_markdown_block * | blocks | |
| size_t | n_blocks | |
| struct n_markdown_inline |
One flow of inline runs (a paragraph, a quote, or one list item).
Definition at line 124 of file n_markdown.h.
| Data Fields | ||
|---|---|---|
| size_t | n_spans | |
| n_markdown_span * | spans | |
| struct n_markdown_span |
One inline run: visible text, a style bitmask, and (for a link) an already-http(s)-validated url.
Both strings are owned, NUL-terminated; url is NULL unless N_MARKDOWN_LINK is set.
Definition at line 117 of file n_markdown.h.
| Data Fields | ||
|---|---|---|
| unsigned | style | |
| char * | text | |
| char * | url | |
| #define N_MARKDOWN_ALIGN_CENTER 1 |
what "|:---:|" asks for.
Definition at line 98 of file n_markdown.h.
Referenced by main(), md_flush_line(), and rule_align().
| #define N_MARKDOWN_ALIGN_LEFT 0 |
table column alignment: the default, and what "|:---|" asks for.
Definition at line 96 of file n_markdown.h.
Referenced by main(), md_run(), md_table(), n_markdown_parse_ex(), and rule_align().
| #define N_MARKDOWN_ALIGN_RIGHT 2 |
what "|---:|" asks for.
Definition at line 100 of file n_markdown.h.
Referenced by main(), md_flush_line(), and rule_align().
| #define N_MARKDOWN_ALL (N_MARKDOWN_HEADINGS | N_MARKDOWN_TABLES) |
every block kind this parser knows.
Deliberately NOT the inline options below: a renderer asking for every block kind (n_gui_md) would otherwise be handed a N_MARKDOWN_STRIKE span it does not draw.
Definition at line 90 of file n_markdown.h.
Referenced by main(), main(), and n_gui_md_style_default().
| #define N_MARKDOWN_AUTOLINKS (1u << 2) |
n_markdown_parse_ex flag: a bare http(s) URL, or one in <angle brackets>, is a link whose text is the URL.
Trailing sentence punctuation and an unbalanced ")" are left out of it, and a bare one starts only at a word boundary.
Definition at line 81 of file n_markdown.h.
Referenced by parse_inline().
| #define N_MARKDOWN_BOLD (1u << 0) |
bold inline style flag
Definition at line 63 of file n_markdown.h.
Referenced by main(), md_font_for(), md_table(), md_table_cols(), and try_emphasis().
| #define N_MARKDOWN_CODE (1u << 2) |
inline code style flag (carries no emphasis)
Definition at line 67 of file n_markdown.h.
Referenced by main(), md_flow(), md_font_for(), md_run(), and try_code().
| #define N_MARKDOWN_ESCAPES (1u << 4) |
n_markdown_parse_ex flag: a backslash before ASCII punctuation makes that character literal ("\\*not italic\\*"); before anything else it stays.
Definition at line 86 of file n_markdown.h.
Referenced by n_markdown_has_markup_ex(), and parse_inline().
| #define N_MARKDOWN_HEADINGS (1u << 0) |
n_markdown_parse_ex flag: recognise "# " to "###### " headings.
Definition at line 74 of file n_markdown.h.
Referenced by line_starts_block(), main(), and n_markdown_parse_ex().
| #define N_MARKDOWN_INLINE_ALL (N_MARKDOWN_AUTOLINKS | N_MARKDOWN_STRIKETHROUGH | N_MARKDOWN_ESCAPES) |
every inline option: autolinks, strikethrough and escapes.
Definition at line 92 of file n_markdown.h.
| #define N_MARKDOWN_ITALIC (1u << 1) |
italic inline style flag
Definition at line 65 of file n_markdown.h.
Referenced by main(), md_font_for(), and try_emphasis().
| #define N_MARKDOWN_LINK (1u << 3) |
[text](http(s)://url) style flag; url is set only when this is present
Definition at line 69 of file n_markdown.h.
Referenced by main(), md_flow(), try_autolink(), and try_link().
| #define N_MARKDOWN_STRIKE (1u << 4) |
strike inline style flag (only with N_MARKDOWN_STRIKETHROUGH)
Definition at line 71 of file n_markdown.h.
Referenced by main(), and try_strike().
| #define N_MARKDOWN_STRIKETHROUGH (1u << 3) |
n_markdown_parse_ex flag: "~~text~~" carries N_MARKDOWN_STRIKE.
Definition at line 83 of file n_markdown.h.
Referenced by try_strike().
| #define N_MARKDOWN_TABLES (1u << 1) |
n_markdown_parse_ex flag: recognise GitHub-style pipe tables.
Definition at line 76 of file n_markdown.h.
Referenced by line_starts_block(), main(), and n_markdown_parse_ex().
Block kinds.
The last two appear only when n_markdown_parse_ex() was asked for them, so a caller that has not been updated cannot meet one.
Definition at line 104 of file n_markdown.h.
| void n_markdown_free | ( | n_markdown_doc * | doc | ) |
free everything a n_markdown_doc owns and zero it
| doc | the document (safe on a zeroed doc and on NULL) |
Definition at line 918 of file n_markdown.c.
References n_markdown_block::align, n_markdown_doc::blocks, n_markdown_block::code, free_inline(), n_markdown_block::inl, n_markdown_block::items, n_markdown_doc::n_blocks, and n_markdown_block::n_items.
Referenced by main(), md_run(), and n_markdown_has_markup_ex().
| int n_markdown_has_markup | ( | const char * | text, |
| size_t | len ) |
1 if text contains any renderable markup, else 0
Lets a caller skip the styled path for a plain message.
| text | the UTF-8 source |
| len | number of bytes of text |
Definition at line 936 of file n_markdown.c.
References n_markdown_has_markup_ex().
Referenced by main().
| int n_markdown_has_markup_ex | ( | const char * | text, |
| size_t | len, | ||
| unsigned | flags ) |
1 if text contains any markup the given flags would render, else 0
n_markdown_has_markup() is this with flags of zero. A document that is nothing but a heading has no markup in the default subset and has markup with N_MARKDOWN_HEADINGS, which is the answer each caller wants.
| text | the UTF-8 source |
| len | number of bytes of text |
| flags | as n_markdown_parse_ex() |
Definition at line 940 of file n_markdown.c.
References n_markdown_doc::blocks, n_markdown_block::inl, is_md_punct(), n_markdown_block::kind, n_markdown_doc::n_blocks, N_MARKDOWN_ESCAPES, n_markdown_free(), N_MARKDOWN_PARA, n_markdown_parse_ex(), n_markdown_inline::n_spans, n_markdown_inline::spans, and n_markdown_span::style.
Referenced by main(), and n_markdown_has_markup().
| void n_markdown_parse | ( | const char * | text, |
| size_t | len, | ||
| n_markdown_doc * | out ) |
parse text (len bytes, plain UTF-8) into out
Never fails destructively: on allocation failure or a bounds cap it keeps what it has (safe truncation). out is zeroed first. Always pair with n_markdown_free.
| text | the UTF-8 source (may be NULL) |
| len | number of bytes of text |
| out | the document to fill (zeroed first) |
Definition at line 706 of file n_markdown.c.
References n_markdown_parse_ex().
Referenced by main(), and parse().
| void n_markdown_parse_ex | ( | const char * | text, |
| size_t | len, | ||
| unsigned | flags, | ||
| n_markdown_doc * | out ) |
parse text into out, choosing which optional block kinds to recognise
n_markdown_parse() is this with flags of zero, and that is the whole difference: the default subset is unchanged, byte for byte, so a caller that never passes a flag can never be handed a block kind it does not know.
Same guarantees as n_markdown_parse(): out is zeroed first, an allocation failure or a bounds cap truncates safely rather than failing, and the result is always released with n_markdown_free().
| text | the UTF-8 source (may be NULL) |
| len | number of bytes of text |
| flags | any of N_MARKDOWN_HEADINGS, N_MARKDOWN_TABLES, N_MARKDOWN_AUTOLINKS, N_MARKDOWN_STRIKETHROUGH, N_MARKDOWN_ESCAPES, N_MARKDOWN_ALL, N_MARKDOWN_INLINE_ALL; unknown bits are ignored |
| out | the document to fill (zeroed first) |
Definition at line 710 of file n_markdown.c.
References md_cells::a, n_markdown_block::align, md_cells::b, n_markdown_block::code, doc_push(), dup_range(), has_pipe(), n_markdown_block::inl, join_lines(), n_markdown_block::level, line_blank(), line_indented(), line_starts_block(), list_add_wrapped(), match_heading(), match_ol(), match_quote(), match_ul(), md_cells::n, mline::n, n_markdown_block::n_cols, N_MARKDOWN_ALIGN_LEFT, N_MARKDOWN_CODE_BLOCK, N_MARKDOWN_HEADING, N_MARKDOWN_HEADINGS, N_MARKDOWN_OL, N_MARKDOWN_PARA, N_MARKDOWN_QUOTE, N_MARKDOWN_TABLE, N_MARKDOWN_TABLES, N_MARKDOWN_UL, mline::p, parse_inline(), row_cells(), rule_align(), starts_fence(), starts_table(), strip_quote(), and table_add_row().
Referenced by md_run(), n_markdown_has_markup_ex(), n_markdown_parse(), and parse_ex().