Implement source block results

To support code block directives like :exports none we need context - i.e. we
need to have the block and it's results at once and can't just render them
independently.
This commit is contained in:
Niklas Fasching 2020-04-17 14:53:46 +02:00
parent f6f4646d45
commit cd923ba41a
4 changed files with 31 additions and 5 deletions

View file

@ -10,6 +10,7 @@ type Block struct {
Name string Name string
Parameters []string Parameters []string
Children []Node Children []Node
Result Node
} }
type Result struct { type Result struct {
@ -58,7 +59,7 @@ func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) {
stop := func(d *Document, i int) bool { stop := func(d *Document, i int) bool {
return i >= len(d.tokens) || (d.tokens[i].kind == "endBlock" && d.tokens[i].content == name) return i >= len(d.tokens) || (d.tokens[i].kind == "endBlock" && d.tokens[i].content == name)
} }
block, i := Block{name, parameters, nil}, i+1 block, i := Block{name, parameters, nil, nil}, i+1
if isRawTextBlock(name) { if isRawTextBlock(name) {
rawText := "" rawText := ""
for ; !stop(d, i); i++ { for ; !stop(d, i); i++ {
@ -73,10 +74,26 @@ func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) {
block.Children = nodes block.Children = nodes
i += consumed i += consumed
} }
if i < len(d.tokens) && d.tokens[i].kind == "endBlock" && d.tokens[i].content == name { if i >= len(d.tokens) || d.tokens[i].kind != "endBlock" || d.tokens[i].content != name {
return i + 1 - start, block return 0, nil
} }
return 0, nil if name == "SRC" {
consumed, result := d.parseSrcBlockResult(i+1, parentStop)
block.Result = result
i += consumed
}
return i + 1 - start, block
}
func (d *Document) parseSrcBlockResult(i int, parentStop stopFn) (int, Node) {
start := i
for ; !parentStop(d, i) && d.tokens[i].kind == "text" && d.tokens[i].content == ""; i++ {
}
if parentStop(d, i) || d.tokens[i].kind != "result" {
return 0, nil
}
consumed, result := d.parseResult(i, parentStop)
return (i - start) + consumed, result
} }
func (d *Document) parseExample(i int, parentStop stopFn) (int, Node) { func (d *Document) parseExample(i int, parentStop stopFn) (int, Node) {

View file

@ -134,6 +134,10 @@ func (w *HTMLWriter) WriteBlock(b Block) {
w.WriteString(fmt.Sprintf(`<div class="%s-block">`, strings.ToLower(b.Name)) + "\n") w.WriteString(fmt.Sprintf(`<div class="%s-block">`, strings.ToLower(b.Name)) + "\n")
w.WriteString(content + "</div>\n") w.WriteString(content + "</div>\n")
} }
if b.Result != nil {
WriteNodes(w, b.Result)
}
} }
func (w *HTMLWriter) WriteResult(r Result) { WriteNodes(w, r.Node) } func (w *HTMLWriter) WriteResult(r Result) { WriteNodes(w, r.Node) }

View file

@ -150,7 +150,7 @@ func (d *Document) parseInclude(k Keyword) (int, Node) {
d.Log.Printf("Bad include %#v: %s", k, err) d.Log.Printf("Bad include %#v: %s", k, err)
return k return k
} }
return Block{strings.ToUpper(kind), []string{lang}, d.parseRawInline(string(bs))} return Block{strings.ToUpper(kind), []string{lang}, d.parseRawInline(string(bs)), nil}
} }
} }
return 1, Include{k, resolve} return 1, Include{k, resolve}

View file

@ -102,6 +102,11 @@ func (w *OrgWriter) WriteBlock(b Block) {
w.WriteString(w.indent) w.WriteString(w.indent)
} }
w.WriteString("#+END_" + b.Name + "\n") w.WriteString("#+END_" + b.Name + "\n")
if b.Result != nil {
w.WriteString("\n")
WriteNodes(w, b.Result)
}
} }
func (w *OrgWriter) WriteResult(r Result) { func (w *OrgWriter) WriteResult(r Result) {