From 81110a42d3e8acf54bd059afb29098770437d398 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Mon, 7 Jan 2019 07:26:29 +0000 Subject: Represent mdoc(7) .Pp (and .sp, and some SYNOPSIS and .Rs features) by the

HTML element and use the html_fillmode() mechanism for .Bd -unfilled, just like it was done for man(7) earlier, finally getting rid both of the horrible

hack and of the worst HTML syntax violations caused by nested displays. Care is needed because in some situations, paragraphs have to remain open across several subsequent macros, whereas in other situations, they must get closed together with a block containing them. Some implementation details include: * Always close paragraphs before emitting HTML flow content. * Let html_close_paragraph() also close
 for extra safety.
* Drop the old, now unused function print_paragraph().
* Minor adjustments in the top-level man(7) node formatter for symmetry.
* Bugfix: .Ss heads suspend no-fill mode, even though .Ss doesn't end it.
* Bugfix: give up on .Op semantic markup for now, see the comment.
---
 html.c                                 |  24 ++--
 html.h                                 |   3 +-
 man_html.c                             |  23 ++--
 mdoc_html.c                            | 226 +++++++++++++++++++--------------
 mdoc_macro.c                           |  17 ++-
 regress/char/unicode/invalid.out_html  |  14 +-
 regress/mdoc/Bd/Makefile               |   5 +-
 regress/mdoc/Bd/nf.in                  |   9 +-
 regress/mdoc/Bd/nf.out_ascii           |   6 +-
 regress/mdoc/Bd/nf.out_html            |  22 ++++
 regress/mdoc/Bd/nf.out_markdown        |   7 +-
 regress/mdoc/Bd/paragraph.in           |  39 ++++++
 regress/mdoc/Bd/paragraph.out_ascii    |  27 ++++
 regress/mdoc/Bd/paragraph.out_html     |  19 +++
 regress/mdoc/Bd/paragraph.out_markdown |  39 ++++++
 regress/mdoc/Bf/Makefile               |   7 +-
 regress/mdoc/Bf/paragraph.in           |  22 ++++
 regress/mdoc/Bf/paragraph.out_ascii    |  14 ++
 regress/mdoc/Bf/paragraph.out_html     |   6 +
 regress/mdoc/D1/Makefile               |   3 +-
 regress/mdoc/D1/spacing.in             |  13 +-
 regress/mdoc/D1/spacing.out_ascii      |   8 +-
 regress/mdoc/D1/spacing.out_html       |   8 ++
 regress/mdoc/D1/spacing.out_lint       |   2 +-
 regress/mdoc/D1/spacing.out_markdown   |  11 +-
 regress/mdoc/Rs/Makefile               |   5 +-
 regress/mdoc/Rs/paragraph.in           |  37 ++++++
 regress/mdoc/Rs/paragraph.out_ascii    |  23 ++++
 regress/mdoc/Rs/paragraph.out_html     |  17 +++
 regress/mdoc/Rs/paragraph.out_markdown |  32 +++++
 regress/mdoc/Sh/Makefile               |   5 +-
 regress/mdoc/Sh/paragraph.in           |  19 +++
 regress/mdoc/Sh/paragraph.out_ascii    |  20 +++
 regress/mdoc/Sh/paragraph.out_html     |   7 +
 regress/mdoc/Sh/paragraph.out_markdown |  24 ++++
 regress/roff/string/dotT.in            |  12 +-
 regress/roff/string/dotT.out_ascii     |   8 +-
 regress/roff/string/dotT.out_html      |   8 +-
 regress/roff/string/dotT.out_markdown  |  10 +-
 regress/roff/string/dotT.out_utf8      |   8 +-
 roff_html.c                            |   8 +-
 41 files changed, 627 insertions(+), 190 deletions(-)
 create mode 100644 regress/mdoc/Bd/nf.out_html
 create mode 100644 regress/mdoc/Bd/paragraph.in
 create mode 100644 regress/mdoc/Bd/paragraph.out_ascii
 create mode 100644 regress/mdoc/Bd/paragraph.out_html
 create mode 100644 regress/mdoc/Bd/paragraph.out_markdown
 create mode 100644 regress/mdoc/Bf/paragraph.in
 create mode 100644 regress/mdoc/Bf/paragraph.out_ascii
 create mode 100644 regress/mdoc/Bf/paragraph.out_html
 create mode 100644 regress/mdoc/D1/spacing.out_html
 create mode 100644 regress/mdoc/Rs/paragraph.in
 create mode 100644 regress/mdoc/Rs/paragraph.out_ascii
 create mode 100644 regress/mdoc/Rs/paragraph.out_html
 create mode 100644 regress/mdoc/Rs/paragraph.out_markdown
 create mode 100644 regress/mdoc/Sh/paragraph.in
 create mode 100644 regress/mdoc/Sh/paragraph.out_ascii
 create mode 100644 regress/mdoc/Sh/paragraph.out_html
 create mode 100644 regress/mdoc/Sh/paragraph.out_markdown

diff --git a/html.c b/html.c
index 71070769..55d5c99f 100644
--- a/html.c
+++ b/html.c
@@ -1,4 +1,4 @@
-/*	$Id: html.c,v 1.249 2019/01/06 04:55:09 schwarze Exp $ */
+/*	$Id: html.c,v 1.250 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons 
  * Copyright (c) 2011-2015, 2017-2019 Ingo Schwarze 
@@ -272,7 +272,7 @@ html_close_paragraph(struct html *h)
 	struct tag	*t;
 
 	for (t = h->tag; t != NULL; t = t->next) {
-		if (t->tag == TAG_P) {
+		if (t->tag == TAG_P || t->tag == TAG_PRE) {
 			print_tagq(h, t);
 			break;
 		}
@@ -834,32 +834,30 @@ print_tagq(struct html *h, const struct tag *until)
 
 	while ((tag = h->tag) != NULL) {
 		print_ctag(h, tag);
-		if (until && tag == until)
+		if (tag == until)
 			return;
 	}
 }
 
+/*
+ * Close out all open elements up to but excluding suntil.
+ * Note that a paragraph just inside stays open together with it
+ * because paragraphs include subsequent phrasing content.
+ */
 void
 print_stagq(struct html *h, const struct tag *suntil)
 {
 	struct tag	*tag;
 
 	while ((tag = h->tag) != NULL) {
-		if (suntil && tag == suntil)
+		if (tag == suntil ||
+		    (tag->next == suntil &&
+		     (tag->tag == TAG_P || tag->tag == TAG_PRE)))
 			return;
 		print_ctag(h, tag);
 	}
 }
 
-void
-print_paragraph(struct html *h)
-{
-	struct tag	*t;
-
-	t = print_otag(h, TAG_DIV, "c", "Pp");
-	print_tagq(h, t);
-}
-
 
 /***********************************************************************
  * Low level output functions.
diff --git a/html.h b/html.h
index 89cfa96f..546f3582 100644
--- a/html.h
+++ b/html.h
@@ -1,4 +1,4 @@
-/*	$Id: html.h,v 1.99 2019/01/06 04:55:09 schwarze Exp $ */
+/*	$Id: html.h,v 1.100 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons 
  * Copyright (c) 2017, 2018, 2019 Ingo Schwarze 
@@ -133,7 +133,6 @@ void		  print_text(struct html *, const char *);
 void		  print_tblclose(struct html *);
 void		  print_tbl(struct html *, const struct tbl_span *);
 void		  print_eqn(struct html *, const struct eqn_box *);
-void		  print_paragraph(struct html *);
 void		  print_endline(struct html *);
 
 void		  html_close_paragraph(struct html *);
diff --git a/man_html.c b/man_html.c
index 98ab2aae..8b4dd945 100644
--- a/man_html.c
+++ b/man_html.c
@@ -1,4 +1,4 @@
-/*	$Id: man_html.c,v 1.166 2019/01/06 04:55:09 schwarze Exp $ */
+/*	$Id: man_html.c,v 1.167 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons 
  * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze 
@@ -162,16 +162,22 @@ print_man_node(MAN_ARGS)
 	struct tag	*t;
 	int		 child;
 
+	if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
+		return;
+
 	html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
 
 	child = 1;
+	t = h->tag;
+	if (t->tag == TAG_P || t->tag == TAG_PRE)
+		t = t->next;
+
 	switch (n->type) {
 	case ROFFT_TEXT:
 		if (*n->string == '\0') {
 			print_endline(h);
 			return;
 		}
-		t = h->tag;
 		if (*n->string == ' ' && n->flags & NODE_LINE &&
 		    (h->flags & HTML_NONEWLINE) == 0)
 			print_endline(h);
@@ -179,10 +185,7 @@ print_man_node(MAN_ARGS)
 			h->flags |= HTML_NOSPACE;
 		print_text(h, n->string);
 		break;
-	case ROFFT_COMMENT:
-		return;
 	case ROFFT_EQN:
-		t = h->tag;
 		print_eqn(h, n->eqn);
 		break;
 	case ROFFT_TBL:
@@ -208,17 +211,15 @@ print_man_node(MAN_ARGS)
 		 * the "meta" table state.  This will be reopened on the
 		 * next table element.
 		 */
-		if (h->tblt != NULL)
+		if (h->tblt != NULL) {
 			print_tblclose(h);
-
-		t = h->tag;
+			t = h->tag;
+		}
 		if (n->tok < ROFF_MAX) {
 			roff_html_pre(h, n);
-			if (n->tok != ROFF_sp)
-				print_stagq(h, t);
+			print_stagq(h, t);
 			return;
 		}
-
 		assert(n->tok >= MAN_TH && n->tok < MAN_MAX);
 		if (man_html_acts[n->tok - MAN_TH].pre != NULL)
 			child = (*man_html_acts[n->tok - MAN_TH].pre)(man,
diff --git a/mdoc_html.c b/mdoc_html.c
index e4523f95..2978f0c8 100644
--- a/mdoc_html.c
+++ b/mdoc_html.c
@@ -1,4 +1,4 @@
-/*	$Id: mdoc_html.c,v 1.322 2018/12/31 10:35:56 schwarze Exp $ */
+/*	$Id: mdoc_html.c,v 1.323 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons 
  * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze 
@@ -268,18 +268,17 @@ synopsis_pre(struct html *h, const struct roff_node *n)
 	case MDOC_Fo:
 	case MDOC_In:
 	case MDOC_Vt:
-		print_paragraph(h);
 		break;
 	case MDOC_Ft:
-		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
-			print_paragraph(h);
+		if (n->tok != MDOC_Fn && n->tok != MDOC_Fo)
 			break;
-		}
 		/* FALLTHROUGH */
 	default:
 		print_otag(h, TAG_BR, "");
-		break;
+		return;
 	}
+	html_close_paragraph(h);
+	print_otag(h, TAG_P, "c", "Pp");
 }
 
 void
@@ -346,16 +345,20 @@ print_mdoc_nodelist(MDOC_ARGS)
 static void
 print_mdoc_node(MDOC_ARGS)
 {
-	int		 child;
 	struct tag	*t;
+	int		 child;
 
 	if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
 		return;
 
+	html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
+
 	child = 1;
 	t = h->tag;
-	n->flags &= ~NODE_ENDED;
+	if (t->tag == TAG_P || t->tag == TAG_PRE)
+		t = t->next;
 
+	n->flags &= ~NODE_ENDED;
 	switch (n->type) {
 	case ROFFT_TEXT:
 		/* No tables in this mode... */
@@ -374,7 +377,7 @@ print_mdoc_node(MDOC_ARGS)
 		print_text(h, n->string);
 		if (NODE_DELIMO & n->flags)
 			h->flags |= HTML_NOSPACE;
-		return;
+		break;
 	case ROFFT_EQN:
 		print_eqn(h, n->eqn);
 		break;
@@ -399,8 +402,8 @@ print_mdoc_node(MDOC_ARGS)
 		assert(h->tblt == NULL);
 		if (n->tok < ROFF_MAX) {
 			roff_html_pre(h, n);
-			child = 0;
-			break;
+			print_stagq(h, t);
+			return;
 		}
 		assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
 		if (mdoc_html_acts[n->tok - MDOC_Dd].pre != NULL &&
@@ -415,17 +418,17 @@ print_mdoc_node(MDOC_ARGS)
 		h->flags |= HTML_PREKEEP;
 	}
 
-	if (child && n->child)
+	if (child && n->child != NULL)
 		print_mdoc_nodelist(meta, n->child, h);
 
 	print_stagq(h, t);
 
 	switch (n->type) {
+	case ROFFT_TEXT:
 	case ROFFT_EQN:
 		break;
 	default:
-		if (n->tok < ROFF_MAX ||
-		    mdoc_html_acts[n->tok - MDOC_Dd].post == NULL ||
+		if (mdoc_html_acts[n->tok - MDOC_Dd].post == NULL ||
 		    n->flags & NODE_ENDED)
 			break;
 		(*mdoc_html_acts[n->tok - MDOC_Dd].post)(meta, n, h);
@@ -433,6 +436,12 @@ print_mdoc_node(MDOC_ARGS)
 			n->body->flags |= NODE_ENDED;
 		break;
 	}
+
+	if (n->flags & NODE_NOFILL &&
+	    (n->next == NULL || n->next->flags & NODE_LINE)) {
+		h->col++;
+		print_endline(h);
+	}
 }
 
 static void
@@ -516,6 +525,7 @@ mdoc_sh_pre(MDOC_ARGS)
 
 	switch (n->type) {
 	case ROFFT_BLOCK:
+		html_close_paragraph(h);
 		if ((h->oflags & HTML_TOC) == 0 ||
 		    h->flags & HTML_TOCDONE ||
 		    n->sec <= SEC_SYNOPSIS)
@@ -582,8 +592,17 @@ mdoc_ss_pre(MDOC_ARGS)
 {
 	char	*id;
 
-	if (n->type != ROFFT_HEAD)
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
+		return 1;
+	case ROFFT_HEAD:
+		break;
+	case ROFFT_BODY:
 		return 1;
+	default:
+		abort();
+	}
 
 	id = html_make_id(n, 1);
 	print_otag(h, TAG_H2, "cTi", "Ss", id);
@@ -625,9 +644,17 @@ mdoc_cm_pre(MDOC_ARGS)
 static int
 mdoc_nd_pre(MDOC_ARGS)
 {
-	if (n->type != ROFFT_BODY)
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
 		return 1;
-
+	case ROFFT_HEAD:
+		return 0;
+	case ROFFT_BODY:
+		break;
+	default:
+		abort();
+	}
 	print_text(h, "\\(em");
 	/* Cannot use TAG_SPAN because it may contain blocks. */
 	print_otag(h, TAG_DIV, "cT", "Nd");
@@ -638,6 +665,8 @@ static int
 mdoc_nm_pre(MDOC_ARGS)
 {
 	switch (n->type) {
+	case ROFFT_BLOCK:
+		break;
 	case ROFFT_HEAD:
 		print_otag(h, TAG_TD, "");
 		/* FALLTHROUGH */
@@ -648,8 +677,9 @@ mdoc_nm_pre(MDOC_ARGS)
 		print_otag(h, TAG_TD, "");
 		return 1;
 	default:
-		break;
+		abort();
 	}
+	html_close_paragraph(h);
 	synopsis_pre(h, n);
 	print_otag(h, TAG_TABLE, "c", "Nm");
 	print_otag(h, TAG_TR, "");
@@ -802,12 +832,15 @@ mdoc_bl_pre(MDOC_ARGS)
 	enum htmltag	 elemtype;
 
 	switch (n->type) {
-	case ROFFT_BODY:
-		return 1;
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
+		break;
 	case ROFFT_HEAD:
 		return 0;
+	case ROFFT_BODY:
+		return 1;
 	default:
-		break;
+		abort();
 	}
 
 	bl = &n->norm->Bl;
@@ -891,14 +924,20 @@ mdoc_em_pre(MDOC_ARGS)
 static int
 mdoc_d1_pre(MDOC_ARGS)
 {
-	if (n->type != ROFFT_BLOCK)
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
+		break;
+	case ROFFT_HEAD:
+		return 0;
+	case ROFFT_BODY:
 		return 1;
-
+	default:
+		abort();
+	}
 	print_otag(h, TAG_DIV, "c", "Bd Bd-indent");
-
 	if (n->tok == MDOC_Dl)
 		print_otag(h, TAG_CODE, "c", "Li");
-
 	return 1;
 }
 
@@ -916,69 +955,45 @@ mdoc_sx_pre(MDOC_ARGS)
 static int
 mdoc_bd_pre(MDOC_ARGS)
 {
-	int			 comp;
+	char			 buf[16];
 	struct roff_node	*nn;
+	int			 comp;
 
-	if (n->type == ROFFT_HEAD)
-		return 0;
-
-	if (n->type == ROFFT_BLOCK) {
-		comp = n->norm->Bd.comp;
-		for (nn = n; nn && ! comp; nn = nn->parent) {
-			if (nn->type != ROFFT_BLOCK)
-				continue;
-			if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok)
-				comp = 1;
-			if (nn->prev)
-				break;
-		}
-		if ( ! comp)
-			print_paragraph(h);
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
 		return 1;
+	case ROFFT_HEAD:
+		return 0;
+	case ROFFT_BODY:
+		break;
+	default:
+		abort();
 	}
 
-	/* Handle the -offset argument. */
-
-	if (n->norm->Bd.offs == NULL ||
-	    ! strcmp(n->norm->Bd.offs, "left"))
-		print_otag(h, TAG_DIV, "c", "Bd");
-	else
-		print_otag(h, TAG_DIV, "c", "Bd Bd-indent");
-
-	if (n->norm->Bd.type != DISP_unfilled &&
-	    n->norm->Bd.type != DISP_literal)
-		return 1;
+	/* Handle preceding whitespace. */
 
-	print_otag(h, TAG_PRE, "c", "Li");
-	for (nn = n->child; nn; nn = nn->next) {
-		print_mdoc_node(meta, nn, h);
-		/*
-		 * If the printed node flushes its own line, then we
-		 * needn't do it here as well.  This is hacky, but the
-		 * notion of selective eoln whitespace is pretty dumb
-		 * anyway, so don't sweat it.
-		 */
-		switch (nn->tok) {
-		case ROFF_br:
-		case ROFF_sp:
-		case MDOC_Sm:
-		case MDOC_Bl:
-		case MDOC_D1:
-		case MDOC_Dl:
-		case MDOC_Pp:
+	comp = n->norm->Bd.comp;
+	for (nn = n; nn != NULL && comp == 0; nn = nn->parent) {
+		if (nn->type != ROFFT_BLOCK)
 			continue;
-		default:
+		if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
+			comp = 1;
+		if (nn->prev != NULL)
 			break;
-		}
-		if (h->flags & HTML_NONEWLINE ||
-		    (nn->next && ! (nn->next->flags & NODE_LINE)))
-			continue;
-		else if (nn->next)
-			print_text(h, "\n");
-
-		h->flags |= HTML_NOSPACE;
 	}
-	return 0;
+	(void)strlcpy(buf, "Bd", sizeof(buf));
+	if (comp == 0)
+		(void)strlcat(buf, " Pp", sizeof(buf));
+
+	/* Handle the -offset argument. */
+
+	if (n->norm->Bd.offs != NULL &&
+	    strcmp(n->norm->Bd.offs, "left") != 0)
+		(void)strlcat(buf, " Bd-indent", sizeof(buf));
+
+	print_otag(h, TAG_DIV, "c", buf);
+	return 1;
 }
 
 static int
@@ -1262,8 +1277,10 @@ mdoc_skip_pre(MDOC_ARGS)
 static int
 mdoc_pp_pre(MDOC_ARGS)
 {
-
-	print_paragraph(h);
+	if ((n->flags & NODE_NOFILL) == 0) {
+		html_close_paragraph(h);
+		print_otag(h, TAG_P, "c", "Pp");
+	}
 	return 0;
 }
 
@@ -1438,10 +1455,17 @@ mdoc_bf_pre(MDOC_ARGS)
 {
 	const char	*cattr;
 
-	if (n->type == ROFFT_HEAD)
-		return 0;
-	else if (n->type != ROFFT_BODY)
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		html_close_paragraph(h);
 		return 1;
+	case ROFFT_HEAD:
+		return 0;
+	case ROFFT_BODY:
+		break;
+	default:
+		abort();
+	}
 
 	if (FONT_Em == n->norm->Bf.font)
 		cattr = "Bf Em";
@@ -1487,13 +1511,21 @@ mdoc_pf_post(MDOC_ARGS)
 static int
 mdoc_rs_pre(MDOC_ARGS)
 {
-	if (n->type != ROFFT_BLOCK)
-		return 1;
-
-	if (n->prev && SEC_SEE_ALSO == n->sec)
-		print_paragraph(h);
-
-	print_otag(h, TAG_CITE, "cT", "Rs");
+	switch (n->type) {
+	case ROFFT_BLOCK:
+		if (n->sec == SEC_SEE_ALSO)
+			html_close_paragraph(h);
+		break;
+	case ROFFT_HEAD:
+		return 0;
+	case ROFFT_BODY:
+		if (n->sec == SEC_SEE_ALSO)
+			print_otag(h, TAG_P, "c", "Pp");
+		print_otag(h, TAG_CITE, "cT", "Rs");
+		break;
+	default:
+		abort();
+	}
 	return 1;
 }
 
@@ -1670,9 +1702,15 @@ mdoc_quote_pre(MDOC_ARGS)
 	case MDOC_Oo:
 	case MDOC_Op:
 		print_text(h, "\\(lB");
-		h->flags |= HTML_NOSPACE;
-		/* Cannot use TAG_SPAN because it may contain blocks. */
-		print_otag(h, TAG_IDIV, "c", "Op");
+		/*
+		 * Give up on semantic markup for now.
+		 * We cannot use TAG_SPAN because .Oo may contain blocks.
+		 * We cannot use TAG_IDIV because we might be in a
+		 * phrasing context (like .Dl or .Pp); we cannot
+		 * close out a .Pp at this point either because
+		 * that would break the line.
+		 */
+		/* XXX print_otag(h, TAG_???, "c", "Op"); */
 		break;
 	case MDOC_En:
 		if (NULL == n->norm->Es ||
diff --git a/mdoc_macro.c b/mdoc_macro.c
index aed0221d..34229458 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -1,4 +1,4 @@
-/*	$Id: mdoc_macro.c,v 1.231 2019/01/01 07:42:04 schwarze Exp $ */
+/*	$Id: mdoc_macro.c,v 1.232 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons 
  * Copyright (c) 2010, 2012-2019 Ingo Schwarze 
@@ -295,6 +295,8 @@ rew_pending(struct roff_man *mdoc, const struct roff_node *n)
 			case ROFFT_HEAD:
 				roff_body_alloc(mdoc, n->line, n->pos,
 				    n->tok);
+				if (n->tok == MDOC_Ss)
+					mdoc->flags &= ~ROFF_NONOFILL;
 				break;
 			case ROFFT_BLOCK:
 				break;
@@ -1053,9 +1055,16 @@ blk_full(MACRO_PROT_ARGS)
 	 * regular child nodes.
 	 */
 
-	if (tok == MDOC_Sh)
+	switch (tok) {
+	case MDOC_Sh:
 		mdoc->flags &= ~ROFF_NOFILL;
-
+		break;
+	case MDOC_Ss:
+		mdoc->flags |= ROFF_NONOFILL;
+		break;
+	default:
+		break;
+	}
 	mdoc_argv(mdoc, line, tok, &arg, pos, buf);
 	blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg);
 	head = body = NULL;
@@ -1197,6 +1206,8 @@ blk_full(MACRO_PROT_ARGS)
 
 	rew_last(mdoc, head);
 	body = roff_body_alloc(mdoc, line, ppos, tok);
+	if (tok == MDOC_Ss)
+		mdoc->flags &= ~ROFF_NONOFILL;
 
 	/*
 	 * Set up fill mode for display blocks.
diff --git a/regress/char/unicode/invalid.out_html b/regress/char/unicode/invalid.out_html
index c4761ea6..0de972f1 100644
--- a/regress/char/unicode/invalid.out_html
+++ b/regress/char/unicode/invalid.out_html
@@ -1,8 +1,8 @@
-BEGINTEST 
-too short: >.< 
-just right: >+< 
-too long: >..< 
-too large: >..< 
-trailing garbage: >< 
-not unicode: >_.↑.⇑< 
+BEGINTEST
+too short: >.<
+just right: >+<
+too long: >..<
+too large: >..<
+trailing garbage: ><
+not unicode: >_.↑.⇑<
 ENDTEST
diff --git a/regress/mdoc/Bd/Makefile b/regress/mdoc/Bd/Makefile
index 0d0b2fb9..f05f54b0 100644
--- a/regress/mdoc/Bd/Makefile
+++ b/regress/mdoc/Bd/Makefile
@@ -1,10 +1,11 @@
-# $OpenBSD: Makefile,v 1.21 2019/01/04 03:54:50 schwarze Exp $
+# $OpenBSD: Makefile,v 1.22 2019/01/07 06:51:37 schwarze Exp $
 
-REGRESS_TARGETS	 = beforeNAME blank centered nested nf spacing
+REGRESS_TARGETS	 = beforeNAME blank centered nested nf paragraph spacing
 REGRESS_TARGETS	+= badargs empty offset-empty offset-neg
 REGRESS_TARGETS	+= break broken unclosed
 
 LINT_TARGETS	 = beforeNAME blank nested badargs break broken unclosed
+HTML_TARGETS	 = nf paragraph
 
 SKIP_TMAN	 = beforeNAME centered
 
diff --git a/regress/mdoc/Bd/nf.in b/regress/mdoc/Bd/nf.in
index 884825e2..2a2c44d8 100644
--- a/regress/mdoc/Bd/nf.in
+++ b/regress/mdoc/Bd/nf.in
@@ -1,11 +1,12 @@
-.\" $OpenBSD: nf.in,v 1.1 2019/01/04 03:54:50 schwarze Exp $
-.Dd $Mdocdate: January 4 2019 $
+.\" $OpenBSD: nf.in,v 1.2 2019/01/07 06:51:37 schwarze Exp $
+.Dd $Mdocdate: January 7 2019 $
 .Dt BD-NF 1
 .Os
 .Sh NAME
 .Nm Bd-nf
 .Nd interaction of no-fill blocks and requests
 .Sh DESCRIPTION
+BEGINTEST
 initial
 text
 .nf
@@ -32,3 +33,7 @@ in filled block
 .Ed
 after end
 of filled block
+.br
+ENDTEST
+.br
+end of file
diff --git a/regress/mdoc/Bd/nf.out_ascii b/regress/mdoc/Bd/nf.out_ascii
index 4a42fe82..d8ceb0c9 100644
--- a/regress/mdoc/Bd/nf.out_ascii
+++ b/regress/mdoc/Bd/nf.out_ascii
@@ -4,7 +4,7 @@ NNAAMMEE
      BBdd--nnff - interaction of no-fill blocks and requests
 
 DDEESSCCRRIIPPTTIIOONN
-     initial text
+     BEGINTEST initial text
      after .nf
      request
      after .fi request
@@ -18,5 +18,7 @@ DDEESSCCRRIIPPTTIIOONN
      after .nf request
      in filled block
      after end of filled block
+     ENDTEST
+     end of file
 
-OpenBSD                         January 4, 2019                        OpenBSD
+OpenBSD                         January 7, 2019                        OpenBSD
diff --git a/regress/mdoc/Bd/nf.out_html b/regress/mdoc/Bd/nf.out_html
new file mode 100644
index 00000000..31642e07
--- /dev/null
+++ b/regress/mdoc/Bd/nf.out_html
@@ -0,0 +1,22 @@
+BEGINTEST initial text
+
+after .nf
+request
+
+after .fi request +
+
+in unfilled
+block
+
+after .fi request in unfilled block
+after end of unfilled block +
in filled block +
+after .nf request
+in filled block
+
+
+after end of filled block +
+ENDTEST diff --git a/regress/mdoc/Bd/nf.out_markdown b/regress/mdoc/Bd/nf.out_markdown index 382bb786..46ece0a2 100644 --- a/regress/mdoc/Bd/nf.out_markdown +++ b/regress/mdoc/Bd/nf.out_markdown @@ -6,6 +6,7 @@ BD-NF(1) - General Commands Manual # DESCRIPTION +BEGINTEST initial text after .nf @@ -27,6 +28,8 @@ of unfilled block > in filled block after end -of filled block +of filled block +ENDTEST +end of file -OpenBSD - January 4, 2019 +OpenBSD - January 7, 2019 diff --git a/regress/mdoc/Bd/paragraph.in b/regress/mdoc/Bd/paragraph.in new file mode 100644 index 00000000..e1ebfd01 --- /dev/null +++ b/regress/mdoc/Bd/paragraph.in @@ -0,0 +1,39 @@ +.\" $OpenBSD: paragraph.in,v 1.1 2019/01/07 06:51:37 schwarze Exp $ +.Dd $Mdocdate: January 7 2019 $ +.Dt BD-PARAGRAPH 1 +.Os +.Sh NAME +.Nm Bd-paragraph +.Nd interaction of paragraphs and displays +.Sh DESCRIPTION +BEGINTEST +initial +text +.Pp +normal +paragraph +.Bd -filled +filled +display +.Pp +paragraph +in display +.Ed +back +to normal +.Pp +another +paragraph +.Bd -unfilled +unfilled +display +.Pp +unfilled +paragraph +.Ed +again back +to normal +.br +ENDTEST +.br +end of file diff --git a/regress/mdoc/Bd/paragraph.out_ascii b/regress/mdoc/Bd/paragraph.out_ascii new file mode 100644 index 00000000..216f4530 --- /dev/null +++ b/regress/mdoc/Bd/paragraph.out_ascii @@ -0,0 +1,27 @@ +BD-PARAGRAPH(1) General Commands Manual BD-PARAGRAPH(1) + +NNAAMMEE + BBdd--ppaarraaggrraapphh - interaction of paragraphs and displays + +DDEESSCCRRIIPPTTIIOONN + BEGINTEST initial text + + normal paragraph + + filled display + + paragraph in display + back to normal + + another paragraph + + unfilled + display + + unfilled + paragraph + again back to normal + ENDTEST + end of file + +OpenBSD January 7, 2019 OpenBSD diff --git a/regress/mdoc/Bd/paragraph.out_html b/regress/mdoc/Bd/paragraph.out_html new file mode 100644 index 00000000..c2c6993e --- /dev/null +++ b/regress/mdoc/Bd/paragraph.out_html @@ -0,0 +1,19 @@ +BEGINTEST initial text +

normal paragraph

+
filled display +

paragraph in display

+
+back to normal +

another paragraph

+
+
+unfilled
+display
+
+unfilled
+paragraph
+
+
+again back to normal +
+ENDTEST diff --git a/regress/mdoc/Bd/paragraph.out_markdown b/regress/mdoc/Bd/paragraph.out_markdown new file mode 100644 index 00000000..13e43f11 --- /dev/null +++ b/regress/mdoc/Bd/paragraph.out_markdown @@ -0,0 +1,39 @@ +BD-PARAGRAPH(1) - General Commands Manual + +# NAME + +**Bd-paragraph** - interaction of paragraphs and displays + +# DESCRIPTION + +BEGINTEST +initial +text + +normal +paragraph + +> filled +> display + +> paragraph +> in display + +back +to normal + +another +paragraph + + unfilled + display + + unfilled + paragraph + +again back +to normal +ENDTEST +end of file + +OpenBSD - January 7, 2019 diff --git a/regress/mdoc/Bf/Makefile b/regress/mdoc/Bf/Makefile index eb845e95..da5b2d91 100644 --- a/regress/mdoc/Bf/Makefile +++ b/regress/mdoc/Bf/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.4 2014/07/04 16:11:42 schwarze Exp $ +# $OpenBSD: Makefile,v 1.6 2019/01/07 06:51:37 schwarze Exp $ -REGRESS_TARGETS = nest multiargs badargs break broken -LINT_TARGETS = multiargs badargs break broken +REGRESS_TARGETS = badargs break broken multiargs nest paragraph +LINT_TARGETS = badargs break broken multiargs +HTML_TARGETS = paragraph # mandoc -T markdown ignores .Bf, at least for now diff --git a/regress/mdoc/Bf/paragraph.in b/regress/mdoc/Bf/paragraph.in new file mode 100644 index 00000000..3dcdabb8 --- /dev/null +++ b/regress/mdoc/Bf/paragraph.in @@ -0,0 +1,22 @@ +.\" $OpenBSD: paragraph.in,v 1.1 2019/01/07 06:51:37 schwarze Exp $ +.Dd $Mdocdate: January 7 2019 $ +.Dt BF-PARAGRAPH 1 +.Os +.Sh NAME +.Nm Bf-paragraph +.Nd interaction of paragraphs and font blocks +.Sh DESCRIPTION +BEGINTEST +.Pp +normal +text +.Bf -literal +literal +text +.Pp +literal +paragraph +.Ef +ENDTEST +.br +end of file diff --git a/regress/mdoc/Bf/paragraph.out_ascii b/regress/mdoc/Bf/paragraph.out_ascii new file mode 100644 index 00000000..25b2fd89 --- /dev/null +++ b/regress/mdoc/Bf/paragraph.out_ascii @@ -0,0 +1,14 @@ +BF-PARAGRAPH(1) General Commands Manual BF-PARAGRAPH(1) + +NNAAMMEE + BBff--ppaarraaggrraapphh - interaction of paragraphs and font blocks + +DDEESSCCRRIIPPTTIIOONN + BEGINTEST + + normal text literal text + + literal paragraph ENDTEST + end of file + +OpenBSD January 7, 2019 OpenBSD diff --git a/regress/mdoc/Bf/paragraph.out_html b/regress/mdoc/Bf/paragraph.out_html new file mode 100644 index 00000000..e86b979a --- /dev/null +++ b/regress/mdoc/Bf/paragraph.out_html @@ -0,0 +1,6 @@ +BEGINTEST +

normal text

+
literal text +

literal paragraph

+
+ENDTEST diff --git a/regress/mdoc/D1/Makefile b/regress/mdoc/D1/Makefile index bed27d1b..b94d5727 100644 --- a/regress/mdoc/D1/Makefile +++ b/regress/mdoc/D1/Makefile @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile,v 1.2 2015/02/06 02:04:35 schwarze Exp $ +# $OpenBSD: Makefile,v 1.5 2019/01/07 06:51:37 schwarze Exp $ REGRESS_TARGETS = spacing LINT_TARGETS = spacing +HTML_TARGETS = spacing .include diff --git a/regress/mdoc/D1/spacing.in b/regress/mdoc/D1/spacing.in index e7733298..c0f293c4 100644 --- a/regress/mdoc/D1/spacing.in +++ b/regress/mdoc/D1/spacing.in @@ -1,13 +1,20 @@ -.\" $OpenBSD: spacing.in,v 1.3 2017/07/04 14:53:24 schwarze Exp $ -.Dd $Mdocdate: July 4 2017 $ +.\" $OpenBSD: spacing.in,v 1.4 2019/01/07 06:51:37 schwarze Exp $ +.Dd $Mdocdate: January 7 2019 $ .Dt D1-SPACING 1 .Os .Sh NAME .Nm D1-spacing .Nd spacing in and around one-line displays .Sh DESCRIPTION -preceding text +BEGINTEST +.Pp +preceding +paragraph .D1 spacing in and around one-line displays empty display: .D1 following text +.br +ENDTEST +.br +end of file diff --git a/regress/mdoc/D1/spacing.out_ascii b/regress/mdoc/D1/spacing.out_ascii index 40945936..c0d1556d 100644 --- a/regress/mdoc/D1/spacing.out_ascii +++ b/regress/mdoc/D1/spacing.out_ascii @@ -4,9 +4,13 @@ NNAAMMEE DD11--ssppaacciinngg - spacing in and around one-line displays DDEESSCCRRIIPPTTIIOONN - preceding text + BEGINTEST + + preceding paragraph spacing in and around one-line displays empty display: following text + ENDTEST + end of file -OpenBSD July 4, 2017 OpenBSD +OpenBSD January 7, 2019 OpenBSD diff --git a/regress/mdoc/D1/spacing.out_html b/regress/mdoc/D1/spacing.out_html new file mode 100644 index 00000000..b1a1d4da --- /dev/null +++ b/regress/mdoc/D1/spacing.out_html @@ -0,0 +1,8 @@ +BEGINTEST +

preceding paragraph

+
spacing in and around one-line displays
+empty display: +
+following text +
+ENDTEST diff --git a/regress/mdoc/D1/spacing.out_lint b/regress/mdoc/D1/spacing.out_lint index 5ac4d0c0..0a2790bb 100644 --- a/regress/mdoc/D1/spacing.out_lint +++ b/regress/mdoc/D1/spacing.out_lint @@ -1 +1 @@ -mandoc: spacing.in:12:2: WARNING: empty block: D1 +mandoc: spacing.in:15:2: WARNING: empty block: D1 diff --git a/regress/mdoc/D1/spacing.out_markdown b/regress/mdoc/D1/spacing.out_markdown index eac16dfe..d1f12f63 100644 --- a/regress/mdoc/D1/spacing.out_markdown +++ b/regress/mdoc/D1/spacing.out_markdown @@ -6,12 +6,17 @@ D1-SPACING(1) - General Commands Manual # DESCRIPTION -preceding text +BEGINTEST + +preceding +paragraph > spacing in and around one-line displays empty display: -following text +following text +ENDTEST +end of file -OpenBSD - July 4, 2017 +OpenBSD - January 7, 2019 diff --git a/regress/mdoc/Rs/Makefile b/regress/mdoc/Rs/Makefile index 3732dc0a..2881b874 100644 --- a/regress/mdoc/Rs/Makefile +++ b/regress/mdoc/Rs/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.7 2015/02/04 18:03:28 schwarze Exp $ +# $OpenBSD: Makefile,v 1.11 2019/01/07 06:51:37 schwarze Exp $ -REGRESS_TARGETS = allch args break empty three_authors +REGRESS_TARGETS = allch args break empty paragraph three_authors UTF8_TARGETS = allch break empty three_authors LINT_TARGETS = allch args empty +HTML_TARGETS = paragraph # groff-1.22.3 defect: # - arguments after .Rs cause the macro to be ignored diff --git a/regress/mdoc/Rs/paragraph.in b/regress/mdoc/Rs/paragraph.in new file mode 100644 index 00000000..a64e1b82 --- /dev/null +++ b/regress/mdoc/Rs/paragraph.in @@ -0,0 +1,37 @@ +.\" $OpenBSD: paragraph.in,v 1.1 2019/01/07 06:51:37 schwarze Exp $ +.Dd $Mdocdate: January 7 2019 $ +.Dt RS-PARAGRAPH 1 +.Os +.Sh NAME +.Nm Rs-paragraph +.Nd interaction of paragraphs and reference blocks +.Sh DESCRIPTION +BEGINTEST +.br +initial reference: +.Rs +.%A author name +.%B book title +.Re +.Pp +in a paragraph: +.Rs +.%A another author +.%B another book +.Re +.Sh SEE ALSO +initial reference: +.Rs +.%A author name +.%B book title +.Re +.Pp +in a paragraph: +.Rs +.%A another author +.%B another book +.Re +.nf +ENDTEST +.br +end of file diff --git a/regress/mdoc/Rs/paragraph.out_ascii b/regress/mdoc/Rs/paragraph.out_ascii new file mode 100644 index 00000000..821e721d --- /dev/null +++ b/regress/mdoc/Rs/paragraph.out_ascii @@ -0,0 +1,23 @@ +RS-PARAGRAPH(1) General Commands Manual RS-PARAGRAPH(1) + +NNAAMMEE + RRss--ppaarraaggrraapphh - interaction of paragraphs and reference blocks + +DDEESSCCRRIIPPTTIIOONN + BEGINTEST + initial reference: author name, _b_o_o_k _t_i_t_l_e. + + in a paragraph: another author, _a_n_o_t_h_e_r _b_o_o_k. + +SSEEEE AALLSSOO + initial reference: + + author name, _b_o_o_k _t_i_t_l_e. + + in a paragraph: + + another author, _a_n_o_t_h_e_r _b_o_o_k. + ENDTEST + end of file + +OpenBSD January 7, 2019 OpenBSD diff --git a/regress/mdoc/Rs/paragraph.out_html b/regress/mdoc/Rs/paragraph.out_html new file mode 100644 index 00000000..19e9362c --- /dev/null +++ b/regress/mdoc/Rs/paragraph.out_html @@ -0,0 +1,17 @@ +BEGINTEST +
+initial reference: author + name, book title. +

in a paragraph: + another author, + another book.

+

+initial reference: +

author name, + book title.

+

in a paragraph:

+

another + author, another book.

+
+ENDTEST
diff --git a/regress/mdoc/Rs/paragraph.out_markdown b/regress/mdoc/Rs/paragraph.out_markdown
new file mode 100644
index 00000000..c8bb4429
--- /dev/null
+++ b/regress/mdoc/Rs/paragraph.out_markdown
@@ -0,0 +1,32 @@
+RS-PARAGRAPH(1) - General Commands Manual
+
+# NAME
+
+**Rs-paragraph** - interaction of paragraphs and reference blocks
+
+# DESCRIPTION
+
+BEGINTEST  
+initial reference:
+author name,
+*book title*.
+
+in a paragraph:
+another author,
+*another book*.
+
+# SEE ALSO
+
+initial reference:
+
+author name,
+*book title*.
+
+in a paragraph:
+
+another author,
+*another book*.
+ENDTEST  
+end of file
+
+OpenBSD - January 7, 2019
diff --git a/regress/mdoc/Sh/Makefile b/regress/mdoc/Sh/Makefile
index 9610ec4c..1c20f13f 100644
--- a/regress/mdoc/Sh/Makefile
+++ b/regress/mdoc/Sh/Makefile
@@ -1,9 +1,10 @@
-# $OpenBSD: Makefile,v 1.7 2017/01/08 00:10:22 schwarze Exp $
+# $OpenBSD: Makefile,v 1.11 2019/01/07 06:51:37 schwarze Exp $
 
 REGRESS_TARGETS	 = badNAME before empty emptyNAME first nohead order
-REGRESS_TARGETS	+= orderNAME parbefore parborder punctNAME subbefore
+REGRESS_TARGETS	+= orderNAME paragraph parbefore parborder punctNAME subbefore
 LINT_TARGETS	 = badNAME before empty emptyNAME first nohead order
 LINT_TARGETS	+= orderNAME parbefore parborder punctNAME subbefore
+HTML_TARGETS	 = paragraph
 
 # groff-1.22.3 defects:
 # - .Pp before .Sh NAME causes a blank line before the header line
diff --git a/regress/mdoc/Sh/paragraph.in b/regress/mdoc/Sh/paragraph.in
new file mode 100644
index 00000000..8adea45c
--- /dev/null
+++ b/regress/mdoc/Sh/paragraph.in
@@ -0,0 +1,19 @@
+.\" $OpenBSD: paragraph.in,v 1.1 2019/01/07 06:51:37 schwarze Exp $
+.Dd $Mdocdate: January 7 2019 $
+.Dt SH-PARAGRAPH 1
+.Os
+.Sh NAME
+.Nm Sh-paragraph
+.Nd interaction of paragraph and section macros
+.Sh DESCRIPTION
+BEGINTEST
+.Pp
+descriptive text
+.Ss Subsection
+initial subsection text
+.Pp
+subsection paragraph
+.Sh EXAMPLES
+ENDTEST
+.br
+end of file
diff --git a/regress/mdoc/Sh/paragraph.out_ascii b/regress/mdoc/Sh/paragraph.out_ascii
new file mode 100644
index 00000000..0ef1787f
--- /dev/null
+++ b/regress/mdoc/Sh/paragraph.out_ascii
@@ -0,0 +1,20 @@
+SH-PARAGRAPH(1)             General Commands Manual            SH-PARAGRAPH(1)
+
+NNAAMMEE
+     SShh--ppaarraaggrraapphh - interaction of paragraph and section macros
+
+DDEESSCCRRIIPPTTIIOONN
+     BEGINTEST
+
+     descriptive text
+
+   SSuubbsseeccttiioonn
+     initial subsection text
+
+     subsection paragraph
+
+EEXXAAMMPPLLEESS
+     ENDTEST
+     end of file
+
+OpenBSD                         January 7, 2019                        OpenBSD
diff --git a/regress/mdoc/Sh/paragraph.out_html b/regress/mdoc/Sh/paragraph.out_html
new file mode 100644
index 00000000..3eeb9fe8
--- /dev/null
+++ b/regress/mdoc/Sh/paragraph.out_html
@@ -0,0 +1,7 @@
+BEGINTEST
+

descriptive text

+

+initial subsection text +

subsection paragraph

+

+ENDTEST diff --git a/regress/mdoc/Sh/paragraph.out_markdown b/regress/mdoc/Sh/paragraph.out_markdown new file mode 100644 index 00000000..4f0affe4 --- /dev/null +++ b/regress/mdoc/Sh/paragraph.out_markdown @@ -0,0 +1,24 @@ +SH-PARAGRAPH(1) - General Commands Manual + +# NAME + +**Sh-paragraph** - interaction of paragraph and section macros + +# DESCRIPTION + +BEGINTEST + +descriptive text + +## Subsection + +initial subsection text + +subsection paragraph + +# EXAMPLES + +ENDTEST +end of file + +OpenBSD - January 7, 2019 diff --git a/regress/roff/string/dotT.in b/regress/roff/string/dotT.in index 06c544de..62b4a959 100644 --- a/regress/roff/string/dotT.in +++ b/regress/roff/string/dotT.in @@ -1,20 +1,18 @@ -.\" $OpenBSD: dotT.in,v 1.1 2018/08/16 13:49:40 schwarze Exp $ -.Dd $Mdocdate: August 16 2018 $ +.\" $OpenBSD: dotT.in,v 1.2 2019/01/07 06:51:37 schwarze Exp $ +.Dd $Mdocdate: January 7 2019 $ .Dt STRING-DOTT 1 .Os .Sh NAME .Nm string-dotT .Nd interpolating the device name .Sh DESCRIPTION -initial text -.Pp BEGINTEST .Pp We are using the \*(.T device. .Pp .ds .T name The device \*(.T can be overridden. -.Pp +.nf ENDTEST -.Pp -final text +.br +end of file diff --git a/regress/roff/string/dotT.out_ascii b/regress/roff/string/dotT.out_ascii index e1737090..26f53380 100644 --- a/regress/roff/string/dotT.out_ascii +++ b/regress/roff/string/dotT.out_ascii @@ -4,16 +4,12 @@ NNAAMMEE ssttrriinngg--ddoottTT - interpolating the device name DDEESSCCRRIIPPTTIIOONN - initial text - BEGINTEST We are using the ascii device. The device name can be overridden. - ENDTEST + end of file - final text - -OpenBSD August 16, 2018 OpenBSD +OpenBSD January 7, 2019 OpenBSD diff --git a/regress/roff/string/dotT.out_html b/regress/roff/string/dotT.out_html index 67cb1eed..8143fd88 100644 --- a/regress/roff/string/dotT.out_html +++ b/regress/roff/string/dotT.out_html @@ -1,7 +1,5 @@ BEGINTEST -
-We are using the html device. -
-The device name can be overridden. -
+

We are using the html device.

+

The device name can be overridden.

+
 ENDTEST
diff --git a/regress/roff/string/dotT.out_markdown b/regress/roff/string/dotT.out_markdown
index 5a1f8d09..d7400eaa 100644
--- a/regress/roff/string/dotT.out_markdown
+++ b/regress/roff/string/dotT.out_markdown
@@ -6,16 +6,12 @@ STRING-DOTT(1) - General Commands Manual
 
 # DESCRIPTION
 
-initial text
-
 BEGINTEST
 
 We are using the  markdown device.
 
 The device name can be overridden.
+ENDTEST  
+end of file
 
-ENDTEST
-
-final text
-
-OpenBSD - August 16, 2018
+OpenBSD - January 7, 2019
diff --git a/regress/roff/string/dotT.out_utf8 b/regress/roff/string/dotT.out_utf8
index 827b3994..63bbf5fd 100644
--- a/regress/roff/string/dotT.out_utf8
+++ b/regress/roff/string/dotT.out_utf8
@@ -4,16 +4,12 @@ NNAAMMEE
      ssttrriinngg--ddoottTT – interpolating the device name
 
 DDEESSCCRRIIPPTTIIOONN
-     initial text
-
      BEGINTEST
 
      We are using the utf8 device.
 
      The device name can be overridden.
-
      ENDTEST
+     end of file
 
-     final text
-
-OpenBSD                         August 16, 2018                        OpenBSD
+OpenBSD                         January 7, 2019                        OpenBSD
diff --git a/roff_html.c b/roff_html.c
index dabf7ca9..02b8beea 100644
--- a/roff_html.c
+++ b/roff_html.c
@@ -1,4 +1,4 @@
-/*	$Id: roff_html.c,v 1.18 2019/01/06 04:55:09 schwarze Exp $ */
+/*	$Id: roff_html.c,v 1.19 2019/01/07 07:26:29 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons 
  * Copyright (c) 2014, 2017, 2018, 2019 Ingo Schwarze 
@@ -110,8 +110,8 @@ roff_html_pre_sp(ROFF_HTML_ARGS)
 	if (html_fillmode(h, TOKEN_NONE) == ROFF_nf) {
 		h->col++;
 		print_endline(h);
-	} else if (n->parent->tok >= MAN_TH)
+	} else {
+		html_close_paragraph(h);
 		print_otag(h, TAG_P, "c", "Pp");
-	else
-		print_paragraph(h);
+	}
 }
-- 
cgit v1.2.3-56-ge451