summaryrefslogtreecommitdiffstats
path: root/vendor/gitlab.com/golang-commonmark/markdown/parser_block.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gitlab.com/golang-commonmark/markdown/parser_block.go')
-rw-r--r--vendor/gitlab.com/golang-commonmark/markdown/parser_block.go159
1 files changed, 159 insertions, 0 deletions
diff --git a/vendor/gitlab.com/golang-commonmark/markdown/parser_block.go b/vendor/gitlab.com/golang-commonmark/markdown/parser_block.go
new file mode 100644
index 00000000..8a6ee1ad
--- /dev/null
+++ b/vendor/gitlab.com/golang-commonmark/markdown/parser_block.go
@@ -0,0 +1,159 @@
+// Copyright 2015 The Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package markdown
+
+import (
+ "bytes"
+ "unicode/utf8"
+)
+
+type ParserBlock struct{}
+
+type BlockRule func(*StateBlock, int, int, bool) bool
+
+var blockRules []BlockRule
+
+var nl = []byte{'\n'}
+
+func normalizeNewlines(src []byte) ([]byte, int) {
+ if bytes.IndexByte(src, '\r') == -1 {
+ return src, bytes.Count(src, nl)
+ }
+ n := 0
+ buf := make([]byte, 0, len(src))
+ for i := 0; i < len(src); i++ {
+ switch ch := src[i]; ch {
+ case '\n':
+ n++
+ buf = append(buf, '\n')
+ case '\r':
+ buf = append(buf, '\n')
+ n++
+ if i < len(src)-1 && src[i+1] == '\n' {
+ i++
+ }
+ default:
+ buf = append(buf, ch)
+ }
+ }
+ return buf, n
+}
+
+func (b ParserBlock) Parse(src []byte, md *Markdown, env *Environment) []Token {
+ src, n := normalizeNewlines(src)
+ if len(src) == 0 || src[len(src)-1] != '\n' {
+ n++
+ }
+ n++
+
+ indentFound := false
+ start := 0
+ indent := 0
+ offset := 0
+
+ mem := make([]int, 0, n*5)
+ bMarks := mem[0:0:n]
+ eMarks := mem[n : n : n*2]
+ tShift := mem[n*2 : n*2 : n*3]
+ sCount := mem[n*3 : n*3 : n*4]
+ bsCount := mem[n*4 : n*4 : n*5]
+
+ _, lastRuneLen := utf8.DecodeLastRune(src)
+ lastRunePos := len(src) - lastRuneLen
+ for pos, r := range string(src) {
+ if !indentFound {
+ if runeIsSpace(r) {
+ indent++
+ if r == '\t' {
+ offset += 4 - offset%4
+ } else {
+ offset++
+ }
+ continue
+ }
+ indentFound = true
+ }
+
+ if r == '\n' || pos == lastRunePos {
+ if r != '\n' {
+ pos = len(src)
+ }
+ bMarks = append(bMarks, start)
+ eMarks = append(eMarks, pos)
+ tShift = append(tShift, indent)
+ sCount = append(sCount, offset)
+ bsCount = append(bsCount, 0)
+
+ indentFound = false
+ indent = 0
+ offset = 0
+ start = pos + 1
+ }
+ }
+
+ bMarks = append(bMarks, len(src))
+ eMarks = append(eMarks, len(src))
+ tShift = append(tShift, 0)
+ sCount = append(sCount, 0)
+ bsCount = append(bsCount, 0)
+
+ var s StateBlock
+ s.BMarks = bMarks
+ s.EMarks = eMarks
+ s.TShift = tShift
+ s.SCount = sCount
+ s.BSCount = bsCount
+ s.LineMax = n - 1
+ s.Src = string(src)
+ s.Md = md
+ s.Env = env
+
+ b.Tokenize(&s, s.Line, s.LineMax)
+
+ return s.Tokens
+}
+
+func (ParserBlock) Tokenize(s *StateBlock, startLine, endLine int) {
+ line := startLine
+ hasEmptyLines := false
+ maxNesting := s.Md.MaxNesting
+
+ for line < endLine {
+ line = s.SkipEmptyLines(line)
+ s.Line = line
+ if line >= endLine {
+ break
+ }
+
+ if s.SCount[line] < s.BlkIndent {
+ break
+ }
+
+ if s.Level >= maxNesting {
+ s.Line = endLine
+ break
+ }
+
+ for _, r := range blockRules {
+ if r(s, line, endLine, false) {
+ break
+ }
+ }
+
+ s.Tight = !hasEmptyLines
+
+ if s.IsLineEmpty(s.Line - 1) {
+ hasEmptyLines = true
+ }
+
+ line = s.Line
+
+ if line < endLine && s.IsLineEmpty(line) {
+ hasEmptyLines = true
+ line++
+ s.Line = line
+ }
+ }
+}