diff --git a/present/doc.go b/present/doc.go
index 2256f31082..804ec847b3 100644
--- a/present/doc.go
+++ b/present/doc.go
@@ -77,14 +77,22 @@ Fonts:
Within the input for plain text or lists, text bracketed by font
markers will be presented in italic, bold, or program font.
Marker characters are _ (italic), * (bold) and ` (program font).
-Unmatched markers appear as plain text.
-Within marked text, a single marker character becomes a space
-and a doubled single marker quotes the marker character.
+An opening marker must be preceded by a space or punctuation
+character or else be at start of a line; similarly, a closing
+marker must be followed by a space or punctuation character or
+else be at the end of a line. Unmatched markers appear as plain text.
+There must be no spaces between markers. Within marked text,
+a single marker character becomes a space and a doubled single
+marker quotes the marker character.
+
+at the beginning of a line or
+else be preceded by a space or punctuation; similarly a closing
+marker must be at the end of the lineo
_italic_
*bold*
`program`
- _this_is_all_italic_
+ Markup—_especially_italic_text_—can easily be overused.
_Why_use_scoped__ptr_? Use plain ***ptr* instead.
Inline links:
diff --git a/present/style.go b/present/style.go
index 1cd240de72..a6d8d39cc9 100644
--- a/present/style.go
+++ b/present/style.go
@@ -52,16 +52,16 @@ Word:
words[w] = link
continue Word
}
- const punctuation = `.,;:()!?—–'"`
const marker = "_*`"
// Initial punctuation is OK but must be peeled off.
first := strings.IndexAny(word, marker)
if first == -1 {
continue Word
}
- // Is the marker prefixed only by punctuation?
- for _, r := range word[:first] {
- if !strings.ContainsRune(punctuation, r) {
+ // Opening marker must be at the beginning of the token or else preceded by punctuation.
+ if first != 0 {
+ r, _ := utf8.DecodeLastRuneInString(word[:first])
+ if !unicode.IsPunct(r) {
continue Word
}
}
@@ -81,17 +81,18 @@ Word:
open += ""
close = "
"
}
- // Terminal punctuation is OK but must be peeled off.
+ // Closing marker must be at the end of the token or else followed by punctuation.
last := strings.LastIndex(word, word[:1])
if last == 0 {
continue Word
}
- head, tail := word[:last+1], word[last+1:]
- for _, r := range tail {
- if !strings.ContainsRune(punctuation, r) {
+ if last+1 != len(word) {
+ r, _ := utf8.DecodeRuneInString(word[last+1:])
+ if !unicode.IsPunct(r) {
continue Word
}
}
+ head, tail := word[:last+1], word[last+1:]
b.Reset()
b.WriteString(open)
var wid int
diff --git a/present/style_test.go b/present/style_test.go
index d04db72d25..cef5a62f5c 100644
--- a/present/style_test.go
+++ b/present/style_test.go
@@ -72,6 +72,14 @@ func TestFont(t *testing.T) {
`Visit golang.org now`},
{"my talk ([[http://talks.golang.org/][slides here]])",
`my talk (slides here)`},
+ {"Markup—_especially_italic_text_—can easily be overused.",
+ `Markup—especially italic text—can easily be overused.`},
+ {"`go`get`'s codebase", // ascii U+0027 ' before s
+ `go get
's codebase`},
+ {"`go`get`’s codebase", // unicode right single quote U+2019 ’ before s
+ `go get
’s codebase`},
+ {"a_variable_name",
+ `a_variable_name`},
}
for _, test := range tests {
out := font(test.in)