Refactor keyword parsing/rendering & add support for ATTR_HTML
This commit is contained in:
parent
a859264420
commit
81f74f4ad9
9 changed files with 169 additions and 76 deletions
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue