Add support for timestamps
This commit is contained in:
parent
bd33e8885e
commit
63fef04fb3
9 changed files with 121 additions and 1 deletions
|
@ -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; }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"><`)
|
||||
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(`></span>`)
|
||||
}
|
||||
|
||||
func (w *HTMLWriter) WriteRegularLink(l RegularLink) {
|
||||
url := html.EscapeString(l.URL)
|
||||
if l.Protocol == "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) }
|
||||
|
|
|
@ -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 {
|
||||
|
|
37
org/testdata/inline.html
vendored
37
org/testdata/inline.html
vendored
|
@ -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"><2019-01-06 Sun></span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="timestamp"><2019-01-06 Sun></span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="timestamp"><2019-01-06 Sun 18:00></span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="timestamp"><2019-01-06 Sun 18:00 +1w></span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="timestamp"><2019-01-06 Sun 18:00></span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="timestamp"><2019-01-06 Sun 18:00 +1w></span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
7
org/testdata/inline.org
vendored
7
org/testdata/inline.org
vendored
|
@ -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>
|
||||
|
|
7
org/testdata/inline.pretty_org
vendored
7
org/testdata/inline.pretty_org
vendored
|
@ -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>
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue