Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions inline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ func TestEmphasis(t *testing.T) {
doTestsInlineParam(t, tests, TestParams{})
}

func TestBug279(t *testing.T) {
var tests = []string{
"**bold *ital***\n",
"<p><strong>bold <em>ital</em></strong></p>\n",
"**bold *ital* more**\n",
"<p><strong>bold <em>ital</em> more</strong></p>\n",
"*ital **bold***\n",
"<p><em>ital <strong>bold</strong></em></p>\n",
"**no inner star**\n",
"<p><strong>no inner star</strong></p>\n",
}
doTestsInlineParam(t, tests, TestParams{})
}

func TestBug309(t *testing.T) {
var tests = []string{
`*f*—`,
Expand Down
39 changes: 37 additions & 2 deletions parser/inline.go
Original file line number Diff line number Diff line change
Expand Up @@ -1247,18 +1247,53 @@ func helperDoubleEmphasis(p *Parser, data []byte, c byte) (int, ast.Node) {
i += length

if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !IsSpace(data[i-1]) {
// When the closing delimiter is *** (3+ chars) and there is an
// unclosed single emphasis opener inside the content, include
// one extra char in the content so that the inner emphasis can
// pair with it. For example: **bold *ital*** should produce
// <strong>bold <em>ital</em></strong>, not <strong>bold *ital</strong>*.
// See https://github.com/gomarkdown/markdown/issues/279
contentEnd := i
if i+2 < len(data) && data[i+2] == c && c != '~' {
if hasTrailingEmphOpener(data[:i], c) {
contentEnd = i + 1
}
}

var node ast.Node = &ast.Strong{}
if c == '~' {
node = &ast.Del{}
}
p.Inline(node, data[:i])
return i + 2, node
p.Inline(node, data[:contentEnd])
return contentEnd + 2, node
}
i++
}
return 0, nil
}

// hasTrailingEmphOpener checks if the last occurrence of c in data is an
// unclosed opener. An opener is c preceded by whitespace or start of data,
// followed by non-whitespace. If the last c is a closer (preceded by
// non-whitespace), the emphasis pair is balanced and we should not shift
// the content boundary.
func hasTrailingEmphOpener(data []byte, c byte) bool {
// find the last c in data
last := -1
for j := len(data) - 1; j >= 0; j-- {
if data[j] == c {
last = j
break
}
}
if last < 0 {
return false
}
// opener: preceded by space/start, followed by non-space
return (last == 0 || IsSpace(data[last-1])) &&
last+1 < len(data) && !IsSpace(data[last+1])
}

func helperTripleEmphasis(p *Parser, data []byte, offset int, c byte) (int, ast.Node) {
i := 0
origData := data
Expand Down