lowdown.h (11074B)
/* $Id$ */
/*
* Copyright (c) 2017--2021 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef LOWDOWN_H
#define LOWDOWN_H
/*
* All of this is documented in lowdown.3.
* If it's not documented, don't use it.
* Or report it as a bug.
*/
/* We need this for compilation on musl systems. */
#ifndef __BEGIN_DECLS
# ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# else
# define __BEGIN_DECLS
# endif
#endif
#ifndef __END_DECLS
# ifdef __cplusplus
# define __END_DECLS }
# else
# define __END_DECLS
# endif
#endif
enum lowdown_type {
LOWDOWN_GEMINI,
LOWDOWN_HTML,
LOWDOWN_LATEX,
LOWDOWN_MAN,
LOWDOWN_NROFF,
LOWDOWN_FODT,
LOWDOWN_TERM,
LOWDOWN_TREE,
LOWDOWN_NULL
};
/*
* All types of Markdown nodes that lowdown understands.
*/
enum lowdown_rndrt {
LOWDOWN_ROOT,
LOWDOWN_BLOCKCODE,
LOWDOWN_BLOCKQUOTE,
LOWDOWN_DEFINITION,
LOWDOWN_DEFINITION_TITLE,
LOWDOWN_DEFINITION_DATA,
LOWDOWN_HEADER,
LOWDOWN_HRULE,
LOWDOWN_LIST,
LOWDOWN_LISTITEM,
LOWDOWN_PARAGRAPH,
LOWDOWN_TABLE_BLOCK,
LOWDOWN_TABLE_HEADER,
LOWDOWN_TABLE_BODY,
LOWDOWN_TABLE_ROW,
LOWDOWN_TABLE_CELL,
LOWDOWN_BLOCKHTML,
LOWDOWN_LINK_AUTO,
LOWDOWN_CODESPAN,
LOWDOWN_DOUBLE_EMPHASIS,
LOWDOWN_EMPHASIS,
LOWDOWN_HIGHLIGHT,
LOWDOWN_IMAGE,
LOWDOWN_LINEBREAK,
LOWDOWN_LINK,
LOWDOWN_TRIPLE_EMPHASIS,
LOWDOWN_STRIKETHROUGH,
LOWDOWN_SUPERSCRIPT,
LOWDOWN_FOOTNOTE,
LOWDOWN_MATH_BLOCK,
LOWDOWN_RAW_HTML,
LOWDOWN_ENTITY,
LOWDOWN_NORMAL_TEXT,
LOWDOWN_DOC_HEADER,
LOWDOWN_META,
LOWDOWN__MAX
};
struct lowdown_buf {
char *data; /* actual character data */
size_t size; /* size of the string */
size_t maxsize; /* allocated size (0 = volatile) */
size_t unit; /* realloc unit size (0 = read-only) */
int buffer_free; /* obj should be freed */
};
TAILQ_HEAD(lowdown_nodeq, lowdown_node);
enum htbl_flags {
HTBL_FL_ALIGN_LEFT = 1,
HTBL_FL_ALIGN_RIGHT = 2,
HTBL_FL_ALIGN_CENTER = 3,
HTBL_FL_ALIGNMASK = 3,
HTBL_FL_HEADER = 4
};
enum halink_type {
HALINK_NONE, /* used internally when it is not an autolink */
HALINK_NORMAL,
HALINK_EMAIL
};
enum hlist_fl {
HLIST_FL_ORDERED = (1 << 0), /* <ol> list item */
HLIST_FL_BLOCK = (1 << 1), /* <li> containing block data */
HLIST_FL_UNORDERED = (1 << 2), /* <ul> list item */
HLIST_FL_DEF = (1 << 3), /* <dl> list item */
HLIST_FL_CHECKED = (1 << 4), /* <li> with checked box */
HLIST_FL_UNCHECKED = (1 << 5), /* <li> with unchecked box */
};
/*
* Meta-data keys and values.
* Both of these are non-NULL (but possibly empty).
*/
struct lowdown_meta {
char *key;
char *value;
TAILQ_ENTRY(lowdown_meta) entries;
};
TAILQ_HEAD(lowdown_metaq, lowdown_meta);
enum lowdown_chng {
LOWDOWN_CHNG_NONE = 0,
LOWDOWN_CHNG_INSERT,
LOWDOWN_CHNG_DELETE,
};
struct rndr_meta {
struct lowdown_buf key;
};
struct rndr_paragraph {
size_t lines;
int beoln;
};
struct rndr_normal_text {
struct lowdown_buf text;
};
struct rndr_entity {
struct lowdown_buf text;
};
struct rndr_autolink {
struct lowdown_buf link;
enum halink_type type;
};
struct rndr_raw_html {
struct lowdown_buf text;
};
struct rndr_link {
struct lowdown_buf link;
struct lowdown_buf title;
struct lowdown_buf attr_cls;
struct lowdown_buf attr_id;
};
struct rndr_blockcode {
struct lowdown_buf text;
struct lowdown_buf lang;
};
struct rndr_definition {
enum hlist_fl flags;
};
struct rndr_codespan {
struct lowdown_buf text;
};
struct rndr_table{
size_t columns;
};
struct rndr_table_header {
enum htbl_flags *flags;
size_t columns;
};
struct rndr_table_cell {
enum htbl_flags flags;
size_t col;
size_t columns;
};
struct rndr_blockhtml {
struct lowdown_buf text;
};
struct rndr_list {
enum hlist_fl flags;
size_t start;
};
struct rndr_listitem {
enum hlist_fl flags;
size_t num;
};
struct rndr_header{
size_t level;
struct lowdown_buf attr_cls;
struct lowdown_buf attr_id;
};
struct rndr_image {
struct lowdown_buf link;
struct lowdown_buf title;
struct lowdown_buf dims;
struct lowdown_buf alt;
struct lowdown_buf attr_width;
struct lowdown_buf attr_height;
struct lowdown_buf attr_cls;
struct lowdown_buf attr_id;
};
struct rndr_math {
struct lowdown_buf text;
int blockmode;
};
/*
* Node parsed from input document.
* Each node is part of the parse tree.
*/
struct lowdown_node {
enum lowdown_rndrt type;
enum lowdown_chng chng; /* change type */
size_t id; /* unique identifier */
union {
struct rndr_meta rndr_meta;
struct rndr_list rndr_list;
struct rndr_paragraph rndr_paragraph;
struct rndr_listitem rndr_listitem;
struct rndr_header rndr_header;
struct rndr_normal_text rndr_normal_text;
struct rndr_entity rndr_entity;
struct rndr_autolink rndr_autolink;
struct rndr_raw_html rndr_raw_html;
struct rndr_link rndr_link;
struct rndr_blockcode rndr_blockcode;
struct rndr_definition rndr_definition;
struct rndr_codespan rndr_codespan;
struct rndr_table rndr_table;
struct rndr_table_header rndr_table_header;
struct rndr_table_cell rndr_table_cell;
struct rndr_image rndr_image;
struct rndr_math rndr_math;
struct rndr_blockhtml rndr_blockhtml;
};
struct lowdown_node *parent;
struct lowdown_nodeq children;
TAILQ_ENTRY(lowdown_node) entries;
};
struct lowdown_opts_odt {
const char *sty;
};
struct lowdown_opts {
enum lowdown_type type;
union {
struct lowdown_opts_odt odt;
};
size_t maxdepth;
size_t cols;
size_t hmargin;
size_t vmargin;
unsigned int feat;
#define LOWDOWN_TABLES 0x01
#define LOWDOWN_FENCED 0x02
#define LOWDOWN_FOOTNOTES 0x04
#define LOWDOWN_AUTOLINK 0x08
#define LOWDOWN_STRIKE 0x10
/* Omitted 0x20 */
#define LOWDOWN_HILITE 0x40
/* Omitted 0x80 */
#define LOWDOWN_SUPER 0x100
#define LOWDOWN_MATH 0x200
#define LOWDOWN_NOINTEM 0x400
/* Disabled LOWDOWN_MATHEXP 0x1000 */
#define LOWDOWN_NOCODEIND 0x2000
#define LOWDOWN_METADATA 0x4000
#define LOWDOWN_COMMONMARK 0x8000
#define LOWDOWN_DEFLIST 0x10000
#define LOWDOWN_IMG_EXT 0x20000 /* -> LOWDOWN_ATTRS */
#define LOWDOWN_TASKLIST 0x40000
#define LOWDOWN_ATTRS 0x80000
unsigned int oflags;
#define LOWDOWN_GEMINI_LINK_END 0x8000 /* links at end */
#define LOWDOWN_GEMINI_LINK_IN 0x10000 /* links inline */
#define LOWDOWN_GEMINI_LINK_NOREF 0x200000 /* for !inline, no names */
#define LOWDOWN_GEMINI_LINK_ROMAN 0x400000 /* roman link names */
#define LOWDOWN_HTML_NUM_ENT 0x1000 /* use &#nn; if possible */
#define LOWDOWN_HTML_OWASP 0x800 /* use OWASP escaping */
#define LOWDOWN_ODT_SKIP_HTML 0x2000000 /* skip all HTML */
#define LOWDOWN_SMARTY 0x40 /* smart typography */
#define LOWDOWN_TERM_NOANSI 0x1000000 /* no ANSI escapes at all */
#define LOWDOWN_TERM_NOCOLOUR 0x800000 /* no ANSI colours */
#define LOWDOWN_GEMINI_METADATA 0x100000 /* show metadata */
#define LOWDOWN_HTML_ESCAPE 0x02 /* escape HTML (if not skip) */
#define LOWDOWN_HTML_HARD_WRAP 0x04 /* paragraph line breaks */
#define LOWDOWN_HTML_HEAD_IDS 0x100 /* <hN id="the_name"> */
#define LOWDOWN_HTML_SKIP_HTML 0x01 /* skip all HTML */
#define LOWDOWN_LATEX_NUMBERED 0x4000 /* numbered sections */
#define LOWDOWN_LATEX_SKIP_HTML 0x2000 /* skip all HTML */
#define LOWDOWN_NROFF_GROFF 0x20 /* use groff extensions */
/* Disable LOWDOWN_NROFF_HARD_WRAP 0x10 */
#define LOWDOWN_NROFF_NOLINK 0x80000 /* don't show URLs */
#define LOWDOWN_NROFF_NUMBERED 0x80 /* numbered section headers */
#define LOWDOWN_NROFF_SHORTLINK 0x40000 /* shorten URLs */
#define LOWDOWN_NROFF_SKIP_HTML 0x08 /* skip all HTML */
#define LOWDOWN_STANDALONE 0x200 /* emit complete document */
#define LOWDOWN_TERM_NOLINK 0x20000 /* don't show URLs */
#define LOWDOWN_TERM_SHORTLINK 0x400 /* shorten URLs */
char **meta;
size_t metasz;
char **metaovr;
size_t metaovrsz;
};
struct lowdown_doc;
__BEGIN_DECLS
/*
* High-level functions.
* These use the "lowdown_opts" to determine how to parse and render
* content, and extract that content from a buffer, file, or descriptor.
*/
int lowdown_buf(const struct lowdown_opts *,
const char *, size_t,
char **, size_t *, struct lowdown_metaq *);
int lowdown_buf_diff(const struct lowdown_opts *,
const char *, size_t, const char *, size_t,
char **, size_t *);
int lowdown_file(const struct lowdown_opts *,
FILE *, char **, size_t *, struct lowdown_metaq *);
int lowdown_file_diff(const struct lowdown_opts *, FILE *,
FILE *, char **, size_t *);
/*
* Low-level functions.
* These actually parse and render the AST from a buffer in various
* ways.
*/
struct lowdown_buf
*lowdown_buf_new(size_t) __attribute__((malloc));
void lowdown_buf_free(struct lowdown_buf *);
struct lowdown_doc
*lowdown_doc_new(const struct lowdown_opts *);
struct lowdown_node
*lowdown_doc_parse(struct lowdown_doc *, size_t *,
const char *, size_t, struct lowdown_metaq *);
struct lowdown_node
*lowdown_diff(const struct lowdown_node *,
const struct lowdown_node *, size_t *);
void lowdown_doc_free(struct lowdown_doc *);
void lowdown_metaq_free(struct lowdown_metaq *);
void lowdown_node_free(struct lowdown_node *);
void lowdown_html_free(void *);
void *lowdown_html_new(const struct lowdown_opts *);
int lowdown_html_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
void lowdown_gemini_free(void *);
void *lowdown_gemini_new(const struct lowdown_opts *);
int lowdown_gemini_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
void lowdown_term_free(void *);
void *lowdown_term_new(const struct lowdown_opts *);
int lowdown_term_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
void lowdown_nroff_free(void *);
void *lowdown_nroff_new(const struct lowdown_opts *);
int lowdown_nroff_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
int lowdown_tree_rndr(struct lowdown_buf *,
const struct lowdown_node *);
void lowdown_latex_free(void *);
void *lowdown_latex_new(const struct lowdown_opts *);
int lowdown_latex_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
void lowdown_odt_free(void *);
void *lowdown_odt_new(const struct lowdown_opts *);
int lowdown_odt_rndr(struct lowdown_buf *, void *,
const struct lowdown_node *);
__END_DECLS
#endif /* !LOWDOWN_H */