Print this page
9718 update mandoc to 1.14.4

*** 1,9 **** ! /* $Id: html.c,v 1.219 2017/07/15 17:57:51 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> ! * Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org> * * 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. * --- 1,9 ---- ! /* $Id: html.c,v 1.238 2018/06/25 16:54:59 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> ! * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org> * * 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. *
*** 20,36 **** --- 20,38 ---- #include <sys/types.h> #include <assert.h> #include <ctype.h> #include <stdarg.h> + #include <stddef.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "mandoc_aux.h" + #include "mandoc_ohash.h" #include "mandoc.h" #include "roff.h" #include "out.h" #include "html.h" #include "manconf.h"
*** 57,75 **** {"head", HTML_NLALL | HTML_INDENT}, {"body", HTML_NLALL}, {"meta", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"title", HTML_NLAROUND}, {"div", HTML_NLAROUND}, {"h1", HTML_NLAROUND}, {"h2", HTML_NLAROUND}, {"span", 0}, {"link", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"a", 0}, {"table", HTML_NLALL | HTML_INDENT}, - {"colgroup", HTML_NLALL | HTML_INDENT}, - {"col", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"tr", HTML_NLALL | HTML_INDENT}, {"td", HTML_NLAROUND}, {"li", HTML_NLAROUND | HTML_INDENT}, {"ul", HTML_NLALL | HTML_INDENT}, {"ol", HTML_NLALL | HTML_INDENT}, --- 59,76 ---- {"head", HTML_NLALL | HTML_INDENT}, {"body", HTML_NLALL}, {"meta", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"title", HTML_NLAROUND}, {"div", HTML_NLAROUND}, + {"div", 0}, {"h1", HTML_NLAROUND}, {"h2", HTML_NLAROUND}, {"span", 0}, {"link", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, {"a", 0}, {"table", HTML_NLALL | HTML_INDENT}, {"tr", HTML_NLALL | HTML_INDENT}, {"td", HTML_NLAROUND}, {"li", HTML_NLAROUND | HTML_INDENT}, {"ul", HTML_NLALL | HTML_INDENT}, {"ol", HTML_NLALL | HTML_INDENT},
*** 101,124 **** {"munderover", 0}, {"munder", 0}, {"mover", 0}, }; ! static const char *const roffscales[SCALE_MAX] = { ! "cm", /* SCALE_CM */ ! "in", /* SCALE_IN */ ! "pc", /* SCALE_PC */ ! "pt", /* SCALE_PT */ ! "em", /* SCALE_EM */ ! "em", /* SCALE_MM */ ! "ex", /* SCALE_EN */ ! "ex", /* SCALE_BU */ ! "em", /* SCALE_VS */ ! "ex", /* SCALE_FS */ ! }; - static void a2width(const char *, struct roffsu *); static void print_byte(struct html *, char); static void print_endword(struct html *); static void print_indent(struct html *); static void print_word(struct html *, const char *); --- 102,114 ---- {"munderover", 0}, {"munder", 0}, {"mover", 0}, }; ! /* Avoid duplicate HTML id= attributes. */ ! static struct ohash id_unique; static void print_byte(struct html *, char); static void print_endword(struct html *); static void print_indent(struct html *); static void print_word(struct html *, const char *);
*** 141,178 **** h->base_man = outopts->man; h->base_includes = outopts->includes; if (outopts->fragment) h->oflags |= HTML_FRAGMENT; return h; } void html_free(void *p) { struct tag *tag; struct html *h; h = (struct html *)p; - while ((tag = h->tag) != NULL) { h->tag = tag->next; free(tag); } - free(h); } void print_gen_head(struct html *h) { struct tag *t; print_otag(h, TAG_META, "?", "charset", "utf-8"); /* ! * Print a default style-sheet. */ t = print_otag(h, TAG_STYLE, ""); print_text(h, "table.head, table.foot { width: 100%; }"); print_endline(h); --- 131,182 ---- h->base_man = outopts->man; h->base_includes = outopts->includes; if (outopts->fragment) h->oflags |= HTML_FRAGMENT; + mandoc_ohash_init(&id_unique, 4, 0); + return h; } void html_free(void *p) { struct tag *tag; struct html *h; + char *cp; + unsigned int slot; h = (struct html *)p; while ((tag = h->tag) != NULL) { h->tag = tag->next; free(tag); } free(h); + + cp = ohash_first(&id_unique, &slot); + while (cp != NULL) { + free(cp); + cp = ohash_next(&id_unique, &slot); + } + ohash_delete(&id_unique); } void print_gen_head(struct html *h) { struct tag *t; print_otag(h, TAG_META, "?", "charset", "utf-8"); + if (h->style != NULL) { + print_otag(h, TAG_LINK, "?h??", "rel", "stylesheet", + h->style, "type", "text/css", "media", "all"); + return; + } /* ! * Print a minimal embedded style sheet. */ t = print_otag(h, TAG_STYLE, ""); print_text(h, "table.head, table.foot { width: 100%; }"); print_endline(h);
*** 179,193 **** print_text(h, "td.head-rtitle, td.foot-os { text-align: right; }"); print_endline(h); print_text(h, "td.head-vol { text-align: center; }"); print_endline(h); print_text(h, "div.Pp { margin: 1ex 0ex; }"); print_tagq(h, t); - - if (h->style) - print_otag(h, TAG_LINK, "?h??", "rel", "stylesheet", - h->style, "type", "text/css", "media", "all"); } static void print_metaf(struct html *h, enum mandoc_esc deco) { --- 183,209 ---- print_text(h, "td.head-rtitle, td.foot-os { text-align: right; }"); print_endline(h); print_text(h, "td.head-vol { text-align: center; }"); print_endline(h); print_text(h, "div.Pp { margin: 1ex 0ex; }"); + print_endline(h); + print_text(h, "div.Nd, div.Bf, div.Op { display: inline; }"); + print_endline(h); + print_text(h, "span.Pa, span.Ad { font-style: italic; }"); + print_endline(h); + print_text(h, "span.Ms { font-weight: bold; }"); + print_endline(h); + print_text(h, "dl.Bl-diag "); + print_byte(h, '>'); + print_text(h, " dt { font-weight: bold; }"); + print_endline(h); + print_text(h, "code.Nm, code.Fl, code.Cm, code.Ic, " + "code.In, code.Fd, code.Fn,"); + print_endline(h); + print_text(h, "code.Cd { font-weight: bold; " + "font-family: inherit; }"); print_tagq(h, t); } static void print_metaf(struct html *h, enum mandoc_esc deco) {
*** 237,316 **** break; } } 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) ! { ! size_t rsz; ! int skip, sz; ! /* ! * Account for escaped sequences within string length ! * calculations. This follows the logic in term_strlen() as we ! * must calculate the width of produced strings. ! * Assume that characters are always width of "1". This is ! * hacky, but it gets the job done for approximation of widths. ! */ ! ! sz = 0; ! skip = 0; ! while (1) { ! rsz = strcspn(cp, "\\"); ! if (rsz) { ! cp += rsz; ! if (skip) { ! skip = 0; ! rsz--; } ! sz += rsz; } ! if ('\0' == *cp) ! break; ! cp++; ! switch (mandoc_escape(&cp, NULL, NULL)) { ! case ESCAPE_ERROR: ! return sz; ! case ESCAPE_UNICODE: ! case ESCAPE_NUMBERED: ! case ESCAPE_SPECIAL: ! case ESCAPE_OVERSTRIKE: ! if (skip) ! skip = 0; ! else ! sz++; ! break; ! case ESCAPE_SKIPCHAR: ! skip = 1; ! break; ! default: ! break; } ! } ! return sz; } static int print_escape(struct html *h, char c) { --- 253,315 ---- break; } } char * ! html_make_id(const struct roff_node *n, int unique) { const struct roff_node *nch; ! char *buf, *bufs, *cp; ! unsigned int slot; ! int suffix; for (nch = n->child; nch != NULL; nch = nch->next) if (nch->type != ROFFT_TEXT) return NULL; buf = NULL; deroff(&buf, n); + if (buf == NULL) + return NULL; ! /* ! * In ID attributes, only use ASCII characters that are ! * permitted in URL-fragment strings according to the ! * explicit list at: ! * https://url.spec.whatwg.org/#url-fragment-string ! */ for (cp = buf; *cp != '\0'; cp++) ! if (isalnum((unsigned char)*cp) == 0 && ! strchr("!$&'()*+,-./:;=?@_~", *cp) == NULL) *cp = '_'; + if (unique == 0) return buf; ! /* Avoid duplicate HTML id= attributes. */ ! bufs = NULL; ! suffix = 1; ! slot = ohash_qlookup(&id_unique, buf); ! cp = ohash_find(&id_unique, slot); ! if (cp != NULL) { ! while (cp != NULL) { ! free(bufs); ! if (++suffix > 127) { ! free(buf); ! return NULL; } ! mandoc_asprintf(&bufs, "%s_%d", buf, suffix); ! slot = ohash_qlookup(&id_unique, bufs); ! cp = ohash_find(&id_unique, slot); } ! free(buf); ! buf = bufs; } ! ohash_insert(&id_unique, slot, buf); ! return buf; } static int print_escape(struct html *h, char c) {
*** 488,504 **** struct tag * print_otag(struct html *h, enum htmltag tag, const char *fmt, ...) { va_list ap; - struct roffsu mysu, *su; - char numbuf[16]; struct tag *t; const char *attr; char *arg1, *arg2; ! double v; ! int i, have_style, tflags; tflags = htmltags[tag].flags; /* Push this tag onto the stack of open scopes. */ --- 487,500 ---- struct tag * print_otag(struct html *h, enum htmltag tag, const char *fmt, ...) { va_list ap; struct tag *t; const char *attr; char *arg1, *arg2; ! int tflags; tflags = htmltags[tag].flags; /* Push this tag onto the stack of open scopes. */
*** 534,554 **** print_byte(h, '<'); print_word(h, htmltags[tag].name); va_start(ap, fmt); - have_style = 0; while (*fmt != '\0') { - if (*fmt == 's') { - have_style = 1; - fmt++; - break; - } ! /* Parse a non-style attribute and its arguments. */ arg1 = va_arg(ap, char *); switch (*fmt++) { case 'c': attr = "class"; break; case 'h': --- 530,545 ---- print_byte(h, '<'); print_word(h, htmltags[tag].name); va_start(ap, fmt); while (*fmt != '\0') { ! /* Parse attributes and arguments. */ arg1 = va_arg(ap, char *); + arg2 = NULL; switch (*fmt++) { case 'c': attr = "class"; break; case 'h':
*** 555,578 **** attr = "href"; break; case 'i': attr = "id"; break; case '?': attr = arg1; arg1 = va_arg(ap, char *); break; default: abort(); } - arg2 = NULL; if (*fmt == 'M') arg2 = va_arg(ap, char *); if (arg1 == NULL) continue; ! /* Print the non-style attributes. */ print_byte(h, ' '); print_word(h, attr); print_byte(h, '='); print_byte(h, '"'); --- 546,572 ---- attr = "href"; break; case 'i': attr = "id"; break; + case 's': + attr = "style"; + arg2 = va_arg(ap, char *); + break; case '?': attr = arg1; arg1 = va_arg(ap, char *); break; default: abort(); } if (*fmt == 'M') arg2 = va_arg(ap, char *); if (arg1 == NULL) continue; ! /* Print the attributes. */ print_byte(h, ' '); print_word(h, attr); print_byte(h, '='); print_byte(h, '"');
*** 595,712 **** print_word(h, "\" title=\""); print_encode(h, arg1, NULL, 1); fmt++; break; default: print_encode(h, arg1, NULL, 1); ! break; ! } ! print_byte(h, '"'); ! } ! ! /* Print out styles. */ ! ! while (*fmt != '\0') { ! arg1 = NULL; ! su = NULL; ! ! /* First letter: input argument type. */ ! ! switch (*fmt++) { ! case 'h': ! i = va_arg(ap, int); ! su = &mysu; ! SCALE_HS_INIT(su, i); ! break; ! case 's': ! arg1 = va_arg(ap, char *); ! break; ! case 'u': ! su = va_arg(ap, struct roffsu *); ! break; ! case 'w': ! if ((arg2 = va_arg(ap, char *)) != NULL) { ! su = &mysu; ! a2width(arg2, su); ! } ! if (*fmt == '*') { ! if (su != NULL && su->unit == SCALE_EN && ! su->scale > 5.9 && su->scale < 6.1) ! su = NULL; ! fmt++; ! } ! if (*fmt == '+') { ! if (su != NULL) { ! /* Make even bold text fit. */ ! su->scale *= 1.2; ! /* Add padding. */ ! su->scale += 3.0; ! } ! fmt++; ! } ! if (*fmt == '-') { ! if (su != NULL) ! su->scale *= -1.0; ! fmt++; ! } ! break; ! default: ! abort(); ! } ! ! /* Second letter: style name. */ ! ! switch (*fmt++) { ! case 'h': ! attr = "height"; ! break; ! case 'i': ! attr = "text-indent"; ! break; ! case 'l': ! attr = "margin-left"; ! break; ! case 'w': ! attr = "width"; ! break; ! case 'W': ! attr = "min-width"; ! break; ! case '?': ! attr = arg1; ! arg1 = va_arg(ap, char *); ! break; ! default: ! abort(); ! } ! if (su == NULL && arg1 == NULL) ! continue; ! ! if (have_style == 1) ! print_word(h, " style=\""); ! else ! print_byte(h, ' '); ! print_word(h, attr); print_byte(h, ':'); print_byte(h, ' '); ! if (su != NULL) { ! v = su->scale; ! if (su->unit == SCALE_MM && (v /= 100.0) == 0.0) ! v = 1.0; ! else if (su->unit == SCALE_BU) ! v /= 24.0; ! (void)snprintf(numbuf, sizeof(numbuf), "%.2f", v); ! print_word(h, numbuf); ! print_word(h, roffscales[su->unit]); ! } else ! print_word(h, arg1); print_byte(h, ';'); - have_style = 2; } ! if (have_style == 2) print_byte(h, '"'); ! va_end(ap); /* Accommodate for "well-formed" singleton escaping. */ if (HTML_AUTOCLOSE & htmltags[tag].flags) --- 589,611 ---- print_word(h, "\" title=\""); print_encode(h, arg1, NULL, 1); fmt++; break; default: + if (arg2 == NULL) print_encode(h, arg1, NULL, 1); ! else { ! print_word(h, arg1); print_byte(h, ':'); print_byte(h, ' '); ! print_word(h, arg2); print_byte(h, ';'); } ! break; ! } print_byte(h, '"'); ! } va_end(ap); /* Accommodate for "well-formed" singleton escaping. */ if (HTML_AUTOCLOSE & htmltags[tag].flags)
*** 767,776 **** --- 666,701 ---- print_word(h, "<!DOCTYPE html>"); print_endline(h); } void + print_gen_comment(struct html *h, struct roff_node *n) + { + int wantblank; + + print_word(h, "<!-- This is an automatically generated file." + " Do not edit."); + h->indent = 1; + wantblank = 0; + while (n != NULL && n->type == ROFFT_COMMENT) { + if (strstr(n->string, "-->") == NULL && + (wantblank || *n->string != '\0')) { + print_endline(h); + print_indent(h); + print_word(h, n->string); + wantblank = *n->string != '\0'; + } + n = n->next; + } + if (wantblank) + print_endline(h); + print_word(h, " -->"); + print_endline(h); + h->indent = 0; + } + + void print_text(struct html *h, const char *word) { if (h->col && (h->flags & HTML_NOSPACE) == 0) { if ( ! (HTML_KEEP & h->flags)) { if (HTML_PREKEEP & h->flags)
*** 956,979 **** static void print_word(struct html *h, const char *cp) { while (*cp != '\0') print_byte(h, *cp++); - } - - /* - * Calculate the scaling unit passed in a `-width' argument. This uses - * either a native scaling unit (e.g., 1i, 2m) or the string length of - * the value. - */ - static void - a2width(const char *p, struct roffsu *su) - { - const char *end; - - end = a2roffsu(p, su, SCALE_MAX); - if (end == NULL || *end != '\0') { - su->unit = SCALE_EN; - su->scale = html_strlen(p); - } else if (su->scale < 0.0) - su->scale = 0.0; } --- 881,886 ----