Compare commits
12
Commits
main
..
674882c38d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
674882c38d | ||
|
|
a8477cafbf | ||
|
|
46c7c5d45c | ||
|
|
ce1fd5dce5 | ||
|
|
34f2a41ba0 | ||
|
|
0e05aa0caf | ||
|
|
0345cee606 | ||
|
|
10bfc1145d | ||
|
|
7735888f61 | ||
|
|
bc264ac185 | ||
|
|
8b77537f44 | ||
|
|
fcd37feb2a |
No files matched your search
@@ -1 +0,0 @@
|
||||
((nil . ((cider-clojure-cli-aliases . ":dev:test"))))
|
||||
@@ -9,3 +9,5 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- name: build doerg
|
||||
run: nix build -L .#doerg
|
||||
- name: build publisher
|
||||
run: nix build -L .#publisher
|
||||
@@ -9,6 +9,7 @@ result-*
|
||||
.lsp
|
||||
.nrepl
|
||||
.direnv/
|
||||
resources/vendor/*
|
||||
node_modules
|
||||
.cljs_node_repl
|
||||
build/
|
||||
|
||||
+52
-9
@@ -1,6 +1,14 @@
|
||||
{
|
||||
"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-path": "aero/aero/1.1.6/aero-1.1.6.jar",
|
||||
@@ -137,6 +145,11 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"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-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -358,9 +371,14 @@
|
||||
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
||||
},
|
||||
{
|
||||
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.pom",
|
||||
"mvn-path": "fipp/fipp/0.6.27/fipp-0.6.27.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-p+xjV7gTIRMv0HwvV+/rAhFEFVlDY9g6FDE6GU9fVTU="
|
||||
"hash": "sha256-qK1dAlan2r+90UOm6QvnZXURhA/is4MMp9tnK20RDPc="
|
||||
},
|
||||
{
|
||||
"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",
|
||||
@@ -468,14 +486,14 @@
|
||||
"hash": "sha256-1PXzUUHstr5hI/+oPIQUGogO744bynAw2Zoo5HSjTbE="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.11.216/deep-diff2-2.11.216.jar",
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-U2zJZmPIO66EtkgwwfyY41uRyu2DRmXH0ogNfluw5Rg="
|
||||
"hash": "sha256-BkOq5C/7omo09wyTTg7nkBi6GWBmlayVsPa9mrDvCyU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.11.216/deep-diff2-2.11.216.pom",
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-ok3nYS+8XCcCTPJIkqaO1SQH6v2ENwK2GZJdH0c4D20="
|
||||
"hash": "sha256-rW/85js2hSWVc36e2BcTRmkahJHc2TjGIEfvForuToY="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/kaocha/1.91.1392/kaocha-1.91.1392.jar",
|
||||
@@ -953,9 +971,14 @@
|
||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.pom",
|
||||
"mvn-path": "org/clojure/core.rrb-vector/0.2.0/core.rrb-vector-0.2.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-juK6yvw4QzWMznZRDXMyQhK7NRn61XgE7Oq9w3rFCR8="
|
||||
"hash": "sha256-ftqNXGlaxVNp3NTHN4YUMhdXuBAoG//KMMss02PRZZQ="
|
||||
},
|
||||
{
|
||||
"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",
|
||||
@@ -1037,6 +1060,11 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"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-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -1072,6 +1100,16 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"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-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -1102,6 +1140,11 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"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-repo": "https://repo1.maven.org/maven2/",
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{:deps {aero/aero #:mvn{:version "1.1.6"}
|
||||
babashka/fs #:mvn{:version "0.5.24"}
|
||||
babashka/process #:mvn{:version "0.6.25"}
|
||||
ch.qos.logback/logback-classic #:mvn{:version "1.1.3"}
|
||||
cheshire/cheshire #:mvn{:version "6.1.0"}
|
||||
com.github.seancorfield/next.jdbc #:mvn{:version "1.3.1070"}
|
||||
com.rpl/specter #:mvn{:version "1.1.6"}
|
||||
hiccup/hiccup #:mvn{:version "2.0.0-RC4"}
|
||||
http-kit/http-kit #:mvn{:version "2.8.0"}
|
||||
instaparse/instaparse #:mvn{:version "1.5.0"}
|
||||
metosin/reitit #:mvn{:version "0.10.1"}
|
||||
mvxcvi/clj-cbor #:mvn{:version "1.1.1"}
|
||||
org.clojars.pntblnk/clj-ldap #:mvn{:version "0.0.17"}
|
||||
org.clojure/clojure #:mvn{:version "1.12.0"}
|
||||
org.clojure/core.match #:mvn{:version "1.1.0"}
|
||||
org.clojure/test.check #:mvn{:version "1.1.3"}
|
||||
org.clojure/tools.logging #:mvn{:version "1.3.0"}
|
||||
org.xerial/sqlite-jdbc #:mvn{:version "3.47.1.0"}}
|
||||
:paths ["src" "resources"]
|
||||
:aliases
|
||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:extra-paths ["test"]
|
||||
:main-opts ["-m" "kaocha.runner"]}
|
||||
:dev {:extra-paths ["dev"]}}}
|
||||
@@ -1,17 +0,0 @@
|
||||
(ns user
|
||||
(:require [net.deertopia.doerg.server :as server]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[net.deertopia.doerg.cached-file :as cached-file]
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
(cfg/load-config! :profile :dev)
|
||||
|
||||
(when (not= :running (server/status))
|
||||
(server/start!))
|
||||
|
||||
(defn invalidate-html-cache! []
|
||||
(fs/delete-tree (server/html-dir))
|
||||
nil)
|
||||
|
||||
(defn toggle-html-cache! []
|
||||
(alter-var-root #'cached-file/*use-cache?* not))
|
||||
@@ -0,0 +1,6 @@
|
||||
#+title: Doerg specification
|
||||
#+author: Guppy
|
||||
|
||||
* Footnotes
|
||||
|
||||
- A bunch of metadata should be read into a node of type =doerg-data=
|
||||
@@ -4,11 +4,9 @@
|
||||
, doerg-parser
|
||||
, doerg-temml-worker
|
||||
, ibm-plex-web
|
||||
, test-emacs ? callPackage ./test-emacs.nix {}
|
||||
, fake-git
|
||||
, our-tex
|
||||
, our-tex ? callPackage ./our-tex.nix {}
|
||||
, makeWrapper
|
||||
, writeText
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -25,39 +23,23 @@ let
|
||||
plex = ibm-plex-web.override {
|
||||
families = [ "math" "serif" "sans" "sans-kr" ];
|
||||
};
|
||||
|
||||
bin-path = lib.makeBinPath [
|
||||
doerg-parser
|
||||
our-tex
|
||||
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' {
|
||||
name = "net.deertopia/doerg";
|
||||
version = "0.1.0";
|
||||
projectSrc = lib.cleanSourceWith {
|
||||
filter = path: type:
|
||||
lib.sources.cleanSourceFilter path type
|
||||
|| lib.hasSuffix ".nix" path;
|
||||
src = ./.;
|
||||
};
|
||||
lockfile = ./deps-lock.json;
|
||||
projectSrc = lib.cleanSource ./.;
|
||||
lockfile = ../deps-lock.json;
|
||||
main-ns = "net.deertopia.doerg.main";
|
||||
nativeBuildInputs = [
|
||||
plex
|
||||
makeWrapper
|
||||
];
|
||||
propagatedBuildInputs = [
|
||||
buildInputs = [
|
||||
doerg-parser
|
||||
ibm-plex-web
|
||||
doerg-temml-worker
|
||||
plex
|
||||
our-tex
|
||||
@@ -65,20 +47,15 @@ in mkCljBin' {
|
||||
nativeCheckInputs = [
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
test-emacs
|
||||
plex
|
||||
our-tex
|
||||
];
|
||||
preBuild = ''
|
||||
cp ${doerg-config} resources/net/deertopia/doerg/extra-config.edn
|
||||
'';
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
export \
|
||||
EMACS=test-emacs \
|
||||
XDG_STATE_HOME=$(mktemp -d "state-home-XXXXXX")
|
||||
clojure -M:test
|
||||
'';
|
||||
passthru = { inherit plex our-tex test-emacs doerg-config; };
|
||||
meta.mainProgram = "doerg";
|
||||
postInstall = ''
|
||||
wrapProgram $out/bin/doerg \
|
||||
--prefix PATH : ${bin-path}
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
{
|
||||
"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="
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{: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"]}}}
|
||||
File renamed without changes.
@@ -10,5 +10,4 @@ buildNpmPackage {
|
||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
dontNpmBuild = true;
|
||||
meta.mainProgram = "doerg-parser";
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -18,5 +18,4 @@ buildNpmPackage {
|
||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
dontNpmBuild = true;
|
||||
meta.mainProgram = "doerg-temml-worker";
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{: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 ["."]}
|
||||
@@ -0,0 +1,7 @@
|
||||
(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))
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,13 @@
|
||||
(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")
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -438,7 +438,7 @@ label.margin-toggle:not(.sidenote-number) {
|
||||
}
|
||||
}
|
||||
|
||||
.org-link.external::after
|
||||
.link.external::after
|
||||
{ content: "↗"
|
||||
; vertical-align: super
|
||||
; font-size: 1rem
|
||||
@@ -446,8 +446,8 @@ label.margin-toggle:not(.sidenote-number) {
|
||||
}
|
||||
|
||||
.center
|
||||
{ align-items: center
|
||||
; justify-content: center
|
||||
{ align-items: "center"
|
||||
; justify-content: "center"
|
||||
; display: flex
|
||||
; max-width: 55%
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
(ns scratch
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[spec-dict.main :refer [dict]]
|
||||
[clojure.test.check.generators :as gen]))
|
||||
|
||||
|
||||
(defmulti node-spec :type)
|
||||
|
||||
(s/def ::node
|
||||
(s/multi-spec node-spec :type))
|
||||
|
||||
(s/def ::children (s/coll-of ::node :kind vector?))
|
||||
|
||||
(s/def ::value nat-int?)
|
||||
|
||||
(defmethod node-spec :branch [_]
|
||||
(dict {:children ::children})
|
||||
#_(s/keys :req-un [::children]))
|
||||
|
||||
(defmethod node-spec :leaf [_]
|
||||
(dict {:value ::value})
|
||||
#_
|
||||
(s/keys :req-un [::value]))
|
||||
|
||||
(comment
|
||||
(binding [s/*recursion-limit* 1]
|
||||
(gen/generate (s/gen ::node))))
|
||||
File renamed without changes.
@@ -0,0 +1,42 @@
|
||||
(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)
|
||||
@@ -6,6 +6,7 @@
|
||||
[clojure.core.match :refer [match]]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.set :as set]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.string :as str]
|
||||
[clojure.test.check.generators :as gen]
|
||||
[clojure.tools.logging.readable :as lr]
|
||||
@@ -14,6 +15,7 @@
|
||||
[com.rpl.specter.zipper :as sz]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[spec-dict.main :refer [dict]]
|
||||
[clojure.tools.logging :as l])
|
||||
(:import
|
||||
(java.util UUID)))
|
||||
@@ -34,7 +36,7 @@
|
||||
:or {in *in*}}]
|
||||
(let [r (-> (p/process
|
||||
{:in in :out :string}
|
||||
(-> cfg/*cfg* ::cfg/doerg-parser str))
|
||||
(::cfg/doerg-parser cfg/*cfg*))
|
||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||
(when (zero? (:exit r))
|
||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||
@@ -62,6 +64,8 @@
|
||||
(and (map? e) (contains? e :children)))
|
||||
|
||||
(defn org-element? [element]
|
||||
#_
|
||||
(s/valid? ::org-element element)
|
||||
(and (map? element)
|
||||
(contains? element :type)))
|
||||
|
||||
@@ -94,6 +98,16 @@
|
||||
(and (of-type? element "latex-fragment")
|
||||
(-> 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
|
||||
|
||||
@@ -300,3 +314,149 @@
|
||||
(recur (conj acc c) rest)
|
||||
[] 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,6 +1,7 @@
|
||||
(ns net.deertopia.doerg.html
|
||||
"Common HTML elements and utilities"
|
||||
(:require [clojure.java.io :as io]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
#_
|
||||
@@ -27,7 +28,7 @@
|
||||
[:meta {:charset "utf-8"}])
|
||||
|
||||
(defn external-stylesheet [href]
|
||||
[:link {:rel "stylesheet" :type "text/css" :href (str "/resource/" href)}])
|
||||
[:link {:rel "stylesheet" :type "text/css" :href href}])
|
||||
|
||||
(def ibm-plex
|
||||
(concat
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns net.deertopia.doerg.main
|
||||
(:gen-class))
|
||||
|
||||
(defn -main []
|
||||
(println "hello from doerg"))
|
||||
@@ -12,8 +12,7 @@
|
||||
[net.deertopia.doerg.tex :as tex]
|
||||
[net.deertopia.doerg.tex.temml :as tex-temml]
|
||||
[clojure.zip :as z]
|
||||
[babashka.fs :as fs]
|
||||
[clojure.edn :as edn]))
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
;;; Top-level API
|
||||
|
||||
@@ -40,7 +39,7 @@
|
||||
#(do (assert (element/of-type? % "keyword"))
|
||||
(:key %)))
|
||||
|
||||
(def ^:dynamic ^:private *opts*)
|
||||
(def ^:dynamic ^:private *document-info*)
|
||||
|
||||
(declare ^:private gather-footnotes render-renderer-error
|
||||
view-children-as-seq render-tex-snippets)
|
||||
@@ -63,31 +62,23 @@
|
||||
|
||||
(defn org-document
|
||||
"Recursively render an Org-mode document to Hiccup."
|
||||
[doc & {:as opts :keys [postamble header title]}]
|
||||
(binding [*opts* opts]
|
||||
(tex-temml/binding-worker
|
||||
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
||||
org-element-recursive)]
|
||||
[:html
|
||||
[:head
|
||||
(when title
|
||||
[:title title])
|
||||
doerg-html/head]
|
||||
[:body {:lang default-language}
|
||||
(when header
|
||||
[:header header])
|
||||
[:article
|
||||
rendered
|
||||
(when postamble
|
||||
[:footer
|
||||
[:hr]
|
||||
postamble])]]]))))
|
||||
[doc]
|
||||
(tex-temml/binding-worker
|
||||
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
||||
org-element-recursive)]
|
||||
[:html
|
||||
[:head
|
||||
[:title "org document"]
|
||||
doerg-html/head]
|
||||
[:body {:lang default-language}
|
||||
[:article
|
||||
rendered]]])))
|
||||
|
||||
(defn to-html
|
||||
"Read `f` with `slurp` as an Org document and return a string of
|
||||
rendered HTML. See `org-document` for opts."
|
||||
[f & {:as opts}]
|
||||
(str (hiccup/html {} (-> f slurp element/read-string (org-document opts)))))
|
||||
rendered HTML."
|
||||
[f]
|
||||
(str (hiccup/html {} (-> f slurp element/read-string org-document))))
|
||||
|
||||
|
||||
;;; Further dispatching on `org-element`
|
||||
@@ -111,19 +102,6 @@
|
||||
(sp/view #(update % :children seq))
|
||||
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]
|
||||
(some #(element/of-type? % "footnote-reference")
|
||||
(:children node)))
|
||||
@@ -201,7 +179,7 @@
|
||||
|
||||
|
||||
|
||||
(defn render-pprint
|
||||
(defn- render-pprint
|
||||
"Render the argument inline as `clojure.pprint/pprint` output."
|
||||
[x & {:keys [text]
|
||||
:or {text "debug!"}}]
|
||||
@@ -276,14 +254,11 @@
|
||||
(defmethod org-element "bold" [{:keys [children]}]
|
||||
[:b children])
|
||||
|
||||
(defmethod org-element "strike-through" [{:keys [children]}]
|
||||
[:s children])
|
||||
|
||||
(defmethod org-element "subscript" [{:keys [children]}]
|
||||
[:sub children])
|
||||
|
||||
(defmethod org-element "superscript" [{:keys [children]}]
|
||||
[:sup children])
|
||||
[:super children])
|
||||
|
||||
(defmethod org-element "italic" [{:keys [children]}]
|
||||
[:em children])
|
||||
@@ -354,52 +329,23 @@
|
||||
[:span.latex-fragment.display-math
|
||||
(-> e ::rendered deref)])
|
||||
|
||||
(defmethod org-element "example-block" [{:keys [value] :as e}]
|
||||
(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 "example-block" [{:keys [value]}]
|
||||
[:pre value])
|
||||
|
||||
(defmethod org-element "src-block" [{:keys [value]}]
|
||||
[:pre [:code value]])
|
||||
|
||||
(defn- split-quote-block-children [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 "quote-block" [{:keys [children]}]
|
||||
[:blockquote children])
|
||||
|
||||
(defmethod org-element "comment" [_] nil)
|
||||
|
||||
(defmethod org-keyword "TITLE" [{:keys [value]}]
|
||||
[:h1 value])
|
||||
|
||||
(defmethod org-keyword "SUBTITLE" [{:keys [value]}]
|
||||
[:p.subtitle value])
|
||||
|
||||
(defmethod org-keyword "LATEX_COMPILER" [_] 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.
|
||||
(defmethod org-keyword "AUTHOR" [_] nil)
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
[clojure.java.io :as io]
|
||||
[hiccup2.core :as h]
|
||||
[clojure.pprint]
|
||||
[babashka.fs :as fs]
|
||||
[net.deertopia.doerg :as-alias doerg]))
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
(def some-org-file
|
||||
#_
|
||||
@@ -28,20 +27,27 @@
|
||||
(fs/delete-if-exists path)
|
||||
(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]
|
||||
:or {src some-org-file
|
||||
dest "/tmp/doerg-test"}}]
|
||||
(let [resource-dir (fs/file dest "resource")]
|
||||
(fs/create-dirs dest)
|
||||
(fs/create-dirs resource-dir)
|
||||
(force-create-sym-link (fs/file resource-dir "ibm-plex-web")
|
||||
(-> cfg/*cfg* ::cfg/ibm-plex-web))
|
||||
(doseq [x #{"Temml-Plex.css" "tuftesque.css" "deerstar.css"}]
|
||||
(force-create-sym-link
|
||||
(fs/file resource-dir x)
|
||||
(io/resource (str "net/deertopia/doerg/" x))))
|
||||
(fs/delete-if-exists (fs/file dest "index.html"))
|
||||
(->> src render/to-html str (spit (fs/file dest "index.html")))))
|
||||
(fs/create-dirs dest)
|
||||
(force-create-sym-link (fs/file dest "ibm-plex-web")
|
||||
(-> cfg/*cfg* ::cfg/ibm-plex-web))
|
||||
(force-create-sym-link (fs/file dest "deerstar.css")
|
||||
(io/resource "net/deertopia/doerg/deerstar.css"))
|
||||
(force-create-sym-link (fs/file dest "tuftesque.css")
|
||||
(io/resource "net/deertopia/doerg/tuftesque.css"))
|
||||
(force-create-sym-link (fs/file dest "Temml-Plex.css")
|
||||
(io/resource "net/deertopia/doerg/Temml-Plex.css"))
|
||||
(fs/delete-if-exists (fs/file dest "index.html"))
|
||||
(->> src render/to-html str (spit (fs/file dest "index.html"))))
|
||||
|
||||
(defn render-edn [& {:keys [src dest]
|
||||
:or {src some-org-file
|
||||
File renamed without changes.
+3
-4
@@ -7,8 +7,7 @@
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[babashka.fs :as fs]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[net.deertopia.doerg :as-alias doerg])
|
||||
[net.deertopia.doerg.config :as cfg])
|
||||
(:import (java.io ByteArrayOutputStream)))
|
||||
|
||||
(def ^:private scale-divisor 66873.46948423679)
|
||||
@@ -83,14 +82,14 @@
|
||||
acc))))
|
||||
|
||||
(defn- invoke-latex [& {:keys [file output-dir]}]
|
||||
(let [latex (-> cfg/*cfg* ::cfg/latex)]
|
||||
(let [latex (::cfg/latex cfg/*cfg*)]
|
||||
(invoke
|
||||
{:dir output-dir}
|
||||
latex "-no-pdf" "-interaction" "nonstopmode"
|
||||
"-output-directory" output-dir file)))
|
||||
|
||||
(defn- invoke-dvisvgm [& {:keys [file output-dir]}]
|
||||
(let [dvisvgm (-> cfg/*cfg* ::cfg/dvisvgm)]
|
||||
(let [dvisvgm (::cfg/dvisvgm cfg/*cfg*)]
|
||||
(invoke
|
||||
{:dir output-dir}
|
||||
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
||||
+7
-16
@@ -6,8 +6,7 @@
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[babashka.fs :as fs]
|
||||
[net.deertopia.doerg :as-alias doerg])
|
||||
[babashka.fs :as fs])
|
||||
(:import (java.io ByteArrayOutputStream)))
|
||||
|
||||
(def ^:dynamic *worker-timeout-duration*
|
||||
@@ -17,17 +16,13 @@
|
||||
|
||||
(def ^:dynamic *worker*)
|
||||
|
||||
;; 외부의 브로그램이 JVM resource를 사용 위해서 파일 시스템에서 써야
|
||||
;; 합니다.
|
||||
(defonce ^:private prelude-file
|
||||
(-> (fs/create-temp-file {:prefix "doerg-prelude-"
|
||||
:suffix ".tex"})
|
||||
fs/file))
|
||||
(def ^:private prelude-file
|
||||
(fs/create-temp-file {:prefix "doerg-prelude-"
|
||||
:suffix ".tex"}))
|
||||
|
||||
(defn worker []
|
||||
(let [doerg-temml-worker (-> cfg/*cfg* ::cfg/doerg-temml-worker)]
|
||||
(when (or (not (fs/exists? prelude-file))
|
||||
(zero? (fs/size prelude-file)))
|
||||
(let [doerg-temml-worker (::cfg/doerg-temml-worker cfg/*cfg*)]
|
||||
(when-not (fs/exists? prelude-file)
|
||||
(-> "net/deertopia/doerg/prelude.tex"
|
||||
io/resource
|
||||
io/input-stream
|
||||
@@ -59,11 +54,7 @@
|
||||
(defn command-worker [x]
|
||||
(cbor/encode cbor/default-codec (:in *worker*) x)
|
||||
(.flush (:in *worker*))
|
||||
(let [r (cbor/decode cbor/default-codec (:out *worker*))]
|
||||
(if (string? r)
|
||||
r
|
||||
(throw (ex-info "bad data from temml worker"
|
||||
{:data r})))))
|
||||
(cbor/decode cbor/default-codec (:out *worker*)))
|
||||
|
||||
(defn render-inline [s]
|
||||
(command-worker s))
|
||||
File renamed without changes.
@@ -0,0 +1,8 @@
|
||||
(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))))
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Generated
+37
-3
@@ -59,6 +59,24 @@
|
||||
"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": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
@@ -111,11 +129,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||
"lastModified": 1760038930,
|
||||
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -144,6 +162,7 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"clj-nix": "clj-nix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"sydpkgs": "sydpkgs"
|
||||
}
|
||||
@@ -165,6 +184,21 @@
|
||||
"repo": "sydpkgs",
|
||||
"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",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
clj-nix.url = "github:jlesquembre/clj-nix";
|
||||
sydpkgs.url = "github:msyds/sydpkgs";
|
||||
};
|
||||
@@ -14,19 +15,16 @@
|
||||
"x86_64-linux"
|
||||
];
|
||||
|
||||
overlays = [
|
||||
inputs.sydpkgs.overlays.default
|
||||
clj-nix.overlays.default
|
||||
];
|
||||
|
||||
each-system = f: nixpkgs.lib.genAttrs supportedSystems (system: f rec {
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = overlays ++ [
|
||||
self.overlays.default
|
||||
];
|
||||
};
|
||||
inherit (pkgs) lib;
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
inputs.sydpkgs.overlays.default
|
||||
clj-nix.overlays.default
|
||||
self.overlays.default
|
||||
];
|
||||
};
|
||||
inherit (pkgs) lib;
|
||||
inherit system;
|
||||
});
|
||||
in {
|
||||
@@ -34,51 +32,45 @@
|
||||
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
||||
|
||||
packages = each-system ({ pkgs, ... }: {
|
||||
inherit (pkgs) doerg doerg-parser doerg-temml-worker;
|
||||
default = pkgs.doerg;
|
||||
inherit (pkgs) publisher doerg doerg-parser doerg-temml-worker;
|
||||
default = pkgs.publisher;
|
||||
});
|
||||
|
||||
overlays.default = final: prev:
|
||||
let
|
||||
# is this really the correct way to satisfy our
|
||||
# dependencies? lmfao
|
||||
final' = final.appendOverlays overlays;
|
||||
graal = x: final'.mkGraalBin { cljDrv = x; };
|
||||
in {
|
||||
ibm-plex-web = final'.callPackage ./ibm-plex-web.nix {};
|
||||
doerg = final'.callPackage ./. {};
|
||||
doerg-parser = final'.callPackage ./doerg-parser {};
|
||||
doerg-temml-worker = final'.callPackage ./doerg-temml-worker {};
|
||||
our-tex = final'.callPackage ./our-tex.nix {};
|
||||
};
|
||||
let graal = x: final.mkGraalBin { cljDrv = x; };
|
||||
vendored = final.callPackage ./vendor {};
|
||||
in {
|
||||
inherit (vendored) ibm-plex-web;
|
||||
publisher = final.callPackage ./publisher {};
|
||||
doerg = final.callPackage ./doerg {};
|
||||
doerg-parser = final.callPackage ./doerg/doerg-parser {};
|
||||
doerg-temml-worker = final.callPackage ./doerg/doerg-temml-worker {};
|
||||
};
|
||||
|
||||
checks = each-system ({ pkgs, system, ... }: {
|
||||
build-all =
|
||||
pkgs.linkFarmFromDrvs
|
||||
"all"
|
||||
(pkgs.lib.attrValues self.packages.${system});
|
||||
build-all =
|
||||
pkgs.linkFarmFromDrvs
|
||||
"all"
|
||||
(pkgs.lib.attrValues self.packages.${system});
|
||||
});
|
||||
|
||||
nixosModules.default = import ./module.nix { inherit self; };
|
||||
|
||||
devShells = each-system ({ pkgs, system, ... }: {
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [
|
||||
pkgs.doerg
|
||||
pkgs.doerg-parser
|
||||
pkgs.doerg-temml-worker
|
||||
];
|
||||
packages = with pkgs; [
|
||||
clojure-lsp
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
zprint
|
||||
clojure
|
||||
babashka
|
||||
sqlite-web
|
||||
pkgs.doerg.test-emacs
|
||||
];
|
||||
};
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [
|
||||
pkgs.doerg
|
||||
pkgs.doerg-parser
|
||||
pkgs.doerg-temml-worker
|
||||
];
|
||||
packages = with pkgs; [
|
||||
clojure-lsp
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
zprint
|
||||
clojure
|
||||
babashka
|
||||
sqlite-web
|
||||
];
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
{ self, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.doerg;
|
||||
doerg-config = pkgs.writeText "doerg-config.edn" ''
|
||||
#:net.deertopia.doerg.config
|
||||
{:org-roam-db-path "${cfg.databasePath}"
|
||||
:state-directory "${cfg.stateDir}"
|
||||
:port ${builtins.toString cfg.port}}
|
||||
'';
|
||||
|
||||
inherit (lib) types;
|
||||
|
||||
org-roam-db-sync = pkgs.writeText "org-roam-db-sync.el" ''
|
||||
#!/usr/bin/env -S emacs -Q -x
|
||||
|
||||
(require 'org-roam)
|
||||
|
||||
(setq org-roam-directory (expand-file-name (car command-line-args-left)))
|
||||
(setq org-roam-db-location (expand-file-name (cadr command-line-args-left)))
|
||||
|
||||
(org-roam-db-sync)
|
||||
'';
|
||||
in {
|
||||
options.services.doerg = {
|
||||
enable = lib.mkEnableOption "Doerg";
|
||||
org-roam-db-sync.enable = lib.mkEnableOption "Org-roam db sync";
|
||||
port = lib.mkOption {
|
||||
default = 21984;
|
||||
type = lib.types.port;
|
||||
description = ''
|
||||
The port on which Doerg will listen.
|
||||
'';
|
||||
};
|
||||
stateDir = lib.mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/private/doerg";
|
||||
description = "Daemon's state directory.";
|
||||
};
|
||||
orgDir = lib.mkOption {
|
||||
type = types.path;
|
||||
description = "Org roam directory.";
|
||||
};
|
||||
package = lib.mkPackageOption pkgs "doerg" {};
|
||||
databasePath = lib.mkOption {
|
||||
type = types.path;
|
||||
description = "Org roam database path";
|
||||
default = cfg.orgDir + "org-roam.db";
|
||||
};
|
||||
openFirewall = lib.mkOption {
|
||||
type = types.bool;
|
||||
description = "Open doerg ports?";
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nixpkgs.overlays = [ self.overlays.default ];
|
||||
|
||||
systemd.services.org-roam-db-sync = lib.mkIf cfg.org-roam-db-sync.enable {
|
||||
script = lib.escapeShellArgs [
|
||||
(lib.getExe cfg.package.test-emacs)
|
||||
"-Q" "-x" org-roam-db-sync cfg.orgDir cfg.databasePath
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ReadOnlyBindPaths = [
|
||||
cfg.orgDir
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.org-roam-db-sync = lib.mkIf cfg.org-roam-db-sync.enable {
|
||||
unitConfig.StopWhenUnneeded = true;
|
||||
timerConfig = {
|
||||
OnActiveSec = "1h";
|
||||
RandomizedDelaySec = "30m";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
|
||||
cfg.port
|
||||
];
|
||||
|
||||
systemd.services.doerg = {
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" "org-roam-db-sync.timer" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.DOERG_CONFIG = doerg-config;
|
||||
serviceConfig = {
|
||||
# WorkingDirectory = cfg.stateDir;
|
||||
StateDirectory = "doerg";
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
DynamicUser = true;
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
BindReadOnlyPaths = [
|
||||
cfg.orgDir
|
||||
# cfg.databasePath
|
||||
"/nix"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
((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))))))
|
||||
@@ -0,0 +1,21 @@
|
||||
{ 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"}'
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{: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"]}
|
||||
@@ -0,0 +1,53 @@
|
||||
;;; -*- 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"}}))
|
||||
|
||||
File renamed without changes.
+2
-5
@@ -1,4 +1,4 @@
|
||||
(ns net.deertopia.doerg.cached-file
|
||||
(ns net.deertopia.publisher.cached-file
|
||||
(:require [babashka.fs :as fs]))
|
||||
|
||||
(defn newer-than?
|
||||
@@ -18,10 +18,7 @@
|
||||
calling `compute` with no arguments only if stale? is logical true."
|
||||
[& {:keys [file stale? compute]}]
|
||||
(when (or (not *use-cache?*) stale?)
|
||||
(let [r (compute)
|
||||
dir (fs/parent file)]
|
||||
(let [r (compute)]
|
||||
(assert (string? r))
|
||||
(when-not (fs/exists? dir)
|
||||
(fs/create-dirs dir))
|
||||
(spit file r)))
|
||||
file)
|
||||
@@ -0,0 +1,17 @@
|
||||
(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,12 +1,12 @@
|
||||
(ns net.deertopia.doerg.elisp
|
||||
(:require [clojure.core.match :refer [match]]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.spec.alpha :as s]
|
||||
[instaparse.core :as ip])
|
||||
(:refer-clojure :exclude [print read read-string]))
|
||||
(ns net.deertopia.publisher.elisp
|
||||
(:require
|
||||
[clojure.core.match :refer [match]]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.spec.alpha :as s]
|
||||
[instaparse.core :as ip]))
|
||||
|
||||
(ip/defparser read*
|
||||
(io/resource "net/deertopia/doerg/elisp/grammar"))
|
||||
(io/resource "net/deertopia/publisher/elisp/grammar"))
|
||||
|
||||
(defn- transform-string [s]
|
||||
(let [s* (loop [s (seq s)
|
||||
@@ -106,9 +106,9 @@
|
||||
|
||||
(defn print [x]
|
||||
;; TODO: this is really not how it should be done lol. at the
|
||||
;; moment, `print` is only used in `net.deertopia.doerg.roam`
|
||||
;; moment, `print` is only used in `net.deertopia.publisher.roam`
|
||||
;; and only to serialise uuids, so it's not a /massive/ priority.
|
||||
(cond (or (string? x) (uuid? x)) (str \" x \")
|
||||
(cond (string? x) (str \" x \")
|
||||
:else (throw (ex-info "`print` is unimplemented lol"
|
||||
{:x x}))))
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
(ns net.deertopia.publisher.main
|
||||
(:require [net.deertopia.doerg.main :as doerg]
|
||||
[net.deertopia.publisher.server :as server])
|
||||
(:gen-class))
|
||||
|
||||
(defn -main []
|
||||
(server/start!))
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns net.deertopia.doerg.roam
|
||||
(ns net.deertopia.publisher.roam
|
||||
(:require [babashka.fs :as fs]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[net.deertopia.doerg.elisp :as elisp]
|
||||
[net.deertopia.doerg.slug :as slug]
|
||||
[net.deertopia.publisher.config :as cfg]
|
||||
[net.deertopia.publisher.elisp :as elisp]
|
||||
[net.deertopia.publisher.slug :as slug]
|
||||
[next.jdbc :as sql])
|
||||
(:import (java.util UUID)))
|
||||
|
||||
@@ -11,10 +11,13 @@
|
||||
|
||||
(defonce ^:dynamic *use-db-cache?* true)
|
||||
|
||||
(defn ds []
|
||||
(sql/get-datasource
|
||||
{:dbtype "sqlite"
|
||||
:dbname (-> cfg/*cfg* ::cfg/org-roam-db-path str)}))
|
||||
(def db-path (-> cfg/*cfg* ::cfg/org-roam-db-path
|
||||
fs/expand-home str))
|
||||
|
||||
(def db {:dbtype "sqlite"
|
||||
:dbname db-path})
|
||||
|
||||
(def ds (sql/get-datasource db))
|
||||
|
||||
|
||||
;;; Elisp sexp (de)serialisation
|
||||
@@ -26,23 +29,15 @@
|
||||
(-> node :id slug/from-uuid))
|
||||
|
||||
(defn- print-id [node]
|
||||
(-> node id elisp/print))
|
||||
(-> node id print))
|
||||
|
||||
|
||||
;;; Node
|
||||
|
||||
(defrecord Node [id cache])
|
||||
|
||||
(defn uuid-exists? [uuid]
|
||||
(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 make-node [uuid]
|
||||
(->Node uuid (atom {})))
|
||||
|
||||
(defn- fetch-with-cache [node field fetch]
|
||||
(if *use-db-cache?*
|
||||
@@ -57,20 +52,11 @@
|
||||
node :org-file
|
||||
(fn [node]
|
||||
(when-some [r (sql/execute-one!
|
||||
(ds)
|
||||
ds
|
||||
["select file from nodes where id = ?"
|
||||
(-> node :id str elisp/print)])]
|
||||
(-> 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
|
||||
(get-node [this]
|
||||
"Return the node associated with `this` or nil."))
|
||||
@@ -85,7 +71,7 @@
|
||||
java.util.UUID
|
||||
(get-node [this]
|
||||
(make-node this))
|
||||
net.deertopia.doerg.slug.Slug
|
||||
net.deertopia.publisher.slug.Slug
|
||||
(get-node [this]
|
||||
(-> this slug/to-uuid make-node))
|
||||
Node
|
||||
@@ -97,7 +83,7 @@
|
||||
(fetch-with-cache
|
||||
node :title
|
||||
#(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 %))]))))
|
||||
|
||||
|
||||
@@ -107,7 +93,7 @@
|
||||
(fetch-with-cache
|
||||
node :level
|
||||
#(-> (sql/execute-one!
|
||||
(ds) ["select level from nodes where id = ?"
|
||||
ds ["select level from nodes where id = ?"
|
||||
(print-id %)])
|
||||
:nodes/level)))
|
||||
|
||||
@@ -118,7 +104,7 @@
|
||||
(fetch-with-cache
|
||||
node :file
|
||||
#(-> (sql/execute-one!
|
||||
(ds) ["select file from nodes where id = ?"
|
||||
ds ["select file from nodes where id = ?"
|
||||
(print-id %)])
|
||||
:nodes/file
|
||||
elisp/read-string)))
|
||||
@@ -127,35 +113,31 @@
|
||||
(fetch-with-cache
|
||||
node :properties
|
||||
#(-> (sql/execute-one!
|
||||
(ds) ["select properties from nodes where id = ?"
|
||||
ds ["select properties from nodes where id = ?"
|
||||
(print-id %)])
|
||||
:nodes/properties
|
||||
elisp/read-alist)))
|
||||
|
||||
(defn public? [node]
|
||||
(some-> (properties node) (get "DEERTOPIAVISIBILITY") (= "public")))
|
||||
|
||||
(defn get-public-node [node]
|
||||
(when-let [n (get-node node)]
|
||||
(when (public? n) n)))
|
||||
(-> node properties (get "DEERTOPIAVISIBILITY") (= "public")))
|
||||
|
||||
(defn graph-visible? [node]
|
||||
(#{"public" "graphonly"}
|
||||
(some-> (properties node) (get "DEERTOPIAVISIBILITY"))))
|
||||
(-> node properties (get "DEERTOPIAVISIBILITY"))))
|
||||
|
||||
(defn backlinks
|
||||
"Returns a collection of nodes linking to `node`."
|
||||
"Returns a collection of maps {:id …, :title …}."
|
||||
[node]
|
||||
(for [{id :nodes/id title :nodes/title}
|
||||
(sql/execute! (ds) ["select distinct nodes.id, nodes.title from links
|
||||
inner join nodes
|
||||
on nodes.id = links.source
|
||||
where links.dest = ?"
|
||||
(elisp/print (str (:id node)))])
|
||||
:let [id' (elisp/read-string id)]
|
||||
:when (some-> (-> id' parse-uuid get-node)
|
||||
public?)]
|
||||
(make-node id' {:title (elisp/read-string title)})))
|
||||
(for [{id :nodes/id, title :nodes/title}
|
||||
(sql/execute! ds ["select distinct nodes.id, nodes.title from links
|
||||
inner join nodes
|
||||
on nodes.id = links.source
|
||||
where links.dest = ?"
|
||||
(elisp/print (:id node))])
|
||||
:let [id (elisp/read-string id)]
|
||||
:when (graph-visible? (get-node (UUID/fromString id)))]
|
||||
{:id id
|
||||
:title (elisp/read-string title)}))
|
||||
|
||||
|
||||
;;; Graph support
|
||||
@@ -167,9 +149,9 @@
|
||||
(-> uuid parse-uuid get-node graph-visible?))
|
||||
|
||||
(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!
|
||||
(ds)
|
||||
ds
|
||||
["select n1.id as source, nodes.id as target from
|
||||
((nodes as n1) join links on n1.id = links.source)
|
||||
join (nodes as n2) on links.dest = nodes.id
|
||||
@@ -0,0 +1,112 @@
|
||||
(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,4 +1,4 @@
|
||||
(ns net.deertopia.doerg.slug
|
||||
(ns net.deertopia.publisher.slug
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[spec-tools.core :as st])
|
||||
(:import (java.nio ByteBuffer)
|
||||
@@ -0,0 +1,25 @@
|
||||
{ fetchzip
|
||||
, fetchurl
|
||||
}:
|
||||
|
||||
{
|
||||
ibm-plex-serif = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-serif%401.1.0/ibm-plex-serif.zip";
|
||||
hash = "sha256-8ygaAeMKygYS4GCub4YUQmkh87pYHfi3s0PQ6AbaeGw=";
|
||||
};
|
||||
|
||||
ibm-plex-math = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-math%401.1.0/ibm-plex-math.zip";
|
||||
hash = "sha256-dJA6uqxa/yb3eLY4l39NeP0yIl2NfrbaRpf6h0/F7Xc=";
|
||||
};
|
||||
|
||||
ibm-plex-sans-kr = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-sans-kr%401.1.0/ibm-plex-sans-kr.zip";
|
||||
hash = "sha256-FsHxMvLlI4yylgG96DOZIdW2DYpk7I+c5QgkVIkNZIE=";
|
||||
};
|
||||
|
||||
"d3.v7.min.js" = fetchurl {
|
||||
url = "https://d3js.org/d3.v7.min.js";
|
||||
hash = "sha256-8glLv2FBs1lyLE/kVOtsSw8OQswQzHr5IfwVj864ZTk=";
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#:net.deertopia.doerg.config
|
||||
{:ibm-plex-web #or [#env IBM_PLEX_WEB
|
||||
#xdg-data-dir "ibm-plex-web"]
|
||||
:latex "xelatex"
|
||||
:dvisvgm "dvisvgm"
|
||||
:doerg-temml-worker
|
||||
#profile {:dev #file "../../../../doerg-temml-worker/index.js"
|
||||
:default "doerg-temml-worker"}
|
||||
:doerg-parser
|
||||
#profile {:dev #file "../../../../doerg-parser/index.js"
|
||||
:default "doerg-parser"}
|
||||
:state-directory #join [#or [#env XDG_STATE_HOME
|
||||
#envf ["%s/.local/share" HOME]]
|
||||
"/doerg-server"]
|
||||
:org-roam-db-path
|
||||
#profile {:default #join [#env HOME "/.cache/emacs/org-roam.db"]
|
||||
:test #join [#or [#env TMP "/tmp"] "/doerg-org-roam-test.db"]}
|
||||
:port #profile {:default 8080}}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB |
@@ -1 +0,0 @@
|
||||
../Temml-Plex.css
|
||||
@@ -1 +0,0 @@
|
||||
../deerstar.css
|
||||
@@ -1 +0,0 @@
|
||||
../tuftesque.css
|
||||
@@ -1,87 +0,0 @@
|
||||
(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))))))
|
||||
@@ -1,8 +0,0 @@
|
||||
(ns net.deertopia.doerg.main
|
||||
(:require [net.deertopia.doerg.server :as server]
|
||||
[net.deertopia.doerg.config :as cfg])
|
||||
(:gen-class))
|
||||
|
||||
(defn -main [& _]
|
||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources)]
|
||||
(server/start!)))
|
||||
@@ -1,210 +0,0 @@
|
||||
(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,10 +0,0 @@
|
||||
{ emacsPackages
|
||||
, symlinkJoin
|
||||
, writeScriptBin
|
||||
, lib
|
||||
}:
|
||||
|
||||
let emacs = emacsPackages.emacsWithPackages (epkgs: [ epkgs.org-roam ]);
|
||||
in writeScriptBin "test-emacs" ''
|
||||
exec ${lib.getExe emacs} "$@"
|
||||
''
|
||||
@@ -1,9 +0,0 @@
|
||||
(ns net.deertopia.doerg.config-test
|
||||
(:require [clojure.test :as t]
|
||||
[net.deertopia.doerg.config :as cfg]))
|
||||
|
||||
(defn test-config-fixture
|
||||
"`clojure.test` fixture to run tests with the :test configuration."
|
||||
[f]
|
||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources :profile :test)]
|
||||
(f)))
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env -S emacs -Q -x
|
||||
|
||||
(require 'org-roam)
|
||||
|
||||
(setq org-roam-directory (expand-file-name (car command-line-args-left)))
|
||||
(setq org-roam-db-location (expand-file-name (cadr command-line-args-left)))
|
||||
|
||||
(org-roam-db-sync)
|
||||
@@ -1,7 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 23ee464d-b13e-4649-826f-622d0edef24e
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: awesome file
|
||||
|
||||
wow!
|
||||
@@ -1,23 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 3c60c74e-f533-43ad-89b3-563975bf80f2
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: page not found
|
||||
|
||||
the page you're looking for doesn't exist, or you lack the permissions necessary to view it........
|
||||
|
||||
#+attr_doerg: :center? true :alt "A doe sitting and sobbing" :scale 1.4
|
||||
#+begin_example
|
||||
\{ / \ }/
|
||||
\/ . . \/
|
||||
.. \Y` `Y/ ..
|
||||
\ `\|~==~|/' /
|
||||
'". T T ."`
|
||||
{`^' }
|
||||
| |
|
||||
/</3 \
|
||||
|| ||
|
||||
_| || |_
|
||||
.,_) ) || ( (_,.
|
||||
|__ /_||_\ __|
|
||||
#+end_example
|
||||
@@ -1,7 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 90f23e03-f746-42cb-862f-1af2d4bde3cc
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: Category theory
|
||||
|
||||
*Category theory* is the mathematical study of categories and functors between them.
|
||||
@@ -1,7 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: ebc5ea84-77ab-4d60-9b13-ef9160b11d1f
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: deertopia.net!!!!!!!!
|
||||
|
||||
homeee
|
||||
@@ -1,22 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 897bfc9d-94ce-4c58-8d21-93f13372b17b
|
||||
:END:
|
||||
#+title: Monomorphisms and epimorphisms
|
||||
|
||||
In [[id:90f23e03-f746-42cb-862f-1af2d4bde3cc][category theory]], *monomorphisms* and *epimorphisms* are types of cancellative morphisms generalising injective and surjective functions, respectively.[fn:1]
|
||||
|
||||
\begin{tikzcd}
|
||||
% https://q.uiver.app/#q=WzAsNixbMCwwLCJYIl0sWzEsMCwiWSJdLFsyLDAsIloiXSxbMSwxLCJZIl0sWzIsMSwiWiJdLFswLDEsIlgiXSxbMCwxLCJnXzEiLDAseyJvZmZzZXQiOi0yfV0sWzAsMSwiZ18yIiwyLHsib2Zmc2V0IjoyfV0sWzEsMiwiZiIsMl0sWzMsNCwiZ18xIiwwLHsib2Zmc2V0IjotMn1dLFszLDQsImdfMiIsMix7Im9mZnNldCI6Mn1dLFs1LDMsImYiLDJdXQ==
|
||||
X & Y & Z \\
|
||||
X & Y & Z
|
||||
\arrow["{g_1}", shift left=2, from=1-1, to=1-2]
|
||||
\arrow["{g_2}"', shift right=2, from=1-1, to=1-2]
|
||||
\arrow["f"', from=1-2, to=1-3]
|
||||
\arrow["f"', from=2-1, to=2-2]
|
||||
\arrow["{g_1}", shift left=2, from=2-2, to=2-3]
|
||||
\arrow["{g_2}"', shift right=2, from=2-2, to=2-3]
|
||||
\end{tikzcd}
|
||||
|
||||
* Footnotes
|
||||
|
||||
[fn:1] blahahahahah blah blah
|
||||
@@ -1,63 +0,0 @@
|
||||
(ns net.deertopia.doerg.roam-test
|
||||
(:require [net.deertopia.doerg.roam :as sut]
|
||||
[clojure.test :as t]
|
||||
[clojure.java.io :as io]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[babashka.fs :as fs]
|
||||
[babashka.process :as p]
|
||||
[net.deertopia.doerg.config-test :refer [test-config-fixture]]
|
||||
[next.jdbc :as sql]
|
||||
[clojure.string :as str]
|
||||
[net.deertopia.doerg.elisp :as elisp]
|
||||
[com.rpl.specter :as sp]))
|
||||
|
||||
(def org-roam-directory
|
||||
(fs/file "test/net/deertopia/doerg/roam-test"))
|
||||
|
||||
(defn org-roam-db-sync [db-file]
|
||||
(let [script-file (fs/create-temp-file {:prefix "org-roam-db-sync-"
|
||||
:suffix ".el"})
|
||||
emacs (->> [(System/getenv "EMACS") "test-emacs" "emacs"]
|
||||
(some #(some-> % fs/which)))]
|
||||
(io/copy (-> "net/deertopia/doerg/org-roam-db-sync.el"
|
||||
io/resource io/reader)
|
||||
(fs/file script-file))
|
||||
(p/shell {:out :string :err :string}
|
||||
emacs "-Q" "-x" script-file org-roam-directory db-file)
|
||||
(fs/delete script-file)))
|
||||
|
||||
(defn test-db-fixture [f]
|
||||
(let [db-file (-> cfg/*cfg* ::cfg/org-roam-db-path)]
|
||||
(assert (->> db-file fs/canonicalize str
|
||||
(re-matches #"^/(build|tmp)/.*"))
|
||||
(format "i'm scared to delete a non-test database... %s"
|
||||
(str db-file)))
|
||||
(fs/delete-if-exists db-file)
|
||||
(org-roam-db-sync db-file)
|
||||
(f)
|
||||
(fs/delete db-file)))
|
||||
|
||||
(t/use-fixtures
|
||||
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
||||
|
||||
|
||||
|
||||
(t/deftest all-nodes-exist
|
||||
(let [known-node-files (->> (fs/list-dir org-roam-directory)
|
||||
(map (comp str fs/canonicalize))
|
||||
(into #{}))
|
||||
database-nodes
|
||||
(->> (sql/execute!
|
||||
(sut/ds) ["select file, id from nodes"])
|
||||
(map (fn [x]
|
||||
{:file (-> x :nodes/file elisp/read-string)
|
||||
:id (-> x :nodes/id elisp/read-string parse-uuid)}))
|
||||
(into #{}))]
|
||||
(t/testing "database has a node for each file?"
|
||||
(t/is (= known-node-files (sp/transform
|
||||
[sp/ALL]
|
||||
#(:file %)
|
||||
database-nodes))))
|
||||
(t/testing "each uuid exists?"
|
||||
(t/is (every? (comp sut/uuid-exists? :id)
|
||||
database-nodes)))))
|
||||
@@ -1,52 +0,0 @@
|
||||
(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)))))
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{ fetchzip
|
||||
, fetchurl
|
||||
, callPackage
|
||||
}:
|
||||
|
||||
{
|
||||
ibm-plex-web = callPackage ./ibm-plex-web.nix {};
|
||||
}
|
||||
File renamed without changes.
Reference in new issue
Block a user