Compare commits
1
Commits
main
..
de61e45637
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de61e45637 |
No files matched your search
@@ -1 +0,0 @@
|
|||||||
((nil . ((cider-clojure-cli-aliases . ":dev:test"))))
|
|
||||||
@@ -9,3 +9,5 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: build doerg
|
- name: build doerg
|
||||||
run: nix build -L .#doerg
|
run: nix build -L .#doerg
|
||||||
|
- name: build publisher
|
||||||
|
run: nix build -L .#publisher
|
||||||
@@ -9,6 +9,7 @@ result-*
|
|||||||
.lsp
|
.lsp
|
||||||
.nrepl
|
.nrepl
|
||||||
.direnv/
|
.direnv/
|
||||||
|
resources/vendor/*
|
||||||
node_modules
|
node_modules
|
||||||
.cljs_node_repl
|
.cljs_node_repl
|
||||||
build/
|
build/
|
||||||
|
|||||||
+29
-1
@@ -1,6 +1,14 @@
|
|||||||
{
|
{
|
||||||
"lock-version": 4,
|
"lock-version": 4,
|
||||||
"git-deps": [],
|
"git-deps": [
|
||||||
|
{
|
||||||
|
"lib": "io.github.msyds/spec-dict",
|
||||||
|
"url": "https://github.com/msyds/spec-dict.git",
|
||||||
|
"rev": "531d629b7f05f37232261cf9e8927a4b5915714f",
|
||||||
|
"git-dir": "https/github.com/msyds/spec-dict",
|
||||||
|
"hash": "sha256-5hMdPsB8OhOCtByPZS+CHXzVLq0H+OBKKnXec21xwmg="
|
||||||
|
}
|
||||||
|
],
|
||||||
"mvn-deps": [
|
"mvn-deps": [
|
||||||
{
|
{
|
||||||
"mvn-path": "aero/aero/1.1.6/aero-1.1.6.jar",
|
"mvn-path": "aero/aero/1.1.6/aero-1.1.6.jar",
|
||||||
@@ -137,6 +145,11 @@
|
|||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
"hash": "sha256-ccrFOSFR4qUozJoJF58KM0F58FxS+OWWz1jd8Suyfys="
|
"hash": "sha256-ccrFOSFR4qUozJoJF58KM0F58FxS+OWWz1jd8Suyfys="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mvn-path": "com/fasterxml/jackson/core/jackson-core/2.20.0/jackson-core-2.20.0.jar",
|
||||||
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
|
"hash": "sha256-vAz0YHWHcgH4QG7n3idBrn32wGb18EV72AYypxjAbnI="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "com/fasterxml/jackson/core/jackson-core/2.20.0/jackson-core-2.20.0.pom",
|
"mvn-path": "com/fasterxml/jackson/core/jackson-core/2.20.0/jackson-core-2.20.0.pom",
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
@@ -357,6 +370,11 @@
|
|||||||
"mvn-repo": "https://repo.clojars.org/",
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.jar",
|
||||||
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
|
"hash": "sha256-98tpbM5Vr9dMg41UQUGcfl9tSRrxhajlY9+nl5aFcoM="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.pom",
|
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.pom",
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
@@ -952,6 +970,11 @@
|
|||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.jar",
|
||||||
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
|
"hash": "sha256-UfmOunss1C7jDzgmkl3N6HkRZ/dvcSMprlG4gkToE44="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.pom",
|
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.pom",
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
@@ -1102,6 +1125,11 @@
|
|||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
"hash": "sha256-E15H98p5wKoYG2kJPML50aYyKt1qgli2aXxQCNIwv00="
|
"hash": "sha256-E15H98p5wKoYG2kJPML50aYyKt1qgli2aXxQCNIwv00="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mvn-path": "org/clojure/tools.reader/1.3.6/tools.reader-1.3.6.jar",
|
||||||
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
|
"hash": "sha256-EdGzHyxlwzVbKSu5tEuPyv2lS0TaY+NKuXt5qKs7uOA="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/tools.reader/1.3.6/tools.reader-1.3.6.pom",
|
"mvn-path": "org/clojure/tools.reader/1.3.6/tools.reader-1.3.6.pom",
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
{:deps {aero/aero #:mvn{:version "1.1.6"}
|
|
||||||
babashka/fs #:mvn{:version "0.5.24"}
|
|
||||||
babashka/process #:mvn{:version "0.6.25"}
|
|
||||||
ch.qos.logback/logback-classic #:mvn{:version "1.1.3"}
|
|
||||||
cheshire/cheshire #:mvn{:version "6.1.0"}
|
|
||||||
com.github.seancorfield/next.jdbc #:mvn{:version "1.3.1070"}
|
|
||||||
com.rpl/specter #:mvn{:version "1.1.6"}
|
|
||||||
hiccup/hiccup #:mvn{:version "2.0.0-RC4"}
|
|
||||||
http-kit/http-kit #:mvn{:version "2.8.0"}
|
|
||||||
instaparse/instaparse #:mvn{:version "1.5.0"}
|
|
||||||
metosin/reitit #:mvn{:version "0.10.1"}
|
|
||||||
mvxcvi/clj-cbor #:mvn{:version "1.1.1"}
|
|
||||||
org.clojars.pntblnk/clj-ldap #:mvn{:version "0.0.17"}
|
|
||||||
org.clojure/clojure #:mvn{:version "1.12.0"}
|
|
||||||
org.clojure/core.match #:mvn{:version "1.1.0"}
|
|
||||||
org.clojure/test.check #:mvn{:version "1.1.3"}
|
|
||||||
org.clojure/tools.logging #:mvn{:version "1.3.0"}
|
|
||||||
org.xerial/sqlite-jdbc #:mvn{:version "3.47.1.0"}}
|
|
||||||
:paths ["src" "resources"]
|
|
||||||
:aliases
|
|
||||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
|
||||||
:extra-paths ["test"]
|
|
||||||
:main-opts ["-m" "kaocha.runner"]}
|
|
||||||
:dev {:extra-paths ["dev"]}}}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
(ns user
|
|
||||||
(:require [net.deertopia.doerg.server :as server]
|
|
||||||
[net.deertopia.doerg.config :as cfg]
|
|
||||||
[net.deertopia.doerg.cached-file :as cached-file]
|
|
||||||
[babashka.fs :as fs]))
|
|
||||||
|
|
||||||
(cfg/load-config! :profile :dev)
|
|
||||||
|
|
||||||
(when (not= :running (server/status))
|
|
||||||
(server/start!))
|
|
||||||
|
|
||||||
(defn invalidate-html-cache! []
|
|
||||||
(fs/delete-tree (server/html-dir))
|
|
||||||
nil)
|
|
||||||
|
|
||||||
(defn toggle-html-cache! []
|
|
||||||
(alter-var-root #'cached-file/*use-cache?* not))
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#+title: Doerg specification
|
||||||
|
#+author: Guppy
|
||||||
|
|
||||||
|
* Footnotes
|
||||||
|
|
||||||
|
- A bunch of metadata should be read into a node of type =doerg-data=
|
||||||
@@ -4,9 +4,8 @@
|
|||||||
, doerg-parser
|
, doerg-parser
|
||||||
, doerg-temml-worker
|
, doerg-temml-worker
|
||||||
, ibm-plex-web
|
, ibm-plex-web
|
||||||
, test-emacs ? callPackage ./test-emacs.nix {}
|
|
||||||
, fake-git
|
, fake-git
|
||||||
, our-tex
|
, our-tex ? callPackage ./our-tex.nix {}
|
||||||
, makeWrapper
|
, makeWrapper
|
||||||
, writeText
|
, writeText
|
||||||
}:
|
}:
|
||||||
@@ -33,8 +32,8 @@ let
|
|||||||
];
|
];
|
||||||
|
|
||||||
doerg-config = writeText "doerg-extra-config.edn" ''
|
doerg-config = writeText "doerg-extra-config.edn" ''
|
||||||
#:net.deertopia.doerg.config
|
#:net.deertopia.doerg
|
||||||
{:ibm-plex-web "${ibm-plex-web}/share/ibm-plex-web"
|
{:ibm-plex-web "${ibm-plex-web}"
|
||||||
:latex "${lib.getExe' our-tex "xelatex"}"
|
:latex "${lib.getExe' our-tex "xelatex"}"
|
||||||
:dvisvgm "${lib.getExe' our-tex "dvisvgm"}"
|
:dvisvgm "${lib.getExe' our-tex "dvisvgm"}"
|
||||||
:doerg-temml-worker "${lib.getExe doerg-temml-worker}"
|
:doerg-temml-worker "${lib.getExe doerg-temml-worker}"
|
||||||
@@ -43,21 +42,15 @@ let
|
|||||||
in mkCljBin' {
|
in mkCljBin' {
|
||||||
name = "net.deertopia/doerg";
|
name = "net.deertopia/doerg";
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
projectSrc = lib.cleanSourceWith {
|
projectSrc = lib.cleanSource ./.;
|
||||||
filter = path: type:
|
lockfile = ../deps-lock.json;
|
||||||
lib.sources.cleanSourceFilter path type
|
|
||||||
|| lib.hasSuffix ".nix" path;
|
|
||||||
src = ./.;
|
|
||||||
};
|
|
||||||
lockfile = ./deps-lock.json;
|
|
||||||
main-ns = "net.deertopia.doerg.main";
|
main-ns = "net.deertopia.doerg.main";
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
plex
|
plex
|
||||||
makeWrapper
|
makeWrapper
|
||||||
];
|
];
|
||||||
propagatedBuildInputs = [
|
buildInputs = [
|
||||||
doerg-parser
|
doerg-parser
|
||||||
ibm-plex-web
|
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
plex
|
plex
|
||||||
our-tex
|
our-tex
|
||||||
@@ -65,7 +58,6 @@ in mkCljBin' {
|
|||||||
nativeCheckInputs = [
|
nativeCheckInputs = [
|
||||||
doerg-parser
|
doerg-parser
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
test-emacs
|
|
||||||
plex
|
plex
|
||||||
our-tex
|
our-tex
|
||||||
];
|
];
|
||||||
@@ -74,11 +66,6 @@ in mkCljBin' {
|
|||||||
'';
|
'';
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
checkPhase = ''
|
checkPhase = ''
|
||||||
export \
|
|
||||||
EMACS=test-emacs \
|
|
||||||
XDG_STATE_HOME=$(mktemp -d "state-home-XXXXXX")
|
|
||||||
clojure -M:test
|
clojure -M:test
|
||||||
'';
|
'';
|
||||||
passthru = { inherit plex our-tex test-emacs doerg-config; };
|
|
||||||
meta.mainProgram = "doerg";
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{:deps {org.clojure/tools.logging {:mvn/version "1.3.0"}
|
||||||
|
babashka/fs {:mvn/version "0.5.24"}
|
||||||
|
org.clojure/core.match {:mvn/version "1.1.0"}
|
||||||
|
cheshire/cheshire {:mvn/version "6.1.0"}
|
||||||
|
babashka/process {:mvn/version "0.6.25"}
|
||||||
|
io.github.msyds/spec-dict
|
||||||
|
{:git/sha "531d629b7f05f37232261cf9e8927a4b5915714f"}
|
||||||
|
hiccup/hiccup {:mvn/version "2.0.0-RC4"}
|
||||||
|
com.rpl/specter {:mvn/version "1.1.6"}
|
||||||
|
mvxcvi/clj-cbor {:mvn/version "1.1.1"}
|
||||||
|
ch.qos.logback/logback-classic {:mvn/version "1.1.3"}
|
||||||
|
org.clojure/test.check {:mvn/version "1.1.3"}
|
||||||
|
aero/aero {:mvn/version "1.1.6"}}
|
||||||
|
:paths ["src" "resources"]
|
||||||
|
:aliases
|
||||||
|
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||||
|
:extra-paths ["test"]
|
||||||
|
:main-opts ["-m" "kaocha.runner"]}}}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,11 @@
|
|||||||
|
#:net.deertopia.doerg
|
||||||
|
{:ibm-plex-web #or [#xdg-data-dir "ibm-plex-web"
|
||||||
|
#env IBM_PLEX_WEB]
|
||||||
|
:latex "xelatex"
|
||||||
|
:dvisvgm "dvisvgm"
|
||||||
|
:doerg-temml-worker
|
||||||
|
#profile {:dev #file "../../../../doerg-temml-worker/index.js"
|
||||||
|
:default "doerg-temml-worker"}
|
||||||
|
:doerg-parser
|
||||||
|
#profile {:dev #file "../../../../doerg-parser/index.js"
|
||||||
|
:default "doerg-parser"}}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -438,7 +438,7 @@ label.margin-toggle:not(.sidenote-number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.org-link.external::after
|
.link.external::after
|
||||||
{ content: "↗"
|
{ content: "↗"
|
||||||
; vertical-align: super
|
; vertical-align: super
|
||||||
; font-size: 1rem
|
; font-size: 1rem
|
||||||
@@ -446,8 +446,8 @@ label.margin-toggle:not(.sidenote-number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.center
|
.center
|
||||||
{ align-items: center
|
{ align-items: "center"
|
||||||
; justify-content: center
|
; justify-content: "center"
|
||||||
; display: flex
|
; display: flex
|
||||||
; max-width: 55%
|
; max-width: 55%
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
(ns scratch
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[spec-dict.main :refer [dict]]
|
||||||
|
[clojure.test.check.generators :as gen]))
|
||||||
|
|
||||||
|
|
||||||
|
(defmulti node-spec :type)
|
||||||
|
|
||||||
|
(s/def ::node
|
||||||
|
(s/multi-spec node-spec :type))
|
||||||
|
|
||||||
|
(s/def ::children (s/coll-of ::node :kind vector?))
|
||||||
|
|
||||||
|
(s/def ::value nat-int?)
|
||||||
|
|
||||||
|
(defmethod node-spec :branch [_]
|
||||||
|
(dict {:children ::children})
|
||||||
|
#_(s/keys :req-un [::children]))
|
||||||
|
|
||||||
|
(defmethod node-spec :leaf [_]
|
||||||
|
(dict {:value ::value})
|
||||||
|
#_
|
||||||
|
(s/keys :req-un [::value]))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(binding [s/*recursion-limit* 1]
|
||||||
|
(gen/generate (s/gen ::node))))
|
||||||
File renamed without changes.
@@ -1,25 +1,25 @@
|
|||||||
(ns net.deertopia.doerg.config
|
(ns net.deertopia.doerg.config
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[babashka.fs :as fs]
|
[babashka.fs :as fs]
|
||||||
|
[spec-dict.main :refer [dict]]
|
||||||
[aero.core :as aero]
|
[aero.core :as aero]
|
||||||
|
[net.deertopia.doerg :as-alias d]
|
||||||
[clojure.java.io :as io]))
|
[clojure.java.io :as io]))
|
||||||
|
|
||||||
(s/def ::config
|
(s/def ::d/config
|
||||||
(s/keys :req [::ibm-plex-web
|
(s/keys :req [::d/ibm-plex-web
|
||||||
::latex
|
::d/latex
|
||||||
::dvisvgm
|
::d/dvisvgm
|
||||||
::doerg-temml-worker
|
::d/doerg-temml-worker
|
||||||
::doerg-parser
|
::d/doerg-parser]))
|
||||||
::state-directory
|
|
||||||
::org-roam-db-path]))
|
|
||||||
|
|
||||||
(s/def ::directory
|
(s/def ::d/directory
|
||||||
(s/conformer #(fs/file %)))
|
(s/conformer #(fs/file %)))
|
||||||
|
|
||||||
(s/def ::file
|
(s/def ::d/file
|
||||||
(s/conformer #(-> % fs/expand-home fs/file)))
|
(s/conformer #(-> % fs/expand-home fs/file)))
|
||||||
|
|
||||||
(s/def ::executable
|
(s/def ::d/executable
|
||||||
(s/conformer
|
(s/conformer
|
||||||
;; I'd love to use `fs/which` here, but it's fairly problematic to
|
;; I'd love to use `fs/which` here, but it's fairly problematic to
|
||||||
;; check `fs/executable?` at… build time (which `fs/which` does)?
|
;; check `fs/executable?` at… build time (which `fs/which` does)?
|
||||||
@@ -28,26 +28,22 @@
|
|||||||
(some-> % fs/expand-home fs/file)
|
(some-> % fs/expand-home fs/file)
|
||||||
::s/invalid)))
|
::s/invalid)))
|
||||||
|
|
||||||
(s/def ::ibm-plex-web ::directory)
|
(s/def ::d/ibm-plex-web ::d/directory)
|
||||||
|
|
||||||
(s/def ::latex ::executable)
|
(s/def ::d/latex ::d/executable)
|
||||||
|
|
||||||
(s/def ::dvisvgm ::executable)
|
(s/def ::d/dvisvgm ::d/executable)
|
||||||
|
|
||||||
(s/def ::doerg-temml-worker ::executable)
|
(s/def ::d/doerg-temml-worker ::d/executable)
|
||||||
|
|
||||||
(s/def ::doerg-parser ::executable)
|
(s/def ::d/doerg-parser ::d/executable)
|
||||||
|
|
||||||
(s/def ::state-directory ::file)
|
|
||||||
(s/def ::org-roam-db-path ::file)
|
|
||||||
|
|
||||||
(defmethod aero/reader 'xdg-data-dir
|
(defmethod aero/reader 'xdg-data-dir
|
||||||
[_opts tag value]
|
[_opts tag value]
|
||||||
"Aero tag to search for a directory on $XDG_DATA_DIRS."
|
"Aero tag to search for a directory on $XDG_DATA_DIRS."
|
||||||
(some #(let [x (fs/path % value)]
|
(some #(let [x (fs/path % value)]
|
||||||
(and (fs/exists? x) x))
|
(and (fs/exists? x) x))
|
||||||
(some-> (System/getenv "XDG_DATA_DIRS")
|
(fs/split-paths (System/getenv "XDG_DATA_DIRS"))))
|
||||||
fs/split-paths)))
|
|
||||||
|
|
||||||
(defmethod aero/reader 'file
|
(defmethod aero/reader 'file
|
||||||
[{:keys [source]} tag value]
|
[{:keys [source]} tag value]
|
||||||
@@ -56,16 +52,19 @@
|
|||||||
(-> (aero/relative-resolver source value)
|
(-> (aero/relative-resolver source value)
|
||||||
fs/file))
|
fs/file))
|
||||||
|
|
||||||
(defn read-config [files & {:as opts}]
|
(defn read-config [spec files & {:as opts}]
|
||||||
(let [r (->> files
|
(let [r (->> files
|
||||||
(filter identity)
|
(filter identity)
|
||||||
(map #(aero/read-config % opts))
|
(map #(aero/read-config % opts))
|
||||||
(apply merge))
|
(apply merge))
|
||||||
conformed (s/conform ::config r)]
|
conformed (s/conform spec r)]
|
||||||
(if-not (s/invalid? conformed)
|
(if-not (s/invalid? conformed)
|
||||||
conformed
|
conformed
|
||||||
(throw (ex-info "Failed to conform config"
|
(throw (ex-info "Failed to conform config"
|
||||||
(s/explain-data ::config r))))))
|
(s/explain-data spec r))))))
|
||||||
|
|
||||||
|
(defn load-config! [var spec files & {:as opts}]
|
||||||
|
(alter-var-root var (constantly (read-config spec files opts))))
|
||||||
|
|
||||||
(def sources
|
(def sources
|
||||||
[;; Default config.
|
[;; Default config.
|
||||||
@@ -75,13 +74,6 @@
|
|||||||
;; Config set at runtime.
|
;; Config set at runtime.
|
||||||
(System/getenv "DOERG_CONFIG")])
|
(System/getenv "DOERG_CONFIG")])
|
||||||
|
|
||||||
(def default (read-config sources))
|
(def default (read-config ::d/config sources))
|
||||||
|
|
||||||
(def ^:dynamic *cfg* default)
|
(def ^:dynamic *cfg* default)
|
||||||
|
|
||||||
(defn load-config!
|
|
||||||
([& {:as opts :keys [files]
|
|
||||||
:or {files sources}}]
|
|
||||||
(let [passthru-opts (-> opts (dissoc :files))]
|
|
||||||
(alter-var-root
|
|
||||||
#'*cfg* (constantly (read-config files passthru-opts))))))
|
|
||||||
@@ -4,8 +4,10 @@
|
|||||||
[babashka.process :as p]
|
[babashka.process :as p]
|
||||||
[cheshire.core :as json]
|
[cheshire.core :as json]
|
||||||
[clojure.core.match :refer [match]]
|
[clojure.core.match :refer [match]]
|
||||||
|
[net.deertopia.doerg :as-alias doerg]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[clojure.test.check.generators :as gen]
|
[clojure.test.check.generators :as gen]
|
||||||
[clojure.tools.logging.readable :as lr]
|
[clojure.tools.logging.readable :as lr]
|
||||||
@@ -14,6 +16,7 @@
|
|||||||
[com.rpl.specter.zipper :as sz]
|
[com.rpl.specter.zipper :as sz]
|
||||||
[net.deertopia.doerg.common :as common]
|
[net.deertopia.doerg.common :as common]
|
||||||
[net.deertopia.doerg.config :as cfg]
|
[net.deertopia.doerg.config :as cfg]
|
||||||
|
[spec-dict.main :refer [dict]]
|
||||||
[clojure.tools.logging :as l])
|
[clojure.tools.logging :as l])
|
||||||
(:import
|
(:import
|
||||||
(java.util UUID)))
|
(java.util UUID)))
|
||||||
@@ -34,7 +37,7 @@
|
|||||||
:or {in *in*}}]
|
:or {in *in*}}]
|
||||||
(let [r (-> (p/process
|
(let [r (-> (p/process
|
||||||
{:in in :out :string}
|
{:in in :out :string}
|
||||||
(-> cfg/*cfg* ::cfg/doerg-parser str))
|
(-> cfg/*cfg* ::doerg/doerg-parser str))
|
||||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||||
(when (zero? (:exit r))
|
(when (zero? (:exit r))
|
||||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||||
@@ -62,6 +65,8 @@
|
|||||||
(and (map? e) (contains? e :children)))
|
(and (map? e) (contains? e :children)))
|
||||||
|
|
||||||
(defn org-element? [element]
|
(defn org-element? [element]
|
||||||
|
#_
|
||||||
|
(s/valid? ::org-element element)
|
||||||
(and (map? element)
|
(and (map? element)
|
||||||
(contains? element :type)))
|
(contains? element :type)))
|
||||||
|
|
||||||
@@ -94,6 +99,16 @@
|
|||||||
(and (of-type? element "latex-fragment")
|
(and (of-type? element "latex-fragment")
|
||||||
(-> element :contents (str/starts-with? "\\[")))))
|
(-> element :contents (str/starts-with? "\\[")))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Spec
|
||||||
|
|
||||||
|
(s/def ::org-element
|
||||||
|
(dict {:type string?}
|
||||||
|
^:opt {:contents-begin nat-int?
|
||||||
|
:contents-end nat-int?
|
||||||
|
:children (s/coll-of ::org-element
|
||||||
|
:kind seq?)}))
|
||||||
|
|
||||||
|
|
||||||
;;; Zipper
|
;;; Zipper
|
||||||
|
|
||||||
@@ -300,3 +315,149 @@
|
|||||||
(recur (conj acc c) rest)
|
(recur (conj acc c) rest)
|
||||||
[] acc))))))
|
[] acc))))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Specs (top-level)
|
||||||
|
|
||||||
|
;; Data taken from uniorg/index.d.ts
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(defn- typescript-enum->set [s]
|
||||||
|
(as-> s
|
||||||
|
it
|
||||||
|
(str/split it #" \| ")
|
||||||
|
(map camel->kebab it)
|
||||||
|
(into #{} it))))
|
||||||
|
|
||||||
|
(def greater-element-types
|
||||||
|
#{"org-data" "section" "property-drawer" "drawer" "plain-list"
|
||||||
|
"list-item" "quote-block" "verse-block" "center-block"
|
||||||
|
"special-block" "footnote-definition" "table"})
|
||||||
|
|
||||||
|
(def element-types
|
||||||
|
#{"list-item-tag" "src-block" "comment-block" "latex-environment"
|
||||||
|
"keyword" "paragraph" "node-property" "example-block" "clock"
|
||||||
|
"planning" "diary-sexp" "fixed-width" "export-block"
|
||||||
|
"horizontal-rule" "comment" "table-row" "headline"})
|
||||||
|
|
||||||
|
(def recursive-object-types
|
||||||
|
#{"citation" "footnote-reference" "superscript" "table-cell" "link"
|
||||||
|
"italic" "citation-common-prefix" "subscript" "citation-prefix"
|
||||||
|
"citation-common-suffix" "strike-through" "citation-reference"
|
||||||
|
"bold" "underline"})
|
||||||
|
|
||||||
|
(def object-types
|
||||||
|
#{"line-break" "citation-suffix" "statistics-cookie" "timestamp"
|
||||||
|
"text" "verbatim" "citation-key" "export-snippet" "latex-fragment"
|
||||||
|
"entity" "code"})
|
||||||
|
|
||||||
|
(s/def ::greater-element-type greater-element-types)
|
||||||
|
(s/def ::element-type element-types)
|
||||||
|
(s/def ::object-type (set/union recursive-object-types object-types))
|
||||||
|
(s/def ::recursive-object-type recursive-object-types)
|
||||||
|
|
||||||
|
(s/def ::contents-begin nat-int?)
|
||||||
|
(s/def ::contents-end nat-int?)
|
||||||
|
|
||||||
|
(defmulti node-spec :type)
|
||||||
|
|
||||||
|
(defn- unimplemented-spec [x]
|
||||||
|
(lr/warnf "unimplemented method for %s" x)
|
||||||
|
(s/with-gen any?
|
||||||
|
(constantly (gen/return {}))))
|
||||||
|
|
||||||
|
(defmethod node-spec :default [x] (unimplemented-spec x))
|
||||||
|
|
||||||
|
(def ^:private nfe
|
||||||
|
"NFE — “no further expectations.” Used in sub-specs of `::element`
|
||||||
|
et al. for elements with no additional structure beyond that
|
||||||
|
provided by their parents."
|
||||||
|
(s/with-gen any?
|
||||||
|
(constantly (gen/return {}))))
|
||||||
|
|
||||||
|
(s/def ::node
|
||||||
|
(s/multi-spec node-spec :type))
|
||||||
|
|
||||||
|
(s/def :object/type ::object-type)
|
||||||
|
|
||||||
|
(s/def ::object
|
||||||
|
(s/keys :req-un [:object/type]))
|
||||||
|
|
||||||
|
(s/def :element/children (s/coll-of ::object :kind vector?))
|
||||||
|
(s/def :element/type ::element-type)
|
||||||
|
|
||||||
|
(s/def ::element
|
||||||
|
(s/keys :opt-un [::contents-begin ::contents-end]
|
||||||
|
:req-un [:element/children :element/type]))
|
||||||
|
|
||||||
|
(s/def :greater-element/children
|
||||||
|
(s/coll-of (s/merge
|
||||||
|
(dict {:type (set/union greater-element-types
|
||||||
|
element-types)})
|
||||||
|
::node)
|
||||||
|
:kind vector?))
|
||||||
|
|
||||||
|
(s/def :greater-element/type ::greater-element-type)
|
||||||
|
|
||||||
|
(s/def ::greater-element
|
||||||
|
(s/keys :req-un [::contents-begin ::contents-end
|
||||||
|
:greater-element/children
|
||||||
|
:greater-element/type]))
|
||||||
|
|
||||||
|
(s/def :recursive-object/children
|
||||||
|
(s/coll-of
|
||||||
|
(s/merge
|
||||||
|
(dict {:type ::object-type})
|
||||||
|
::node)
|
||||||
|
:kind vector?))
|
||||||
|
|
||||||
|
(s/def :recursive-object/type ::object-type)
|
||||||
|
|
||||||
|
(s/def ::recursive-object
|
||||||
|
(s/keys :opt-un [::contents-begin ::contents-end]
|
||||||
|
:req-un [:recursive-object/children
|
||||||
|
:recursive-object/type]))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(use 'net.deertopia.doerg.repl)
|
||||||
|
(def doc (-> "test/net/deertopia/doerg/element_test/paragraph-with-multiple-latex.org"
|
||||||
|
slurp
|
||||||
|
(read-string :post-processors
|
||||||
|
[gather-first-section])))
|
||||||
|
(s/explain ::node doc)
|
||||||
|
(binding [s/*recursion-limit* 1]
|
||||||
|
(gen/generate (s/gen ::node)))
|
||||||
|
(sp/select [postorder-walker (sp/must :children)
|
||||||
|
(sp/continuous-subseqs)]
|
||||||
|
doc))
|
||||||
|
|
||||||
|
(s/def ::todo-keyword string?)
|
||||||
|
(s/def ::priority string?)
|
||||||
|
(s/def ::commented boolean?)
|
||||||
|
(s/def ::level nat-int?)
|
||||||
|
(s/def ::tags (s/coll-of string? :kind vector?))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Specs (specific elements)
|
||||||
|
|
||||||
|
(def ^:private string-value (dict {:value string?}))
|
||||||
|
|
||||||
|
(defmethod node-spec "text" [_] (s/merge ::object string-value))
|
||||||
|
(defmethod node-spec "verbatim" [_] (s/merge ::object string-value))
|
||||||
|
(defmethod node-spec "code" [_] (s/merge ::object string-value))
|
||||||
|
(defmethod node-spec "bold" [_] ::recursive-object)
|
||||||
|
(defmethod node-spec "italic" [_] ::recursive-object)
|
||||||
|
|
||||||
|
(defmethod node-spec "headline" [_]
|
||||||
|
(s/merge ::element
|
||||||
|
(dict {:todo-keyword (s/nilable ::todo-keyword)
|
||||||
|
:priority (s/nilable ::priority)
|
||||||
|
:level ::level
|
||||||
|
:commented ::commented
|
||||||
|
:raw-value string?
|
||||||
|
:tags ::tags})))
|
||||||
|
|
||||||
|
(defmethod node-spec "org-data" [_]
|
||||||
|
::greater-element)
|
||||||
|
|
||||||
|
(defmethod node-spec "section" [_]
|
||||||
|
::greater-element)
|
||||||
File renamed without changes.
@@ -0,0 +1,5 @@
|
|||||||
|
(ns net.deertopia.doerg.main
|
||||||
|
(:gen-class))
|
||||||
|
|
||||||
|
(defn -main []
|
||||||
|
(println "hello from doerg"))
|
||||||
@@ -12,8 +12,7 @@
|
|||||||
[net.deertopia.doerg.tex :as tex]
|
[net.deertopia.doerg.tex :as tex]
|
||||||
[net.deertopia.doerg.tex.temml :as tex-temml]
|
[net.deertopia.doerg.tex.temml :as tex-temml]
|
||||||
[clojure.zip :as z]
|
[clojure.zip :as z]
|
||||||
[babashka.fs :as fs]
|
[babashka.fs :as fs]))
|
||||||
[clojure.edn :as edn]))
|
|
||||||
|
|
||||||
;;; Top-level API
|
;;; Top-level API
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@
|
|||||||
#(do (assert (element/of-type? % "keyword"))
|
#(do (assert (element/of-type? % "keyword"))
|
||||||
(:key %)))
|
(:key %)))
|
||||||
|
|
||||||
(def ^:dynamic ^:private *opts*)
|
(def ^:dynamic ^:private *document-info*)
|
||||||
|
|
||||||
(declare ^:private gather-footnotes render-renderer-error
|
(declare ^:private gather-footnotes render-renderer-error
|
||||||
view-children-as-seq render-tex-snippets)
|
view-children-as-seq render-tex-snippets)
|
||||||
@@ -63,31 +62,23 @@
|
|||||||
|
|
||||||
(defn org-document
|
(defn org-document
|
||||||
"Recursively render an Org-mode document to Hiccup."
|
"Recursively render an Org-mode document to Hiccup."
|
||||||
[doc & {:as opts :keys [postamble header title]}]
|
[doc]
|
||||||
(binding [*opts* opts]
|
(tex-temml/binding-worker
|
||||||
(tex-temml/binding-worker
|
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
||||||
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
org-element-recursive)]
|
||||||
org-element-recursive)]
|
[:html
|
||||||
[:html
|
[:head
|
||||||
[:head
|
[:title "org document"]
|
||||||
(when title
|
doerg-html/head]
|
||||||
[:title title])
|
[:body {:lang default-language}
|
||||||
doerg-html/head]
|
[:article
|
||||||
[:body {:lang default-language}
|
rendered]]])))
|
||||||
(when header
|
|
||||||
[:header header])
|
|
||||||
[:article
|
|
||||||
rendered
|
|
||||||
(when postamble
|
|
||||||
[:footer
|
|
||||||
[:hr]
|
|
||||||
postamble])]]]))))
|
|
||||||
|
|
||||||
(defn to-html
|
(defn to-html
|
||||||
"Read `f` with `slurp` as an Org document and return a string of
|
"Read `f` with `slurp` as an Org document and return a string of
|
||||||
rendered HTML. See `org-document` for opts."
|
rendered HTML."
|
||||||
[f & {:as opts}]
|
[f]
|
||||||
(str (hiccup/html {} (-> f slurp element/read-string (org-document opts)))))
|
(str (hiccup/html {} (-> f slurp element/read-string org-document))))
|
||||||
|
|
||||||
|
|
||||||
;;; Further dispatching on `org-element`
|
;;; Further dispatching on `org-element`
|
||||||
@@ -111,19 +102,6 @@
|
|||||||
(sp/view #(update % :children seq))
|
(sp/view #(update % :children seq))
|
||||||
sp/STAY))
|
sp/STAY))
|
||||||
|
|
||||||
(defn center [& es]
|
|
||||||
[:div.center es])
|
|
||||||
|
|
||||||
(defn doerg-attrs [e]
|
|
||||||
(->> e :affiliated :attr_doerg (str/join " ")
|
|
||||||
(format "{%s}") edn/read-string))
|
|
||||||
|
|
||||||
(defn em [x]
|
|
||||||
(format "%.4fem" x))
|
|
||||||
|
|
||||||
(defn wrap-if [x c f]
|
|
||||||
(if c (f x) x))
|
|
||||||
|
|
||||||
(defn- contains-footnote-refs? [node]
|
(defn- contains-footnote-refs? [node]
|
||||||
(some #(element/of-type? % "footnote-reference")
|
(some #(element/of-type? % "footnote-reference")
|
||||||
(:children node)))
|
(:children node)))
|
||||||
@@ -276,14 +254,11 @@
|
|||||||
(defmethod org-element "bold" [{:keys [children]}]
|
(defmethod org-element "bold" [{:keys [children]}]
|
||||||
[:b children])
|
[:b children])
|
||||||
|
|
||||||
(defmethod org-element "strike-through" [{:keys [children]}]
|
|
||||||
[:s children])
|
|
||||||
|
|
||||||
(defmethod org-element "subscript" [{:keys [children]}]
|
(defmethod org-element "subscript" [{:keys [children]}]
|
||||||
[:sub children])
|
[:sub children])
|
||||||
|
|
||||||
(defmethod org-element "superscript" [{:keys [children]}]
|
(defmethod org-element "superscript" [{:keys [children]}]
|
||||||
[:sup children])
|
[:super children])
|
||||||
|
|
||||||
(defmethod org-element "italic" [{:keys [children]}]
|
(defmethod org-element "italic" [{:keys [children]}]
|
||||||
[:em children])
|
[:em children])
|
||||||
@@ -354,52 +329,23 @@
|
|||||||
[:span.latex-fragment.display-math
|
[:span.latex-fragment.display-math
|
||||||
(-> e ::rendered deref)])
|
(-> e ::rendered deref)])
|
||||||
|
|
||||||
(defmethod org-element "example-block" [{:keys [value] :as e}]
|
(defmethod org-element "example-block" [{:keys [value]}]
|
||||||
(let [{:keys [center? alt scale img?]} (doerg-attrs e)]
|
[:pre value])
|
||||||
(-> [:pre (merge (and img? {:role "img"
|
|
||||||
:aria-label alt
|
|
||||||
:title alt})
|
|
||||||
(and scale {:style {:font-size (em scale)}}))
|
|
||||||
value]
|
|
||||||
(wrap-if center? center))))
|
|
||||||
|
|
||||||
(defmethod org-element "src-block" [{:keys [value]}]
|
(defmethod org-element "src-block" [{:keys [value]}]
|
||||||
[:pre [:code value]])
|
[:pre [:code value]])
|
||||||
|
|
||||||
(defn- split-quote-block-children [children]
|
(defmethod org-element "quote-block" [{:keys [children]}]
|
||||||
(match (split-with #(not= % [:hr]) children)
|
[:blockquote children])
|
||||||
[x ([[:hr] & ys] :seq)] [x (strip-paragraphs ys)]
|
|
||||||
x x))
|
|
||||||
|
|
||||||
(defmethod org-element "quote-block" [{:keys [children] :as e}]
|
|
||||||
(let [{:keys [epigraph?]} (doerg-attrs e)
|
|
||||||
[content footer] (split-quote-block-children children)]
|
|
||||||
(-> [:blockquote
|
|
||||||
content
|
|
||||||
(when footer
|
|
||||||
[:footer footer])]
|
|
||||||
(wrap-if epigraph? (fn [c] [:div.epigraph c])))))
|
|
||||||
|
|
||||||
(defmethod org-element "horizontal-rule" [_]
|
|
||||||
[:hr])
|
|
||||||
|
|
||||||
(defmethod org-element "comment" [_] nil)
|
(defmethod org-element "comment" [_] nil)
|
||||||
|
|
||||||
(defmethod org-keyword "TITLE" [{:keys [value]}]
|
(defmethod org-keyword "TITLE" [{:keys [value]}]
|
||||||
[:h1 value])
|
[:h1 value])
|
||||||
|
|
||||||
(defmethod org-keyword "SUBTITLE" [{:keys [value]}]
|
|
||||||
[:p.subtitle value])
|
|
||||||
|
|
||||||
(defmethod org-keyword "LATEX_COMPILER" [_] nil)
|
(defmethod org-keyword "LATEX_COMPILER" [_] nil)
|
||||||
(defmethod org-keyword "LATEX_HEADER" [_] nil)
|
(defmethod org-keyword "LATEX_HEADER" [_] nil)
|
||||||
|
|
||||||
;; TODO: A bunch of things I'd rather hide for now, but should be
|
|
||||||
;; implemented eventually.
|
|
||||||
(defmethod org-keyword "FILETAGS" [_] nil)
|
|
||||||
(defmethod org-element "planning" [_] nil)
|
|
||||||
(defmethod org-element "timestamp" [_] nil)
|
|
||||||
|
|
||||||
;; Not sure how to deal with this one yet.
|
;; Not sure how to deal with this one yet.
|
||||||
(defmethod org-keyword "AUTHOR" [_] nil)
|
(defmethod org-keyword "AUTHOR" [_] nil)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
(fs/create-dirs dest)
|
(fs/create-dirs dest)
|
||||||
(fs/create-dirs resource-dir)
|
(fs/create-dirs resource-dir)
|
||||||
(force-create-sym-link (fs/file resource-dir "ibm-plex-web")
|
(force-create-sym-link (fs/file resource-dir "ibm-plex-web")
|
||||||
(-> cfg/*cfg* ::cfg/ibm-plex-web))
|
(-> cfg/*cfg* ::doerg/ibm-plex-web))
|
||||||
(doseq [x #{"Temml-Plex.css" "tuftesque.css" "deerstar.css"}]
|
(doseq [x #{"Temml-Plex.css" "tuftesque.css" "deerstar.css"}]
|
||||||
(force-create-sym-link
|
(force-create-sym-link
|
||||||
(fs/file resource-dir x)
|
(fs/file resource-dir x)
|
||||||
File renamed without changes.
+2
-2
@@ -83,14 +83,14 @@
|
|||||||
acc))))
|
acc))))
|
||||||
|
|
||||||
(defn- invoke-latex [& {:keys [file output-dir]}]
|
(defn- invoke-latex [& {:keys [file output-dir]}]
|
||||||
(let [latex (-> cfg/*cfg* ::cfg/latex)]
|
(let [latex (-> cfg/*cfg* ::doerg/latex)]
|
||||||
(invoke
|
(invoke
|
||||||
{:dir output-dir}
|
{:dir output-dir}
|
||||||
latex "-no-pdf" "-interaction" "nonstopmode"
|
latex "-no-pdf" "-interaction" "nonstopmode"
|
||||||
"-output-directory" output-dir file)))
|
"-output-directory" output-dir file)))
|
||||||
|
|
||||||
(defn- invoke-dvisvgm [& {:keys [file output-dir]}]
|
(defn- invoke-dvisvgm [& {:keys [file output-dir]}]
|
||||||
(let [dvisvgm (-> cfg/*cfg* ::cfg/dvisvgm)]
|
(let [dvisvgm (-> cfg/*cfg* ::doerg/dvisvgm)]
|
||||||
(invoke
|
(invoke
|
||||||
{:dir output-dir}
|
{:dir output-dir}
|
||||||
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
fs/file))
|
fs/file))
|
||||||
|
|
||||||
(defn worker []
|
(defn worker []
|
||||||
(let [doerg-temml-worker (-> cfg/*cfg* ::cfg/doerg-temml-worker)]
|
(let [doerg-temml-worker (-> cfg/*cfg* ::doerg/doerg-temml-worker)]
|
||||||
(when (or (not (fs/exists? prelude-file))
|
(when (or (not (fs/exists? prelude-file))
|
||||||
(zero? (fs/size prelude-file)))
|
(zero? (fs/size prelude-file)))
|
||||||
(-> "net/deertopia/doerg/prelude.tex"
|
(-> "net/deertopia/doerg/prelude.tex"
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Generated
+3
-3
@@ -111,11 +111,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774386573,
|
"lastModified": 1760038930,
|
||||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -14,19 +14,16 @@
|
|||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
];
|
];
|
||||||
|
|
||||||
overlays = [
|
|
||||||
inputs.sydpkgs.overlays.default
|
|
||||||
clj-nix.overlays.default
|
|
||||||
];
|
|
||||||
|
|
||||||
each-system = f: nixpkgs.lib.genAttrs supportedSystems (system: f rec {
|
each-system = f: nixpkgs.lib.genAttrs supportedSystems (system: f rec {
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = overlays ++ [
|
overlays = [
|
||||||
self.overlays.default
|
inputs.sydpkgs.overlays.default
|
||||||
];
|
clj-nix.overlays.default
|
||||||
};
|
self.overlays.default
|
||||||
inherit (pkgs) lib;
|
];
|
||||||
|
};
|
||||||
|
inherit (pkgs) lib;
|
||||||
inherit system;
|
inherit system;
|
||||||
});
|
});
|
||||||
in {
|
in {
|
||||||
@@ -34,51 +31,45 @@
|
|||||||
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
||||||
|
|
||||||
packages = each-system ({ pkgs, ... }: {
|
packages = each-system ({ pkgs, ... }: {
|
||||||
inherit (pkgs) doerg doerg-parser doerg-temml-worker;
|
inherit (pkgs) publisher doerg doerg-parser doerg-temml-worker;
|
||||||
default = pkgs.doerg;
|
default = pkgs.publisher;
|
||||||
});
|
});
|
||||||
|
|
||||||
overlays.default = final: prev:
|
overlays.default = final: prev:
|
||||||
let
|
let graal = x: final.mkGraalBin { cljDrv = x; };
|
||||||
# is this really the correct way to satisfy our
|
vendored = final.callPackage ./vendor {};
|
||||||
# dependencies? lmfao
|
in {
|
||||||
final' = final.appendOverlays overlays;
|
inherit (vendored) ibm-plex-web;
|
||||||
graal = x: final'.mkGraalBin { cljDrv = x; };
|
publisher = final.callPackage ./publisher {};
|
||||||
in {
|
doerg = final.callPackage ./doerg {};
|
||||||
ibm-plex-web = final'.callPackage ./ibm-plex-web.nix {};
|
doerg-parser = final.callPackage ./doerg/doerg-parser {};
|
||||||
doerg = final'.callPackage ./. {};
|
doerg-temml-worker = final.callPackage ./doerg/doerg-temml-worker {};
|
||||||
doerg-parser = final'.callPackage ./doerg-parser {};
|
};
|
||||||
doerg-temml-worker = final'.callPackage ./doerg-temml-worker {};
|
|
||||||
our-tex = final'.callPackage ./our-tex.nix {};
|
|
||||||
};
|
|
||||||
|
|
||||||
checks = each-system ({ pkgs, system, ... }: {
|
checks = each-system ({ pkgs, system, ... }: {
|
||||||
build-all =
|
build-all =
|
||||||
pkgs.linkFarmFromDrvs
|
pkgs.linkFarmFromDrvs
|
||||||
"all"
|
"all"
|
||||||
(pkgs.lib.attrValues self.packages.${system});
|
(pkgs.lib.attrValues self.packages.${system});
|
||||||
});
|
});
|
||||||
|
|
||||||
nixosModules.default = import ./module.nix { inherit self; };
|
|
||||||
|
|
||||||
devShells = each-system ({ pkgs, system, ... }: {
|
devShells = each-system ({ pkgs, system, ... }: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
pkgs.doerg
|
pkgs.doerg
|
||||||
pkgs.doerg-parser
|
pkgs.doerg-parser
|
||||||
pkgs.doerg-temml-worker
|
pkgs.doerg-temml-worker
|
||||||
];
|
];
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
clojure-lsp
|
clojure-lsp
|
||||||
doerg-parser
|
doerg-parser
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
zprint
|
zprint
|
||||||
clojure
|
clojure
|
||||||
babashka
|
babashka
|
||||||
sqlite-web
|
sqlite-web
|
||||||
pkgs.doerg.test-emacs
|
];
|
||||||
];
|
};
|
||||||
};
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
{ self, ... }:
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.doerg;
|
|
||||||
doerg-config = pkgs.writeText "doerg-config.edn" ''
|
|
||||||
#:net.deertopia.doerg.config
|
|
||||||
{:org-roam-db-path "${cfg.databasePath}"
|
|
||||||
:state-directory "${cfg.stateDir}"
|
|
||||||
:port ${builtins.toString cfg.port}}
|
|
||||||
'';
|
|
||||||
|
|
||||||
inherit (lib) types;
|
|
||||||
|
|
||||||
org-roam-db-sync = pkgs.writeText "org-roam-db-sync.el" ''
|
|
||||||
#!/usr/bin/env -S emacs -Q -x
|
|
||||||
|
|
||||||
(require 'org-roam)
|
|
||||||
|
|
||||||
(setq org-roam-directory (expand-file-name (car command-line-args-left)))
|
|
||||||
(setq org-roam-db-location (expand-file-name (cadr command-line-args-left)))
|
|
||||||
|
|
||||||
(org-roam-db-sync)
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
options.services.doerg = {
|
|
||||||
enable = lib.mkEnableOption "Doerg";
|
|
||||||
org-roam-db-sync.enable = lib.mkEnableOption "Org-roam db sync";
|
|
||||||
port = lib.mkOption {
|
|
||||||
default = 21984;
|
|
||||||
type = lib.types.port;
|
|
||||||
description = ''
|
|
||||||
The port on which Doerg will listen.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
stateDir = lib.mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = "/var/lib/private/doerg";
|
|
||||||
description = "Daemon's state directory.";
|
|
||||||
};
|
|
||||||
orgDir = lib.mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = "Org roam directory.";
|
|
||||||
};
|
|
||||||
package = lib.mkPackageOption pkgs "doerg" {};
|
|
||||||
databasePath = lib.mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = "Org roam database path";
|
|
||||||
default = cfg.orgDir + "org-roam.db";
|
|
||||||
};
|
|
||||||
openFirewall = lib.mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
description = "Open doerg ports?";
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
nixpkgs.overlays = [ self.overlays.default ];
|
|
||||||
|
|
||||||
systemd.services.org-roam-db-sync = lib.mkIf cfg.org-roam-db-sync.enable {
|
|
||||||
script = lib.escapeShellArgs [
|
|
||||||
(lib.getExe cfg.package.test-emacs)
|
|
||||||
"-Q" "-x" org-roam-db-sync cfg.orgDir cfg.databasePath
|
|
||||||
];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ReadOnlyBindPaths = [
|
|
||||||
cfg.orgDir
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.timers.org-roam-db-sync = lib.mkIf cfg.org-roam-db-sync.enable {
|
|
||||||
unitConfig.StopWhenUnneeded = true;
|
|
||||||
timerConfig = {
|
|
||||||
OnActiveSec = "1h";
|
|
||||||
RandomizedDelaySec = "30m";
|
|
||||||
Persistent = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
|
|
||||||
cfg.port
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.doerg = {
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
wants = [ "network-online.target" "org-roam-db-sync.timer" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
environment.DOERG_CONFIG = doerg-config;
|
|
||||||
serviceConfig = {
|
|
||||||
# WorkingDirectory = cfg.stateDir;
|
|
||||||
StateDirectory = "doerg";
|
|
||||||
ExecStart = lib.getExe cfg.package;
|
|
||||||
DynamicUser = true;
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
PrivateTmp = true;
|
|
||||||
BindReadOnlyPaths = [
|
|
||||||
cfg.orgDir
|
|
||||||
# cfg.databasePath
|
|
||||||
"/nix"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
((nil
|
||||||
|
. ((cider-clojure-cli-aliases . ":dev:test")
|
||||||
|
;; (eval
|
||||||
|
;; . (progn
|
||||||
|
;; (defun start-deertopia-server ()
|
||||||
|
;; (let ((n (cider-format-connection-params "%j" cider-launch-params)))
|
||||||
|
;; (when (equal n "net-deertopia")
|
||||||
|
;; (cider-interactive-eval
|
||||||
|
;; "(do (require '[net.deertopia.publisher.server :as server])
|
||||||
|
;; (server/start!))"))))
|
||||||
|
;; (add-hook 'cider-connected-hook #'start-deertopia-server)))
|
||||||
|
)))
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{ mkCljBin
|
||||||
|
, doerg
|
||||||
|
, babashka
|
||||||
|
}:
|
||||||
|
|
||||||
|
mkCljBin {
|
||||||
|
name = "net.deertopia/publisher";
|
||||||
|
version = "0.1.0";
|
||||||
|
projectSrc = ./.;
|
||||||
|
lockfile = ../deps-lock.json;
|
||||||
|
main-ns = "net.deertopia.publisher.main";
|
||||||
|
buildInputs = [
|
||||||
|
doerg
|
||||||
|
];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
babashka
|
||||||
|
];
|
||||||
|
postPatch = ''
|
||||||
|
mv deps.edn deps.edn.old
|
||||||
|
bb -cp . -m override-deps < deps.edn.old > deps.edn \
|
||||||
|
net.deertopia/doerg '{:local/root "${doerg.lib}/${doerg.name}.jar"}'
|
||||||
|
'';
|
||||||
|
doCheck = true;
|
||||||
|
checkPhase = ''
|
||||||
|
clojure -M:test
|
||||||
|
'';
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{:deps {org.clojure/clojure {:mvn/version "1.12.0"}
|
||||||
|
org.clojure/tools.logging {:mvn/version "1.3.0"}
|
||||||
|
hiccup/hiccup {:mvn/version "2.0.0-RC4"}
|
||||||
|
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"}
|
||||||
|
babashka/fs {:mvn/version "0.5.24"}
|
||||||
|
org.clojure/core.match {:mvn/version "1.1.0"}
|
||||||
|
com.github.seancorfield/next.jdbc {:mvn/version "1.3.1070"}
|
||||||
|
org.xerial/sqlite-jdbc {:mvn/version "3.47.1.0"}
|
||||||
|
cheshire/cheshire {:mvn/version "6.1.0"}
|
||||||
|
org.clojure/test.check {:mvn/version "1.1.3"}
|
||||||
|
net.deertopia/doerg {:local/root "../doerg"}
|
||||||
|
metosin/reitit {:mvn/version "0.10.1"}
|
||||||
|
http-kit/http-kit {:mvn/version "2.8.0"}
|
||||||
|
instaparse/instaparse {:mvn/version "1.5.0"}
|
||||||
|
aero/aero {:mvn/version "1.1.6"}}
|
||||||
|
:paths ["src" "resources"]
|
||||||
|
:aliases
|
||||||
|
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||||
|
:extra-paths ["test"]
|
||||||
|
:main-opts ["-m" "kaocha.runner"]}
|
||||||
|
:dev {:extra-paths ["dev"]}}}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
(ns user
|
||||||
|
(:require [net.deertopia.publisher.server :as server]
|
||||||
|
[net.deertopia.doerg :as-alias doerg]
|
||||||
|
[net.deertopia.publisher :as-alias publisher]
|
||||||
|
[net.deertopia.doerg.config :as doerg-config]
|
||||||
|
[net.deertopia.publisher.config :as publisher-config]
|
||||||
|
[babashka.fs :as fs]))
|
||||||
|
|
||||||
|
(doerg-config/load-config! #'doerg-config/*cfg*
|
||||||
|
::doerg/config
|
||||||
|
doerg-config/sources
|
||||||
|
:profile :dev)
|
||||||
|
|
||||||
|
(doerg-config/load-config! #'publisher-config/*cfg*
|
||||||
|
::publisher/config
|
||||||
|
publisher-config/sources
|
||||||
|
:profile :dev)
|
||||||
|
|
||||||
|
(when (not= :running (server/status))
|
||||||
|
(server/start!))
|
||||||
|
|
||||||
|
(defn invalidate-html-cache! []
|
||||||
|
(fs/delete-tree (server/html-dir))
|
||||||
|
nil)
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
;;; -*- mode:clojure -*-
|
||||||
|
;;;
|
||||||
|
;;; USAGE:
|
||||||
|
;;;
|
||||||
|
;;; bb -cp . -m override-deps -- [DEP-NAME INFO]…
|
||||||
|
;;;
|
||||||
|
;;; This script takes a series of deps substitutions on the command
|
||||||
|
;;; line, applies them to a deps.edn file (read on stdin), and spits
|
||||||
|
;;; the result to stdout.
|
||||||
|
;;;
|
||||||
|
;;; It is used to build the Doerg server with Nix, since Clj-nix does
|
||||||
|
;;; not resolve the local deps itself.
|
||||||
|
|
||||||
|
(ns override-deps
|
||||||
|
(:require [rewrite-clj.zip :as z]
|
||||||
|
[babashka.fs :as fs]
|
||||||
|
[clojure.edn :as edn]))
|
||||||
|
|
||||||
|
(defn apply-overrides [zloc overrides]
|
||||||
|
(loop [os (seq overrides)
|
||||||
|
loc zloc]
|
||||||
|
(if-some [[[k v] & xs] os]
|
||||||
|
(do (binding [*out* *err*]
|
||||||
|
(printf "override dep %s with %s\n"
|
||||||
|
(pr-str k) (pr-str v)))
|
||||||
|
(recur xs (z/assoc loc k v)))
|
||||||
|
loc)))
|
||||||
|
|
||||||
|
(defn args->overrides [args]
|
||||||
|
(assert (even? (count args)))
|
||||||
|
(->> args (map edn/read-string) (apply hash-map)))
|
||||||
|
|
||||||
|
(defn -main [& args]
|
||||||
|
(let [zloc (-> (slurp *in*) z/of-string)
|
||||||
|
overrides (args->overrides args)]
|
||||||
|
(-> zloc
|
||||||
|
z/down
|
||||||
|
(z/find-value :deps) z/right
|
||||||
|
(apply-overrides overrides)
|
||||||
|
z/root-string
|
||||||
|
print)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(comment
|
||||||
|
"Example overrides"
|
||||||
|
(def overrides '{net.deertopia/doerg "blah!!!!"
|
||||||
|
ring/ring-defaults {:mvn/version "xxxxx"}}))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
"Behaviour of `args->overrides`."
|
||||||
|
(= (args->overrides ["net.deertopia/doerg" "{:mvn/version \"abc\"}"
|
||||||
|
"ring/ring-defaults" "{:local/root \"/path/to/jar\"}"])
|
||||||
|
'{ring/ring-defaults {:local/root "/path/to/jar"}
|
||||||
|
net.deertopia/doerg {:mvn/version "abc"}}))
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#:net.deertopia.publisher
|
||||||
|
{:state-directory #join [#or [#env XDG_STATE_HOME
|
||||||
|
#envf ["%s/.local/share" HOME]]
|
||||||
|
"/doerg-publisher"]
|
||||||
|
:org-roam-db-path
|
||||||
|
#profile {:default #join [#env HOME "/.cache/emacs/org-roam.db"]
|
||||||
|
:test #file "../../../../test/net/deertopia/publisher/roam-test.db"}
|
||||||
|
:port #profile {:default 8080}}
|
||||||
File renamed without changes.
+3
-5
@@ -1,4 +1,4 @@
|
|||||||
(ns net.deertopia.doerg.cached-file
|
(ns net.deertopia.publisher.cached-file
|
||||||
(:require [babashka.fs :as fs]))
|
(:require [babashka.fs :as fs]))
|
||||||
|
|
||||||
(defn newer-than?
|
(defn newer-than?
|
||||||
@@ -18,10 +18,8 @@
|
|||||||
calling `compute` with no arguments only if stale? is logical true."
|
calling `compute` with no arguments only if stale? is logical true."
|
||||||
[& {:keys [file stale? compute]}]
|
[& {:keys [file stale? compute]}]
|
||||||
(when (or (not *use-cache?*) stale?)
|
(when (or (not *use-cache?*) stale?)
|
||||||
(let [r (compute)
|
(let [r (compute)]
|
||||||
dir (fs/parent file)]
|
|
||||||
(assert (string? r))
|
(assert (string? r))
|
||||||
(when-not (fs/exists? dir)
|
(fs/create-dirs (fs/parent file))
|
||||||
(fs/create-dirs dir))
|
|
||||||
(spit file r)))
|
(spit file r)))
|
||||||
file)
|
file)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
(ns net.deertopia.publisher.config
|
||||||
|
(:require [babashka.fs :as fs]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[net.deertopia.doerg.config :as doerg-config]
|
||||||
|
[net.deertopia.doerg :as-alias doerg]
|
||||||
|
[net.deertopia.publisher :as-alias p]
|
||||||
|
[aero.core :as aero]
|
||||||
|
[clojure.java.io :as io]))
|
||||||
|
|
||||||
|
(s/def ::p/config
|
||||||
|
(s/keys :req [::p/state-directory
|
||||||
|
::p/org-roam-db-path]))
|
||||||
|
|
||||||
|
(s/def ::p/state-directory ::doerg/file)
|
||||||
|
(s/def ::p/org-roam-db-path ::doerg/file)
|
||||||
|
|
||||||
|
(def sources
|
||||||
|
[;; Default config.
|
||||||
|
(io/resource "net/deertopia/publisher/default-config.edn")
|
||||||
|
;; Defaults set at build time, if any.
|
||||||
|
(io/resource "net/deertopia/publisher/extra-config.edn")
|
||||||
|
;; Config set at runtime.
|
||||||
|
(System/getenv "DOERG_PUBLISHER_CONFIG")])
|
||||||
|
|
||||||
|
(def default
|
||||||
|
(doerg-config/read-config ::p/config sources))
|
||||||
|
|
||||||
|
(def ^:dynamic *cfg* default)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(ns net.deertopia.doerg.elisp
|
(ns net.deertopia.publisher.elisp
|
||||||
(:require [clojure.core.match :refer [match]]
|
(:require [clojure.core.match :refer [match]]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
(:refer-clojure :exclude [print read read-string]))
|
(:refer-clojure :exclude [print read read-string]))
|
||||||
|
|
||||||
(ip/defparser read*
|
(ip/defparser read*
|
||||||
(io/resource "net/deertopia/doerg/elisp/grammar"))
|
(io/resource "net/deertopia/publisher/elisp/grammar"))
|
||||||
|
|
||||||
(defn- transform-string [s]
|
(defn- transform-string [s]
|
||||||
(let [s* (loop [s (seq s)
|
(let [s* (loop [s (seq s)
|
||||||
@@ -106,9 +106,9 @@
|
|||||||
|
|
||||||
(defn print [x]
|
(defn print [x]
|
||||||
;; TODO: this is really not how it should be done lol. at the
|
;; TODO: this is really not how it should be done lol. at the
|
||||||
;; moment, `print` is only used in `net.deertopia.doerg.roam`
|
;; moment, `print` is only used in `net.deertopia.publisher.roam`
|
||||||
;; and only to serialise uuids, so it's not a /massive/ priority.
|
;; and only to serialise uuids, so it's not a /massive/ priority.
|
||||||
(cond (or (string? x) (uuid? x)) (str \" x \")
|
(cond (string? x) (str \" x \")
|
||||||
:else (throw (ex-info "`print` is unimplemented lol"
|
:else (throw (ex-info "`print` is unimplemented lol"
|
||||||
{:x x}))))
|
{:x x}))))
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
(ns net.deertopia.publisher.main
|
||||||
|
(:require [net.deertopia.doerg.main :as doerg]
|
||||||
|
[net.deertopia.publisher.server :as server])
|
||||||
|
(:gen-class))
|
||||||
|
|
||||||
|
(defn -main []
|
||||||
|
(server/start!))
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
(ns net.deertopia.doerg.roam
|
(ns net.deertopia.publisher.roam
|
||||||
(:require [babashka.fs :as fs]
|
(:require [babashka.fs :as fs]
|
||||||
[net.deertopia.doerg.config :as cfg]
|
[net.deertopia.publisher.config :as cfg]
|
||||||
[net.deertopia.doerg.elisp :as elisp]
|
[net.deertopia.publisher.elisp :as elisp]
|
||||||
[net.deertopia.doerg.slug :as slug]
|
[net.deertopia.publisher.slug :as slug]
|
||||||
|
[net.deertopia.publisher :as-alias publisher]
|
||||||
[next.jdbc :as sql])
|
[next.jdbc :as sql])
|
||||||
(:import (java.util UUID)))
|
(:import (java.util UUID)))
|
||||||
|
|
||||||
@@ -11,10 +12,13 @@
|
|||||||
|
|
||||||
(defonce ^:dynamic *use-db-cache?* true)
|
(defonce ^:dynamic *use-db-cache?* true)
|
||||||
|
|
||||||
(defn ds []
|
(def db-path (-> cfg/*cfg* ::publisher/org-roam-db-path
|
||||||
(sql/get-datasource
|
fs/expand-home str))
|
||||||
{:dbtype "sqlite"
|
|
||||||
:dbname (-> cfg/*cfg* ::cfg/org-roam-db-path str)}))
|
(def db {:dbtype "sqlite"
|
||||||
|
:dbname db-path})
|
||||||
|
|
||||||
|
(def ds (sql/get-datasource db))
|
||||||
|
|
||||||
|
|
||||||
;;; Elisp sexp (de)serialisation
|
;;; Elisp sexp (de)serialisation
|
||||||
@@ -26,23 +30,21 @@
|
|||||||
(-> node :id slug/from-uuid))
|
(-> node :id slug/from-uuid))
|
||||||
|
|
||||||
(defn- print-id [node]
|
(defn- print-id [node]
|
||||||
(-> node id elisp/print))
|
(-> node id print))
|
||||||
|
|
||||||
|
|
||||||
;;; Node
|
;;; Node
|
||||||
|
|
||||||
(defrecord Node [id cache])
|
(defrecord Node [id cache])
|
||||||
|
|
||||||
(defn uuid-exists? [uuid]
|
(defn- uuid-exists? [uuid]
|
||||||
(sql/execute-one! (ds)
|
(sql/execute-one! ds
|
||||||
["select 1 from nodes where id = ? limit 1"
|
["select 1 from nodes where id = ? limit 1"
|
||||||
(-> uuid str elisp/print)]))
|
(-> uuid str elisp/print)]))
|
||||||
|
|
||||||
(defn make-node
|
(defn make-node [uuid]
|
||||||
([uuid] (make-node uuid {}))
|
(and (uuid-exists? uuid)
|
||||||
([uuid props]
|
(->Node uuid (atom {}))))
|
||||||
(and (uuid-exists? uuid)
|
|
||||||
(->Node uuid (atom props)))))
|
|
||||||
|
|
||||||
(defn- fetch-with-cache [node field fetch]
|
(defn- fetch-with-cache [node field fetch]
|
||||||
(if *use-db-cache?*
|
(if *use-db-cache?*
|
||||||
@@ -57,20 +59,11 @@
|
|||||||
node :org-file
|
node :org-file
|
||||||
(fn [node]
|
(fn [node]
|
||||||
(when-some [r (sql/execute-one!
|
(when-some [r (sql/execute-one!
|
||||||
(ds)
|
ds
|
||||||
["select file from nodes where id = ?"
|
["select file from nodes where id = ?"
|
||||||
(-> node :id str elisp/print)])]
|
(-> node :id str elisp/print)])]
|
||||||
(-> r :nodes/file elisp/read-string)))))
|
(-> r :nodes/file elisp/read-string)))))
|
||||||
|
|
||||||
(defn title [node]
|
|
||||||
(fetch-with-cache
|
|
||||||
node :title
|
|
||||||
#(when-some [r (sql/execute-one!
|
|
||||||
(ds)
|
|
||||||
["select title from nodes where id = ?"
|
|
||||||
(print-id %)])]
|
|
||||||
(-> r :nodes/title elisp/read-string))))
|
|
||||||
|
|
||||||
(defprotocol GetNode
|
(defprotocol GetNode
|
||||||
(get-node [this]
|
(get-node [this]
|
||||||
"Return the node associated with `this` or nil."))
|
"Return the node associated with `this` or nil."))
|
||||||
@@ -85,7 +78,7 @@
|
|||||||
java.util.UUID
|
java.util.UUID
|
||||||
(get-node [this]
|
(get-node [this]
|
||||||
(make-node this))
|
(make-node this))
|
||||||
net.deertopia.doerg.slug.Slug
|
net.deertopia.publisher.slug.Slug
|
||||||
(get-node [this]
|
(get-node [this]
|
||||||
(-> this slug/to-uuid make-node))
|
(-> this slug/to-uuid make-node))
|
||||||
Node
|
Node
|
||||||
@@ -97,7 +90,7 @@
|
|||||||
(fetch-with-cache
|
(fetch-with-cache
|
||||||
node :title
|
node :title
|
||||||
#(do (println "fetch")
|
#(do (println "fetch")
|
||||||
(sql/execute-one! (ds) ["select title from nodes where id = ?"
|
(sql/execute-one! ds ["select title from nodes where id = ?"
|
||||||
(elisp/print (:id %))]))))
|
(elisp/print (:id %))]))))
|
||||||
|
|
||||||
|
|
||||||
@@ -107,7 +100,7 @@
|
|||||||
(fetch-with-cache
|
(fetch-with-cache
|
||||||
node :level
|
node :level
|
||||||
#(-> (sql/execute-one!
|
#(-> (sql/execute-one!
|
||||||
(ds) ["select level from nodes where id = ?"
|
ds ["select level from nodes where id = ?"
|
||||||
(print-id %)])
|
(print-id %)])
|
||||||
:nodes/level)))
|
:nodes/level)))
|
||||||
|
|
||||||
@@ -118,7 +111,7 @@
|
|||||||
(fetch-with-cache
|
(fetch-with-cache
|
||||||
node :file
|
node :file
|
||||||
#(-> (sql/execute-one!
|
#(-> (sql/execute-one!
|
||||||
(ds) ["select file from nodes where id = ?"
|
ds ["select file from nodes where id = ?"
|
||||||
(print-id %)])
|
(print-id %)])
|
||||||
:nodes/file
|
:nodes/file
|
||||||
elisp/read-string)))
|
elisp/read-string)))
|
||||||
@@ -127,35 +120,31 @@
|
|||||||
(fetch-with-cache
|
(fetch-with-cache
|
||||||
node :properties
|
node :properties
|
||||||
#(-> (sql/execute-one!
|
#(-> (sql/execute-one!
|
||||||
(ds) ["select properties from nodes where id = ?"
|
ds ["select properties from nodes where id = ?"
|
||||||
(print-id %)])
|
(print-id %)])
|
||||||
:nodes/properties
|
:nodes/properties
|
||||||
elisp/read-alist)))
|
elisp/read-alist)))
|
||||||
|
|
||||||
(defn public? [node]
|
(defn public? [node]
|
||||||
(some-> (properties node) (get "DEERTOPIAVISIBILITY") (= "public")))
|
(-> node properties (get "DEERTOPIAVISIBILITY") (= "public")))
|
||||||
|
|
||||||
(defn get-public-node [node]
|
|
||||||
(when-let [n (get-node node)]
|
|
||||||
(when (public? n) n)))
|
|
||||||
|
|
||||||
(defn graph-visible? [node]
|
(defn graph-visible? [node]
|
||||||
(#{"public" "graphonly"}
|
(#{"public" "graphonly"}
|
||||||
(some-> (properties node) (get "DEERTOPIAVISIBILITY"))))
|
(-> node properties (get "DEERTOPIAVISIBILITY"))))
|
||||||
|
|
||||||
(defn backlinks
|
(defn backlinks
|
||||||
"Returns a collection of nodes linking to `node`."
|
"Returns a collection of maps {:id …, :title …}."
|
||||||
[node]
|
[node]
|
||||||
(for [{id :nodes/id title :nodes/title}
|
(for [{id :nodes/id, title :nodes/title}
|
||||||
(sql/execute! (ds) ["select distinct nodes.id, nodes.title from links
|
(sql/execute! ds ["select distinct nodes.id, nodes.title from links
|
||||||
inner join nodes
|
inner join nodes
|
||||||
on nodes.id = links.source
|
on nodes.id = links.source
|
||||||
where links.dest = ?"
|
where links.dest = ?"
|
||||||
(elisp/print (str (:id node)))])
|
(elisp/print (:id node))])
|
||||||
:let [id' (elisp/read-string id)]
|
:let [id (elisp/read-string id)]
|
||||||
:when (some-> (-> id' parse-uuid get-node)
|
:when (graph-visible? (get-node (UUID/fromString id)))]
|
||||||
public?)]
|
{:id id
|
||||||
(make-node id' {:title (elisp/read-string title)})))
|
:title (elisp/read-string title)}))
|
||||||
|
|
||||||
|
|
||||||
;;; Graph support
|
;;; Graph support
|
||||||
@@ -167,9 +156,9 @@
|
|||||||
(-> uuid parse-uuid get-node graph-visible?))
|
(-> uuid parse-uuid get-node graph-visible?))
|
||||||
|
|
||||||
(defn get-graph []
|
(defn get-graph []
|
||||||
(let [nodes (sql/execute! (ds) ["select id, title from nodes"])
|
(let [nodes (sql/execute! ds ["select id, title from nodes"])
|
||||||
links (sql/execute!
|
links (sql/execute!
|
||||||
(ds)
|
ds
|
||||||
["select n1.id as source, nodes.id as target from
|
["select n1.id as source, nodes.id as target from
|
||||||
((nodes as n1) join links on n1.id = links.source)
|
((nodes as n1) join links on n1.id = links.source)
|
||||||
join (nodes as n2) on links.dest = nodes.id
|
join (nodes as n2) on links.dest = nodes.id
|
||||||
+21
-57
@@ -1,12 +1,12 @@
|
|||||||
(ns net.deertopia.doerg.server
|
(ns net.deertopia.publisher.server
|
||||||
(:require [clojure.pprint :refer [pprint]]
|
(:require [clojure.pprint :refer [pprint]]
|
||||||
[clojure.tools.logging :as l]
|
[clojure.tools.logging :as l]
|
||||||
[hiccup2.core :as hiccup]
|
[hiccup2.core :as hiccup]
|
||||||
[net.deertopia.doerg.html :as doerg-html]
|
[net.deertopia.doerg.html :as doerg-html]
|
||||||
[net.deertopia.doerg.config :as-alias cfg]
|
[net.deertopia.publisher :as-alias publisher]
|
||||||
[net.deertopia.doerg.slug :as slug]
|
[net.deertopia.publisher.slug :as slug]
|
||||||
[net.deertopia.doerg.config :as cfg]
|
[net.deertopia.publisher.config :as cfg]
|
||||||
[net.deertopia.doerg.roam :as roam]
|
[net.deertopia.publisher.roam :as roam]
|
||||||
[org.httpkit.server :as http]
|
[org.httpkit.server :as http]
|
||||||
[reitit.coercion]
|
[reitit.coercion]
|
||||||
[reitit.coercion.spec]
|
[reitit.coercion.spec]
|
||||||
@@ -20,10 +20,12 @@
|
|||||||
[reitit.dev.pretty]
|
[reitit.dev.pretty]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[net.deertopia.doerg.render :as doerg-render]
|
[net.deertopia.doerg.render :as doerg-render]
|
||||||
[net.deertopia.doerg.cached-file :as cached-file]
|
[net.deertopia.publisher.cached-file :as cached-file]
|
||||||
[babashka.fs :as fs]
|
[babashka.fs :as fs]
|
||||||
[aero.core :as aero]
|
[aero.core :as aero]
|
||||||
[clojure.string :as str]))
|
[clojure.string :as str]
|
||||||
|
[net.deertopia.doerg :as-alias doerg]
|
||||||
|
[net.deertopia.doerg.config :as doerg-config]))
|
||||||
|
|
||||||
|
|
||||||
;;; Routes
|
;;; Routes
|
||||||
@@ -47,15 +49,10 @@
|
|||||||
(response/content-type "text/html")))
|
(response/content-type "text/html")))
|
||||||
|
|
||||||
(defn html-dir []
|
(defn html-dir []
|
||||||
(-> cfg/*cfg* ::cfg/state-directory (fs/file "html")))
|
(-> cfg/*cfg* ::publisher/state-directory (fs/file "html")))
|
||||||
|
|
||||||
(declare node-by-slug)
|
(defn not-found [req]
|
||||||
|
(response/not-found "not found"))
|
||||||
;; This could infinitely loop if the 404 page can't be found. lmfao.
|
|
||||||
(defn not-found [_req]
|
|
||||||
(-> (node-by-slug {:path-params {:slug not-found-slug}})
|
|
||||||
(assoc :status 404))
|
|
||||||
#_(response/not-found "not found"))
|
|
||||||
|
|
||||||
(defn org-file->html-file [org-file]
|
(defn org-file->html-file [org-file]
|
||||||
(fs/file (html-dir)
|
(fs/file (html-dir)
|
||||||
@@ -64,56 +61,20 @@
|
|||||||
(fs/strip-ext {:ext "org"})
|
(fs/strip-ext {:ext "org"})
|
||||||
(str ".html"))))
|
(str ".html"))))
|
||||||
|
|
||||||
(defn slug-link [slug & contents]
|
|
||||||
[:a {:href (str "/n/" slug)}
|
|
||||||
contents])
|
|
||||||
|
|
||||||
(defmethod doerg-render/org-link "id"
|
(defmethod doerg-render/org-link "id"
|
||||||
[{:keys [path raw-link children]}]
|
[{:keys [path raw-link children]}]
|
||||||
[:span.org-link
|
[:span.org-link
|
||||||
(slug-link (slug/from-uuid path)
|
[:a {:href (str "/n/" (slug/from-uuid path))}
|
||||||
(or (seq children) raw-link))
|
|
||||||
#_[:a {:href (str "/n/" (slug/from-uuid path))}
|
|
||||||
(or (seq children) raw-link)]])
|
(or (seq children) raw-link)]])
|
||||||
|
|
||||||
(def navbar
|
|
||||||
"Hiccup element for Deertopia.net's navbar."
|
|
||||||
[:nav.navbar
|
|
||||||
[:ol.navbar-list
|
|
||||||
[:li
|
|
||||||
[:a.home-link {:href "/"}
|
|
||||||
"🦌 deertopia.net"]]
|
|
||||||
#_[:li
|
|
||||||
[:a.home-link {:href "/graph"}
|
|
||||||
"graph"]]
|
|
||||||
#_
|
|
||||||
[:li
|
|
||||||
[:a.home-link {:onclick "alert('unimplemented }:(')"}
|
|
||||||
"search"]]]])
|
|
||||||
|
|
||||||
(defn backlinks-postamble [node]
|
|
||||||
(let [backlinks (roam/backlinks node)]
|
|
||||||
(when-not (empty? backlinks)
|
|
||||||
[:section#backlinks
|
|
||||||
[:h2 "Backlinks"]
|
|
||||||
[:ul
|
|
||||||
(for [n (->> backlinks
|
|
||||||
(sort-by (comp str/lower-case roam/title)))]
|
|
||||||
[:li (slug-link (roam/slug n)
|
|
||||||
(roam/title n))])]])))
|
|
||||||
|
|
||||||
(defn node-by-slug [{{:keys [slug]} :path-params :as req}]
|
(defn node-by-slug [{{:keys [slug]} :path-params :as req}]
|
||||||
(if-some [node (some-> slug slug/from-string roam/get-public-node)]
|
(if-some [node (some-> slug slug/from-string roam/get-node)]
|
||||||
(let [org-file (roam/org-file node)
|
(let [org-file (roam/org-file node)
|
||||||
html-file (org-file->html-file org-file)]
|
html-file (org-file->html-file org-file)]
|
||||||
(cached-file/cached-file
|
(cached-file/cached-file
|
||||||
:file html-file
|
:file html-file
|
||||||
:stale? (cached-file/newer-than? org-file html-file)
|
:stale? (cached-file/newer-than? org-file html-file)
|
||||||
:compute #(doerg-render/to-html
|
:compute #(doerg-render/to-html org-file))
|
||||||
org-file
|
|
||||||
:postamble (backlinks-postamble node)
|
|
||||||
:header navbar
|
|
||||||
:title (roam/title node)))
|
|
||||||
(-> (str html-file)
|
(-> (str html-file)
|
||||||
response/file-response
|
response/file-response
|
||||||
(response/content-type "text/html")))
|
(response/content-type "text/html")))
|
||||||
@@ -136,11 +97,14 @@
|
|||||||
(assoc-in [:path-params :slug] homepage-slug)
|
(assoc-in [:path-params :slug] homepage-slug)
|
||||||
node-by-slug))
|
node-by-slug))
|
||||||
|
|
||||||
|
(def doerg-resources
|
||||||
|
#{"Temml-Plex.css" "tuftesque.css" "deerstar.css"})
|
||||||
|
|
||||||
(defn handle-resource [{:keys [uri]}]
|
(defn handle-resource [{:keys [uri]}]
|
||||||
(if-some [[_ resource] (re-matches #"^/resource/ibm-plex-web/(.*)" uri)]
|
(if-some [[_ resource] (re-matches #"^/resource/ibm-plex-web/(.*)" uri)]
|
||||||
(-> resource
|
(-> resource
|
||||||
(response/file-response
|
(response/file-response
|
||||||
{:root (-> cfg/*cfg* ::cfg/ibm-plex-web str)}))
|
{:root (-> doerg-config/*cfg* ::doerg/ibm-plex-web str)}))
|
||||||
(-> uri
|
(-> uri
|
||||||
(str/replace-first #"^/resource/" "")
|
(str/replace-first #"^/resource/" "")
|
||||||
(response/resource-response
|
(response/resource-response
|
||||||
@@ -191,7 +155,7 @@
|
|||||||
(throw (IllegalStateException. "Server already started"))
|
(throw (IllegalStateException. "Server already started"))
|
||||||
(do (reset! server
|
(do (reset! server
|
||||||
(http/run-server (bound-fn* #'app)
|
(http/run-server (bound-fn* #'app)
|
||||||
{:port (-> cfg/*cfg* ::cfg/port)
|
{:port (-> cfg/*cfg* ::publisher/port)
|
||||||
:legacy-return-value? false}))
|
:legacy-return-value? false}))
|
||||||
;; For some reason, the log messages are not flushed before
|
;; For some reason, the log messages are not flushed before
|
||||||
;; the JVM shuts dowm. Nevertheless, the server /does/ come
|
;; the JVM shuts dowm. Nevertheless, the server /does/ come
|
||||||
@@ -202,7 +166,7 @@
|
|||||||
(ex-message e))
|
(ex-message e))
|
||||||
(throw e))))
|
(throw e))))
|
||||||
(l/infof "Server started on port %d"
|
(l/infof "Server started on port %d"
|
||||||
(-> cfg/*cfg* ::cfg/port)))))
|
(-> cfg/*cfg* ::publisher/port)))))
|
||||||
|
|
||||||
(defn status []
|
(defn status []
|
||||||
(if @server
|
(if @server
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(ns net.deertopia.doerg.slug
|
(ns net.deertopia.publisher.slug
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[spec-tools.core :as st])
|
[spec-tools.core :as st])
|
||||||
(:import (java.nio ByteBuffer)
|
(:import (java.nio ByteBuffer)
|
||||||
Binary file not shown.
File renamed without changes.
+20
-14
@@ -1,16 +1,24 @@
|
|||||||
(ns net.deertopia.doerg.server-test
|
(ns net.deertopia.publisher.server-test
|
||||||
(:require [net.deertopia.doerg.server :as sut]
|
(:require [net.deertopia.publisher.server :as sut]
|
||||||
[reitit.ring]
|
[reitit.ring]
|
||||||
[clojure.test :as t]
|
[clojure.test :as t]
|
||||||
[net.deertopia.doerg.config :as cfg]
|
[net.deertopia.publisher.config :as publisher-cfg]
|
||||||
[net.deertopia.doerg.roam :as roam]
|
[net.deertopia.doerg.config :as doerg-cfg]
|
||||||
[babashka.fs :as fs]
|
[net.deertopia.publisher :as-alias publisher]
|
||||||
[clojure.java.io :as io]
|
[net.deertopia.doerg :as-alias doerg]
|
||||||
[net.deertopia.doerg.roam-test :refer [test-db-fixture]]
|
[net.deertopia.publisher.roam :as roam]))
|
||||||
[net.deertopia.doerg.config-test :refer [test-config-fixture]]))
|
|
||||||
|
|
||||||
(t/use-fixtures
|
(t/use-fixtures
|
||||||
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
:once (fn [f]
|
||||||
|
(binding [doerg-cfg/*cfg*
|
||||||
|
(doerg-cfg/read-config
|
||||||
|
::doerg/config doerg-cfg/sources
|
||||||
|
:profile :test)
|
||||||
|
publisher-cfg/*cfg*
|
||||||
|
(doerg-cfg/read-config
|
||||||
|
::publisher/config publisher-cfg/sources
|
||||||
|
:profile :test)]
|
||||||
|
(f))))
|
||||||
|
|
||||||
(defn with-server [f]
|
(defn with-server [f]
|
||||||
(let [was-already-running? (= :running (sut/status))]
|
(let [was-already-running? (= :running (sut/status))]
|
||||||
@@ -24,8 +32,6 @@
|
|||||||
(sut/app {:request-method :get
|
(sut/app {:request-method :get
|
||||||
:uri uri}))
|
:uri uri}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(t/deftest server-is-running
|
(t/deftest server-is-running
|
||||||
;; 서버는 벌써 시작한 다음에 이 테스트 하면 잘못됩니다.
|
;; 서버는 벌써 시작한 다음에 이 테스트 하면 잘못됩니다.
|
||||||
;; (assert (not= :running (sut/status)))
|
;; (assert (not= :running (sut/status)))
|
||||||
@@ -33,9 +39,9 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(t/is (= :running (sut/status)))
|
(t/is (= :running (sut/status)))
|
||||||
(t/is (->> (format "http://localhost:%d"
|
(t/is (->> (format "http://localhost:%d"
|
||||||
(::cfg/port cfg/*cfg*))
|
(::publisher/port publisher-cfg/*cfg*))
|
||||||
slurp
|
slurp
|
||||||
string?)))))
|
string?)))))
|
||||||
|
|
||||||
(t/deftest get-nonexistent-node
|
(t/deftest get-nonexistent-node
|
||||||
(let [slug "3Lxvxnb0QrivoU3DX-l_5w"]
|
(let [slug "3Lxvxnb0QrivoU3DX-l_5w"]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#kaocha/v1 {}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{ fetchzip
|
||||||
|
, fetchurl
|
||||||
|
}:
|
||||||
|
|
||||||
|
{
|
||||||
|
ibm-plex-serif = fetchzip {
|
||||||
|
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-serif%401.1.0/ibm-plex-serif.zip";
|
||||||
|
hash = "sha256-8ygaAeMKygYS4GCub4YUQmkh87pYHfi3s0PQ6AbaeGw=";
|
||||||
|
};
|
||||||
|
|
||||||
|
ibm-plex-math = fetchzip {
|
||||||
|
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-math%401.1.0/ibm-plex-math.zip";
|
||||||
|
hash = "sha256-dJA6uqxa/yb3eLY4l39NeP0yIl2NfrbaRpf6h0/F7Xc=";
|
||||||
|
};
|
||||||
|
|
||||||
|
ibm-plex-sans-kr = fetchzip {
|
||||||
|
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-sans-kr%401.1.0/ibm-plex-sans-kr.zip";
|
||||||
|
hash = "sha256-FsHxMvLlI4yylgG96DOZIdW2DYpk7I+c5QgkVIkNZIE=";
|
||||||
|
};
|
||||||
|
|
||||||
|
"d3.v7.min.js" = fetchurl {
|
||||||
|
url = "https://d3js.org/d3.v7.min.js";
|
||||||
|
hash = "sha256-8glLv2FBs1lyLE/kVOtsSw8OQswQzHr5IfwVj864ZTk=";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#:net.deertopia.doerg.config
|
|
||||||
{:ibm-plex-web #or [#env IBM_PLEX_WEB
|
|
||||||
#xdg-data-dir "ibm-plex-web"]
|
|
||||||
:latex "xelatex"
|
|
||||||
:dvisvgm "dvisvgm"
|
|
||||||
:doerg-temml-worker
|
|
||||||
#profile {:dev #file "../../../../doerg-temml-worker/index.js"
|
|
||||||
:default "doerg-temml-worker"}
|
|
||||||
:doerg-parser
|
|
||||||
#profile {:dev #file "../../../../doerg-parser/index.js"
|
|
||||||
:default "doerg-parser"}
|
|
||||||
:state-directory #join [#or [#env XDG_STATE_HOME
|
|
||||||
#envf ["%s/.local/share" HOME]]
|
|
||||||
"/doerg-server"]
|
|
||||||
:org-roam-db-path
|
|
||||||
#profile {:default #join [#env HOME "/.cache/emacs/org-roam.db"]
|
|
||||||
:test #join [#or [#env TMP "/tmp"] "/doerg-org-roam-test.db"]}
|
|
||||||
:port #profile {:default 8080}}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.main
|
|
||||||
(:require [net.deertopia.doerg.server :as server]
|
|
||||||
[net.deertopia.doerg.config :as cfg])
|
|
||||||
(:gen-class))
|
|
||||||
|
|
||||||
(defn -main [& _]
|
|
||||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources)]
|
|
||||||
(server/start!)))
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{ emacsPackages
|
|
||||||
, symlinkJoin
|
|
||||||
, writeScriptBin
|
|
||||||
, lib
|
|
||||||
}:
|
|
||||||
|
|
||||||
let emacs = emacsPackages.emacsWithPackages (epkgs: [ epkgs.org-roam ]);
|
|
||||||
in writeScriptBin "test-emacs" ''
|
|
||||||
exec ${lib.getExe emacs} "$@"
|
|
||||||
''
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.config-test
|
|
||||||
(:require [clojure.test :as t]
|
|
||||||
[net.deertopia.doerg.config :as cfg]))
|
|
||||||
|
|
||||||
(defn test-config-fixture
|
|
||||||
"`clojure.test` fixture to run tests with the :test configuration."
|
|
||||||
[f]
|
|
||||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources :profile :test)]
|
|
||||||
(f)))
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/usr/bin/env -S emacs -Q -x
|
|
||||||
|
|
||||||
(require 'org-roam)
|
|
||||||
|
|
||||||
(setq org-roam-directory (expand-file-name (car command-line-args-left)))
|
|
||||||
(setq org-roam-db-location (expand-file-name (cadr command-line-args-left)))
|
|
||||||
|
|
||||||
(org-roam-db-sync)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
:PROPERTIES:
|
|
||||||
:ID: 3c60c74e-f533-43ad-89b3-563975bf80f2
|
|
||||||
:DeertopiaVisibility: public
|
|
||||||
:END:
|
|
||||||
#+title: page not found
|
|
||||||
|
|
||||||
the page you're looking for doesn't exist, or you lack the permissions necessary to view it........
|
|
||||||
|
|
||||||
#+attr_doerg: :center? true :alt "A doe sitting and sobbing" :scale 1.4
|
|
||||||
#+begin_example
|
|
||||||
\{ / \ }/
|
|
||||||
\/ . . \/
|
|
||||||
.. \Y` `Y/ ..
|
|
||||||
\ `\|~==~|/' /
|
|
||||||
'". T T ."`
|
|
||||||
{`^' }
|
|
||||||
| |
|
|
||||||
/</3 \
|
|
||||||
|| ||
|
|
||||||
_| || |_
|
|
||||||
.,_) ) || ( (_,.
|
|
||||||
|__ /_||_\ __|
|
|
||||||
#+end_example
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
:PROPERTIES:
|
|
||||||
:ID: 90f23e03-f746-42cb-862f-1af2d4bde3cc
|
|
||||||
:DeertopiaVisibility: public
|
|
||||||
:END:
|
|
||||||
#+title: Category theory
|
|
||||||
|
|
||||||
*Category theory* is the mathematical study of categories and functors between them.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
:PROPERTIES:
|
|
||||||
:ID: ebc5ea84-77ab-4d60-9b13-ef9160b11d1f
|
|
||||||
:DeertopiaVisibility: public
|
|
||||||
:END:
|
|
||||||
#+title: deertopia.net!!!!!!!!
|
|
||||||
|
|
||||||
homeee
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
:PROPERTIES:
|
|
||||||
:ID: 897bfc9d-94ce-4c58-8d21-93f13372b17b
|
|
||||||
:END:
|
|
||||||
#+title: Monomorphisms and epimorphisms
|
|
||||||
|
|
||||||
In [[id:90f23e03-f746-42cb-862f-1af2d4bde3cc][category theory]], *monomorphisms* and *epimorphisms* are types of cancellative morphisms generalising injective and surjective functions, respectively.[fn:1]
|
|
||||||
|
|
||||||
\begin{tikzcd}
|
|
||||||
% https://q.uiver.app/#q=WzAsNixbMCwwLCJYIl0sWzEsMCwiWSJdLFsyLDAsIloiXSxbMSwxLCJZIl0sWzIsMSwiWiJdLFswLDEsIlgiXSxbMCwxLCJnXzEiLDAseyJvZmZzZXQiOi0yfV0sWzAsMSwiZ18yIiwyLHsib2Zmc2V0IjoyfV0sWzEsMiwiZiIsMl0sWzMsNCwiZ18xIiwwLHsib2Zmc2V0IjotMn1dLFszLDQsImdfMiIsMix7Im9mZnNldCI6Mn1dLFs1LDMsImYiLDJdXQ==
|
|
||||||
X & Y & Z \\
|
|
||||||
X & Y & Z
|
|
||||||
\arrow["{g_1}", shift left=2, from=1-1, to=1-2]
|
|
||||||
\arrow["{g_2}"', shift right=2, from=1-1, to=1-2]
|
|
||||||
\arrow["f"', from=1-2, to=1-3]
|
|
||||||
\arrow["f"', from=2-1, to=2-2]
|
|
||||||
\arrow["{g_1}", shift left=2, from=2-2, to=2-3]
|
|
||||||
\arrow["{g_2}"', shift right=2, from=2-2, to=2-3]
|
|
||||||
\end{tikzcd}
|
|
||||||
|
|
||||||
* Footnotes
|
|
||||||
|
|
||||||
[fn:1] blahahahahah blah blah
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.roam-test
|
|
||||||
(:require [net.deertopia.doerg.roam :as sut]
|
|
||||||
[clojure.test :as t]
|
|
||||||
[clojure.java.io :as io]
|
|
||||||
[net.deertopia.doerg.config :as cfg]
|
|
||||||
[babashka.fs :as fs]
|
|
||||||
[babashka.process :as p]
|
|
||||||
[net.deertopia.doerg.config-test :refer [test-config-fixture]]
|
|
||||||
[next.jdbc :as sql]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[net.deertopia.doerg.elisp :as elisp]
|
|
||||||
[com.rpl.specter :as sp]))
|
|
||||||
|
|
||||||
(def org-roam-directory
|
|
||||||
(fs/file "test/net/deertopia/doerg/roam-test"))
|
|
||||||
|
|
||||||
(defn org-roam-db-sync [db-file]
|
|
||||||
(let [script-file (fs/create-temp-file {:prefix "org-roam-db-sync-"
|
|
||||||
:suffix ".el"})
|
|
||||||
emacs (->> [(System/getenv "EMACS") "test-emacs" "emacs"]
|
|
||||||
(some #(some-> % fs/which)))]
|
|
||||||
(io/copy (-> "net/deertopia/doerg/org-roam-db-sync.el"
|
|
||||||
io/resource io/reader)
|
|
||||||
(fs/file script-file))
|
|
||||||
(p/shell {:out :string :err :string}
|
|
||||||
emacs "-Q" "-x" script-file org-roam-directory db-file)
|
|
||||||
(fs/delete script-file)))
|
|
||||||
|
|
||||||
(defn test-db-fixture [f]
|
|
||||||
(let [db-file (-> cfg/*cfg* ::cfg/org-roam-db-path)]
|
|
||||||
(assert (->> db-file fs/canonicalize str
|
|
||||||
(re-matches #"^/(build|tmp)/.*"))
|
|
||||||
(format "i'm scared to delete a non-test database... %s"
|
|
||||||
(str db-file)))
|
|
||||||
(fs/delete-if-exists db-file)
|
|
||||||
(org-roam-db-sync db-file)
|
|
||||||
(f)
|
|
||||||
(fs/delete db-file)))
|
|
||||||
|
|
||||||
(t/use-fixtures
|
|
||||||
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(t/deftest all-nodes-exist
|
|
||||||
(let [known-node-files (->> (fs/list-dir org-roam-directory)
|
|
||||||
(map (comp str fs/canonicalize))
|
|
||||||
(into #{}))
|
|
||||||
database-nodes
|
|
||||||
(->> (sql/execute!
|
|
||||||
(sut/ds) ["select file, id from nodes"])
|
|
||||||
(map (fn [x]
|
|
||||||
{:file (-> x :nodes/file elisp/read-string)
|
|
||||||
:id (-> x :nodes/id elisp/read-string parse-uuid)}))
|
|
||||||
(into #{}))]
|
|
||||||
(t/testing "database has a node for each file?"
|
|
||||||
(t/is (= known-node-files (sp/transform
|
|
||||||
[sp/ALL]
|
|
||||||
#(:file %)
|
|
||||||
database-nodes))))
|
|
||||||
(t/testing "each uuid exists?"
|
|
||||||
(t/is (every? (comp sut/uuid-exists? :id)
|
|
||||||
database-nodes)))))
|
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
{ fetchzip
|
||||||
|
, fetchurl
|
||||||
|
, callPackage
|
||||||
|
}:
|
||||||
|
|
||||||
|
{
|
||||||
|
ibm-plex-web = callPackage ./ibm-plex-web.nix {};
|
||||||
|
}
|
||||||
File renamed without changes.
Reference in new issue
Block a user