This commit is contained in:
yuin 2021-10-21 18:24:30 +09:00
parent 15ea97611d
commit 7557842636
3 changed files with 74 additions and 25 deletions

View file

@ -614,3 +614,28 @@ a</p>
b</li> b</li>
</ul> </ul>
//= = = = = = = = = = = = = = = = = = = = = = = =// //= = = = = = = = = = = = = = = = = = = = = = = =//
49: A list item that is indented up to 3 spaces after an empty list item
//- - - - - - - - -//
1.
1. b
-
- b
//- - - - - - - - -//
<ol>
<li></li>
<li>
<p>b</p>
</li>
</ol>
<ul>
<li></li>
<li>
<p>b</p>
</li>
</ul>
//= = = = = = = = = = = = = = = = = = = = = = = =//

View file

@ -16,6 +16,10 @@ const (
orderedList orderedList
) )
var skipListParserKey = NewContextKey()
var emptyListItemWithBlankLines = NewContextKey()
var listItemFlagValue interface{} = true
// Same as // Same as
// `^(([ ]*)([\-\*\+]))(\s+.*)?\n?$`.FindSubmatchIndex or // `^(([ ]*)([\-\*\+]))(\s+.*)?\n?$`.FindSubmatchIndex or
// `^(([ ]*)(\d{1,9}[\.\)]))(\s+.*)?\n?$`.FindSubmatchIndex // `^(([ ]*)(\d{1,9}[\.\)]))(\s+.*)?\n?$`.FindSubmatchIndex
@ -123,8 +127,8 @@ func (b *listParser) Trigger() []byte {
func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) { func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
last := pc.LastOpenedBlock().Node last := pc.LastOpenedBlock().Node
if _, lok := last.(*ast.List); lok || pc.Get(skipListParser) != nil { if _, lok := last.(*ast.List); lok || pc.Get(skipListParserKey) != nil {
pc.Set(skipListParser, nil) pc.Set(skipListParserKey, nil)
return nil, NoChildren return nil, NoChildren
} }
line, _ := reader.PeekLine() line, _ := reader.PeekLine()
@ -154,25 +158,19 @@ func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.
if start > -1 { if start > -1 {
node.Start = start node.Start = start
} }
pc.Set(emptyListItemWithBlankLines, nil)
return node, HasChildren return node, HasChildren
} }
func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) State { func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
list := node.(*ast.List) list := node.(*ast.List)
line, _ := reader.PeekLine() line, _ := reader.PeekLine()
startsWithBlankLines := util.IsBlank(line) if util.IsBlank(line) {
if startsWithBlankLines { if node.LastChild().ChildCount() == 0 {
if node.LastChild().ChildCount() != 0 { pc.Set(emptyListItemWithBlankLines, listItemFlagValue)
}
return Continue | HasChildren return Continue | HasChildren
} }
for {
reader.AdvanceLine()
line, _ = reader.PeekLine()
if !util.IsBlank(line) {
break
}
}
}
// "offset" means a width that bar indicates. // "offset" means a width that bar indicates.
// - aaaaaaaa // - aaaaaaaa
@ -182,10 +180,23 @@ func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) Sta
// - a // - a
// - b <--- current line // - b <--- current line
// it maybe a new child of the list. // it maybe a new child of the list.
//
// Empty list items can have multiple blanklines
//
// - <--- 1st item is an empty thus "offset" is unknown
//
//
// - <--- current line
//
// -> 1 list with 2 blank items
//
// So if the last item is an empty, it maybe a new child of the list.
//
offset := lastOffset(node) offset := lastOffset(node)
lastIsEmpty := node.LastChild().ChildCount() == 0
indent, _ := util.IndentWidth(line, reader.LineOffset()) indent, _ := util.IndentWidth(line, reader.LineOffset())
if indent < offset { if indent < offset || lastIsEmpty {
if indent < 4 { if indent < 4 {
match, typ := matchesListItem(line, false) // may have a leading spaces more than 3 match, typ := matchesListItem(line, false) // may have a leading spaces more than 3
if typ != notList && match[1]-offset < 4 { if typ != notList && match[1]-offset < 4 {
@ -207,13 +218,23 @@ func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) Sta
return Close return Close
} }
} }
return Continue | HasChildren return Continue | HasChildren
} }
} }
if !lastIsEmpty {
return Close return Close
} }
if startsWithBlankLines { }
// Non empty items can not exist next to an empty list item
// with blank lines. So we need to close the current list
//
// -
//
// foo
//
// -> 1 list with 1 blank items and 1 paragraph
if pc.Get(emptyListItemWithBlankLines) != nil {
return Close return Close
} }
return Continue | HasChildren return Continue | HasChildren

View file

@ -17,9 +17,6 @@ func NewListItemParser() BlockParser {
return defaultListItemParser return defaultListItemParser
} }
var skipListParser = NewContextKey()
var skipListParserValue interface{} = true
func (b *listItemParser) Trigger() []byte { func (b *listItemParser) Trigger() []byte {
return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
} }
@ -38,6 +35,9 @@ func (b *listItemParser) Open(parent ast.Node, reader text.Reader, pc Context) (
if match[1]-offset > 3 { if match[1]-offset > 3 {
return nil, NoChildren return nil, NoChildren
} }
pc.Set(emptyListItemWithBlankLines, nil)
itemOffset := calcListOffset(line, match) itemOffset := calcListOffset(line, match)
node := ast.NewListItem(match[3] + itemOffset) node := ast.NewListItem(match[3] + itemOffset)
if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) { if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
@ -54,20 +54,23 @@ func (b *listItemParser) Continue(node ast.Node, reader text.Reader, pc Context)
line, _ := reader.PeekLine() line, _ := reader.PeekLine()
if util.IsBlank(line) { if util.IsBlank(line) {
reader.Advance(len(line) - 1) reader.Advance(len(line) - 1)
return Continue | HasChildren return Continue | HasChildren
} }
indent, _ := util.IndentWidth(line, reader.LineOffset())
offset := lastOffset(node.Parent()) offset := lastOffset(node.Parent())
if indent < offset && indent < 4 { isEmpty := node.ChildCount() == 0
indent, _ := util.IndentWidth(line, reader.LineOffset())
if (isEmpty || indent < offset) && indent < 4 {
_, typ := matchesListItem(line, true) _, typ := matchesListItem(line, true)
// new list item found // new list item found
if typ != notList { if typ != notList {
pc.Set(skipListParser, skipListParserValue) pc.Set(skipListParserKey, listItemFlagValue)
}
return Close return Close
} }
if !isEmpty {
return Close
}
}
pos, padding := util.IndentPosition(line, reader.LineOffset(), offset) pos, padding := util.IndentPosition(line, reader.LineOffset(), offset)
reader.AdvanceAndSetPadding(pos, padding) reader.AdvanceAndSetPadding(pos, padding)