diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..e276411 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,11 @@ +name: build +on: [push] + +jobs: + build: + runs-on: nixos + steps: + - name: Check out repository code + uses: actions/checkout@v4 + - name: build doerg + run: nix build -L .#doerg diff --git a/.gitea/workflows/demo.yaml b/.gitea/workflows/demo.yaml new file mode 100644 index 0000000..2486fdd --- /dev/null +++ b/.gitea/workflows/demo.yaml @@ -0,0 +1,26 @@ +name: Gitea Actions Demo +run-name: ${{ gitea.actor }} is testing out Gitea Actions πŸš€ +on: [push] + +jobs: + build: + runs-on: nixos + steps: + - name: Check out repository code + uses: actions/checkout@v4 + - name: build doerg + run: nix build -L .#doerg + Explore-Gitea-Actions: + runs-on: nixos + steps: + - run: echo "πŸŽ‰ The job was automatically triggered by a ${{ gitea.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!" + - run: echo "πŸ”Ž The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." + - name: Check out repository code + uses: actions/checkout@v4 + - run: echo "πŸ’‘ The ${{ gitea.repository }} repository has been cloned to the runner." + - run: echo "πŸ–₯️ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ gitea.workspace }} + - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/deps-lock.json b/deps-lock.json index 986bedb..8579cce 100644 --- a/deps-lock.json +++ b/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/", diff --git a/doerg/deps.edn b/doerg/deps.edn index 956b86c..2c1cbff 100644 --- a/doerg/deps.edn +++ b/doerg/deps.edn @@ -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"]}}} diff --git a/doerg/doerg-parser/package.nix b/doerg/doerg-parser/default.nix similarity index 100% rename from doerg/doerg-parser/package.nix rename to doerg/doerg-parser/default.nix diff --git a/doerg/doerg-temml-worker/README.org b/doerg/doerg-temml-worker/README.org new file mode 100644 index 0000000..c2d5bd4 --- /dev/null +++ b/doerg/doerg-temml-worker/README.org @@ -0,0 +1 @@ +#+title: doerg-temml-worker diff --git a/doerg/doerg-temml-worker/default.nix b/doerg/doerg-temml-worker/default.nix new file mode 100644 index 0000000..94783fe --- /dev/null +++ b/doerg/doerg-temml-worker/default.nix @@ -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; +} diff --git a/doerg/doerg-temml-worker/deps.edn b/doerg/doerg-temml-worker/deps.edn new file mode 100644 index 0000000..65b9cb6 --- /dev/null +++ b/doerg/doerg-temml-worker/deps.edn @@ -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"]} diff --git a/doerg/doerg-temml-worker/deserialise.clj b/doerg/doerg-temml-worker/deserialise.clj new file mode 100644 index 0000000..cb0011c --- /dev/null +++ b/doerg/doerg-temml-worker/deserialise.clj @@ -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)) diff --git a/doerg/doerg-temml-worker/index.js b/doerg/doerg-temml-worker/index.js new file mode 100755 index 0000000..d9156c3 --- /dev/null +++ b/doerg/doerg-temml-worker/index.js @@ -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 () diff --git a/doerg/doerg-temml-worker/package-lock.json b/doerg/doerg-temml-worker/package-lock.json new file mode 100644 index 0000000..e6e6eca --- /dev/null +++ b/doerg/doerg-temml-worker/package-lock.json @@ -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" + } + } + } +} diff --git a/doerg/doerg-temml-worker/package.json b/doerg/doerg-temml-worker/package.json new file mode 100644 index 0000000..f07b9be --- /dev/null +++ b/doerg/doerg-temml-worker/package.json @@ -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"}} diff --git a/doerg/doerg-temml-worker/serialise.clj b/doerg/doerg-temml-worker/serialise.clj new file mode 100644 index 0000000..417a648 --- /dev/null +++ b/doerg/doerg-temml-worker/serialise.clj @@ -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") diff --git a/doerg/our-tex.nix b/doerg/our-tex.nix new file mode 100644 index 0000000..fa70de0 --- /dev/null +++ b/doerg/our-tex.nix @@ -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 + ; +} diff --git a/doerg/package.nix b/doerg/package.nix index d2a1715..171e5e5 100644 --- a/doerg/package.nix +++ b/doerg/package.nix @@ -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} + ''; } diff --git a/doerg/resources/net/deertopia/doerg/Temml-Plex.css b/doerg/resources/net/deertopia/doerg/Temml-Plex.css new file mode 100644 index 0000000..e4c46c0 --- /dev/null +++ b/doerg/resources/net/deertopia/doerg/Temml-Plex.css @@ -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,"); +} + +@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 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; +} diff --git a/doerg/resources/net/deertopia/doerg/prelude.tex b/doerg/resources/net/deertopia/doerg/prelude.tex new file mode 100644 index 0000000..37a3084 --- /dev/null +++ b/doerg/resources/net/deertopia/doerg/prelude.tex @@ -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} diff --git a/doerg/resources/net/deertopia/doerg/preview-template.tex b/doerg/resources/net/deertopia/doerg/preview-template.tex new file mode 100644 index 0000000..9ecc15a --- /dev/null +++ b/doerg/resources/net/deertopia/doerg/preview-template.tex @@ -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} diff --git a/doerg/resources/net/deertopia/doerg/tuftesque.css b/doerg/resources/net/deertopia/doerg/tuftesque.css index f1c27de..d71d1ac 100644 --- a/doerg/resources/net/deertopia/doerg/tuftesque.css +++ b/doerg/resources/net/deertopia/doerg/tuftesque.css @@ -105,8 +105,8 @@ p, dl, ol, ul { - font-size: 1.4rem; - line-height: 2rem; + font-size: 1.2rem; + line-height: 1.5rem; } p { @@ -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% +} diff --git a/doerg/src/net/deertopia/doerg/common.clj b/doerg/src/net/deertopia/doerg/common.clj new file mode 100644 index 0000000..8cbdc1c --- /dev/null +++ b/doerg/src/net/deertopia/doerg/common.clj @@ -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)) diff --git a/doerg/src/net/deertopia/doerg/config.clj b/doerg/src/net/deertopia/doerg/config.clj index 54e753f..628c1a7 100644 --- a/doerg/src/net/deertopia/doerg/config.clj +++ b/doerg/src/net/deertopia/doerg/config.clj @@ -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) diff --git a/doerg/src/net/deertopia/doerg/element.clj b/doerg/src/net/deertopia/doerg/element.clj index 65c1781..f3a0041 100644 --- a/doerg/src/net/deertopia/doerg/element.clj +++ b/doerg/src/net/deertopia/doerg/element.clj @@ -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] @@ -14,26 +15,11 @@ (:refer-clojure :exclude [read-string])) -(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 +30,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 +79,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 +185,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"))) diff --git a/doerg/src/net/deertopia/doerg/html.clj b/doerg/src/net/deertopia/doerg/html.clj index 76cf513..0a17511 100644 --- a/doerg/src/net/deertopia/doerg/html.clj +++ b/doerg/src/net/deertopia/doerg/html.clj @@ -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)) diff --git a/doerg/src/net/deertopia/doerg/render.clj b/doerg/src/net/deertopia/doerg/render.clj index 89b33b0..0619019 100644 --- a/doerg/src/net/deertopia/doerg/render.clj +++ b/doerg/src/net/deertopia/doerg/render.clj @@ -7,8 +7,14 @@ [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 @@ -38,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` @@ -87,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))) @@ -134,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 e ::rendered deref)]) -(defmethod org-element "latex-environment" [{:keys [value]}] - [:pre [:code value]]) +(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]) @@ -299,7 +384,6 @@ ;; Completely ignore the LATEX_COMPILER keyword. (defmethod org-keyword "LATEX_COMPILER" [_] nil) -;; TODO: Real LatEx support. (defmethod org-keyword "LATEX_HEADER" [_] nil) ;; Not sure how to deal with this one yet. @@ -322,4 +406,3 @@ [:span.org-link.external [:a {:href raw-link} (or (seq children) raw-link)]]) - diff --git a/doerg/src/net/deertopia/doerg/repl.clj b/doerg/src/net/deertopia/doerg/repl.clj index 56dfe43..f2313cf 100644 --- a/doerg/src/net/deertopia/doerg/repl.clj +++ b/doerg/src/net/deertopia/doerg/repl.clj @@ -14,7 +14,11 @@ "/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/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) @@ -30,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 diff --git a/doerg/src/net/deertopia/doerg/tex.clj b/doerg/src/net/deertopia/doerg/tex.clj new file mode 100644 index 0000000..59c9e0c --- /dev/null +++ b/doerg/src/net/deertopia/doerg/tex.clj @@ -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])) diff --git a/doerg/src/net/deertopia/doerg/tex/native.clj b/doerg/src/net/deertopia/doerg/tex/native.clj new file mode 100644 index 0000000..cddbb11 --- /dev/null +++ b/doerg/src/net/deertopia/doerg/tex/native.clj @@ -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\\)")) + diff --git a/doerg/src/net/deertopia/doerg/tex/temml.clj b/doerg/src/net/deertopia/doerg/tex/temml.clj new file mode 100644 index 0000000..18aacdf --- /dev/null +++ b/doerg/src/net/deertopia/doerg/tex/temml.clj @@ -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)) diff --git a/doerg/test/net/deertopia/doerg/common_test.clj b/doerg/test/net/deertopia/doerg/common_test.clj new file mode 100644 index 0000000..9305aec --- /dev/null +++ b/doerg/test/net/deertopia/doerg/common_test.clj @@ -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))))) diff --git a/doerg/test/net/deertopia/doerg/element_test.clj b/doerg/test/net/deertopia/doerg/element_test.clj index 981c30b..3406bb1 100644 --- a/doerg/test/net/deertopia/doerg/element_test.clj +++ b/doerg/test/net/deertopia/doerg/element_test.clj @@ -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))) diff --git a/doerg/test/net/deertopia/doerg/render_test.clj b/doerg/test/net/deertopia/doerg/render_test.clj new file mode 100644 index 0000000..976c82b --- /dev/null +++ b/doerg/test/net/deertopia/doerg/render_test.clj @@ -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 "\n) (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)))) diff --git a/doerg/test/net/deertopia/doerg/render_test/fallbacks.edn b/doerg/test/net/deertopia/doerg/render_test/fallbacks.edn new file mode 100644 index 0000000..bcd9d18 --- /dev/null +++ b/doerg/test/net/deertopia/doerg/render_test/fallbacks.edn @@ -0,0 +1,7 @@ +[:mathml + :mathml + :mathml + :mathml + :svg + :mathml + :svg] diff --git a/doerg/test/net/deertopia/doerg/render_test/fallbacks.org b/doerg/test/net/deertopia/doerg/render_test/fallbacks.org new file mode 100644 index 0000000..1de6c11 --- /dev/null +++ b/doerg/test/net/deertopia/doerg/render_test/fallbacks.org @@ -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} diff --git a/doerg/test/net/deertopia/doerg/render_test/latexless.org b/doerg/test/net/deertopia/doerg/render_test/latexless.org new file mode 100644 index 0000000..3179de7 --- /dev/null +++ b/doerg/test/net/deertopia/doerg/render_test/latexless.org @@ -0,0 +1,3 @@ +#+title: 이 νŒŒμΌμ€ LaTeX μ½”λ“œκ°€ ν¬ν•¨λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. + +🦌! diff --git a/doerg/tests.edn b/doerg/tests.edn new file mode 100644 index 0000000..9d8d845 --- /dev/null +++ b/doerg/tests.edn @@ -0,0 +1 @@ +#kaocha/v1 {} diff --git a/flake.lock b/flake.lock index fd47f11..39abbbd 100644 --- a/flake.lock +++ b/flake.lock @@ -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": { diff --git a/flake.nix b/flake.nix index d00a376..facf0a4 100644 --- a/flake.nix +++ b/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