mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-08-23 22:46:35 +00:00
Merge pull request #1831 from a7i/amir/CVE-2024-44337
chore: upgrade github.com/gomarkdown/markdown to latest version
This commit is contained in:
@@ -67,7 +67,7 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang/glog v1.2.5 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.0 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
|
||||
@@ -130,8 +130,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab h1:VYNivV7P8IRHUam2swVUNkhIdp0LRRFKe4hXNnoZKTc=
|
||||
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
|
||||
|
||||
+28
-19
@@ -641,14 +641,29 @@ func (r *Renderer) EnsureUniqueHeadingID(id string) string {
|
||||
return id
|
||||
}
|
||||
|
||||
func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) {
|
||||
func (r *Renderer) MakeUniqueHeadingID(hdr *ast.Heading) string {
|
||||
if hdr.HeadingID == "" {
|
||||
return ""
|
||||
}
|
||||
id := r.EnsureUniqueHeadingID(hdr.HeadingID)
|
||||
if r.Opts.HeadingIDPrefix != "" {
|
||||
id = r.Opts.HeadingIDPrefix + id
|
||||
}
|
||||
if r.Opts.HeadingIDSuffix != "" {
|
||||
id = id + r.Opts.HeadingIDSuffix
|
||||
}
|
||||
hdr.HeadingID = id
|
||||
return id
|
||||
}
|
||||
|
||||
func (r *Renderer) HeadingEnter(w io.Writer, hdr *ast.Heading) {
|
||||
var attrs []string
|
||||
var class string
|
||||
// TODO(miek): add helper functions for coalescing these classes.
|
||||
if nodeData.IsTitleblock {
|
||||
if hdr.IsTitleblock {
|
||||
class = "title"
|
||||
}
|
||||
if nodeData.IsSpecial {
|
||||
if hdr.IsSpecial {
|
||||
if class != "" {
|
||||
class += " special"
|
||||
} else {
|
||||
@@ -659,35 +674,29 @@ func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) {
|
||||
attrs = []string{`class="` + class + `"`}
|
||||
}
|
||||
|
||||
if nodeData.HeadingID != "" {
|
||||
id := r.EnsureUniqueHeadingID(nodeData.HeadingID)
|
||||
if r.Opts.HeadingIDPrefix != "" {
|
||||
id = r.Opts.HeadingIDPrefix + id
|
||||
}
|
||||
if r.Opts.HeadingIDSuffix != "" {
|
||||
id = id + r.Opts.HeadingIDSuffix
|
||||
}
|
||||
if hdr.HeadingID != "" {
|
||||
id := r.MakeUniqueHeadingID(hdr)
|
||||
attrID := `id="` + id + `"`
|
||||
attrs = append(attrs, attrID)
|
||||
}
|
||||
attrs = append(attrs, BlockAttrs(nodeData)...)
|
||||
attrs = append(attrs, BlockAttrs(hdr)...)
|
||||
r.CR(w)
|
||||
r.OutTag(w, HeadingOpenTagFromLevel(nodeData.Level), attrs)
|
||||
r.OutTag(w, HeadingOpenTagFromLevel(hdr.Level), attrs)
|
||||
}
|
||||
|
||||
func (r *Renderer) headingExit(w io.Writer, heading *ast.Heading) {
|
||||
r.Outs(w, HeadingCloseTagFromLevel(heading.Level))
|
||||
if !(IsListItem(heading.Parent) && ast.GetNextNode(heading) == nil) {
|
||||
func (r *Renderer) HeadingExit(w io.Writer, hdr *ast.Heading) {
|
||||
r.Outs(w, HeadingCloseTagFromLevel(hdr.Level))
|
||||
if !(IsListItem(hdr.Parent) && ast.GetNextNode(hdr) == nil) {
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
|
||||
// Heading writes ast.Heading node
|
||||
func (r *Renderer) Heading(w io.Writer, node *ast.Heading, entering bool) {
|
||||
func (r *Renderer) Heading(w io.Writer, hdr *ast.Heading, entering bool) {
|
||||
if entering {
|
||||
r.headingEnter(w, node)
|
||||
r.HeadingEnter(w, hdr)
|
||||
} else {
|
||||
r.headingExit(w, node)
|
||||
r.HeadingExit(w, hdr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+84
-40
@@ -76,6 +76,7 @@ var (
|
||||
"output": {},
|
||||
"progress": {},
|
||||
"section": {},
|
||||
"svg": {},
|
||||
"video": {},
|
||||
}
|
||||
)
|
||||
@@ -925,7 +926,7 @@ func syntaxRange(data []byte, iout *int) (int, int) {
|
||||
|
||||
i++
|
||||
} else {
|
||||
for i < n && !IsSpace(data[i]) {
|
||||
for i < n && data[i] != '\n' {
|
||||
syn++
|
||||
i++
|
||||
}
|
||||
@@ -950,8 +951,6 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
||||
work.WriteByte('\n')
|
||||
|
||||
for {
|
||||
// safe to assume beg < len(data)
|
||||
|
||||
// check for the end of the code block
|
||||
fenceEnd, _ := isFenceLine(data[beg:], nil, marker)
|
||||
if fenceEnd != 0 {
|
||||
@@ -968,48 +967,47 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
||||
}
|
||||
|
||||
// verbatim copy to the working buffer
|
||||
if doRender {
|
||||
work.Write(data[beg:end])
|
||||
}
|
||||
work.Write(data[beg:end])
|
||||
beg = end
|
||||
}
|
||||
|
||||
if doRender {
|
||||
codeBlock := &ast.CodeBlock{
|
||||
IsFenced: true,
|
||||
}
|
||||
codeBlock.Content = work.Bytes() // TODO: get rid of temp buffer
|
||||
if !doRender {
|
||||
return beg
|
||||
}
|
||||
codeBlock := &ast.CodeBlock{
|
||||
IsFenced: true,
|
||||
}
|
||||
codeBlock.Content = work.Bytes() // TODO: get rid of temp buffer
|
||||
|
||||
if p.extensions&Mmark == 0 {
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
return beg
|
||||
}
|
||||
|
||||
// Check for caption and if found make it a figure.
|
||||
if captionContent, id, consumed := p.caption(data[beg:], []byte(captionFigure)); consumed > 0 {
|
||||
figure := &ast.CaptionFigure{}
|
||||
caption := &ast.Caption{}
|
||||
figure.HeadingID = id
|
||||
p.Inline(caption, captionContent)
|
||||
|
||||
p.AddBlock(figure)
|
||||
codeBlock.AsLeaf().Attribute = figure.AsContainer().Attribute
|
||||
p.addChild(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
p.addChild(caption)
|
||||
p.Finalize(figure)
|
||||
|
||||
beg += consumed
|
||||
|
||||
return beg
|
||||
}
|
||||
|
||||
// Still here, normal block
|
||||
if p.extensions&Mmark == 0 {
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
return beg
|
||||
}
|
||||
|
||||
// Check for caption and if found make it a figure.
|
||||
if captionContent, id, consumed := p.caption(data[beg:], []byte(captionFigure)); consumed > 0 {
|
||||
figure := &ast.CaptionFigure{}
|
||||
caption := &ast.Caption{}
|
||||
figure.HeadingID = id
|
||||
p.Inline(caption, captionContent)
|
||||
|
||||
p.AddBlock(figure)
|
||||
codeBlock.AsLeaf().Attribute = figure.AsContainer().Attribute
|
||||
p.addChild(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
p.addChild(caption)
|
||||
p.Finalize(figure)
|
||||
|
||||
beg += consumed
|
||||
|
||||
return beg
|
||||
}
|
||||
|
||||
// Still here, normal block
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
|
||||
return beg
|
||||
}
|
||||
|
||||
@@ -1352,6 +1350,7 @@ func finalizeList(list *ast.List) {
|
||||
// Parse a single list item.
|
||||
// Assumes initial prefix is already removed if this is a sublist.
|
||||
func (p *Parser) listItem(data []byte, flags *ast.ListType) int {
|
||||
isDefinitionList := *flags&ast.ListTypeDefinition != 0
|
||||
// keep track of the indentation of the first line
|
||||
itemIndent := 0
|
||||
if data[0] == '\t' {
|
||||
@@ -1384,7 +1383,7 @@ func (p *Parser) listItem(data []byte, flags *ast.ListType) int {
|
||||
}
|
||||
if i == 0 {
|
||||
// if in definition list, set term flag and continue
|
||||
if *flags&ast.ListTypeDefinition != 0 {
|
||||
if isDefinitionList {
|
||||
*flags |= ast.ListTypeTerm
|
||||
} else {
|
||||
return 0
|
||||
@@ -1410,6 +1409,9 @@ func (p *Parser) listItem(data []byte, flags *ast.ListType) int {
|
||||
// process the following lines
|
||||
containsBlankLine := false
|
||||
sublist := 0
|
||||
// track fenced code blocks inside list items so that lines within
|
||||
// the fence are gathered verbatim (not misinterpreted as list items)
|
||||
fenceMarker := ""
|
||||
|
||||
gatherlines:
|
||||
for line < len(data) {
|
||||
@@ -1443,9 +1445,49 @@ gatherlines:
|
||||
|
||||
chunk := data[line+indentIndex : i]
|
||||
|
||||
// track fenced code blocks inside list items;
|
||||
// only track fences that are indented (part of the list item content),
|
||||
// a fence at indent 0 ends the list (handled below)
|
||||
if !isDefinitionList && p.extensions&FencedCode != 0 {
|
||||
if fenceMarker != "" {
|
||||
if indent == 0 {
|
||||
// non-indented line while inside a fence means we
|
||||
// left the list item content -- abandon the fence
|
||||
fenceMarker = ""
|
||||
} else {
|
||||
// inside a fence: check for closing fence
|
||||
_, marker := isFenceLine(chunk, nil, fenceMarker)
|
||||
if marker != "" {
|
||||
fenceMarker = ""
|
||||
}
|
||||
// gather the line verbatim, skip structure detection
|
||||
if containsBlankLine {
|
||||
containsBlankLine = false
|
||||
raw.WriteByte('\n')
|
||||
}
|
||||
raw.Write(chunk)
|
||||
line = i
|
||||
continue
|
||||
}
|
||||
} else if indent > 0 {
|
||||
// not inside a fence: check for opening fence (indented only)
|
||||
_, marker := isFenceLine(chunk, nil, "")
|
||||
if marker != "" {
|
||||
fenceMarker = marker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a fence line (marking starting of a code block)
|
||||
// without indent do not process it as part of the list.
|
||||
if p.extensions&FencedCode != 0 {
|
||||
//
|
||||
// does not apply for definition lists because it causes infinite
|
||||
// loop if text before defintion term is fenced code block start
|
||||
// marker but not part of actual fenced code block
|
||||
// for defnition lists we're called after parsing fence code blocks
|
||||
// so we kno this cannot be a fenced block
|
||||
// https://github.com/gomarkdown/markdown/issues/326
|
||||
if !isDefinitionList && p.extensions&FencedCode != 0 {
|
||||
fenceLineEnd, _ := isFenceLine(chunk, nil, "")
|
||||
if fenceLineEnd > 0 && indent == 0 {
|
||||
*flags |= ast.ListItemEndOfList
|
||||
@@ -1652,7 +1694,9 @@ func (p *Parser) paragraph(data []byte) int {
|
||||
if p.extensions&DefinitionLists != 0 {
|
||||
if i < len(data)-1 && data[i+1] == ':' {
|
||||
listLen := p.list(data[prev:], ast.ListTypeDefinition, 0, '.')
|
||||
return prev + listLen
|
||||
if listLen > 0 {
|
||||
return prev + listLen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -49,6 +49,9 @@ func citation(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
for _, citation := range citations {
|
||||
var suffix []byte
|
||||
citation = bytes.TrimSpace(citation)
|
||||
if len(citation) == 0 {
|
||||
continue
|
||||
}
|
||||
j := 0
|
||||
if citation[j] != '@' {
|
||||
// not a citation, drop out entirely.
|
||||
|
||||
+76
-27
@@ -271,7 +271,7 @@ func maybeInlineFootnoteOrSuper(p *Parser, data []byte, offset int) (int, ast.No
|
||||
// '[': parse a link or an image or a footnote or a citation
|
||||
func link(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
// no links allowed inside regular links, footnote, and deferred footnotes
|
||||
if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') {
|
||||
if p.InsideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -362,25 +362,27 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
linkB := i
|
||||
brace := 0
|
||||
|
||||
var c byte
|
||||
// look for link end: ' " )
|
||||
findlinkend:
|
||||
for i < len(data) {
|
||||
c = data[i]
|
||||
switch {
|
||||
case data[i] == '\\':
|
||||
case c == '\\':
|
||||
i += 2
|
||||
|
||||
case data[i] == '(':
|
||||
case c == '(':
|
||||
brace++
|
||||
i++
|
||||
|
||||
case data[i] == ')':
|
||||
case c == ')':
|
||||
if brace <= 0 {
|
||||
break findlinkend
|
||||
}
|
||||
brace--
|
||||
i++
|
||||
|
||||
case data[i] == '\'' || data[i] == '"':
|
||||
case c == '\'' || c == '"':
|
||||
break findlinkend
|
||||
|
||||
default:
|
||||
@@ -402,14 +404,15 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
|
||||
findtitleend:
|
||||
for i < len(data) {
|
||||
c = data[i]
|
||||
switch {
|
||||
case data[i] == '\\':
|
||||
case c == '\\':
|
||||
i++
|
||||
|
||||
case data[i] == data[titleB-1]: // matching title delimiter
|
||||
case c == data[titleB-1]: // matching title delimiter
|
||||
titleEndCharFound = true
|
||||
|
||||
case titleEndCharFound && data[i] == ')':
|
||||
case titleEndCharFound && c == ')':
|
||||
break findtitleend
|
||||
}
|
||||
i++
|
||||
@@ -619,10 +622,10 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
} else {
|
||||
// links cannot contain other links, so turn off link parsing
|
||||
// temporarily and recurse
|
||||
insideLink := p.insideLink
|
||||
p.insideLink = true
|
||||
InsideLink := p.InsideLink
|
||||
p.InsideLink = true
|
||||
p.Inline(link, data[1:txtE])
|
||||
p.insideLink = insideLink
|
||||
p.InsideLink = InsideLink
|
||||
}
|
||||
return i, link
|
||||
|
||||
@@ -736,7 +739,7 @@ func leftAngle(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
}
|
||||
|
||||
// '\\' backslash escape
|
||||
var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~^$")
|
||||
var EscapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~^$")
|
||||
|
||||
func escape(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
data = data[offset:]
|
||||
@@ -753,7 +756,7 @@ func escape(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
return 2, &ast.Hardbreak{}
|
||||
}
|
||||
|
||||
if bytes.IndexByte(escapeChars, data[1]) < 0 {
|
||||
if bytes.IndexByte(EscapeChars, data[1]) < 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -814,7 +817,12 @@ func entity(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
codepoint, err = strconv.ParseUint(string(ent[2:len(ent)-1]), 10, 64)
|
||||
}
|
||||
if err == nil { // only if conversion was valid return here.
|
||||
return end, newTextNode([]byte(string(rune(codepoint))))
|
||||
r := rune(codepoint)
|
||||
// Replace invalid codepoints with U+FFFD per CommonMark spec section 6.2
|
||||
if r == 0 || (r >= 0xD800 && r <= 0xDFFF) || r > 0x10FFFF {
|
||||
r = '\uFFFD'
|
||||
}
|
||||
return end, newTextNode([]byte(string(r)))
|
||||
}
|
||||
|
||||
return end, newTextNode(ent)
|
||||
@@ -857,7 +865,7 @@ const shortestPrefix = 6 // len("ftp://"), the shortest of the above
|
||||
|
||||
func maybeAutoLink(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
// quick check to rule out most false hits
|
||||
if p.insideLink || len(data) < offset+shortestPrefix {
|
||||
if p.InsideLink || len(data) < offset+shortestPrefix {
|
||||
return 0, nil
|
||||
}
|
||||
for _, prefix := range protocolPrefixes {
|
||||
@@ -1070,10 +1078,11 @@ func tagLength(data []byte) (autolink autolinkType, end int) {
|
||||
// one of the forbidden chars has been found
|
||||
autolink = notAutolink
|
||||
}
|
||||
i += bytes.IndexByte(data[i:], '>')
|
||||
if i < 0 {
|
||||
j = bytes.IndexByte(data[i:], '>')
|
||||
if j < 0 {
|
||||
return autolink, 0
|
||||
}
|
||||
i += j
|
||||
return autolink, i + 1
|
||||
}
|
||||
|
||||
@@ -1185,30 +1194,30 @@ func helperFindEmphChar(data []byte, c byte) int {
|
||||
func helperEmphasis(p *Parser, data []byte, c byte) (int, ast.Node) {
|
||||
i := 0
|
||||
|
||||
// skip one symbol if coming from emph3
|
||||
// skip two symbol if coming from emph3, as it detected a double emphasis case
|
||||
if len(data) > 1 && data[0] == c && data[1] == c {
|
||||
i = 1
|
||||
i = 2
|
||||
}
|
||||
|
||||
for i < len(data) {
|
||||
length := helperFindEmphChar(data[i:], c)
|
||||
if length == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
i += length
|
||||
if i >= len(data) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if i+1 < len(data) && data[i+1] == c {
|
||||
i++
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
|
||||
if data[i] == c && !IsSpace(data[i-1]) {
|
||||
|
||||
if p.extensions&NoIntraEmphasis != 0 {
|
||||
if !(i+1 == len(data) || IsSpace(data[i+1]) || IsPunctuation(data[i+1])) {
|
||||
rest := data[i+1:]
|
||||
if !(len(rest) == 0 || IsSpace(rest[0]) || IsPunctuation2(rest)) {
|
||||
if length == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -1217,6 +1226,11 @@ func helperEmphasis(p *Parser, data []byte, c byte) (int, ast.Node) {
|
||||
p.Inline(emph, data[:i])
|
||||
return i + 1, emph
|
||||
}
|
||||
|
||||
// We have to check this at the end, otherwise the scenario where we find repeated c's will get skipped
|
||||
if length == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
@@ -1233,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
|
||||
|
||||
+32
-7
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gomarkdown/markdown/ast"
|
||||
)
|
||||
@@ -56,7 +58,7 @@ const (
|
||||
)
|
||||
|
||||
// for each character that triggers a response when parsing inline data.
|
||||
type inlineParser func(p *Parser, data []byte, offset int) (int, ast.Node)
|
||||
type InlineParser func(p *Parser, data []byte, offset int) (int, ast.Node)
|
||||
|
||||
// ReferenceOverrideFunc is expected to be called with a reference string and
|
||||
// return either a valid Reference type that the reference string maps to or
|
||||
@@ -98,10 +100,10 @@ type Parser struct {
|
||||
|
||||
refs map[string]*reference
|
||||
refsRecord map[string]struct{}
|
||||
inlineCallback [256]inlineParser
|
||||
inlineCallback [256]InlineParser
|
||||
nesting int
|
||||
maxNesting int
|
||||
insideLink bool
|
||||
InsideLink bool
|
||||
indexCnt int // incremented after every index
|
||||
|
||||
// Footnotes need to be ordered as well as available to quickly check for
|
||||
@@ -122,6 +124,8 @@ type Parser struct {
|
||||
// collect headings where we auto-generated id so that we can
|
||||
// ensure they are unique at the end
|
||||
allHeadingsWithAutoID []*ast.Heading
|
||||
|
||||
didParse bool
|
||||
}
|
||||
|
||||
// New creates a markdown parser with CommonExtensions.
|
||||
@@ -138,8 +142,8 @@ func NewWithExtensions(extension Extensions) *Parser {
|
||||
p := Parser{
|
||||
refs: make(map[string]*reference),
|
||||
refsRecord: make(map[string]struct{}),
|
||||
maxNesting: 16,
|
||||
insideLink: false,
|
||||
maxNesting: 64,
|
||||
InsideLink: false,
|
||||
Doc: &ast.Document{},
|
||||
extensions: extension,
|
||||
allClosed: true,
|
||||
@@ -181,7 +185,7 @@ func NewWithExtensions(extension Extensions) *Parser {
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *Parser) RegisterInline(n byte, fn inlineParser) inlineParser {
|
||||
func (p *Parser) RegisterInline(n byte, fn InlineParser) InlineParser {
|
||||
prev := p.inlineCallback[n]
|
||||
p.inlineCallback[n] = fn
|
||||
return prev
|
||||
@@ -290,7 +294,14 @@ type Reference struct {
|
||||
//
|
||||
// You can then convert AST to html using html.Renderer, to some other format
|
||||
// using a custom renderer or transform the tree.
|
||||
//
|
||||
// Parser is not reusable. Create a new Parser for each Parse() call.
|
||||
func (p *Parser) Parse(input []byte) ast.Node {
|
||||
if p.didParse {
|
||||
panic("Parser is not reusable. Must create new Parser for each Parse() call.")
|
||||
}
|
||||
p.didParse = true
|
||||
|
||||
// the code only works with Unix CR newlines so to make life easy for
|
||||
// callers normalize newlines
|
||||
input = NormalizeNewlines(input)
|
||||
@@ -727,7 +738,21 @@ func IsPunctuation(c byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsSpace returns true if c is a white-space charactr
|
||||
func IsPunctuation2(d []byte) bool {
|
||||
if len(d) == 0 {
|
||||
return false
|
||||
}
|
||||
if IsPunctuation(d[0]) {
|
||||
return true
|
||||
}
|
||||
r, _ := utf8.DecodeRune(d)
|
||||
if r == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
return unicode.IsPunct(r)
|
||||
}
|
||||
|
||||
// IsSpace returns true if c is a white-space character
|
||||
func IsSpace(c byte) bool {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -103,7 +103,7 @@ github.com/golang/glog/internal/stackdump
|
||||
# github.com/golang/protobuf v1.5.4
|
||||
## explicit; go 1.17
|
||||
github.com/golang/protobuf/proto
|
||||
# github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0
|
||||
# github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab
|
||||
## explicit; go 1.12
|
||||
github.com/gomarkdown/markdown/ast
|
||||
github.com/gomarkdown/markdown/html
|
||||
|
||||
Reference in New Issue
Block a user