=================================================================== RCS file: /cvs/mandoc/mdoc_markdown.c,v retrieving revision 1.33 retrieving revision 1.40 diff -u -p -r1.33 -r1.40 --- mandoc/mdoc_markdown.c 2020/02/20 00:29:16 1.33 +++ mandoc/mdoc_markdown.c 2025/06/26 17:06:34 1.40 @@ -1,6 +1,6 @@ -/* $Id: mdoc_markdown.c,v 1.33 2020/02/20 00:29:16 schwarze Exp $ */ +/* $Id: mdoc_markdown.c,v 1.40 2025/06/26 17:06:34 schwarze Exp $ */ /* - * Copyright (c) 2017, 2018 Ingo Schwarze + * Copyright (c) 2017, 2018, 2020, 2025 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,7 +13,11 @@ * 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. + * + * Markdown formatter for mdoc(7) used by mandoc(1). */ +#include "config.h" + #include #include @@ -29,16 +33,16 @@ #include "main.h" struct md_act { - int (*cond)(struct roff_node *n); - int (*pre)(struct roff_node *n); - void (*post)(struct roff_node *n); + int (*cond)(struct roff_node *); + int (*pre)(struct roff_node *); + void (*post)(struct roff_node *); const char *prefix; /* pre-node string constant */ const char *suffix; /* post-node string constant */ }; static void md_nodelist(struct roff_node *); static void md_node(struct roff_node *); -static const char *md_stack(char c); +static const char *md_stack(char); static void md_preword(void); static void md_rawword(const char *); static void md_word(const char *); @@ -81,6 +85,7 @@ static int md_pre_Sh(struct roff_node *); static int md_pre_Sm(struct roff_node *); static int md_pre_Vt(struct roff_node *); static int md_pre_Xr(struct roff_node *); +static int md_pre__R(struct roff_node *); static int md_pre__T(struct roff_node *); static int md_pre_br(struct roff_node *); @@ -155,7 +160,7 @@ static const struct md_act md_acts[MDOC_MAX - MDOC_Dd] { NULL, NULL, md_post_pc, NULL, NULL }, /* %N */ { NULL, NULL, md_post_pc, NULL, NULL }, /* %O */ { NULL, NULL, md_post_pc, NULL, NULL }, /* %P */ - { NULL, NULL, md_post_pc, NULL, NULL }, /* %R */ + { NULL, md_pre__R, md_post_pc, NULL, NULL }, /* %R */ { NULL, md_pre__T, md_post__T, NULL, NULL }, /* %T */ { NULL, NULL, md_post_pc, NULL, NULL }, /* %V */ { NULL, NULL, NULL, NULL, NULL }, /* Ac */ @@ -287,6 +292,14 @@ markdown_mdoc(void *arg, const struct roff_meta *mdoc) md_word(mdoc->os); md_word("-"); md_word(mdoc->date); + md_word("-"); + md_word(mdoc->title); + if (mdoc->msec != NULL) { + outflags &= ~MD_spc; + md_word("("); + md_word(mdoc->msec); + md_word(")"); + } putchar('\n'); } @@ -310,7 +323,9 @@ md_node(struct roff_node *n) if (outflags & MD_nonl) outflags &= ~(MD_nl | MD_sp); - else if (outflags & MD_spc && n->flags & NODE_LINE) + else if (outflags & MD_spc && + n->flags & NODE_LINE && + !roff_node_transparent(n)) outflags |= MD_nl; act = NULL; @@ -597,16 +612,18 @@ md_word(const char *s) md_rawword("markdown"); continue; case ESCAPE_FONTBOLD: + case ESCAPE_FONTCB: nextfont = "**"; break; case ESCAPE_FONTITALIC: + case ESCAPE_FONTCI: nextfont = "*"; break; case ESCAPE_FONTBI: nextfont = "***"; break; case ESCAPE_FONT: - case ESCAPE_FONTCW: + case ESCAPE_FONTCR: case ESCAPE_FONTROMAN: nextfont = ""; break; @@ -742,7 +759,7 @@ md_pre_raw(struct roff_node *n) if ((prefix = md_act(n->tok)->prefix) != NULL) { md_rawword(prefix); outflags &= ~MD_spc; - if (*prefix == '`') + if (strchr(prefix, '`') != NULL) code_blocks++; } return 1; @@ -756,7 +773,7 @@ md_post_raw(struct roff_node *n) if ((suffix = md_act(n->tok)->suffix) != NULL) { outflags &= ~(MD_spc | MD_nl); md_rawword(suffix); - if (*suffix == '`') + if (strchr(suffix, '`') != NULL) code_blocks--; } } @@ -787,14 +804,17 @@ md_post_word(struct roff_node *n) static void md_post_pc(struct roff_node *n) { + struct roff_node *nn; + md_post_raw(n); if (n->parent->tok != MDOC_Rs) return; - if (n->next != NULL) { + + if ((nn = roff_node_next(n)) != NULL) { md_word(","); - if (n->prev != NULL && - n->prev->tok == n->tok && - n->next->tok == n->tok) + if (nn->tok == n->tok && + (nn = roff_node_prev(n)) != NULL && + nn->tok == n->tok) md_word("and"); } else { md_word("."); @@ -811,10 +831,13 @@ md_pre_skip(struct roff_node *n) static void md_pre_syn(struct roff_node *n) { - if (n->prev == NULL || ! (n->flags & NODE_SYNPRETTY)) + struct roff_node *np; + + if ((n->flags & NODE_SYNPRETTY) == 0 || + (np = roff_node_prev(n)) == NULL) return; - if (n->prev->tok == n->tok && + if (np->tok == n->tok && n->tok != MDOC_Ft && n->tok != MDOC_Fo && n->tok != MDOC_Fn) { @@ -822,7 +845,7 @@ md_pre_syn(struct roff_node *n) return; } - switch (n->prev->tok) { + switch (np->tok) { case MDOC_Fd: case MDOC_Fn: case MDOC_Fo: @@ -1053,7 +1076,9 @@ md_pre_Fa(struct roff_node *n) static void md_post_Fa(struct roff_node *n) { - if (n->next != NULL && n->next->tok == MDOC_Fa) + struct roff_node *nn; + + if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC_Fa) md_word(","); } @@ -1075,9 +1100,11 @@ md_post_Fd(struct roff_node *n) static void md_post_Fl(struct roff_node *n) { + struct roff_node *nn; + md_post_raw(n); - if (n->child == NULL && n->next != NULL && - n->next->type != ROFFT_TEXT && !(n->next->flags & NODE_LINE)) + if (n->child == NULL && (nn = roff_node_next(n)) != NULL && + nn->type != ROFFT_TEXT && (nn->flags & NODE_LINE) == 0) outflags &= ~MD_spc; } @@ -1559,6 +1586,34 @@ md_pre_Xr(struct roff_node *n) md_word("("); md_node(n); md_word(")"); + return 0; +} + +static int +md_pre__R(struct roff_node *n) +{ + const unsigned char *cp; + const char *arg; + + arg = n->child->string; + + if (strncmp(arg, "RFC ", 4) != 0) + return 1; + cp = arg += 4; + while (isdigit(*cp)) + cp++; + if (*cp != '\0') + return 1; + + md_rawword("[RFC "); + outflags &= ~MD_spc; + md_rawword(arg); + outflags &= ~MD_spc; + md_rawword("](http://www.rfc-editor.org/rfc/rfc"); + outflags &= ~MD_spc; + md_rawword(arg); + outflags &= ~MD_spc; + md_rawword(".html)"); return 0; }