From 28bf3097cb23e1f811b5273cd04e16d309f04607 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Wed, 15 Mar 2017 11:29:53 +0000 Subject: Minimal support for deep linking into man(7) pages. As the man(7) language does not provide semantic markup, only .SH, .SS, and .UR become anchors for now. --- html.c | 25 ++++++++++++++++++++++++- html.h | 2 ++ man_html.c | 22 +++++++++++++++++----- mandoc_html.3 | 29 ++++++++++++++++++++++++++++- mdoc_html.c | 33 +++++---------------------------- 5 files changed, 76 insertions(+), 35 deletions(-) diff --git a/html.c b/html.c index c477fd1b..ed076eaa 100644 --- a/html.c +++ b/html.c @@ -28,8 +28,9 @@ #include #include -#include "mandoc.h" #include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" #include "out.h" #include "html.h" #include "manconf.h" @@ -236,6 +237,28 @@ print_metaf(struct html *h, enum mandoc_esc deco) } } +char * +html_make_id(const struct roff_node *n) +{ + const struct roff_node *nch; + char *buf, *cp; + + for (nch = n->child; nch != NULL; nch = nch->next) + if (nch->type != ROFFT_TEXT) + return NULL; + + buf = NULL; + deroff(&buf, n); + + /* http://www.w3.org/TR/html5/dom.html#the-id-attribute */ + + for (cp = buf; *cp != '\0'; cp++) + if (*cp == ' ') + *cp = '_'; + + return buf; +} + int html_strlen(const char *cp) { diff --git a/html.h b/html.h index 29e5e868..e228be5d 100644 --- a/html.h +++ b/html.h @@ -112,6 +112,7 @@ struct html { }; +struct roff_node; struct tbl_span; struct eqn; @@ -127,4 +128,5 @@ void print_eqn(struct html *, const struct eqn *); void print_paragraph(struct html *); void print_endline(struct html *); +char *html_make_id(const struct roff_node *); int html_strlen(const char *); diff --git a/man_html.c b/man_html.c index 7db71e2a..cc3fc761 100644 --- a/man_html.c +++ b/man_html.c @@ -435,8 +435,14 @@ man_br_pre(MAN_ARGS) static int man_SH_pre(MAN_ARGS) { - if (n->type == ROFFT_HEAD) - print_otag(h, TAG_H1, "c", "Sh"); + char *id; + + if (n->type == ROFFT_HEAD) { + id = html_make_id(n); + print_otag(h, TAG_H1, "cTi", "Sh", id); + print_otag(h, TAG_A, "chR", "selflink", id); + free(id); + } return 1; } @@ -498,8 +504,14 @@ man_SM_pre(MAN_ARGS) static int man_SS_pre(MAN_ARGS) { - if (n->type == ROFFT_HEAD) - print_otag(h, TAG_H2, "c", "Ss"); + char *id; + + if (n->type == ROFFT_HEAD) { + id = html_make_id(n); + print_otag(h, TAG_H2, "cTi", "Ss", id); + print_otag(h, TAG_A, "chR", "selflink", id); + free(id); + } return 1; } @@ -656,7 +668,7 @@ man_UR_pre(MAN_ARGS) assert(n->type == ROFFT_HEAD); if (n->child != NULL) { assert(n->child->type == ROFFT_TEXT); - print_otag(h, TAG_A, "ch", "Lk", n->child->string); + print_otag(h, TAG_A, "cTh", "Lk", n->child->string); } assert(n->next->type == ROFFT_BODY); diff --git a/mandoc_html.3 b/mandoc_html.3 index deae701b..f675d400 100644 --- a/mandoc_html.3 +++ b/mandoc_html.3 @@ -48,6 +48,14 @@ .Fa "struct html *h" .Fa "const char *word" .Fc +.Ft char * +.Fo html_make_id +.Fa "const struct roff_node *n" +.Fc +.Ft int +.Fo html_strlen +.Fa "const char *cp" +.Fc .Sh DESCRIPTION The mandoc HTML formatter is not a formal library. However, as it is compiled into more than one program, in particular @@ -306,8 +314,27 @@ and .Fn print_tagq functions. .Pp +The function +.Fn html_make_id +takes a node containing one or more text children +and returns a newly allocated string containing the concatenation +of the child strings, with blanks replaced by underscores. +If the node +.Fa n +contains any non-text child node, +.Fn html_make_id +returns +.Dv NULL +instead. +The caller is responsible for freeing the returned string. +.Pp +The function +.Fn html_strlen +counts the number of characters in +.Fa cp . +It is used as a crude estimate of the width needed to display a string. +.Pp The functions -.Fn html_strlen , .Fn print_eqn , .Fn print_tbl , and diff --git a/mdoc_html.c b/mdoc_html.c index 3a0b774b..eda5ce41 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -49,7 +49,6 @@ struct htmlmdoc { }; static char *cond_id(const struct roff_node *); -static char *make_id(const struct roff_node *); static void print_mdoc_head(MDOC_ARGS); static void print_mdoc_node(MDOC_ARGS); static void print_mdoc_nodelist(MDOC_ARGS); @@ -477,28 +476,6 @@ mdoc_root_pre(MDOC_ARGS) return 1; } -static char * -make_id(const struct roff_node *n) -{ - const struct roff_node *nch; - char *buf, *cp; - - for (nch = n->child; nch != NULL; nch = nch->next) - if (nch->type != ROFFT_TEXT) - return NULL; - - buf = NULL; - deroff(&buf, n); - - /* http://www.w3.org/TR/html5/dom.html#the-id-attribute */ - - for (cp = buf; *cp != '\0'; cp++) - if (*cp == ' ') - *cp = '_'; - - return buf; -} - static char * cond_id(const struct roff_node *n) { @@ -511,7 +488,7 @@ cond_id(const struct roff_node *n) (n->parent->tok == MDOC_Xo && n->parent->parent->prev == NULL && n->parent->parent->parent->tok == MDOC_It))) - return make_id(n); + return html_make_id(n); return NULL; } @@ -522,7 +499,7 @@ mdoc_sh_pre(MDOC_ARGS) switch (n->type) { case ROFFT_HEAD: - id = make_id(n); + id = html_make_id(n); print_otag(h, TAG_H1, "cTi", "Sh", id); print_otag(h, TAG_A, "chR", "selflink", id); free(id); @@ -545,7 +522,7 @@ mdoc_ss_pre(MDOC_ARGS) if (n->type != ROFFT_HEAD) return 1; - id = make_id(n); + id = html_make_id(n); print_otag(h, TAG_H2, "cTi", "Ss", id); print_otag(h, TAG_A, "chR", "selflink", id); free(id); @@ -955,7 +932,7 @@ mdoc_sx_pre(MDOC_ARGS) { char *id; - id = make_id(n); + id = html_make_id(n); print_otag(h, TAG_A, "cThR", "Sx", id); free(id); return 1; @@ -1128,7 +1105,7 @@ mdoc_er_pre(MDOC_ARGS) (n->parent->tok == MDOC_It || (n->parent->tok == MDOC_Bq && n->parent->parent->parent->tok == MDOC_It)) ? - make_id(n) : NULL; + html_make_id(n) : NULL; if (id != NULL) print_otag(h, TAG_A, "chR", "selflink", id); -- cgit