diff --git a/doc/org-roam.org b/doc/org-roam.org index 4879517..4619166 100644 --- a/doc/org-roam.org +++ b/doc/org-roam.org @@ -1439,6 +1439,82 @@ Essentially, to migrate notes from v1 to v2, one must: and the ~ROAM_TAGS~ property for headline nodes 6. Replace existing file links with ID links. +** How do I publish my notes with an Internet-friendly graph? + +The default graph builder creates a graph with an [[https://orgmode.org/worg/org-contrib/org-protocol.html][org-protocol]] +handler which is convenient when you're working locally but +inconvenient when you want to publish your notes for remote access. +Likewise, it defaults to displaying the graph in Emacs which has the +exact same caveats. This problem is solvable in the following way +using org-mode's native [[https://orgmode.org/manual/Publishing.html][publishing]] capability: + +1. configure org-mode to publish your org-roam notes as a project. +2. create a function that overrides the default org-protocol link + creation function(=org-roam-default-link-builder=). +3. create a hook that's called at the end of graph creation to copy + the generated graph to the appropriate place. + +The example code below is used to publish to a local directory where a +separate shell script copies the files to the remote site. + +*** Configure org-mode for publishing +This has two steps: +1. Setting of a /roam/ project that publishes your notes. +2. Configuring the /sitemap.html/ generation. +3. Setting up =org-publish= to generate the graph. + +This will require code like the following: +#+begin_src emacs-lisp + (defun roam-sitemap (title list) + (concat "#+OPTIONS: ^:nil author:nil html-postamble:nil\n" + "#+SETUPFILE: ./simple_inline.theme\n" + "#+TITLE: " title "\n\n" + (org-list-to-org list) "\nfile:sitemap.svg")) + + (setq my-publish-time 0) ; see the next section for context + (defun roam-publication-wrapper (plist filename pubdir) + (org-roam-graph) + (org-html-publish-to-html plist filename pubdir) + (setq my-publish-time (cadr (current-time)))) + + (setq org-publish-project-alist + '(("roam" + :base-directory "~/roam" + :auto-sitemap t + :sitemap-function roam-sitemap + :sitemap-title "Roam notes" + :publishing-function roam-publication-wrapper + :publishing-directory "~/roam-export" + :section-number nil + :table-of-contents nil + :style ""))) +#+end_src + +*** Overriding the default link creation function +The code below will generate a link to the generated html file instead +of the default org-protocol link. +#+begin_src emacs-lisp + (defun org-roam-custom-link-builder (node) + (let ((file (org-roam-node-file node))) + (concat (file-name-base file) ".html"))) + + (setq org-roam-graph-link-builder 'org-roam-custom-link-builder) +#+end_src + +*** Copying the generated file to the export directory +The default behavior of =org-roam-graph= is to generate the graph and +display it in Emacs. There is an =org-roam-graph-generation-hook= +available that provides access to the file names so they can be copied +to the publishing directory. Example code follows: + +#+begin_src emacs-lisp + (add-hook 'org-roam-graph-generation-hook + (lambda (dot svg) (if (< (- (cadr (current-time)) my-publish-time) 5) + (progn (copy-file svg "~/roam-export/sitemap.svg" 't) + (kill-buffer (file-name-nondirectory svg)) + (setq my-publish-time 0))))) +#+end_src + * Developer's Guide to Org-roam ** Org-roam's Design Principle diff --git a/doc/org-roam.texi b/doc/org-roam.texi index d6d584d..0e7b33d 100644 --- a/doc/org-roam.texi +++ b/doc/org-roam.texi @@ -86,7 +86,6 @@ General Public License for more details. * Command Index:: * Function Index:: * Variable Index:: -* Bibliography: Bibliography (1). @detailmenu --- The Detailed Node Listing --- @@ -190,6 +189,13 @@ FAQ * How can I stop Org-roam from creating IDs everywhere?:: * How do I migrate from Roam Research?:: * How to migrate from Org-roam v1?:: +* How do I publish my notes with an Internet-friendly graph?:: + +How do I publish my notes with an Internet-friendly graph? + +* Configure org-mode for publishing:: +* Overriding the default link creation function:: +* Copying the generated file to the export directory:: Developer's Guide to Org-roam @@ -1059,7 +1065,7 @@ Remove a ref from the node at point. Since version 9.5, Org has first-class support for citations. Org-roam supports the caching of both these in-built citations (of form @code{[cite:@@key]}) and @uref{https://github.com/jkitchin/org-ref, org-ref} -citations (of form (NO@math{_ITEM}@math{_DATA}:key)). +citations (of form @uref{key}). Org-roam attempts to load both the @code{org-ref} and @code{org-cite} package when indexing files, so no further setup from the user is required for citation @@ -1914,6 +1920,7 @@ Org-mode, and sync your cards to Anki via @uref{https://github.com/FooSoft/anki- * How can I stop Org-roam from creating IDs everywhere?:: * How do I migrate from Roam Research?:: * How to migrate from Org-roam v1?:: +* How do I publish my notes with an Internet-friendly graph?:: @end menu @node How do I have more than one Org-roam directory? @@ -2008,6 +2015,109 @@ and the @code{ROAM_TAGS} property for headline nodes Replace existing file links with ID links. @end itemize +@node How do I publish my notes with an Internet-friendly graph? +@section How do I publish my notes with an Internet-friendly graph? + +The default graph builder creates a graph with an @uref{https://orgmode.org/worg/org-contrib/org-protocol.html, org-protocol} +handler which is convenient when you're working locally but +inconvenient when you want to publish your notes for remote access. +Likewise, it defaults to displaying the graph in Emacs which has the +exact same caveats. This problem is solvable in the following way +using org-mode's native @uref{https://orgmode.org/manual/Publishing.html, publishing} capability: + +@itemize +@item +configure org-mode to publish your org-roam notes as a project. + +@item +create a function that overrides the default org-protocol link +creation function(@samp{org-roam-default-link-builder}). + +@item +create a hook that's called at the end of graph creation to copy +the generated graph to the appropriate place. +@end itemize + +The example code below is used to publish to a local directory where a +separate shell script copies the files to the remote site. + +@menu +* Configure org-mode for publishing:: +* Overriding the default link creation function:: +* Copying the generated file to the export directory:: +@end menu + +@node Configure org-mode for publishing +@subsection Configure org-mode for publishing + +This has two steps: +@itemize +@item +Setting of a @emph{roam} project that publishes your notes. + +@item +Configuring the @emph{sitemap.html} generation. + +@item +Setting up @samp{org-publish} to generate the graph. +@end itemize + +This will require code like the following: +@lisp +(defun roam-sitemap (title list) + (concat "#+OPTIONS: ^:nil author:nil html-postamble:nil\n" + "#+SETUPFILE: ./simple_inline.theme\n" + "#+TITLE: " title "\n\n" + (org-list-to-org list) "\nfile:sitemap.svg")) + +(setq my-publish-time 0) ; see the next section for context +(defun roam-publication-wrapper (plist filename pubdir) + (org-roam-graph) + (org-html-publish-to-html plist filename pubdir) + (setq my-publish-time (cadr (current-time)))) + +(setq org-publish-project-alist + '(("roam" + :base-directory "~/roam" + :auto-sitemap t + :sitemap-function roam-sitemap + :sitemap-title "Roam notes" + :publishing-function roam-publication-wrapper + :publishing-directory "~/roam-export" + :section-number nil + :table-of-contents nil + :style ""))) +@end lisp + +@node Overriding the default link creation function +@subsection Overriding the default link creation function + +The code below will generate a link to the generated html file instead +of the default org-protocol link. +@lisp +(defun org-roam-custom-link-builder (node) + (let ((file (org-roam-node-file node))) + (concat (file-name-base file) ".html"))) + +(setq org-roam-graph-link-builder 'org-roam-custom-link-builder) +@end lisp + +@node Copying the generated file to the export directory +@subsection Copying the generated file to the export directory + +The default behavior of @samp{org-roam-graph} is to generate the graph and +display it in Emacs. There is an @samp{org-roam-graph-generation-hook} +available that provides access to the file names so they can be copied +to the publishing directory. Example code follows: + +@lisp +(add-hook 'org-roam-graph-generation-hook + (lambda (dot svg) (if (< (- (cadr (current-time)) my-publish-time) 5) + (progn (copy-file svg "~/roam-export/sitemap.svg" 't) + (kill-buffer (file-name-nondirectory svg)) + (setq my-publish-time 0))))) +@end lisp + @node Developer's Guide to Org-roam @chapter Developer's Guide to Org-roam @@ -2260,10 +2370,5 @@ When GOTO is non-nil, go the note without creating an entry." @printindex vr -@node Bibliography (1) -@chapter Bibliography - -NO@math{_ITEM}@math{_DATA}:key - -Emacs 28.0.50 (Org mode N/A) +Emacs 29.0.50 (Org mode 9.6) @bye diff --git a/extensions/org-roam-graph.el b/extensions/org-roam-graph.el index 152e620..c7c56d1 100644 --- a/extensions/org-roam-graph.el +++ b/extensions/org-roam-graph.el @@ -113,6 +113,25 @@ All other values including nil will have no effect." (const :tag "no" nil)) :group 'org-roam) +(defcustom org-roam-graph-link-builder 'org-roam-org-protocol-link-builder + "Function used to build the Org-roam graph links. +Given a node name, return a string to be used for the link fed to +the graph generation utility." + :type 'function + :group 'org-roam) + +(defcustom org-roam-graph-generation-hook nil + "Functions to run after the graph has been generated. +Each function is called with two arguments: the filename +containing the graph generation tool, and the generated graph." + :type 'hook + :group 'org-roam) + +(defun org-roam-org-protocol-link-builder (node) + "Default org-roam link builder. Generate an org-protocol link using NODE." + (concat "org-protocol://roam-node?node=" + (url-hexify-string (org-roam-node-id node)))) + ;;; Interactive command ;;;###autoload (defun org-roam-graph (&optional arg node) @@ -153,7 +172,8 @@ CALLBACK is passed the graph file as its sole argument." :sentinel (when callback (lambda (process _event) (when (= 0 (process-exit-status process)) - (funcall callback temp-graph))))))) + (progn (funcall callback temp-graph) + (run-hook-with-args 'org-roam-graph-generation-hook temp-dot temp-graph)))))))) (defun org-roam-graph--dot (&optional edges all-nodes) "Build the graphviz given the EDGES of the graph. @@ -250,8 +270,7 @@ Handles both Org-roam nodes, and string nodes (e.g. urls)." (_ title))))) (setq node-id (org-roam-node-id node) node-properties `(("label" . ,shortened-title) - ("URL" . ,(concat "org-protocol://roam-node?node=" - (url-hexify-string (org-roam-node-id node)))) + ("URL" . ,(funcall org-roam-graph-link-builder node)) ("tooltip" . ,(xml-escape-string title))))) (setq node-id node node-properties (append `(("label" . ,(concat type ":" node)))