Compare commits
44 Commits
footnotes
...
f947df6711
| Author | SHA1 | Date | |
|---|---|---|---|
| f947df6711 | |||
| 7aa6e02b9e | |||
| 01d88bb30d | |||
| 7e0826c496 | |||
| 06c20588f2 | |||
| 4b4573ee1d | |||
| 071a15ca51 | |||
| f811a519b5 | |||
| fa42052a6a | |||
| ea3b77619a | |||
| cf225f6bc5 | |||
| 2776144f04 | |||
| 71163b9bb5 | |||
| 7d12f7d90e | |||
| d5ccadb326 | |||
| ee86f0d643 | |||
| e67f62e5b0 | |||
| b765f71b55 | |||
| 47b201fd03 | |||
| 8ec78c040a | |||
| d15f9988c2 | |||
| b3ca176ee2 | |||
| efd4c4cdbc | |||
| f6da1187ad | |||
| bd3e6016ed | |||
| 02bbe0a8b8 | |||
| dc31f02b30 | |||
| fd8354f398 | |||
| af493a1291 | |||
| 955db64027 | |||
| ad8ae8f743 | |||
| a52bc97ed3 | |||
| 470dec9183 | |||
| 790ce7e01f | |||
| aa8b89fe84 | |||
| 638b12c9eb | |||
| 9ac8577478 | |||
| b5a5721eed | |||
| 651ed4f26c | |||
| a26df4011a | |||
| 71b370147e | |||
| 703bcff905 | |||
| 3fa63d03d8 | |||
| 98c0be72e0 |
382
deps-lock.json
382
deps-lock.json
@@ -10,6 +10,16 @@
|
||||
}
|
||||
],
|
||||
"mvn-deps": [
|
||||
{
|
||||
"mvn-path": "aero/aero/1.1.6/aero-1.1.6.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-9LCpJy2lDICRxVKcn+NVxHI08e65X+kiluLCP3h/PSI="
|
||||
},
|
||||
{
|
||||
"mvn-path": "aero/aero/1.1.6/aero-1.1.6.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-WUXPjq14D3SX6G8piWPyeGgdUZrpshvpSfrFQg8F01A="
|
||||
},
|
||||
{
|
||||
"mvn-path": "babashka/fs/0.5.24/fs-0.5.24.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -40,6 +50,31 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-LVp6g6ymqHa1ZOMHYD0CRaNxZ4osT0xoEH7dC5sLv7s="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-mMPxj10NZCzV8yfMckVmzRlklibH2I9wFDvXBMlBV9U="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-Ond3RjIf1uIuOMzf1PY0vKNysA7mIAPlJ/aqRkkF8+g="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ch/qos/logback/logback-core/1.1.3/logback-core-1.1.3.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-R8D9NCmV0zFbj6zKzDJLKnYUOyfEMNSy1qKeq8MfXBQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ch/qos/logback/logback-core/1.1.3/logback-core-1.1.3.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-ziBX5rWqOWLWyNtAxJ6LzhFQqaobNhXtS6b1I9O5pwA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ch/qos/logback/logback-parent/1.1.3/logback-parent-1.1.3.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-ag4n7GeP9dkLjMZku0UZifXitbMAamW95Lld7BmHOHE="
|
||||
},
|
||||
{
|
||||
"mvn-path": "cheshire/cheshire/6.1.0/cheshire-6.1.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -125,6 +160,26 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-dXkdZHooK97QEyeXodFSC942EiB9B8MlHUNZlbH8nvI="
|
||||
},
|
||||
{
|
||||
"mvn-path": "com/nextjournal/beholder/1.0.2/beholder-1.0.2.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-iQOMTbidIDu1sSpfsa2qkpXgWirEsk+u2ZbJNOqJ0Xo="
|
||||
},
|
||||
{
|
||||
"mvn-path": "com/nextjournal/beholder/1.0.2/beholder-1.0.2.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-LRJkSGdQPfLoeGjLwU3deFKoaum2dW/QJ46lCK0d4u4="
|
||||
},
|
||||
{
|
||||
"mvn-path": "com/rpl/specter/1.1.6/specter-1.1.6.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-vqmD19/KmPN99xUGxINR1L2PzgwiUEoa+da1r39BE9U="
|
||||
},
|
||||
{
|
||||
"mvn-path": "com/rpl/specter/1.1.6/specter-1.1.6.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-2Fv7Xf/j/e+vS9pjGOyCkOyQEqA+0rzjZzo3p4T2WmU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "com/unboundid/unboundid-ldapsdk/5.1.1/unboundid-ldapsdk-5.1.1.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -185,6 +240,36 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-2OgLA0KFMl6QX1RkmhWYtoe5pKmaOk9LlO7TWXyyEEg="
|
||||
},
|
||||
{
|
||||
"mvn-path": "expound/expound/0.9.0/expound-0.9.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-1qNyYJkY4DUb+mqL1pPRi8GZ6Lp6r67BHola+uAY+Vw="
|
||||
},
|
||||
{
|
||||
"mvn-path": "expound/expound/0.9.0/expound-0.9.0.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-kJSODD3MvE8aCvaABWue2JizAcvtLd4/9CR5eWmXxdk="
|
||||
},
|
||||
{
|
||||
"mvn-path": "fipp/fipp/0.6.27/fipp-0.6.27.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"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": "hawk/hawk/0.2.11/hawk-0.2.11.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-6UPy8MSHxsWmsg5wzpHdXzHkBIlXCRe7oT/OpzyaekM="
|
||||
},
|
||||
{
|
||||
"mvn-path": "hawk/hawk/0.2.11/hawk-0.2.11.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-q4PzoWHUY53W2TZWihPpw+qXB4QWWVnS1iW3WlvIxFg="
|
||||
},
|
||||
{
|
||||
"mvn-path": "hiccup/hiccup/2.0.0-RC4/hiccup-2.0.0-RC4.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -215,6 +300,56 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-7Vh2tzj7zXYdGd03xiyTExP/beuWSi8Nn1NmRKkw9bQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "io/methvin/directory-watcher/0.17.3/directory-watcher-0.17.3.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-BSPdOKOTpjt15DIP9SMDSgrDzqaX9hUaesiok8MiUx4="
|
||||
},
|
||||
{
|
||||
"mvn-path": "io/methvin/directory-watcher/0.17.3/directory-watcher-0.17.3.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-Y/C4zR1No0m2Dfk4kdHgDF0/0sm9M9jlvu0HWijNiFQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/clj-diff/1.4.78/clj-diff-1.4.78.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-oovG5LKVI8wppHLlfm6rlYD6DQNorXvliypH6JGhRZw="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/clj-diff/1.4.78/clj-diff-1.4.78.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-2QZ6mFjx7+UGI232PUr3CzsQenqd+xcRsbqEpxs32w0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-BkOq5C/7omo09wyTTg7nkBi6GWBmlayVsPa9mrDvCyU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/deep-diff2/2.12.219/deep-diff2-2.12.219.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-rW/85js2hSWVc36e2BcTRmkahJHc2TjGIEfvForuToY="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/kaocha/1.91.1392/kaocha-1.91.1392.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-W7EV1MqxeIVqyTyt6lV9vpZrLRc+TWQKnmNfiPoieug="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/kaocha/1.91.1392/kaocha-1.91.1392.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-p6+0cuuFYlJU5YlhGIbnuHt1d6yOZXx/FhwAM6wCyzg="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/tools.namespace/0.3.256/tools.namespace-0.3.256.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-jt141ljkjv97etTTE995zZnqiZfoFnyt0g2hwmuOU8M="
|
||||
},
|
||||
{
|
||||
"mvn-path": "lambdaisland/tools.namespace/0.3.256/tools.namespace-0.3.256.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-n+46BXjy57A8898EXgyplEyyqf/S5qocf140ZbglV64="
|
||||
},
|
||||
{
|
||||
"mvn-path": "medley/medley/1.4.0/medley-1.4.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -225,6 +360,56 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-JhEgB4cMXujVcrvDw4n8a9bMZG1cUAdfbolYQMWGEMA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "meta-merge/meta-merge/1.0.0/meta-merge-1.0.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-1/7i4+PXBuDlRWLnKqNxIQjXAYahLLwJDhBoBYLrAsc="
|
||||
},
|
||||
{
|
||||
"mvn-path": "meta-merge/meta-merge/1.0.0/meta-merge-1.0.0.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-sAogZY/OzCvRNBAx85T1LWjFP7SAxEVBNMyqwgTqWTE="
|
||||
},
|
||||
{
|
||||
"mvn-path": "mvxcvi/arrangement/2.1.0/arrangement-2.1.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-83JROF0iDfiVHmjVJVq7UZetvL2PxrPT/KhyojOfOcg="
|
||||
},
|
||||
{
|
||||
"mvn-path": "mvxcvi/arrangement/2.1.0/arrangement-2.1.0.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-fWiMhmYYFAo78Am00FcK7acJA0h7dlH7VNBHf5TT2Is="
|
||||
},
|
||||
{
|
||||
"mvn-path": "mvxcvi/clj-cbor/1.1.1/clj-cbor-1.1.1.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-XqYtfq4Seg2W6Favuh2Ogm2TrZfFCgEFNvsekCgX4I8="
|
||||
},
|
||||
{
|
||||
"mvn-path": "mvxcvi/clj-cbor/1.1.1/clj-cbor-1.1.1.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-SzmvI+F2QOnCPH5H6OKH124pbohIazXgPG3PhqH0VZA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "net/incongru/watchservice/barbary-watchservice/1.0/barbary-watchservice-1.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-VMbKvYIJPIUV9uFOQ9lL/n6fx5XRV4nzlDoUGNgmOrU="
|
||||
},
|
||||
{
|
||||
"mvn-path": "net/incongru/watchservice/barbary-watchservice/1.0/barbary-watchservice-1.0.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-k7OxHaltUXiIDfjFBT8Yz8eByv8Nnd9LPGRyRKnRws8="
|
||||
},
|
||||
{
|
||||
"mvn-path": "net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-kagUrE9A1g3ukdhC4aith0xiGXmEQD0OPDDTnlXPU7M="
|
||||
},
|
||||
{
|
||||
"mvn-path": "net/java/dev/jna/jna/5.12.1/jna-5.12.1.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-Zf8lhJuthZVUtQMXeS9Wia20UprkAx6aUkYxnLK4U1Y="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/apache/apache/23/apache-23.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -282,62 +467,62 @@
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.10.3/clojure-1.10.3.jar",
|
||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-a6YADmhI+Cw5y5tJqyqmo6Vi9MJNUrMeUZCuZJXwwwk="
|
||||
},
|
||||
{
|
||||
@@ -350,6 +535,46 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-KfRiqonLl2RXWEGKXwjUwagrc1yW569JgX0WqpuQgVA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.1/clojure-1.12.1.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-h+7qnjVdhsBFc4r0lNaD4J6RTLBGeuQNRqZrh6NsctQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.1/clojure-1.12.1.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-JUvpyKuMzDArR9fFaj/KEUl+WcMFvxX6YFTD3/TrkZ0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.2/clojure-1.12.2.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-pYv4B+zv7K6iIri4tH4UNo7o4yy0VAs//v/4yglTSA0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.2/clojure-1.12.2.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-55suCRfnPnPCX7N5PzFV+PD4jYAvUMJf1Sl3l3rDQiA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.3/clojure-1.12.3.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-yyoaPbHCzXbvT6SlRdWmXxCxtIt/dnLwoQn1R28FcWY="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.3/clojure-1.12.3.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-q2CmyyuMxXyG21ECte4p8hWsg8/20wEblV+fxb5dAZ0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.4/clojure-1.12.4.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-S4Hpum2jjEXZzFgCPGdAYrjJ8HFPM/8A3tIuapSdoXc="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/clojure/1.12.4/clojure-1.12.4.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-xRh5Bi5B/58hr6DkCbGZ/+nyo8aucizf7F/Z26BeQXI="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/core.match/1.1.0/core.match-1.1.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -360,24 +585,34 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-NnHYN2UlIwq6Ah8fYmx54g86ELYrXfgXIiWJDsSv4EU="
|
||||
},
|
||||
{
|
||||
"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-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.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar",
|
||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-F3i70Ti9GFkLgFS+nZGdG+toCfhbduXGKFtn1Ad9MA4="
|
||||
},
|
||||
{
|
||||
@@ -390,6 +625,16 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-M0EOuKpz1S2Vez3G4KZfOZisBiPL2BPZDDPm5onEJCk="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/java.classpath/1.0.0/java.classpath-1.0.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-wU4OEDBKXlz9LMdC+976wfUpPuxgcML/6JA/tcf+fW8="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/java.classpath/1.0.0/java.classpath-1.0.0.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-C+AThRRX/CTENM5FU0ZD8iblwQgASGJT/Tc/LglUXig="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/java.data/1.3.113/java.data-1.3.113.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -405,9 +650,14 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-RoC9g43MuowXwlgXE0fxb1uq5rXft4Grc4K8Y4X/gAY="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/pom.contrib/0.2.2/pom.contrib-0.2.2.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-4OoifEnFw+MHVM0m/MV75+Telz/kOqXMZmdAHsXBAyM="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/pom.contrib/0.3.0/pom.contrib-0.3.0.pom",
|
||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-fxgrOypUPgV0YL+T/8XpzvasUn3xoTdqfZki6+ee8Rk="
|
||||
},
|
||||
{
|
||||
@@ -427,22 +677,22 @@
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar",
|
||||
"mvn-repo": "https://repo.maven.apache.org/maven2/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.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/",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-bY3hTDrIdXYMX/kJVi/5hzB3AxxquTnxyxOeFp/pB1g="
|
||||
},
|
||||
{
|
||||
@@ -465,6 +715,16 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-UZ45jnJMYvCsnWsZ15+P8QAdqYWD/eAb1wUrB+Ga1ow="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/tools.cli/1.1.230/tools.cli-1.1.230.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-kWYwtTmkP/RotN0BbGKFfitMtdpmhvEpdYfN1DyhAs0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/tools.cli/1.1.230/tools.cli-1.1.230.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-v7Yh5LAaW4vOEWpgcIQNzdWUnomceEaNgRtuiqqf0cc="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/clojure/tools.logging/1.3.0/tools.logging-1.3.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -485,6 +745,16 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-cGCU9H2ljugXofq5uAwxLs0nZHK85uHVRCOfFAcR2zE="
|
||||
},
|
||||
{
|
||||
"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/",
|
||||
"hash": "sha256-rvXugot8sUocWPRbn4oQ/zQMV2mSXqDvXDXR5J2SC+o="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/junit/junit-bom/5.11.0/junit-bom-5.11.0.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -530,11 +800,51 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-oLLU3iXdPWNptThQLeay5UJcKxyOM6GQKZgIS4o4EWs="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-0+9XXj5JeWeNwBvx3M5RAhSTtNEft/G+itmCh3wWocA="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-+wRqnCKUN5KLsRwtJ8i113PriiXmDL0lPZhSEN7cJoQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-aZgMA4yhsTGSZWFZFhfZwl+r/Hspgor5FZfKhXDPNf4="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-NTkEp6bCgwTQ3KyA+tMMSM2Jj22wO5PwWtbJDdQtmK0="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-parent/1.7.36/slf4j-parent-1.7.36.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-uziNN/vN083mTDzt4hg4aTIY3EUfBAQMXfNgp47X6BI="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/slf4j/slf4j-parent/1.7.7/slf4j-parent-1.7.7.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-Hf+uPOdo0FR+JhyWiYz12dGUv/1WAPWXyXUcxqc9M9Q="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/sonatype/oss/oss-parent/7/oss-parent-7.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-tR+IZ8kranIkmVV/w6H96ne9+e9XRyL+kM5DailVlFQ="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/tcrawley/dynapath/1.1.0/dynapath-1.1.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-n8eqO+Y4XaOtIqBlJvFaXTNdnonUDzm/L5oA4Lu9iug="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/tcrawley/dynapath/1.1.0/dynapath-1.1.0.pom",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-5OPOTeIWKm8U9QjB0Nv0s9tsrBk5E+kVeAhcGLesJho="
|
||||
},
|
||||
{
|
||||
"mvn-path": "org/xerial/sqlite-jdbc/3.47.1.0/sqlite-jdbc-3.47.1.0.jar",
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
@@ -545,6 +855,26 @@
|
||||
"mvn-repo": "https://repo1.maven.org/maven2/",
|
||||
"hash": "sha256-Z3XeNvNR9MdFCL/+qtZAIceVhx/ZRIXsdsPhduUwU7g="
|
||||
},
|
||||
{
|
||||
"mvn-path": "progrock/progrock/0.1.2/progrock-0.1.2.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-Aln+tbAkduswC31k5UPrVM5Kw9yuU5gxDxZCdo/VPyo="
|
||||
},
|
||||
{
|
||||
"mvn-path": "progrock/progrock/0.1.2/progrock-0.1.2.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-6rULcjyeeEkPWDy5n7HUa8KA/xH9X4Ujub7XamTq8CM="
|
||||
},
|
||||
{
|
||||
"mvn-path": "riddley/riddley/0.1.12/riddley-0.1.12.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-OY9h+kgluPhskWrlgMfhM7fEd9C3Kn07KY04EDJ0C64="
|
||||
},
|
||||
{
|
||||
"mvn-path": "riddley/riddley/0.1.12/riddley-0.1.12.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-At+3ryDvgcJTZQVfYCjoscwpBdCyaLuJzEKM2nIwo2U="
|
||||
},
|
||||
{
|
||||
"mvn-path": "ring/ring-anti-forgery/1.4.0/ring-anti-forgery-1.4.0.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
@@ -610,6 +940,16 @@
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-HHmMD/cPNu7HwRubeajXYOBDYK1y9x9F9KhRytq2AQw="
|
||||
},
|
||||
{
|
||||
"mvn-path": "slingshot/slingshot/0.12.2/slingshot-0.12.2.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-porCK/LqPNVM4023D9aYRNYx71SfZFDCeMMOb3nfY/M="
|
||||
},
|
||||
{
|
||||
"mvn-path": "slingshot/slingshot/0.12.2/slingshot-0.12.2.pom",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
"hash": "sha256-SrxOK5ppxzvTc+gy0/AOWQZ4Q/+DUe/V7rsfOCTbnFE="
|
||||
},
|
||||
{
|
||||
"mvn-path": "tigris/tigris/0.1.2/tigris-0.1.2.jar",
|
||||
"mvn-repo": "https://repo.clojars.org/",
|
||||
|
||||
@@ -7,5 +7,10 @@
|
||||
{: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"}}
|
||||
:paths ["src" "resources" "test"]}
|
||||
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"}}
|
||||
:paths ["src" "resources" "test"]
|
||||
:aliases
|
||||
{:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:main-opts ["-m" "kaocha.runner"]}}}
|
||||
|
||||
1
doerg/doerg-temml-worker/README.org
Normal file
1
doerg/doerg-temml-worker/README.org
Normal file
@@ -0,0 +1 @@
|
||||
#+title: doerg-temml-worker
|
||||
15
doerg/doerg-temml-worker/default.nix
Normal file
15
doerg/doerg-temml-worker/default.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ buildNpmPackage
|
||||
, importNpmLock
|
||||
, makeWrapper
|
||||
, ibm-plex
|
||||
, callPackage
|
||||
}:
|
||||
|
||||
buildNpmPackage {
|
||||
pname = "doerg-temml-worker";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
dontNpmBuild = true;
|
||||
}
|
||||
6
doerg/doerg-temml-worker/deps.edn
Normal file
6
doerg/doerg-temml-worker/deps.edn
Normal file
@@ -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 ["." "classes"]}
|
||||
5
doerg/doerg-temml-worker/deserialise.clj
Normal file
5
doerg/doerg-temml-worker/deserialise.clj
Normal file
@@ -0,0 +1,5 @@
|
||||
(ns deserialise
|
||||
(:require [clj-cbor.core :as cbor]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(prn (cbor/decode cbor/default-codec System/in :eof))
|
||||
55
doerg/doerg-temml-worker/index.js
Executable file
55
doerg/doerg-temml-worker/index.js
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const commandLineArgs = require ("command-line-args")
|
||||
const temml = require ("temml")
|
||||
const fs = require ("node:fs")
|
||||
const path = require ("node:path")
|
||||
const { DecoderStream, EncoderStream } = require ("cbor-x")
|
||||
const { Transform } = require('node:stream')
|
||||
|
||||
const cli_spec =
|
||||
[ { name: "preamble" }
|
||||
]
|
||||
|
||||
function load_preambles (preamble) {
|
||||
const data = fs.readFileSync (preamble, "utf8") .toString ()
|
||||
return temml.definePreamble (data)
|
||||
}
|
||||
|
||||
let macros = {}
|
||||
|
||||
function is_render_command (cmd) {
|
||||
return cmd instanceof Array
|
||||
&& cmd.length === 1
|
||||
&& typeof cmd[0] === "string"
|
||||
}
|
||||
|
||||
function do_command (cmd) {
|
||||
try {
|
||||
if (typeof cmd === "string") {
|
||||
return temml.renderToString (cmd, {macros})
|
||||
} else if (is_render_command (cmd)) {
|
||||
return temml.renderToString (cmd[0], {displayMode: true,macros})
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
} catch (e) {
|
||||
console.error (e)
|
||||
return {type: "error", error: e}
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
const options = commandLineArgs (cli_spec)
|
||||
macros = load_preambles (options.preamble)
|
||||
const decoder = new DecoderStream ()
|
||||
const encoder = new EncoderStream ()
|
||||
process.stdin.pipe (decoder)
|
||||
const command_responses = decoder.map (do_command)
|
||||
decoder
|
||||
.map (do_command)
|
||||
.pipe (encoder)
|
||||
.pipe (process.stdout)
|
||||
}
|
||||
|
||||
main ()
|
||||
227
doerg/doerg-temml-worker/package-lock.json
generated
Normal file
227
doerg/doerg-temml-worker/package-lock.json
generated
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"name": "doerg-tex",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "doerg-tex",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"cbor-x": "^1.6.0",
|
||||
"command-line-args": "^6.0.1",
|
||||
"temml": "^0.13.1"
|
||||
},
|
||||
"bin": {
|
||||
"doerg-tex": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz",
|
||||
"integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-darwin-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-arm": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz",
|
||||
"integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-arm64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz",
|
||||
"integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-win32-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/array-back": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
|
||||
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/cbor-extract": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
|
||||
"integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build-optional-packages": "5.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"download-cbor-prebuilds": "bin/download-prebuilds.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-arm": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-x64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-win32-x64": "2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cbor-x": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
|
||||
"integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"cbor-extract": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/command-line-args": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz",
|
||||
"integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"array-back": "^6.2.2",
|
||||
"find-replace": "^5.0.2",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"typical": "^7.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-replace": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz",
|
||||
"integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-gyp-build-optional-packages": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
|
||||
"integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-gyp-build-optional-packages": "bin.js",
|
||||
"node-gyp-build-optional-packages-optional": "optional.js",
|
||||
"node-gyp-build-optional-packages-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/temml": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/temml/-/temml-0.13.1.tgz",
|
||||
"integrity": "sha512-/fL1utq8QUD9YpcLeZHPRnp9Cbzbexq5hZl5uSBhf8mNYiKkcS4eYbLidDB+/nF8C+RHAcBQbKw2bKoS83mz1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typical": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
|
||||
"integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
doerg/doerg-temml-worker/package.json
Normal file
6
doerg/doerg-temml-worker/package.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{"dependencies":{"temml":"^0.13.1"
|
||||
,"command-line-args":"^6.0.1"
|
||||
,"cbor-x":"^1.6.0"}
|
||||
,"name":"doerg-temml-worker"
|
||||
,"version":"0.1.0"
|
||||
,"bin":{"doerg-temml-worker":"index.js"}}
|
||||
19
doerg/doerg-temml-worker/serialise.clj
Normal file
19
doerg/doerg-temml-worker/serialise.clj
Normal file
@@ -0,0 +1,19 @@
|
||||
(ns serialise
|
||||
(: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 "\\naturalto")
|
||||
|
||||
(w "\\ifxetex blah \\fi")
|
||||
|
||||
#_#_#_
|
||||
(w "c = \\sqrt{a^2 + y^2}")
|
||||
(w "c = \\sqrt{a^ + y^2")
|
||||
(w "\\alpha^\\beta")
|
||||
43
doerg/our-tex.nix
Normal file
43
doerg/our-tex.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{ texlive
|
||||
, syd-plex-latex
|
||||
}:
|
||||
|
||||
texlive.combine {
|
||||
inherit syd-plex-latex;
|
||||
inherit (texlive)
|
||||
scheme-basic
|
||||
xkeyval
|
||||
changepage
|
||||
fancyhdr
|
||||
geometry
|
||||
natbib
|
||||
paralist
|
||||
placeins
|
||||
ragged2e
|
||||
setspace
|
||||
textcase
|
||||
titlesec
|
||||
xcolor
|
||||
hardwrap
|
||||
xifthen
|
||||
catchfile
|
||||
fontspec
|
||||
latexmk
|
||||
xetex
|
||||
dvisvgm dvipng wrapfig # For Org-mode previews/export.
|
||||
amsmath # Essential for mathematics.
|
||||
spath3 # TikZ dependency?
|
||||
ulem hyperref
|
||||
capt-of
|
||||
pgf # Includes TikZ.
|
||||
tikz-cd # Commutative diagrams w/ TikZ.
|
||||
quiver # Commutative diagrams w/ TikZ & q.uiver.app.
|
||||
bookmark
|
||||
metafont
|
||||
preview # For new-gen org-latex-preview.
|
||||
mylatexformat # For new-gen org-latex-preview.
|
||||
collection-fontsrecommended # Essential fonts.
|
||||
etoolbox # For Org-mode exports.
|
||||
caption
|
||||
;
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
{ mkCljBin
|
||||
, callPackage
|
||||
, lib
|
||||
, doerg-parser
|
||||
, doerg-temml-worker
|
||||
, ibm-plex-web
|
||||
, fake-git
|
||||
, our-tex ? callPackage ./our-tex.nix {}
|
||||
, makeWrapper
|
||||
, breakpointHook
|
||||
}:
|
||||
|
||||
let
|
||||
# mkCljBin sans fake-git.
|
||||
# mkCljBin sans fake-git. We don't need it, and I don't want it in
|
||||
# my dev shell.
|
||||
mkCljBin' = args: (mkCljBin args).overrideAttrs (final: prev: {
|
||||
nativeBuildInputs =
|
||||
builtins.filter
|
||||
@@ -18,6 +24,11 @@ let
|
||||
plex = ibm-plex-web.override {
|
||||
families = [ "math" "serif" "sans" "sans-kr" ];
|
||||
};
|
||||
bin-path = lib.makeBinPath [
|
||||
doerg-parser
|
||||
our-tex
|
||||
doerg-temml-worker
|
||||
];
|
||||
in mkCljBin' {
|
||||
name = "net.deertopia/doerg";
|
||||
version = "0.1.0";
|
||||
@@ -26,9 +37,27 @@ in mkCljBin' {
|
||||
main-ns = "net.deertopia.doerg.main";
|
||||
nativeBuildInputs = [
|
||||
plex
|
||||
makeWrapper
|
||||
breakpointHook
|
||||
];
|
||||
buildInputs = [
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
plex
|
||||
our-tex
|
||||
];
|
||||
nativeCheckInputs = [
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
plex
|
||||
our-tex
|
||||
];
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
clojure -M:test
|
||||
'';
|
||||
postInstall = ''
|
||||
wrapProgram $out/bin/doerg \
|
||||
--prefix PATH : ${bin-path}
|
||||
'';
|
||||
}
|
||||
|
||||
343
doerg/resources/net/deertopia/doerg/Temml-Plex.css
Normal file
343
doerg/resources/net/deertopia/doerg/Temml-Plex.css
Normal file
@@ -0,0 +1,343 @@
|
||||
/* Based on Temml-local.css. */
|
||||
math {
|
||||
font-family: "IBM Plex Math", "Cambria Math", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: normal;
|
||||
font-size-adjust: none;
|
||||
text-indent: 0;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
/* Prevent Firefox from omitting the dot on i or j. */
|
||||
font-feature-settings: "dtls" off;
|
||||
}
|
||||
|
||||
math * {
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
/* display: block is necessary in Firefox and Safari.
|
||||
* Not in Chromium, which recognizes display: "block math" written inline. */
|
||||
math.tml-display {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
*.mathcal {
|
||||
/* NotoSans */
|
||||
font-feature-settings: 'ss01';
|
||||
}
|
||||
|
||||
math .mathscr {
|
||||
font-family: "IBM Plex Math";
|
||||
}
|
||||
|
||||
mo.tml-prime {
|
||||
font-family: "IBM Plex Math";
|
||||
}
|
||||
|
||||
/* Cramped superscripts in WebKit */
|
||||
mfrac > :nth-child(2),
|
||||
msqrt,
|
||||
mover > :first-child {
|
||||
math-shift: compact
|
||||
}
|
||||
|
||||
.menclose {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0.5ex 0ex;
|
||||
}
|
||||
.tml-cancelto {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0.5ex 0ex;
|
||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='currentColor' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%' y1='100%' stroke='currentColor' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
|
||||
}
|
||||
|
||||
@supports (-moz-appearance: none) {
|
||||
/* \vec w/o italic correction for Firefox */
|
||||
.tml-vec {
|
||||
transform: scale(0.75)
|
||||
}
|
||||
/* Fix \cancelto in Firefox */
|
||||
.ff-narrow {
|
||||
width: 0em;
|
||||
}
|
||||
.ff-nudge-left {
|
||||
margin-left: -0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@supports (not (-moz-appearance: none)) {
|
||||
/* Chromium and WebKit */
|
||||
/* prime vertical alignment */
|
||||
mo.tml-prime {
|
||||
font-family: "IBM Plex Math";
|
||||
}
|
||||
/* Italic correction on superscripts */
|
||||
.tml-sml-pad {
|
||||
padding-left: 0.05em;
|
||||
}
|
||||
.tml-med-pad {
|
||||
padding-left: 0.10em;
|
||||
}
|
||||
.tml-lrg-pad {
|
||||
padding-left: 0.15em;
|
||||
}
|
||||
}
|
||||
|
||||
@supports (-webkit-backdrop-filter: blur(1px)) {
|
||||
/* WebKit vertical & italic correction on accents */
|
||||
.wbk-acc {
|
||||
/* lower by x-height distance */
|
||||
transform: translate(0em, 0.431em);
|
||||
}
|
||||
.wbk-sml {
|
||||
transform: translate(0.07em, 0);
|
||||
}
|
||||
.wbk-sml-acc {
|
||||
transform: translate(0.07em, 0.431em);
|
||||
}
|
||||
.wbk-sml-vec {
|
||||
transform: scale(0.75) translate(0.07em, 0);
|
||||
}
|
||||
.wbk-med {
|
||||
transform: translate(0.14em, 0);
|
||||
}
|
||||
.wbk-med-acc {
|
||||
transform: translate(0.14em, 0.431em);
|
||||
}
|
||||
.wbk-med-vec {
|
||||
transform: scale(0.75) translate(0.14em, 0);
|
||||
}
|
||||
.wbk-lrg {
|
||||
transform: translate(0.21em, 0);
|
||||
}
|
||||
.wbk-lrg-acc {
|
||||
transform: translate(0.21em, 0.431em);
|
||||
}
|
||||
.wbk-lrg-vec {
|
||||
transform: scale(0.75) translate(0.21em, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* \cancel & \phase use background images. Get them to print. */
|
||||
menclose {
|
||||
-webkit-print-color-adjust: exact; /* Chrome & Edge */
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
/* Array cell justification in Firefox & WebKit */
|
||||
.tml-right {
|
||||
text-align: right;
|
||||
}
|
||||
.tml-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* For CD labels that grow to the left in Firefox and WebKit */
|
||||
.tml-shift-left { margin-left:-200% }
|
||||
|
||||
/* Styles for Chromium only */
|
||||
@supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
|
||||
/* Italic correction on accents */
|
||||
.chr-sml {
|
||||
transform: translate(0.07em, 0)
|
||||
}
|
||||
.chr-sml-vec {
|
||||
transform: scale(0.75) translate(0.07em, 0)
|
||||
}
|
||||
.chr-med {
|
||||
transform: translate(0.14em, 0)
|
||||
}
|
||||
.chr-med-vec {
|
||||
transform: scale(0.75) translate(0.14em, 0)
|
||||
}
|
||||
.chr-lrg {
|
||||
transform: translate(0.21em, 0)
|
||||
}
|
||||
.chr-lrg-vec {
|
||||
transform: scale(0.75) translate(0.21em, 0)
|
||||
}
|
||||
|
||||
/* For CD labels that grow to the left */
|
||||
.tml-shift-left { margin-left:-100% }
|
||||
|
||||
/* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */
|
||||
/* So use styles. */
|
||||
menclose {
|
||||
position: relative;
|
||||
padding: 0.5ex 0ex;
|
||||
}
|
||||
|
||||
.tml-overline {
|
||||
padding: 0.1em 0 0 0;
|
||||
border-top: 0.065em solid;
|
||||
}
|
||||
|
||||
.tml-underline {
|
||||
padding: 0 0 0.1em 0;
|
||||
border-bottom: 0.065em solid;
|
||||
}
|
||||
|
||||
.tml-cancel {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0.5px;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: currentColor;
|
||||
}
|
||||
.upstrike {
|
||||
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
|
||||
}
|
||||
.downstrike {
|
||||
clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
|
||||
}
|
||||
.sout {
|
||||
clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
|
||||
}
|
||||
.tml-xcancel {
|
||||
background: linear-gradient(to top left,
|
||||
rgba(0,0,0,0) 0%,
|
||||
rgba(0,0,0,0) calc(50% - 0.06em),
|
||||
rgba(0,0,0,1) 50%,
|
||||
rgba(0,0,0,0) calc(50% + 0.06em),
|
||||
rgba(0,0,0,0) 100%),
|
||||
linear-gradient(to top right,
|
||||
rgba(0,0,0,0) 0%,
|
||||
rgba(0,0,0,0) calc(50% - 0.06em),
|
||||
rgba(0,0,0,1) 50%,
|
||||
rgba(0,0,0,0) calc(50% + 0.06em),
|
||||
rgba(0,0,0,0) 100%)
|
||||
}
|
||||
|
||||
.longdiv-top {
|
||||
border-top: 0.067em solid;
|
||||
padding: 0.1em 0.2em 0.2em 0.433em;
|
||||
}
|
||||
.longdiv-arc {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0.1em;
|
||||
left: -0.4em;
|
||||
width: 0.7em;
|
||||
border: 0.067em solid;
|
||||
transform: translateY(-0.067em);
|
||||
border-radius: 70%;
|
||||
clip-path: inset(0 0 0 0.4em);
|
||||
box-sizing: border-box;}
|
||||
.menclose {display: inline-block;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.phasor-bottom {
|
||||
border-bottom: 0.067em solid;
|
||||
padding: 0.2em 0.2em 0.1em 0.6em;
|
||||
}
|
||||
.phasor-angle {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0.5px;
|
||||
bottom: -0.04em;
|
||||
height: 100%;
|
||||
aspect-ratio: 0.5;
|
||||
background-color: currentColor;
|
||||
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
|
||||
}
|
||||
|
||||
.tml-fbox {
|
||||
padding: 3pt;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.circle-pad {
|
||||
padding: 0.267em;
|
||||
}
|
||||
.textcircle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
border: 0.067em solid;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.actuarial {
|
||||
padding: 0.03889em 0.03889em 0 0.03889em;
|
||||
border-width: 0.08em 0.08em 0em 0em;
|
||||
border-style: solid;
|
||||
margin-right: 0.03889em;
|
||||
}
|
||||
|
||||
/* Stretch \widetilde */
|
||||
.tml-crooked-2 {
|
||||
transform: scale(2.0, 1.1)
|
||||
}
|
||||
.tml-crooked-3 {
|
||||
transform: scale(3.0, 1.3)
|
||||
}
|
||||
.tml-crooked-4 {
|
||||
transform: scale(4.0, 1.4)
|
||||
}
|
||||
/* set array cell justification */
|
||||
.tml-right {
|
||||
text-align: -webkit-right;
|
||||
}
|
||||
.tml-left {
|
||||
text-align: -webkit-left;
|
||||
}
|
||||
}
|
||||
|
||||
.special-fraction {
|
||||
font-family: "IBM Plex Math", 'STIX TWO', 'Times New Roman', Times, Tinos, serif;
|
||||
}
|
||||
|
||||
/* flex-wrap for line-breaking in Chromium */
|
||||
math {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
}
|
||||
math > mrow {
|
||||
padding: 0.5ex 0ex;
|
||||
}
|
||||
|
||||
/* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */
|
||||
/* We adjust for jot and small */
|
||||
mtable.tml-jot mtd {
|
||||
padding-top: 0.7ex;
|
||||
padding-bottom: 0.7ex;
|
||||
}
|
||||
mtable.tml-small mtd {
|
||||
padding-top: 0.35ex;
|
||||
padding-bottom: 0.35ex;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
@-moz-document url-prefix() {
|
||||
/* Avoid flex-wrap */
|
||||
math { display: inline; }
|
||||
math > mrow { padding: 0 }
|
||||
/* Adjust Firefox spacing between array rows */
|
||||
mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
|
||||
mtable.tml-jot mtd { padding-top: 0.2ex; padding-bottom: 0.ex; }
|
||||
}
|
||||
|
||||
/* AMS environment auto-numbering via CSS counter. */
|
||||
.tml-eqn::before {
|
||||
counter-increment: tmlEqnNo;
|
||||
content: "(" counter(tmlEqnNo) ")";
|
||||
}
|
||||
|
||||
body {
|
||||
counter-reset: tmlEqnNo;
|
||||
}
|
||||
154
doerg/resources/net/deertopia/doerg/prelude.tex
Normal file
154
doerg/resources/net/deertopia/doerg/prelude.tex
Normal file
@@ -0,0 +1,154 @@
|
||||
% Of the highest importance:
|
||||
\renewcommand{\phi}{\varphi}
|
||||
\renewcommand{\epsilon}{\varepsilon}
|
||||
|
||||
% Saner abbreviations for font faces (take an argument rather than
|
||||
% applying to the current context).
|
||||
\renewcommand{\rm}[1]{\mathrm{#1}}
|
||||
\newcommand{\bb}[1]{\mathbb{#1}}
|
||||
\renewcommand{\bf}[1]{\mathbf{#1}}
|
||||
|
||||
% \cA … \cZ
|
||||
\newcommand{\cA}{\mathcal{A}}
|
||||
\newcommand{\cB}{\mathcal{B}}
|
||||
\newcommand{\cC}{\mathcal{C}}
|
||||
\newcommand{\cD}{\mathcal{D}}
|
||||
\newcommand{\cE}{\mathcal{E}}
|
||||
\newcommand{\cF}{\mathcal{F}}
|
||||
\newcommand{\cG}{\mathcal{G}}
|
||||
\newcommand{\cH}{\mathcal{H}}
|
||||
\newcommand{\cI}{\mathcal{I}}
|
||||
\newcommand{\cJ}{\mathcal{J}}
|
||||
\newcommand{\cK}{\mathcal{K}}
|
||||
\newcommand{\cL}{\mathcal{L}}
|
||||
\newcommand{\cM}{\mathcal{M}}
|
||||
\newcommand{\cN}{\mathcal{N}}
|
||||
\newcommand{\cO}{\mathcal{O}}
|
||||
\newcommand{\cP}{\mathcal{P}}
|
||||
\newcommand{\cQ}{\mathcal{Q}}
|
||||
\newcommand{\cR}{\mathcal{R}}
|
||||
\newcommand{\cS}{\mathcal{S}}
|
||||
\newcommand{\cT}{\mathcal{T}}
|
||||
\newcommand{\cU}{\mathcal{U}}
|
||||
\newcommand{\cV}{\mathcal{V}}
|
||||
\newcommand{\cW}{\mathcal{W}}
|
||||
\newcommand{\cX}{\mathcal{X}}
|
||||
\newcommand{\cY}{\mathcal{Y}}
|
||||
\newcommand{\cZ}{\mathcal{Z}}
|
||||
|
||||
% \bA … \bZ
|
||||
\newcommand{\bA}{\mathbb{A}}
|
||||
\newcommand{\bB}{\mathbb{B}}
|
||||
\newcommand{\bC}{\mathbb{C}}
|
||||
\newcommand{\bD}{\mathbb{D}}
|
||||
\newcommand{\bE}{\mathbb{E}}
|
||||
\newcommand{\bF}{\mathbb{F}}
|
||||
\newcommand{\bG}{\mathbb{G}}
|
||||
\newcommand{\bH}{\mathbb{H}}
|
||||
\newcommand{\bI}{\mathbb{I}}
|
||||
\newcommand{\bJ}{\mathbb{J}}
|
||||
\newcommand{\bK}{\mathbb{K}}
|
||||
\newcommand{\bL}{\mathbb{L}}
|
||||
\newcommand{\bM}{\mathbb{M}}
|
||||
\newcommand{\bN}{\mathbb{N}}
|
||||
\newcommand{\bO}{\mathbb{O}}
|
||||
\newcommand{\bP}{\mathbb{P}}
|
||||
\newcommand{\bQ}{\mathbb{Q}}
|
||||
\newcommand{\bR}{\mathbb{R}}
|
||||
\newcommand{\bS}{\mathbb{S}}
|
||||
\newcommand{\bT}{\mathbb{T}}
|
||||
\newcommand{\bU}{\mathbb{U}}
|
||||
\newcommand{\bV}{\mathbb{V}}
|
||||
\newcommand{\bW}{\mathbb{W}}
|
||||
\newcommand{\bX}{\mathbb{X}}
|
||||
\newcommand{\bY}{\mathbb{Y}}
|
||||
\newcommand{\bZ}{\mathbb{Z}}
|
||||
|
||||
% Notation for lambda abstractions and function application. $~$
|
||||
% is the spacing that should be used between arguments.
|
||||
\newcommand{\lam}[2]{\lambda #1.\ #2}
|
||||
|
||||
% Notation for paths, the interval, and its operations.
|
||||
\newcommand{\PathP}[3]{\rm{PathP}~ {#1}~ {#2}~ {#3}}
|
||||
\newcommand{\Path}[3]{\rm{Path}~ {#1}~ {#2}~ {#3}}
|
||||
\newcommand{\Square}[4]{\rm{Square}~ {#1}~ {#2}~ {#3}~ {#4}}
|
||||
\newcommand{\ap}[2]{\rm{ap}~ {#1}~ {#2}}
|
||||
|
||||
\newcommand{\subst}{\operatorname{subst}}
|
||||
\newcommand{\ua}{\operatorname{ua}}
|
||||
|
||||
\newcommand{\iZ}{\rm{i0}}
|
||||
\newcommand{\iO}{\rm{i1}}
|
||||
|
||||
\newcommand{\ineg}{\lnot}
|
||||
\newcommand{\imin}{\land}
|
||||
\newcommand{\imax}{\lor}
|
||||
|
||||
\newcommand{\transport}[2]{\rm{transport}~ #1~ #2}
|
||||
\newcommand{\transp}[3]{\rm{transp}~ #1~ #2~ #3}
|
||||
\newcommand{\Partial}[2]{\rm{Partial}~ #1~ #2}
|
||||
\newcommand{\dcomp}{\mathrel{\cdot\cdot}}
|
||||
\newcommand{\Extn}[2]{{#1}[#2]}
|
||||
|
||||
\newcommand{\thecat}[1]{\mathbf{#1}} % Names of "concrete" categories
|
||||
\newcommand{\ca}[1]{\mathcal{#1}} % Names of variable categories
|
||||
|
||||
%% \newcommand{\knowncat}[1]{\newcommand{\csname #1\endcsname}{\thecat{#1}}}
|
||||
%% \newcommand{\knownbicat}[1]{\newcommand{\csname #1\endcsname}{\thebicat{#1}}}
|
||||
|
||||
\newcommand{\ty}{\rm{Type}}
|
||||
%% \newcommand{\set}{\rm{Set}}
|
||||
\newcommand{\prop}{\rm{Prop}}
|
||||
|
||||
%% \DeclareMathOperator{\id}{id}
|
||||
%% \DeclareMathOperator{\Id}{Id}
|
||||
|
||||
%% \knowncat{Sets}
|
||||
%% \knowncat{Ab}
|
||||
%% \knowncat{Graphs}
|
||||
%% \knowncat{MarkedGraphs}
|
||||
%% \knowncat{Props}
|
||||
%% \knowncat{FinSets}
|
||||
%% \knowncat{Rings}
|
||||
%% \knowncat{Grp}
|
||||
%% \knowncat{Rel}
|
||||
%% \knowncat{Par}
|
||||
%% \knowncat{Pos}
|
||||
|
||||
\renewcommand{\Set}{\thecat{Set}}
|
||||
|
||||
% "Postfix" operators that have a subscript and are annoying to write
|
||||
% out:
|
||||
\newcommand{\inv}{^{-1}}
|
||||
\renewcommand{\op}{^{\rm{op}}}
|
||||
|
||||
\newcommand{\eps}{\varepsilon}
|
||||
|
||||
\newcommand{\B}[1]{\mathbf{B} #1}
|
||||
\newcommand{\point}[1]{\bullet_{#1}}
|
||||
\newcommand{\List}[1]{\operatorname{List}(#1)}
|
||||
|
||||
\renewcommand{\hom}{\mathbf{Hom}}
|
||||
|
||||
\newcommand{\refl}{\mathrm{refl}}
|
||||
|
||||
\DeclareMathOperator{\isiso}{is-iso}
|
||||
\DeclareMathOperator{\isequiv}{is-equiv}
|
||||
|
||||
% Relations
|
||||
\newcommand{\pathto}{\equiv}
|
||||
\newcommand{\is}{\pathto}
|
||||
\newcommand{\definedto}{≔}
|
||||
\newcommand{\equivto}{\simeq}
|
||||
\newcommand{\homotopicto}{\sim}
|
||||
\newcommand{\homotopyto}{\sim}
|
||||
\newcommand{\naturalto}{\Rightarrow}
|
||||
\newcommand{\isoto}{\cong}
|
||||
\newcommand{\monicto}{\rightarrowtail}
|
||||
\newcommand{\epicto}{\twoheadrightarrow}
|
||||
|
||||
% Category names
|
||||
\newcommand{\C}[1]{\mathbf{#1}}
|
||||
|
||||
\newcommand{\homset}[3]{{{#1} \left[ {#2} \to {#3} \right]}}
|
||||
\newcommand{\horizontalcompose}{\ast}
|
||||
11
doerg/resources/net/deertopia/doerg/preview-template.tex
Normal file
11
doerg/resources/net/deertopia/doerg/preview-template.tex
Normal file
@@ -0,0 +1,11 @@
|
||||
\documentclass{article}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[active,tightpage,auctex,dvips]{preview}
|
||||
\usepackage{fontspec}
|
||||
\usepackage{ifxetex}
|
||||
\usepackage{syd-plex}
|
||||
|
||||
\begin{document}
|
||||
\setlength\abovedisplayskip{0pt}
|
||||
% {{contents}}
|
||||
\end{document}
|
||||
@@ -105,8 +105,8 @@ p,
|
||||
dl,
|
||||
ol,
|
||||
ul {
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
@@ -219,7 +219,7 @@ img {
|
||||
}
|
||||
|
||||
.sidenote,
|
||||
.margin-note {
|
||||
.marginnote {
|
||||
float: right;
|
||||
clear: right;
|
||||
margin-right: -60%;
|
||||
@@ -542,3 +542,17 @@ figure.fullwidth figcaption {
|
||||
; max-width: 55%
|
||||
; font-size: 1.5rem
|
||||
}
|
||||
|
||||
.latex-fragment
|
||||
{ fill: currentColor
|
||||
}
|
||||
|
||||
.latex-fragment.display-math
|
||||
{ display: block
|
||||
; width: 55%
|
||||
/* Center it — do we want to do that? */
|
||||
; align-items: center
|
||||
; justify-content: center
|
||||
; display: flex
|
||||
; max-width: 55%
|
||||
}
|
||||
|
||||
125
doerg/src/net/deertopia/doerg/common.clj
Normal file
125
doerg/src/net/deertopia/doerg/common.clj
Normal file
@@ -0,0 +1,125 @@
|
||||
(ns net.deertopia.doerg.common
|
||||
(:require [babashka.process :as p]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[clojure.java.io :as io])
|
||||
(:import (java.io FilterInputStream StringWriter InputStream
|
||||
OutputStream PrintStream ByteArrayOutputStream
|
||||
ByteArrayInputStream FilterOutputStream)
|
||||
(java.nio.charset StandardCharsets)))
|
||||
|
||||
(defn deref-with-timeout [process ms]
|
||||
(let [p (promise)
|
||||
process-future (future (deliver p @process))
|
||||
timeout-future (future (Thread/sleep ms)
|
||||
(future-cancel process-future)
|
||||
(p/destroy-tree process)
|
||||
(deliver p ::timed-out))]
|
||||
(if (= @p ::timed-out)
|
||||
(throw (ex-info (format "external command `%s' timed out after %.2fs."
|
||||
(str/join " " (:cmd process))
|
||||
(/ (double ms) 1000))
|
||||
{:process process
|
||||
:timed-out-after-milliseconds ms}))
|
||||
@p)))
|
||||
|
||||
(defn tee-input-stream
|
||||
"Return a wrapped `InputStream` that writes all bytes read from
|
||||
input-stream to sink, à la the UNIX command tee(1)."
|
||||
[input-stream sink]
|
||||
(proxy [FilterInputStream] [input-stream]
|
||||
(read
|
||||
([]
|
||||
(let [c (proxy-super read)]
|
||||
(when (not= c -1)
|
||||
(.write sink c))
|
||||
c))
|
||||
([^bytes bs]
|
||||
(let [n (proxy-super read bs)]
|
||||
(when (not= n -1)
|
||||
(.write sink bs 0 n))
|
||||
n))
|
||||
([^bytes bs off len]
|
||||
(let [n (proxy-super read bs off len)]
|
||||
(when (not= n -1)
|
||||
(.write sink bs off n))
|
||||
n)))
|
||||
(close []
|
||||
(try (proxy-super close)
|
||||
(finally (.close sink))))))
|
||||
|
||||
(defn tee-output-stream
|
||||
"Return a wrapped `OutputStream` that writes all bytes written to
|
||||
output-stream to sink, à la the UNIX command tee(1)."
|
||||
[output-stream sink]
|
||||
(proxy [FilterOutputStream] [output-stream]
|
||||
(write
|
||||
([bs-or-b]
|
||||
(proxy-super write bs-or-b)
|
||||
(.write sink bs-or-b))
|
||||
([^bytes bs off len]
|
||||
(proxy-super write bs off len)
|
||||
(.write sink bs off len)))
|
||||
(close []
|
||||
(try (proxy-super close)
|
||||
(finally (.close sink))))))
|
||||
|
||||
#_
|
||||
(defn hook-input-stream [input-stream hook]
|
||||
(proxy [FilterInputStream] [input-stream]
|
||||
(read
|
||||
([]
|
||||
(let [c (proxy-super read)]
|
||||
(when (not= c -1)
|
||||
(hook (byte-array [c])))
|
||||
c))
|
||||
([^bytes bs]
|
||||
(let [n (proxy-super read bs)]
|
||||
(when (not= n -1)
|
||||
(let [bs* (byte-array n 0)]
|
||||
(System/arraycopy bs 0 bs* 0 n)
|
||||
(hook bs*)))
|
||||
n))
|
||||
([^bytes bs off len]
|
||||
(let [n (proxy-super read bs off len)]
|
||||
(when (not= n -1)
|
||||
(.write sink bs off n))
|
||||
n)))
|
||||
(close []
|
||||
(try (proxy-super close)
|
||||
(finally (.close sink))))))
|
||||
|
||||
(comment
|
||||
(with-open [sink (ByteArrayOutputStream.)
|
||||
out (ByteArrayOutputStream.)
|
||||
in (ByteArrayInputStream. (.getBytes "hello worms"))]
|
||||
(io/copy (tee-input-stream in sink) out)
|
||||
(def the-out out)
|
||||
(def the-sink sink)
|
||||
{:out out
|
||||
:sink sink})
|
||||
(with-open [sink (l/log-stream :info "blah")
|
||||
out (ByteArrayOutputStream.)
|
||||
in (ByteArrayInputStream. (.getBytes "hello worms"))]
|
||||
(io/copy (tee-input-stream in sink) out)
|
||||
(def the-out out)
|
||||
(def the-sink sink)
|
||||
{:out out
|
||||
:sink sink}))
|
||||
|
||||
(comment
|
||||
(let [out (ByteArrayOutputStream.)]
|
||||
(p/shell {:out (tee-output-stream
|
||||
out (l/log-stream :info "blah"))}
|
||||
"echo" "hello\n" "worms")
|
||||
(.toString out)))
|
||||
|
||||
(defn invoke [opts & cmd]
|
||||
(l/info (str/join " " (cons "$" cmd)))
|
||||
(let [r (apply p/shell
|
||||
(merge {:continue true
|
||||
:in nil :out :string :err :string}
|
||||
opts)
|
||||
cmd)
|
||||
bin (first cmd)]
|
||||
r))
|
||||
@@ -4,16 +4,32 @@
|
||||
[spec-dict.main :refer [dict]]))
|
||||
|
||||
(s/def ::config
|
||||
(s/keys :req [::ibm-plex-web]))
|
||||
(s/keys :req [::ibm-plex-web
|
||||
::latex
|
||||
::dvisvgm]))
|
||||
|
||||
(s/def ::file
|
||||
#(or (instance? java.io.File %)
|
||||
(string? %)))
|
||||
|
||||
(def default
|
||||
{::ibm-plex-web
|
||||
(fs/file
|
||||
(or (System/getenv "IBM_PLEX_WEB")
|
||||
(some #(let [x (fs/path % "ibm-plex-web")]
|
||||
(and (fs/exists? x) x))
|
||||
(fs/split-paths (System/getenv "XDG_DATA_DIRS")))))})
|
||||
(or (System/getenv "DOERG_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"})
|
||||
|
||||
(def ^:dynamic *cfg* default)
|
||||
|
||||
(s/def ::ibm-plex-web string?)
|
||||
(s/def ::ibm-plex-web ::file)
|
||||
|
||||
(s/def ::latex ::file)
|
||||
|
||||
(s/def ::dvisvgm ::file)
|
||||
|
||||
(s/def ::doerg-temml-worker ::file)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns net.deertopia.doerg.element
|
||||
(:require [babashka.process :as p]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[clojure.string :as str]
|
||||
[clojure.zip]
|
||||
[babashka.fs :as fs]
|
||||
@@ -16,24 +17,11 @@
|
||||
|
||||
(defonce ^:private uniorg-script-path-atom (atom nil))
|
||||
|
||||
(def ^:dynamic *uniorg-timeout-after-milliseconds*
|
||||
(def ^:dynamic *uniorg-timeout-duration*
|
||||
"Number of milliseconds to wait before killing the external Uniorg
|
||||
process."
|
||||
(* 10 1000))
|
||||
|
||||
(defn deref-with-timeout [process ms]
|
||||
(let [p (promise)
|
||||
process-future (future (deliver p @process))
|
||||
timeout-future (future (Thread/sleep ms)
|
||||
(future-cancel process-future)
|
||||
(p/destroy-tree process)
|
||||
(deliver p ::timed-out))]
|
||||
(if (= @p ::timed-out)
|
||||
(throw (ex-info (format "external command `%s' timed out after %.2fs."
|
||||
(str/join " " (:cmd process))
|
||||
(/ (double ms) 1000))
|
||||
{:process process
|
||||
:timed-out-after-milliseconds ms}))
|
||||
@p)))
|
||||
|
||||
(defn- camel->kebab [s]
|
||||
(->> (str/split s #"(?<=[a-z])(?=[A-Z])")
|
||||
(map str/lower-case)
|
||||
@@ -44,7 +32,7 @@
|
||||
(let [r (-> (p/process
|
||||
{:in in :out :string}
|
||||
"doerg-parser")
|
||||
(deref-with-timeout *uniorg-timeout-after-milliseconds*))]
|
||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||
(if (zero? (:exit r))
|
||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||
|
||||
@@ -93,6 +81,13 @@
|
||||
(when-some [footnotes-headline (first (:children element))]
|
||||
(= "Footnotes" (:raw-value footnotes-headline)))))
|
||||
|
||||
(defn display-math?
|
||||
"Return truthy if `element` should be considered display math."
|
||||
[element]
|
||||
(or (of-type? element "latex-environment")
|
||||
(and (of-type? element "latex-fragment")
|
||||
(-> element :contents (str/starts-with? "\\[")))))
|
||||
|
||||
|
||||
;;; Spec
|
||||
|
||||
@@ -192,8 +187,8 @@
|
||||
parser, return a map with the following keys
|
||||
• :top-level-nodes The nodes that /should/ be at the top-level.
|
||||
• :first-section-nodes The nodes that should be wrapped in a new
|
||||
section node
|
||||
• :rest Everything else!"
|
||||
section node.
|
||||
• :rest Everything else."
|
||||
[nodes]
|
||||
(let [[of-top-level remaining-nodes]
|
||||
(->> nodes (split-with #(of-type? % "property-drawer" "keyword")))
|
||||
|
||||
@@ -31,28 +31,17 @@
|
||||
[:link {:rel "stylesheet" :type "text/css" :href href}])
|
||||
|
||||
(def ibm-plex
|
||||
(for [family ["serif" "sans-kr" "math"]]
|
||||
#_
|
||||
[:style (-> cfg/*cfg* ::cfg/ibm-plex-web
|
||||
(fs/file (format "css/ibm-plex-%s-default.min.css" family))
|
||||
slurp)]
|
||||
(external-stylesheet
|
||||
(format "ibm-plex-web/css/ibm-plex-%s-all.min.css" family))))
|
||||
(concat
|
||||
(for [family ["serif" "sans-kr" "math"]]
|
||||
(external-stylesheet
|
||||
(format "ibm-plex-web/css/ibm-plex-%s-all.min.css" family)))
|
||||
[(external-stylesheet "Temml-Plex.css")]))
|
||||
|
||||
(def deerstar
|
||||
(external-stylesheet "deerstar.css")
|
||||
#_
|
||||
[:style (slurp (io/resource "net/deertopia/doerg/deerstar.css"))])
|
||||
(external-stylesheet "deerstar.css"))
|
||||
|
||||
(def tuftesque
|
||||
(external-stylesheet "tuftesque.css")
|
||||
#_
|
||||
[:link {:rel "stylesheet"
|
||||
:type "text/css"
|
||||
:href "/resources/tuftesque.css"}]
|
||||
#_
|
||||
[:style
|
||||
(slurp (io/resource "net/deertopia/doerg/tuftesque.css"))])
|
||||
(external-stylesheet "tuftesque.css"))
|
||||
|
||||
(def head
|
||||
(list viewport charset ibm-plex deerstar tuftesque))
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
(ns net.deertopia.doerg.render
|
||||
(:require [net.deertopia.doerg.element :as element]
|
||||
[clojure.stacktrace]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[clojure.core.match :refer [match]]
|
||||
[clojure.tools.logging.readable :as lr]
|
||||
[com.rpl.specter :as sp]
|
||||
[net.deertopia.doerg.html :as doerg-html]
|
||||
[hiccup2.core :as hiccup]
|
||||
[clojure.pprint]
|
||||
[clojure.zip :as z]))
|
||||
#_
|
||||
[net.deertopia.doerg.tex :as tex]
|
||||
[net.deertopia.doerg.tex.native :as tex-native]
|
||||
[net.deertopia.doerg.tex.temml :as tex-temml]
|
||||
[clojure.zip :as z]
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
;;; Top-level API
|
||||
|
||||
@@ -37,32 +44,39 @@
|
||||
(def ^:dynamic ^:private *document-info*)
|
||||
|
||||
(declare ^:private gather-footnotes render-renderer-error
|
||||
view-children-as-seq)
|
||||
view-children-as-seq render-tex-snippets)
|
||||
|
||||
(defn org-element-recursive
|
||||
"Recursively render an Org-mode element to Hiccup."
|
||||
[e]
|
||||
(->> e
|
||||
;; gather-footnotes
|
||||
(sp/transform
|
||||
[element/postorder-walker view-children-as-seq]
|
||||
(fn [node]
|
||||
(try (org-element node)
|
||||
(catch Throwable e
|
||||
(lr/error e "Error in renderer" {:node node})
|
||||
(render-renderer-error e)))))))
|
||||
[element/postorder-walker view-children-as-seq]
|
||||
(fn [node]
|
||||
(try (org-element node)
|
||||
(catch Throwable e
|
||||
(lr/error e "Error in renderer" {:node node})
|
||||
(render-renderer-error e)))))))
|
||||
|
||||
(defn org-document
|
||||
"Recursively render an Org-mode document to Hiccup."
|
||||
[doc]
|
||||
(let [rendered (org-element-recursive (gather-footnotes doc))]
|
||||
[:html
|
||||
[:head
|
||||
[:title "org document"]
|
||||
doerg-html/head]
|
||||
[:body
|
||||
[:article
|
||||
rendered]]]))
|
||||
(tex-temml/binding-worker
|
||||
(let [rendered (-> doc gather-footnotes render-tex-snippets
|
||||
org-element-recursive)]
|
||||
[:html
|
||||
[:head
|
||||
[:title "org document"]
|
||||
doerg-html/head]
|
||||
[:body
|
||||
[:article
|
||||
rendered]]])))
|
||||
|
||||
(defn to-html
|
||||
"Read `f` with `slurp` as an Org document and return a string of
|
||||
rendered HTML."
|
||||
[f]
|
||||
(str (hiccup/html {} (-> f slurp element/read-string org-document))))
|
||||
|
||||
|
||||
;;; Further dispatching on `org-element`
|
||||
@@ -73,6 +87,9 @@
|
||||
(defmethod org-element "link" [e]
|
||||
(org-link e))
|
||||
|
||||
(defmethod org-element "special-block" [e]
|
||||
(org-special-block e))
|
||||
|
||||
|
||||
|
||||
(def view-children-as-seq
|
||||
@@ -83,17 +100,6 @@
|
||||
(sp/view #(update % :children seq))
|
||||
sp/STAY))
|
||||
|
||||
#_
|
||||
(defn- gather-footnotes [doc]
|
||||
(->> doc
|
||||
(sp/select
|
||||
[element/children-walker element/footnotes-section?
|
||||
element/children-walker
|
||||
#(element/of-type? % "footnote-definition")
|
||||
(sp/view (fn [d]
|
||||
{(:label d) d}))])
|
||||
(apply merge)))
|
||||
|
||||
(defn- contains-footnote-refs? [node]
|
||||
(some #(element/of-type? % "footnote-reference")
|
||||
(:children node)))
|
||||
@@ -130,6 +136,85 @@
|
||||
element/footnotes-section?]
|
||||
sp/NONE))))
|
||||
|
||||
(defn- collect-latex-headers [doc]
|
||||
(->> doc
|
||||
(sp/select
|
||||
[element/postorder-walker
|
||||
#(element/of-keyword-type? % "LATEX_HEADER")
|
||||
(sp/view :value)])))
|
||||
|
||||
(defn- read-and-patch-generated-svg [{:keys [file height depth]}]
|
||||
;; dvisvgm writes standalone SVG files, to which we need to make a
|
||||
;; few changes to use them inline within our HTML.
|
||||
;; • XML header: Bad syntax when embedded in an HTML doc. Remove
|
||||
;; it.
|
||||
;; • Width and height: We override these with our own values
|
||||
;; computed by `net.deertopia.doerg.tex` to ensure correct
|
||||
;; positioning relative to the surrounding text. More
|
||||
;; accurately, we remove the height and width attributes from
|
||||
;; the SVG tag, and set the new values for height and
|
||||
;; vertical-align in the style attribute
|
||||
;; • Viewbox: Must be removed entirely for correct positioning.
|
||||
(-> (slurp file)
|
||||
(str/replace-first #"<\?xml version='1.0' encoding='UTF-8'\?>\n?" "")
|
||||
(str/replace-first #" height=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first #" width=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first
|
||||
#"viewBox=['\"][^\"']+[\"']"
|
||||
(fn [s]
|
||||
(format "%s style=\"%s\""
|
||||
s
|
||||
(format "height:%.4fem;vertical-align:%.4fem;display:inline-block"
|
||||
height (- depth)))))))
|
||||
|
||||
(defn render-tex-snippets
|
||||
"Traverse doc, adorning each LaTeX node with a promise resolving to,
|
||||
optimistically, Hiccup-rendered SVG or MathML code."
|
||||
[doc]
|
||||
(let [promises (atom [])
|
||||
r (->> doc (sp/transform
|
||||
[element/postorder-walker
|
||||
#(element/of-type?
|
||||
% "latex-fragment" "latex-environment")]
|
||||
(fn [node]
|
||||
(let [p (promise)]
|
||||
(swap! promises #(conj % {:promise p :node node}))
|
||||
(assoc node ::rendered p)))))
|
||||
f (fn []
|
||||
(fs/with-temp-dir [svg-dir {:prefix "doerg-svg"}]
|
||||
(let [rendered-snippets
|
||||
(delay (->> @promises
|
||||
(map #(-> % :node :value))
|
||||
(apply tex-native/render svg-dir)))]
|
||||
(doseq [{:keys [promise node]} @promises]
|
||||
(try (let [{:keys [value]} node
|
||||
temml (tex-temml/render value)]
|
||||
(if (tex-temml/erroneous-output? temml)
|
||||
(let [tex (get @rendered-snippets value)]
|
||||
(if (:errors tex)
|
||||
(deliver promise (hiccup/raw temml))
|
||||
(->> tex
|
||||
read-and-patch-generated-svg
|
||||
hiccup/raw
|
||||
(deliver promise))))
|
||||
(deliver promise (hiccup/raw temml))))
|
||||
(catch Exception e
|
||||
(lr/error e)
|
||||
(throw e)))))))
|
||||
fut (future-call (bound-fn* f))]
|
||||
;; Time out after eight seconds. With all the LaTeX and IPC, there
|
||||
;; are so many opportunities for things to go wrong </3.
|
||||
(let [fut-res (deref fut (* 10 1000) ::timed-out)]
|
||||
(if (= fut-res ::timed-out)
|
||||
(do (future-cancel fut)
|
||||
(doseq [{:keys [promise]} @promises]
|
||||
(deliver promise ::timed-out)))
|
||||
fut-res))
|
||||
r))
|
||||
|
||||
(comment
|
||||
(render-tex-snippets doc))
|
||||
|
||||
|
||||
|
||||
(defn- render-pprint
|
||||
@@ -163,6 +248,10 @@
|
||||
:dd (apply vector :dd dds)}
|
||||
_ nil))
|
||||
|
||||
(defn- same-tag? [x y]
|
||||
(let [x* (-> x name (str/replace #"^([^\.#]).*" "$1") keyword)]
|
||||
(= x* y)))
|
||||
|
||||
;; In HTML5, </p> tags cannot be nested for… reasons. In fact, no
|
||||
;; block-level elements are allowed within paragraphs. This stupid
|
||||
;; hack works around that restriction by stripping </p> tags }:).
|
||||
@@ -170,8 +259,10 @@
|
||||
(apply concat
|
||||
(for [x elements]
|
||||
(match x
|
||||
[:p (_ :guard map?) & xs] (seq xs)
|
||||
[:p & xs] (seq xs)
|
||||
[(_ :guard #(same-tag? % :p)) (_ :guard map?) & xs]
|
||||
(seq xs)
|
||||
[(_ :guard #(same-tag? % :p)) & xs]
|
||||
(seq xs)
|
||||
_ x))))
|
||||
|
||||
|
||||
@@ -201,6 +292,18 @@
|
||||
(defmethod org-element "bold" [{:keys [children]}]
|
||||
[:b children])
|
||||
|
||||
(defmethod org-element "subscript" [{:keys [children]}]
|
||||
[:sub children])
|
||||
|
||||
(defmethod org-element "superscript" [{:keys [children]}]
|
||||
[:super children])
|
||||
|
||||
(defmethod org-element "italic" [{:keys [children]}]
|
||||
[:em children])
|
||||
|
||||
(defmethod org-element "verbatim" [{:keys [value]}]
|
||||
value)
|
||||
|
||||
(defmethod org-element "code" [{:keys [value]}]
|
||||
[:code value])
|
||||
|
||||
@@ -247,8 +350,33 @@
|
||||
(defmethod org-element "node-property" [{:keys [key value]}]
|
||||
[:tr [:th key] [:td value]])
|
||||
|
||||
(defmethod org-element "citation" [{:keys [prefix suffix children]}]
|
||||
[:div prefix children suffix])
|
||||
(defmethod org-element "citation" [{:keys [prefix suffix children] :as e}]
|
||||
;; TODO: Real citations.
|
||||
[:span "[cite:" prefix children suffix "]"])
|
||||
|
||||
(defmethod org-element "citation-reference" [{:keys [key]}]
|
||||
(str "@" key))
|
||||
|
||||
(defmethod org-element "latex-fragment" [{:keys [contents value] :as e}]
|
||||
[:span {:class (if (element/display-math? e)
|
||||
"latex-fragment display-math"
|
||||
"latex-fragment")}
|
||||
(-> e ::rendered deref)])
|
||||
|
||||
(defmethod org-element "latex-environment" [{:keys [value] :as e}]
|
||||
[:span.latex-fragment.display-math
|
||||
(-> e ::rendered deref)])
|
||||
|
||||
(defmethod org-element "example-block" [{:keys [value]}]
|
||||
[:pre value])
|
||||
|
||||
(defmethod org-element "src-block" [{:keys [value]}]
|
||||
[:pre [:code value]])
|
||||
|
||||
(defmethod org-element "quote-block" [{:keys [children]}]
|
||||
[:blockquote children])
|
||||
|
||||
(defmethod org-element "comment" [_] nil)
|
||||
|
||||
(defmethod org-keyword "TITLE" [{:keys [value]}]
|
||||
[:h1 value])
|
||||
@@ -256,17 +384,25 @@
|
||||
;; Completely ignore the LATEX_COMPILER keyword.
|
||||
(defmethod org-keyword "LATEX_COMPILER" [_] nil)
|
||||
|
||||
(defmethod org-keyword "LATEX_HEADER" [_] nil)
|
||||
|
||||
;; Not sure how to deal with this one yet.
|
||||
(defmethod org-keyword "AUTHOR" [_] nil)
|
||||
|
||||
(defmethod org-element :default [x]
|
||||
(render-pprint x :text "unimplemented!"))
|
||||
|
||||
(defmethod org-keyword :default [x]
|
||||
(render-pprint x :text "unimplemented!"))
|
||||
|
||||
(defmethod org-special-block "margin-note" [{:keys [children]}]
|
||||
[:p [:span.marginnote (strip-paragraphs children)]])
|
||||
|
||||
#_
|
||||
(defmethod org-special-block :default [x]
|
||||
(render-pprint x :text "unimplemented!"))
|
||||
|
||||
(defmethod org-link :default [{:keys [raw-link children]}]
|
||||
[:span {:class "org-link external"}
|
||||
[:span.org-link.external
|
||||
[:a {:href raw-link}
|
||||
(or (seq children) raw-link)]])
|
||||
|
||||
@@ -10,7 +10,15 @@
|
||||
(def some-org-file
|
||||
#_
|
||||
"/home/msyds/org/20251228003307-prerequisite_context_in_korean.org"
|
||||
"/home/msyds/org/20251111182118-path_induction.org")
|
||||
#_
|
||||
"/home/msyds/org/20250919114912-homepage.org"
|
||||
#_
|
||||
"/home/msyds/org/20251111182118-path_induction.org"
|
||||
#_
|
||||
"/home/msyds/org/20250512144715-natural_transformation_category_theory.org"
|
||||
#_
|
||||
"/home/msyds/org/20251021155921-path_action.org"
|
||||
"test/net/deertopia/doerg/render_test/fallbacks.org")
|
||||
|
||||
(defn- force-create-sym-link [path target]
|
||||
(fs/delete-if-exists path)
|
||||
@@ -26,9 +34,10 @@
|
||||
(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"))
|
||||
(->> (h/html (-> src slurp element/read-string render/org-document))
|
||||
str (spit (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
|
||||
|
||||
4
doerg/src/net/deertopia/doerg/tex.clj
Normal file
4
doerg/src/net/deertopia/doerg/tex.clj
Normal file
@@ -0,0 +1,4 @@
|
||||
(ns net.deertopia.doerg.tex
|
||||
(:require [net.deertopia.doerg.tex.native :as native]
|
||||
[net.deertopia.doerg.tex.temml :as temml]
|
||||
[babashka.fs :as fs]))
|
||||
156
doerg/src/net/deertopia/doerg/tex/native.clj
Normal file
156
doerg/src/net/deertopia/doerg/tex/native.clj
Normal file
@@ -0,0 +1,156 @@
|
||||
(ns net.deertopia.doerg.tex.native
|
||||
"Shelling out to (Xe)LaTeX and dvisvgm. Much magic borrowed from
|
||||
the org-latex-preview package for Emacs."
|
||||
(:require [babashka.process :as p]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[babashka.fs :as fs]
|
||||
[net.deertopia.doerg.config :as cfg])
|
||||
(:import (java.io ByteArrayOutputStream)))
|
||||
|
||||
(def ^:private scale-divisor 66873.46948423679)
|
||||
|
||||
(def ^:private font-size 10)
|
||||
|
||||
(def ^:private tightpage-regexp
|
||||
#"Preview: Tightpage (-?\d+) *(-?\d+) *(-?\d+) *(-?\d+)")
|
||||
|
||||
(def ^:private preview-start-regexp
|
||||
#"! Preview: Snippet (\d+) started.")
|
||||
|
||||
(def ^:private preview-end-regexp
|
||||
#"(?:^Preview: Tightpage.*$)?\n! Preview: Snippet (\d+) ended.\((\d+)\+(\d+)x(\d+)\)")
|
||||
|
||||
(defn- invoke [extra-opts & args]
|
||||
(let [namespace (or (::ns extra-opts) (first args))
|
||||
out-bytes (ByteArrayOutputStream.)
|
||||
out-stream (common/tee-output-stream
|
||||
out-bytes
|
||||
(l/log-stream :info (str namespace "/out")))
|
||||
err-stream (l/log-stream :info (str namespace "/err"))
|
||||
opts (merge extra-opts
|
||||
{:out out-stream :err err-stream :continue true
|
||||
:shutdown p/destroy-tree
|
||||
:pre-start-fn (fn [{:keys [cmd]}]
|
||||
(l/infof "$ %s"
|
||||
(str/join " " cmd)))
|
||||
:exit-fn (fn [{:keys [cmd exit]}]
|
||||
(l/infof "%s exited w/ status %d"
|
||||
(first cmd) exit))})
|
||||
r (apply p/shell opts args)
|
||||
out (.toString out-bytes)]
|
||||
(-> r
|
||||
(assoc ::out out))))
|
||||
|
||||
(defn- parse-tightpage [latex-out]
|
||||
(->> (re-find tightpage-regexp latex-out)
|
||||
(drop 1)
|
||||
(map parse-long)))
|
||||
|
||||
(defn- compute-geometry [[tp1 tp2 tp3 tp4] [d1 d2 d3]]
|
||||
(let [depth (/ (- d2 tp2) scale-divisor font-size)]
|
||||
{:depth depth
|
||||
:height (+ depth
|
||||
(/ (+ d1 tp4)
|
||||
scale-divisor
|
||||
font-size))
|
||||
:width (/ (+ d3 tp3 (- tp2))
|
||||
scale-divisor
|
||||
font-size)}))
|
||||
|
||||
(defn- parse-latex-output [out]
|
||||
(let [tightpage-info (parse-tightpage out)
|
||||
m-start (re-matcher preview-start-regexp out)
|
||||
m-end (re-matcher preview-end-regexp out)]
|
||||
(loop [acc []]
|
||||
(if-some [[_ snippet-ix] (re-find m-start)]
|
||||
(let [r (re-find m-end)
|
||||
[_ snippet-ix* _ _ _] r
|
||||
dimensional-info (->> r (drop 2) (map parse-long))
|
||||
errors (-> out
|
||||
(subs (.end m-start) (.start m-end))
|
||||
(str/replace-first #"[^!]*" "")
|
||||
str/trim)]
|
||||
(assert (= snippet-ix snippet-ix*))
|
||||
(recur (conj acc (-> (compute-geometry
|
||||
tightpage-info dimensional-info)
|
||||
(assoc :errors (if (empty? errors)
|
||||
nil
|
||||
errors))))))
|
||||
acc))))
|
||||
|
||||
(defn- invoke-latex [& {:keys [file output-dir]}]
|
||||
(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/dvisvgm cfg/*cfg*)]
|
||||
(invoke
|
||||
{:dir output-dir}
|
||||
dvisvgm "--page=1-" "--optimize" "--clipjoin"
|
||||
"--relative" "--no-fonts" "-v3"
|
||||
"--message=processing page {?pageno}: output written to {?svgpath}"
|
||||
"--bbox=preview" "-o" "%9p.svg" file)))
|
||||
|
||||
(defn- snippet-file-names
|
||||
"Return a map of TeX snippets (as strings, including the math
|
||||
delimiters) to file names as would be output by
|
||||
`invoke-dvisvgm`. The returned file names are relative to dvisvgm's
|
||||
output directory."
|
||||
[snippets]
|
||||
(let [svgs (for [i (range)]
|
||||
(format "%09d.svg" i))]
|
||||
(zipmap (reverse snippets) svgs)))
|
||||
|
||||
(defn- instantiate-preview-template [snippets]
|
||||
(let [contents (->> (for [s snippets]
|
||||
(format "\\begin{preview}\n%s\n\\end{preview}" s))
|
||||
(str/join "\n"))]
|
||||
(-> (io/resource "net/deertopia/doerg/preview-template.tex")
|
||||
slurp
|
||||
(str/replace-first "% {{contents}}" contents))))
|
||||
|
||||
(defn render
|
||||
"Render a collection of `snippets` to SVGs in `output-dir` using a
|
||||
LaTeX engine (XeLaTeX at the moment) and dvisvgm. Returns a map
|
||||
whose keys are `snippets` and whose values are maps containing
|
||||
geometry info, a string of errors output by LaTeX, and the path to
|
||||
the generated SVG file. Math delimiters are *not* implicitly added
|
||||
to each snippet."
|
||||
[output-dir & snippets]
|
||||
(fs/with-temp-dir [dir {:prefix "doerg-latex"}]
|
||||
(let [preview-tex (fs/file dir "preview.tex")
|
||||
preview-xdv (fs/file dir "preview.xdv")
|
||||
distinct-snippets (distinct snippets)]
|
||||
(fs/create-dirs output-dir)
|
||||
(->> (instantiate-preview-template distinct-snippets)
|
||||
(spit preview-tex))
|
||||
(let [dimensions (-> (invoke-latex :output-dir dir :file preview-tex)
|
||||
::out parse-latex-output)
|
||||
_ (invoke-dvisvgm :output-dir output-dir :file preview-xdv)]
|
||||
;; Adorn each snippet with dimensions and errors parsed from
|
||||
;; LaTeX's output, and the paths to SVG files generated by
|
||||
;; dvisvgm.
|
||||
(assert (= (count distinct-snippets) (count dimensions)))
|
||||
(->> (map (fn [ix snippet dimensions]
|
||||
{snippet
|
||||
(-> dimensions
|
||||
(assoc
|
||||
:file (fs/file output-dir
|
||||
(format "%09d.svg" (inc ix)))))})
|
||||
(range)
|
||||
distinct-snippets
|
||||
dimensions)
|
||||
(into {}))))))
|
||||
|
||||
(comment
|
||||
(render "/tmp/doerg-tex-svgs"
|
||||
"\\(c = \\sqrt{x^2 + y^2}\\)"
|
||||
"\\(x\\)" "\\(y\\)" "\\(x\\)"
|
||||
"\\(\\undefinedcommandlol\\)"))
|
||||
|
||||
68
doerg/src/net/deertopia/doerg/tex/temml.clj
Normal file
68
doerg/src/net/deertopia/doerg/tex/temml.clj
Normal file
@@ -0,0 +1,68 @@
|
||||
(ns net.deertopia.doerg.tex.temml
|
||||
(:require [babashka.process :as p]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[net.deertopia.doerg.config :as cfg]
|
||||
[clj-cbor.core :as cbor]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.logging :as l]
|
||||
[babashka.fs :as fs])
|
||||
(:import (java.io ByteArrayOutputStream)))
|
||||
|
||||
(def ^:dynamic *worker-timeout-duration*
|
||||
"Number of milliseconds to wait before killing the external Uniorg
|
||||
process."
|
||||
(* 10 1000))
|
||||
|
||||
(def ^:dynamic *worker*)
|
||||
|
||||
(defn worker [& {:keys [preamble]}]
|
||||
(let [doerg-temml-worker (::cfg/doerg-temml-worker cfg/*cfg*)]
|
||||
(p/process
|
||||
{:shutdown p/destroy-tree
|
||||
:err (l/log-stream :info "temml/err")}
|
||||
doerg-temml-worker
|
||||
"--preamble"
|
||||
"resources/net/deertopia/doerg/prelude.tex")))
|
||||
|
||||
(defn close-worker [tw]
|
||||
(.close (:in tw)))
|
||||
|
||||
(defmacro with-worker [tw & body]
|
||||
`(let [~tw (worker)]
|
||||
(try
|
||||
(do ~@body)
|
||||
(finally
|
||||
(close-worker ~tw)
|
||||
(p/destroy-tree ~tw)))))
|
||||
|
||||
(defmacro binding-worker [& body]
|
||||
`(binding [*worker* (worker)]
|
||||
(try
|
||||
~@body
|
||||
(finally
|
||||
(close-worker *worker*)))))
|
||||
|
||||
(defn command-worker [x]
|
||||
(cbor/encode cbor/default-codec (:in *worker*) x)
|
||||
(.flush (:in *worker*))
|
||||
(cbor/decode cbor/default-codec (:out *worker*)))
|
||||
|
||||
(defn render-inline [s]
|
||||
(command-worker s))
|
||||
|
||||
(defn render-display [s]
|
||||
(command-worker [s]))
|
||||
|
||||
(defn render [s]
|
||||
(if-let [[_ inner] (re-matches #"(?s)\\[(.*)\\]" s)]
|
||||
(render-display inner)
|
||||
(if (re-matches #"(?s)\\begin\{.+?}(.*?)\\end\{.+?}" s)
|
||||
(render-display s)
|
||||
(if-let [[_ inner] (re-matches #"(?s)\\\((.*)\\\)" s)]
|
||||
(render-inline inner)
|
||||
(throw (ex-info "weird" {:snippet s}))))))
|
||||
|
||||
;; hackky....
|
||||
(defn erroneous-output? [s]
|
||||
(re-find #"(#b22222|temml-error)" s))
|
||||
32
doerg/test/net/deertopia/doerg/common_test.clj
Normal file
32
doerg/test/net/deertopia/doerg/common_test.clj
Normal file
@@ -0,0 +1,32 @@
|
||||
(ns net.deertopia.doerg.common-test
|
||||
(:require [net.deertopia.doerg.common :as sut]
|
||||
[babashka.process :as p]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(defn sleep-vs-timeout [& {:keys [sleep timeout]}]
|
||||
(sut/deref-with-timeout
|
||||
(p/process "sleep" (format "%ds" sleep))
|
||||
(* timeout 1000)))
|
||||
|
||||
;; Ideally we would test the following property:
|
||||
;;
|
||||
;; For natural numbers n and m, evaluating the form
|
||||
;; (sut/deref-with-timeout
|
||||
;; (p/process "sleep" (format "%ds" n))
|
||||
;; (* m 1000))
|
||||
;; will throw an exception iff n < m (probably with some margin of
|
||||
;; error lol).
|
||||
;;
|
||||
;; But, this is not something that we want to run dozens-to-hundreds
|
||||
;; of times. }:p
|
||||
|
||||
(t/deftest long-sleep-vs-short-timeout
|
||||
(t/testing "long sleep vs. short timeout"
|
||||
(t/is (thrown-with-msg?
|
||||
Exception #".*timed out.*"
|
||||
(sleep-vs-timeout :sleep 5 :timeout 1)))))
|
||||
|
||||
(t/deftest short-sleep-vs-long-timeout
|
||||
(t/testing "short sleep vs. long timeout"
|
||||
(t/is (instance? babashka.process.Process
|
||||
(sleep-vs-timeout :sleep 1 :timeout 5)))))
|
||||
@@ -6,34 +6,6 @@
|
||||
[clojure.java.io :as io]
|
||||
[com.rpl.specter :as sp]))
|
||||
|
||||
(defn sleep-vs-timeout [& {:keys [sleep timeout]}]
|
||||
(sut/deref-with-timeout
|
||||
(p/process "sleep" (format "%ds" sleep))
|
||||
(* timeout 1000)))
|
||||
|
||||
;; Ideally we would test the following property:
|
||||
;;
|
||||
;; For natural numbers n and m, evaluating the form
|
||||
;; (sut/deref-with-timeout
|
||||
;; (p/process "sleep" (format "%ds" n))
|
||||
;; (* m 1000))
|
||||
;; will throw an exception iff n < m (probably with some margin of
|
||||
;; error lol).
|
||||
;;
|
||||
;; But, this is not something that we want to run dozens-to-hundreds
|
||||
;; of times. }:p
|
||||
|
||||
(t/deftest long-sleep-vs-short-timeout
|
||||
(t/testing "long sleep vs. short timeout"
|
||||
(t/is (thrown-with-msg?
|
||||
Exception #".*timed out.*"
|
||||
(sleep-vs-timeout :sleep 5 :timeout 1)))))
|
||||
|
||||
(t/deftest short-sleep-vs-long-timeout
|
||||
(t/testing "short sleep vs. long timeout"
|
||||
(t/is (instance? babashka.process.Process
|
||||
(sleep-vs-timeout :sleep 1 :timeout 5)))))
|
||||
|
||||
(defn- first-child-of-type [parent type]
|
||||
(some #(and (sut/of-type? % type) %) (:children parent)))
|
||||
|
||||
|
||||
60
doerg/test/net/deertopia/doerg/render_test.clj
Normal file
60
doerg/test/net/deertopia/doerg/render_test.clj
Normal file
@@ -0,0 +1,60 @@
|
||||
(ns net.deertopia.doerg.render-test
|
||||
(:require [net.deertopia.doerg.render :as sut]
|
||||
[net.deertopia.doerg.element :as element]
|
||||
[net.deertopia.doerg.tex.temml :as temml]
|
||||
[net.deertopia.doerg.tex.native :as native]
|
||||
[com.rpl.specter :as sp]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.test :as t]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str]))
|
||||
|
||||
;; Stupid and hacky.
|
||||
(defn mathml? [s]
|
||||
(str/starts-with? s "<math"))
|
||||
|
||||
;; Also stupid and hacky. }:)
|
||||
(defn svg? [s]
|
||||
(some? (re-matches #"(?s)(<!--.*?-->\n)<svg.*" s)))
|
||||
|
||||
(defn read-resource [s]
|
||||
(let [p (-> (format "net/deertopia/doerg/render_test/%s" s)
|
||||
io/resource slurp)]
|
||||
(cond (str/ends-with? s ".edn") (edn/read-string p)
|
||||
(str/ends-with? s ".org") (element/read-string p))))
|
||||
|
||||
(t/deftest latex-fallbacks
|
||||
(t/testing "LaTeX fallback behaviour"
|
||||
(let [doc (temml/binding-worker
|
||||
(-> "fallbacks.org" read-resource sut/render-tex-snippets))
|
||||
snippets (->> doc
|
||||
(sp/select
|
||||
[element/postorder-walker
|
||||
#(element/of-type?
|
||||
% "latex-fragment" "latex-environment")
|
||||
(sp/view #(-> % ::sut/rendered deref str))]))
|
||||
expectations (-> "fallbacks.edn" read-resource)]
|
||||
(doall (map (fn [s e]
|
||||
(let [mathml (mathml? s)
|
||||
svg (svg? s)]
|
||||
(assert
|
||||
(not= mathml svg)
|
||||
"`mathml?` and `svg?` should be mutually-exclusive.")
|
||||
(case e
|
||||
:mathml (t/is mathml)
|
||||
:svg (t/is svg))))
|
||||
snippets expectations)))))
|
||||
|
||||
(t/deftest latex-laziness
|
||||
(t/testing "LaTeX laziness"
|
||||
(let [ex (Exception. "you're supposed to be lazy!")
|
||||
bad (fn [& _] (throw ex))
|
||||
doc (read-resource "latexless.org")
|
||||
r (try (with-redefs-fn {#'native/render bad
|
||||
#'temml/render bad}
|
||||
#(sut/render-tex-snippets doc))
|
||||
(catch Exception e
|
||||
(if (= e ex)
|
||||
false
|
||||
(throw e))))]
|
||||
(t/is r))))
|
||||
7
doerg/test/net/deertopia/doerg/render_test/fallbacks.edn
Normal file
7
doerg/test/net/deertopia/doerg/render_test/fallbacks.edn
Normal file
@@ -0,0 +1,7 @@
|
||||
[:mathml
|
||||
:mathml
|
||||
:mathml
|
||||
:mathml
|
||||
:svg
|
||||
:mathml
|
||||
:svg]
|
||||
20
doerg/test/net/deertopia/doerg/render_test/fallbacks.org
Normal file
20
doerg/test/net/deertopia/doerg/render_test/fallbacks.org
Normal file
@@ -0,0 +1,20 @@
|
||||
#+title: aghhh
|
||||
|
||||
- blah blah prose prose prose \(c = \sqrt{x^2 + y^2}\), alal.
|
||||
- this thing is \(x\)
|
||||
- another thing \(y\)
|
||||
- this thing is also \(x\) and uses the same svg
|
||||
- ifxetex: \(\ifxetex alalala\fi \)
|
||||
|
||||
balahahahahahaj
|
||||
\begin{align*}
|
||||
x &= y
|
||||
\\ &= zzz.
|
||||
\end{align*}
|
||||
awawawa
|
||||
|
||||
cool ass tbale
|
||||
\begin{tabular}{|c|c|c|}
|
||||
blah & glah & zlah
|
||||
\\ abdwa & www &dj
|
||||
\end{tabular}
|
||||
3
doerg/test/net/deertopia/doerg/render_test/latexless.org
Normal file
3
doerg/test/net/deertopia/doerg/render_test/latexless.org
Normal file
@@ -0,0 +1,3 @@
|
||||
#+title: 이 파일은 LaTeX 코드가 포함되지 않습니다.
|
||||
|
||||
🦌!
|
||||
1
doerg/tests.edn
Normal file
1
doerg/tests.edn
Normal file
@@ -0,0 +1 @@
|
||||
#kaocha/v1 {}
|
||||
37
flake.lock
generated
37
flake.lock
generated
@@ -143,11 +143,46 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1750386251,
|
||||
"narHash": "sha256-1ovgdmuDYVo5OUC5NzdF+V4zx2uT8RtsgZahxidBTyw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "076e8c6678d8c54204abcb4b1b14c366835a58bb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"clj-nix": "clj-nix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"sydpkgs": "sydpkgs"
|
||||
}
|
||||
},
|
||||
"sydpkgs": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767975357,
|
||||
"narHash": "sha256-MDVh3/aVhkD1bh/r8c0gs9DL4e78CrUbUxOZHWlCwLM=",
|
||||
"owner": "msyds",
|
||||
"repo": "sydpkgs",
|
||||
"rev": "233479ab277d47b1dbda202eafca50e61c659151",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "msyds",
|
||||
"repo": "sydpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
||||
17
flake.nix
17
flake.nix
@@ -3,7 +3,7 @@
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
clj-nix.url = "github:jlesquembre/clj-nix";
|
||||
# clj-nix.url = "path:///home/msyds/git/clj-nix";
|
||||
sydpkgs.url = "github:msyds/sydpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, clj-nix, ... }@inputs:
|
||||
@@ -19,6 +19,7 @@
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
inputs.sydpkgs.overlays.default
|
||||
clj-nix.overlays.default
|
||||
self.overlays.default
|
||||
];
|
||||
@@ -31,7 +32,7 @@
|
||||
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
||||
|
||||
packages = each-system ({ pkgs, ... }: {
|
||||
inherit (pkgs) publisher doerg doerg-parser;
|
||||
inherit (pkgs) publisher doerg doerg-parser doerg-temml-worker;
|
||||
default = pkgs.publisher;
|
||||
});
|
||||
|
||||
@@ -42,11 +43,12 @@
|
||||
inherit (vendored) ibm-plex-web;
|
||||
publisher = final.callPackage ./publisher/package.nix {};
|
||||
doerg = final.callPackage ./doerg/package.nix {};
|
||||
doerg-parser = final.callPackage ./doerg/doerg-parser/package.nix {};
|
||||
doerg-parser = final.callPackage ./doerg/doerg-parser {};
|
||||
doerg-temml-worker = final.callPackage ./doerg/doerg-temml-worker {};
|
||||
};
|
||||
|
||||
checks = each-system ({ pkgs, system, ... }: {
|
||||
packages =
|
||||
build-all =
|
||||
pkgs.linkFarmFromDrvs
|
||||
"all"
|
||||
(pkgs.lib.attrValues self.packages.${system});
|
||||
@@ -54,10 +56,15 @@
|
||||
|
||||
devShells = each-system ({ pkgs, system, ... }: {
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [ pkgs.doerg ];
|
||||
inputsFrom = [
|
||||
pkgs.doerg
|
||||
pkgs.doerg-parser
|
||||
pkgs.doerg-temml-worker
|
||||
];
|
||||
packages = with pkgs; [
|
||||
clojure-lsp
|
||||
doerg-parser
|
||||
doerg-temml-worker
|
||||
# wahhh ibm-plex-web is a dependency of doerg... why must
|
||||
# i specify it hereeee.
|
||||
# ibm-plex-web
|
||||
|
||||
Reference in New Issue
Block a user