emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Lukas Epple <emacs@lukasepple.de>
To: emacs-orgmode@gnu.org
Subject: [FR] [ox-html] export timestamps and durations via HTML5 <time> element
Date: Mon, 3 Feb 2025 19:16:36 +0100	[thread overview]
Message-ID: <20a8f91f-9edf-448d-aff7-e40e845033cc@lukasepple.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 4672 bytes --]

Hi everyone,

* Feature Request

currently HTML export will always render timestamps, both plain and from 
a clock/planning element to something like the following HTML:

     <span class="timestamp-wrapper"><span class="timestamp">
     [2025-01-31 Fri]
     </span></span>

If we are using HTML5 (<!doctype html>) to export, we are entitled to 
use the <time> element [1] [2] which allows attaching a machine readable 
date, time, datetime or duration to text. Consequently, I propose that 
we change the rendering to something like the following if the user sets 
org-html-doctype to use HTML5:

     <span class="timestamp-wrapper">
     <time class="timestamp" datetime="2025-01-31">[2025-01-31 Fri]
     </time></span>

Browsers don't seem to treat <time> much differently from <span>, so I
don't think we'd need to adjust CSS. For non-HTML5 rendering, we can
continue using <span>.

* Motivation

MDN states

> It may include the datetime attribute to translate dates into 
> machine-readable format, allowing for better search engine results 
> or custom features such as reminders.

Also, screen readers can in principle rely on this extra information in
order to properly present the content of the element (I do not know if
they do in practice, though). For Org Mode, using <time> would mean that
the export doesn't loose information even if the user defines some org-
display-custom-times format that does (see also Open Questions section
below).

* Proposed Implementation

I would be happy to write the patch myself, but I figured I'd ask for
feedback on the idea and some pointers first, especially since I've not
yet assigned my copyright to the FSF. I've attached an (undocumented)
proof of concept which implements this change for org-html-timestamp
only (by overriding the function using advice-add).

As far as I can see, a concrete implementation could be achieved in the 
following steps:

1) Add a new pair of timestamp formats to ox-html which are HTML
compatible (i.e. ISO8601), e.g. '("%F" . "%FT%T%z").

2) Add a new function that handles rendering everything inside the
timestamp-wrapper span (in my code, it is called le-org-html-format-
timestamp). This function would be used by org-html-timestamp, org-html-
planning and org-html-clock.

It would switch between <span> and <time> based on org-html-html5-p. If
HTML5, the datetime attribute is added based on the format from 1) via 
org-format-timestamp. For the text inside the element, 
org-timestamp-translate would be used in all cases, like before.

3) For the duration part of org-html-clock we need to render a supported
duration string (see [2]) inside the datetime (!) attribute. As far as I 
know, there are no existing facilities to render a compatible output. It 
shouldn't be difficult to write a function similar to 
le-org-html-format-timestamp for durations. The formatted string would 
probably need to be generated based on org-duration-to-minutes.

** Open Questions

1) In the example above, I've used an RFC3339 format string which
includes the local time zone. Since I've written that code, I've become
somewhat convinced that we should not include the timezone (at least not
by default). While it is nice that this would actually make the
timestamp fully determinate, timestamps in org files don't have the
ability to prescribe the timezone, so the system time zone is used. As a
result, exporting the same org file on machines with different time zone
settings would reduce in HTML export that references different points in
time.

2) It also occurred to me that including the timezone would leak the
user's timezone settings without them necessarily noticing. Browsers
usually don't display the datetime attribute to users anywhere.

This got me wondering about a hypothetical scenario where a user
deliberately uses org-display-custom-times to reduce the precision of
timestamps in the output. With my proposed change, the full precision
timestamp would still be recoverable via the datetime attribute. If the
user were to do this for increased privacy, it would be problematic.

These scenarios are probably (?) outlandish, but I'm interested to hear
opinions on this or maybe related design decisions Org Mode has made in
the past. It is not like we'd be breaking an intended privacy feature in
Org Mode, so the change is permissible, I think. It is worth 
considering, though, since the changed HTML output wouldn't be apparent 
to the user unless they'd look at the underlying HTML.

Kind regards,

Lukas

[1]: https://html.spec.whatwg.org/multipage/text-level-
semantics.html#the-time-element
[2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time

[-- Attachment #2: le-org-html5-timestamps.el --]
[-- Type: text/x-emacs-lisp, Size: 1338 bytes --]

;; SPDX-FileCopyrightText: Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; SPDX-FileCopyrightText: Copyright (C) 2025 Lukas Epple
;; SPDX-License-Identifier: GPL-3.0-or-later
(require 'org)
(require 'ox-html)

(defconst le-org-html-timestamp-formats '("%F" . "%FT%T%z"))

(defun le-org-html-format-timestamp (timestamp info)
  (let* ((tag (if (org-html-html5-p info) "time" "span"))
         (html5-format (funcall (if (org-timestamp-has-time-p timestamp) #'car #'cdr)
                                le-org-html-timestamp-formats))
         (attrs (append '("class=\"timestamp\"")
                        (when (org-html-html5-p info)
                          (list (format "datetime=\"%s\""
                                        (org-format-timestamp timestamp html5-format))))))
         (display-value (org-html-plain-text (org-timestamp-translate timestamp) info)))
    (format "<%s %s>%s</%s>"
            tag
            (mapconcat #'identity attrs " ")
            (replace-regexp-in-string "--" "&#x20213;" display-value)
            tag)))

(defun le-org-html-timestamp (timestamp _contents info)
  (format "<span class=\"timestamp-wrapper\">%s</span>"
          (le-org-html-format-timestamp timestamp info)))

(advice-add 'org-html-timestamp :override #'le-org-html-timestamp)

(provide 'le-org-html5-timestamps)

                 reply	other threads:[~2025-02-03 18:18 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20a8f91f-9edf-448d-aff7-e40e845033cc@lukasepple.de \
    --to=emacs@lukasepple.de \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).