Export backlinks on Org export

I’ve been using this to export backlinks when publishing my notes to html, it works with V2.

I hope it will help.

(defun collect-backlinks-string (backend)
  "Insert backlinks into the end of the org file before parsing it."
  (goto-char (point-max))
  ;; Add a new header for the references
  (insert "\n\n* Referenced in\n")
  (let* ((backlinks (org-roam-backlinks-get (org-roam-node-at-point))))
    (dolist (backlink backlinks)
      (let* ((source-node (org-roam-backlink-source-node backlink))
             (point (org-roam-backlink-point backlink))
             (text (-last-item (org-roam-node-preview (org-roam-node-file source-node)
                                                      point))))
        (insert
         (format "- [[./%s][%s]]\n%s\n"
                 (file-name-nondirectory (org-roam-node-file source-node))
                 (org-roam-node-title source-node)
                 text))))))

(add-hook 'org-export-before-processing-hook 'collect-backlinks-string)

The final result will be something like this:

4 Likes

Thank you very much!
But when i try to export any file without org-roam-node, it fails.
Maybe better add something like

(when (org-roam-node-at-point)
...
 )

?
I’m not sure how to say it in elisp correct, but this works for me :smiley:

1 Like

That is exactly it. Thank you.

Here is the the code:

(defun collect-backlinks-string (backend)
  "Insert backlinks into the end of the org file before parsing it."
  (when (org-roam-node-at-point)
    (goto-char (point-max))
    ;; Add a new header for the references
    (insert "\n\n* Referenced in\n")
    (let* ((backlinks (org-roam-backlinks-get (org-roam-node-at-point))))
      (dolist (backlink backlinks)
        (let* ((source-node (org-roam-backlink-source-node backlink))
               (point (org-roam-backlink-point backlink))
               (text (-last-item (org-roam-node-preview (org-roam-node-file source-node)
                                                        point))))
          (insert
           (format "- [[./%s][%s]]\n%s\n"
                   (file-name-nondirectory (org-roam-node-file source-node))
                   (org-roam-node-title source-node)
                   text)))))))

(add-hook 'org-export-before-processing-hook 'collect-backlinks-string)
1 Like

Maybe file-relative-name is better than file-name-nondirectory. I have subfolders in my org-roam folder. :slight_smile:

Wish it is possible to make backlinks list for every org-roam-node in file…

1 Like

Hey!

I’ve tried to implement a way to take into account files with multiple nodes.

Is it something like this?

An org file:

:PROPERTIES:
:ID:       114b9147-47c4-4008-9cba-fcb8338f2e98
:END:
#+title: Org-Roam test

Testing stuff with org-roam.

It contains both [[id:foo][Foo]] and [[id:bar][Bar]].

* Foo
:PROPERTIES:
:ID:       foo
:END:

Part of [[id:bar][Bar]].

* Bar
:PROPERTIES:
:ID:       bar
:END:

Part of [[id:foo][Foo]]

The output:

The code:

(defun collect-backlinks-string (backend)
  (let* ((source-node (org-roam-node-at-point))
         (source-file (org-roam-node-file source-node))
         ;; Sort the nodes by the point to avoid errors when inserting the
         ;; references
         (nodes-in-file (--sort (< (org-roam-node-point it)
                                   (org-roam-node-point other))
                                (-filter (lambda (node)
                                           (s-equals?
                                            (org-roam-node-file node)
                                            source-file))
                                         (org-roam-node-list))))
         ;; Nodes don't store the last position so, get the next node position
         ;; and subtract one character
         (nodes-start-position (-map (lambda (node) (org-roam-node-point node))
                                     nodes-in-file))
         (nodes-end-position (-concat (-map (lambda (next-node-position)
                                              (- next-node-position 1))
                                            (-drop 1 nodes-start-position))
                                      (list (point-max))))
         ;; Keep track of the current-node index
         (current-node 0)
         ;; Keep track of the amount of text added
         (character-count 0))
    (dolist (node nodes-in-file)
      (when (org-roam-backlinks-get node)
        ;; Go to the end of the node and don't forget about previously inserted
        ;; text
        (goto-char (+ (nth current-node nodes-end-position) character-count))
        ;; Add the references as a subtree of the node
        (setq heading (format "\n\n%s References\n\n"
                              (s-repeat (+ (org-roam-node-level node) 1) "*")))
        ;; Also count the new lines (4)
        (setq character-count (+ 4 character-count (string-width heading)))
        (insert heading)
        (dolist (backlink (org-roam-backlinks-get node))
          (let* ((source-node (org-roam-backlink-source-node backlink))
                 (point (org-roam-backlink-point backlink))
                 (text (-last-item (org-roam-node-preview
                                    (org-roam-node-file source-node)
                                    point)))
                 (references (format "- [[./%s][%s]]: %s\n\n"
                                     (file-relative-name (org-roam-node-file source-node))
                                     (org-roam-node-title source-node)
                                     text)))
            ;; Also count the new lines (2)
            (setq character-count (+ 2 character-count (string-width references)))
            (insert references))))
      (setq current-node (+ current-node 1)))))