diff --git a/go.mod b/go.mod index cb78656bed..dac411590c 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( github.com/urfave/cli v1.20.0 github.com/xanzy/go-gitlab v0.31.0 github.com/yohcop/openid-go v1.0.0 - github.com/yuin/goldmark v1.1.25 + github.com/yuin/goldmark v1.1.32 github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 golang.org/x/net v0.0.0-20200602114024-627f9648deb9 diff --git a/go.sum b/go.sum index ac04f8acfa..4369dfa676 100644 --- a/go.sum +++ b/go.sum @@ -673,6 +673,8 @@ github.com/yohcop/openid-go v1.0.0/go.mod h1:/408xiwkeItSPJZSTPF7+VtZxPkPrRRpRNK github.com/yuin/goldmark v1.1.7/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25 h1:isv+Q6HQAmmL2Ofcmg8QauBmDPlUUnSoNhEcC940Rds= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32 h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 h1:gZucqLjL1eDzVWrXj4uiWeMbAopJlBR2mKQAsTGdPwo= github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60/go.mod h1:i9VhcIHN2PxXMbQrKqXNueok6QNONoPjNMoj9MygVL0= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= diff --git a/vendor/github.com/yuin/goldmark/extension/typographer.go b/vendor/github.com/yuin/goldmark/extension/typographer.go index fc4040209a..8e95231006 100644 --- a/vendor/github.com/yuin/goldmark/extension/typographer.go +++ b/vendor/github.com/yuin/goldmark/extension/typographer.go @@ -10,6 +10,27 @@ import ( "github.com/yuin/goldmark/util" ) +var uncloseCounterKey = parser.NewContextKey() + +type unclosedCounter struct { + Single int + Double int +} + +func (u *unclosedCounter) Reset() { + u.Single = 0 + u.Double = 0 +} + +func getUnclosedCounter(pc parser.Context) *unclosedCounter { + v := pc.Get(uncloseCounterKey) + if v == nil { + v = &unclosedCounter{} + pc.Set(uncloseCounterKey, v) + } + return v.(*unclosedCounter) +} + // TypographicPunctuation is a key of the punctuations that can be replaced with // typographic entities. type TypographicPunctuation int @@ -143,7 +164,6 @@ func (s *typographerParser) Trigger() []byte { } func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node { - before := block.PrecendingCharacter() line, _ := block.PeekLine() c := line[0] if len(line) > 2 { @@ -189,15 +209,20 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } } if c == '\'' || c == '"' { + before := block.PrecendingCharacter() d := parser.ScanDelimiter(line, before, 1, defaultTypographerDelimiterProcessor) if d == nil { return nil } + counter := getUnclosedCounter(pc) if c == '\'' { if s.Substitutions[Apostrophe] != nil { // Handle decade abbrevations such as '90s if d.CanOpen && !d.CanClose && len(line) > 3 && util.IsNumeric(line[1]) && util.IsNumeric(line[2]) && line[3] == 's' { - after := util.ToRune(line, 4) + after := rune(' ') + if len(line) > 4 { + after = util.ToRune(line, 4) + } if len(line) == 3 || unicode.IsSpace(after) || unicode.IsPunct(after) { node := gast.NewString(s.Substitutions[Apostrophe]) node.SetCode(true) @@ -207,7 +232,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } // Convert normal apostrophes. This is probably more flexible than necessary but // converts any apostrophe in between two alphanumerics. - if len(line) > 1 && (unicode.IsDigit(before) || unicode.IsLetter(before)) && (util.IsAlphaNumeric(line[1])) { + if len(line) > 1 && (unicode.IsDigit(before) || unicode.IsLetter(before)) && (unicode.IsLetter(util.ToRune(line, 1))) { node := gast.NewString(s.Substitutions[Apostrophe]) node.SetCode(true) block.Advance(1) @@ -215,16 +240,34 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } } if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose { - node := gast.NewString(s.Substitutions[LeftSingleQuote]) + nt := LeftSingleQuote + // special cases: Alice's, I'm ,Don't, You'd + if len(line) > 1 && (line[1] == 's' || line[1] == 'm' || line[1] == 't' || line[1] == 'd') && (len(line) < 3 || util.IsPunct(line[2]) || util.IsSpace(line[2])) { + nt = RightSingleQuote + } + // special cases: I've, I'll, You're + if len(line) > 2 && ((line[1] == 'v' && line[2] == 'e') || (line[1] == 'l' && line[2] == 'l') || (line[1] == 'r' && line[2] == 'e')) && (len(line) < 4 || util.IsPunct(line[3]) || util.IsSpace(line[3])) { + nt = RightSingleQuote + } + if nt == LeftSingleQuote { + counter.Single++ + } + + node := gast.NewString(s.Substitutions[nt]) node.SetCode(true) block.Advance(1) return node } - if s.Substitutions[RightSingleQuote] != nil && d.CanClose && !d.CanOpen { - node := gast.NewString(s.Substitutions[RightSingleQuote]) - node.SetCode(true) - block.Advance(1) - return node + if s.Substitutions[RightSingleQuote] != nil && counter.Single > 0 { + isClose := d.CanClose && !d.CanOpen + maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (line[1] == ',' || line[1] == '.' || line[1] == '!' || line[1] == '?') && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2]))) + if isClose || maybeClose { + node := gast.NewString(s.Substitutions[RightSingleQuote]) + node.SetCode(true) + block.Advance(1) + counter.Single-- + return node + } } } if c == '"' { @@ -232,13 +275,23 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser node := gast.NewString(s.Substitutions[LeftDoubleQuote]) node.SetCode(true) block.Advance(1) + counter.Double++ return node } - if s.Substitutions[RightDoubleQuote] != nil && d.CanClose && !d.CanOpen { - node := gast.NewString(s.Substitutions[RightDoubleQuote]) - node.SetCode(true) - block.Advance(1) - return node + if s.Substitutions[RightDoubleQuote] != nil && counter.Double > 0 { + isClose := d.CanClose && !d.CanOpen + maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (line[1] == ',' || line[1] == '.' || line[1] == '!' || line[1] == '?') && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2]))) + if isClose || maybeClose { + // special case: "Monitor 21"" + if len(line) > 1 && line[1] == '"' && unicode.IsDigit(before) { + return nil + } + node := gast.NewString(s.Substitutions[RightDoubleQuote]) + node.SetCode(true) + block.Advance(1) + counter.Double-- + return node + } } } } @@ -246,7 +299,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } func (s *typographerParser) CloseBlock(parent gast.Node, pc parser.Context) { - // nothing to do + getUnclosedCounter(pc).Reset() } type typographer struct { diff --git a/vendor/github.com/yuin/goldmark/parser/atx_heading.go b/vendor/github.com/yuin/goldmark/parser/atx_heading.go index 0b63fabc0b..2526088819 100644 --- a/vendor/github.com/yuin/goldmark/parser/atx_heading.go +++ b/vendor/github.com/yuin/goldmark/parser/atx_heading.go @@ -126,7 +126,8 @@ func (b *atxHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context) if closureClose > 0 { reader.Advance(closureClose) attrs, ok := ParseAttributes(reader) - parsed = ok + rest, _ := reader.PeekLine() + parsed = ok && util.IsBlank(rest) if parsed { for _, attr := range attrs { node.SetAttribute(attr.Name, attr.Value) @@ -232,7 +233,7 @@ func parseLastLineAttributes(node ast.Node, reader text.Reader, pc Context) { } lr.Advance(1) } - if ok && util.IsBlank(line[end.Stop:]) { + if ok && util.IsBlank(line[end.Start:]) { for _, attr := range attrs { node.SetAttribute(attr.Name, attr.Value) } diff --git a/vendor/github.com/yuin/goldmark/parser/html_block.go b/vendor/github.com/yuin/goldmark/parser/html_block.go index 95b6918cdc..845c00f982 100644 --- a/vendor/github.com/yuin/goldmark/parser/html_block.go +++ b/vendor/github.com/yuin/goldmark/parser/html_block.go @@ -93,7 +93,7 @@ var htmlBlockType5Close = []byte{']', ']', '>'} var htmlBlockType6Regexp = regexp.MustCompile(`^[ ]{0,3}.*|/>.*|)\n?$`) -var htmlBlockType7Regexp = regexp.MustCompile(`^[ ]{0,3}<(/)?([a-zA-Z0-9]+)(` + attributePattern + `*)(:?>|/>)\s*\n?$`) +var htmlBlockType7Regexp = regexp.MustCompile(`^[ ]{0,3}<(/)?([a-zA-Z0-9\-]+)(` + attributePattern + `*)(:?>|/>)\s*\n?$`) type htmlBlockParser struct { } diff --git a/vendor/github.com/yuin/goldmark/parser/list.go b/vendor/github.com/yuin/goldmark/parser/list.go index df1607ea0f..9183a6da3f 100644 --- a/vendor/github.com/yuin/goldmark/parser/list.go +++ b/vendor/github.com/yuin/goldmark/parser/list.go @@ -191,7 +191,7 @@ func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) Sta isHeading := false last := pc.LastOpenedBlock().Node if ast.IsParagraph(last) { - c, ok := matchesSetextHeadingBar(line) + c, ok := matchesSetextHeadingBar(line[match[3]-1:]) if ok && c == '-' { isHeading = true } diff --git a/vendor/github.com/yuin/goldmark/util/util.go b/vendor/github.com/yuin/goldmark/util/util.go index b6896ad7c3..ef113c4ae1 100644 --- a/vendor/github.com/yuin/goldmark/util/util.go +++ b/vendor/github.com/yuin/goldmark/util/util.go @@ -268,7 +268,7 @@ func FindClosure(bs []byte, opener, closure byte, codeSpan, allowNesting bool) i if codeSpanCloser == codeSpanOpener { codeSpanOpener = 0 } - } else if c == '\\' && i < len(bs)-1 && IsPunct(bs[i+1]) { + } else if codeSpanOpener == 0 && c == '\\' && i < len(bs)-1 && IsPunct(bs[i+1]) { i += 2 continue } else if codeSpan && codeSpanOpener == 0 && c == '`' { diff --git a/vendor/github.com/yuin/goldmark/util/util_safe.go b/vendor/github.com/yuin/goldmark/util/util_safe.go index d640585d8b..507a9d0293 100644 --- a/vendor/github.com/yuin/goldmark/util/util_safe.go +++ b/vendor/github.com/yuin/goldmark/util/util_safe.go @@ -1,4 +1,4 @@ -// +build appengine,js +// +build appengine js package util diff --git a/vendor/github.com/yuin/goldmark/util/util_unsafe.go b/vendor/github.com/yuin/goldmark/util/util_unsafe.go index beeae29361..d098811044 100644 --- a/vendor/github.com/yuin/goldmark/util/util_unsafe.go +++ b/vendor/github.com/yuin/goldmark/util/util_unsafe.go @@ -13,8 +13,11 @@ func BytesToReadOnlyString(b []byte) string { } // StringToReadOnlyBytes returns bytes converted from given string. -func StringToReadOnlyBytes(s string) []byte { +func StringToReadOnlyBytes(s string) (bs []byte) { sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) - bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} - return *(*[]byte)(unsafe.Pointer(&bh)) + bh := (*reflect.SliceHeader)(unsafe.Pointer(&bs)) + bh.Data = sh.Data + bh.Cap = sh.Len + bh.Len = sh.Len + return } diff --git a/vendor/modules.txt b/vendor/modules.txt index 23748f5894..c733a8d909 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -677,7 +677,7 @@ github.com/xi2/xz # github.com/yohcop/openid-go v1.0.0 ## explicit github.com/yohcop/openid-go -# github.com/yuin/goldmark v1.1.25 +# github.com/yuin/goldmark v1.1.32 ## explicit github.com/yuin/goldmark github.com/yuin/goldmark/ast