diff options
Diffstat (limited to 'vendor/github.com/gomarkdown/markdown/parser')
5 files changed, 119 insertions, 59 deletions
diff --git a/vendor/github.com/gomarkdown/markdown/parser/block.go b/vendor/github.com/gomarkdown/markdown/parser/block.go index 7c2401f1..eda9be7a 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/block.go +++ b/vendor/github.com/gomarkdown/markdown/parser/block.go @@ -909,18 +909,18 @@ func syntaxRange(data []byte, iout *int) (int, int) { // strip all whitespace at the beginning and the end // of the {} block - for syn > 0 && isSpace(data[syntaxStart]) { + for syn > 0 && IsSpace(data[syntaxStart]) { syntaxStart++ syn-- } - for syn > 0 && isSpace(data[syntaxStart+syn-1]) { + for syn > 0 && IsSpace(data[syntaxStart+syn-1]) { syn-- } i++ } else { - for i < n && !isSpace(data[i]) { + for i < n && !IsSpace(data[i]) { syn++ i++ } @@ -1767,7 +1767,7 @@ func skipUntilChar(data []byte, i int, c byte) int { func skipAlnum(data []byte, i int) int { n := len(data) - for i < n && isAlnum(data[i]) { + for i < n && IsAlnum(data[i]) { i++ } return i @@ -1775,7 +1775,7 @@ func skipAlnum(data []byte, i int) int { func skipSpace(data []byte, i int) int { n := len(data) - for i < n && isSpace(data[i]) { + for i < n && IsSpace(data[i]) { i++ } return i diff --git a/vendor/github.com/gomarkdown/markdown/parser/caption.go b/vendor/github.com/gomarkdown/markdown/parser/caption.go index 54d3f741..fe31711a 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/caption.go +++ b/vendor/github.com/gomarkdown/markdown/parser/caption.go @@ -58,7 +58,7 @@ func captionID(data []byte) (string, int) { } // remains must be whitespace. for l := k + 1; l < end; l++ { - if !isSpace(data[l]) { + if !IsSpace(data[l]) { return "", 0 } } diff --git a/vendor/github.com/gomarkdown/markdown/parser/inline.go b/vendor/github.com/gomarkdown/markdown/parser/inline.go index c16eddd8..70d38f29 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/inline.go +++ b/vendor/github.com/gomarkdown/markdown/parser/inline.go @@ -6,7 +6,6 @@ import ( "strconv" "github.com/gomarkdown/markdown/ast" - "github.com/gomarkdown/markdown/internal/valid" ) // Parsing of inline elements @@ -69,7 +68,7 @@ func emphasis(p *Parser, data []byte, offset int) (int, ast.Node) { if n > 2 && data[1] != c { // whitespace cannot follow an opening emphasis; // strikethrough only takes two characters '~~' - if isSpace(data[1]) { + if IsSpace(data[1]) { return 0, nil } if p.extensions&SuperSubscript != 0 && c == '~' { @@ -81,7 +80,7 @@ func emphasis(p *Parser, data []byte, offset int) (int, ast.Node) { } ret++ // we started with data[1:] above. for i := 1; i < ret; i++ { - if isSpace(data[i]) && !isEscape(data, i) { + if IsSpace(data[i]) && !isEscape(data, i) { return 0, nil } } @@ -98,7 +97,7 @@ func emphasis(p *Parser, data []byte, offset int) (int, ast.Node) { } if n > 3 && data[1] == c && data[2] != c { - if isSpace(data[2]) { + if IsSpace(data[2]) { return 0, nil } ret, node := helperDoubleEmphasis(p, data[2:], c) @@ -110,7 +109,7 @@ func emphasis(p *Parser, data []byte, offset int) (int, ast.Node) { } if n > 4 && data[1] == c && data[2] == c && data[3] != c { - if c == '~' || isSpace(data[3]) { + if c == '~' || IsSpace(data[3]) { return 0, nil } ret, node := helperTripleEmphasis(p, data, 3, c) @@ -156,7 +155,7 @@ func codeSpan(p *Parser, data []byte, offset int) (int, ast.Node) { if data[j] == '\n' { break } - if !isSpace(data[j]) { + if !IsSpace(data[j]) { hasCharsAfterDelimiter = true } } @@ -256,7 +255,7 @@ func maybeInlineFootnoteOrSuper(p *Parser, data []byte, offset int) (int, ast.No return 0, nil } for i := offset; i < offset+ret; i++ { - if isSpace(data[i]) && !isEscape(data, i) { + if IsSpace(data[i]) && !isEscape(data, i) { return 0, nil } } @@ -421,7 +420,7 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) { // skip whitespace after title titleE = i - 1 - for titleE > titleB && isSpace(data[titleE]) { + for titleE > titleB && IsSpace(data[titleE]) { titleE-- } @@ -433,7 +432,7 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) { } // remove whitespace at the end of the link - for linkE > linkB && isSpace(data[linkE-1]) { + for linkE > linkB && IsSpace(data[linkE-1]) { linkE-- } @@ -602,9 +601,8 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) { } // links need something to click on and somewhere to go - if len(uLink) == 0 || (t == linkNormal && txtE <= 1) { - return 0, nil - } + // [](http://bla) is legal in CommonMark, so allow txtE <=1 for linkNormal + // [bla]() is also legal in CommonMark, so allow empty uLink } // call the relevant rendering function @@ -827,7 +825,9 @@ func linkEndsWithEntity(data []byte, linkEnd int) bool { } // hasPrefixCaseInsensitive is a custom implementation of -// strings.HasPrefix(strings.ToLower(s), prefix) +// +// strings.HasPrefix(strings.ToLower(s), prefix) +// // we rolled our own because ToLower pulls in a huge machinery of lowercasing // anything from Unicode and that's very slow. Since this func will only be // used on ASCII protocol prefixes, we can take shortcuts. @@ -889,7 +889,7 @@ func autoLink(p *Parser, data []byte, offset int) (int, ast.Node) { // scan backward for a word boundary rewind := 0 - for offset-rewind > 0 && rewind <= 7 && isLetter(data[offset-rewind-1]) { + for offset-rewind > 0 && rewind <= 7 && IsLetter(data[offset-rewind-1]) { rewind++ } if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters @@ -901,7 +901,7 @@ func autoLink(p *Parser, data []byte, offset int) (int, ast.Node) { isSafeURL := p.IsSafeURLOverride if isSafeURL == nil { - isSafeURL = valid.IsSafeURL + isSafeURL = IsSafeURL } if !isSafeURL(data) { return 0, nil @@ -996,7 +996,7 @@ func autoLink(p *Parser, data []byte, offset int) (int, ast.Node) { } func isEndOfLink(char byte) bool { - return isSpace(char) || char == '<' + return IsSpace(char) || char == '<' } // return the length of the given tag, or 0 is it's not valid @@ -1018,7 +1018,7 @@ func tagLength(data []byte) (autolink autolinkType, end int) { i = 1 } - if !isAlnum(data[i]) { + if !IsAlnum(data[i]) { return notAutolink, 0 } @@ -1026,7 +1026,7 @@ func tagLength(data []byte) (autolink autolinkType, end int) { autolink = notAutolink // try to find the beginning of an URI - for i < len(data) && (isAlnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { + for i < len(data) && (IsAlnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { i++ } @@ -1051,7 +1051,7 @@ func tagLength(data []byte) (autolink autolinkType, end int) { for i < len(data) { if data[i] == '\\' { i += 2 - } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isSpace(data[i]) { + } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || IsSpace(data[i]) { break } else { i++ @@ -1083,7 +1083,7 @@ func isMailtoAutoLink(data []byte) int { // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' for i, c := range data { - if isAlnum(c) { + if IsAlnum(c) { continue } @@ -1204,10 +1204,10 @@ func helperEmphasis(p *Parser, data []byte, c byte) (int, ast.Node) { continue } - if data[i] == c && !isSpace(data[i-1]) { + 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])) { + if !(i+1 == len(data) || IsSpace(data[i+1]) || IsPunctuation(data[i+1])) { continue } } @@ -1231,7 +1231,7 @@ 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]) { + if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !IsSpace(data[i-1]) { var node ast.Node = &ast.Strong{} if c == '~' { node = &ast.Del{} @@ -1257,7 +1257,7 @@ func helperTripleEmphasis(p *Parser, data []byte, offset int, c byte) (int, ast. i += length // skip whitespace preceded symbols - if data[i] != c || isSpace(data[i-1]) { + if data[i] != c || IsSpace(data[i-1]) { continue } diff --git a/vendor/github.com/gomarkdown/markdown/parser/parser.go b/vendor/github.com/gomarkdown/markdown/parser/parser.go index 19d1f70b..07444cd8 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/parser.go +++ b/vendor/github.com/gomarkdown/markdown/parser/parser.go @@ -84,7 +84,9 @@ type Parser struct { // the bottom will be used to fill in the link details. ReferenceOverride ReferenceOverrideFunc - // TODO: documentation + // IsSafeURLOverride allows overriding the default URL matcher. URL is + // safe if the overriding function returns true. Can be used to extend + // the default list of safe URLs. IsSafeURLOverride func(url []byte) bool Opts Options @@ -390,35 +392,35 @@ func (p *Parser) parseRefsToAST() { // // Consider this markdown with reference-style links: // -// [link][ref] +// [link][ref] // -// [ref]: /url/ "tooltip title" +// [ref]: /url/ "tooltip title" // // It will be ultimately converted to this HTML: // -// <p><a href=\"/url/\" title=\"title\">link</a></p> +// <p><a href=\"/url/\" title=\"title\">link</a></p> // // And a reference structure will be populated as follows: // -// p.refs["ref"] = &reference{ -// link: "/url/", -// title: "tooltip title", -// } +// p.refs["ref"] = &reference{ +// link: "/url/", +// title: "tooltip title", +// } // // Alternatively, reference can contain information about a footnote. Consider // this markdown: // -// Text needing a footnote.[^a] +// Text needing a footnote.[^a] // -// [^a]: This is the note +// [^a]: This is the note // // A reference structure will be populated as follows: // -// p.refs["a"] = &reference{ -// link: "a", -// title: "This is the note", -// noteID: <some positive int>, -// } +// p.refs["a"] = &reference{ +// link: "a", +// title: "This is the note", +// noteID: <some positive int>, +// } // // TODO: As you can see, it begs for splitting into two dedicated structures // for refs and for footnotes. @@ -693,8 +695,8 @@ gatherLines: return } -// isPunctuation returns true if c is a punctuation symbol. -func isPunctuation(c byte) bool { +// IsPunctuation returns true if c is a punctuation symbol. +func IsPunctuation(c byte) bool { for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") { if c == r { return true @@ -703,20 +705,63 @@ func isPunctuation(c byte) bool { return false } -// isSpace returns true if c is a white-space charactr -func isSpace(c byte) bool { +// IsSpace returns true if c is a white-space charactr +func IsSpace(c byte) bool { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' } -// isLetter returns true if c is ascii letter -func isLetter(c byte) bool { +// IsLetter returns true if c is ascii letter +func IsLetter(c byte) bool { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') } -// isAlnum returns true if c is a digit or letter +// IsAlnum returns true if c is a digit or letter // TODO: check when this is looking for ASCII alnum and when it should use unicode -func isAlnum(c byte) bool { - return (c >= '0' && c <= '9') || isLetter(c) +func IsAlnum(c byte) bool { + return (c >= '0' && c <= '9') || IsLetter(c) +} + +var URIs = [][]byte{ + []byte("http://"), + []byte("https://"), + []byte("ftp://"), + []byte("mailto:"), +} + +var Paths = [][]byte{ + []byte("/"), + []byte("./"), + []byte("../"), +} + +// IsSafeURL returns true if url starts with one of the valid schemes or is a relative path. +func IsSafeURL(url []byte) bool { + nLink := len(url) + for _, path := range Paths { + nPath := len(path) + linkPrefix := url[:nPath] + if nLink >= nPath && bytes.Equal(linkPrefix, path) { + if nLink == nPath { + return true + } else if IsAlnum(url[nPath]) { + return true + } + } + } + + for _, prefix := range URIs { + // TODO: handle unicode here + // case-insensitive prefix test + nPrefix := len(prefix) + if nLink > nPrefix { + linkPrefix := bytes.ToLower(url[:nPrefix]) + if bytes.Equal(linkPrefix, prefix) && IsAlnum(url[nPrefix]) { + return true + } + } + } + + return false } // TODO: this is not used @@ -809,7 +854,7 @@ func slugify(in []byte) []byte { sym := false for _, ch := range in { - if isAlnum(ch) { + if IsAlnum(ch) { sym = false out = append(out, ch) } else if sym { diff --git a/vendor/github.com/gomarkdown/markdown/parser/ref.go b/vendor/github.com/gomarkdown/markdown/parser/ref.go index 0b59a196..c1e05341 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/ref.go +++ b/vendor/github.com/gomarkdown/markdown/parser/ref.go @@ -7,8 +7,8 @@ import ( "github.com/gomarkdown/markdown/ast" ) -// parse '(#r)', where r does not contain spaces. Or. -// (!item) (!item, subitem), for an index, (!!item) signals primary. +// parse '(#r, text)', where r does not contain spaces, but text may (similar to a citation). Or. (!item) (!item, +// subitem), for an index, (!!item) signals primary. func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) { if len(data[offset:]) < 4 { return 0, nil @@ -25,8 +25,8 @@ func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) { switch { case c == ')': break Loop - case !isAlnum(c): - if c == '_' || c == '-' || c == ':' { + case !IsAlnum(c): + if c == '_' || c == '-' || c == ':' || c == ' ' || c == ',' { i++ continue } @@ -45,6 +45,21 @@ func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) { id := data[2:i] node := &ast.CrossReference{} node.Destination = id + if c := bytes.Index(id, []byte(",")); c > 0 { + idpart := id[:c] + suff := id[c+1:] + suff = bytes.TrimSpace(suff) + node.Destination = idpart + node.Suffix = suff + } + if bytes.Index(node.Destination, []byte(" ")) > 0 { + // no spaces allowed in id + return 0, nil + } + if bytes.Index(node.Destination, []byte(",")) > 0 { + // nor comma + return 0, nil + } return i + 1, node |