Commit 00997db5 authored by Matthew Holt's avatar Matthew Holt

markdown: Fix large markdown files that got truncated

parent a74b20f2
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
...@@ -150,6 +151,7 @@ func (y *YAMLMetadataParser) Parse(b []byte) ([]byte, error) { ...@@ -150,6 +151,7 @@ func (y *YAMLMetadataParser) Parse(b []byte) ([]byte, error) {
if err != nil { if err != nil {
return markdown, err return markdown, err
} }
m := make(map[string]interface{}) m := make(map[string]interface{})
if err := yaml.Unmarshal(b, &m); err != nil { if err := yaml.Unmarshal(b, &m); err != nil {
return markdown, err return markdown, err
...@@ -187,52 +189,46 @@ func (y *YAMLMetadataParser) Closing() []byte { ...@@ -187,52 +189,46 @@ func (y *YAMLMetadataParser) Closing() []byte {
return []byte("---") return []byte("---")
} }
// extractMetadata extracts metadata content from a page. // extractMetadata separates metadata content from from markdown content in b.
// it returns the metadata, the remaining bytes (markdown), // It returns the metadata, the remaining bytes (markdown), and an error, if any.
// and an error if any.
// Useful for MetadataParser with defined identifiers (YAML, TOML)
func extractMetadata(parser MetadataParser, b []byte) (metadata []byte, markdown []byte, err error) { func extractMetadata(parser MetadataParser, b []byte) (metadata []byte, markdown []byte, err error) {
b = bytes.TrimSpace(b) b = bytes.TrimSpace(b)
reader := bytes.NewBuffer(b) reader := bufio.NewReader(bytes.NewBuffer(b))
scanner := bufio.NewScanner(reader)
// Read first line // Read first line, which should indicate metadata or not
if !scanner.Scan() { line, err := reader.ReadBytes('\n')
// if no line is read, if err != nil || !bytes.Equal(bytes.TrimSpace(line), parser.Opening()) {
// assume metadata not present return nil, b, fmt.Errorf("first line missing expected metadata identifier")
return nil, b, nil
}
line := bytes.TrimSpace(scanner.Bytes())
if !bytes.Equal(line, parser.Opening()) {
return nil, b, fmt.Errorf("wrong identifier")
} }
// buffer for metadata contents // buffer for metadata contents
buf := bytes.Buffer{} metaBuf := bytes.Buffer{}
// Read remaining lines until closing identifier is found // Read remaining lines until closing identifier is found
for scanner.Scan() { for {
line := scanner.Bytes() line, err := reader.ReadBytes('\n')
if err != nil {
if err == io.EOF {
// no closing metadata identifier found
return nil, nil, fmt.Errorf("metadata not closed ('%s' not found)", parser.Closing())
}
return nil, nil, err
}
// if closing identifier found // if closing identifier found, the remaining bytes must be markdown content
if bytes.Equal(bytes.TrimSpace(line), parser.Closing()) { if bytes.Equal(bytes.TrimSpace(line), parser.Closing()) {
break
// get the scanner to return remaining bytes
scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
return len(data), data, nil
})
// scan the remaining bytes
scanner.Scan()
return buf.Bytes(), scanner.Bytes(), nil
} }
buf.Write(line)
buf.WriteString("\r\n") metaBuf.Write(line)
metaBuf.WriteString("\r\n")
} }
// closing identifier not found // By now, the rest of the buffer contains markdown content
return buf.Bytes(), nil, fmt.Errorf("metadata not closed. '%v' not found", string(parser.Closing())) contentBuf := new(bytes.Buffer)
io.Copy(contentBuf, reader)
return metaBuf.Bytes(), contentBuf.Bytes(), nil
} }
// findParser finds the parser using line that contains opening identifier // findParser finds the parser using line that contains opening identifier
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment