diff options
-rw-r--r-- | org-roam-ui.el | 149 |
1 files changed, 107 insertions, 42 deletions
diff --git a/org-roam-ui.el b/org-roam-ui.el index 473f479..80991ad 100644 --- a/org-roam-ui.el +++ b/org-roam-ui.el @@ -1,65 +1,130 @@ + ;;; org-roam-ui.el --- User Interface for Org-roam -*- coding: utf-8; lexical-binding: t; -*- + +;; Copyright © 2021 ... + +;; Author: ... +;; URL: https://github.com/org-roam/org-roam-ui +;; Keywords: org-mode, roam +;; Version: ... +;; Package-Requires: ((emacs "26.1") (f "0.17.2") (org-roam "2.0.0")) + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; Org-roam-ui provides a web interface for navigating around notes created +;; within Org-roam. +;; +;;; Code: +;;;; Dependencies (require 'f) (require 'json) (require 'simple-httpd) +(require 'org-roam) + +(defgroup org-roam-ui nil + "UI in Org-roam." + :group 'org-roam + :prefix "org-roam-ui-" + :link '(url-link :tag "Github" "https://github.com/org-roam/org-roam-ui")) + +(defvar org-roam-ui/root-dir default-directory + "Root directory of the org-roam-ui project.") + +(defvar org-roam-ui/app-build-dir (expand-file-name "./web-build/") + "Directory containing org-roam-ui's web build.") -(defvar org-roam-ui/root-dir - (concat - (file-name-directory - (f-full (or - load-file-name - buffer-file-name))) ".")) +;;; Dynamic variables +(defvar org-roam-ui-current-node-id nil + "The current node id Org-roam is tracking.") -(setq org-roam-ui/app-build-dir (expand-file-name "./web-build/" org-roam-ui/root-dir)) +;; TODO: make into defcustom +(defvar org-roam-ui-port + 35901 + "Port to serve the org-roam-ui interface.") (define-minor-mode org-roam-ui-mode - "Start the http API for org-roam-ui." - :lighter "" + "Enable org-roam-ui. +This serves the web-build and API over HTTP." + :lighter "org-roam-ui " :global t :group 'org-roam-ui :init-value nil (cond (org-roam-ui-mode - (setq-local httpd-port 35901) - (setq httpd-root org-roam-ui/app-build-dir) - (httpd-start)) + (setq httpd-port org-roam-ui-port + httpd-root org-roam-ui/app-build-dir) + (httpd-start) + (add-hook 'post-command-hook #'org-roam-ui-update)) (t + (remove-hook 'post-command-hook #'org-roam-ui-update) (httpd-stop)))) - (defservlet* graph application/json () - (let* ( - (nodes-db-rows (org-roam-db-query `[:select [*] :from nodes])) - (links-db-rows (org-roam-db-query `[:select [*] :from links :where (= type "id")])) - (response (json-encode (list - (cons 'nodes (mapcar 'nodes-row-to-cons nodes-db-rows)) - (cons 'links (mapcar 'links-row-to-cons links-db-rows)))))) - (progn - (insert response) - (httpd-send-header t "application/json" 200 :Access-Control-Allow-Origin "*")))) + (let* ((nodes-columns [id file title]) + (links-columns [source dest]) + (nodes-db-rows (org-roam-db-query `[:select ,nodes-columns :from nodes])) + (links-db-rows (org-roam-db-query `[:select ,links-columns :from links :where (= type "id")])) + (response (json-encode `((nodes . ,(mapcar (apply-partially #'org-roam-ui-sql-to-alist (append nodes-columns nil)) nodes-db-rows)) + (links . ,(mapcar (apply-partially #'org-roam-ui-sql-to-alist '(source target)) links-db-rows)))))) + (insert response) + (httpd-send-header t "application/json" 200 :Access-Control-Allow-Origin "*"))) -(defun nodes-row-to-cons (row) - (list - (cons 'id (elt row 0)) - (cons 'file (elt row 1)) - (cons 'title (elt row 8)))) - -(defun links-row-to-cons (row) - (list - (cons 'source (elt row 1)) - (cons 'target (elt row 2)))) +(defun org-roam-ui-sql-to-alist (column-names rows) + "Convert sql result to alist for json encoding. +ROWS is the sql result, while COLUMN-NAMES is the columns to use." + (let (res) + (while rows + (push (cons (pop column-names) (pop rows)) res)) + res)) (defservlet* theme application/json () - (if - (boundp 'doom-themes--colors) + (when (boundp 'doom-themes--colors) (let* - ((colors (butlast doom-themes--colors (- (length doom-themes--colors) 25))) - (ui-theme)) - (progn - (dolist (color colors) - (push (cons (car color) (car (cdr color))) ui-theme)) - (insert (json-encode ui-theme)))) - (insert "{}")) - (httpd-send-header t "text/plain" 200 :Access-Control-Allow-Origin "*")) + ((colors (butlast doom-themes--colors (- (length doom-themes--colors) 25))) + ui-theme (list nil)) + (progn + (dolist (color colors) + (push (cons (car color) (car (cdr color))) ui-theme)) + (insert (json-encode ui-theme)) + (httpd-send-header t "text/plain" 200 :Access-Control-Allow-Origin "*"))))) + +(defservlet* id/:id text/html () + (let ((node (org-roam-populate (org-roam-node-create :id id))) + html-string) + (org-roam-with-temp-buffer (org-roam-node-file node) + (setq-local org-export-with-toc nil) + (setq-local org-export-with-broken-links t) + (setq-local org-export-with-sub-superscripts nil) + (setq html-string (org-export-as 'html))) + (insert html-string))) + +(defservlet* current-node-data text/event-stream () + (insert (format "data: %s\n\n" + org-roam-ui-current-node-id))) + +(defun org-roam-ui-update () + "Track changes within Emacs to update Org-roam UI. +This function is added to `post-command-hook'." + (setq org-roam-ui-current-node-id + (or (org-roam-id-at-point) + org-roam-ui-current-node-id))) (provide 'org-roam-ui) +;;; org-roam-ui.el ends here |