a bc
`, - want: "**a**[b**c**](https://example.com)\n", + want: "**a** [b**c**](https://example.com)\n", }, } for name, tc := range tests { diff --git a/internal/convert/table_property_test.go b/internal/convert/table_property_test.go index 7eb2454..50dbed8 100644 --- a/internal/convert/table_property_test.go +++ b/internal/convert/table_property_test.go @@ -106,7 +106,7 @@ func newPropertyEnv(t testing.TB) *propertyEnv { } func (e *propertyEnv) check(seed uint64) string { - g := &tableGen{r: rand.New(rand.NewPCG(seed, 0x55))} + g := &tableGen{r: rand.New(rand.NewPCG(seed, 0x55)), edge: rand.New(rand.NewPCG(seed, 0x204))} return e.checkStorage(fmt.Sprintf("seed %d", seed), g.table(0)) } @@ -416,10 +416,27 @@ func modelInline(kids []*snode) string { if a, ok := inlineAlias[name]; ok { name = a } - fmt.Fprintf(&b, "<%s>%s%s>", name, modelInline(k.kids), name) + inner := modelInline(k.kids) + // A space at the edge of a mark separates the same words inside it + // as outside, and Markdown can only put it outside (#204). Only the + // marks: a span's spaces are its text.
+ var lead, trail string
+ if name == "strong" || name == "em" || name == "del" {
+ body := strings.TrimLeft(inner, " ")
+ lead = inner[:len(inner)-len(body)]
+ inner = strings.TrimRight(body, " ")
+ trail = body[len(inner):]
+ }
+ fmt.Fprintf(&b, "%s<%s>%s%s>%s", lead, name, inner, name, trail)
}
}
s := whitespaceRunRE.ReplaceAllString(b.String(), " ")
+ // Two runs of one mark with nothing but a space between them read as one
+ // run: "a b" and "a b" look the same.
+ for _, m := range []string{"strong", "em", "del"} {
+ s = strings.ReplaceAll(s, ""+m+"><"+m+">", "")
+ s = strings.ReplaceAll(s, ""+m+"> <"+m+">", " ")
+ }
// Whitespace beside a line break shows nothing, and publishing writes a
// newline after every
.
return strings.ReplaceAll(strings.ReplaceAll(s, " ⏎", "⏎"), "⏎ ", "⏎")
@@ -541,7 +558,10 @@ func modelHasElement(n *snode) bool {
// which #203 covers, and inline tags read has no Markdown for (