0

Version info:

Emacs: 26.3
Org: 9.1.9

Am trying to export org notes to markdown format for publishing. Am using the org-gfm-export-as-markdown to preview the markdown that will be generated. Later I will wrap this in a script so I can do bulk export.

However am having a tough time finding an option that will export the timestamps as normal text and not surround it with the <span class="timestamp-wrapper"></span>

Please find the image as an example:

Screenshot

I would like the timestamp line to look something like this in markdown:

## [2018-11-14 Wed]: #journal:

P.S.: I tried pandoc but I had other issues with it. The [ in the timestamp was exported as \[. For eg: ## \[2018-11-14 Wed\]: \#journal: @EmacsExport

3 Answers 3

1

[This is a supplement to my other answer: it has very little to do with emacs, but it does address the common question of how to sustainably carry a patch for some upstream component, in the context of an emacs package. If the moderators deem it off-topic, I will delete it or perhaps incorporate it into my other answer, whichever seems most appropriate.]

My other answer describes the low-level things that you would have to do in emacs to add a timestamp-rendering function that does away with some of the things that the built-in function does. Basically, you write your own back end, my-gfm, which inherits from the gfm back end, which inherits from the md back end, which inherits from the html back end. You only provide one function in your back end to override the one in the html back end (since the intermediate back ends do not redefine that function).

There are disadvantages however: you have to maintain your own back end and you don't get your back end in the export menu unless you expend extra effort (see org-export-define-derived-backend's :menu-entry option), so you have to manually export with (org-export-to-buffer 'my-gfm) or (org-export-to-file 'my-gfm).

@dbx48's answer correctly advises to file an issue with the upstream ox-gfm project: they might do the change and that will spare you from the effort necessary to maintain your own back end in perpetuity. The question is: what to do in the meantime (or if they refuse to make that change)?

What I would do is clone the ox-gfm github repo, create a branch, switch to it and apply the change to add a timestamp function at the gfm level:

    git clone  https://github.com/larstvei/ox-gfm.git
    cd ox-gfm
    git checkout -b timestamp
    ... edit ox-gfm.el and add the line `(timestamp . my-gfm-org-timestamp)` to it, somewhere in the `:translate-alist` list.

Then point my emacs to that:

    (add-to-list 'load-path "/path/to/cloned/ox-gfm")

That allows you to use the gfm menu entry and to more-or-less forget that you patched ox-gfm -- until there is an upstream change to ox-gfm and you want to install the new version.

Git makes that fairly easy:

cd /path/to/cloned/ox-gfm
git remote update
git checkout master
git rebase
git checkout timestamp
git rebase master

That's it (and you can actually shorten that sequence, using more advanced git, but I'll skip that here). What this does is:

  • pull down the changes from upstream
  • switch to your master branch
  • update the master branch with the changes that you pulled down
  • switch to the timestamp branch
  • rebase your timestamp branch on your current master, thereby applying the timestamp patch to the current ox-gfm code.

You can then continue as if nothing happened.

If the change is applied upstream, all you have to do is get rid of the timestamp branch and just keep the master branch. The update procedure is the same for the first four steps: you just skip the last two steps since you no longer have to maintain a timestamp branch.

2

That's either a bug or a feature in the ox-gfm package. Basically, the ox-gfm package defines an exporter that derives from the ox-md exporter, which derives from the ox-html exporter. The html exporter states that all timestamps need to be run through the org-html-timestamp function, which is what prints out the span you see. Neither the md or gfm exporter happen to override that decision, so they both print out timestamps in exactly the same way.

You could file a bug (or a feature request) at https://github.com/larstvei/ox-gfm, or you could take a look at the source code an modify it to do what you want. The exporter is defined at https://github.com/larstvei/ox-gfm/blob/master/ox-gfm.el#L43-L62; you could just add a (timestamp . your-function-here) entry to it.

1

The reason for this is the md export backend is derived from the html backend and does not redefine how time stamps are exported, so it falls back to however the html backend exports time stamps.

There are various ways, some more invasive than others, to change that. The least invasive way is probably to define your own specialized backend that is almost md but not quite. See the doc string for the function org-export-define-derived-backend and in particular the example shown there: you only need a tiny modification (I think - this is untested, so caveat emptor):

(org-export-define-derived-backend 'my-md 'md
     :translate-alist '((timestamp . my-md-org-timestamp)))

(defun my-md-org-timestamp (timestamp _contents info)
  "Transcode a TIMESTAMP object from Org to my-md.
CONTENTS is nil.  INFO is a plist holding contextual
information."
  (let ((value (org-html-plain-text (org-timestamp-translate timestamp) info)))
    (format "%s" value)))

You can of course change that last function to modify the value to whatever you want, but try it as is first.

EDIT: I missed the fact that you are using ox-gfm rather than md. You should derive the my-md backend from the gfm backend (and maybe call it my-gfm instead of my-md), but the rest is the same (although again you might want to rename things for clarity).

EDIT: The function org-export-define-derived-backend is defined in the file ox.el which contains the generic bits of the exporter. You may need to require that library before you use it. Add

(require 'ox)

at the top of the code above. Here's the final code (still untested, but including the gfm changes and the renaming from the first edit):

(require 'org)
(require 'ox)
(require 'ox-html)
(require 'ox-gfm)

(org-export-define-derived-backend 'my-gfm 'gfm
     :translate-alist '((timestamp . my-gfm-org-timestamp)))

(defun my-gfm-org-timestamp (timestamp _contents info)
  "Transcode a TIMESTAMP object from Org to my-gfm, a derived exporter from the gfm exporter, which in turn is derived from the md exporter, which is derived from the html exporter.
CONTENTS is nil.  INFO is a plist holding contextual
information."
  (let ((value (org-html-plain-text (org-timestamp-translate timestamp) info)))
    (format "%s" value)))
8
  • Sorry, am new to emacs-lisp. Am getting this error when I used your function as-is: Symbol's function definition is void: org-export-define-derived-backend
    – CodeRain
    May 17, 2020 at 4:57
  • Add (require 'ox) before you try to use it.
    – NickD
    May 17, 2020 at 12:12
  • Getting this error now : error: Cannot use unknown "gfm" back-end as a parent
    – CodeRain
    May 18, 2020 at 5:09
  • I added a couple of more requires to make sure that everything is defined before you use it.
    – NickD
    May 18, 2020 at 12:40
  • 1
    I had two typos in the code: in the definition of the derived back end, the entry should be timestamp and not time-stamp; and I misspelled the name of the back end: I had it as my-gfg and it should be my-gfm. The good thing is that it is tested now. Sorry for the run-around.
    – NickD
    May 19, 2020 at 21:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.