Compare commits
31 Commits
d4ff27ada4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7aaec7388d | |||
| 7e6fb22d03 | |||
| ac1c0eacd9 | |||
| e0ceefa399 | |||
| a9d105b639 | |||
| 1c31f4064a | |||
| 4e343fde99 | |||
| d967188e18 | |||
| 694136b643 | |||
| 32a45b3a16 | |||
| 5472d93cff | |||
| 32dad302f0 | |||
| 7fbc5c8059 | |||
| 55dd22f220 | |||
| dcaac98252 | |||
| 5ca59fdb5e | |||
| 55fa2473a2 | |||
| 9349293684 | |||
| 4d310afa18 | |||
| 7634303b13 | |||
| cf242b778d | |||
| 9cc0def4d5 | |||
| e02b77e1e4 | |||
| c74e36d8af | |||
| 36e328915e | |||
| b607ab8cae | |||
| fb2974bb21 | |||
| 79735cc0ba | |||
| 931f6f9006 | |||
| 811d07de39 | |||
| 29d5cdc85a |
1
.dir-locals.el
Normal file
1
.dir-locals.el
Normal file
@@ -0,0 +1 @@
|
|||||||
|
((nil . ((cider-clojure-cli-aliases . ":dev:test"))))
|
||||||
@@ -9,5 +9,3 @@ 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
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,7 +9,6 @@ result-*
|
|||||||
.lsp
|
.lsp
|
||||||
.nrepl
|
.nrepl
|
||||||
.direnv/
|
.direnv/
|
||||||
resources/vendor/*
|
|
||||||
node_modules
|
node_modules
|
||||||
.cljs_node_repl
|
.cljs_node_repl
|
||||||
build/
|
build/
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
, 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 ? callPackage ./our-tex.nix {}
|
, our-tex
|
||||||
, makeWrapper
|
, makeWrapper
|
||||||
|
, writeText
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -23,23 +25,39 @@ let
|
|||||||
plex = ibm-plex-web.override {
|
plex = ibm-plex-web.override {
|
||||||
families = [ "math" "serif" "sans" "sans-kr" ];
|
families = [ "math" "serif" "sans" "sans-kr" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
bin-path = lib.makeBinPath [
|
bin-path = lib.makeBinPath [
|
||||||
doerg-parser
|
doerg-parser
|
||||||
our-tex
|
our-tex
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
];
|
];
|
||||||
|
|
||||||
|
doerg-config = writeText "doerg-extra-config.edn" ''
|
||||||
|
#:net.deertopia.doerg.config
|
||||||
|
{:ibm-plex-web "${ibm-plex-web}/share/ibm-plex-web"
|
||||||
|
:latex "${lib.getExe' our-tex "xelatex"}"
|
||||||
|
:dvisvgm "${lib.getExe' our-tex "dvisvgm"}"
|
||||||
|
:doerg-temml-worker "${lib.getExe doerg-temml-worker}"
|
||||||
|
:doerg-parser "${lib.getExe doerg-parser}"}
|
||||||
|
'';
|
||||||
in mkCljBin' {
|
in mkCljBin' {
|
||||||
name = "net.deertopia/doerg";
|
name = "net.deertopia/doerg";
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
projectSrc = lib.cleanSource ./.;
|
projectSrc = lib.cleanSourceWith {
|
||||||
lockfile = ../deps-lock.json;
|
filter = path: type:
|
||||||
|
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
|
||||||
];
|
];
|
||||||
buildInputs = [
|
propagatedBuildInputs = [
|
||||||
doerg-parser
|
doerg-parser
|
||||||
|
ibm-plex-web
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
plex
|
plex
|
||||||
our-tex
|
our-tex
|
||||||
@@ -47,15 +65,20 @@ in mkCljBin' {
|
|||||||
nativeCheckInputs = [
|
nativeCheckInputs = [
|
||||||
doerg-parser
|
doerg-parser
|
||||||
doerg-temml-worker
|
doerg-temml-worker
|
||||||
|
test-emacs
|
||||||
plex
|
plex
|
||||||
our-tex
|
our-tex
|
||||||
];
|
];
|
||||||
|
preBuild = ''
|
||||||
|
cp ${doerg-config} resources/net/deertopia/doerg/extra-config.edn
|
||||||
|
'';
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
checkPhase = ''
|
checkPhase = ''
|
||||||
|
export \
|
||||||
|
EMACS=test-emacs \
|
||||||
|
XDG_STATE_HOME=$(mktemp -d "state-home-XXXXXX")
|
||||||
clojure -M:test
|
clojure -M:test
|
||||||
'';
|
'';
|
||||||
postInstall = ''
|
passthru = { inherit plex our-tex test-emacs doerg-config; };
|
||||||
wrapProgram $out/bin/doerg \
|
meta.mainProgram = "doerg";
|
||||||
--prefix PATH : ${bin-path}
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
{
|
{
|
||||||
"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",
|
||||||
@@ -145,11 +137,6 @@
|
|||||||
"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/",
|
||||||
@@ -371,14 +358,9 @@
|
|||||||
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "fipp/fipp/0.6.27/fipp-0.6.27.jar",
|
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.pom",
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
"hash": "sha256-qK1dAlan2r+90UOm6QvnZXURhA/is4MMp9tnK20RDPc="
|
"hash": "sha256-p+xjV7gTIRMv0HwvV+/rAhFEFVlDY9g6FDE6GU9fVTU="
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "fipp/fipp/0.6.27/fipp-0.6.27.pom",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-ugagpDW5XBNQMTr+1z3s6r5TXwbF/pw6Ffrcc4Tzlvk="
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "fipp/fipp/0.6.29/fipp-0.6.29.jar",
|
"mvn-path": "fipp/fipp/0.6.29/fipp-0.6.29.jar",
|
||||||
@@ -486,14 +468,14 @@
|
|||||||
"hash": "sha256-1PXzUUHstr5hI/+oPIQUGogO744bynAw2Zoo5HSjTbE="
|
"hash": "sha256-1PXzUUHstr5hI/+oPIQUGogO744bynAw2Zoo5HSjTbE="
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.jar",
|
"mvn-path": "lambdaisland/deep-diff2/2.11.216/deep-diff2-2.11.216.jar",
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
"hash": "sha256-BkOq5C/7omo09wyTTg7nkBi6GWBmlayVsPa9mrDvCyU="
|
"hash": "sha256-U2zJZmPIO66EtkgwwfyY41uRyu2DRmXH0ogNfluw5Rg="
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.pom",
|
"mvn-path": "lambdaisland/deep-diff2/2.11.216/deep-diff2-2.11.216.pom",
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
"mvn-repo": "https://repo.clojars.org/",
|
||||||
"hash": "sha256-rW/85js2hSWVc36e2BcTRmkahJHc2TjGIEfvForuToY="
|
"hash": "sha256-ok3nYS+8XCcCTPJIkqaO1SQH6v2ENwK2GZJdH0c4D20="
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "lambdaisland/kaocha/1.91.1392/kaocha-1.91.1392.jar",
|
"mvn-path": "lambdaisland/kaocha/1.91.1392/kaocha-1.91.1392.jar",
|
||||||
@@ -971,14 +953,9 @@
|
|||||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/core.rrb-vector/0.2.0/core.rrb-vector-0.2.0.jar",
|
"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/",
|
||||||
"hash": "sha256-ftqNXGlaxVNp3NTHN4YUMhdXuBAoG//KMMss02PRZZQ="
|
"hash": "sha256-juK6yvw4QzWMznZRDXMyQhK7NRn61XgE7Oq9w3rFCR8="
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.rrb-vector/0.2.0/core.rrb-vector-0.2.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-t+0/8ZfxrdZOHvJS2zRY8wlhPcZXdejY4OkTlx4CRY4="
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/core.rrb-vector/0.2.1/core.rrb-vector-0.2.1.jar",
|
"mvn-path": "org/clojure/core.rrb-vector/0.2.1/core.rrb-vector-0.2.1.jar",
|
||||||
@@ -1060,11 +1037,6 @@
|
|||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
"hash": "sha256-CRbXpBVYuVAKQnyIb6KYJ6zlJZIGvjrTPmTilvwaYRE="
|
"hash": "sha256-CRbXpBVYuVAKQnyIb6KYJ6zlJZIGvjrTPmTilvwaYRE="
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/pom.contrib/1.3.0/pom.contrib-1.3.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-g5qUXfrO6lvVB5+CSPM0bdIULesJFGyj9dG/riYxCWc="
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/pom.contrib/1.4.0/pom.contrib-1.4.0.pom",
|
"mvn-path": "org/clojure/pom.contrib/1.4.0/pom.contrib-1.4.0.pom",
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
@@ -1100,16 +1072,6 @@
|
|||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
"hash": "sha256-PLp+DcwIXEzpLd3/6iJhJP+sF4vnm9A3m1suMKlpy+o="
|
"hash": "sha256-PLp+DcwIXEzpLd3/6iJhJP+sF4vnm9A3m1suMKlpy+o="
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/test.check/1.1.2/test.check-1.1.2.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-93r5qZJ67LZqNoa282s1Al8kvOZr8/AF3UTcQEvIdgE="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/test.check/1.1.2/test.check-1.1.2.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-UZ45jnJMYvCsnWsZ15+P8QAdqYWD/eAb1wUrB+Ga1ow="
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"mvn-path": "org/clojure/test.check/1.1.3/test.check-1.1.3.jar",
|
"mvn-path": "org/clojure/test.check/1.1.3/test.check-1.1.3.jar",
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||||
@@ -1140,11 +1102,6 @@
|
|||||||
"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/",
|
||||||
|
|||||||
24
deps.edn
Normal file
24
deps.edn
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{: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"]}}}
|
||||||
17
dev/user.clj
Normal file
17
dev/user.clj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
(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))
|
||||||
@@ -10,4 +10,5 @@ buildNpmPackage {
|
|||||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||||
npmConfigHook = importNpmLock.npmConfigHook;
|
npmConfigHook = importNpmLock.npmConfigHook;
|
||||||
dontNpmBuild = true;
|
dontNpmBuild = true;
|
||||||
|
meta.mainProgram = "doerg-parser";
|
||||||
}
|
}
|
||||||
@@ -18,4 +18,5 @@ buildNpmPackage {
|
|||||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||||
npmConfigHook = importNpmLock.npmConfigHook;
|
npmConfigHook = importNpmLock.npmConfigHook;
|
||||||
dontNpmBuild = true;
|
dontNpmBuild = true;
|
||||||
|
meta.mainProgram = "doerg-temml-worker";
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#+title: Doerg specification
|
|
||||||
#+author: Guppy
|
|
||||||
|
|
||||||
* Footnotes
|
|
||||||
|
|
||||||
- A bunch of metadata should be read into a node of type =doerg-data=
|
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
{
|
|
||||||
"lock-version": 4,
|
|
||||||
"git-deps": [],
|
|
||||||
"mvn-deps": [
|
|
||||||
{
|
|
||||||
"mvn-path": "babashka/fs/0.5.24/fs-0.5.24.jar",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-owunNIWFqt6xNGhNV6vFs7GyYEz8z8wHRT7TSw1MDlU="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "babashka/fs/0.5.24/fs-0.5.24.pom",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-E1jX6M3DeoTXVU6Vzd6xIpE0s9QAZpZALJl4nSKU8E8="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "babashka/process/0.6.25/process-0.6.25.jar",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-XWTJ6kUgLD3/UJGe++Lf0+/Ja9SPViS50v33v3JOf4s="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "babashka/process/0.6.25/process-0.6.25.pom",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-4bSR/Z0g4rXVwv2u6e9rkoL8d1nV5b9iNIs/U2o8l8Y="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "cheshire/cheshire/6.1.0/cheshire-6.1.0.jar",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-ruCrbkSBlaoJXyLEKOINK8YQWRxUwQ7D4YPdOwgWOcI="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "cheshire/cheshire/6.1.0/cheshire-6.1.0.pom",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-KKpi9U7eZ2YjAyQI14sMgqv91IiMfFagshIrg+Pad+M="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-XxZVisIjBzpvJHRA8wX1nwXv9QqvHurguq1BKAABb2g="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.20.0/jackson-dataformat-cbor-2.20.0.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-qwdWFsvWf1Z2+Jgl7JyLx7VMhNvpNLFiFFs0FyNwtdY="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.20.0/jackson-dataformat-cbor-2.20.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-SYvwMYvqLnY2Wf0r/k8W8pHt8JNaMMnysKKP7jrXz8c="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/dataformat/jackson-dataformat-smile/2.20.0/jackson-dataformat-smile-2.20.0.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-NFwALLesnlQ0Go8ExWoR3CGUVCbqg5n/VuAvuOkSpm4="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/dataformat/jackson-dataformat-smile/2.20.0/jackson-dataformat-smile-2.20.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-IM1JgnnQUcaQMkt6R1+Ee/wQoAcQS6uc371ga1sFhDk="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/dataformat/jackson-dataformats-binary/2.20.0/jackson-dataformats-binary-2.20.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-ZJ/OQKV9Qhx82erCP919XPbzwdG5NAbuJ3xFw1Mm5Yg="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/jackson-base/2.20.0/jackson-base-2.20.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-/IgCjRnuqjftpZbmuY03SfIs/IrdGeoZdFq+g2iDzmY="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/jackson-bom/2.20.0/jackson-bom-2.20.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-9ig2R+cB/aHNMS3MIcsTKkD3mPGejkL6/D/jR8WlG7s="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/jackson/jackson-parent/2.20/jackson-parent-2.20.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-tDt/XGLoaxZPrnCuF9aRHF22B5mvAQVzYK/aguSEW+U="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "com/fasterxml/oss-parent/70/oss-parent-70.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-JsqO1vgsnS7XzTIpgQW7ZcD52JnbYXV6CXQVhvqTpjk="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.10.3/clojure-1.10.3.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-fxJHLa7Y9rUXSYqqKrE6ViR1w+31FHjkWBzHYemJeaM="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.10.3/clojure-1.10.3.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-GJwAxDNAdJai+7DsyzeQjJSVXZHq0b5IFWdE7MGBbZQ="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.0/clojure-1.11.0.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-PiH6daB+yd278bK1A1bPGAcQ0DmN6qT0TpHNYwRVWUc="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.0/clojure-1.11.0.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-SQjMS0yeYsmoFJb5PLWsb2lBd8xkXc87jOXkkavOHro="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.1/clojure-1.11.1.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-I4G26UI6tGUVFFWUSQPROlYkPWAGuRlK/Bv0+HEMtN4="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.1/clojure-1.11.1.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-IMRaGr7b2L4grvk2BQrjGgjBZ0CzL4dAuIOM3pb/y4o="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.2/clojure-1.11.2.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-iPqZkT1pIs+39kn1xGdQOHfLb8yMwW02948mSAhLqZc="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.2/clojure-1.11.2.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-FzbP/xCV4dT+/raogrut9ttB7+MV8pbw/aMtt//EExE="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.3/clojure-1.11.3.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-nDBUCTKOK5boXdK160t1gQxnt2unCuTQ9t3pvPtVsbc="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.3/clojure-1.11.3.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-DA2+Ge4NKpxXMQzr3dNWRD8NFlFMQmBHsGLjpXwNuK0="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.4/clojure-1.11.4.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-/H/xtmENDjSUp1zBHvgYEL2kAqwVcBL+TjuJlYbPQTM="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.11.4/clojure-1.11.4.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-a6YADmhI+Cw5y5tJqyqmo6Vi9MJNUrMeUZCuZJXwwwk="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.12.0/clojure-1.12.0.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-xFMzAGRBoFnqn9sTQfxsH0C5IaENzNgmZTEeSKA4R2M="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/clojure/1.12.0/clojure-1.12.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-KfRiqonLl2RXWEGKXwjUwagrc1yW569JgX0WqpuQgVA="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.match/1.1.0/core.match-1.1.0.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-10V6tjEIWae9cTmEM4IEX6PN7A0T97qSEpfy8/uZj1M="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.match/1.1.0/core.match-1.1.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-/PRCveArBKhj8vzFjuaiowxM8Mlw99q4VjTwq3ERZrY="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-AarxdIP/HHSCySoHKV1+e8bjszIt9EsptXONAg/wB0A="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-Bu6owHC75FwVhWfkQ0OWgbyMRukSNBT4G/oyukLWy8g="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-F3i70Ti9GFkLgFS+nZGdG+toCfhbduXGKFtn1Ad9MA4="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.4.74/core.specs.alpha-0.4.74.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-63OsCM9JuoQMiLpnvu8RM2ylVDM9lAiAjXiUbg/rnds="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/core.specs.alpha/0.4.74/core.specs.alpha-0.4.74.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-M0EOuKpz1S2Vez3G4KZfOZisBiPL2BPZDDPm5onEJCk="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/pom.contrib/0.3.0/pom.contrib-0.3.0.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-fxgrOypUPgV0YL+T/8XpzvasUn3xoTdqfZki6+ee8Rk="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/pom.contrib/1.1.0/pom.contrib-1.1.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-EOzku1+YKQENwWVh9C67g7ry9HYFtR+RBbkvPKoIlxU="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/pom.contrib/1.2.0/pom.contrib-1.2.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-CRbXpBVYuVAKQnyIb6KYJ6zlJZIGvjrTPmTilvwaYRE="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-z2iZ+YUpjGSxPqEplGrZAo3uja3w6rmuGORVAn04JJw="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-WhHw4eizwFLmUcSYxpRbRNs1Nb8sGHGf3PZd8fiLE+Y="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-Z+yJjrVcZqlXpVJ53YXRN2u5lL2HZosrDeHrO5foquA="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.pom",
|
|
||||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
|
||||||
"hash": "sha256-bY3hTDrIdXYMX/kJVi/5hzB3AxxquTnxyxOeFp/pB1g="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.5.238/spec.alpha-0.5.238.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-lM2ZtupjlkHzevSGCmQ7btOZ7lqL5dcXz/C2Y8jXUHc="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/spec.alpha/0.5.238/spec.alpha-0.5.238.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-PLp+DcwIXEzpLd3/6iJhJP+sF4vnm9A3m1suMKlpy+o="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/tools.logging/1.3.0/tools.logging-1.3.0.jar",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-gmlpt42a2jJ95rfaDxdkV9lWFPo4woAyZhDzGmtRXJE="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/clojure/tools.logging/1.3.0/tools.logging-1.3.0.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-E15H98p5wKoYG2kJPML50aYyKt1qgli2aXxQCNIwv00="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "org/junit/junit-bom/5.13.4/junit-bom-5.13.4.pom",
|
|
||||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
|
||||||
"hash": "sha256-16CKmbJQLwu2jNTh+YTwv2kySqogi9D3M2bAP8NUikI="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "tigris/tigris/0.1.2/tigris-0.1.2.jar",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-SapkjttsFOVwlaEbOR6u5gZXgyP7eXVfkjMaxjAPl6A="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mvn-path": "tigris/tigris/0.1.2/tigris-0.1.2.pom",
|
|
||||||
"mvn-repo": "https://repo.clojars.org/",
|
|
||||||
"hash": "sha256-H9VZA1l1INzUrnbmoz7/XjWmFUIrutKo7ZrDMqr75KA="
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{: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"}
|
|
||||||
lambdaisland/deep-diff2 {:mvn/version "2.12.219"}
|
|
||||||
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"}}
|
|
||||||
:paths ["src" "resources" "test"]
|
|
||||||
:aliases
|
|
||||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
|
||||||
:main-opts ["-m" "kaocha.runner"]}}}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{:deps {babashka/fs {:mvn/version "0.5.24"}
|
|
||||||
cheshire/cheshire {:mvn/version "6.1.0"}
|
|
||||||
com.rpl/specter {:mvn/version "1.1.6"}
|
|
||||||
mvxcvi/clj-cbor {:mvn/version "1.1.1"}
|
|
||||||
babashka/process {:mvn/version "0.6.25"}}
|
|
||||||
:paths ["."]}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
(ns deserialise
|
|
||||||
"A toy script for conveniently interfacing with doerg-temml-worker
|
|
||||||
during development."
|
|
||||||
(:require [clj-cbor.core :as cbor]
|
|
||||||
[clojure.string :as str]))
|
|
||||||
|
|
||||||
(prn (cbor/decode cbor/default-codec System/in :eof))
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
(ns serialise
|
|
||||||
"A toy script for conveniently interfacing with doerg-temml-worker
|
|
||||||
during development."
|
|
||||||
(:require [clj-cbor.core :as cbor]
|
|
||||||
[clojure.string :as str]))
|
|
||||||
|
|
||||||
(defn w [x]
|
|
||||||
(cbor/encode cbor/default-codec System/out x))
|
|
||||||
|
|
||||||
(defn c [x]
|
|
||||||
(->> x cbor/encode (map #(format "%02x" %)) (str/join " ")))
|
|
||||||
|
|
||||||
(w "\\ifxetex blah \\fi")
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
(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))))
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.config
|
|
||||||
(:require [clojure.spec.alpha :as s]
|
|
||||||
[babashka.fs :as fs]
|
|
||||||
[spec-dict.main :refer [dict]]))
|
|
||||||
|
|
||||||
(s/def ::config
|
|
||||||
(s/keys :req [::ibm-plex-web
|
|
||||||
::latex
|
|
||||||
::dvisvgm
|
|
||||||
::doerg-temml-worker
|
|
||||||
::doerg-parser]))
|
|
||||||
|
|
||||||
(s/def ::file
|
|
||||||
(s/conformer (comp fs/file fs/absolutize fs/expand-home)))
|
|
||||||
|
|
||||||
(s/def ::executable #(or (fs/executable? %)
|
|
||||||
(and (fs/relative? %)
|
|
||||||
(fs/which %))))
|
|
||||||
|
|
||||||
(def default
|
|
||||||
{::ibm-plex-web
|
|
||||||
(fs/file (some #(let [x (fs/path % "ibm-plex-web")]
|
|
||||||
(and (fs/exists? x) x))
|
|
||||||
(fs/split-paths (System/getenv "XDG_DATA_DIRS"))))
|
|
||||||
::latex "xelatex"
|
|
||||||
::dvisvgm "dvisvgm"
|
|
||||||
;; TODO: Can we automatically set this to "./doerg-temml-worker/index.js" in
|
|
||||||
;; a development environment?
|
|
||||||
::doerg-temml-worker "doerg-temml-worker"
|
|
||||||
::doerg-parser "doerg-parser"})
|
|
||||||
|
|
||||||
(def ^:dynamic *cfg* default)
|
|
||||||
|
|
||||||
(s/def ::ibm-plex-web ::file)
|
|
||||||
|
|
||||||
(s/def ::latex ::executable)
|
|
||||||
|
|
||||||
(s/def ::dvisvgm ::executable)
|
|
||||||
|
|
||||||
(s/def ::doerg-temml-worker ::executable)
|
|
||||||
|
|
||||||
(s/def ::doerg-parser ::executable)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.main
|
|
||||||
(:gen-class))
|
|
||||||
|
|
||||||
(defn -main []
|
|
||||||
(println "hello from doerg"))
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
(ns net.deertopia.doerg.config-test
|
|
||||||
(:require [net.deertopia.doerg.config :as sut]
|
|
||||||
[clojure.test :as t]
|
|
||||||
[clojure.spec.alpha :as s]))
|
|
||||||
|
|
||||||
(t/deftest default-config-is-config
|
|
||||||
(t/testing "default config is valid"
|
|
||||||
(t/is (s/valid? ::sut/config sut/default))))
|
|
||||||
40
flake.lock
generated
40
flake.lock
generated
@@ -59,24 +59,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-fetcher-data": {
|
"nix-fetcher-data": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
@@ -129,11 +111,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760038930,
|
"lastModified": 1774386573,
|
||||||
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -162,7 +144,6 @@
|
|||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"clj-nix": "clj-nix",
|
"clj-nix": "clj-nix",
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
"sydpkgs": "sydpkgs"
|
"sydpkgs": "sydpkgs"
|
||||||
}
|
}
|
||||||
@@ -184,21 +165,6 @@
|
|||||||
"repo": "sydpkgs",
|
"repo": "sydpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
90
flake.nix
90
flake.nix
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
clj-nix.url = "github:jlesquembre/clj-nix";
|
clj-nix.url = "github:jlesquembre/clj-nix";
|
||||||
sydpkgs.url = "github:msyds/sydpkgs";
|
sydpkgs.url = "github:msyds/sydpkgs";
|
||||||
};
|
};
|
||||||
@@ -15,16 +14,19 @@
|
|||||||
"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 ++ [
|
||||||
inputs.sydpkgs.overlays.default
|
self.overlays.default
|
||||||
clj-nix.overlays.default
|
];
|
||||||
self.overlays.default
|
};
|
||||||
];
|
inherit (pkgs) lib;
|
||||||
};
|
|
||||||
inherit (pkgs) lib;
|
|
||||||
inherit system;
|
inherit system;
|
||||||
});
|
});
|
||||||
in {
|
in {
|
||||||
@@ -32,45 +34,51 @@
|
|||||||
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
||||||
|
|
||||||
packages = each-system ({ pkgs, ... }: {
|
packages = each-system ({ pkgs, ... }: {
|
||||||
inherit (pkgs) publisher doerg doerg-parser doerg-temml-worker;
|
inherit (pkgs) doerg doerg-parser doerg-temml-worker;
|
||||||
default = pkgs.publisher;
|
default = pkgs.doerg;
|
||||||
});
|
});
|
||||||
|
|
||||||
overlays.default = final: prev:
|
overlays.default = final: prev:
|
||||||
let graal = x: final.mkGraalBin { cljDrv = x; };
|
let
|
||||||
vendored = final.callPackage ./vendor {};
|
# is this really the correct way to satisfy our
|
||||||
in {
|
# dependencies? lmfao
|
||||||
inherit (vendored) ibm-plex-web;
|
final' = final.appendOverlays overlays;
|
||||||
publisher = final.callPackage ./publisher {};
|
graal = x: final'.mkGraalBin { cljDrv = x; };
|
||||||
doerg = final.callPackage ./doerg {};
|
in {
|
||||||
doerg-parser = final.callPackage ./doerg/doerg-parser {};
|
ibm-plex-web = final'.callPackage ./ibm-plex-web.nix {};
|
||||||
doerg-temml-worker = final.callPackage ./doerg/doerg-temml-worker {};
|
doerg = final'.callPackage ./. {};
|
||||||
};
|
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
module.nix
Normal file
107
module.nix
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
{ 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"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
((nil
|
|
||||||
. ((cider-clojure-cli-aliases . ":dev")
|
|
||||||
(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))))))
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
{ mkCljBin
|
|
||||||
, doerg
|
|
||||||
, babashka
|
|
||||||
}:
|
|
||||||
|
|
||||||
mkCljBin {
|
|
||||||
name = "net.deertopia/publisher";
|
|
||||||
version = "0.1.0";
|
|
||||||
projectSrc = ./.;
|
|
||||||
lockfile = ../deps-lock.json;
|
|
||||||
main-ns = "net.deertopia.publisher.main";
|
|
||||||
buildInputs = [];
|
|
||||||
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"}'
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{: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.2"}
|
|
||||||
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"}}
|
|
||||||
:paths ["src" "resources" "test"]}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
;;; -*- 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]
|
|
||||||
(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"}}))
|
|
||||||
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
(ns net.deertopia.publisher.config
|
|
||||||
(:require [babashka.fs :as fs]
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[net.deertopia.doerg.config :as doerg]))
|
|
||||||
|
|
||||||
(s/def ::config
|
|
||||||
(s/keys :req [::state-directory
|
|
||||||
::org-roam-db-path]))
|
|
||||||
|
|
||||||
(def default
|
|
||||||
{::state-directory (fs/xdg-state-home "doerg-publisher")
|
|
||||||
::org-roam-db-path (fs/file (fs/home) ".cache" "emacs" "org-roam.db")})
|
|
||||||
|
|
||||||
(def ^:dynamic *cfg* default)
|
|
||||||
|
|
||||||
(s/def ::state-directory ::doerg/file)
|
|
||||||
(s/def ::org-roam-db-path ::doerg/file)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
(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,112 +0,0 @@
|
|||||||
(ns net.deertopia.publisher.server
|
|
||||||
(:require [clojure.pprint :refer [pprint]]
|
|
||||||
[clojure.tools.logging :as l]
|
|
||||||
[hiccup2.core :as hiccup]
|
|
||||||
[net.deertopia.doerg.html :as doerg-html]
|
|
||||||
[net.deertopia.publisher.slug :as slug]
|
|
||||||
[net.deertopia.publisher.config :as cfg]
|
|
||||||
[net.deertopia.publisher.roam :as roam]
|
|
||||||
[org.httpkit.server :as http]
|
|
||||||
[reitit.coercion]
|
|
||||||
[reitit.coercion.spec]
|
|
||||||
[reitit.ring.coercion]
|
|
||||||
[reitit.core :as r]
|
|
||||||
[reitit.ring]
|
|
||||||
[reitit.ring.middleware.exception :as reitit-exception]
|
|
||||||
[ring.util.response :as response]
|
|
||||||
[spec-tools.spell]
|
|
||||||
[reitit.spec]
|
|
||||||
[reitit.dev.pretty]
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[net.deertopia.doerg.render :as doerg-render]))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Routes
|
|
||||||
|
|
||||||
(defn hello [req]
|
|
||||||
(-> (hiccup/html {}
|
|
||||||
[:html
|
|
||||||
[:head
|
|
||||||
[:title "hello"]
|
|
||||||
doerg-html/charset
|
|
||||||
doerg-html/viewport]
|
|
||||||
[:body
|
|
||||||
[:pre
|
|
||||||
(with-out-str
|
|
||||||
(pprint req))]]])
|
|
||||||
str
|
|
||||||
response/response
|
|
||||||
(response/content-type "text/html")))
|
|
||||||
|
|
||||||
(defn node-by-slug [{{{:keys [slug]} :path} :parameters}]
|
|
||||||
(let [html (-> slug slug/from-string roam/get-node
|
|
||||||
roam/org-file doerg-render/to-html)]
|
|
||||||
(-> html response/response
|
|
||||||
(response/content-type "text/html"))))
|
|
||||||
|
|
||||||
(defn node-by-id [req]
|
|
||||||
(hello req))
|
|
||||||
|
|
||||||
(def exception-middleware
|
|
||||||
(reitit-exception/create-exception-middleware
|
|
||||||
(merge
|
|
||||||
reitit-exception/default-handlers
|
|
||||||
{::reitit-exception/wrap
|
|
||||||
(fn [handler e request]
|
|
||||||
(l/error e "error in fucking somwhere dude")
|
|
||||||
(handler e request))})))
|
|
||||||
|
|
||||||
(def router
|
|
||||||
(reitit.ring/router
|
|
||||||
#{["/" {:get hello}]
|
|
||||||
["/n/:slug"
|
|
||||||
{:get {:handler #'node-by-slug
|
|
||||||
:parameters
|
|
||||||
{:path {:slug ::slug/slug}}}}]
|
|
||||||
["/id/:id" {:get #'node-by-id}]}
|
|
||||||
{:validate reitit.spec/validate
|
|
||||||
:exception reitit.dev.pretty/exception
|
|
||||||
:spec (s/merge :reitit.spec/default-data)
|
|
||||||
:data
|
|
||||||
{:coercion reitit.coercion.spec/coercion
|
|
||||||
:middleware [exception-middleware
|
|
||||||
reitit.ring.coercion/coerce-request-middleware
|
|
||||||
reitit.ring.coercion/coerce-response-middleware
|
|
||||||
#_reitit.ring.coercion/coerce-exceptions-middleware]}}))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Server API
|
|
||||||
|
|
||||||
(def app (reitit.ring/ring-handler router))
|
|
||||||
|
|
||||||
(defonce server (atom nil))
|
|
||||||
|
|
||||||
(defn stop! []
|
|
||||||
(when @server
|
|
||||||
(http/server-stop! @server {:timeout 100})
|
|
||||||
(reset! server nil)
|
|
||||||
(l/info "Stopped server")))
|
|
||||||
|
|
||||||
;; For some reason, the log messages from `stop!` are not flushed
|
|
||||||
;; before the JVM shuts dowm. Nevertheless, the server /does/ come to
|
|
||||||
;; a graceful halt.
|
|
||||||
(def ^:private shutdown-hook (Thread. stop!))
|
|
||||||
|
|
||||||
(defn start! []
|
|
||||||
(if @server
|
|
||||||
(let [msg "Server already started"]
|
|
||||||
(throw (ex-info msg {})))
|
|
||||||
(do (reset! server
|
|
||||||
(http/run-server (bound-fn* #'app)
|
|
||||||
{:port 8080
|
|
||||||
:legacy-return-value? false}))
|
|
||||||
;; For some reason, the log messages are not flushed before
|
|
||||||
;; the JVM shuts dowm. Nevertheless, the server /does/ come
|
|
||||||
;; to a graceful halt.
|
|
||||||
(.addShutdownHook (Runtime/getRuntime) shutdown-hook)
|
|
||||||
(l/info "Server started on port 8080"))))
|
|
||||||
|
|
||||||
(defn status []
|
|
||||||
(if @server
|
|
||||||
(http/server-status @server)
|
|
||||||
:stopped))
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{ 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=";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
18
resources/net/deertopia/doerg/default-config.edn
Normal file
18
resources/net/deertopia/doerg/default-config.edn
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#: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}}
|
||||||
BIN
resources/net/deertopia/doerg/favicon.ico
Normal file
BIN
resources/net/deertopia/doerg/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
1
resources/net/deertopia/doerg/public/Temml-Plex.css
Symbolic link
1
resources/net/deertopia/doerg/public/Temml-Plex.css
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../Temml-Plex.css
|
||||||
1
resources/net/deertopia/doerg/public/deerstar.css
Symbolic link
1
resources/net/deertopia/doerg/public/deerstar.css
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../deerstar.css
|
||||||
1
resources/net/deertopia/doerg/public/tuftesque.css
Symbolic link
1
resources/net/deertopia/doerg/public/tuftesque.css
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tuftesque.css
|
||||||
@@ -438,7 +438,7 @@ label.margin-toggle:not(.sidenote-number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.link.external::after
|
.org-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%
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(ns net.deertopia.publisher.cached-file
|
(ns net.deertopia.doerg.cached-file
|
||||||
(:require [babashka.fs :as fs]))
|
(:require [babashka.fs :as fs]))
|
||||||
|
|
||||||
(defn newer-than?
|
(defn newer-than?
|
||||||
@@ -18,7 +18,10 @@
|
|||||||
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 dir))
|
||||||
(spit file r)))
|
(spit file r)))
|
||||||
file)
|
file)
|
||||||
87
src/net/deertopia/doerg/config.clj
Normal file
87
src/net/deertopia/doerg/config.clj
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
(ns net.deertopia.doerg.config
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[babashka.fs :as fs]
|
||||||
|
[aero.core :as aero]
|
||||||
|
[clojure.java.io :as io]))
|
||||||
|
|
||||||
|
(s/def ::config
|
||||||
|
(s/keys :req [::ibm-plex-web
|
||||||
|
::latex
|
||||||
|
::dvisvgm
|
||||||
|
::doerg-temml-worker
|
||||||
|
::doerg-parser
|
||||||
|
::state-directory
|
||||||
|
::org-roam-db-path]))
|
||||||
|
|
||||||
|
(s/def ::directory
|
||||||
|
(s/conformer #(fs/file %)))
|
||||||
|
|
||||||
|
(s/def ::file
|
||||||
|
(s/conformer #(-> % fs/expand-home fs/file)))
|
||||||
|
|
||||||
|
(s/def ::executable
|
||||||
|
(s/conformer
|
||||||
|
;; I'd love to use `fs/which` here, but it's fairly problematic to
|
||||||
|
;; check `fs/executable?` at… build time (which `fs/which` does)?
|
||||||
|
;; Wait… what? Do I know how Clojure compilation works?
|
||||||
|
#(or #_(some-> % fs/expand-home fs/which fs/file)
|
||||||
|
(some-> % fs/expand-home fs/file)
|
||||||
|
::s/invalid)))
|
||||||
|
|
||||||
|
(s/def ::ibm-plex-web ::directory)
|
||||||
|
|
||||||
|
(s/def ::latex ::executable)
|
||||||
|
|
||||||
|
(s/def ::dvisvgm ::executable)
|
||||||
|
|
||||||
|
(s/def ::doerg-temml-worker ::executable)
|
||||||
|
|
||||||
|
(s/def ::doerg-parser ::executable)
|
||||||
|
|
||||||
|
(s/def ::state-directory ::file)
|
||||||
|
(s/def ::org-roam-db-path ::file)
|
||||||
|
|
||||||
|
(defmethod aero/reader 'xdg-data-dir
|
||||||
|
[_opts tag value]
|
||||||
|
"Aero tag to search for a directory on $XDG_DATA_DIRS."
|
||||||
|
(some #(let [x (fs/path % value)]
|
||||||
|
(and (fs/exists? x) x))
|
||||||
|
(some-> (System/getenv "XDG_DATA_DIRS")
|
||||||
|
fs/split-paths)))
|
||||||
|
|
||||||
|
(defmethod aero/reader 'file
|
||||||
|
[{:keys [source]} tag value]
|
||||||
|
"Aero tag to reference a `java.io.File` relative to the config
|
||||||
|
file."
|
||||||
|
(-> (aero/relative-resolver source value)
|
||||||
|
fs/file))
|
||||||
|
|
||||||
|
(defn read-config [files & {:as opts}]
|
||||||
|
(let [r (->> files
|
||||||
|
(filter identity)
|
||||||
|
(map #(aero/read-config % opts))
|
||||||
|
(apply merge))
|
||||||
|
conformed (s/conform ::config r)]
|
||||||
|
(if-not (s/invalid? conformed)
|
||||||
|
conformed
|
||||||
|
(throw (ex-info "Failed to conform config"
|
||||||
|
(s/explain-data ::config r))))))
|
||||||
|
|
||||||
|
(def sources
|
||||||
|
[;; Default config.
|
||||||
|
(io/resource "net/deertopia/doerg/default-config.edn")
|
||||||
|
;; Defaults set at build time, if any.
|
||||||
|
(io/resource "net/deertopia/doerg/extra-config.edn")
|
||||||
|
;; Config set at runtime.
|
||||||
|
(System/getenv "DOERG_CONFIG")])
|
||||||
|
|
||||||
|
(def default (read-config sources))
|
||||||
|
|
||||||
|
(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))))))
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
[clojure.core.match :refer [match]]
|
[clojure.core.match :refer [match]]
|
||||||
[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]
|
||||||
@@ -15,7 +14,6 @@
|
|||||||
[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)))
|
||||||
@@ -36,7 +34,7 @@
|
|||||||
:or {in *in*}}]
|
:or {in *in*}}]
|
||||||
(let [r (-> (p/process
|
(let [r (-> (p/process
|
||||||
{:in in :out :string}
|
{:in in :out :string}
|
||||||
(::cfg/doerg-parser cfg/*cfg*))
|
(-> cfg/*cfg* ::cfg/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))))))
|
||||||
@@ -64,8 +62,6 @@
|
|||||||
(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)))
|
||||||
|
|
||||||
@@ -98,16 +94,6 @@
|
|||||||
(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
|
||||||
|
|
||||||
@@ -314,149 +300,3 @@
|
|||||||
(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)
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
(ns net.deertopia.publisher.elisp
|
(ns net.deertopia.doerg.elisp
|
||||||
(:require
|
(:require [clojure.core.match :refer [match]]
|
||||||
[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]
|
[instaparse.core :as ip])
|
||||||
[instaparse.core :as ip]))
|
(:refer-clojure :exclude [print read read-string]))
|
||||||
|
|
||||||
(ip/defparser read*
|
(ip/defparser read*
|
||||||
(io/resource "net/deertopia/publisher/elisp/grammar"))
|
(io/resource "net/deertopia/doerg/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.publisher.roam`
|
;; moment, `print` is only used in `net.deertopia.doerg.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 (string? x) (str \" x \")
|
(cond (or (string? x) (uuid? x)) (str \" x \")
|
||||||
:else (throw (ex-info "`print` is unimplemented lol"
|
:else (throw (ex-info "`print` is unimplemented lol"
|
||||||
{:x x}))))
|
{:x x}))))
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
(ns net.deertopia.doerg.html
|
(ns net.deertopia.doerg.html
|
||||||
"Common HTML elements and utilities"
|
"Common HTML elements and utilities"
|
||||||
(:require [clojure.java.io :as io]
|
(:require [clojure.java.io :as io]
|
||||||
[net.deertopia.doerg.config :as cfg]
|
|
||||||
[babashka.fs :as fs]))
|
[babashka.fs :as fs]))
|
||||||
|
|
||||||
#_
|
#_
|
||||||
@@ -28,7 +27,7 @@
|
|||||||
[:meta {:charset "utf-8"}])
|
[:meta {:charset "utf-8"}])
|
||||||
|
|
||||||
(defn external-stylesheet [href]
|
(defn external-stylesheet [href]
|
||||||
[:link {:rel "stylesheet" :type "text/css" :href href}])
|
[:link {:rel "stylesheet" :type "text/css" :href (str "/resource/" href)}])
|
||||||
|
|
||||||
(def ibm-plex
|
(def ibm-plex
|
||||||
(concat
|
(concat
|
||||||
8
src/net/deertopia/doerg/main.clj
Normal file
8
src/net/deertopia/doerg/main.clj
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(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!)))
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
[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
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
#(do (assert (element/of-type? % "keyword"))
|
#(do (assert (element/of-type? % "keyword"))
|
||||||
(:key %)))
|
(:key %)))
|
||||||
|
|
||||||
(def ^:dynamic ^:private *document-info*)
|
(def ^:dynamic ^:private *opts*)
|
||||||
|
|
||||||
(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)
|
||||||
@@ -62,23 +63,31 @@
|
|||||||
|
|
||||||
(defn org-document
|
(defn org-document
|
||||||
"Recursively render an Org-mode document to Hiccup."
|
"Recursively render an Org-mode document to Hiccup."
|
||||||
[doc]
|
[doc & {:as opts :keys [postamble header title]}]
|
||||||
(tex-temml/binding-worker
|
(binding [*opts* opts]
|
||||||
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
(tex-temml/binding-worker
|
||||||
org-element-recursive)]
|
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
||||||
[:html
|
org-element-recursive)]
|
||||||
[:head
|
[:html
|
||||||
[:title "org document"]
|
[:head
|
||||||
doerg-html/head]
|
(when title
|
||||||
[:body {:lang default-language}
|
[:title title])
|
||||||
[:article
|
doerg-html/head]
|
||||||
rendered]]])))
|
[:body {:lang default-language}
|
||||||
|
(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."
|
rendered HTML. See `org-document` for opts."
|
||||||
[f]
|
[f & {:as opts}]
|
||||||
(str (hiccup/html {} (-> f slurp element/read-string org-document))))
|
(str (hiccup/html {} (-> f slurp element/read-string (org-document opts)))))
|
||||||
|
|
||||||
|
|
||||||
;;; Further dispatching on `org-element`
|
;;; Further dispatching on `org-element`
|
||||||
@@ -102,6 +111,19 @@
|
|||||||
(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)))
|
||||||
@@ -179,7 +201,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn- render-pprint
|
(defn render-pprint
|
||||||
"Render the argument inline as `clojure.pprint/pprint` output."
|
"Render the argument inline as `clojure.pprint/pprint` output."
|
||||||
[x & {:keys [text]
|
[x & {:keys [text]
|
||||||
:or {text "debug!"}}]
|
:or {text "debug!"}}]
|
||||||
@@ -254,11 +276,14 @@
|
|||||||
(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]}]
|
||||||
[:super children])
|
[:sup children])
|
||||||
|
|
||||||
(defmethod org-element "italic" [{:keys [children]}]
|
(defmethod org-element "italic" [{:keys [children]}]
|
||||||
[:em children])
|
[:em children])
|
||||||
@@ -329,23 +354,52 @@
|
|||||||
[:span.latex-fragment.display-math
|
[:span.latex-fragment.display-math
|
||||||
(-> e ::rendered deref)])
|
(-> e ::rendered deref)])
|
||||||
|
|
||||||
(defmethod org-element "example-block" [{:keys [value]}]
|
(defmethod org-element "example-block" [{:keys [value] :as e}]
|
||||||
[:pre value])
|
(let [{:keys [center? alt scale img?]} (doerg-attrs e)]
|
||||||
|
(-> [: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]])
|
||||||
|
|
||||||
(defmethod org-element "quote-block" [{:keys [children]}]
|
(defn- split-quote-block-children [children]
|
||||||
[:blockquote children])
|
(match (split-with #(not= % [:hr]) 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)
|
||||||
|
|
||||||
@@ -5,7 +5,8 @@
|
|||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[hiccup2.core :as h]
|
[hiccup2.core :as h]
|
||||||
[clojure.pprint]
|
[clojure.pprint]
|
||||||
[babashka.fs :as fs]))
|
[babashka.fs :as fs]
|
||||||
|
[net.deertopia.doerg :as-alias doerg]))
|
||||||
|
|
||||||
(def some-org-file
|
(def some-org-file
|
||||||
#_
|
#_
|
||||||
@@ -27,27 +28,20 @@
|
|||||||
(fs/delete-if-exists path)
|
(fs/delete-if-exists path)
|
||||||
(fs/create-sym-link path target))
|
(fs/create-sym-link path target))
|
||||||
|
|
||||||
(defn reconfigure-doerg! []
|
|
||||||
(alter-var-root
|
|
||||||
#'cfg/*cfg*
|
|
||||||
#(assoc %
|
|
||||||
::cfg/doerg-temml-worker "./doerg-temml-worker/index.js"
|
|
||||||
::cfg/doerg-parser "./doerg-parser/index.js")))
|
|
||||||
|
|
||||||
(defn render-html [& {:keys [src dest]
|
(defn render-html [& {:keys [src dest]
|
||||||
:or {src some-org-file
|
:or {src some-org-file
|
||||||
dest "/tmp/doerg-test"}}]
|
dest "/tmp/doerg-test"}}]
|
||||||
(fs/create-dirs dest)
|
(let [resource-dir (fs/file dest "resource")]
|
||||||
(force-create-sym-link (fs/file dest "ibm-plex-web")
|
(fs/create-dirs dest)
|
||||||
(-> cfg/*cfg* ::cfg/ibm-plex-web))
|
(fs/create-dirs resource-dir)
|
||||||
(force-create-sym-link (fs/file dest "deerstar.css")
|
(force-create-sym-link (fs/file resource-dir "ibm-plex-web")
|
||||||
(io/resource "net/deertopia/doerg/deerstar.css"))
|
(-> cfg/*cfg* ::cfg/ibm-plex-web))
|
||||||
(force-create-sym-link (fs/file dest "tuftesque.css")
|
(doseq [x #{"Temml-Plex.css" "tuftesque.css" "deerstar.css"}]
|
||||||
(io/resource "net/deertopia/doerg/tuftesque.css"))
|
(force-create-sym-link
|
||||||
(force-create-sym-link (fs/file dest "Temml-Plex.css")
|
(fs/file resource-dir x)
|
||||||
(io/resource "net/deertopia/doerg/Temml-Plex.css"))
|
(io/resource (str "net/deertopia/doerg/" x))))
|
||||||
(fs/delete-if-exists (fs/file dest "index.html"))
|
(fs/delete-if-exists (fs/file dest "index.html"))
|
||||||
(->> src render/to-html str (spit (fs/file dest "index.html"))))
|
(->> src render/to-html str (spit (fs/file dest "index.html")))))
|
||||||
|
|
||||||
(defn render-edn [& {:keys [src dest]
|
(defn render-edn [& {:keys [src dest]
|
||||||
:or {src some-org-file
|
:or {src some-org-file
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
(ns net.deertopia.publisher.roam
|
(ns net.deertopia.doerg.roam
|
||||||
(:require [babashka.fs :as fs]
|
(:require [babashka.fs :as fs]
|
||||||
[net.deertopia.publisher.config :as cfg]
|
[net.deertopia.doerg.config :as cfg]
|
||||||
[net.deertopia.publisher.elisp :as elisp]
|
[net.deertopia.doerg.elisp :as elisp]
|
||||||
[net.deertopia.publisher.slug :as slug]
|
[net.deertopia.doerg.slug :as slug]
|
||||||
[next.jdbc :as sql])
|
[next.jdbc :as sql])
|
||||||
(:import (java.util UUID)))
|
(:import (java.util UUID)))
|
||||||
|
|
||||||
@@ -11,13 +11,10 @@
|
|||||||
|
|
||||||
(defonce ^:dynamic *use-db-cache?* true)
|
(defonce ^:dynamic *use-db-cache?* true)
|
||||||
|
|
||||||
(def db-path (-> cfg/*cfg* ::cfg/org-roam-db-path
|
(defn ds []
|
||||||
fs/expand-home str))
|
(sql/get-datasource
|
||||||
|
{:dbtype "sqlite"
|
||||||
(def db {:dbtype "sqlite"
|
:dbname (-> cfg/*cfg* ::cfg/org-roam-db-path str)}))
|
||||||
:dbname db-path})
|
|
||||||
|
|
||||||
(def ds (sql/get-datasource db))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Elisp sexp (de)serialisation
|
;;; Elisp sexp (de)serialisation
|
||||||
@@ -29,15 +26,23 @@
|
|||||||
(-> node :id slug/from-uuid))
|
(-> node :id slug/from-uuid))
|
||||||
|
|
||||||
(defn- print-id [node]
|
(defn- print-id [node]
|
||||||
(-> node id print))
|
(-> node id elisp/print))
|
||||||
|
|
||||||
|
|
||||||
;;; Node
|
;;; Node
|
||||||
|
|
||||||
(defrecord Node [id cache])
|
(defrecord Node [id cache])
|
||||||
|
|
||||||
(defn make-node [uuid]
|
(defn uuid-exists? [uuid]
|
||||||
(->Node uuid (atom {})))
|
(sql/execute-one! (ds)
|
||||||
|
["select 1 from nodes where id = ? limit 1"
|
||||||
|
(-> uuid str elisp/print)]))
|
||||||
|
|
||||||
|
(defn make-node
|
||||||
|
([uuid] (make-node uuid {}))
|
||||||
|
([uuid props]
|
||||||
|
(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?*
|
||||||
@@ -52,11 +57,20 @@
|
|||||||
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."))
|
||||||
@@ -71,7 +85,7 @@
|
|||||||
java.util.UUID
|
java.util.UUID
|
||||||
(get-node [this]
|
(get-node [this]
|
||||||
(make-node this))
|
(make-node this))
|
||||||
net.deertopia.publisher.slug.Slug
|
net.deertopia.doerg.slug.Slug
|
||||||
(get-node [this]
|
(get-node [this]
|
||||||
(-> this slug/to-uuid make-node))
|
(-> this slug/to-uuid make-node))
|
||||||
Node
|
Node
|
||||||
@@ -83,7 +97,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 %))]))))
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +107,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)))
|
||||||
|
|
||||||
@@ -104,7 +118,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)))
|
||||||
@@ -113,31 +127,35 @@
|
|||||||
(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]
|
||||||
(-> node properties (get "DEERTOPIAVISIBILITY") (= "public")))
|
(some-> (properties node) (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"}
|
||||||
(-> node properties (get "DEERTOPIAVISIBILITY"))))
|
(some-> (properties node) (get "DEERTOPIAVISIBILITY"))))
|
||||||
|
|
||||||
(defn backlinks
|
(defn backlinks
|
||||||
"Returns a collection of maps {:id …, :title …}."
|
"Returns a collection of nodes linking to `node`."
|
||||||
[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 (:id node))])
|
(elisp/print (str (:id node)))])
|
||||||
:let [id (elisp/read-string id)]
|
:let [id' (elisp/read-string id)]
|
||||||
:when (graph-visible? (get-node (UUID/fromString id)))]
|
:when (some-> (-> id' parse-uuid get-node)
|
||||||
{:id id
|
public?)]
|
||||||
:title (elisp/read-string title)}))
|
(make-node id' {:title (elisp/read-string title)})))
|
||||||
|
|
||||||
|
|
||||||
;;; Graph support
|
;;; Graph support
|
||||||
@@ -149,9 +167,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
|
||||||
210
src/net/deertopia/doerg/server.clj
Normal file
210
src/net/deertopia/doerg/server.clj
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
(ns net.deertopia.doerg.server
|
||||||
|
(:require [clojure.pprint :refer [pprint]]
|
||||||
|
[clojure.tools.logging :as l]
|
||||||
|
[hiccup2.core :as hiccup]
|
||||||
|
[net.deertopia.doerg.html :as doerg-html]
|
||||||
|
[net.deertopia.doerg.config :as-alias cfg]
|
||||||
|
[net.deertopia.doerg.slug :as slug]
|
||||||
|
[net.deertopia.doerg.config :as cfg]
|
||||||
|
[net.deertopia.doerg.roam :as roam]
|
||||||
|
[org.httpkit.server :as http]
|
||||||
|
[reitit.coercion]
|
||||||
|
[reitit.coercion.spec]
|
||||||
|
[reitit.ring.coercion]
|
||||||
|
[reitit.core :as r]
|
||||||
|
[reitit.ring]
|
||||||
|
[reitit.ring.middleware.exception :as reitit-exception]
|
||||||
|
[ring.util.response :as response]
|
||||||
|
[spec-tools.spell]
|
||||||
|
[reitit.spec]
|
||||||
|
[reitit.dev.pretty]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[net.deertopia.doerg.render :as doerg-render]
|
||||||
|
[net.deertopia.doerg.cached-file :as cached-file]
|
||||||
|
[babashka.fs :as fs]
|
||||||
|
[aero.core :as aero]
|
||||||
|
[clojure.string :as str]))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Routes
|
||||||
|
|
||||||
|
(def homepage-slug "68XqhHerTWCbE--RYLEdHw")
|
||||||
|
(def not-found-slug "PGDHTvUzQ62Js1Y5db-A8g")
|
||||||
|
|
||||||
|
(defn hello [req]
|
||||||
|
(-> (hiccup/html {}
|
||||||
|
[:html
|
||||||
|
[:head
|
||||||
|
[:title "hello"]
|
||||||
|
doerg-html/charset
|
||||||
|
doerg-html/viewport]
|
||||||
|
[:body
|
||||||
|
[:pre
|
||||||
|
(with-out-str
|
||||||
|
(pprint req))]]])
|
||||||
|
str
|
||||||
|
response/response
|
||||||
|
(response/content-type "text/html")))
|
||||||
|
|
||||||
|
(defn html-dir []
|
||||||
|
(-> cfg/*cfg* ::cfg/state-directory (fs/file "html")))
|
||||||
|
|
||||||
|
(declare node-by-slug)
|
||||||
|
|
||||||
|
;; 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]
|
||||||
|
(fs/file (html-dir)
|
||||||
|
(-> org-file
|
||||||
|
fs/file-name
|
||||||
|
(fs/strip-ext {:ext "org"})
|
||||||
|
(str ".html"))))
|
||||||
|
|
||||||
|
(defn slug-link [slug & contents]
|
||||||
|
[:a {:href (str "/n/" slug)}
|
||||||
|
contents])
|
||||||
|
|
||||||
|
(defmethod doerg-render/org-link "id"
|
||||||
|
[{:keys [path raw-link children]}]
|
||||||
|
[:span.org-link
|
||||||
|
(slug-link (slug/from-uuid path)
|
||||||
|
(or (seq children) raw-link))
|
||||||
|
#_[:a {:href (str "/n/" (slug/from-uuid path))}
|
||||||
|
(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}]
|
||||||
|
(if-some [node (some-> slug slug/from-string roam/get-public-node)]
|
||||||
|
(let [org-file (roam/org-file node)
|
||||||
|
html-file (org-file->html-file org-file)]
|
||||||
|
(cached-file/cached-file
|
||||||
|
:file html-file
|
||||||
|
:stale? (cached-file/newer-than? org-file html-file)
|
||||||
|
:compute #(doerg-render/to-html
|
||||||
|
org-file
|
||||||
|
:postamble (backlinks-postamble node)
|
||||||
|
:header navbar
|
||||||
|
:title (roam/title node)))
|
||||||
|
(-> (str html-file)
|
||||||
|
response/file-response
|
||||||
|
(response/content-type "text/html")))
|
||||||
|
(not-found req)))
|
||||||
|
|
||||||
|
(defn node-by-id [req]
|
||||||
|
(hello req))
|
||||||
|
|
||||||
|
(def exception-middleware
|
||||||
|
(reitit-exception/create-exception-middleware
|
||||||
|
(merge
|
||||||
|
reitit-exception/default-handlers
|
||||||
|
{::reitit-exception/wrap
|
||||||
|
(fn [handler e request]
|
||||||
|
(l/error e "error in fucking somwhere dude")
|
||||||
|
(handler e request))})))
|
||||||
|
|
||||||
|
(defn handle-homepage [req]
|
||||||
|
(-> req
|
||||||
|
(assoc-in [:path-params :slug] homepage-slug)
|
||||||
|
node-by-slug))
|
||||||
|
|
||||||
|
(defn handle-resource [{:keys [uri]}]
|
||||||
|
(if-some [[_ resource] (re-matches #"^/resource/ibm-plex-web/(.*)" uri)]
|
||||||
|
(-> resource
|
||||||
|
(response/file-response
|
||||||
|
{:root (-> cfg/*cfg* ::cfg/ibm-plex-web str)}))
|
||||||
|
(-> uri
|
||||||
|
(str/replace-first #"^/resource/" "")
|
||||||
|
(response/resource-response
|
||||||
|
{:root "net/deertopia/doerg/public"
|
||||||
|
:allow-symlinks? true}))))
|
||||||
|
|
||||||
|
(defn handle-favicon [_]
|
||||||
|
(response/resource-response "net/deertopia/doerg/favicon.ico"))
|
||||||
|
|
||||||
|
(def router
|
||||||
|
(reitit.ring/router
|
||||||
|
#{["/" #'handle-homepage]
|
||||||
|
["/n/:slug" #'node-by-slug]
|
||||||
|
["/id/:id" #'node-by-id]
|
||||||
|
["/resource/*" #'handle-resource]
|
||||||
|
["/myreq" #'hello]
|
||||||
|
["/favicon.ico" #'handle-favicon]}
|
||||||
|
{:validate reitit.spec/validate
|
||||||
|
:exception reitit.dev.pretty/exception
|
||||||
|
:spec :reitit.spec/default-data
|
||||||
|
:data
|
||||||
|
{:coercion reitit.coercion.spec/coercion
|
||||||
|
:middleware [exception-middleware
|
||||||
|
reitit.ring.coercion/coerce-request-middleware
|
||||||
|
reitit.ring.coercion/coerce-response-middleware
|
||||||
|
#_reitit.ring.coercion/coerce-exceptions-middleware]}}))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Server API
|
||||||
|
|
||||||
|
(def app (reitit.ring/ring-handler router))
|
||||||
|
|
||||||
|
(defonce server (atom nil))
|
||||||
|
|
||||||
|
(defn stop! []
|
||||||
|
(when @server
|
||||||
|
(http/server-stop! @server {:timeout 100})
|
||||||
|
(reset! server nil)
|
||||||
|
(l/info "Stopped server")))
|
||||||
|
|
||||||
|
;; For some reason, the log messages from `stop!` are not flushed
|
||||||
|
;; before the JVM shuts dowm. Nevertheless, the server /does/ come to
|
||||||
|
;; a graceful halt.
|
||||||
|
(def ^:private shutdown-hook (Thread. stop!))
|
||||||
|
|
||||||
|
(defn start! []
|
||||||
|
(if @server
|
||||||
|
(throw (IllegalStateException. "Server already started"))
|
||||||
|
(do (reset! server
|
||||||
|
(http/run-server (bound-fn* #'app)
|
||||||
|
{:port (-> cfg/*cfg* ::cfg/port)
|
||||||
|
:legacy-return-value? false}))
|
||||||
|
;; For some reason, the log messages are not flushed before
|
||||||
|
;; the JVM shuts dowm. Nevertheless, the server /does/ come
|
||||||
|
;; to a graceful halt.
|
||||||
|
(try (.addShutdownHook (Runtime/getRuntime) shutdown-hook)
|
||||||
|
(catch IllegalArgumentException e
|
||||||
|
(when (not= "Hook previously registered"
|
||||||
|
(ex-message e))
|
||||||
|
(throw e))))
|
||||||
|
(l/infof "Server started on port %d"
|
||||||
|
(-> cfg/*cfg* ::cfg/port)))))
|
||||||
|
|
||||||
|
(defn status []
|
||||||
|
(if @server
|
||||||
|
(http/server-status @server)
|
||||||
|
:stopped))
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(ns net.deertopia.publisher.slug
|
(ns net.deertopia.doerg.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)
|
||||||
@@ -7,7 +7,8 @@
|
|||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[clojure.tools.logging :as l]
|
[clojure.tools.logging :as l]
|
||||||
[babashka.fs :as fs]
|
[babashka.fs :as fs]
|
||||||
[net.deertopia.doerg.config :as cfg])
|
[net.deertopia.doerg.config :as cfg]
|
||||||
|
[net.deertopia.doerg :as-alias doerg])
|
||||||
(:import (java.io ByteArrayOutputStream)))
|
(:import (java.io ByteArrayOutputStream)))
|
||||||
|
|
||||||
(def ^:private scale-divisor 66873.46948423679)
|
(def ^:private scale-divisor 66873.46948423679)
|
||||||
@@ -82,14 +83,14 @@
|
|||||||
acc))))
|
acc))))
|
||||||
|
|
||||||
(defn- invoke-latex [& {:keys [file output-dir]}]
|
(defn- invoke-latex [& {:keys [file output-dir]}]
|
||||||
(let [latex (::cfg/latex cfg/*cfg*)]
|
(let [latex (-> cfg/*cfg* ::cfg/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/dvisvgm cfg/*cfg*)]
|
(let [dvisvgm (-> cfg/*cfg* ::cfg/dvisvgm)]
|
||||||
(invoke
|
(invoke
|
||||||
{:dir output-dir}
|
{:dir output-dir}
|
||||||
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
||||||
@@ -6,7 +6,8 @@
|
|||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[clojure.tools.logging :as l]
|
[clojure.tools.logging :as l]
|
||||||
[babashka.fs :as fs])
|
[babashka.fs :as fs]
|
||||||
|
[net.deertopia.doerg :as-alias doerg])
|
||||||
(:import (java.io ByteArrayOutputStream)))
|
(:import (java.io ByteArrayOutputStream)))
|
||||||
|
|
||||||
(def ^:dynamic *worker-timeout-duration*
|
(def ^:dynamic *worker-timeout-duration*
|
||||||
@@ -16,13 +17,17 @@
|
|||||||
|
|
||||||
(def ^:dynamic *worker*)
|
(def ^:dynamic *worker*)
|
||||||
|
|
||||||
(def ^:private prelude-file
|
;; 외부의 브로그램이 JVM resource를 사용 위해서 파일 시스템에서 써야
|
||||||
(fs/create-temp-file {:prefix "doerg-prelude-"
|
;; 합니다.
|
||||||
:suffix ".tex"}))
|
(defonce ^:private prelude-file
|
||||||
|
(-> (fs/create-temp-file {:prefix "doerg-prelude-"
|
||||||
|
:suffix ".tex"})
|
||||||
|
fs/file))
|
||||||
|
|
||||||
(defn worker []
|
(defn worker []
|
||||||
(let [doerg-temml-worker (::cfg/doerg-temml-worker cfg/*cfg*)]
|
(let [doerg-temml-worker (-> cfg/*cfg* ::cfg/doerg-temml-worker)]
|
||||||
(when-not (fs/exists? prelude-file)
|
(when (or (not (fs/exists? prelude-file))
|
||||||
|
(zero? (fs/size prelude-file)))
|
||||||
(-> "net/deertopia/doerg/prelude.tex"
|
(-> "net/deertopia/doerg/prelude.tex"
|
||||||
io/resource
|
io/resource
|
||||||
io/input-stream
|
io/input-stream
|
||||||
@@ -54,7 +59,11 @@
|
|||||||
(defn command-worker [x]
|
(defn command-worker [x]
|
||||||
(cbor/encode cbor/default-codec (:in *worker*) x)
|
(cbor/encode cbor/default-codec (:in *worker*) x)
|
||||||
(.flush (:in *worker*))
|
(.flush (:in *worker*))
|
||||||
(cbor/decode cbor/default-codec (:out *worker*)))
|
(let [r (cbor/decode cbor/default-codec (:out *worker*))]
|
||||||
|
(if (string? r)
|
||||||
|
r
|
||||||
|
(throw (ex-info "bad data from temml worker"
|
||||||
|
{:data r})))))
|
||||||
|
|
||||||
(defn render-inline [s]
|
(defn render-inline [s]
|
||||||
(command-worker s))
|
(command-worker s))
|
||||||
10
test-emacs.nix
Normal file
10
test-emacs.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{ emacsPackages
|
||||||
|
, symlinkJoin
|
||||||
|
, writeScriptBin
|
||||||
|
, lib
|
||||||
|
}:
|
||||||
|
|
||||||
|
let emacs = emacsPackages.emacsWithPackages (epkgs: [ epkgs.org-roam ]);
|
||||||
|
in writeScriptBin "test-emacs" ''
|
||||||
|
exec ${lib.getExe emacs} "$@"
|
||||||
|
''
|
||||||
9
test/net/deertopia/doerg/config_test.clj
Normal file
9
test/net/deertopia/doerg/config_test.clj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
(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)))
|
||||||
8
test/net/deertopia/doerg/org-roam-db-sync.el
Executable file
8
test/net/deertopia/doerg/org-roam-db-sync.el
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/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)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 23ee464d-b13e-4649-826f-622d0edef24e
|
||||||
|
:DeertopiaVisibility: public
|
||||||
|
:END:
|
||||||
|
#+title: awesome file
|
||||||
|
|
||||||
|
wow!
|
||||||
23
test/net/deertopia/doerg/roam-test/404.org
Normal file
23
test/net/deertopia/doerg/roam-test/404.org
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
: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
|
||||||
7
test/net/deertopia/doerg/roam-test/categorytheory.org
Normal file
7
test/net/deertopia/doerg/roam-test/categorytheory.org
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
: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.
|
||||||
7
test/net/deertopia/doerg/roam-test/fake-homepage.org
Normal file
7
test/net/deertopia/doerg/roam-test/fake-homepage.org
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: ebc5ea84-77ab-4d60-9b13-ef9160b11d1f
|
||||||
|
:DeertopiaVisibility: public
|
||||||
|
:END:
|
||||||
|
#+title: deertopia.net!!!!!!!!
|
||||||
|
|
||||||
|
homeee
|
||||||
22
test/net/deertopia/doerg/roam-test/monoepi.org
Normal file
22
test/net/deertopia/doerg/roam-test/monoepi.org
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
: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
|
||||||
63
test/net/deertopia/doerg/roam_test.clj
Normal file
63
test/net/deertopia/doerg/roam_test.clj
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
(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)))))
|
||||||
52
test/net/deertopia/doerg/server_test.clj
Normal file
52
test/net/deertopia/doerg/server_test.clj
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
(ns net.deertopia.doerg.server-test
|
||||||
|
(:require [net.deertopia.doerg.server :as sut]
|
||||||
|
[reitit.ring]
|
||||||
|
[clojure.test :as t]
|
||||||
|
[net.deertopia.doerg.config :as cfg]
|
||||||
|
[net.deertopia.doerg.roam :as roam]
|
||||||
|
[babashka.fs :as fs]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[net.deertopia.doerg.roam-test :refer [test-db-fixture]]
|
||||||
|
[net.deertopia.doerg.config-test :refer [test-config-fixture]]))
|
||||||
|
|
||||||
|
(t/use-fixtures
|
||||||
|
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
||||||
|
|
||||||
|
(defn with-server [f]
|
||||||
|
(let [was-already-running? (= :running (sut/status))]
|
||||||
|
(when-not was-already-running?
|
||||||
|
(sut/start!))
|
||||||
|
(f)
|
||||||
|
(when-not was-already-running?
|
||||||
|
(sut/stop!))))
|
||||||
|
|
||||||
|
(defn get-sut [uri]
|
||||||
|
(sut/app {:request-method :get
|
||||||
|
:uri uri}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest server-is-running
|
||||||
|
;; 서버는 벌써 시작한 다음에 이 테스트 하면 잘못됩니다.
|
||||||
|
;; (assert (not= :running (sut/status)))
|
||||||
|
(with-server
|
||||||
|
(fn []
|
||||||
|
(t/is (= :running (sut/status)))
|
||||||
|
(t/is (->> (format "http://localhost:%d"
|
||||||
|
(::cfg/port cfg/*cfg*))
|
||||||
|
slurp
|
||||||
|
string?)))))
|
||||||
|
|
||||||
|
(t/deftest get-nonexistent-node
|
||||||
|
(let [slug "3Lxvxnb0QrivoU3DX-l_5w"]
|
||||||
|
(assert (nil? (roam/make-node slug)))
|
||||||
|
(t/is (= 404
|
||||||
|
(-> (str "/n/" slug)
|
||||||
|
get-sut :status)))))
|
||||||
|
|
||||||
|
(t/deftest get-homepage
|
||||||
|
(let [resp (-> (str "/n/" sut/homepage-slug)
|
||||||
|
get-sut)]
|
||||||
|
(t/is (= 200 (:status resp)))
|
||||||
|
(t/is (= (-> "/" get-sut :body)
|
||||||
|
(-> resp :body)))))
|
||||||
8
vendor/default.nix
vendored
8
vendor/default.nix
vendored
@@ -1,8 +0,0 @@
|
|||||||
{ fetchzip
|
|
||||||
, fetchurl
|
|
||||||
, callPackage
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
ibm-plex-web = callPackage ./ibm-plex-web.nix {};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user