Add go dependencies for mdtoc

This commit is contained in:
Manuel Alejandro de Brito Fontes 2019-07-21 14:00:47 -04:00
parent cb33c4ed26
commit 36959a4878
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
63 changed files with 12675 additions and 0 deletions

31
vendor/github.com/mmarkdown/mmark/LICENSE.txt generated vendored Normal file
View file

@ -0,0 +1,31 @@
Markdown is distributed under the Simplified BSD License:
Copyright © 2011 Russ Ross
Copyright © 2018 Krzysztof Kowalczyk
Copyright © 2018 Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with
the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

23
vendor/github.com/mmarkdown/mmark/mast/bibliography.go generated vendored Normal file
View file

@ -0,0 +1,23 @@
package mast
import (
"github.com/gomarkdown/markdown/ast"
"github.com/mmarkdown/mmark/mast/reference"
)
// Bibliography represents markdown bibliography node.
type Bibliography struct {
ast.Container
Type ast.CitationTypes
}
// BibliographyItem contains a single bibliography item.
type BibliographyItem struct {
ast.Leaf
Anchor []byte
Type ast.CitationTypes
Reference *reference.Reference // parsed reference XML
}

34
vendor/github.com/mmarkdown/mmark/mast/index.go generated vendored Normal file
View file

@ -0,0 +1,34 @@
package mast
import "github.com/gomarkdown/markdown/ast"
// DocumentIndex represents markdown document index node.
type DocumentIndex struct {
ast.Container
}
// IndexItem contains an index for the indices section.
type IndexItem struct {
ast.Container
*ast.Index
}
// IndexSubItem contains an sub item index for the indices section.
type IndexSubItem struct {
ast.Container
*ast.Index
}
// IndexLetter has the Letter of this index item.
type IndexLetter struct {
ast.Container
}
// IndexLink links to the index in the document.
type IndexLink struct {
*ast.Link
Primary bool
}

171
vendor/github.com/mmarkdown/mmark/mast/nodes.go generated vendored Normal file
View file

@ -0,0 +1,171 @@
package mast
import (
"bytes"
"sort"
"github.com/gomarkdown/markdown/ast"
)
// some extra functions for manipulation the AST
// MoveChilderen moves the children from a to b *and* make the parent of each point to b.
// Any children of b are obliterated.
func MoveChildren(a, b ast.Node) {
a.SetChildren(b.GetChildren())
b.SetChildren(nil)
for _, child := range a.GetChildren() {
child.SetParent(a)
}
}
// Some attribute helper functions.
// AttributeFromNode returns the attribute from the node, if it was there was one.
func AttributeFromNode(node ast.Node) *ast.Attribute {
if c := node.AsContainer(); c != nil && c.Attribute != nil {
return c.Attribute
}
if l := node.AsLeaf(); l != nil && l.Attribute != nil {
return l.Attribute
}
return nil
}
// AttributeInit will initialize an *Attribute on node if there wasn't one.
func AttributeInit(node ast.Node) {
if l := node.AsLeaf(); l != nil && l.Attribute == nil {
l.Attribute = &ast.Attribute{Attrs: make(map[string][]byte)}
return
}
if c := node.AsContainer(); c != nil && c.Attribute == nil {
c.Attribute = &ast.Attribute{Attrs: make(map[string][]byte)}
return
}
}
// DeleteAttribute delete the attribute under key from a.
func DeleteAttribute(node ast.Node, key string) {
a := AttributeFromNode(node)
if a == nil {
return
}
switch key {
case "id":
a.ID = nil
case "class":
// TODO
default:
delete(a.Attrs, key)
}
}
// SetAttribute sets the attribute under key to value.
func SetAttribute(node ast.Node, key string, value []byte) {
a := AttributeFromNode(node)
if a == nil {
return
}
switch key {
case "id":
a.ID = value
case "class":
// TODO
default:
a.Attrs[key] = value
}
}
// Attribute returns the attribute value under key. Use AttributeClass to retrieve
// a class.
func Attribute(node ast.Node, key string) []byte {
a := AttributeFromNode(node)
if a == nil {
return nil
}
switch key {
case "id":
return a.ID
case "class":
// use AttributeClass.
}
return a.Attrs[key]
}
func AttributeBytes(attr *ast.Attribute) []byte {
ret := &bytes.Buffer{}
ret.WriteByte('{')
if len(attr.ID) != 0 {
ret.WriteByte('#')
ret.Write(attr.ID)
}
for _, c := range attr.Classes {
if ret.Len() > 1 {
ret.WriteByte(' ')
}
ret.WriteByte('.')
ret.Write(c)
}
keys := []string{}
for k := range attr.Attrs {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if ret.Len() > 1 {
ret.WriteByte(' ')
}
ret.WriteString(k)
ret.WriteString(`="`)
ret.Write(attr.Attrs[k])
ret.WriteByte('"')
}
ret.WriteByte('}')
return ret.Bytes()
}
// AttributeClass returns true is class key is set.
func AttributeClass(node ast.Node, key string) bool {
a := AttributeFromNode(node)
if a == nil {
return false
}
for _, c := range a.Classes {
if string(c) == key {
return true
}
}
return false
}
// AttributeFilter runs the attribute on node through filter and only allows elements for which filter returns true.
func AttributeFilter(node ast.Node, filter func(key string) bool) {
a := AttributeFromNode(node)
if a == nil {
return
}
if !filter("id") {
a.ID = nil
}
if !filter("class") {
a.Classes = nil
}
for k, _ := range a.Attrs {
if !filter(k) {
delete(a.Attrs, k)
}
}
}
// FilterFunc checks if s is an allowed key in an attribute.
// If s is:
// "id" the ID should be checked
// "class" the classes should be allowed or disallowed
// any other string means checking the individual attributes.
// it returns true for elements that are allows, false otherwise.
type FilterFunc func(s string) bool

View file

@ -0,0 +1,71 @@
// Package reference defines the elements of a <reference> block.
package reference
import "encoding/xml"
// Author is the reference author.
type Author struct {
Fullname string `xml:"fullname,attr,omitempty"`
Initials string `xml:"initials,attr,omitempty"`
Surname string `xml:"surname,attr,omitempty"`
Role string `xml:"role,attr,omitempty"`
Organization *Organization `xml:"organization,omitempty"`
Address *Address `xml:"address,omitempty"`
}
type Organization struct {
Abbrev string `xml:"abbrev,attr,omitempty"`
Value string `xml:",chardata"`
}
// this is copied from ../title.go; it might make sense to unify them, both especially, it we
// want to allow reference to be given in TOML as well. See #55.
// Author denotes an RFC author.
// Address denotes the address of an RFC author.
type Address struct {
Phone string `xml:"phone,omitempty"`
Email string `xml:"email,omitempty"`
URI string `xml:"uri,omitempty"`
Postal AddressPostal `xml:"postal,omitempty"`
}
// AddressPostal denotes the postal address of an RFC author.
type AddressPostal struct {
PostalLine []string `xml:"postalline,omitempty"`
Streets []string `xml:"street,omitempty"`
Cities []string `xml:"city,omitempty"`
Codes []string `xml:"code,omitempty"`
Countries []string `xml:"country,omitempty"`
Regions []string `xml:"region,omitempty"`
}
// Date is the reference date.
type Date struct {
Year string `xml:"year,attr,omitempty"`
Month string `xml:"month,attr,omitempty"`
Day string `xml:"day,attr,omitempty"`
}
// Front the reference <front>.
type Front struct {
Title string `xml:"title"`
Authors []Author `xml:"author,omitempty"`
Date Date `xml:"date"`
}
// Format is the reference <format>. This is deprecated in RFC 7991, see Section 3.3.
type Format struct {
Type string `xml:"type,attr,omitempty"`
Target string `xml:"target,attr"`
}
// Reference is the entire <reference> structure.
type Reference struct {
XMLName xml.Name `xml:"reference"`
Anchor string `xml:"anchor,attr"`
Front Front `xml:"front"`
Format *Format `xml:"format,omitempty"`
Target string `xml:"target,attr"`
}

95
vendor/github.com/mmarkdown/mmark/mast/title.go generated vendored Normal file
View file

@ -0,0 +1,95 @@
package mast
import (
"time"
"github.com/gomarkdown/markdown/ast"
)
// Title represents the TOML encoded title block.
type Title struct {
ast.Leaf
*TitleData
Trigger string // either triggered by %%% or ---
}
// NewTitle returns a pointer to TitleData with some defaults set.
func NewTitle(trigger byte) *Title {
t := &Title{
TitleData: &TitleData{
Area: "Internet",
Ipr: "trust200902",
Consensus: true,
},
}
t.Trigger = string([]byte{trigger, trigger, trigger})
return t
}
const triggerDash = "---"
func (t *Title) IsTriggerDash() bool { return t.Trigger == triggerDash }
// TitleData holds all the elements of the title.
type TitleData struct {
Title string
Abbrev string
SeriesInfo SeriesInfo
Consensus bool
Ipr string // See https://tools.ietf.org/html/rfc7991#appendix-A.1
Obsoletes []int
Updates []int
SubmissionType string // IETF, IAB, IRTF or independent
Date time.Time
Area string
Workgroup string
Keyword []string
Author []Author
}
// SeriesInfo holds details on the Internet-Draft or RFC, see https://tools.ietf.org/html/rfc7991#section-2.47
type SeriesInfo struct {
Name string // name of the document, values are "RFC", "Internet-Draft", and "DOI"
Value string // either draft name, or number
Status string // The status of this document, values: "standard", "informational", "experimental", "bcp", "fyi", and "full-standard"
Stream string // "IETF" (default),"IAB", "IRTF" or "independent"
}
// Author denotes an RFC author.
type Author struct {
Initials string
Surname string
Fullname string
Organization string
OrganizationAbbrev string `toml:"abbrev"`
Role string
ASCII string
Address Address
}
// Address denotes the address of an RFC author.
type Address struct {
Phone string
Email string
URI string
Postal AddressPostal
}
// AddressPostal denotes the postal address of an RFC author.
type AddressPostal struct {
Street string
City string
Code string
Country string
Region string
PostalLine []string
// Plurals when these need to be specified multiple times.
Streets []string
Cities []string
Codes []string
Countries []string
Regions []string
}

View file

@ -0,0 +1,184 @@
package mparser
import (
"bytes"
"encoding/xml"
"log"
"github.com/gomarkdown/markdown/ast"
"github.com/mmarkdown/mmark/mast"
"github.com/mmarkdown/mmark/mast/reference"
)
// CitationToBibliography walks the AST and gets all the citations on HTML blocks and groups them into
// normative and informative references.
func CitationToBibliography(doc ast.Node) (normative ast.Node, informative ast.Node) {
seen := map[string]*mast.BibliographyItem{}
raw := map[string][]byte{}
// Gather all citations.
// Gather all reference HTML Blocks to see if we have XML we can output.
ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus {
switch c := node.(type) {
case *ast.Citation:
for i, d := range c.Destination {
if _, ok := seen[string(bytes.ToLower(d))]; ok {
continue
}
ref := &mast.BibliographyItem{}
ref.Anchor = d
ref.Type = c.Type[i]
seen[string(d)] = ref
}
case *ast.HTMLBlock:
anchor := anchorFromReference(c.Literal)
if anchor != nil {
raw[string(bytes.ToLower(anchor))] = c.Literal
}
}
return ast.GoToNext
})
for _, r := range seen {
// If we have a reference anchor and the raw XML add that here.
if raw, ok := raw[string(bytes.ToLower(r.Anchor))]; ok {
var x reference.Reference
if e := xml.Unmarshal(raw, &x); e != nil {
log.Printf("Failed to unmarshal reference: %q: %s", r.Anchor, e)
continue
}
r.Reference = &x
}
switch r.Type {
case ast.CitationTypeInformative:
if informative == nil {
informative = &mast.Bibliography{Type: ast.CitationTypeInformative}
}
ast.AppendChild(informative, r)
case ast.CitationTypeSuppressed:
fallthrough
case ast.CitationTypeNormative:
if normative == nil {
normative = &mast.Bibliography{Type: ast.CitationTypeNormative}
}
ast.AppendChild(normative, r)
}
}
return normative, informative
}
// NodeBackMatter is the place where we should inject the bibliography
func NodeBackMatter(doc ast.Node) ast.Node {
var matter ast.Node
ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus {
if mat, ok := node.(*ast.DocumentMatter); ok {
if mat.Matter == ast.DocumentMatterBack {
matter = mat
return ast.Terminate
}
}
return ast.GoToNext
})
return matter
}
// Parse '<reference anchor='CBR03' target=''>' and return the string after anchor= is the ID for the reference.
func anchorFromReference(data []byte) []byte {
if !bytes.HasPrefix(data, []byte("<reference ")) {
return nil
}
anchor := bytes.Index(data, []byte("anchor="))
if anchor < 0 {
return nil
}
beg := anchor + 7
if beg >= len(data) {
return nil
}
quote := data[beg]
i := beg + 1
// scan for an end-of-reference marker
for i < len(data) && data[i] != quote {
i++
}
// no end-of-reference marker
if i >= len(data) {
return nil
}
return data[beg+1 : i]
}
// ReferenceHook is the hook used to parse reference nodes.
func ReferenceHook(data []byte) (ast.Node, []byte, int) {
ref, ok := IsReference(data)
if !ok {
return nil, nil, 0
}
node := &ast.HTMLBlock{}
node.Literal = fmtReference(ref)
return node, nil, len(ref)
}
// IfReference returns wether data contains a reference.
func IsReference(data []byte) ([]byte, bool) {
if !bytes.HasPrefix(data, []byte("<reference ")) {
return nil, false
}
i := 12
// scan for an end-of-reference marker, across lines if necessary
for i < len(data) &&
!(data[i-12] == '<' && data[i-11] == '/' && data[i-10] == 'r' && data[i-9] == 'e' && data[i-8] == 'f' &&
data[i-7] == 'e' && data[i-6] == 'r' && data[i-5] == 'e' &&
data[i-4] == 'n' && data[i-3] == 'c' && data[i-2] == 'e' &&
data[i-1] == '>') {
i++
}
// no end-of-reference marker
if i > len(data) {
return nil, false
}
return data[:i], true
}
func fmtReference(data []byte) []byte {
var x reference.Reference
if e := xml.Unmarshal(data, &x); e != nil {
return data
}
out, e := xml.MarshalIndent(x, "", " ")
if e != nil {
return data
}
return out
}
// AddBibliography adds the bibliography to the document. It will be
// added just after the backmatter node. If that node can't be found this
// function returns false and does nothing.
func AddBibliography(doc ast.Node) bool {
where := NodeBackMatter(doc)
if where == nil {
return false
}
norm, inform := CitationToBibliography(doc)
if norm != nil {
ast.AppendChild(where, norm)
}
if inform != nil {
ast.AppendChild(where, inform)
}
return (norm != nil) || (inform != nil)
}

View file

@ -0,0 +1,11 @@
package mparser
import (
"github.com/gomarkdown/markdown/parser"
)
// Extensions is the default set of extensions mmark requires.
var Extensions = parser.Tables | parser.FencedCode | parser.Autolink | parser.Strikethrough |
parser.SpaceHeadings | parser.HeadingIDs | parser.BackslashLineBreak | parser.SuperSubscript |
parser.DefinitionLists | parser.MathJax | parser.AutoHeadingIDs | parser.Footnotes |
parser.Strikethrough | parser.OrderedListStart | parser.Attributes | parser.Mmark | parser.Includes

59
vendor/github.com/mmarkdown/mmark/mparser/hook.go generated vendored Normal file
View file

@ -0,0 +1,59 @@
package mparser
import (
"io/ioutil"
"log"
"path/filepath"
"github.com/gomarkdown/markdown/ast"
"github.com/gomarkdown/markdown/parser"
)
var UnsafeInclude parser.Flags = 1 << 3
// Hook will call both TitleHook and ReferenceHook.
func Hook(data []byte) (ast.Node, []byte, int) {
n, b, i := TitleHook(data)
if n != nil {
return n, b, i
}
return ReferenceHook(data)
}
// ReadInclude is the hook to read includes.
// Its supports the following options for address.
//
// 4,5 - line numbers separated by commas
// N, - line numbers, end not specified, read until the end.
// /start/,/end/ - regexp separated by commas
// optional a prefix="" string.
func (i Initial) ReadInclude(from, file string, address []byte) []byte {
path := i.path(from, file)
if i.Flags&UnsafeInclude == 0 {
if ok := i.pathAllowed(path); !ok {
log.Printf("Failure to read: %q: path is not on or below %q", path, i.i)
return nil
}
}
data, err := ioutil.ReadFile(path)
if err != nil {
log.Printf("Failure to read: %q (from %q)", err, filepath.Join(from, "*"))
return nil
}
data, err = parseAddress(address, data)
if err != nil {
log.Printf("Failure to parse address for %q: %q (from %q)", path, err, filepath.Join(from, "*"))
return nil
}
if len(data) == 0 {
return data
}
if data[len(data)-1] != '\n' {
data = append(data, '\n')
}
return data
}

251
vendor/github.com/mmarkdown/mmark/mparser/include.go generated vendored Normal file
View file

@ -0,0 +1,251 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Adapted for mmark, by Miek Gieben, 2015.
// Adapted for mmark2 (fastly simplified and features removed), 2018.
package mparser
import (
"bytes"
"errors"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/gomarkdown/markdown/parser"
)
// Initial is the initial file we are working on, empty for stdin and adjusted is we we have an absolute or relative file.
type Initial struct {
Flags parser.Flags
i string
}
// NewInitial returns an initialized Initial.
func NewInitial(s string) Initial {
if path.IsAbs(s) {
return Initial{i: path.Dir(s)}
}
cwd, _ := os.Getwd()
if s == "" {
return Initial{i: cwd}
}
return Initial{i: path.Dir(filepath.Join(cwd, s))}
}
// path returns the full path we should use according to from, file and initial.
func (i Initial) path(from, file string) string {
if path.IsAbs(file) {
return file
}
if path.IsAbs(from) {
filepath.Join(from, file)
}
f1 := filepath.Join(i.i, from)
return filepath.Join(f1, file)
}
// pathAllowed returns true is file is on the same level or below the initial file.
func (i Initial) pathAllowed(file string) bool {
x, err := filepath.Rel(i.i, file)
if err != nil {
return false
}
return !strings.Contains(x, "..")
}
// parseAddress parses a code address directive and returns the bytes or an error.
func parseAddress(addr []byte, data []byte) ([]byte, error) {
bytes.TrimSpace(addr)
if len(addr) == 0 {
return data, nil
}
// check for prefix, either as ;prefix, prefix; or just standalone prefix.
var prefix []byte
if x := bytes.Index(addr, []byte("prefix=")); x >= 0 {
if x+1 > len(addr) {
return nil, fmt.Errorf("invalid prefix in address specification: %s", addr)
}
start := x + len("prefix=")
quote := addr[start]
if quote != '\'' && quote != '"' {
return nil, fmt.Errorf("invalid prefix in address specification: %s", addr)
}
end := SkipUntilChar(addr, start+1, quote)
prefix = addr[start+1 : end]
if len(prefix) == 0 {
return nil, fmt.Errorf("invalid prefix in address specification: %s", addr)
}
addr = append(addr[:x], addr[end+1:]...)
addr = bytes.Replace(addr, []byte(";"), []byte(""), 1)
if len(addr) == 0 {
data = addPrefix(data, prefix)
return data, nil
}
}
lo, hi, err := addrToByteRange(addr, data)
if err != nil {
return nil, err
}
// Acme pattern matches can stop mid-line,
// so run to end of line in both directions if not at line start/end.
for lo > 0 && data[lo-1] != '\n' {
lo--
}
if hi > 0 {
for hi < len(data) && data[hi-1] != '\n' {
hi++
}
}
data = data[lo:hi]
if prefix != nil {
data = addPrefix(data, prefix)
}
return data, nil
}
// addrToByteRange evaluates the given address. It returns the start and end index of the data we should return.
// Supported syntax: N, M or /start/, /end/ .
func addrToByteRange(addr, data []byte) (lo, hi int, err error) {
chunk := bytes.Split(addr, []byte(","))
if len(chunk) != 2 {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
left := bytes.TrimSpace(chunk[0])
right := bytes.TrimSpace(chunk[1])
if len(left) == 0 {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
if len(right) == 0 {
// open ended right term
}
if left[0] == '/' { //regular expression
if left[len(left)-1] != '/' {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
if right[0] != '/' {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
if right[len(right)-1] != '/' {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
lo, hi, err = addrRegexp(data, string(left[1:len(left)-1]), string(right[1:len(right)-1]))
if err != nil {
return 0, 0, err
}
} else {
lo, err = strconv.Atoi(string(left))
if err != nil {
return 0, 0, err
}
i, j := 0, 0
for i < len(data) {
if data[i] == '\n' {
j++
if j >= lo {
break
}
}
i++
}
lo = i
if len(right) == 0 {
hi = len(data)
goto End
}
hi, err = strconv.Atoi(string(right))
if err != nil {
return 0, 0, err
}
i, j = 0, 0
for i < len(data) {
if data[i] == '\n' {
j++
if j+1 >= hi {
break
}
}
i++
}
hi = i
}
End:
if lo > hi {
return 0, 0, fmt.Errorf("invalid address specification: %s", addr)
}
return lo, hi, nil
}
// addrRegexp searches for pattern start and pattern end
func addrRegexp(data []byte, start, end string) (int, int, error) {
start = "(?m:" + start + ")" // match through newlines
reStart, err := regexp.Compile(start)
if err != nil {
return 0, 0, err
}
end = "(?m:" + end + ")"
reEnd, err := regexp.Compile(end)
if err != nil {
return 0, 0, err
}
m := reStart.FindIndex(data)
if len(m) == 0 {
return 0, 0, errors.New("no match for " + start)
}
lo := m[0]
m = reEnd.FindIndex(data[lo:]) // start *from* lo
if len(m) == 0 {
return 0, 0, errors.New("no match for " + end)
}
hi := m[0]
return lo, hi, nil
}
func SkipUntilChar(data []byte, i int, c byte) int {
n := len(data)
for i < n && data[i] != c {
i++
}
return i
}
func addPrefix(data, prefix []byte) []byte {
b := &bytes.Buffer{}
b.Write(prefix)
// assured that data ends in newline
i := 0
for i < len(data)-1 {
b.WriteByte(data[i])
if data[i] == '\n' {
b.Write(prefix)
}
i++
}
return b.Bytes()
}

111
vendor/github.com/mmarkdown/mmark/mparser/index.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
package mparser
import (
"bytes"
"fmt"
"sort"
"github.com/gomarkdown/markdown/ast"
"github.com/mmarkdown/mmark/mast"
)
// IndexToDocumentIndex crawls the entire doc searching for indices, it will then return
// an mast.DocumentIndex that contains a tree:
//
// IndexLetter
// - IndexItem
// - IndexLink
// - IndexSubItem
// - IndexLink
// - IndexLink
//
// Which can then be rendered by the renderer.
func IndexToDocumentIndex(doc ast.Node) *mast.DocumentIndex {
main := map[string]*mast.IndexItem{}
subitem := map[string][]*mast.IndexSubItem{} // gather these so we can add them in one swoop at the end
// Gather all indexes.
ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus {
switch i := node.(type) {
case *ast.Index:
item := string(i.Item)
if _, ok := main[item]; !ok {
main[item] = &mast.IndexItem{Index: i}
}
// only the main item
if i.Subitem == nil {
ast.AppendChild(main[item], newLink(i.ID, len(main[item].GetChildren()), i.Primary))
return ast.GoToNext
}
// check if we already have a child with the subitem and then just add the link
for _, sub := range subitem[item] {
if bytes.Compare(sub.Subitem, i.Subitem) == 0 {
ast.AppendChild(sub, newLink(i.ID, len(sub.GetChildren()), i.Primary))
return ast.GoToNext
}
}
sub := &mast.IndexSubItem{Index: i}
ast.AppendChild(sub, newLink(i.ID, len(subitem[item]), i.Primary))
subitem[item] = append(subitem[item], sub)
}
return ast.GoToNext
})
if len(main) == 0 {
return nil
}
// Now add a subitem children to the correct main item.
for k, sub := range subitem {
// sort sub here ideally
for j := range sub {
ast.AppendChild(main[k], sub[j])
}
}
keys := []string{}
for k := range main {
keys = append(keys, k)
}
sort.Strings(keys)
letters := []*mast.IndexLetter{}
var prevLetter byte
var il *mast.IndexLetter
for _, k := range keys {
letter := k[0]
if letter != prevLetter {
il = &mast.IndexLetter{}
il.Literal = []byte{letter}
letters = append(letters, il)
}
ast.AppendChild(il, main[k])
prevLetter = letter
}
docIndex := &mast.DocumentIndex{}
for i := range letters {
ast.AppendChild(docIndex, letters[i])
}
return docIndex
}
func newLink(id string, number int, primary bool) *mast.IndexLink {
link := &ast.Link{Destination: []byte(id)}
il := &mast.IndexLink{Link: link, Primary: primary}
il.Literal = []byte(fmt.Sprintf("%d", number))
return il
}
// AddIndex adds an index to the end of the current document. If not indices can be found
// this returns false and no index will be added.
func AddIndex(doc ast.Node) bool {
idx := IndexToDocumentIndex(doc)
if idx == nil {
return false
}
ast.AppendChild(doc, idx)
return true
}

57
vendor/github.com/mmarkdown/mmark/mparser/title.go generated vendored Normal file
View file

@ -0,0 +1,57 @@
package mparser
import (
"log"
"github.com/BurntSushi/toml"
"github.com/gomarkdown/markdown/ast"
"github.com/mmarkdown/mmark/mast"
)
// TitleHook will parse a title and returns it. The start and ending can
// be signalled with %%% or --- (the later to more inline with Hugo and other markdown dialects.
func TitleHook(data []byte) (ast.Node, []byte, int) {
i := 0
if len(data) < 3 {
return nil, nil, 0
}
c := data[i] // first char can either be % or -
if c != '%' && c != '-' {
return nil, nil, 0
}
if data[i] != c || data[i+1] != c || data[i+2] != c {
return nil, nil, 0
}
i += 3
beg := i
found := false
// search for end.
for i < len(data) {
if data[i] == c && data[i+1] == c && data[i+2] == c {
found = true
break
}
i++
}
if !found {
return nil, nil, 0
}
node := mast.NewTitle(c)
buf := data[beg:i]
if c == '-' {
node.Content = buf
return node, nil, i + 3
}
if _, err := toml.Decode(string(buf), node.TitleData); err != nil {
log.Printf("Failure parsing title block: %s", err)
}
node.Content = buf
return node, nil, i + 3
}