Add support for timestamps

This commit is contained in:
Niklas Fasching 2019-01-06 20:50:10 +01:00
parent bd33e8885e
commit 63fef04fb3
9 changed files with 121 additions and 1 deletions

View file

@ -118,3 +118,8 @@ dl > dd { margin: -1em 0 1em 1em; }
font-size: 0.8em;
color: lightgrey;
}
.timestamp {
background-color: #eee;
padding: 0.05em 0.2em;
border: 1px solid #ccc; }

View file

@ -81,7 +81,7 @@ func New() *Configuration {
DefaultSettings: map[string]string{
"TODO": "TODO | DONE",
"EXCLUDE_TAGS": "noexport",
"OPTIONS": "toc:t e:t f:t pri:t todo:t tags:t",
"OPTIONS": "toc:t <:t e:t f:t pri:t todo:t tags:t",
},
Log: log.New(os.Stderr, "go-org: ", 0),
}
@ -166,6 +166,7 @@ func (d *Document) Get(key string) string {
// GetOption returns the value associated to the export option key
// Currently supported options:
// - < (export timestamps)
// - e (export org entities)
// - f (export footnotes)
// - toc (export table of content)

View file

@ -246,6 +246,22 @@ func (w *HTMLWriter) WriteFootnoteLink(l FootnoteLink) {
w.WriteString(fmt.Sprintf(`<sup class="footnote-reference"><a id="footnote-reference-%s" href="#footnote-%s">%s</a></sup>`, n, n, n))
}
func (w *HTMLWriter) WriteTimestamp(t Timestamp) {
if !w.document.GetOption("<") {
return
}
w.WriteString(`<span class="timestamp">&lt;`)
if t.IsDate {
w.WriteString(t.Time.Format(datestampFormat))
} else {
w.WriteString(t.Time.Format(timestampFormat))
}
if t.Interval != "" {
w.WriteString(" " + t.Interval)
}
w.WriteString(`&gt;</span>`)
}
func (w *HTMLWriter) WriteRegularLink(l RegularLink) {
url := html.EscapeString(l.URL)
if l.Protocol == "file" {

View file

@ -1,9 +1,11 @@
package org
import (
"fmt"
"path"
"regexp"
"strings"
"time"
"unicode"
)
@ -17,6 +19,12 @@ type ExplicitLineBreak struct{}
type StatisticToken struct{ Content string }
type Timestamp struct {
Time time.Time
IsDate bool
Interval string
}
type Emphasis struct {
Kind string
Content []Node
@ -40,9 +48,13 @@ var imageExtensionRegexp = regexp.MustCompile(`^[.](png|gif|jpe?g|svg|tiff?)$`)
var videoExtensionRegexp = regexp.MustCompile(`^[.](webm|mp4)$`)
var subScriptSuperScriptRegexp = regexp.MustCompile(`^([_^]){([^{}]+?)}`)
var timestampRegexp = regexp.MustCompile(`^<(\d{4}-\d{2}-\d{2})( [A-Za-z]+)?( \d{2}:\d{2})?( \+\d+[dwmy])?>`)
var footnoteRegexp = regexp.MustCompile(`^\[fn:([\w-]+?)(:(.*?))?\]`)
var statisticsTokenRegexp = regexp.MustCompile(`^\[(\d+/\d+|\d+%)\]`)
var timestampFormat = "2006-01-02 Mon 15:04"
var datestampFormat = "2006-01-02 Mon"
func (d *Document) parseInline(input string) (nodes []Node) {
previous, current := 0, 0
for current < len(input) {
@ -58,6 +70,8 @@ func (d *Document) parseInline(input string) (nodes []Node) {
consumed, node = d.parseEmphasis(input, current, true)
case '[':
consumed, node = d.parseOpeningBracket(input, current)
case '<':
consumed, node = d.parseTimestamp(input, current)
case '\\':
consumed, node = d.parseExplicitLineBreak(input, current)
case '\n':
@ -222,6 +236,22 @@ func (d *Document) parseRegularLink(input string, start int) (int, Node) {
return consumed, RegularLink{protocol, description, link, false}
}
func (d *Document) parseTimestamp(input string, start int) (int, Node) {
if m := timestampRegexp.FindStringSubmatch(input[start:]); m != nil {
ddmmyy, hhmm, interval, isDate := m[1], m[3], strings.TrimSpace(m[4]), false
if hhmm == "" {
hhmm, isDate = "00:00", true
}
t, err := time.Parse(timestampFormat, fmt.Sprintf("%s Mon %s", ddmmyy, hhmm))
if err != nil {
return 0, nil
}
timestamp := Timestamp{t, isDate, interval}
return len(m[0]), timestamp
}
return 0, nil
}
func (d *Document) parseEmphasis(input string, start int, isRaw bool) (int, Node) {
marker, i := input[start], start
if !hasValidPreAndBorderChars(input, i) {
@ -282,3 +312,4 @@ func (n StatisticToken) String() string { return orgWriter.nodesAsString(n) }
func (n Emphasis) String() string { return orgWriter.nodesAsString(n) }
func (n FootnoteLink) String() string { return orgWriter.nodesAsString(n) }
func (n RegularLink) String() string { return orgWriter.nodesAsString(n) }
func (n Timestamp) String() string { return orgWriter.nodesAsString(n) }

View file

@ -278,6 +278,19 @@ func (w *OrgWriter) WriteExplicitLineBreak(l ExplicitLineBreak) {
w.WriteString(`\\` + "\n" + w.indent)
}
func (w *OrgWriter) WriteTimestamp(t Timestamp) {
w.WriteString("<")
if t.IsDate {
w.WriteString(t.Time.Format(datestampFormat))
} else {
w.WriteString(t.Time.Format(timestampFormat))
}
if t.Interval != "" {
w.WriteString(" " + t.Interval)
}
w.WriteString(">")
}
func (w *OrgWriter) WriteFootnoteLink(l FootnoteLink) {
w.WriteString("[fn:" + l.Name)
if l.Definition != nil {

View file

@ -111,4 +111,41 @@ auto link, i.e. not inside <code class="verbatim">\[[square brackets]\]</code> <
</li>
</ol>
</li>
<li>
<p>
timestamps
</p>
<ul>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun&gt;</span>
</p>
</li>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun&gt;</span>
</p>
</li>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun 18:00&gt;</span>
</p>
</li>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun 18:00 +1w&gt;</span>
</p>
</li>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun 18:00&gt;</span>
</p>
</li>
<li>
<p>
<span class="timestamp">&lt;2019-01-06 Sun 18:00 +1w&gt;</span>
</p>
</li>
</ul>
</li>
</ul>

View file

@ -27,3 +27,10 @@
6. regular link to https (image) [[https://placekitten.com/200/200#.png]]
7. regular link enclosed in [] [[[https://www.example.com]]] [[[https://www.example.com][example.com]]]
8. auto link, i.e. not inside =\[[square brackets]\]= https://www.example.com
- timestamps
- <2019-01-06>
- <2019-01-06 Sun>
- <2019-01-06 Sun 18:00>
- <2019-01-06 Sun 18:00 +1w>
- <2019-01-06 18:00>
- <2019-01-06 18:00 +1w>

View file

@ -27,3 +27,10 @@
6. regular link to https (image) [[https://placekitten.com/200/200#.png]]
7. regular link enclosed in [] [[[https://www.example.com]]] [[[https://www.example.com][example.com]]]
8. auto link, i.e. not inside =\[[square brackets]\]= https://www.example.com
- timestamps
- <2019-01-06 Sun>
- <2019-01-06 Sun>
- <2019-01-06 Sun 18:00>
- <2019-01-06 Sun 18:00 +1w>
- <2019-01-06 Sun 18:00>
- <2019-01-06 Sun 18:00 +1w>

View file

@ -29,6 +29,7 @@ type Writer interface {
WriteExplicitLineBreak(ExplicitLineBreak)
WriteLineBreak(LineBreak)
WriteRegularLink(RegularLink)
WriteTimestamp(Timestamp)
WriteFootnoteLink(FootnoteLink)
WriteFootnoteDefinition(FootnoteDefinition)
}
@ -78,6 +79,8 @@ func WriteNodes(w Writer, nodes ...Node) {
w.WriteLineBreak(n)
case RegularLink:
w.WriteRegularLink(n)
case Timestamp:
w.WriteTimestamp(n)
case FootnoteLink:
w.WriteFootnoteLink(n)
case FootnoteDefinition: