Compare commits
1
Commits
main
..
de61e45637
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de61e45637 |
No files matched your search
@@ -1 +0,0 @@
|
||||
((nil . ((cider-clojure-cli-aliases . ":dev:test"))))
|
||||
@@ -9,3 +9,5 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- 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/
|
||||
|
||||
+29
-1
@@ -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/",
|
||||
@@ -357,6 +370,11 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-OaawIvv0GgkuZwK6MAFtmuyw3zNcYiZVd66K/IipB2A="
|
||||
},
|
||||
{
|
||||
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-98tpbM5Vr9dMg41UQUGcfl9tSRrxhajlY9+nl5aFcoM="
|
||||
},
|
||||
{
|
||||
"mvn-path": "fipp/fipp/0.6.26/fipp-0.6.26.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -952,6 +970,11 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-UfmOunss1C7jDzgmkl3N6HkRZ/dvcSMprlG4gkToE44="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -1102,6 +1125,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,9 +4,8 @@
|
||||
, 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
|
||||
}:
|
||||
@@ -33,8 +32,8 @@ let
|
||||
];
|
||||
|
||||
doerg-config = writeText "doerg-extra-config.edn" ''
|
||||
#:net.deertopia.doerg.config
|
||||
{:ibm-plex-web "${ibm-plex-web}/share/ibm-plex-web"
|
||||
#:net.deertopia.doerg
|
||||
{:ibm-plex-web "${ibm-plex-web}"
|
||||
:latex "${lib.getExe' our-tex "xelatex"}"
|
||||
:dvisvgm "${lib.getExe' our-tex "dvisvgm"}"
|
||||
:doerg-temml-worker "${lib.getExe doerg-temml-worker}"
|
||||
@@ -43,21 +42,15 @@ let
|
||||
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,7 +58,6 @@ in mkCljBin' {
|
||||
nativeCheckInputs = [
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
test-emacs
|
||||
plex
|
||||
our-tex
|
||||
];
|
||||
@@ -74,11 +66,6 @@ in mkCljBin' {
|
||||
'';
|
||||
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";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{:deps {org.clojure/tools.logging {:mvn/version "1.3.0"}
|
||||
babashka/fs {:mvn/version "0.5.24"}
|
||||
org.clojure/core.match {:mvn/version "1.1.0"}
|
||||
cheshire/cheshire {:mvn/version "6.1.0"}
|
||||
babashka/process {:mvn/version "0.6.25"}
|
||||
io.github.msyds/spec-dict
|
||||
{:git/sha "531d629b7f05f37232261cf9e8927a4b5915714f"}
|
||||
hiccup/hiccup {:mvn/version "2.0.0-RC4"}
|
||||
com.rpl/specter {:mvn/version "1.1.6"}
|
||||
mvxcvi/clj-cbor {:mvn/version "1.1.1"}
|
||||
ch.qos.logback/logback-classic {:mvn/version "1.1.3"}
|
||||
org.clojure/test.check {:mvn/version "1.1.3"}
|
||||
aero/aero {:mvn/version "1.1.6"}}
|
||||
:paths ["src" "resources"]
|
||||
:aliases
|
||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:extra-paths ["test"]
|
||||
:main-opts ["-m" "kaocha.runner"]}}}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,11 @@
|
||||
#:net.deertopia.doerg
|
||||
{:ibm-plex-web #or [#xdg-data-dir "ibm-plex-web"
|
||||
#env IBM_PLEX_WEB]
|
||||
:latex "xelatex"
|
||||
:dvisvgm "dvisvgm"
|
||||
:doerg-temml-worker
|
||||
#profile {:dev #file "../../../../doerg-temml-worker/index.js"
|
||||
:default "doerg-temml-worker"}
|
||||
:doerg-parser
|
||||
#profile {:dev #file "../../../../doerg-parser/index.js"
|
||||
:default "doerg-parser"}}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -438,7 +438,7 @@ label.margin-toggle:not(.sidenote-number) {
|
||||
}
|
||||
}
|
||||
|
||||
.org-link.external::after
|
||||
.link.external::after
|
||||
{ content: "↗"
|
||||
; 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.
@@ -1,25 +1,25 @@
|
||||
(ns net.deertopia.doerg.config
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[babashka.fs :as fs]
|
||||
[spec-dict.main :refer [dict]]
|
||||
[aero.core :as aero]
|
||||
[net.deertopia.doerg :as-alias d]
|
||||
[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 ::d/config
|
||||
(s/keys :req [::d/ibm-plex-web
|
||||
::d/latex
|
||||
::d/dvisvgm
|
||||
::d/doerg-temml-worker
|
||||
::d/doerg-parser]))
|
||||
|
||||
(s/def ::directory
|
||||
(s/def ::d/directory
|
||||
(s/conformer #(fs/file %)))
|
||||
|
||||
(s/def ::file
|
||||
(s/def ::d/file
|
||||
(s/conformer #(-> % fs/expand-home fs/file)))
|
||||
|
||||
(s/def ::executable
|
||||
(s/def ::d/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)?
|
||||
@@ -28,26 +28,22 @@
|
||||
(some-> % fs/expand-home fs/file)
|
||||
::s/invalid)))
|
||||
|
||||
(s/def ::ibm-plex-web ::directory)
|
||||
(s/def ::d/ibm-plex-web ::d/directory)
|
||||
|
||||
(s/def ::latex ::executable)
|
||||
(s/def ::d/latex ::d/executable)
|
||||
|
||||
(s/def ::dvisvgm ::executable)
|
||||
(s/def ::d/dvisvgm ::d/executable)
|
||||
|
||||
(s/def ::doerg-temml-worker ::executable)
|
||||
(s/def ::d/doerg-temml-worker ::d/executable)
|
||||
|
||||
(s/def ::doerg-parser ::executable)
|
||||
|
||||
(s/def ::state-directory ::file)
|
||||
(s/def ::org-roam-db-path ::file)
|
||||
(s/def ::d/doerg-parser ::d/executable)
|
||||
|
||||
(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)))
|
||||
(fs/split-paths (System/getenv "XDG_DATA_DIRS"))))
|
||||
|
||||
(defmethod aero/reader 'file
|
||||
[{:keys [source]} tag value]
|
||||
@@ -56,16 +52,19 @@
|
||||
(-> (aero/relative-resolver source value)
|
||||
fs/file))
|
||||
|
||||
(defn read-config [files & {:as opts}]
|
||||
(defn read-config [spec files & {:as opts}]
|
||||
(let [r (->> files
|
||||
(filter identity)
|
||||
(map #(aero/read-config % opts))
|
||||
(apply merge))
|
||||
conformed (s/conform ::config r)]
|
||||
conformed (s/conform spec r)]
|
||||
(if-not (s/invalid? conformed)
|
||||
conformed
|
||||
(throw (ex-info "Failed to conform config"
|
||||
(s/explain-data ::config r))))))
|
||||
(s/explain-data spec r))))))
|
||||
|
||||
(defn load-config! [var spec files & {:as opts}]
|
||||
(alter-var-root var (constantly (read-config spec files opts))))
|
||||
|
||||
(def sources
|
||||
[;; Default config.
|
||||
@@ -75,13 +74,6 @@
|
||||
;; Config set at runtime.
|
||||
(System/getenv "DOERG_CONFIG")])
|
||||
|
||||
(def default (read-config sources))
|
||||
(def default (read-config ::d/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))))))
|
||||
@@ -4,8 +4,10 @@
|
||||
[babashka.process :as p]
|
||||
[cheshire.core :as json]
|
||||
[clojure.core.match :refer [match]]
|
||||
[net.deertopia.doerg :as-alias doerg]
|
||||
[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 +16,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 +37,7 @@
|
||||
:or {in *in*}}]
|
||||
(let [r (-> (p/process
|
||||
{:in in :out :string}
|
||||
(-> cfg/*cfg* ::cfg/doerg-parser str))
|
||||
(-> cfg/*cfg* ::doerg/doerg-parser str))
|
||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||
(when (zero? (:exit r))
|
||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||
@@ -62,6 +65,8 @@
|
||||
(and (map? e) (contains? e :children)))
|
||||
|
||||
(defn org-element? [element]
|
||||
#_
|
||||
(s/valid? ::org-element element)
|
||||
(and (map? element)
|
||||
(contains? element :type)))
|
||||
|
||||
@@ -94,6 +99,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 +315,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)
|
||||
File renamed without changes.
@@ -0,0 +1,5 @@
|
||||
(ns net.deertopia.doerg.main
|
||||
(:gen-class))
|
||||
|
||||
(defn -main []
|
||||
(println "hello from doerg"))
|
||||
@@ -12,8 +12,7 @@
|
||||
[net.deertopia.doerg.tex :as tex]
|
||||
[net.deertopia.doerg.tex.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)))
|
||||
@@ -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)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
(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))
|
||||
(-> cfg/*cfg* ::doerg/ibm-plex-web))
|
||||
(doseq [x #{"Temml-Plex.css" "tuftesque.css" "deerstar.css"}]
|
||||
(force-create-sym-link
|
||||
(fs/file resource-dir x)
|
||||
File renamed without changes.
+2
-2
@@ -83,14 +83,14 @@
|
||||
acc))))
|
||||
|
||||
(defn- invoke-latex [& {:keys [file output-dir]}]
|
||||
(let [latex (-> cfg/*cfg* ::cfg/latex)]
|
||||
(let [latex (-> cfg/*cfg* ::doerg/latex)]
|
||||
(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/*cfg* ::doerg/dvisvgm)]
|
||||
(invoke
|
||||
{:dir output-dir}
|
||||
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
||||
@@ -25,7 +25,7 @@
|
||||
fs/file))
|
||||
|
||||
(defn worker []
|
||||
(let [doerg-temml-worker (-> cfg/*cfg* ::cfg/doerg-temml-worker)]
|
||||
(let [doerg-temml-worker (-> cfg/*cfg* ::doerg/doerg-temml-worker)]
|
||||
(when (or (not (fs/exists? prelude-file))
|
||||
(zero? (fs/size prelude-file)))
|
||||
(-> "net/deertopia/doerg/prelude.tex"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Generated
+3
-3
@@ -111,11 +111,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||
"lastModified": 1760038930,
|
||||
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -14,19 +14,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 +31,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,12 @@
|
||||
((nil
|
||||
. ((cider-clojure-cli-aliases . ":dev:test")
|
||||
;; (eval
|
||||
;; . (progn
|
||||
;; (defun start-deertopia-server ()
|
||||
;; (let ((n (cider-format-connection-params "%j" cider-launch-params)))
|
||||
;; (when (equal n "net-deertopia")
|
||||
;; (cider-interactive-eval
|
||||
;; "(do (require '[net.deertopia.publisher.server :as server])
|
||||
;; (server/start!))"))))
|
||||
;; (add-hook 'cider-connected-hook #'start-deertopia-server)))
|
||||
)))
|
||||
@@ -0,0 +1,27 @@
|
||||
{ mkCljBin
|
||||
, doerg
|
||||
, babashka
|
||||
}:
|
||||
|
||||
mkCljBin {
|
||||
name = "net.deertopia/publisher";
|
||||
version = "0.1.0";
|
||||
projectSrc = ./.;
|
||||
lockfile = ../deps-lock.json;
|
||||
main-ns = "net.deertopia.publisher.main";
|
||||
buildInputs = [
|
||||
doerg
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
babashka
|
||||
];
|
||||
postPatch = ''
|
||||
mv deps.edn deps.edn.old
|
||||
bb -cp . -m override-deps < deps.edn.old > deps.edn \
|
||||
net.deertopia/doerg '{:local/root "${doerg.lib}/${doerg.name}.jar"}'
|
||||
'';
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
clojure -M:test
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{:deps {org.clojure/clojure {:mvn/version "1.12.0"}
|
||||
org.clojure/tools.logging {:mvn/version "1.3.0"}
|
||||
hiccup/hiccup {:mvn/version "2.0.0-RC4"}
|
||||
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"}
|
||||
babashka/fs {:mvn/version "0.5.24"}
|
||||
org.clojure/core.match {:mvn/version "1.1.0"}
|
||||
com.github.seancorfield/next.jdbc {:mvn/version "1.3.1070"}
|
||||
org.xerial/sqlite-jdbc {:mvn/version "3.47.1.0"}
|
||||
cheshire/cheshire {:mvn/version "6.1.0"}
|
||||
org.clojure/test.check {:mvn/version "1.1.3"}
|
||||
net.deertopia/doerg {:local/root "../doerg"}
|
||||
metosin/reitit {:mvn/version "0.10.1"}
|
||||
http-kit/http-kit {:mvn/version "2.8.0"}
|
||||
instaparse/instaparse {:mvn/version "1.5.0"}
|
||||
aero/aero {:mvn/version "1.1.6"}}
|
||||
:paths ["src" "resources"]
|
||||
:aliases
|
||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:extra-paths ["test"]
|
||||
:main-opts ["-m" "kaocha.runner"]}
|
||||
:dev {:extra-paths ["dev"]}}}
|
||||
@@ -0,0 +1,24 @@
|
||||
(ns user
|
||||
(:require [net.deertopia.publisher.server :as server]
|
||||
[net.deertopia.doerg :as-alias doerg]
|
||||
[net.deertopia.publisher :as-alias publisher]
|
||||
[net.deertopia.doerg.config :as doerg-config]
|
||||
[net.deertopia.publisher.config :as publisher-config]
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
(doerg-config/load-config! #'doerg-config/*cfg*
|
||||
::doerg/config
|
||||
doerg-config/sources
|
||||
:profile :dev)
|
||||
|
||||
(doerg-config/load-config! #'publisher-config/*cfg*
|
||||
::publisher/config
|
||||
publisher-config/sources
|
||||
:profile :dev)
|
||||
|
||||
(when (not= :running (server/status))
|
||||
(server/start!))
|
||||
|
||||
(defn invalidate-html-cache! []
|
||||
(fs/delete-tree (server/html-dir))
|
||||
nil)
|
||||
@@ -0,0 +1,56 @@
|
||||
;;; -*- mode:clojure -*-
|
||||
;;;
|
||||
;;; USAGE:
|
||||
;;;
|
||||
;;; bb -cp . -m override-deps -- [DEP-NAME INFO]…
|
||||
;;;
|
||||
;;; This script takes a series of deps substitutions on the command
|
||||
;;; line, applies them to a deps.edn file (read on stdin), and spits
|
||||
;;; the result to stdout.
|
||||
;;;
|
||||
;;; It is used to build the Doerg server with Nix, since Clj-nix does
|
||||
;;; not resolve the local deps itself.
|
||||
|
||||
(ns override-deps
|
||||
(:require [rewrite-clj.zip :as z]
|
||||
[babashka.fs :as fs]
|
||||
[clojure.edn :as edn]))
|
||||
|
||||
(defn apply-overrides [zloc overrides]
|
||||
(loop [os (seq overrides)
|
||||
loc zloc]
|
||||
(if-some [[[k v] & xs] os]
|
||||
(do (binding [*out* *err*]
|
||||
(printf "override dep %s with %s\n"
|
||||
(pr-str k) (pr-str v)))
|
||||
(recur xs (z/assoc loc k v)))
|
||||
loc)))
|
||||
|
||||
(defn args->overrides [args]
|
||||
(assert (even? (count args)))
|
||||
(->> args (map edn/read-string) (apply hash-map)))
|
||||
|
||||
(defn -main [& args]
|
||||
(let [zloc (-> (slurp *in*) z/of-string)
|
||||
overrides (args->overrides args)]
|
||||
(-> zloc
|
||||
z/down
|
||||
(z/find-value :deps) z/right
|
||||
(apply-overrides overrides)
|
||||
z/root-string
|
||||
print)))
|
||||
|
||||
|
||||
|
||||
(comment
|
||||
"Example overrides"
|
||||
(def overrides '{net.deertopia/doerg "blah!!!!"
|
||||
ring/ring-defaults {:mvn/version "xxxxx"}}))
|
||||
|
||||
(comment
|
||||
"Behaviour of `args->overrides`."
|
||||
(= (args->overrides ["net.deertopia/doerg" "{:mvn/version \"abc\"}"
|
||||
"ring/ring-defaults" "{:local/root \"/path/to/jar\"}"])
|
||||
'{ring/ring-defaults {:local/root "/path/to/jar"}
|
||||
net.deertopia/doerg {:mvn/version "abc"}}))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#:net.deertopia.publisher
|
||||
{:state-directory #join [#or [#env XDG_STATE_HOME
|
||||
#envf ["%s/.local/share" HOME]]
|
||||
"/doerg-publisher"]
|
||||
:org-roam-db-path
|
||||
#profile {:default #join [#env HOME "/.cache/emacs/org-roam.db"]
|
||||
:test #file "../../../../test/net/deertopia/publisher/roam-test.db"}
|
||||
:port #profile {:default 8080}}
|
||||
File renamed without changes.
+3
-5
@@ -1,4 +1,4 @@
|
||||
(ns net.deertopia.doerg.cached-file
|
||||
(ns net.deertopia.publisher.cached-file
|
||||
(:require [babashka.fs :as fs]))
|
||||
|
||||
(defn newer-than?
|
||||
@@ -18,10 +18,8 @@
|
||||
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))
|
||||
(fs/create-dirs (fs/parent file))
|
||||
(spit file r)))
|
||||
file)
|
||||
@@ -0,0 +1,28 @@
|
||||
(ns net.deertopia.publisher.config
|
||||
(:require [babashka.fs :as fs]
|
||||
[clojure.spec.alpha :as s]
|
||||
[net.deertopia.doerg.config :as doerg-config]
|
||||
[net.deertopia.doerg :as-alias doerg]
|
||||
[net.deertopia.publisher :as-alias p]
|
||||
[aero.core :as aero]
|
||||
[clojure.java.io :as io]))
|
||||
|
||||
(s/def ::p/config
|
||||
(s/keys :req [::p/state-directory
|
||||
::p/org-roam-db-path]))
|
||||
|
||||
(s/def ::p/state-directory ::doerg/file)
|
||||
(s/def ::p/org-roam-db-path ::doerg/file)
|
||||
|
||||
(def sources
|
||||
[;; Default config.
|
||||
(io/resource "net/deertopia/publisher/default-config.edn")
|
||||
;; Defaults set at build time, if any.
|
||||
(io/resource "net/deertopia/publisher/extra-config.edn")
|
||||
;; Config set at runtime.
|
||||
(System/getenv "DOERG_PUBLISHER_CONFIG")])
|
||||
|
||||
(def default
|
||||
(doerg-config/read-config ::p/config sources))
|
||||
|
||||
(def ^:dynamic *cfg* default)
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns net.deertopia.doerg.elisp
|
||||
(ns net.deertopia.publisher.elisp
|
||||
(:require [clojure.core.match :refer [match]]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.spec.alpha :as s]
|
||||
@@ -6,7 +6,7 @@
|
||||
(:refer-clojure :exclude [print read read-string]))
|
||||
|
||||
(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,9 @@
|
||||
(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]
|
||||
[net.deertopia.publisher :as-alias publisher]
|
||||
[next.jdbc :as sql])
|
||||
(:import (java.util UUID)))
|
||||
|
||||
@@ -11,10 +12,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* ::publisher/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 +30,21 @@
|
||||
(-> 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)
|
||||
(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]
|
||||
(and (uuid-exists? uuid)
|
||||
(->Node uuid (atom {}))))
|
||||
|
||||
(defn- fetch-with-cache [node field fetch]
|
||||
(if *use-db-cache?*
|
||||
@@ -57,20 +59,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 +78,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 +90,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 +100,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 +111,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 +120,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 +156,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
|
||||
+21
-57
@@ -1,12 +1,12 @@
|
||||
(ns net.deertopia.doerg.server
|
||||
(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.doerg.config :as-alias cfg]
|
||||
[net.deertopia.doerg.slug :as slug]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[net.deertopia.doerg.roam :as roam]
|
||||
[net.deertopia.publisher :as-alias publisher]
|
||||
[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]
|
||||
@@ -20,10 +20,12 @@
|
||||
[reitit.dev.pretty]
|
||||
[clojure.spec.alpha :as s]
|
||||
[net.deertopia.doerg.render :as doerg-render]
|
||||
[net.deertopia.doerg.cached-file :as cached-file]
|
||||
[net.deertopia.publisher.cached-file :as cached-file]
|
||||
[babashka.fs :as fs]
|
||||
[aero.core :as aero]
|
||||
[clojure.string :as str]))
|
||||
[clojure.string :as str]
|
||||
[net.deertopia.doerg :as-alias doerg]
|
||||
[net.deertopia.doerg.config :as doerg-config]))
|
||||
|
||||
|
||||
;;; Routes
|
||||
@@ -47,15 +49,10 @@
|
||||
(response/content-type "text/html")))
|
||||
|
||||
(defn html-dir []
|
||||
(-> cfg/*cfg* ::cfg/state-directory (fs/file "html")))
|
||||
(-> cfg/*cfg* ::publisher/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 not-found [req]
|
||||
(response/not-found "not found"))
|
||||
|
||||
(defn org-file->html-file [org-file]
|
||||
(fs/file (html-dir)
|
||||
@@ -64,56 +61,20 @@
|
||||
(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))}
|
||||
[: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)]
|
||||
(if-some [node (some-> slug slug/from-string roam/get-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)))
|
||||
:compute #(doerg-render/to-html org-file))
|
||||
(-> (str html-file)
|
||||
response/file-response
|
||||
(response/content-type "text/html")))
|
||||
@@ -136,11 +97,14 @@
|
||||
(assoc-in [:path-params :slug] homepage-slug)
|
||||
node-by-slug))
|
||||
|
||||
(def doerg-resources
|
||||
#{"Temml-Plex.css" "tuftesque.css" "deerstar.css"})
|
||||
|
||||
(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)}))
|
||||
{:root (-> doerg-config/*cfg* ::doerg/ibm-plex-web str)}))
|
||||
(-> uri
|
||||
(str/replace-first #"^/resource/" "")
|
||||
(response/resource-response
|
||||
@@ -191,7 +155,7 @@
|
||||
(throw (IllegalStateException. "Server already started"))
|
||||
(do (reset! server
|
||||
(http/run-server (bound-fn* #'app)
|
||||
{:port (-> cfg/*cfg* ::cfg/port)
|
||||
{:port (-> cfg/*cfg* ::publisher/port)
|
||||
:legacy-return-value? false}))
|
||||
;; For some reason, the log messages are not flushed before
|
||||
;; the JVM shuts dowm. Nevertheless, the server /does/ come
|
||||
@@ -202,7 +166,7 @@
|
||||
(ex-message e))
|
||||
(throw e))))
|
||||
(l/infof "Server started on port %d"
|
||||
(-> cfg/*cfg* ::cfg/port)))))
|
||||
(-> cfg/*cfg* ::publisher/port)))))
|
||||
|
||||
(defn status []
|
||||
(if @server
|
||||
@@ -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)
|
||||
Binary file not shown.
File renamed without changes.
+20
-14
@@ -1,16 +1,24 @@
|
||||
(ns net.deertopia.doerg.server-test
|
||||
(:require [net.deertopia.doerg.server :as sut]
|
||||
(ns net.deertopia.publisher.server-test
|
||||
(:require [net.deertopia.publisher.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]]))
|
||||
[net.deertopia.publisher.config :as publisher-cfg]
|
||||
[net.deertopia.doerg.config :as doerg-cfg]
|
||||
[net.deertopia.publisher :as-alias publisher]
|
||||
[net.deertopia.doerg :as-alias doerg]
|
||||
[net.deertopia.publisher.roam :as roam]))
|
||||
|
||||
(t/use-fixtures
|
||||
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
||||
:once (fn [f]
|
||||
(binding [doerg-cfg/*cfg*
|
||||
(doerg-cfg/read-config
|
||||
::doerg/config doerg-cfg/sources
|
||||
:profile :test)
|
||||
publisher-cfg/*cfg*
|
||||
(doerg-cfg/read-config
|
||||
::publisher/config publisher-cfg/sources
|
||||
:profile :test)]
|
||||
(f))))
|
||||
|
||||
(defn with-server [f]
|
||||
(let [was-already-running? (= :running (sut/status))]
|
||||
@@ -24,8 +32,6 @@
|
||||
(sut/app {:request-method :get
|
||||
:uri uri}))
|
||||
|
||||
|
||||
|
||||
(t/deftest server-is-running
|
||||
;; 서버는 벌써 시작한 다음에 이 테스트 하면 잘못됩니다.
|
||||
;; (assert (not= :running (sut/status)))
|
||||
@@ -33,9 +39,9 @@
|
||||
(fn []
|
||||
(t/is (= :running (sut/status)))
|
||||
(t/is (->> (format "http://localhost:%d"
|
||||
(::cfg/port cfg/*cfg*))
|
||||
slurp
|
||||
string?)))))
|
||||
(::publisher/port publisher-cfg/*cfg*))
|
||||
slurp
|
||||
string?)))))
|
||||
|
||||
(t/deftest get-nonexistent-node
|
||||
(let [slug "3Lxvxnb0QrivoU3DX-l_5w"]
|
||||
@@ -0,0 +1 @@
|
||||
#kaocha/v1 {}
|
||||
@@ -0,0 +1,25 @@
|
||||
{ fetchzip
|
||||
, fetchurl
|
||||
}:
|
||||
|
||||
{
|
||||
ibm-plex-serif = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-serif%401.1.0/ibm-plex-serif.zip";
|
||||
hash = "sha256-8ygaAeMKygYS4GCub4YUQmkh87pYHfi3s0PQ6AbaeGw=";
|
||||
};
|
||||
|
||||
ibm-plex-math = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-math%401.1.0/ibm-plex-math.zip";
|
||||
hash = "sha256-dJA6uqxa/yb3eLY4l39NeP0yIl2NfrbaRpf6h0/F7Xc=";
|
||||
};
|
||||
|
||||
ibm-plex-sans-kr = fetchzip {
|
||||
url = "https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-sans-kr%401.1.0/ibm-plex-sans-kr.zip";
|
||||
hash = "sha256-FsHxMvLlI4yylgG96DOZIdW2DYpk7I+c5QgkVIkNZIE=";
|
||||
};
|
||||
|
||||
"d3.v7.min.js" = fetchurl {
|
||||
url = "https://d3js.org/d3.v7.min.js";
|
||||
hash = "sha256-8glLv2FBs1lyLE/kVOtsSw8OQswQzHr5IfwVj864ZTk=";
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#:net.deertopia.doerg.config
|
||||
{:ibm-plex-web #or [#env IBM_PLEX_WEB
|
||||
#xdg-data-dir "ibm-plex-web"]
|
||||
:latex "xelatex"
|
||||
:dvisvgm "dvisvgm"
|
||||
:doerg-temml-worker
|
||||
#profile {:dev #file "../../../../doerg-temml-worker/index.js"
|
||||
:default "doerg-temml-worker"}
|
||||
:doerg-parser
|
||||
#profile {:dev #file "../../../../doerg-parser/index.js"
|
||||
:default "doerg-parser"}
|
||||
:state-directory #join [#or [#env XDG_STATE_HOME
|
||||
#envf ["%s/.local/share" HOME]]
|
||||
"/doerg-server"]
|
||||
:org-roam-db-path
|
||||
#profile {:default #join [#env HOME "/.cache/emacs/org-roam.db"]
|
||||
:test #join [#or [#env TMP "/tmp"] "/doerg-org-roam-test.db"]}
|
||||
:port #profile {:default 8080}}
|
||||
@@ -1,8 +0,0 @@
|
||||
(ns net.deertopia.doerg.main
|
||||
(:require [net.deertopia.doerg.server :as server]
|
||||
[net.deertopia.doerg.config :as cfg])
|
||||
(:gen-class))
|
||||
|
||||
(defn -main [& _]
|
||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources)]
|
||||
(server/start!)))
|
||||
@@ -1,10 +0,0 @@
|
||||
{ emacsPackages
|
||||
, symlinkJoin
|
||||
, writeScriptBin
|
||||
, lib
|
||||
}:
|
||||
|
||||
let emacs = emacsPackages.emacsWithPackages (epkgs: [ epkgs.org-roam ]);
|
||||
in writeScriptBin "test-emacs" ''
|
||||
exec ${lib.getExe emacs} "$@"
|
||||
''
|
||||
@@ -1,9 +0,0 @@
|
||||
(ns net.deertopia.doerg.config-test
|
||||
(:require [clojure.test :as t]
|
||||
[net.deertopia.doerg.config :as cfg]))
|
||||
|
||||
(defn test-config-fixture
|
||||
"`clojure.test` fixture to run tests with the :test configuration."
|
||||
[f]
|
||||
(binding [cfg/*cfg* (cfg/read-config cfg/sources :profile :test)]
|
||||
(f)))
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env -S emacs -Q -x
|
||||
|
||||
(require 'org-roam)
|
||||
|
||||
(setq org-roam-directory (expand-file-name (car command-line-args-left)))
|
||||
(setq org-roam-db-location (expand-file-name (cadr command-line-args-left)))
|
||||
|
||||
(org-roam-db-sync)
|
||||
@@ -1,23 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 3c60c74e-f533-43ad-89b3-563975bf80f2
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: page not found
|
||||
|
||||
the page you're looking for doesn't exist, or you lack the permissions necessary to view it........
|
||||
|
||||
#+attr_doerg: :center? true :alt "A doe sitting and sobbing" :scale 1.4
|
||||
#+begin_example
|
||||
\{ / \ }/
|
||||
\/ . . \/
|
||||
.. \Y` `Y/ ..
|
||||
\ `\|~==~|/' /
|
||||
'". T T ."`
|
||||
{`^' }
|
||||
| |
|
||||
/</3 \
|
||||
|| ||
|
||||
_| || |_
|
||||
.,_) ) || ( (_,.
|
||||
|__ /_||_\ __|
|
||||
#+end_example
|
||||
@@ -1,7 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 90f23e03-f746-42cb-862f-1af2d4bde3cc
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: Category theory
|
||||
|
||||
*Category theory* is the mathematical study of categories and functors between them.
|
||||
@@ -1,7 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: ebc5ea84-77ab-4d60-9b13-ef9160b11d1f
|
||||
:DeertopiaVisibility: public
|
||||
:END:
|
||||
#+title: deertopia.net!!!!!!!!
|
||||
|
||||
homeee
|
||||
@@ -1,22 +0,0 @@
|
||||
:PROPERTIES:
|
||||
:ID: 897bfc9d-94ce-4c58-8d21-93f13372b17b
|
||||
:END:
|
||||
#+title: Monomorphisms and epimorphisms
|
||||
|
||||
In [[id:90f23e03-f746-42cb-862f-1af2d4bde3cc][category theory]], *monomorphisms* and *epimorphisms* are types of cancellative morphisms generalising injective and surjective functions, respectively.[fn:1]
|
||||
|
||||
\begin{tikzcd}
|
||||
% https://q.uiver.app/#q=WzAsNixbMCwwLCJYIl0sWzEsMCwiWSJdLFsyLDAsIloiXSxbMSwxLCJZIl0sWzIsMSwiWiJdLFswLDEsIlgiXSxbMCwxLCJnXzEiLDAseyJvZmZzZXQiOi0yfV0sWzAsMSwiZ18yIiwyLHsib2Zmc2V0IjoyfV0sWzEsMiwiZiIsMl0sWzMsNCwiZ18xIiwwLHsib2Zmc2V0IjotMn1dLFszLDQsImdfMiIsMix7Im9mZnNldCI6Mn1dLFs1LDMsImYiLDJdXQ==
|
||||
X & Y & Z \\
|
||||
X & Y & Z
|
||||
\arrow["{g_1}", shift left=2, from=1-1, to=1-2]
|
||||
\arrow["{g_2}"', shift right=2, from=1-1, to=1-2]
|
||||
\arrow["f"', from=1-2, to=1-3]
|
||||
\arrow["f"', from=2-1, to=2-2]
|
||||
\arrow["{g_1}", shift left=2, from=2-2, to=2-3]
|
||||
\arrow["{g_2}"', shift right=2, from=2-2, to=2-3]
|
||||
\end{tikzcd}
|
||||
|
||||
* Footnotes
|
||||
|
||||
[fn:1] blahahahahah blah blah
|
||||
@@ -1,63 +0,0 @@
|
||||
(ns net.deertopia.doerg.roam-test
|
||||
(:require [net.deertopia.doerg.roam :as sut]
|
||||
[clojure.test :as t]
|
||||
[clojure.java.io :as io]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[babashka.fs :as fs]
|
||||
[babashka.process :as p]
|
||||
[net.deertopia.doerg.config-test :refer [test-config-fixture]]
|
||||
[next.jdbc :as sql]
|
||||
[clojure.string :as str]
|
||||
[net.deertopia.doerg.elisp :as elisp]
|
||||
[com.rpl.specter :as sp]))
|
||||
|
||||
(def org-roam-directory
|
||||
(fs/file "test/net/deertopia/doerg/roam-test"))
|
||||
|
||||
(defn org-roam-db-sync [db-file]
|
||||
(let [script-file (fs/create-temp-file {:prefix "org-roam-db-sync-"
|
||||
:suffix ".el"})
|
||||
emacs (->> [(System/getenv "EMACS") "test-emacs" "emacs"]
|
||||
(some #(some-> % fs/which)))]
|
||||
(io/copy (-> "net/deertopia/doerg/org-roam-db-sync.el"
|
||||
io/resource io/reader)
|
||||
(fs/file script-file))
|
||||
(p/shell {:out :string :err :string}
|
||||
emacs "-Q" "-x" script-file org-roam-directory db-file)
|
||||
(fs/delete script-file)))
|
||||
|
||||
(defn test-db-fixture [f]
|
||||
(let [db-file (-> cfg/*cfg* ::cfg/org-roam-db-path)]
|
||||
(assert (->> db-file fs/canonicalize str
|
||||
(re-matches #"^/(build|tmp)/.*"))
|
||||
(format "i'm scared to delete a non-test database... %s"
|
||||
(str db-file)))
|
||||
(fs/delete-if-exists db-file)
|
||||
(org-roam-db-sync db-file)
|
||||
(f)
|
||||
(fs/delete db-file)))
|
||||
|
||||
(t/use-fixtures
|
||||
:once (t/join-fixtures [test-config-fixture test-db-fixture]))
|
||||
|
||||
|
||||
|
||||
(t/deftest all-nodes-exist
|
||||
(let [known-node-files (->> (fs/list-dir org-roam-directory)
|
||||
(map (comp str fs/canonicalize))
|
||||
(into #{}))
|
||||
database-nodes
|
||||
(->> (sql/execute!
|
||||
(sut/ds) ["select file, id from nodes"])
|
||||
(map (fn [x]
|
||||
{:file (-> x :nodes/file elisp/read-string)
|
||||
:id (-> x :nodes/id elisp/read-string parse-uuid)}))
|
||||
(into #{}))]
|
||||
(t/testing "database has a node for each file?"
|
||||
(t/is (= known-node-files (sp/transform
|
||||
[sp/ALL]
|
||||
#(:file %)
|
||||
database-nodes))))
|
||||
(t/testing "each uuid exists?"
|
||||
(t/is (every? (comp sut/uuid-exists? :id)
|
||||
database-nodes)))))
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{ fetchzip
|
||||
, fetchurl
|
||||
, callPackage
|
||||
}:
|
||||
|
||||
{
|
||||
ibm-plex-web = callPackage ./ibm-plex-web.nix {};
|
||||
}
|
||||
File renamed without changes.
Reference in new issue
Block a user