Skip to content

Commit

Permalink
Allow setting publishdate and expirydate also using Org time stamp
Browse files Browse the repository at this point in the history
Now you can "C-c . RET" to set values for HUGO_PUBLISHDATE and
HUGO_EXPIRYDATE properties too (just like you can already do that for
DATE and HUGO_LASTMOD properties).

Added test cases for "lastmod", "publishdate" and "expirydate"
front-matter variables.

Consolidate the date formatting logic into a separate new function
`org-hugo--format-date', and use it to derive all the Hugo date
front-matter variable values: "date", "lastmod", "publishdate", and
"expirydate".
  • Loading branch information
kaushalmodi committed Jan 23, 2018
1 parent aa0150d commit 12dc593
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 73 deletions.
149 changes: 83 additions & 66 deletions ox-hugo.el
Expand Up @@ -1064,6 +1064,85 @@ INFO is a plist used as a communication channel."
dir)))
(file-truename pub-dir)))

(defun org-hugo--format-date (date-key info)
"Return a date string formatted in Hugo-compatible format.
DATE-KEY is the key in INFO from which the date is to be
retrieved. INFO is a plist used as a communication channel.
Possible values of DATE-KEY are `:date', `:hugo-lastmod',
`:hugo-publishdate', and `:hugo-expirydate'.
Return nil if the retrieved date from INFO is nil or if the date
cannot be formatted in Hugo-compatible format."
(let* ((hugo-date-fmt "%Y-%m-%dT%T%z")
(date-raw (cond
((equal date-key :date)
(or
;; Get the date from the "CLOSED" property;
;; generated automatically when switching a
;; headline to "DONE" state,
(org-entry-get (point) "CLOSED")
;; Else get the date from the subtree property,
;; `EXPORT_DATE' if available
(org-string-nw-p
(org-export-data (plist-get info date-key) info))
;; Else try to get it from the #+DATE keyword in
;; the Org file.
(org-string-nw-p
(org-export-get-date info hugo-date-fmt))))
(t ;:hugo-lastmod, :hugo-publishdate, :hugo-expirydate
(org-string-nw-p
(org-export-data (plist-get info date-key) info)))))
(date-nocolon (cond
;; If the date set for the DATE-KEY parameter
;; is already in Hugo-compatible format, use
;; it.
((and (stringp date-raw)
(string-match-p org-hugo--date-time-regexp date-raw))
date-raw)
;; Else if it's any other string (like
;; "<2018-01-23 Tue>"), try to parse that
;; date.
((stringp date-raw)
(condition-case err
(format-time-string
hugo-date-fmt
(apply #'encode-time (org-parse-time-string date-raw)))
(error
;; Set date-nocolon to nil if error
;; happens. An example: If #+DATE is set
;; to 2012-2017 to set the copyright
;; years, just set the date to nil instead
;; of throwing an error like:
;; org-parse-time-string: Not a standard
;; Org time string: 2012-2017
(message
(format "[ox-hugo] Date will not be set in the front-matter: %s"
(nth 1 err)))
nil)))
;; Else (if nil) and user want to auto-set the
;; lastmod field.
((and (equal date-key :hugo-lastmod)
(org-hugo--plist-get-true-p info :hugo-auto-set-lastmod))
(format-time-string hugo-date-fmt (org-current-time)))
;; Else.. do nothing.
(t
nil)))
;; Hugo expects the date stamp in this format (RFC3339 -- See
;; `org-hugo--date-time-regexp'.) i.e. requires a colon to
;; separate the hours and minutes in the time-zone section of
;; the date.
;; 2017-07-06T14:59:45-04:00
;; But the "%Y-%m-%dT%T%z" format (`hugo-date-fmt') produces the date
;; in this format:
;; 2017-07-06T14:59:45-0400 (Note the missing colon)
;; Below simply adds that colon.
(date-str (and (stringp date-nocolon)
(replace-regexp-in-string "\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\'" "\\1:\\2"
date-nocolon))))
date-str))



;;; Transcode Functions
Expand Down Expand Up @@ -2094,47 +2173,6 @@ INFO is a plist used as a communication channel."
(mapcar #'org-trim author-list-1))))))
(creator (and (plist-get info :with-creator)
(plist-get info :creator)))
(hugo-date-fmt "%Y-%m-%dT%T%z")
(date-raw (or
;; Get the date from the "CLOSED" property;
;; generated automatically when switching a
;; headline to "DONE" state,
(org-entry-get (point) "CLOSED")
;; Else get the date from the subtree property,
;; `EXPORT_DATE' if available
(org-string-nw-p (org-export-data (plist-get info :date) info))
;; Else try to get it from the #+DATE keyword in
;; the Org file.
(org-string-nw-p (org-export-get-date info hugo-date-fmt))))
(date-nocolon (and (stringp date-raw)
(if (string-match-p org-hugo--date-time-regexp date-raw)
;; If the set DATE is already in
;; Hugo-compatible date format, use it.
date-raw
;; Else try to parse the date.
(condition-case err
(format-time-string
hugo-date-fmt
(apply #'encode-time (org-parse-time-string date-raw)))
(error
;; Set date-nocolon to nil if error happens.
;; An example: If #+DATE is set to
;; 2012-2017 to set the copyright
;; years, just set the date to nil
;; instead of throwing an error like:
;; org-parse-time-string: Not a standard Org time string: 2012-2017
(message
(format "[ox-hugo] Date will not be set in the front-matter: %s"
(nth 1 err)))
nil)))))
;; Hugo expects the date stamp in this format:
;; 2017-07-06T14:59:45-04:00
;; But the "%Y-%m-%dT%T%z" format produces the date in this format:
;; 2017-07-06T14:59:45-0400 (Note the missing colon)
;; Below simply adds that colon.
(date (and (stringp date-nocolon)
(replace-regexp-in-string "\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\'" "\\1:\\2"
date-nocolon)))
(aliases-raw (let ((aliases-raw-1
(org-string-nw-p
(org-export-data (plist-get info :hugo-aliases) info))))
Expand All @@ -2155,27 +2193,6 @@ INFO is a plist used as a communication channel."
(org-export-data (plist-get info :hugo-outputs) info)))
(outputs (when outputs-raw
(org-split-string outputs-raw " ")))
(lastmod-raw (org-string-nw-p (org-export-data (plist-get info :hugo-lastmod) info)))
(lastmod-nocolon (cond
;; If the set HUGO_LASTMOD is already in
;; Hugo-compatible lastmod format, use it.
((and (stringp lastmod-raw)
(string-match-p org-hugo--date-time-regexp lastmod-raw))
lastmod-raw)
;; Else if it's a string, try to parse the lastmod.
((stringp lastmod-raw)
(format-time-string
hugo-date-fmt
(apply #'encode-time (org-parse-time-string lastmod-raw))))
;; Else (if nil) and user want to auto-set the lastmod field.
((org-hugo--plist-get-true-p info :hugo-auto-set-lastmod)
(format-time-string hugo-date-fmt (org-current-time)))
;; Else.. do nothing.
(t
nil)))
(lastmod (and (stringp lastmod-nocolon)
(replace-regexp-in-string "\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\'" "\\1:\\2"
lastmod-nocolon)))
(todo-keyword (org-entry-get (point) "TODO"))
(draft (cond
((and todo-keyword
Expand Down Expand Up @@ -2256,14 +2273,14 @@ INFO is a plist used as a communication channel."
(title . ,(org-hugo--sanitize-title info))
(author . ,author-list)
(description . ,(org-export-data (plist-get info :description) info))
(date . ,date)
(publishDate . ,(org-export-data (plist-get info :hugo-publishdate) info))
(expiryDate . ,(org-export-data (plist-get info :hugo-expirydate) info))
(date . ,(org-hugo--format-date :date info))
(publishDate . ,(org-hugo--format-date :hugo-publishdate info))
(expiryDate . ,(org-hugo--format-date :hugo-expirydate info))
(aliases . ,aliases)
(isCJKLanguage . ,(org-hugo--plist-get-true-p info :hugo-iscjklanguage))
(keywords . ,(org-export-data (plist-get info :keywords) info))
(layout . ,(org-export-data (plist-get info :hugo-layout) info))
(lastmod . ,lastmod)
(lastmod . ,(org-hugo--format-date :hugo-lastmod info))
(linkTitle . ,(org-export-data (plist-get info :hugo-linktitle) info))
(markup . ,(org-export-data (plist-get info :hugo-markup) info))
(outputs . ,outputs)
Expand Down
59 changes: 52 additions & 7 deletions test/site/content-org/all-posts.org
Expand Up @@ -3211,33 +3211,34 @@ If such a property is non-nil, the value (time-stamp) of that is used
to set the =date= field in the exported front-matter.

- Reference :: [[https://orgmode.org/manual/Special-properties.html][(org) Special properties]] or =C-h i g (org) Special properties=
* Date Formats :date:
** Just date
* Dates
** Date :date:
*** Just date
:PROPERTIES:
:EXPORT_FILE_NAME: date-just-date
:EXPORT_DATE: 2017-09-12
:END:
** Date + Time
*** Date + Time
:PROPERTIES:
:EXPORT_FILE_NAME: date-plus-time
:EXPORT_DATE: 2017-09-12T16:10:00
:END:
** Date + Time (UTC)
*** Date + Time (UTC)
:PROPERTIES:
:EXPORT_FILE_NAME: date-plus-time-utc
:EXPORT_DATE: 2017-09-12T16:10:00Z
:END:
** Date + Time (behind UTC)
*** Date + Time (behind UTC)
:PROPERTIES:
:EXPORT_FILE_NAME: date-plus-time-minus-utc
:EXPORT_DATE: 2017-09-12T16:10:00-04:00
:END:
** Date + Time (after UTC)
*** Date + Time (after UTC)
:PROPERTIES:
:EXPORT_FILE_NAME: date-plus-time-plus-utc
:EXPORT_DATE: 2017-09-12T16:10:00+05:30
:END:
** Invalid Date :invalid:
*** Invalid Date :invalid:
:PROPERTIES:
:EXPORT_FILE_NAME: invalid-date
:EXPORT_DATE: 2012-2017
Expand All @@ -3256,6 +3257,50 @@ front-matter.
In this post the =:EXPORT_DATE:= property is set to =2012-2017=, but
the export will still happen fine, with the =date= front-matter not
set.
** Lastmod Date :lastmod_date:
*** Lastmod date set using Org time stamp
:PROPERTIES:
:EXPORT_FILE_NAME: lastmod-date-org-time-stamp
:EXPORT_HUGO_LASTMOD: <2018-01-23 Tue>
:END:
The =lastmod= for this post is set in Org using the ~C-c . RET~
binding.
*** Lastmod date set using Hugo-compatible date string
:PROPERTIES:
:EXPORT_FILE_NAME: lastmod-date-hugo-compatible-date
:EXPORT_HUGO_LASTMOD: 2018-01-23
:END:
The =lastmod= for this post is Hugo-compatible i.e. [[https://tools.ietf.org/html/rfc3339#section-5.8][RFC3339-compliant]].
** Publish Date :publish_date:
*** Publish date set using Org time stamp
:PROPERTIES:
:EXPORT_FILE_NAME: publish-date-org-time-stamp
:EXPORT_HUGO_PUBLISHDATE: <2018-01-23 Tue>
:END:
The =publishdate= for this post is set in Org using the ~C-c . RET~
binding.
*** Publish date set using Hugo-compatible date string
:PROPERTIES:
:EXPORT_FILE_NAME: publish-date-hugo-compatible-date
:EXPORT_HUGO_PUBLISHDATE: 2018-01-23
:END:
The =publishdate= for this post is Hugo-compatible
i.e. [[https://tools.ietf.org/html/rfc3339#section-5.8][RFC3339-compliant]].
** Expiry Date :expiry_date:
*** Expiry date set using Org time stamp
:PROPERTIES:
:EXPORT_FILE_NAME: expiry-date-org-time-stamp
:EXPORT_HUGO_EXPIRYDATE: <2999-01-23 Tue>
:END:
The =expirydate= for this post is set in Org using the ~C-c . RET~
binding.
*** Expiry date set using Hugo-compatible date string
:PROPERTIES:
:EXPORT_FILE_NAME: expiry-date-hugo-compatible-date
:EXPORT_HUGO_EXPIRYDATE: 2999-01-23
:END:
The =expirydate= for this post is Hugo-compatible
i.e. [[https://tools.ietf.org/html/rfc3339#section-5.8][RFC3339-compliant]].
* Preserve filling option :filling:
** Filling is preserved
:PROPERTIES:
Expand Down
9 changes: 9 additions & 0 deletions test/site/content/posts/expiry-date-hugo-compatible-date.md
@@ -0,0 +1,9 @@
+++
title = "Expiry date set using Hugo-compatible date string"
expiryDate = 2999-01-23
tags = ["expiry-date"]
draft = false
+++

The `expirydate` for this post is Hugo-compatible
i.e. [RFC3339-compliant](https://tools.ietf.org/html/rfc3339#section-5.8).
9 changes: 9 additions & 0 deletions test/site/content/posts/expiry-date-org-time-stamp.md
@@ -0,0 +1,9 @@
+++
title = "Expiry date set using Org time stamp"
expiryDate = 2999-01-23T00:00:00+00:00
tags = ["expiry-date"]
draft = false
+++

The `expirydate` for this post is set in Org using the `C-c . RET`
binding.
8 changes: 8 additions & 0 deletions test/site/content/posts/lastmod-date-hugo-compatible-date.md
@@ -0,0 +1,8 @@
+++
title = "Lastmod date set using Hugo-compatible date string"
lastmod = 2018-01-23
tags = ["lastmod-date"]
draft = false
+++

The `lastmod` for this post is Hugo-compatible i.e. [RFC3339-compliant](https://tools.ietf.org/html/rfc3339#section-5.8).
9 changes: 9 additions & 0 deletions test/site/content/posts/lastmod-date-org-time-stamp.md
@@ -0,0 +1,9 @@
+++
title = "Lastmod date set using Org time stamp"
lastmod = 2018-01-23T00:00:00+00:00
tags = ["lastmod-date"]
draft = false
+++

The `lastmod` for this post is set in Org using the `C-c . RET`
binding.
9 changes: 9 additions & 0 deletions test/site/content/posts/publish-date-hugo-compatible-date.md
@@ -0,0 +1,9 @@
+++
title = "Publish date set using Hugo-compatible date string"
publishDate = 2018-01-23
tags = ["publish-date"]
draft = false
+++

The `publishdate` for this post is Hugo-compatible
i.e. [RFC3339-compliant](https://tools.ietf.org/html/rfc3339#section-5.8).
9 changes: 9 additions & 0 deletions test/site/content/posts/publish-date-org-time-stamp.md
@@ -0,0 +1,9 @@
+++
title = "Publish date set using Org time stamp"
publishDate = 2018-01-23T00:00:00+00:00
tags = ["publish-date"]
draft = false
+++

The `publishdate` for this post is set in Org using the `C-c . RET`
binding.

0 comments on commit 12dc593

Please sign in to comment.