Add support for list item checkboxes (e.g. [X])
see https://orgmode.org/manual/Checkboxes.html We're deviating from Org mode regarding the assigned css classes but the chosen classes feel better than (on, off, trans) and it's not like the export matches 1:1 otherwise.
This commit is contained in:
parent
a60f844e38
commit
7331d24452
7 changed files with 55 additions and 35 deletions
|
@ -10,15 +10,7 @@ Take a look at [[https://niklasfasching.github.io/go-org/][github pages]] for so
|
|||
- see [[https://github.com/kaushalmodi/ox-hugo/blob/8472cf2d8667754c9da3728255634e8001a1da6d/ox-hugo.el#L1785-L1850][ox-hugo]] for auto generation
|
||||
- improve list parsing
|
||||
- handle list items with empty first line
|
||||
- handle checkboxes & statistic cookies
|
||||
- handle ordered list overrides [@10]
|
||||
** TODO list checkboxes & statistics [0/2]
|
||||
https://orgmode.org/manual/Checkboxes.html
|
||||
1. [ ] parse checkbox of list item
|
||||
- convert to html radio button unchecked, indeterminate (visual only), checked
|
||||
2. [ ] parse statistic cookies of headlines & first line of list items
|
||||
-convert to =[sub 1<sup>1</sup>⁄<sub>2</sub>] || [90%]=
|
||||
|
||||
* differences to goorgeous
|
||||
To get a feeling take a look at goorgeous vs go-org html rendering of the examples [[https://niklasfasching.github.io/go-org/go-org-vs-goorgeous][comparison]].
|
||||
Please note that a visual comparison is not fair to goorgeous as the stylesheet is not adapted to it.
|
||||
|
|
19
org/html.go
19
org/html.go
|
@ -34,6 +34,12 @@ var listTags = map[string][]string{
|
|||
"descriptive": []string{"<dl>", "</dl>"},
|
||||
}
|
||||
|
||||
var listItemStatuses = map[string]string{
|
||||
" ": "unchecked",
|
||||
"-": "indeterminate",
|
||||
"X": "checked",
|
||||
}
|
||||
|
||||
func NewHTMLWriter() *HTMLWriter {
|
||||
return &HTMLWriter{
|
||||
htmlEscape: true,
|
||||
|
@ -283,13 +289,22 @@ func (w *HTMLWriter) writeList(l List) {
|
|||
}
|
||||
|
||||
func (w *HTMLWriter) writeListItem(li ListItem) {
|
||||
w.WriteString("<li>\n")
|
||||
if li.Status != "" {
|
||||
w.WriteString(fmt.Sprintf("<li class=\"%s\">\n", listItemStatuses[li.Status]))
|
||||
} else {
|
||||
w.WriteString("<li>\n")
|
||||
}
|
||||
w.writeNodes(li.Children...)
|
||||
w.WriteString("</li>\n")
|
||||
}
|
||||
|
||||
func (w *HTMLWriter) writeDescriptiveListItem(di DescriptiveListItem) {
|
||||
w.WriteString("<dt>\n")
|
||||
if di.Status != "" {
|
||||
w.WriteString(fmt.Sprintf("<dt class=\"%s\">\n", listItemStatuses[di.Status]))
|
||||
} else {
|
||||
w.WriteString("<dt>\n")
|
||||
}
|
||||
|
||||
if len(di.Term) != 0 {
|
||||
w.writeNodes(di.Term...)
|
||||
} else {
|
||||
|
|
13
org/list.go
13
org/list.go
|
@ -14,11 +14,13 @@ type List struct {
|
|||
|
||||
type ListItem struct {
|
||||
Bullet string
|
||||
Status string
|
||||
Children []Node
|
||||
}
|
||||
|
||||
type DescriptiveListItem struct {
|
||||
Bullet string
|
||||
Status string
|
||||
Term []Node
|
||||
Details []Node
|
||||
}
|
||||
|
@ -26,6 +28,7 @@ type DescriptiveListItem struct {
|
|||
var unorderedListRegexp = regexp.MustCompile(`^(\s*)([-]|[+]|[*])\s(.*)`)
|
||||
var orderedListRegexp = regexp.MustCompile(`^(\s*)(([0-9]+|[a-zA-Z])[.)])\s+(.*)`)
|
||||
var descriptiveListItemRegexp = regexp.MustCompile(`\s::(\s|$)`)
|
||||
var listItemStatusRegexp = regexp.MustCompile(`\[( |X|-)\]\s`)
|
||||
|
||||
func lexList(line string) (token, bool) {
|
||||
if m := unorderedListRegexp.FindStringSubmatch(line); m != nil {
|
||||
|
@ -79,12 +82,16 @@ func (d *Document) parseList(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, dterm, content := d.tokens[i].lvl+len(bullet), "", d.tokens[i].content
|
||||
minIndent, dterm, content, status := d.tokens[i].lvl+len(bullet), "", d.tokens[i].content, ""
|
||||
if m := listItemStatusRegexp.FindStringSubmatch(content); m != nil {
|
||||
status, content = m[1], content[len("[ ] "):]
|
||||
}
|
||||
if l.Kind == "descriptive" {
|
||||
if m := descriptiveListItemRegexp.FindStringIndex(content); m != nil {
|
||||
dterm, content = content[:m[0]], content[m[1]:]
|
||||
}
|
||||
}
|
||||
|
||||
d.tokens[i] = tokenize(strings.Repeat(" ", minIndent) + content)
|
||||
stop := func(d *Document, i int) bool {
|
||||
if parentStop(d, i) {
|
||||
|
@ -99,7 +106,7 @@ func (d *Document) parseListItem(l List, i int, parentStop stopFn) (int, Node) {
|
|||
nodes = append(nodes, node)
|
||||
}
|
||||
if l.Kind == "descriptive" {
|
||||
return i - start, DescriptiveListItem{bullet, d.parseInline(dterm), nodes}
|
||||
return i - start, DescriptiveListItem{bullet, status, d.parseInline(dterm), nodes}
|
||||
}
|
||||
return i - start, ListItem{bullet, nodes}
|
||||
return i - start, ListItem{bullet, status, nodes}
|
||||
}
|
||||
|
|
|
@ -203,6 +203,9 @@ func (w *OrgWriter) writeListItem(li ListItem) {
|
|||
liWriter.writeNodes(li.Children...)
|
||||
content := strings.TrimPrefix(liWriter.String(), liWriter.indent)
|
||||
w.WriteString(w.indent + li.Bullet)
|
||||
if li.Status != "" {
|
||||
w.WriteString(fmt.Sprintf(" [%s]", li.Status))
|
||||
}
|
||||
if len(content) > 0 && content[0] == '\n' {
|
||||
w.WriteString(content)
|
||||
} else {
|
||||
|
@ -212,6 +215,9 @@ func (w *OrgWriter) writeListItem(li ListItem) {
|
|||
|
||||
func (w *OrgWriter) writeDescriptiveListItem(di DescriptiveListItem) {
|
||||
w.WriteString(w.indent + di.Bullet)
|
||||
if di.Status != "" {
|
||||
w.WriteString(fmt.Sprintf(" [%s]", di.Status))
|
||||
}
|
||||
indent := w.indent + strings.Repeat(" ", len(di.Bullet)+1)
|
||||
if len(di.Term) != 0 {
|
||||
term := w.nodesAsString(di.Term...)
|
||||
|
|
8
org/testdata/headlines.html
vendored
8
org/testdata/headlines.html
vendored
|
@ -2,14 +2,14 @@
|
|||
Simple Headline <code class="statistic">[1/2]</code>
|
||||
</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<li class="checked">
|
||||
<p>
|
||||
[X] checked
|
||||
checked
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<li class="unchecked">
|
||||
<p>
|
||||
[ ] unchecked
|
||||
unchecked
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
|
|
18
org/testdata/lists.html
vendored
18
org/testdata/lists.html
vendored
|
@ -1,5 +1,5 @@
|
|||
<ul>
|
||||
<li>
|
||||
<li class="unchecked">
|
||||
<p>
|
||||
unordered list item 1
|
||||
</p>
|
||||
|
@ -9,22 +9,22 @@ unordered list item 1
|
|||
unordered list item 2 - with <code>inline</code> <em>markup</em>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
<li class="indeterminate">
|
||||
<p>
|
||||
ordered sublist item 1
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
<li class="checked">
|
||||
<p>
|
||||
ordered sublist item 1
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<li class="unchecked">
|
||||
<p>
|
||||
ordered sublist item 2
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<li class="checked">
|
||||
<p>
|
||||
ordered sublist item 3
|
||||
</p>
|
||||
|
@ -38,7 +38,7 @@ ordered sublist item 2
|
|||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<li class="checked">
|
||||
<p>
|
||||
unordered list item 3 - and a <a href="https://example.com">link</a>
|
||||
and some lines of text
|
||||
|
@ -95,20 +95,20 @@ that spans multiple lines
|
|||
descriptive lists
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<dt class="unchecked">
|
||||
term<dd>
|
||||
<p>
|
||||
details
|
||||
continued details
|
||||
</p>
|
||||
<dd>
|
||||
<dt>
|
||||
<dt class="unchecked">
|
||||
?<dd>
|
||||
<p>
|
||||
details without a term
|
||||
</p>
|
||||
<dd>
|
||||
<dt>
|
||||
<dt class="checked">
|
||||
term<dd>
|
||||
<p>
|
||||
details on a new line
|
||||
|
|
18
org/testdata/lists.org
vendored
18
org/testdata/lists.org
vendored
|
@ -1,11 +1,11 @@
|
|||
- unordered list item 1
|
||||
- [ ] unordered list item 1
|
||||
- unordered list item 2 - with ~inline~ /markup/
|
||||
1. ordered sublist item 1
|
||||
a) ordered sublist item 1
|
||||
b) ordered sublist item 2
|
||||
c) ordered sublist item 3
|
||||
1. [-] ordered sublist item 1
|
||||
a) [X] ordered sublist item 1
|
||||
b) [ ] ordered sublist item 2
|
||||
c) [X] ordered sublist item 3
|
||||
2. ordered sublist item 2
|
||||
- unordered list item 3 - and a [[https://example.com][link]]
|
||||
- [X] unordered list item 3 - and a [[https://example.com][link]]
|
||||
and some lines of text
|
||||
1. and another subitem
|
||||
#+BEGIN_SRC sh
|
||||
|
@ -24,10 +24,10 @@
|
|||
|
||||
|
||||
descriptive lists
|
||||
- term :: details
|
||||
- [ ] term :: details
|
||||
continued details
|
||||
- details without a term
|
||||
- term ::
|
||||
- [ ] details without a term
|
||||
- [X] term ::
|
||||
details on a new line
|
||||
- term ::
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue