Convert panics to errors for public interface
This commit is contained in:
parent
f28f400d7e
commit
04df30a7b5
5 changed files with 52 additions and 15 deletions
11
main.go
11
main.go
|
@ -25,19 +25,22 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
r, out := bytes.NewReader(bs), ""
|
r, out, err := bytes.NewReader(bs), "", nil
|
||||||
switch strings.ToLower(os.Args[2]) {
|
switch strings.ToLower(os.Args[2]) {
|
||||||
case "org":
|
case "org":
|
||||||
out = org.NewDocument().Parse(r).Write(org.NewOrgWriter()).String()
|
out, err = org.NewDocument().Parse(r).Write(org.NewOrgWriter())
|
||||||
case "html":
|
case "html":
|
||||||
out = org.NewDocument().Parse(r).Write(org.NewHTMLWriter()).String()
|
out, err = org.NewDocument().Parse(r).Write(org.NewHTMLWriter())
|
||||||
case "html-chroma":
|
case "html-chroma":
|
||||||
writer := org.NewHTMLWriter()
|
writer := org.NewHTMLWriter()
|
||||||
writer.HighlightCodeBlock = highlightCodeBlock
|
writer.HighlightCodeBlock = highlightCodeBlock
|
||||||
out = org.NewDocument().Parse(r).Write(writer).String()
|
out, err = org.NewDocument().Parse(r).Write(writer)
|
||||||
default:
|
default:
|
||||||
log.Fatal("Unsupported output format")
|
log.Fatal("Unsupported output format")
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
log.Print(out)
|
log.Print(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Document struct {
|
type Document struct {
|
||||||
|
Path string
|
||||||
tokens []token
|
tokens []token
|
||||||
Nodes []Node
|
Nodes []Node
|
||||||
Footnotes *Footnotes
|
Footnotes *Footnotes
|
||||||
|
@ -17,6 +18,7 @@ type Document struct {
|
||||||
AutoLink bool
|
AutoLink bool
|
||||||
BufferSettings map[string]string
|
BufferSettings map[string]string
|
||||||
DefaultSettings map[string]string
|
DefaultSettings map[string]string
|
||||||
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
|
@ -77,24 +79,45 @@ func NewDocument() *Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) Write(w Writer) Writer {
|
func (d *Document) Write(w Writer) (out string, err error) {
|
||||||
if d.Nodes == nil {
|
defer func() {
|
||||||
panic("cannot Write() empty document: you must call Parse() first")
|
if recovered := recover(); recovered != nil {
|
||||||
|
err = fmt.Errorf("could not write output: %s", recovered)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if d.Error != nil {
|
||||||
|
return "", d.Error
|
||||||
|
} else if d.Nodes == nil {
|
||||||
|
return "", fmt.Errorf("could not write output: parse was not called")
|
||||||
}
|
}
|
||||||
w.before(d)
|
w.before(d)
|
||||||
w.writeNodes(d.Nodes...)
|
w.writeNodes(d.Nodes...)
|
||||||
w.after(d)
|
w.after(d)
|
||||||
return w
|
return w.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) Parse(input io.Reader) *Document {
|
func (d *Document) Parse(input io.Reader) *Document {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
d.Error = fmt.Errorf("could not parse input: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if d.tokens != nil {
|
||||||
|
d.Error = fmt.Errorf("parse was called multiple times")
|
||||||
|
}
|
||||||
d.tokenize(input)
|
d.tokenize(input)
|
||||||
_, nodes := d.parseMany(0, func(d *Document, i int) bool { return !(i < len(d.tokens)) })
|
_, nodes := d.parseMany(0, func(d *Document, i int) bool { return !(i < len(d.tokens)) })
|
||||||
d.Nodes = nodes
|
d.Nodes = nodes
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) FrontMatter(input io.Reader, f func(string, string) interface{}) map[string]interface{} {
|
func (d *Document) FrontMatter(input io.Reader, f func(string, string) interface{}) (_ map[string]interface{}, err error) {
|
||||||
|
defer func() {
|
||||||
|
d.tokens = nil
|
||||||
|
if recovered := recover(); recovered != nil {
|
||||||
|
err = fmt.Errorf("could not parse input: %s", recovered)
|
||||||
|
}
|
||||||
|
}()
|
||||||
d.tokenize(input)
|
d.tokenize(input)
|
||||||
d.parseMany(0, func(d *Document, i int) bool {
|
d.parseMany(0, func(d *Document, i int) bool {
|
||||||
if !(i < len(d.tokens)) {
|
if !(i < len(d.tokens)) {
|
||||||
|
@ -107,7 +130,7 @@ func (d *Document) FrontMatter(input io.Reader, f func(string, string) interface
|
||||||
for k, v := range d.BufferSettings {
|
for k, v := range d.BufferSettings {
|
||||||
frontMatter[k] = f(k, v)
|
frontMatter[k] = f(k, v)
|
||||||
}
|
}
|
||||||
return frontMatter
|
return frontMatter, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) tokenize(input io.Reader) {
|
func (d *Document) tokenize(input io.Reader) {
|
||||||
|
@ -117,7 +140,7 @@ func (d *Document) tokenize(input io.Reader) {
|
||||||
d.tokens = append(d.tokens, tokenize(scanner.Text()))
|
d.tokens = append(d.tokens, tokenize(scanner.Text()))
|
||||||
}
|
}
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
panic(err)
|
d.Error = fmt.Errorf("could not tokenize input: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,11 @@ var frontMatterTests = []frontMatterTest{
|
||||||
|
|
||||||
func TestParseFrontMatter(t *testing.T) {
|
func TestParseFrontMatter(t *testing.T) {
|
||||||
for _, test := range frontMatterTests {
|
for _, test := range frontMatterTests {
|
||||||
actual := NewDocument().FrontMatter(strings.NewReader(test.input), test.handler)
|
actual, err := NewDocument().FrontMatter(strings.NewReader(test.input), test.handler)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s\n got error: %s", test.name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !reflect.DeepEqual(test.expected, actual) {
|
if !reflect.DeepEqual(test.expected, actual) {
|
||||||
t.Errorf("%s\n got: %#v\nexpected: %#v\n%s'", test.name, actual, test.expected, test.input)
|
t.Errorf("%s\n got: %#v\nexpected: %#v\n%s'", test.name, actual, test.expected, test.input)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,12 @@ import (
|
||||||
func TestHTMLWriter(t *testing.T) {
|
func TestHTMLWriter(t *testing.T) {
|
||||||
for _, path := range orgTestFiles() {
|
for _, path := range orgTestFiles() {
|
||||||
reader, writer := strings.NewReader(fileString(path)), NewHTMLWriter()
|
reader, writer := strings.NewReader(fileString(path)), NewHTMLWriter()
|
||||||
actual := NewDocument().Parse(reader).Write(writer).String()
|
actual, err := NewDocument().Parse(reader).Write(writer)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s\n got error: %s", path, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
expected := fileString(path[:len(path)-len(".org")] + ".html")
|
expected := fileString(path[:len(path)-len(".org")] + ".html")
|
||||||
|
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
t.Errorf("%s:\n%s'", path, diff(actual, expected))
|
t.Errorf("%s:\n%s'", path, diff(actual, expected))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,7 +14,11 @@ func TestOrgWriter(t *testing.T) {
|
||||||
for _, path := range orgTestFiles() {
|
for _, path := range orgTestFiles() {
|
||||||
expected := fileString(path)
|
expected := fileString(path)
|
||||||
reader, writer := strings.NewReader(expected), NewOrgWriter()
|
reader, writer := strings.NewReader(expected), NewOrgWriter()
|
||||||
actual := NewDocument().Parse(reader).Write(writer).String()
|
actual, err := NewDocument().Parse(reader).Write(writer)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s\n got error: %s", path, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
t.Errorf("%s:\n%s'", path, diff(actual, expected))
|
t.Errorf("%s:\n%s'", path, diff(actual, expected))
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue