Refactor keyword parsing/rendering & add support for ATTR_HTML

This commit is contained in:
Niklas Fasching 2018-12-11 17:30:02 +01:00
parent a859264420
commit 81f74f4ad9
9 changed files with 169 additions and 76 deletions

View file

@ -1,6 +1,7 @@
package org
import (
"encoding/csv"
"regexp"
"strings"
)
@ -12,14 +13,18 @@ type Keyword struct {
type NodeWithMeta struct {
Node Node
Meta map[string]string
Meta Metadata
}
type Metadata struct {
Caption [][]Node
HTMLAttributes [][]string
}
type Comment struct{ Content string }
var keywordRegexp = regexp.MustCompile(`^(\s*)#\+([^:]+):(\s+(.*)|(\s*)$)`)
var commentRegexp = regexp.MustCompile(`^(\s*)#(.*)`)
var affiliatedKeywordRegexp = regexp.MustCompile(`^(CAPTION)$`)
func lexKeywordOrComment(line string) (token, bool) {
if m := keywordRegexp.FindStringSubmatch(line); m != nil {
@ -30,47 +35,44 @@ func lexKeywordOrComment(line string) (token, bool) {
return nilToken, false
}
func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) {
k := parseKeyword(d.tokens[i])
if affiliatedKeywordRegexp.MatchString(k.Key) {
consumed, node := d.parseAffiliated(i, stop)
if consumed != 0 {
return consumed, node
}
} else {
d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n")
}
return 1, k
}
func (d *Document) parseComment(i int, stop stopFn) (int, Node) {
return 1, Comment{d.tokens[i].content}
}
func (d *Document) parseAffiliated(i int, stop stopFn) (int, Node) {
start, meta := i, map[string]string{}
for ; !stop(d, i) && d.tokens[i].kind == "keyword"; i++ {
k := parseKeyword(d.tokens[i])
if !affiliatedKeywordRegexp.MatchString(k.Key) {
return 0, nil
func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) {
k := parseKeyword(d.tokens[i])
if k.Key == "CAPTION" || k.Key == "ATTR_HTML" {
consumed, node := d.parseAffiliated(i, stop)
if consumed != 0 {
return consumed, node
}
if value, ok := meta[k.Key]; ok {
meta[k.Key] = value + " " + k.Value
} else {
meta[k.Key] = k.Value
}
d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n")
return 1, k
}
func (d *Document) parseAffiliated(i int, stop stopFn) (int, Node) {
start, meta := i, Metadata{}
for ; !stop(d, i) && d.tokens[i].kind == "keyword"; i++ {
switch k := parseKeyword(d.tokens[i]); k.Key {
case "CAPTION":
meta.Caption = append(meta.Caption, d.parseInline(k.Value))
case "ATTR_HTML":
r := csv.NewReader(strings.NewReader(k.Value))
r.Comma = ' '
attributes, err := r.Read()
if err != nil {
return 0, nil
}
meta.HTMLAttributes = append(meta.HTMLAttributes, attributes)
default:
return 0, nil
}
}
if stop(d, i) {
return 0, nil
}
consumed, node := 0, (Node)(nil)
if t := d.tokens[i]; t.kind == "text" {
if nodes := d.parseInline(t.content); len(nodes) == 1 && isImageOrVideoLink(nodes[0]) {
consumed, node = 1, Paragraph{nodes[:1]}
}
} else {
consumed, node = d.parseOne(i, stop)
}
consumed, node := d.parseOne(i, stop)
if consumed == 0 || node == nil {
return 0, nil
}