diff --git a/README.org b/README.org
index 2e7f724..981e6f4 100644
--- a/README.org
+++ b/README.org
@@ -2,9 +2,7 @@
A basic org-mode parser in go.
Take a look at [[https://niklasfasching.github.io/go-org/][github pages]] for some examples and an online org->html demo.
* next
-- lists
- definition lists
- checkboxes
+- list checkboxes
- more keywords: https://orgmode.org/manual/In_002dbuffer-settings.html
* other differences to goorgeous
- no headline ids
diff --git a/etc/style.css b/etc/style.css
index 285816b..9f51912 100644
--- a/etc/style.css
+++ b/etc/style.css
@@ -108,3 +108,8 @@ figcaption {
.align-left { text-align: left; }
.align-center { text-align: center; }
.align-right { text-align: right; }
+
+
+dl { font-family: monospace, monospace; }
+dl > dt { font-weight: bold; }
+dl > dd { margin: -1em 0 1em 1em; }
diff --git a/org/html.go b/org/html.go
index bbdcf4f..67fe739 100644
--- a/org/html.go
+++ b/org/html.go
@@ -26,11 +26,9 @@ var emphasisTags = map[string][]string{
}
var listTags = map[string][]string{
- "+": []string{"
"},
- "-": []string{""},
- "*": []string{""},
- "number": []string{"", "
"},
- "letter": []string{"", "
"},
+ "unordered": []string{""},
+ "ordered": []string{"", "
"},
+ "descriptive": []string{"", "
"},
}
func NewHTMLWriter() *HTMLWriter {
@@ -84,6 +82,8 @@ func (w *HTMLWriter) writeNodes(ns ...Node) {
w.writeList(n)
case ListItem:
w.writeListItem(n)
+ case DescriptiveListItem:
+ w.writeDescriptiveListItem(n)
case Table:
w.writeTable(n)
@@ -260,6 +260,18 @@ func (w *HTMLWriter) writeListItem(li ListItem) {
w.WriteString("\n")
}
+func (w *HTMLWriter) writeDescriptiveListItem(di DescriptiveListItem) {
+ w.WriteString("\n")
+ if len(di.Term) != 0 {
+ w.writeNodes(di.Term...)
+ } else {
+ w.WriteString("?")
+ }
+ w.WriteString("\n")
+ w.writeNodes(di.Details...)
+ w.WriteString("\n")
+}
+
func (w *HTMLWriter) writeParagraph(p Paragraph) {
if isEmptyLineParagraph(p) {
return
diff --git a/org/list.go b/org/list.go
index 3ff2214..853a1b6 100644
--- a/org/list.go
+++ b/org/list.go
@@ -17,8 +17,15 @@ type ListItem struct {
Children []Node
}
+type DescriptiveListItem struct {
+ Bullet string
+ Term []Node
+ Details []Node
+}
+
var unorderedListRegexp = regexp.MustCompile(`^(\s*)([-]|[+]|[*])\s(.*)`)
var orderedListRegexp = regexp.MustCompile(`^(\s*)(([0-9]+|[a-zA-Z])[.)])\s+(.*)`)
+var descriptiveListItemRegexp = regexp.MustCompile(`\s::(\s|$)`)
func lexList(line string) (token, bool) {
if m := unorderedListRegexp.FindStringSubmatch(line); m != nil {
@@ -39,12 +46,12 @@ func stopIndentBelow(t token, minIndent int) bool {
func listKind(t token) string {
switch bullet := t.matches[2]; {
+ case descriptiveListItemRegexp.MatchString(t.content):
+ return "descriptive"
case bullet == "*" || bullet == "+" || bullet == "-":
- return bullet
- case unicode.IsLetter(rune(bullet[0])):
- return "letter"
- case unicode.IsDigit(rune(bullet[0])):
- return "number"
+ return "unordered"
+ case unicode.IsLetter(rune(bullet[0])), unicode.IsDigit(rune(bullet[0])):
+ return "ordered"
default:
panic(fmt.Sprintf("bad list bullet '%s': %#v", bullet, t))
}
@@ -52,20 +59,36 @@ func listKind(t token) string {
func (d *Document) parseList(i int, parentStop stopFn) (int, Node) {
start, lvl := i, d.tokens[i].lvl
-
list := List{Kind: listKind(d.tokens[i])}
- for !parentStop(d, i) && d.tokens[i].lvl == lvl && isListToken(d.tokens[i]) && listKind(d.tokens[i]) == list.Kind {
- consumed, node := d.parseListItem(i, parentStop)
+ stop := func(*Document, int) bool {
+ if parentStop(d, i) || d.tokens[i].lvl != lvl || !isListToken(d.tokens[i]) {
+ return true
+ }
+ if list.Kind == "descriptive" {
+ return false
+ }
+ return listKind(d.tokens[i]) != list.Kind
+ }
+ for !stop(d, i) {
+ consumed, node := d.parseListItem(list, i, parentStop)
i += consumed
list.Items = append(list.Items, node)
}
return i - start, list
}
-func (d *Document) parseListItem(i int, parentStop stopFn) (int, Node) {
+func (d *Document) parseListItem(l List, i int, parentStop stopFn) (int, Node) {
start, nodes, bullet := i, []Node{}, d.tokens[i].matches[2]
- minIndent := d.tokens[i].lvl + len(bullet)
- d.tokens[i] = tokenize(strings.Repeat(" ", minIndent) + d.tokens[i].content)
+ minIndent, dterm, content := d.tokens[i].lvl+len(bullet), "", d.tokens[i].content
+ if l.Kind == "descriptive" {
+ if m := descriptiveListItemRegexp.FindStringIndex(content); m != nil {
+ dterm, content = content[:m[0]], content[m[1]:]
+ if len(content) == 0 {
+ content = "\n"
+ }
+ }
+ }
+ d.tokens[i] = tokenize(strings.Repeat(" ", minIndent) + content)
stop := func(d *Document, i int) bool {
if parentStop(d, i) {
return true
@@ -78,5 +101,8 @@ func (d *Document) parseListItem(i int, parentStop stopFn) (int, Node) {
i += consumed
nodes = append(nodes, node)
}
+ if l.Kind == "descriptive" {
+ return i - start, DescriptiveListItem{bullet, d.parseInline(dterm), nodes}
+ }
return i - start, ListItem{bullet, nodes}
}
diff --git a/org/org.go b/org/org.go
index 29894ca..224313c 100644
--- a/org/org.go
+++ b/org/org.go
@@ -72,6 +72,8 @@ func (w *OrgWriter) writeNodes(ns ...Node) {
w.writeList(n)
case ListItem:
w.writeListItem(n)
+ case DescriptiveListItem:
+ w.writeDescriptiveListItem(n)
case Table:
w.writeTable(n)
@@ -228,6 +230,22 @@ func (w *OrgWriter) writeListItem(li ListItem) {
w.WriteString(strings.TrimPrefix(liWriter.String(), liWriter.indent))
}
+func (w *OrgWriter) writeDescriptiveListItem(di DescriptiveListItem) {
+ diWriter := w.emptyClone()
+ diWriter.indent = w.indent + strings.Repeat(" ", len(di.Bullet)+1)
+ diWriter.writeNodes(di.Details...)
+ details := strings.TrimPrefix(diWriter.String(), diWriter.indent)
+ w.WriteString(w.indent + di.Bullet)
+ if len(di.Term) != 0 {
+ w.WriteString(" " + w.nodesAsString(di.Term...) + " ::")
+ }
+ if len(details) > 0 && details[0] == '\n' {
+ w.WriteString(details)
+ } else {
+ w.WriteString(" " + details)
+ }
+}
+
func (w *OrgWriter) writeTable(t Table) {
for _, row := range t.Rows {
w.WriteString(w.indent)
diff --git a/org/testdata/lists.html b/org/testdata/lists.html
index fdc0d24..e93a7bf 100644
--- a/org/testdata/lists.html
+++ b/org/testdata/lists.html
@@ -92,3 +92,26 @@ that spans multiple lines
+
+descriptive lists
+
+
+-
+term
-
+
+description
+
+-
+
-
+?
-
+
+without term
+
+-
+
-
+term
-
+
+description
+
+-
+
diff --git a/org/testdata/lists.org b/org/testdata/lists.org
index 8c16479..bf96925 100644
--- a/org/testdata/lists.org
+++ b/org/testdata/lists.org
@@ -21,3 +21,11 @@
: with an example
:
: that spans multiple lines
+
+
+descriptive lists
+
+- term :: description
+- without term
+- term ::
+ description