mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-11 21:16:27 +00:00
Update dependencies and remove old matterclient lib (#2067)
This commit is contained in:
9
vendor/github.com/gomarkdown/markdown/.gitpod.yml
generated
vendored
9
vendor/github.com/gomarkdown/markdown/.gitpod.yml
generated
vendored
@ -1,9 +0,0 @@
|
||||
# This configuration file was automatically generated by Gitpod.
|
||||
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
|
||||
# and commit this file to your remote git repository to share the goodness with others.
|
||||
|
||||
tasks:
|
||||
- init: go get && go build ./... && go test ./...
|
||||
command: go run
|
||||
|
||||
|
149
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
149
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
@ -6,7 +6,16 @@ Package `github.com/gomarkdown/markdown` is a Go library for parsing Markdown te
|
||||
|
||||
It's very fast and supports common extensions.
|
||||
|
||||
Try code examples online: https://replit.com/@kjk1?path=folder/gomarkdown
|
||||
Tutorial: https://blog.kowalczyk.info/article/cxn3/advanced-markdown-processing-in-go.html
|
||||
|
||||
Code examples:
|
||||
* https://onlinetool.io/goplayground/#txO7hJ-ibeU : basic markdown => HTML
|
||||
* https://onlinetool.io/goplayground/#yFRIWRiu-KL : customize HTML renderer
|
||||
* https://onlinetool.io/goplayground/#2yV5-HDKBUV : modify AST
|
||||
* https://onlinetool.io/goplayground/#9fqKwRbuJ04 : customize parser
|
||||
* https://onlinetool.io/goplayground/#Bk0zTvrzUDR : syntax highlight
|
||||
|
||||
Those examples are also in [examples](./examples) directory.
|
||||
|
||||
## API Docs:
|
||||
|
||||
@ -15,101 +24,58 @@ Try code examples online: https://replit.com/@kjk1?path=folder/gomarkdown
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown/parser : parser
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown/html : html renderer
|
||||
|
||||
## Users
|
||||
|
||||
Some tools using this package: https://pkg.go.dev/github.com/gomarkdown/markdown?tab=importedby
|
||||
|
||||
## Usage
|
||||
|
||||
To convert markdown text to HTML using reasonable defaults:
|
||||
|
||||
```go
|
||||
md := []byte("## markdown document")
|
||||
output := markdown.ToHTML(md, nil, nil)
|
||||
```
|
||||
package main
|
||||
|
||||
Try it online: https://replit.com/@kjk1/gomarkdown-basic
|
||||
|
||||
## Customizing markdown parser
|
||||
|
||||
Markdown format is loosely specified and there are multiple extensions invented after original specification was created.
|
||||
|
||||
The parser supports several [extensions](https://pkg.go.dev/github.com/gomarkdown/markdown/parser#Extensions).
|
||||
|
||||
Default parser uses most common `parser.CommonExtensions` but you can easily use parser with custom extension:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/parser"
|
||||
"os"
|
||||
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/ast"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
"github.com/gomarkdown/markdown/parser"
|
||||
|
||||
"fmt"
|
||||
)
|
||||
|
||||
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
|
||||
parser := parser.NewWithExtensions(extensions)
|
||||
var mds = `# header
|
||||
|
||||
md := []byte("markdown text")
|
||||
html := markdown.ToHTML(md, parser, nil)
|
||||
```
|
||||
Sample text.
|
||||
|
||||
Try it online: https://replit.com/@kjk1/gomarkdown-customized-html-renderer
|
||||
[link](http://example.com)
|
||||
`
|
||||
|
||||
## Customizing HTML renderer
|
||||
func mdToHTML(md []byte) []byte {
|
||||
// create markdown parser with extensions
|
||||
extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
|
||||
p := parser.NewWithExtensions(extensions)
|
||||
doc := p.Parse(md)
|
||||
|
||||
Similarly, HTML renderer can be configured with different [options](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RendererOptions)
|
||||
// create HTML renderer with extensions
|
||||
htmlFlags := html.CommonFlags | html.HrefTargetBlank
|
||||
opts := html.RendererOptions{Flags: htmlFlags}
|
||||
renderer := html.NewRenderer(opts)
|
||||
|
||||
Here's how to use a custom renderer:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
)
|
||||
|
||||
htmlFlags := html.CommonFlags | html.HrefTargetBlank
|
||||
opts := html.RendererOptions{Flags: htmlFlags}
|
||||
renderer := html.NewRenderer(opts)
|
||||
|
||||
md := []byte("markdown text")
|
||||
html := markdown.ToHTML(md, nil, renderer)
|
||||
```
|
||||
|
||||
Try it online: https://replit.com/@kjk1/gomarkdown-customized-html-renderer
|
||||
|
||||
HTML renderer also supports reusing most of the logic and overriding rendering of only specific nodes.
|
||||
|
||||
You can provide [RenderNodeFunc](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RenderNodeFunc) in [RendererOptions](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RendererOptions).
|
||||
|
||||
The function is called for each node in AST, you can implement custom rendering logic and tell HTML renderer to skip rendering this node.
|
||||
|
||||
Here's the simplest example that drops all code blocks from the output:
|
||||
|
||||
````go
|
||||
import (
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/ast"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
)
|
||||
|
||||
// return (ast.GoToNext, true) to tell html renderer to skip rendering this node
|
||||
// (because you've rendered it)
|
||||
func renderHookDropCodeBlock(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
|
||||
// skip all nodes that are not CodeBlock nodes
|
||||
if _, ok := node.(*ast.CodeBlock); !ok {
|
||||
return ast.GoToNext, false
|
||||
}
|
||||
// custom rendering logic for ast.CodeBlock. By doing nothing it won't be
|
||||
// present in the output
|
||||
return ast.GoToNext, true
|
||||
return markdown.Render(doc, renderer)
|
||||
}
|
||||
|
||||
opts := html.RendererOptions{
|
||||
Flags: html.CommonFlags,
|
||||
RenderNodeHook: renderHookDropCodeBlock,
|
||||
func main() {
|
||||
md := []byte(mds)
|
||||
html := mdToHTML(md)
|
||||
|
||||
fmt.Printf("--- Markdown:\n%s\n\n--- HTML:\n%s\n", md, html)
|
||||
}
|
||||
renderer := html.NewRenderer(opts)
|
||||
md := "test\n```\nthis code block will be dropped from output\n```\ntext"
|
||||
html := markdown.ToHTML([]byte(md), nil, renderer)
|
||||
````
|
||||
```
|
||||
|
||||
Try it online: https://onlinetool.io/goplayground/#txO7hJ-ibeU
|
||||
|
||||
For more documentation read [this guide](https://blog.kowalczyk.info/article/cxn3/advanced-markdown-processing-in-go.html)
|
||||
|
||||
Comparing to other markdown parsers: https://babelmark.github.io/
|
||||
|
||||
## Sanitize untrusted content
|
||||
|
||||
@ -129,12 +95,6 @@ maybeUnsafeHTML := markdown.ToHTML(md, nil, nil)
|
||||
html := bluemonday.UGCPolicy().SanitizeBytes(maybeUnsafeHTML)
|
||||
```
|
||||
|
||||
## Windows / Mac newlines
|
||||
|
||||
The library only supports Unix newlines. If you have markdown text with possibly
|
||||
Windows / Mac newlines, normalize newlines before calling this library using
|
||||
`d = markdown.NormalizeNewlines(d)`
|
||||
|
||||
## mdtohtml command-line tool
|
||||
|
||||
https://github.com/gomarkdown/mdtohtml is a command-line markdown to html
|
||||
@ -323,26 +283,15 @@ implements the following extensions:
|
||||
|
||||
- **Mmark support**, see <https://mmark.miek.nl/post/syntax/> for all new syntax elements this adds.
|
||||
|
||||
## Todo
|
||||
## Users
|
||||
|
||||
- port https://github.com/russross/blackfriday/issues/348
|
||||
- port [LaTeX output](https://github.com/Ambrevar/Blackfriday-LaTeX):
|
||||
renders output as LaTeX.
|
||||
- port https://github.com/shurcooL/github_flavored_markdown to markdown
|
||||
- port [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt,
|
||||
but for markdown.
|
||||
- More unit testing
|
||||
- Improve unicode support. It does not understand all unicode
|
||||
rules (about what constitutes a letter, a punctuation symbol,
|
||||
etc.), so it may fail to detect word boundaries correctly in
|
||||
some instances. It is safe on all utf-8 input.
|
||||
Some tools using this package: https://pkg.go.dev/github.com/gomarkdown/markdown?tab=importedby
|
||||
|
||||
## History
|
||||
|
||||
markdown is a fork of v2 of https://github.com/russross/blackfriday that is:
|
||||
markdown is a fork of v2 of https://github.com/russross/blackfriday.
|
||||
|
||||
- actively maintained (sadly in Feb 2018 blackfriday was inactive for 5 months with many bugs and pull requests accumulated)
|
||||
- refactored API (split into ast/parser/html sub-packages)
|
||||
I refactored the API (split into ast/parser/html sub-packages).
|
||||
|
||||
Blackfriday itself was based on C implementation [sundown](https://github.com/vmg/sundown) which in turn was based on [libsoldout](http://fossil.instinctive.eu/libsoldout/home).
|
||||
|
||||
|
6
vendor/github.com/gomarkdown/markdown/ast/node.go
generated
vendored
6
vendor/github.com/gomarkdown/markdown/ast/node.go
generated
vendored
@ -92,6 +92,12 @@ type Container struct {
|
||||
*Attribute // Block level attribute
|
||||
}
|
||||
|
||||
// return true if can contain children of a given node type
|
||||
// used by custom nodes to over-ride logic in canNodeContain
|
||||
type CanContain interface {
|
||||
CanContain(Node) bool
|
||||
}
|
||||
|
||||
// AsContainer returns itself as *Container
|
||||
func (c *Container) AsContainer() *Container {
|
||||
return c
|
||||
|
2
vendor/github.com/gomarkdown/markdown/ast/print.go
generated
vendored
2
vendor/github.com/gomarkdown/markdown/ast/print.go
generated
vendored
@ -157,6 +157,8 @@ func printRecur(w io.Writer, node Node, prefix string, depth int) {
|
||||
content += "flags=" + flags + " "
|
||||
}
|
||||
printDefault(w, indent, typeName, content)
|
||||
case *CodeBlock:
|
||||
printDefault(w, indent, typeName + ":" + string(v.Info), content)
|
||||
default:
|
||||
printDefault(w, indent, typeName, content)
|
||||
}
|
||||
|
8
vendor/github.com/gomarkdown/markdown/codecov.yml
generated
vendored
8
vendor/github.com/gomarkdown/markdown/codecov.yml
generated
vendored
@ -1,8 +0,0 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# basic
|
||||
target: 60%
|
||||
threshold: 2%
|
||||
base: auto
|
267
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
267
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
@ -88,13 +88,15 @@ type RendererOptions struct {
|
||||
// FootnoteReturnLinks flag is enabled. If blank, the string
|
||||
// <sup>[return]</sup> is used.
|
||||
FootnoteReturnLinkContents string
|
||||
// CitationFormatString defines how a citation is rendered. If blnck, the string
|
||||
// CitationFormatString defines how a citation is rendered. If blank, the string
|
||||
// <sup>[%s]</sup> is used. Where %s will be substituted with the citation target.
|
||||
CitationFormatString string
|
||||
// If set, add this text to the front of each Heading ID, to ensure uniqueness.
|
||||
HeadingIDPrefix string
|
||||
// If set, add this text to the back of each Heading ID, to ensure uniqueness.
|
||||
HeadingIDSuffix string
|
||||
// can over-write <p> for paragraph tag
|
||||
ParagraphTag string
|
||||
|
||||
Title string // Document title (used if CompletePage is set)
|
||||
CSS string // Optional CSS file URL (used if CompletePage is set)
|
||||
@ -120,7 +122,7 @@ type RendererOptions struct {
|
||||
//
|
||||
// Do not create this directly, instead use the NewRenderer function.
|
||||
type Renderer struct {
|
||||
opts RendererOptions
|
||||
Opts RendererOptions
|
||||
|
||||
closeTag string // how to end singleton tags: either " />" or ">"
|
||||
|
||||
@ -168,7 +170,7 @@ func EscapeHTML(w io.Writer, d []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func escLink(w io.Writer, text []byte) {
|
||||
func EscLink(w io.Writer, text []byte) {
|
||||
unesc := html.UnescapeString(string(text))
|
||||
EscapeHTML(w, []byte(unesc))
|
||||
}
|
||||
@ -207,7 +209,7 @@ func NewRenderer(opts RendererOptions) *Renderer {
|
||||
}
|
||||
|
||||
return &Renderer{
|
||||
opts: opts,
|
||||
Opts: opts,
|
||||
|
||||
closeTag: closeTag,
|
||||
headingIDs: make(map[string]int),
|
||||
@ -250,12 +252,12 @@ func isRelativeLink(link []byte) (yes bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Renderer) addAbsPrefix(link []byte) []byte {
|
||||
if len(link) == 0 {
|
||||
func AddAbsPrefix(link []byte, prefix string) []byte {
|
||||
if len(link) == 0 || len(prefix) == 0 {
|
||||
return link
|
||||
}
|
||||
if r.opts.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' {
|
||||
newDest := r.opts.AbsolutePrefix
|
||||
if isRelativeLink(link) && link[0] != '.' {
|
||||
newDest := prefix
|
||||
if link[0] != '/' {
|
||||
newDest += "/"
|
||||
}
|
||||
@ -294,7 +296,7 @@ func isMailto(link []byte) bool {
|
||||
}
|
||||
|
||||
func needSkipLink(r *Renderer, dest []byte) bool {
|
||||
flags := r.opts.Flags
|
||||
flags := r.Opts.Flags
|
||||
if flags&SkipLinks != 0 {
|
||||
return true
|
||||
}
|
||||
@ -317,7 +319,7 @@ func appendLanguageAttr(attrs []string, info []byte) []string {
|
||||
return append(attrs, s)
|
||||
}
|
||||
|
||||
func (r *Renderer) outTag(w io.Writer, name string, attrs []string) {
|
||||
func (r *Renderer) OutTag(w io.Writer, name string, attrs []string) {
|
||||
s := name
|
||||
if len(attrs) > 0 {
|
||||
s += " " + strings.Join(attrs, " ")
|
||||
@ -326,22 +328,22 @@ func (r *Renderer) outTag(w io.Writer, name string, attrs []string) {
|
||||
r.lastOutputLen = 1
|
||||
}
|
||||
|
||||
func footnoteRef(prefix string, node *ast.Link) string {
|
||||
urlFrag := prefix + string(slugify(node.Destination))
|
||||
func FootnoteRef(prefix string, node *ast.Link) string {
|
||||
urlFrag := prefix + string(Slugify(node.Destination))
|
||||
nStr := strconv.Itoa(node.NoteID)
|
||||
anchor := `<a href="#fn:` + urlFrag + `">` + nStr + `</a>`
|
||||
return `<sup class="footnote-ref" id="fnref:` + urlFrag + `">` + anchor + `</sup>`
|
||||
}
|
||||
|
||||
func footnoteItem(prefix string, slug []byte) string {
|
||||
func FootnoteItem(prefix string, slug []byte) string {
|
||||
return `<li id="fn:` + prefix + string(slug) + `">`
|
||||
}
|
||||
|
||||
func footnoteReturnLink(prefix, returnLink string, slug []byte) string {
|
||||
func FootnoteReturnLink(prefix, returnLink string, slug []byte) string {
|
||||
return ` <a class="footnote-return" href="#fnref:` + prefix + string(slug) + `">` + returnLink + `</a>`
|
||||
}
|
||||
|
||||
func listItemOpenCR(listItem *ast.ListItem) bool {
|
||||
func ListItemOpenCR(listItem *ast.ListItem) bool {
|
||||
if ast.GetPrevNode(listItem) == nil {
|
||||
return false
|
||||
}
|
||||
@ -349,13 +351,13 @@ func listItemOpenCR(listItem *ast.ListItem) bool {
|
||||
return !ld.Tight && ld.ListFlags&ast.ListTypeDefinition == 0
|
||||
}
|
||||
|
||||
func skipParagraphTags(para *ast.Paragraph) bool {
|
||||
func SkipParagraphTags(para *ast.Paragraph) bool {
|
||||
parent := para.Parent
|
||||
grandparent := parent.GetParent()
|
||||
if grandparent == nil || !isList(grandparent) {
|
||||
if grandparent == nil || !IsList(grandparent) {
|
||||
return false
|
||||
}
|
||||
isParentTerm := isListItemTerm(parent)
|
||||
isParentTerm := IsListItemTerm(parent)
|
||||
grandparentListData := grandparent.(*ast.List)
|
||||
tightOrTerm := grandparentListData.Tight || isParentTerm
|
||||
return tightOrTerm
|
||||
@ -391,35 +393,35 @@ var (
|
||||
closeHTags = []string{"</h1>", "</h2>", "</h3>", "</h4>", "</h5>"}
|
||||
)
|
||||
|
||||
func headingOpenTagFromLevel(level int) string {
|
||||
func HeadingOpenTagFromLevel(level int) string {
|
||||
if level < 1 || level > 5 {
|
||||
return "<h6"
|
||||
}
|
||||
return openHTags[level-1]
|
||||
}
|
||||
|
||||
func headingCloseTagFromLevel(level int) string {
|
||||
func HeadingCloseTagFromLevel(level int) string {
|
||||
if level < 1 || level > 5 {
|
||||
return "</h6>"
|
||||
}
|
||||
return closeHTags[level-1]
|
||||
}
|
||||
|
||||
func (r *Renderer) outHRTag(w io.Writer, attrs []string) {
|
||||
func (r *Renderer) OutHRTag(w io.Writer, attrs []string) {
|
||||
hr := TagWithAttributes("<hr", attrs)
|
||||
r.OutOneOf(w, r.opts.Flags&UseXHTML == 0, hr, "<hr />")
|
||||
r.OutOneOf(w, r.Opts.Flags&UseXHTML == 0, hr, "<hr />")
|
||||
}
|
||||
|
||||
// Text writes ast.Text node
|
||||
func (r *Renderer) Text(w io.Writer, text *ast.Text) {
|
||||
if r.opts.Flags&Smartypants != 0 {
|
||||
if r.Opts.Flags&Smartypants != 0 {
|
||||
var tmp bytes.Buffer
|
||||
EscapeHTML(&tmp, text.Literal)
|
||||
r.sr.Process(w, tmp.Bytes())
|
||||
} else {
|
||||
_, parentIsLink := text.Parent.(*ast.Link)
|
||||
if parentIsLink {
|
||||
escLink(w, text.Literal)
|
||||
EscLink(w, text.Literal)
|
||||
} else {
|
||||
EscapeHTML(w, text.Literal)
|
||||
}
|
||||
@ -428,7 +430,7 @@ func (r *Renderer) Text(w io.Writer, text *ast.Text) {
|
||||
|
||||
// HardBreak writes ast.Hardbreak node
|
||||
func (r *Renderer) HardBreak(w io.Writer, node *ast.Hardbreak) {
|
||||
r.OutOneOf(w, r.opts.Flags&UseXHTML == 0, "<br>", "<br />")
|
||||
r.OutOneOf(w, r.Opts.Flags&UseXHTML == 0, "<br>", "<br />")
|
||||
r.CR(w)
|
||||
}
|
||||
|
||||
@ -459,7 +461,7 @@ func (r *Renderer) OutOneOfCr(w io.Writer, outFirst bool, first string, second s
|
||||
|
||||
// HTMLSpan writes ast.HTMLSpan node
|
||||
func (r *Renderer) HTMLSpan(w io.Writer, span *ast.HTMLSpan) {
|
||||
if r.opts.Flags&SkipHTML == 0 {
|
||||
if r.Opts.Flags&SkipHTML == 0 {
|
||||
r.Out(w, span.Literal)
|
||||
}
|
||||
}
|
||||
@ -467,18 +469,18 @@ func (r *Renderer) HTMLSpan(w io.Writer, span *ast.HTMLSpan) {
|
||||
func (r *Renderer) linkEnter(w io.Writer, link *ast.Link) {
|
||||
attrs := link.AdditionalAttributes
|
||||
dest := link.Destination
|
||||
dest = r.addAbsPrefix(dest)
|
||||
dest = AddAbsPrefix(dest, r.Opts.AbsolutePrefix)
|
||||
var hrefBuf bytes.Buffer
|
||||
hrefBuf.WriteString("href=\"")
|
||||
escLink(&hrefBuf, dest)
|
||||
EscLink(&hrefBuf, dest)
|
||||
hrefBuf.WriteByte('"')
|
||||
attrs = append(attrs, hrefBuf.String())
|
||||
if link.NoteID != 0 {
|
||||
r.Outs(w, footnoteRef(r.opts.FootnoteAnchorPrefix, link))
|
||||
r.Outs(w, FootnoteRef(r.Opts.FootnoteAnchorPrefix, link))
|
||||
return
|
||||
}
|
||||
|
||||
attrs = appendLinkAttrs(attrs, r.opts.Flags, dest)
|
||||
attrs = appendLinkAttrs(attrs, r.Opts.Flags, dest)
|
||||
if len(link.Title) > 0 {
|
||||
var titleBuff bytes.Buffer
|
||||
titleBuff.WriteString("title=\"")
|
||||
@ -486,7 +488,7 @@ func (r *Renderer) linkEnter(w io.Writer, link *ast.Link) {
|
||||
titleBuff.WriteByte('"')
|
||||
attrs = append(attrs, titleBuff.String())
|
||||
}
|
||||
r.outTag(w, "<a", attrs)
|
||||
r.OutTag(w, "<a", attrs)
|
||||
}
|
||||
|
||||
func (r *Renderer) linkExit(w io.Writer, link *ast.Link) {
|
||||
@ -511,33 +513,34 @@ func (r *Renderer) Link(w io.Writer, link *ast.Link, entering bool) {
|
||||
}
|
||||
|
||||
func (r *Renderer) imageEnter(w io.Writer, image *ast.Image) {
|
||||
dest := image.Destination
|
||||
dest = r.addAbsPrefix(dest)
|
||||
if r.DisableTags == 0 {
|
||||
//if options.safe && potentiallyUnsafe(dest) {
|
||||
//out(w, `<img src="" alt="`)
|
||||
//} else {
|
||||
if r.opts.Flags&LazyLoadImages != 0 {
|
||||
r.Outs(w, `<img loading="lazy" src="`)
|
||||
} else {
|
||||
r.Outs(w, `<img src="`)
|
||||
}
|
||||
escLink(w, dest)
|
||||
r.Outs(w, `" alt="`)
|
||||
//}
|
||||
}
|
||||
r.DisableTags++
|
||||
if r.DisableTags > 1 {
|
||||
return
|
||||
}
|
||||
src := image.Destination
|
||||
src = AddAbsPrefix(src, r.Opts.AbsolutePrefix)
|
||||
attrs := BlockAttrs(image)
|
||||
if r.Opts.Flags&LazyLoadImages != 0 {
|
||||
attrs = append(attrs, `loading="lazy"`)
|
||||
}
|
||||
|
||||
s := TagWithAttributes("<img", attrs)
|
||||
s = s[:len(s)-1] // hackish: strip off ">" from end
|
||||
r.Outs(w, s+` src="`)
|
||||
EscLink(w, src)
|
||||
r.Outs(w, `" alt="`)
|
||||
}
|
||||
|
||||
func (r *Renderer) imageExit(w io.Writer, image *ast.Image) {
|
||||
r.DisableTags--
|
||||
if r.DisableTags == 0 {
|
||||
if image.Title != nil {
|
||||
r.Outs(w, `" title="`)
|
||||
EscapeHTML(w, image.Title)
|
||||
}
|
||||
r.Outs(w, `" />`)
|
||||
if r.DisableTags > 0 {
|
||||
return
|
||||
}
|
||||
if image.Title != nil {
|
||||
r.Outs(w, `" title="`)
|
||||
EscapeHTML(w, image.Title)
|
||||
}
|
||||
r.Outs(w, `" />`)
|
||||
}
|
||||
|
||||
// Image writes ast.Image node
|
||||
@ -571,20 +574,28 @@ func (r *Renderer) paragraphEnter(w io.Writer, para *ast.Paragraph) {
|
||||
}
|
||||
}
|
||||
|
||||
tag := TagWithAttributes("<p", BlockAttrs(para))
|
||||
ptag := "<p"
|
||||
if r.Opts.ParagraphTag != "" {
|
||||
ptag = "<" + r.Opts.ParagraphTag
|
||||
}
|
||||
tag := TagWithAttributes(ptag, BlockAttrs(para))
|
||||
r.Outs(w, tag)
|
||||
}
|
||||
|
||||
func (r *Renderer) paragraphExit(w io.Writer, para *ast.Paragraph) {
|
||||
r.Outs(w, "</p>")
|
||||
if !(isListItem(para.Parent) && ast.GetNextNode(para) == nil) {
|
||||
ptag := "</p>"
|
||||
if r.Opts.ParagraphTag != "" {
|
||||
ptag = "</" + r.Opts.ParagraphTag + ">"
|
||||
}
|
||||
r.Outs(w, ptag)
|
||||
if !(IsListItem(para.Parent) && ast.GetNextNode(para) == nil) {
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
|
||||
// Paragraph writes ast.Paragraph node
|
||||
func (r *Renderer) Paragraph(w io.Writer, para *ast.Paragraph, entering bool) {
|
||||
if skipParagraphTags(para) {
|
||||
if SkipParagraphTags(para) {
|
||||
return
|
||||
}
|
||||
if entering {
|
||||
@ -603,7 +614,7 @@ func (r *Renderer) Code(w io.Writer, node *ast.Code) {
|
||||
|
||||
// HTMLBlock write ast.HTMLBlock node
|
||||
func (r *Renderer) HTMLBlock(w io.Writer, node *ast.HTMLBlock) {
|
||||
if r.opts.Flags&SkipHTML != 0 {
|
||||
if r.Opts.Flags&SkipHTML != 0 {
|
||||
return
|
||||
}
|
||||
r.CR(w)
|
||||
@ -611,6 +622,25 @@ func (r *Renderer) HTMLBlock(w io.Writer, node *ast.HTMLBlock) {
|
||||
r.CR(w)
|
||||
}
|
||||
|
||||
func (r *Renderer) EnsureUniqueHeadingID(id string) string {
|
||||
for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] {
|
||||
tmp := fmt.Sprintf("%s-%d", id, count+1)
|
||||
|
||||
if _, tmpFound := r.headingIDs[tmp]; !tmpFound {
|
||||
r.headingIDs[id] = count + 1
|
||||
id = tmp
|
||||
} else {
|
||||
id = id + "-1"
|
||||
}
|
||||
}
|
||||
|
||||
if _, found := r.headingIDs[id]; !found {
|
||||
r.headingIDs[id] = 0
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) {
|
||||
var attrs []string
|
||||
var class string
|
||||
@ -629,44 +659,25 @@ func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) {
|
||||
attrs = []string{`class="` + class + `"`}
|
||||
}
|
||||
|
||||
ensureUniqueHeadingID := func(id string) string {
|
||||
for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] {
|
||||
tmp := fmt.Sprintf("%s-%d", id, count+1)
|
||||
|
||||
if _, tmpFound := r.headingIDs[tmp]; !tmpFound {
|
||||
r.headingIDs[id] = count + 1
|
||||
id = tmp
|
||||
} else {
|
||||
id = id + "-1"
|
||||
}
|
||||
}
|
||||
|
||||
if _, found := r.headingIDs[id]; !found {
|
||||
r.headingIDs[id] = 0
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
if nodeData.HeadingID != "" {
|
||||
id := ensureUniqueHeadingID(nodeData.HeadingID)
|
||||
if r.opts.HeadingIDPrefix != "" {
|
||||
id = r.opts.HeadingIDPrefix + id
|
||||
id := r.EnsureUniqueHeadingID(nodeData.HeadingID)
|
||||
if r.Opts.HeadingIDPrefix != "" {
|
||||
id = r.Opts.HeadingIDPrefix + id
|
||||
}
|
||||
if r.opts.HeadingIDSuffix != "" {
|
||||
id = id + r.opts.HeadingIDSuffix
|
||||
if r.Opts.HeadingIDSuffix != "" {
|
||||
id = id + r.Opts.HeadingIDSuffix
|
||||
}
|
||||
attrID := `id="` + id + `"`
|
||||
attrs = append(attrs, attrID)
|
||||
}
|
||||
attrs = append(attrs, BlockAttrs(nodeData)...)
|
||||
r.CR(w)
|
||||
r.outTag(w, headingOpenTagFromLevel(nodeData.Level), attrs)
|
||||
r.OutTag(w, HeadingOpenTagFromLevel(nodeData.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) {
|
||||
r.Outs(w, HeadingCloseTagFromLevel(heading.Level))
|
||||
if !(IsListItem(heading.Parent) && ast.GetNextNode(heading) == nil) {
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
@ -683,7 +694,7 @@ func (r *Renderer) Heading(w io.Writer, node *ast.Heading, entering bool) {
|
||||
// HorizontalRule writes ast.HorizontalRule node
|
||||
func (r *Renderer) HorizontalRule(w io.Writer, node *ast.HorizontalRule) {
|
||||
r.CR(w)
|
||||
r.outHRTag(w, BlockAttrs(node))
|
||||
r.OutHRTag(w, BlockAttrs(node))
|
||||
r.CR(w)
|
||||
}
|
||||
|
||||
@ -693,15 +704,15 @@ func (r *Renderer) listEnter(w io.Writer, nodeData *ast.List) {
|
||||
|
||||
if nodeData.IsFootnotesList {
|
||||
r.Outs(w, "\n<div class=\"footnotes\">\n\n")
|
||||
if r.opts.Flags&FootnoteNoHRTag == 0 {
|
||||
r.outHRTag(w, nil)
|
||||
if r.Opts.Flags&FootnoteNoHRTag == 0 {
|
||||
r.OutHRTag(w, nil)
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
r.CR(w)
|
||||
if isListItem(nodeData.Parent) {
|
||||
if IsListItem(nodeData.Parent) {
|
||||
grand := nodeData.Parent.GetParent()
|
||||
if isListTight(grand) {
|
||||
if IsListTight(grand) {
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
@ -717,7 +728,7 @@ func (r *Renderer) listEnter(w io.Writer, nodeData *ast.List) {
|
||||
openTag = "<dl"
|
||||
}
|
||||
attrs = append(attrs, BlockAttrs(nodeData)...)
|
||||
r.outTag(w, openTag, attrs)
|
||||
r.OutTag(w, openTag, attrs)
|
||||
r.CR(w)
|
||||
}
|
||||
|
||||
@ -760,12 +771,12 @@ func (r *Renderer) List(w io.Writer, list *ast.List, entering bool) {
|
||||
}
|
||||
|
||||
func (r *Renderer) listItemEnter(w io.Writer, listItem *ast.ListItem) {
|
||||
if listItemOpenCR(listItem) {
|
||||
if ListItemOpenCR(listItem) {
|
||||
r.CR(w)
|
||||
}
|
||||
if listItem.RefLink != nil {
|
||||
slug := slugify(listItem.RefLink)
|
||||
r.Outs(w, footnoteItem(r.opts.FootnoteAnchorPrefix, slug))
|
||||
slug := Slugify(listItem.RefLink)
|
||||
r.Outs(w, FootnoteItem(r.Opts.FootnoteAnchorPrefix, slug))
|
||||
return
|
||||
}
|
||||
|
||||
@ -780,11 +791,11 @@ func (r *Renderer) listItemEnter(w io.Writer, listItem *ast.ListItem) {
|
||||
}
|
||||
|
||||
func (r *Renderer) listItemExit(w io.Writer, listItem *ast.ListItem) {
|
||||
if listItem.RefLink != nil && r.opts.Flags&FootnoteReturnLinks != 0 {
|
||||
slug := slugify(listItem.RefLink)
|
||||
prefix := r.opts.FootnoteAnchorPrefix
|
||||
link := r.opts.FootnoteReturnLinkContents
|
||||
s := footnoteReturnLink(prefix, link, slug)
|
||||
if listItem.RefLink != nil && r.Opts.Flags&FootnoteReturnLinks != 0 {
|
||||
slug := Slugify(listItem.RefLink)
|
||||
prefix := r.Opts.FootnoteAnchorPrefix
|
||||
link := r.Opts.FootnoteReturnLinkContents
|
||||
s := FootnoteReturnLink(prefix, link, slug)
|
||||
r.Outs(w, s)
|
||||
}
|
||||
|
||||
@ -815,7 +826,7 @@ func (r *Renderer) EscapeHTMLCallouts(w io.Writer, d []byte) {
|
||||
ld := len(d)
|
||||
Parse:
|
||||
for i := 0; i < ld; i++ {
|
||||
for _, comment := range r.opts.Comments {
|
||||
for _, comment := range r.Opts.Comments {
|
||||
if !bytes.HasPrefix(d[i:], comment) {
|
||||
break
|
||||
}
|
||||
@ -853,14 +864,14 @@ func (r *Renderer) CodeBlock(w io.Writer, codeBlock *ast.CodeBlock) {
|
||||
r.Outs(w, "<pre>")
|
||||
code := TagWithAttributes("<code", attrs)
|
||||
r.Outs(w, code)
|
||||
if r.opts.Comments != nil {
|
||||
if r.Opts.Comments != nil {
|
||||
r.EscapeHTMLCallouts(w, codeBlock.Literal)
|
||||
} else {
|
||||
EscapeHTML(w, codeBlock.Literal)
|
||||
}
|
||||
r.Outs(w, "</code>")
|
||||
r.Outs(w, "</pre>")
|
||||
if !isListItem(codeBlock.Parent) {
|
||||
if !IsListItem(codeBlock.Parent) {
|
||||
r.CR(w)
|
||||
}
|
||||
}
|
||||
@ -910,7 +921,7 @@ func (r *Renderer) TableCell(w io.Writer, tableCell *ast.TableCell, entering boo
|
||||
if ast.GetPrevNode(tableCell) == nil {
|
||||
r.CR(w)
|
||||
}
|
||||
r.outTag(w, openTag, attrs)
|
||||
r.OutTag(w, openTag, attrs)
|
||||
}
|
||||
|
||||
// TableBody writes ast.TableBody node
|
||||
@ -959,8 +970,8 @@ func (r *Renderer) Citation(w io.Writer, node *ast.Citation) {
|
||||
case ast.CitationTypeSuppressed:
|
||||
attr[0] = `class="suppressed"`
|
||||
}
|
||||
r.outTag(w, "<cite", attr)
|
||||
r.Outs(w, fmt.Sprintf(`<a href="#%s">`+r.opts.CitationFormatString+`</a>`, c, c))
|
||||
r.OutTag(w, "<cite", attr)
|
||||
r.Outs(w, fmt.Sprintf(`<a href="#%s">`+r.Opts.CitationFormatString+`</a>`, c, c))
|
||||
r.Outs(w, "</cite>")
|
||||
}
|
||||
}
|
||||
@ -968,7 +979,7 @@ func (r *Renderer) Citation(w io.Writer, node *ast.Citation) {
|
||||
// Callout writes ast.Callout node
|
||||
func (r *Renderer) Callout(w io.Writer, node *ast.Callout) {
|
||||
attr := []string{`class="callout"`}
|
||||
r.outTag(w, "<span", attr)
|
||||
r.OutTag(w, "<span", attr)
|
||||
r.Out(w, node.ID)
|
||||
r.Outs(w, "</span>")
|
||||
}
|
||||
@ -977,14 +988,14 @@ func (r *Renderer) Callout(w io.Writer, node *ast.Callout) {
|
||||
func (r *Renderer) Index(w io.Writer, node *ast.Index) {
|
||||
// there is no in-text representation.
|
||||
attr := []string{`class="index"`, fmt.Sprintf(`id="%s"`, node.ID)}
|
||||
r.outTag(w, "<span", attr)
|
||||
r.OutTag(w, "<span", attr)
|
||||
r.Outs(w, "</span>")
|
||||
}
|
||||
|
||||
// RenderNode renders a markdown node to HTML
|
||||
func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.WalkStatus {
|
||||
if r.opts.RenderNodeHook != nil {
|
||||
status, didHandle := r.opts.RenderNodeHook(w, node, entering)
|
||||
if r.Opts.RenderNodeHook != nil {
|
||||
status, didHandle := r.Opts.RenderNodeHook(w, node, entering)
|
||||
if didHandle {
|
||||
return status
|
||||
}
|
||||
@ -1019,7 +1030,7 @@ func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.Wal
|
||||
case *ast.Citation:
|
||||
r.Citation(w, node)
|
||||
case *ast.Image:
|
||||
if r.opts.Flags&SkipImages != 0 {
|
||||
if r.Opts.Flags&SkipImages != 0 {
|
||||
return ast.SkipChildren
|
||||
}
|
||||
r.Image(w, node, entering)
|
||||
@ -1098,7 +1109,7 @@ func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.Wal
|
||||
// RenderHeader writes HTML document preamble and TOC if requested.
|
||||
func (r *Renderer) RenderHeader(w io.Writer, ast ast.Node) {
|
||||
r.writeDocumentHeader(w)
|
||||
if r.opts.Flags&TOC != 0 {
|
||||
if r.Opts.Flags&TOC != 0 {
|
||||
r.writeTOC(w, ast)
|
||||
}
|
||||
}
|
||||
@ -1109,18 +1120,18 @@ func (r *Renderer) RenderFooter(w io.Writer, _ ast.Node) {
|
||||
r.Outs(w, "</section>\n")
|
||||
}
|
||||
|
||||
if r.opts.Flags&CompletePage == 0 {
|
||||
if r.Opts.Flags&CompletePage == 0 {
|
||||
return
|
||||
}
|
||||
io.WriteString(w, "\n</body>\n</html>\n")
|
||||
}
|
||||
|
||||
func (r *Renderer) writeDocumentHeader(w io.Writer) {
|
||||
if r.opts.Flags&CompletePage == 0 {
|
||||
if r.Opts.Flags&CompletePage == 0 {
|
||||
return
|
||||
}
|
||||
ending := ""
|
||||
if r.opts.Flags&UseXHTML != 0 {
|
||||
if r.Opts.Flags&UseXHTML != 0 {
|
||||
io.WriteString(w, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ")
|
||||
io.WriteString(w, "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n")
|
||||
io.WriteString(w, "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n")
|
||||
@ -1131,35 +1142,35 @@ func (r *Renderer) writeDocumentHeader(w io.Writer) {
|
||||
}
|
||||
io.WriteString(w, "<head>\n")
|
||||
io.WriteString(w, " <title>")
|
||||
if r.opts.Flags&Smartypants != 0 {
|
||||
r.sr.Process(w, []byte(r.opts.Title))
|
||||
if r.Opts.Flags&Smartypants != 0 {
|
||||
r.sr.Process(w, []byte(r.Opts.Title))
|
||||
} else {
|
||||
EscapeHTML(w, []byte(r.opts.Title))
|
||||
EscapeHTML(w, []byte(r.Opts.Title))
|
||||
}
|
||||
io.WriteString(w, "</title>\n")
|
||||
io.WriteString(w, r.opts.Generator)
|
||||
io.WriteString(w, r.Opts.Generator)
|
||||
io.WriteString(w, "\"")
|
||||
io.WriteString(w, ending)
|
||||
io.WriteString(w, ">\n")
|
||||
io.WriteString(w, " <meta charset=\"utf-8\"")
|
||||
io.WriteString(w, ending)
|
||||
io.WriteString(w, ">\n")
|
||||
if r.opts.CSS != "" {
|
||||
if r.Opts.CSS != "" {
|
||||
io.WriteString(w, " <link rel=\"stylesheet\" type=\"text/css\" href=\"")
|
||||
EscapeHTML(w, []byte(r.opts.CSS))
|
||||
EscapeHTML(w, []byte(r.Opts.CSS))
|
||||
io.WriteString(w, "\"")
|
||||
io.WriteString(w, ending)
|
||||
io.WriteString(w, ">\n")
|
||||
}
|
||||
if r.opts.Icon != "" {
|
||||
if r.Opts.Icon != "" {
|
||||
io.WriteString(w, " <link rel=\"icon\" type=\"image/x-icon\" href=\"")
|
||||
EscapeHTML(w, []byte(r.opts.Icon))
|
||||
EscapeHTML(w, []byte(r.Opts.Icon))
|
||||
io.WriteString(w, "\"")
|
||||
io.WriteString(w, ending)
|
||||
io.WriteString(w, ">\n")
|
||||
}
|
||||
if r.opts.Head != nil {
|
||||
w.Write(r.opts.Head)
|
||||
if r.Opts.Head != nil {
|
||||
w.Write(r.Opts.Head)
|
||||
}
|
||||
io.WriteString(w, "</head>\n")
|
||||
io.WriteString(w, "<body>\n\n")
|
||||
@ -1221,31 +1232,31 @@ func (r *Renderer) writeTOC(w io.Writer, doc ast.Node) {
|
||||
r.lastOutputLen = buf.Len()
|
||||
}
|
||||
|
||||
func isList(node ast.Node) bool {
|
||||
func IsList(node ast.Node) bool {
|
||||
_, ok := node.(*ast.List)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isListTight(node ast.Node) bool {
|
||||
func IsListTight(node ast.Node) bool {
|
||||
if list, ok := node.(*ast.List); ok {
|
||||
return list.Tight
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isListItem(node ast.Node) bool {
|
||||
func IsListItem(node ast.Node) bool {
|
||||
_, ok := node.(*ast.ListItem)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isListItemTerm(node ast.Node) bool {
|
||||
func IsListItemTerm(node ast.Node) bool {
|
||||
data, ok := node.(*ast.ListItem)
|
||||
return ok && data.ListFlags&ast.ListTypeTerm != 0
|
||||
}
|
||||
|
||||
// TODO: move to internal package
|
||||
// Create a url-safe slug for fragments
|
||||
func slugify(in []byte) []byte {
|
||||
func Slugify(in []byte) []byte {
|
||||
if len(in) == 0 {
|
||||
return in
|
||||
}
|
||||
|
27
vendor/github.com/gomarkdown/markdown/markdown.go
generated
vendored
27
vendor/github.com/gomarkdown/markdown/markdown.go
generated
vendored
@ -84,28 +84,7 @@ func ToHTML(markdown []byte, p *parser.Parser, renderer Renderer) []byte {
|
||||
return Render(doc, renderer)
|
||||
}
|
||||
|
||||
// NormalizeNewlines converts Windows and Mac newlines to Unix newlines
|
||||
// The parser only supports Unix newlines. If your mardown content
|
||||
// NormalizeNewlines converts Windows and Mac newlines to Unix newlines.
|
||||
// The parser only supports Unix newlines. If your markdown content
|
||||
// might contain Windows or Mac newlines, use this function to convert to Unix newlines
|
||||
func NormalizeNewlines(d []byte) []byte {
|
||||
wi := 0
|
||||
n := len(d)
|
||||
for i := 0; i < n; i++ {
|
||||
c := d[i]
|
||||
// 13 is CR
|
||||
if c != 13 {
|
||||
d[wi] = c
|
||||
wi++
|
||||
continue
|
||||
}
|
||||
// replace CR (mac / win) with LF (unix)
|
||||
d[wi] = 10
|
||||
wi++
|
||||
if i < n-1 && d[i+1] == 10 {
|
||||
// this was CRLF, so skip the LF
|
||||
i++
|
||||
}
|
||||
|
||||
}
|
||||
return d[:wi]
|
||||
}
|
||||
var NormalizeNewlines = parser.NormalizeNewlines
|
||||
|
10
vendor/github.com/gomarkdown/markdown/parser/aside.go
generated
vendored
10
vendor/github.com/gomarkdown/markdown/parser/aside.go
generated
vendored
@ -25,13 +25,13 @@ func (p *Parser) asidePrefix(data []byte) int {
|
||||
// aside ends with at least one blank line
|
||||
// followed by something without a aside prefix
|
||||
func (p *Parser) terminateAside(data []byte, beg, end int) bool {
|
||||
if p.isEmpty(data[beg:]) <= 0 {
|
||||
if IsEmpty(data[beg:]) <= 0 {
|
||||
return false
|
||||
}
|
||||
if end >= len(data) {
|
||||
return true
|
||||
}
|
||||
return p.asidePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0
|
||||
return p.asidePrefix(data[end:]) == 0 && IsEmpty(data[end:]) == 0
|
||||
}
|
||||
|
||||
// parse a aside fragment
|
||||
@ -66,8 +66,8 @@ func (p *Parser) aside(data []byte) int {
|
||||
beg = end
|
||||
}
|
||||
|
||||
block := p.addBlock(&ast.Aside{})
|
||||
p.block(raw.Bytes())
|
||||
p.finalize(block)
|
||||
block := p.AddBlock(&ast.Aside{})
|
||||
p.Block(raw.Bytes())
|
||||
p.Finalize(block)
|
||||
return end
|
||||
}
|
||||
|
134
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
134
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
@ -103,10 +103,10 @@ func sanitizeHeadingID(text string) string {
|
||||
return string(anchorName)
|
||||
}
|
||||
|
||||
// Parse block-level data.
|
||||
// Parse Block-level data.
|
||||
// Note: this function and many that it calls assume that
|
||||
// the input buffer ends with a newline.
|
||||
func (p *Parser) block(data []byte) {
|
||||
func (p *Parser) Block(data []byte) {
|
||||
// this is called recursively: enforce a maximum depth
|
||||
if p.nesting >= p.maxNesting {
|
||||
return
|
||||
@ -142,7 +142,7 @@ func (p *Parser) block(data []byte) {
|
||||
}
|
||||
}
|
||||
p.includeStack.Push(path)
|
||||
p.block(included)
|
||||
p.Block(included)
|
||||
p.includeStack.Pop()
|
||||
data = data[consumed:]
|
||||
continue
|
||||
@ -156,10 +156,10 @@ func (p *Parser) block(data []byte) {
|
||||
data = data[consumed:]
|
||||
|
||||
if node != nil {
|
||||
p.addBlock(node)
|
||||
p.AddBlock(node)
|
||||
if blockdata != nil {
|
||||
p.block(blockdata)
|
||||
p.finalize(node)
|
||||
p.Block(blockdata)
|
||||
p.Finalize(node)
|
||||
}
|
||||
}
|
||||
continue
|
||||
@ -213,7 +213,7 @@ func (p *Parser) block(data []byte) {
|
||||
}
|
||||
|
||||
// blank lines. note: returns the # of bytes to skip
|
||||
if i := p.isEmpty(data); i > 0 {
|
||||
if i := IsEmpty(data); i > 0 {
|
||||
data = data[i:]
|
||||
continue
|
||||
}
|
||||
@ -255,11 +255,11 @@ func (p *Parser) block(data []byte) {
|
||||
// ******
|
||||
// or
|
||||
// ______
|
||||
if p.isHRule(data) {
|
||||
if isHRule(data) {
|
||||
i := skipUntilChar(data, 0, '\n')
|
||||
hr := ast.HorizontalRule{}
|
||||
hr.Literal = bytes.Trim(data[:i], " \n")
|
||||
p.addBlock(&hr)
|
||||
p.AddBlock(&hr)
|
||||
data = data[i:]
|
||||
continue
|
||||
}
|
||||
@ -377,7 +377,7 @@ func (p *Parser) block(data []byte) {
|
||||
p.nesting--
|
||||
}
|
||||
|
||||
func (p *Parser) addBlock(n ast.Node) ast.Node {
|
||||
func (p *Parser) AddBlock(n ast.Node) ast.Node {
|
||||
p.closeUnmatchedBlocks()
|
||||
|
||||
if p.attr != nil {
|
||||
@ -448,7 +448,7 @@ func (p *Parser) prefixHeading(data []byte) int {
|
||||
p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block)
|
||||
}
|
||||
block.Content = data[i:end]
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
}
|
||||
return skip
|
||||
}
|
||||
@ -521,7 +521,7 @@ func (p *Parser) prefixSpecialHeading(data []byte) int {
|
||||
}
|
||||
block.Literal = data[i:end]
|
||||
block.Content = data[i:end]
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
}
|
||||
return skip
|
||||
}
|
||||
@ -572,7 +572,7 @@ func (p *Parser) titleBlock(data []byte, doRender bool) int {
|
||||
IsTitleblock: true,
|
||||
}
|
||||
block.Content = data
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
|
||||
return consumed
|
||||
}
|
||||
@ -617,14 +617,14 @@ func (p *Parser) html(data []byte, doRender bool) int {
|
||||
}
|
||||
|
||||
// see if it is the only thing on the line
|
||||
if skip := p.isEmpty(data[j:]); skip > 0 {
|
||||
if skip := IsEmpty(data[j:]); skip > 0 {
|
||||
// see if it is followed by a blank line/eof
|
||||
j += skip
|
||||
if j >= len(data) {
|
||||
found = true
|
||||
i = j
|
||||
} else {
|
||||
if skip := p.isEmpty(data[j:]); skip > 0 {
|
||||
if skip := IsEmpty(data[j:]); skip > 0 {
|
||||
j += skip
|
||||
found = true
|
||||
i = j
|
||||
@ -667,7 +667,7 @@ func (p *Parser) html(data []byte, doRender bool) int {
|
||||
// trim newlines
|
||||
end := backChar(data, i, '\n')
|
||||
htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||
p.addBlock(htmlBLock)
|
||||
p.AddBlock(htmlBLock)
|
||||
finalizeHTMLBlock(htmlBLock)
|
||||
}
|
||||
|
||||
@ -683,13 +683,13 @@ func finalizeHTMLBlock(block *ast.HTMLBlock) {
|
||||
func (p *Parser) htmlComment(data []byte, doRender bool) int {
|
||||
i := p.inlineHTMLComment(data)
|
||||
// needs to end with a blank line
|
||||
if j := p.isEmpty(data[i:]); j > 0 {
|
||||
if j := IsEmpty(data[i:]); j > 0 {
|
||||
size := i + j
|
||||
if doRender {
|
||||
// trim trailing newlines
|
||||
end := backChar(data, size, '\n')
|
||||
htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||
p.addBlock(htmlBLock)
|
||||
p.AddBlock(htmlBLock)
|
||||
finalizeHTMLBlock(htmlBLock)
|
||||
}
|
||||
return size
|
||||
@ -715,13 +715,13 @@ func (p *Parser) htmlHr(data []byte, doRender bool) int {
|
||||
}
|
||||
if i < len(data) && data[i] == '>' {
|
||||
i++
|
||||
if j := p.isEmpty(data[i:]); j > 0 {
|
||||
if j := IsEmpty(data[i:]); j > 0 {
|
||||
size := i + j
|
||||
if doRender {
|
||||
// trim newlines
|
||||
end := backChar(data, size, '\n')
|
||||
htmlBlock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||
p.addBlock(htmlBlock)
|
||||
p.AddBlock(htmlBlock)
|
||||
finalizeHTMLBlock(htmlBlock)
|
||||
}
|
||||
return size
|
||||
@ -753,7 +753,7 @@ func (p *Parser) htmlFindEnd(tag string, data []byte) int {
|
||||
|
||||
// check that the rest of the line is blank
|
||||
skip := 0
|
||||
if skip = p.isEmpty(data[i:]); skip == 0 {
|
||||
if skip = IsEmpty(data[i:]); skip == 0 {
|
||||
return 0
|
||||
}
|
||||
i += skip
|
||||
@ -766,7 +766,7 @@ func (p *Parser) htmlFindEnd(tag string, data []byte) int {
|
||||
if p.extensions&LaxHTMLBlocks != 0 {
|
||||
return i
|
||||
}
|
||||
if skip = p.isEmpty(data[i:]); skip == 0 {
|
||||
if skip = IsEmpty(data[i:]); skip == 0 {
|
||||
// following line must be blank
|
||||
return 0
|
||||
}
|
||||
@ -774,7 +774,7 @@ func (p *Parser) htmlFindEnd(tag string, data []byte) int {
|
||||
return i + skip
|
||||
}
|
||||
|
||||
func (*Parser) isEmpty(data []byte) int {
|
||||
func IsEmpty(data []byte) int {
|
||||
// it is okay to call isEmpty on an empty buffer
|
||||
if len(data) == 0 {
|
||||
return 0
|
||||
@ -790,7 +790,7 @@ func (*Parser) isEmpty(data []byte) int {
|
||||
return i
|
||||
}
|
||||
|
||||
func (*Parser) isHRule(data []byte) bool {
|
||||
func isHRule(data []byte) bool {
|
||||
i := 0
|
||||
|
||||
// skip up to three spaces
|
||||
@ -976,7 +976,7 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
||||
codeBlock.Content = work.Bytes() // TODO: get rid of temp buffer
|
||||
|
||||
if p.extensions&Mmark == 0 {
|
||||
p.addBlock(codeBlock)
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
return beg
|
||||
}
|
||||
@ -988,12 +988,12 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
||||
figure.HeadingID = id
|
||||
p.Inline(caption, captionContent)
|
||||
|
||||
p.addBlock(figure)
|
||||
p.AddBlock(figure)
|
||||
codeBlock.AsLeaf().Attribute = figure.AsContainer().Attribute
|
||||
p.addChild(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
p.addChild(caption)
|
||||
p.finalize(figure)
|
||||
p.Finalize(figure)
|
||||
|
||||
beg += consumed
|
||||
|
||||
@ -1001,7 +1001,7 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
||||
}
|
||||
|
||||
// Still here, normal block
|
||||
p.addBlock(codeBlock)
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
}
|
||||
|
||||
@ -1055,13 +1055,13 @@ func (p *Parser) quotePrefix(data []byte) int {
|
||||
// blockquote ends with at least one blank line
|
||||
// followed by something without a blockquote prefix
|
||||
func (p *Parser) terminateBlockquote(data []byte, beg, end int) bool {
|
||||
if p.isEmpty(data[beg:]) <= 0 {
|
||||
if IsEmpty(data[beg:]) <= 0 {
|
||||
return false
|
||||
}
|
||||
if end >= len(data) {
|
||||
return true
|
||||
}
|
||||
return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0
|
||||
return p.quotePrefix(data[end:]) == 0 && IsEmpty(data[end:]) == 0
|
||||
}
|
||||
|
||||
// parse a blockquote fragment
|
||||
@ -1096,9 +1096,9 @@ func (p *Parser) quote(data []byte) int {
|
||||
}
|
||||
|
||||
if p.extensions&Mmark == 0 {
|
||||
block := p.addBlock(&ast.BlockQuote{})
|
||||
p.block(raw.Bytes())
|
||||
p.finalize(block)
|
||||
block := p.AddBlock(&ast.BlockQuote{})
|
||||
p.Block(raw.Bytes())
|
||||
p.Finalize(block)
|
||||
return end
|
||||
}
|
||||
|
||||
@ -1108,24 +1108,24 @@ func (p *Parser) quote(data []byte) int {
|
||||
figure.HeadingID = id
|
||||
p.Inline(caption, captionContent)
|
||||
|
||||
p.addBlock(figure) // this discard any attributes
|
||||
p.AddBlock(figure) // this discard any attributes
|
||||
block := &ast.BlockQuote{}
|
||||
block.AsContainer().Attribute = figure.AsContainer().Attribute
|
||||
p.addChild(block)
|
||||
p.block(raw.Bytes())
|
||||
p.finalize(block)
|
||||
p.Block(raw.Bytes())
|
||||
p.Finalize(block)
|
||||
|
||||
p.addChild(caption)
|
||||
p.finalize(figure)
|
||||
p.Finalize(figure)
|
||||
|
||||
end += consumed
|
||||
|
||||
return end
|
||||
}
|
||||
|
||||
block := p.addBlock(&ast.BlockQuote{})
|
||||
p.block(raw.Bytes())
|
||||
p.finalize(block)
|
||||
block := p.AddBlock(&ast.BlockQuote{})
|
||||
p.Block(raw.Bytes())
|
||||
p.Finalize(block)
|
||||
|
||||
return end
|
||||
}
|
||||
@ -1152,7 +1152,7 @@ func (p *Parser) code(data []byte) int {
|
||||
i = skipUntilChar(data, i, '\n')
|
||||
i = skipCharN(data, i, '\n', 1)
|
||||
|
||||
blankline := p.isEmpty(data[beg:i]) > 0
|
||||
blankline := IsEmpty(data[beg:i]) > 0
|
||||
if pre := p.codePrefix(data[beg:i]); pre > 0 {
|
||||
beg += pre
|
||||
} else if !blankline {
|
||||
@ -1185,7 +1185,7 @@ func (p *Parser) code(data []byte) int {
|
||||
}
|
||||
// TODO: get rid of temp buffer
|
||||
codeBlock.Content = work.Bytes()
|
||||
p.addBlock(codeBlock)
|
||||
p.AddBlock(codeBlock)
|
||||
finalizeCodeBlock(codeBlock)
|
||||
|
||||
return i
|
||||
@ -1237,10 +1237,29 @@ func (p *Parser) dliPrefix(data []byte) int {
|
||||
if data[0] != ':' || !(data[1] == ' ' || data[1] == '\t') {
|
||||
return 0
|
||||
}
|
||||
// TODO: this is a no-op (data[0] is ':' so not ' ').
|
||||
// Maybe the intent was to eat spaces before ':' ?
|
||||
// either way, no change in tests
|
||||
i := skipChar(data, 0, ' ')
|
||||
return i + 2
|
||||
}
|
||||
|
||||
// TODO: maybe it was meant to be like below
|
||||
// either way, no change in tests
|
||||
/*
|
||||
func (p *Parser) dliPrefix(data []byte) int {
|
||||
i := skipChar(data, 0, ' ')
|
||||
if i+len(data) < 2 {
|
||||
return 0
|
||||
}
|
||||
// need a ':' followed by a space or a tab
|
||||
if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') {
|
||||
return 0
|
||||
}
|
||||
return i + 2
|
||||
}
|
||||
*/
|
||||
|
||||
// parse ordered or unordered list block
|
||||
func (p *Parser) list(data []byte, flags ast.ListType, start int, delim byte) int {
|
||||
i := 0
|
||||
@ -1251,7 +1270,7 @@ func (p *Parser) list(data []byte, flags ast.ListType, start int, delim byte) in
|
||||
Start: start,
|
||||
Delimiter: delim,
|
||||
}
|
||||
block := p.addBlock(list)
|
||||
block := p.AddBlock(list)
|
||||
|
||||
for i < len(data) {
|
||||
skip := p.listItem(data[i:], &flags)
|
||||
@ -1398,7 +1417,7 @@ gatherlines:
|
||||
|
||||
// if it is an empty line, guess that it is part of this item
|
||||
// and move on to the next line
|
||||
if p.isEmpty(data[line:i]) > 0 {
|
||||
if IsEmpty(data[line:i]) > 0 {
|
||||
containsBlankLine = true
|
||||
line = i
|
||||
continue
|
||||
@ -1432,7 +1451,7 @@ gatherlines:
|
||||
// evaluate how this line fits in
|
||||
switch {
|
||||
// is this a nested list item?
|
||||
case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || p.oliPrefix(chunk) > 0 || p.dliPrefix(chunk) > 0:
|
||||
case (p.uliPrefix(chunk) > 0 && !isHRule(chunk)) || p.oliPrefix(chunk) > 0 || p.dliPrefix(chunk) > 0:
|
||||
|
||||
// if indent is 4 or more spaces on unordered or ordered lists
|
||||
// we need to add leadingWhiteSpaces + 1 spaces in the beginning of the chunk
|
||||
@ -1484,10 +1503,7 @@ gatherlines:
|
||||
case containsBlankLine && indent < 4:
|
||||
if *flags&ast.ListTypeDefinition != 0 && i < len(data)-1 {
|
||||
// is the next item still a part of this list?
|
||||
next := i
|
||||
for next < len(data) && data[next] != '\n' {
|
||||
next++
|
||||
}
|
||||
next := skipUntilChar(data, i, '\n')
|
||||
for next < len(data)-1 && data[next] == '\n' {
|
||||
next++
|
||||
}
|
||||
@ -1526,16 +1542,16 @@ gatherlines:
|
||||
BulletChar: bulletChar,
|
||||
Delimiter: delimiter,
|
||||
}
|
||||
p.addBlock(listItem)
|
||||
p.AddBlock(listItem)
|
||||
|
||||
// render the contents of the list item
|
||||
if *flags&ast.ListItemContainsBlock != 0 && *flags&ast.ListTypeTerm == 0 {
|
||||
// intermediate render of block item, except for definition term
|
||||
if sublist > 0 {
|
||||
p.block(rawBytes[:sublist])
|
||||
p.block(rawBytes[sublist:])
|
||||
p.Block(rawBytes[:sublist])
|
||||
p.Block(rawBytes[sublist:])
|
||||
} else {
|
||||
p.block(rawBytes)
|
||||
p.Block(rawBytes)
|
||||
}
|
||||
} else {
|
||||
// intermediate render of inline item
|
||||
@ -1547,7 +1563,7 @@ gatherlines:
|
||||
}
|
||||
p.addChild(para)
|
||||
if sublist > 0 {
|
||||
p.block(rawBytes[sublist:])
|
||||
p.Block(rawBytes[sublist:])
|
||||
}
|
||||
}
|
||||
return line
|
||||
@ -1574,7 +1590,7 @@ func (p *Parser) renderParagraph(data []byte) {
|
||||
}
|
||||
para := &ast.Paragraph{}
|
||||
para.Content = data[beg:end]
|
||||
p.addBlock(para)
|
||||
p.AddBlock(para)
|
||||
}
|
||||
|
||||
// blockMath handle block surround with $$
|
||||
@ -1596,7 +1612,7 @@ func (p *Parser) blockMath(data []byte) int {
|
||||
// render the display math
|
||||
mathBlock := &ast.MathBlock{}
|
||||
mathBlock.Literal = data[2:end]
|
||||
p.addBlock(mathBlock)
|
||||
p.AddBlock(mathBlock)
|
||||
|
||||
return end + 2
|
||||
}
|
||||
@ -1626,7 +1642,7 @@ func (p *Parser) paragraph(data []byte) int {
|
||||
}
|
||||
|
||||
// did we find a blank line marking the end of the paragraph?
|
||||
if n := p.isEmpty(current); n > 0 {
|
||||
if n := IsEmpty(current); n > 0 {
|
||||
// did this blank line followed by a definition list item?
|
||||
if p.extensions&DefinitionLists != 0 {
|
||||
if i < len(data)-1 && data[i+1] == ':' {
|
||||
@ -1663,7 +1679,7 @@ func (p *Parser) paragraph(data []byte) int {
|
||||
}
|
||||
|
||||
block.Content = data[prev:eol]
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
|
||||
// find the end of the underline
|
||||
return skipUntilChar(data, i, '\n')
|
||||
@ -1680,7 +1696,7 @@ func (p *Parser) paragraph(data []byte) int {
|
||||
}
|
||||
|
||||
// if there's a prefixed heading or a horizontal rule after this, paragraph is over
|
||||
if p.isPrefixHeading(current) || p.isPrefixSpecialHeading(current) || p.isHRule(current) {
|
||||
if p.isPrefixHeading(current) || p.isPrefixSpecialHeading(current) || isHRule(current) {
|
||||
p.renderParagraph(data[:i])
|
||||
return i
|
||||
}
|
||||
|
18
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
18
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
@ -12,7 +12,7 @@ func isBackslashEscaped(data []byte, i int) bool {
|
||||
}
|
||||
|
||||
func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) {
|
||||
p.addBlock(&ast.TableRow{})
|
||||
p.AddBlock(&ast.TableRow{})
|
||||
col := 0
|
||||
|
||||
i := skipChar(data, 0, '|')
|
||||
@ -61,7 +61,7 @@ func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool
|
||||
// an empty cell that we should ignore, it exists because of colspan
|
||||
colspans--
|
||||
} else {
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
}
|
||||
|
||||
if colspan > 0 {
|
||||
@ -75,7 +75,7 @@ func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool
|
||||
IsHeader: header,
|
||||
Align: columns[col],
|
||||
}
|
||||
p.addBlock(block)
|
||||
p.AddBlock(block)
|
||||
}
|
||||
|
||||
// silently ignore rows with too many cells
|
||||
@ -109,7 +109,7 @@ func (p *Parser) tableFooter(data []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
p.addBlock(&ast.TableFooter{})
|
||||
p.AddBlock(&ast.TableFooter{})
|
||||
|
||||
return true
|
||||
}
|
||||
@ -217,7 +217,7 @@ func (p *Parser) tableHeader(data []byte, doRender bool) (size int, columns []as
|
||||
}
|
||||
// end of column test is messy
|
||||
switch {
|
||||
case dashes < 3:
|
||||
case dashes < 1:
|
||||
// not a valid column
|
||||
return
|
||||
|
||||
@ -253,9 +253,9 @@ func (p *Parser) tableHeader(data []byte, doRender bool) (size int, columns []as
|
||||
|
||||
if doRender {
|
||||
table = &ast.Table{}
|
||||
p.addBlock(table)
|
||||
p.AddBlock(table)
|
||||
if header != nil {
|
||||
p.addBlock(&ast.TableHeader{})
|
||||
p.AddBlock(&ast.TableHeader{})
|
||||
p.tableRow(header, columns, true)
|
||||
}
|
||||
}
|
||||
@ -277,7 +277,7 @@ func (p *Parser) table(data []byte) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
p.addBlock(&ast.TableBody{})
|
||||
p.AddBlock(&ast.TableBody{})
|
||||
|
||||
for i < len(data) {
|
||||
pipes, rowStart := 0, i
|
||||
@ -319,7 +319,7 @@ func (p *Parser) table(data []byte) int {
|
||||
ast.AppendChild(figure, caption)
|
||||
|
||||
p.addChild(figure)
|
||||
p.finalize(figure)
|
||||
p.Finalize(figure)
|
||||
|
||||
i += consumed
|
||||
}
|
||||
|
8
vendor/github.com/gomarkdown/markdown/parser/caption.go
generated
vendored
8
vendor/github.com/gomarkdown/markdown/parser/caption.go
generated
vendored
@ -11,7 +11,7 @@ func (p *Parser) caption(data, caption []byte) ([]byte, string, int) {
|
||||
}
|
||||
j := len(caption)
|
||||
data = data[j:]
|
||||
end := p.linesUntilEmpty(data)
|
||||
end := LinesUntilEmpty(data)
|
||||
|
||||
data = data[:end]
|
||||
|
||||
@ -23,8 +23,8 @@ func (p *Parser) caption(data, caption []byte) ([]byte, string, int) {
|
||||
return data, "", end + j
|
||||
}
|
||||
|
||||
// linesUntilEmpty scans lines up to the first empty line.
|
||||
func (p *Parser) linesUntilEmpty(data []byte) int {
|
||||
// LinesUntilEmpty scans lines up to the first empty line.
|
||||
func LinesUntilEmpty(data []byte) int {
|
||||
line, i := 0, 0
|
||||
|
||||
for line < len(data) {
|
||||
@ -35,7 +35,7 @@ func (p *Parser) linesUntilEmpty(data []byte) int {
|
||||
i++
|
||||
}
|
||||
|
||||
if p.isEmpty(data[line:i]) == 0 {
|
||||
if IsEmpty(data[line:i]) == 0 {
|
||||
line = i
|
||||
continue
|
||||
}
|
||||
|
8
vendor/github.com/gomarkdown/markdown/parser/figures.go
generated
vendored
8
vendor/github.com/gomarkdown/markdown/parser/figures.go
generated
vendored
@ -98,10 +98,10 @@ func (p *Parser) figureBlock(data []byte, doRender bool) int {
|
||||
}
|
||||
|
||||
figure := &ast.CaptionFigure{}
|
||||
p.addBlock(figure)
|
||||
p.block(raw.Bytes())
|
||||
p.AddBlock(figure)
|
||||
p.Block(raw.Bytes())
|
||||
|
||||
defer p.finalize(figure)
|
||||
defer p.Finalize(figure)
|
||||
|
||||
if captionContent, id, consumed := p.caption(data[beg:], []byte("Figure: ")); consumed > 0 {
|
||||
caption := &ast.Caption{}
|
||||
@ -113,7 +113,5 @@ func (p *Parser) figureBlock(data []byte, doRender bool) int {
|
||||
|
||||
beg += consumed
|
||||
}
|
||||
|
||||
p.finalize(figure)
|
||||
return beg
|
||||
}
|
||||
|
4
vendor/github.com/gomarkdown/markdown/parser/matter.go
generated
vendored
4
vendor/github.com/gomarkdown/markdown/parser/matter.go
generated
vendored
@ -29,8 +29,8 @@ func (p *Parser) documentMatter(data []byte) int {
|
||||
return 0
|
||||
}
|
||||
node := &ast.DocumentMatter{Matter: matter}
|
||||
p.addBlock(node)
|
||||
p.finalize(node)
|
||||
p.AddBlock(node)
|
||||
p.Finalize(node)
|
||||
|
||||
return consumed
|
||||
}
|
||||
|
59
vendor/github.com/gomarkdown/markdown/parser/parser.go
generated
vendored
59
vendor/github.com/gomarkdown/markdown/parser/parser.go
generated
vendored
@ -42,7 +42,7 @@ const (
|
||||
SuperSubscript // Super- and subscript support: 2^10^, H~2~O.
|
||||
EmptyLinesBreakList // 2 empty lines break out of list
|
||||
Includes // Support including other files.
|
||||
Mmark // Support Mmark syntax, see https://mmark.nl/syntax
|
||||
Mmark // Support Mmark syntax, see https://mmark.miek.nl/post/syntax/
|
||||
|
||||
CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
|
||||
Autolink | Strikethrough | SpaceHeadings | HeadingIDs |
|
||||
@ -206,13 +206,13 @@ func (p *Parser) isFootnote(ref *reference) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
func (p *Parser) finalize(block ast.Node) {
|
||||
func (p *Parser) Finalize(block ast.Node) {
|
||||
p.tip = block.GetParent()
|
||||
}
|
||||
|
||||
func (p *Parser) addChild(node ast.Node) ast.Node {
|
||||
for !canNodeContain(p.tip, node) {
|
||||
p.finalize(p.tip)
|
||||
p.Finalize(p.tip)
|
||||
}
|
||||
ast.AppendChild(p.tip, node)
|
||||
p.tip = node
|
||||
@ -239,6 +239,18 @@ func canNodeContain(n ast.Node, v ast.Node) bool {
|
||||
_, ok := v.(*ast.TableCell)
|
||||
return ok
|
||||
}
|
||||
// for nodes implemented outside of ast package, allow them
|
||||
// to implement this logic via CanContain interface
|
||||
if o, ok := n.(ast.CanContain); ok {
|
||||
return o.CanContain(v)
|
||||
}
|
||||
// for container nodes outside of ast package default to true
|
||||
// because false is a bad default
|
||||
typ := fmt.Sprintf("%T", n)
|
||||
customNode := !strings.HasPrefix(typ, "*ast.")
|
||||
if customNode {
|
||||
return n.AsLeaf() == nil
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@ -248,7 +260,7 @@ func (p *Parser) closeUnmatchedBlocks() {
|
||||
}
|
||||
for p.oldTip != p.lastMatchedContainer {
|
||||
parent := p.oldTip.GetParent()
|
||||
p.finalize(p.oldTip)
|
||||
p.Finalize(p.oldTip)
|
||||
p.oldTip = parent
|
||||
}
|
||||
p.allClosed = true
|
||||
@ -273,10 +285,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.
|
||||
func (p *Parser) Parse(input []byte) ast.Node {
|
||||
p.block(input)
|
||||
// the code only works with Unix CR newlines so to make life easy for
|
||||
// callers normalize newlines
|
||||
input = NormalizeNewlines(input)
|
||||
|
||||
p.Block(input)
|
||||
// Walk the tree and finish up some of unfinished blocks
|
||||
for p.tip != nil {
|
||||
p.finalize(p.tip)
|
||||
p.Finalize(p.tip)
|
||||
}
|
||||
// Walk the tree again and process inline markdown in each block
|
||||
ast.WalkFunc(p.Doc, func(node ast.Node, entering bool) ast.WalkStatus {
|
||||
@ -322,8 +338,8 @@ func (p *Parser) parseRefsToAST() {
|
||||
IsFootnotesList: true,
|
||||
ListFlags: ast.ListTypeOrdered,
|
||||
}
|
||||
p.addBlock(&ast.Footnotes{})
|
||||
block := p.addBlock(list)
|
||||
p.AddBlock(&ast.Footnotes{})
|
||||
block := p.AddBlock(list)
|
||||
flags := ast.ListItemBeginningOfList
|
||||
// Note: this loop is intentionally explicit, not range-form. This is
|
||||
// because the body of the loop will append nested footnotes to p.notes and
|
||||
@ -338,7 +354,7 @@ func (p *Parser) parseRefsToAST() {
|
||||
listItem.RefLink = ref.link
|
||||
if ref.hasBlock {
|
||||
flags |= ast.ListItemContainsBlock
|
||||
p.block(ref.title)
|
||||
p.Block(ref.title)
|
||||
} else {
|
||||
p.Inline(block, ref.title)
|
||||
}
|
||||
@ -660,7 +676,7 @@ gatherLines:
|
||||
|
||||
// if it is an empty line, guess that it is part of this item
|
||||
// and move on to the next line
|
||||
if p.isEmpty(data[blockEnd:i]) > 0 {
|
||||
if IsEmpty(data[blockEnd:i]) > 0 {
|
||||
containsBlankLine = true
|
||||
blockEnd = i
|
||||
continue
|
||||
@ -883,3 +899,26 @@ func isListItem(d ast.Node) bool {
|
||||
_, ok := d.(*ast.ListItem)
|
||||
return ok
|
||||
}
|
||||
|
||||
func NormalizeNewlines(d []byte) []byte {
|
||||
wi := 0
|
||||
n := len(d)
|
||||
for i := 0; i < n; i++ {
|
||||
c := d[i]
|
||||
// 13 is CR
|
||||
if c != 13 {
|
||||
d[wi] = c
|
||||
wi++
|
||||
continue
|
||||
}
|
||||
// replace CR (mac / win) with LF (unix)
|
||||
d[wi] = 10
|
||||
wi++
|
||||
if i < n-1 && d[i+1] == 10 {
|
||||
// this was CRLF, so skip the LF
|
||||
i++
|
||||
}
|
||||
|
||||
}
|
||||
return d[:wi]
|
||||
}
|
||||
|
7
vendor/github.com/gomarkdown/markdown/todo.md
generated
vendored
7
vendor/github.com/gomarkdown/markdown/todo.md
generated
vendored
@ -1,7 +0,0 @@
|
||||
# Things to do
|
||||
|
||||
[ ] docs: add examples like https://godoc.org/github.com/dgrijalva/jwt-go (put in foo_example_test.go). Or see https://github.com/garyburd/redigo/blob/master/redis/zpop_example_test.go#L5 / https://godoc.org/github.com/garyburd/redigo/redis or https://godoc.org/github.com/go-redis/redis
|
||||
|
||||
[ ] figure out expandTabs and parser.TabSizeEight. Are those used?
|
||||
|
||||
[ ] SoftbreakData is not used
|
Reference in New Issue
Block a user