0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-06 14:50:20 -05:00

♻️ Internal directory refactor.

Make common as first-class module.
This commit is contained in:
Andrey Antukh 2021-05-28 13:50:42 +02:00 committed by Andrés Moya
parent 6a2e45988f
commit 548664f6ce
86 changed files with 801 additions and 908 deletions

View file

@ -9,7 +9,7 @@ jobs:
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
- image: circleci/postgres:13.1-ram
- image: circleci/postgres:13.3-ram
environment:
POSTGRES_USER: penpot_test
POSTGRES_PASSWORD: penpot_test
@ -29,21 +29,21 @@ jobs:
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}
- v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# run lint
# run backend lint
- run:
working_directory: "./backend"
name: backend lint
working_directory: "./backend"
command: "clj-kondo --lint src/"
# run test
# run backend test
- run:
working_directory: "./backend"
name: backend test
command: "clojure -M:dev:tests"
working_directory: "./backend"
command: "clojure -X:dev:test"
environment:
PENPOT_TEST_DATABASE_URI: "postgresql://localhost/penpot_test"
PENPOT_TEST_DATABASE_USERNAME: penpot_test
@ -51,11 +51,31 @@ jobs:
PENPOT_TEST_REDIS_URI: "redis://localhost/1"
- run:
working_directory: "./frontend"
name: frontend tests
working_directory: "./frontend"
command: |
yarn install
npx shadow-cljs compile tests
clojure -M:dev:shadow-cljs compile test
node target/tests.js
environment:
JAVA_HOME: /usr/lib/jvm/openjdk16
PATH: /usr/local/nodejs/bin/:/usr/local/bin:/bin:/usr/bin:/usr/lib/jvm/openjdk16/bin
# - run:
# name: common lint
# working_directory: "./common"
# command: "clj-kondo --lint src/"
- run:
working_directory: "./common"
name: common tests
command: |
yarn install
clojure -M:dev:shadow-cljs compile test
node target/tests.js
clojure -X:dev:test
environment:
JAVA_HOME: /usr/lib/jvm/openjdk16
PATH: /usr/local/nodejs/bin/:/usr/local/bin:/bin:/usr/bin:/usr/lib/jvm/openjdk16/bin
@ -63,5 +83,5 @@ jobs:
- save_cache:
paths:
- ~/.m2
key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}
key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}

2
.gitignore vendored
View file

@ -30,6 +30,8 @@ node_modules
/exporter/target
/exporter/.shadow-cljs
/docker/images/bundle*
/common/.shadow-cljs
/common/target
/.clj-kondo/.cache
/bundle*
/media

View file

@ -1,22 +1,14 @@
{:mvn/repos
{"central" {:url "https://repo1.maven.org/maven2/"}
"clojars" {:url "https://clojars.org/repo"}
"jcenter" {:url "https://jcenter.bintray.com/"}}
{
;; :mvn/repos
;; {"central" {:url "https://repo1.maven.org/maven2/"}
;; "clojars" {:url "https://clojars.org/repo"}
;; "jcenter" {:url "https://jcenter.bintray.com/"}
;; }
:deps
{org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/data.json {:mvn/version "2.2.3"}
org.clojure/core.async {:mvn/version "1.3.618"}
org.clojure/tools.cli {:mvn/version "1.0.206"}
org.clojure/clojurescript {:mvn/version "1.10.844"}
{penpot/common
{:local/root "../common"}
;; Logging
org.clojure/tools.logging {:mvn/version "1.1.0"}
org.apache.logging.log4j/log4j-api {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-core {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-web {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-jul {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-slf4j18-impl {:mvn/version "2.14.1"}
org.slf4j/slf4j-api {:mvn/version "2.0.0-alpha1"}
org.zeromq/jeromq {:mvn/version "0.5.2"}
com.taoensso/nippy {:mvn/version "3.1.1"}
@ -32,49 +24,31 @@
org.eclipse.jetty/jetty-servlet]}
io.prometheus/simpleclient_httpserver {:mvn/version "0.9.0"}
selmer/selmer {:mvn/version "1.12.40"}
expound/expound {:mvn/version "0.8.9"}
com.cognitect/transit-clj {:mvn/version "1.0.324"}
io.lettuce/lettuce-core {:mvn/version "6.1.2.RELEASE"}
java-http-clj/java-http-clj {:mvn/version "0.4.2"}
info.sunng/ring-jetty9-adapter {:mvn/version "0.15.1"}
com.github.seancorfield/next.jdbc {:mvn/version "1.2.659"}
metosin/reitit-ring {:mvn/version "0.5.13"}
metosin/jsonista {:mvn/version "0.3.3"}
org.postgresql/postgresql {:mvn/version "42.2.20"}
com.zaxxer/HikariCP {:mvn/version "4.0.3"}
funcool/datoteka {:mvn/version "2.0.0"}
funcool/promesa {:mvn/version "6.0.1"}
funcool/cuerdas {:mvn/version "2021.05.09-0"}
buddy/buddy-core {:mvn/version "1.10.1"}
buddy/buddy-hashers {:mvn/version "1.8.1"}
buddy/buddy-sign {:mvn/version "3.4.1"}
lambdaisland/uri {:mvn/version "1.4.54"
:exclusions [org.clojure/data.json]}
frankiesardo/linked {:mvn/version "1.3.0"}
danlentz/clj-uuid {:mvn/version "0.1.9"}
org.jsoup/jsoup {:mvn/version "1.13.1"}
org.im4java/im4java {:mvn/version "1.4.0"}
org.lz4/lz4-java {:mvn/version "1.7.1"}
commons-io/commons-io {:mvn/version "2.8.0"}
com.sun.mail/jakarta.mail {:mvn/version "2.0.1"}
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"}
integrant/integrant {:mvn/version "0.8.0"}
software.amazon.awssdk/s3 {:mvn/version "2.16.62"}
software.amazon.awssdk/s3 {:mvn/version "2.16.62"}}
;; exception printing
io.aviso/pretty {:mvn/version "0.1.37"}
environ/environ {:mvn/version "1.2.0"}}
:paths ["src" "resources" "../common" "common"]
:paths ["src" "resources"]
:aliases
{:dev
{:extra-deps
@ -82,19 +56,24 @@
org.clojure/tools.namespace {:mvn/version "RELEASE"}
org.clojure/test.check {:mvn/version "RELEASE"}
fipp/fipp {:mvn/version "0.6.23"}
criterium/criterium {:mvn/version "0.4.6"}
mockery/mockery {:mvn/version "0.1.4"}}
:extra-paths ["tests" "dev"]}
criterium/criterium {:mvn/version "RELEASE"}
mockery/mockery {:mvn/version "RELEASE"}}
:extra-paths ["test" "dev"]}
:fn-fixtures
{:exec-fn app.cli.fixtures/run
:args {}}
:tests
:kaocha
{:extra-deps {lambdaisland/kaocha {:mvn/version "1.0.829"}}
:main-opts ["-m" "kaocha.runner"]}
:test
{:extra-deps {io.github.cognitect-labs/test-runner
{:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}}
:exec-fn cognitect.test-runner.api/test}
:outdated
{:extra-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}}
:main-opts ["-m" "antq.core"]}

View file

@ -50,7 +50,7 @@
;; --- Development Stuff
(defn- run-tests
([] (run-tests #"^app.tests.*"))
([] (run-tests #"^app.*-test$"))
([o]
(repl/refresh)
(cond

View file

@ -163,7 +163,7 @@
;; when connection is closed
(mtx-aconn :dec)
(mtx-sessions :observe (/ (inst-ms (dt/duration-between created-at (dt/now))) 1000.0))
(mtx-sessions :observe (/ (inst-ms (dt/diff created-at (dt/now))) 1000.0))
;; close subscription
(a/close! sub-ch))))

View file

@ -10,13 +10,14 @@
[clojure.spec.alpha :as s]
[cuerdas.core :as str])
(:import
java.time.Instant
java.time.Duration
java.util.Date
java.time.ZonedDateTime
java.time.Instant
java.time.OffsetDateTime
java.time.ZoneId
java.time.ZonedDateTime
java.time.format.DateTimeFormatter
java.time.temporal.TemporalAmount
java.util.Date
org.apache.logging.log4j.core.util.CronExpression))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -54,28 +55,37 @@
(obj->duration ms-or-obj)))
(defn duration-between
{:deprecated true}
[t1 t2]
(Duration/between t1 t2))
(letfn [(conformer [v]
(cond
(duration? v) v
(defn diff
[t1 t2]
(Duration/between t1 t2))
(string? v)
(try
(duration v)
(catch java.time.format.DateTimeParseException _e
::s/invalid))
(s/def ::duration
(s/conformer
(fn [v]
(cond
(duration? v) v
:else
::s/invalid))
(unformer [v]
(subs (str v) 2))]
(s/def ::duration (s/conformer conformer unformer)))
(string? v)
(try
(duration v)
(catch java.time.format.DateTimeParseException _e
::s/invalid))
:else
::s/invalid))
(fn [v]
(subs (str v) 2))))
(extend-protocol clojure.core/Inst
java.time.Duration
(inst-ms* [v] (.toMillis ^Duration v)))
(inst-ms* [v] (.toMillis ^Duration v))
OffsetDateTime
(inst-ms* [v] (.toEpochMilli (.toInstant ^OffsetDateTime v))))
(defmethod print-method Duration
[mv ^java.io.Writer writer]

View file

@ -442,7 +442,7 @@
(s/assert dt/cron? cron)
(let [now (dt/now)
next (dt/next-valid-instant-from cron now)]
(inst-ms (dt/duration-between now next))))
(inst-ms (dt/diff now next))))
(defn- schedule-task
[{:keys [scheduler] :as cfg} {:keys [cron] :as task}]

View file

@ -4,16 +4,16 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-bounces-handling
(ns app.bounce-handling-test
(:require
[clojure.pprint :refer [pprint]]
[app.http.awsns :as awsns]
[app.emails :as emails]
[app.tests.helpers :as th]
[app.db :as db]
[app.emails :as emails]
[app.http.awsns :as awsns]
[app.test-helpers :as th]
[app.util.time :as dt]
[mockery.core :refer [with-mocks]]
[clojure.test :as t]))
[clojure.pprint :refer [pprint]]
[clojure.test :as t]
[mockery.core :refer [with-mocks]]))
(t/use-fixtures :once th/state-init)
(t/use-fixtures :each th/database-reset)

View file

@ -4,13 +4,13 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-emails
(ns app.emails-test
(:require
[clojure.test :as t]
[promesa.core :as p]
[app.db :as db]
[app.emails :as emails]
[app.tests.helpers :as th]))
[app.test-helpers :as th]))
(t/use-fixtures :once th/state-init)
(t/use-fixtures :each th/database-reset)

View file

@ -4,13 +4,13 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-files
(ns app.services-files-test
(:require
[app.common.uuid :as uuid]
[app.db :as db]
[app.http :as http]
[app.storage :as sto]
[app.tests.helpers :as th]
[app.test-helpers :as th]
[clojure.test :as t]
[datoteka.core :as fs]))
@ -134,7 +134,7 @@
(t/deftest file-media-gc-task
(letfn [(create-file-media-object [{:keys [profile-id file-id]}]
(let [mfile {:filename "sample.jpg"
:tempfile (th/tempfile "app/tests/_files/sample.jpg")
:tempfile (th/tempfile "app/test_files/sample.jpg")
:content-type "image/jpeg"
:size 312043}
params {::th/type :upload-file-media-object

View file

@ -4,13 +4,13 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-fonts
(ns app.services-fonts-test
(:require
[app.common.uuid :as uuid]
[app.db :as db]
[app.http :as http]
[app.storage :as sto]
[app.tests.helpers :as th]
[app.test-helpers :as th]
[clojure.java.io :as io]
[clojure.test :as t]
[datoteka.core :as fs]))
@ -24,7 +24,7 @@
proj-id (:default-project-id prof)
font-id (uuid/custom 10 1)
ttfdata (-> (io/resource "app/tests/_files/font-1.ttf")
ttfdata (-> (io/resource "app/test_files/font-1.ttf")
(fs/slurp-bytes))
params {::th/type :create-font-variant
@ -59,7 +59,7 @@
proj-id (:default-project-id prof)
font-id (uuid/custom 10 1)
data (-> (io/resource "app/tests/_files/font-1.woff")
data (-> (io/resource "app/test_files/font-1.woff")
(fs/slurp-bytes))
params {::th/type :create-font-variant

View file

@ -4,13 +4,13 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-management
(ns app.services-management-test
(:require
[app.common.uuid :as uuid]
[app.db :as db]
[app.http :as http]
[app.storage :as sto]
[app.tests.helpers :as th]
[app.test-helpers :as th]
[clojure.test :as t]
[buddy.core.bytes :as b]
[datoteka.core :as fs]))

View file

@ -4,12 +4,12 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-media
(ns app.services-media-test
(:require
[app.common.uuid :as uuid]
[app.db :as db]
[app.storage :as sto]
[app.tests.helpers :as th]
[app.test-helpers :as th]
[clojure.test :as t]
[datoteka.core :as fs]))
@ -57,7 +57,7 @@
:project-id (:default-project-id prof)
:is-shared false})
mfile {:filename "sample.jpg"
:tempfile (th/tempfile "app/tests/_files/sample.jpg")
:tempfile (th/tempfile "app/test_files/sample.jpg")
:content-type "image/jpeg"
:size 312043}

View file

@ -4,16 +4,16 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-profile
(ns app.services-profile-test
(:require
[clojure.test :as t]
[clojure.java.io :as io]
[mockery.core :refer [with-mocks]]
[cuerdas.core :as str]
[datoteka.core :as fs]
[app.db :as db]
[app.rpc.mutations.profile :as profile]
[app.tests.helpers :as th]))
[app.test-helpers :as th]
[clojure.java.io :as io]
[clojure.test :as t]
[cuerdas.core :as str]
[datoteka.core :as fs]
[mockery.core :refer [with-mocks]]))
;; TODO: profile deletion with teams
;; TODO: profile deletion with owner teams
@ -108,7 +108,7 @@
:profile-id (:id profile)
:file {:filename "sample.jpg"
:size 123123
:tempfile "tests/app/tests/_files/sample.jpg"
:tempfile (th/tempfile "app/test_files/sample.jpg")
:content-type "image/jpeg"}}
out (th/mutation! data)]

View file

@ -4,14 +4,14 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-projects
(ns app.services-projects-test
(:require
[clojure.test :as t]
[promesa.core :as p]
[app.common.uuid :as uuid]
[app.db :as db]
[app.http :as http]
[app.tests.helpers :as th]
[app.common.uuid :as uuid]))
[app.test-helpers :as th]
[clojure.test :as t]
[promesa.core :as p]))
(t/use-fixtures :once th/state-init)
(t/use-fixtures :each th/database-reset)

View file

@ -4,16 +4,16 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-teams
(ns app.services-teams-test
(:require
[app.common.uuid :as uuid]
[app.db :as db]
[app.http :as http]
[app.storage :as sto]
[app.tests.helpers :as th]
[mockery.core :refer [with-mocks]]
[app.test-helpers :as th]
[clojure.test :as t]
[datoteka.core :as fs]))
[datoteka.core :as fs]
[mockery.core :refer [with-mocks]]))
(t/use-fixtures :once th/state-init)
(t/use-fixtures :each th/database-reset)

View file

@ -4,13 +4,13 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-services-viewer
(ns app.services-viewer-test
(:require
[clojure.test :as t]
[datoteka.core :as fs]
[app.common.uuid :as uuid]
[app.db :as db]
[app.tests.helpers :as th]))
[app.test-helpers :as th]
[clojure.test :as t]
[datoteka.core :as fs]))
(t/use-fixtures :once th/state-init)
(t/use-fixtures :each th/database-reset)

View file

@ -4,12 +4,12 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-storage
(ns app.storage-test
(:require
[app.common.exceptions :as ex]
[app.db :as db]
[app.storage :as sto]
[app.tests.helpers :as th]
[app.test-helpers :as th]
[app.util.time :as dt]
[clojure.java.io :as io]
[clojure.test :as t]
@ -106,7 +106,7 @@
:project-id (:default-project-id prof)
:is-shared false})
mfile {:filename "sample.jpg"
:tempfile (th/tempfile "app/tests/_files/sample.jpg")
:tempfile (th/tempfile "app/test_files/sample.jpg")
:content-type "image/jpeg"
:size 312043}
@ -167,7 +167,7 @@
:project-id (:default-project-id prof)
:is-shared false})
mfile {:filename "sample.jpg"
:tempfile (th/tempfile "app/tests/_files/sample.jpg")
:tempfile (th/tempfile "app/test_files/sample.jpg")
:content-type "image/jpeg"
:size 312043}

View file

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 305 KiB

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -4,7 +4,7 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.helpers
(ns app.test-helpers
(:require
[app.common.data :as d]
[app.common.pages :as cp]

View file

@ -1,5 +1,5 @@
#kaocha/v1
{:tests
[{:id :unit
:test-paths ["tests" "src"]
:ns-patterns ["test-.*"]}]}
:test-paths ["test" "src"]
:ns-patterns [".*-test$"]}]}

76
common/deps.edn Normal file
View file

@ -0,0 +1,76 @@
{
;; :mvn/repos
;; {"central" {:url "https://repo1.maven.org/maven2/"}
;; "clojars" {:url "https://clojars.org/repo"}
;; "jcenter" {:url "https://jcenter.bintray.com/"}}
:deps
{org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/data.json {:mvn/version "2.3.1"}
org.clojure/core.async {:mvn/version "1.3.618"}
org.clojure/tools.cli {:mvn/version "1.0.206"}
org.clojure/clojurescript {:mvn/version "1.10.866"}
metosin/jsonista {:mvn/version "0.3.3"}
;; Logging
org.clojure/tools.logging {:mvn/version "1.1.0"}
org.apache.logging.log4j/log4j-api {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-core {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-web {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-jul {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-slf4j18-impl {:mvn/version "2.14.1"}
org.slf4j/slf4j-api {:mvn/version "2.0.0-alpha1"}
selmer/selmer {:mvn/version "1.12.40"}
expound/expound {:mvn/version "0.8.9"}
com.cognitect/transit-clj {:mvn/version "1.0.324"}
java-http-clj/java-http-clj {:mvn/version "0.4.2"}
funcool/promesa {:mvn/version "6.0.1"}
funcool/cuerdas {:mvn/version "2021.05.29-0"}
lambdaisland/uri {:mvn/version "1.4.54"
:exclusions [org.clojure/data.json]}
frankiesardo/linked {:mvn/version "1.3.0"}
danlentz/clj-uuid {:mvn/version "0.1.9"}
commons-io/commons-io {:mvn/version "2.8.0"}
com.sun.mail/jakarta.mail {:mvn/version "2.0.1"}
;; exception printing
io.aviso/pretty {:mvn/version "0.1.37"}
environ/environ {:mvn/version "1.2.0"}}
:paths ["src"]
:aliases
{:dev
{:extra-deps
{org.clojure/tools.namespace {:mvn/version "RELEASE"}
org.clojure/test.check {:mvn/version "RELEASE"}
org.clojure/tools.deps.alpha {:mvn/version "RELEASE"}
thheller/shadow-cljs {:mvn/version "2.14.1"}
criterium/criterium {:mvn/version "RELEASE"}
mockery/mockery {:mvn/version "RELEASE"}}
:extra-paths ["test" "dev"]}
:repl
{:extra-deps
{com.bhauman/rebel-readline {:mvn/version "RELEASE"}}
:main-opts ["-m" "rebel-readline.main"]}
:kaocha
{:extra-deps {lambdaisland/kaocha {:mvn/version "RELEASE"}}
:main-opts ["-m" "kaocha.runner"]}
:test
{:extra-paths ["test"]
:extra-deps {io.github.cognitect-labs/test-runner
{:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}}
:exec-fn cognitect.test-runner.api/test}
:shadow-cljs
{:main-opts ["-m" "shadow.cljs.devtools.cli"]}
:outdated
{:extra-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}}
:main-opts ["-m" "antq.core"]}}}

51
common/dev/user.clj Normal file
View file

@ -0,0 +1,51 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns user
(:require
[clojure.java.io :as io]
[clojure.pprint :refer [pprint print-table]]
[clojure.repl :refer :all]
[clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as sgen]
[clojure.test :as test]
[clojure.tools.namespace.repl :as repl]
[clojure.walk :refer [macroexpand-all]]
[criterium.core :refer [quick-bench bench with-progress-reporting]]))
;; --- Benchmarking Tools
(defmacro run-quick-bench
[& exprs]
`(with-progress-reporting (quick-bench (do ~@exprs) :verbose)))
(defmacro run-quick-bench'
[& exprs]
`(quick-bench (do ~@exprs)))
(defmacro run-bench
[& exprs]
`(with-progress-reporting (bench (do ~@exprs) :verbose)))
(defmacro run-bench'
[& exprs]
`(bench (do ~@exprs)))
;; --- Development Stuff
(defn- run-tests
([] (run-tests #"^app.common.tests.*"))
([o]
(repl/refresh)
(cond
(instance? java.util.regex.Pattern o)
(test/run-all-tests o)
(symbol? o)
(if-let [sns (namespace o)]
(do (require (symbol sns))
(test/test-vars [(resolve o)]))
(test/test-ns o)))))

13
common/package.json Normal file
View file

@ -0,0 +1,13 @@
{
"name": "penpot-common",
"version": "1.0.0",
"main": "index.js",
"license": "MPL-2.0",
"dependencies": {
"luxon": "^1.27.0"
},
"devDependencies": {
"source-map-support": "^0.5.19",
"ws": "^7.4.6"
}
}

17
common/shadow-cljs.edn Normal file
View file

@ -0,0 +1,17 @@
{:deps {:aliases [:dev]}
;; :http {:port 3448}
;; :nrepl {:port 3447}
:jvm-opts ["-Xmx700m" "-Xms100m" "-XX:+UseSerialGC" "-XX:-OmitStackTraceInFastThrow"]
:builds
{:test
{:target :node-test
:output-to "target/tests.js"
:ns-regexp "^app.common.*-test$"
;; :autorun true
:compiler-options
{:output-feature-set :es-next
:output-wrapper false
:warnings {:fn-deprecated false}}}}}

View file

@ -9,7 +9,7 @@
[app.common.attrs :as attrs]
[app.common.uuid :as uuid]
[app.common.data :as d]
[app.util.transit :as t]
[app.common.transit :as t]
[clojure.walk :as walk]
[cuerdas.core :as str]))
@ -82,13 +82,11 @@
(defn encode-style-value
[v]
#?(:cljs (t/encode v)
:clj (t/encode-str v)))
(t/encode-str v))
(defn decode-style-value
[v]
#?(:cljs (t/decode v)
:clj (t/decode-str v)))
(t/decode-str v))
(defn encode-style
[key val]
@ -235,9 +233,9 @@
(remove empty?)
(mapcat vec)
(distinct))
proc #(process-attr children %1 %2)]
f #(process-attr children %1 %2)]
(persistent!
(transduce xform proc (transient []) children))))
(transduce xform (completing f) (transient []) children))))
(build-block [{:keys [key children] :as paragraph}]
{:key key

View file

@ -0,0 +1,216 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.common.transit
(:require
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[cognitect.transit :as t]
[linked.core :as lk]
[linked.set :as lks]
#?(:cljs ["luxon" :as lxn]))
#?(:clj
(:import
app.common.geom.matrix.Matrix
app.common.geom.point.Point
java.io.ByteArrayInputStream
java.io.ByteArrayOutputStream
java.io.File
java.time.Instant
java.time.Duration
java.time.OffsetDateTime
linked.set.LinkedSet)))
;; --- MISC
#?(:clj
(defn str->bytes
([^String s]
(str->bytes s "UTF-8"))
([^String s, ^String encoding]
(.getBytes s encoding))))
#?(:clj
(defn- bytes->str
([^bytes data]
(bytes->str data "UTF-8"))
([^bytes data, ^String encoding]
(String. data encoding))))
#?(:clj
(def ^:private file-write-handler
(t/write-handler
(constantly "file")
(fn [v] (str v)))))
#?(:cljs
(def bigint-read-handler
(t/read-handler
(fn [value]
(js/parseInt value 10)))))
#?(:cljs
(def uuid-read-handler
(t/read-handler uuid)))
;; --- GEOM
(def point-write-handler
(t/write-handler
(constantly "point")
(fn [v] (into {} v))))
(def point-read-handler
(t/read-handler gpt/map->Point))
(def matrix-write-handler
(t/write-handler
(constantly "matrix")
(fn [v] (into {} v))))
(def matrix-read-handler
(t/read-handler gmt/map->Matrix))
;; --- ORDERED SET
(def ordered-set-write-handler
(t/write-handler
(constantly "ordered-set")
(fn [v] (vec v))))
(def ordered-set-read-handler
(t/read-handler #(into (lk/set) %)))
;; --- DURATION
(def duration-read-handler
#?(:cljs (t/read-handler #(.fromMillis ^js lxn/Duration %))
:clj (t/read-handler #(Duration/ofMillis %))))
(def duration-write-handler
(t/write-handler
(constantly "duration")
(fn [v] (inst-ms v))))
;; --- TIME
(def ^:private instant-read-handler
#?(:clj
(t/read-handler
(fn [v] (-> (Long/parseLong v)
(Instant/ofEpochMilli))))
:cljs
(t/read-handler
(fn [v]
(let [ms (js/parseInt v 10)]
(.fromMillis ^js lxn/DateTime ms))))))
(def ^:private instant-write-handler
(t/write-handler
(constantly "m")
(fn [v] (str (inst-ms v)))))
;; --- HANDLERS
(def +read-handlers+
{"matrix" matrix-read-handler
"ordered-set" ordered-set-read-handler
"point" point-read-handler
"duration" duration-read-handler
"m" instant-read-handler
#?@(:cljs ["n" bigint-read-handler
"u" uuid-read-handler])
})
(def +write-handlers+
#?(:clj
{Matrix matrix-write-handler
Point point-write-handler
Instant instant-write-handler
LinkedSet ordered-set-write-handler
File file-write-handler
OffsetDateTime instant-write-handler}
:cljs
{gmt/Matrix matrix-write-handler
gpt/Point point-write-handler
lxn/DateTime instant-write-handler
lxn/Duration duration-write-handler
lks/LinkedSet ordered-set-write-handler}
))
;; --- Low-Level Api
#?(:clj
(defn reader
([istream]
(reader istream nil))
([istream {:keys [type] :or {type :json}}]
(t/reader istream type {:handlers +read-handlers+}))))
#?(:clj
(defn writer
([ostream]
(writer ostream nil))
([ostream {:keys [type] :or {type :json}}]
(t/writer ostream type {:handlers +write-handlers+}))))
#?(:clj
(defn read!
[reader]
(t/read reader)))
#?(:clj
(defn write!
[writer data]
(t/write writer data)))
;; --- High-Level Api
#?(:clj
(defn encode
([data] (encode data nil))
([data opts]
(with-open [out (ByteArrayOutputStream.)]
(t/write (writer out opts) data)
(.toByteArray out)))))
#?(:clj
(defn decode
([data] (decode data nil))
([data opts]
(with-open [input (ByteArrayInputStream. ^bytes data)]
(t/read (reader input opts))))))
(defn encode-str
([data] (encode-str data nil))
([data opts]
#?(:cljs
(let [t (:type opts :json)
w (t/writer t {:handlers +write-handlers+})]
(t/write w data))
:clj
(->> (encode data opts)
(bytes->str)))))
(defn decode-str
([data] (decode-str data nil))
([data opts]
#?(:cljs
(let [t (:type opts :json)
r (t/reader t {:handlers +read-handlers+})]
(t/read r data))
:clj
(-> (str->bytes data)
(decode opts)))))
(defn transit?
"Checks if a string can be decoded with transit"
[v]
(try
(-> v decode-str nil? not)
(catch #?(:cljs js/SyntaxError :clj Exception) e
false)))

View file

@ -42,7 +42,6 @@
#?(:clj (UUID/fromString s)
:cljs (c/uuid s)))
#?(:clj
(defn custom
([a] (UUID. 0 a))
([b a] (UUID. b a))))
(defn custom
([a] #?(:clj (UUID. 0 a) :cljs (c/uuid (impl/custom 0 a))))
([b a] #?(:clj (UUID. b a) :cljs (c/uuid (impl/custom b a)))))

View file

@ -189,4 +189,10 @@ goog.scope(function() {
self.v1 = v1;
self.v4 = v4;
self.custom = function formatAsUUID(mostSigBits, leastSigBits) {
const most = mostSigBits.toString("16").padStart(16, "0");
const least = leastSigBits.toString("16").padStart(16, "0");
return `${most.substring(0, 8)}-${most.substring(8, 12)}-${most.substring(12)}-${least.substring(0, 4)}-${least.substring(4)}`;
}
});

View file

@ -7,7 +7,6 @@
(ns app.common.version
"A version parsing helper."
(:require
[app.common.data :as d]
[cuerdas.core :as str]))
(def version-re #"^(([A-Za-z]+)\-?)?((\d+)\.(\d+)\.(\d+))(\-?((alpha|prealpha|beta|rc|dev)(\d+)?))?(\-?(\d+))?(\-?g(\w+))$")

View file

@ -4,7 +4,7 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-common-geom-shapes
(ns app.common.geom-shapes-test
(:require
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]

View file

@ -4,7 +4,7 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-common-geom
(ns app.common.geom-test
(:require
[clojure.test :as t]
[app.common.geom.point :as gpt]

View file

@ -4,17 +4,14 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-common-pages-migrations
(ns app.common.pages-migrations-test
(:require
[clojure.test :as t]
[clojure.pprint :refer [pprint]]
[promesa.core :as p]
[mockery.core :refer [with-mock]]
[app.common.data :as d]
[app.common.pages :as cp]
[app.common.pages.migrations :as cpm]
[app.common.uuid :as uuid]
[app.tests.helpers :as th]))
[app.common.uuid :as uuid]))
(t/deftest test-migration-8-1
(let [page-id (uuid/custom 0 0)
@ -43,8 +40,8 @@
res (cpm/migrate-data data)]
(pprint data)
(pprint res)
;; (pprint data)
;; (pprint res)
(t/is (= (dissoc data :version)
(dissoc res :version)))))
@ -86,8 +83,8 @@
res (cpm/migrate-data data)]
(pprint res)
(pprint expct)
;; (pprint res)
;; (pprint expct)
(t/is (= (dissoc expct :version)
(dissoc res :version)))

View file

@ -4,15 +4,12 @@
;;
;; Copyright (c) UXBOX Labs SL
(ns app.tests.test-common-pages
(ns app.common.pages-test
(:require
[clojure.test :as t]
[clojure.pprint :refer [pprint]]
[promesa.core :as p]
[mockery.core :refer [with-mock]]
[app.common.pages :as cp]
[app.common.uuid :as uuid]
[app.tests.helpers :as th]))
[app.common.uuid :as uuid]))
(t/deftest process-change-set-option
(let [file-id (uuid/custom 2 2)

View file

@ -0,0 +1,10 @@
(ns app.common.setup-test
(:require
[clojure.test :as t]))
#?(:cljs
(defmethod t/report [:cljs.test/default :end-run-tests]
[m]
(if (t/successful? m)
(set! (.-exitCode js/process) 0)
(set! (.-exitCode js/process) 1))))

View file

@ -1,9 +1,9 @@
(ns app.test-draft-conversion
(ns app.common.text-test
(:require
[app.common.data :as d]
[app.common.text :as txt]
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]))
[clojure.test :as t :include-macros true]
[clojure.pprint :refer [pprint]]))
(t/deftest test-basic-conversion-roundtrip
(let [text "qwqw 🠒"

31
common/yarn.lock Normal file
View file

@ -0,0 +1,31 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
luxon@^1.27.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.27.0.tgz#ae10c69113d85dab8f15f5e8390d0cbeddf4f00f"
integrity sha512-VKsFsPggTA0DvnxtJdiExAucKdAnwbCCNlMM5ENvHlxubqWd0xhZcdb4XgZ7QFNhaRhilXCFxHuoObP5BNA4PA==
source-map-support@^0.5.19:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
ws@^7.4.6:
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==

View file

@ -21,7 +21,7 @@ tmux -2 new-session -d -s penpot
tmux new-window -t penpot:1 -n 'shadow watch'
tmux select-window -t penpot:1
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
tmux send-keys -t penpot 'npx shadow-cljs watch main' enter
tmux send-keys -t penpot 'clojure -M:dev:shadow-cljs watch main' enter
tmux new-window -t penpot:2 -n 'exporter'
tmux select-window -t penpot:2

View file

@ -1,9 +1,32 @@
{:paths ["src" "vendor" "resources" "../common"]
:deps {}
{:paths ["src" "vendor" "resources" "test"]
:deps
{penpot/common
{:local/root "../common"}
binaryage/devtools {:mvn/version "RELEASE"}
metosin/reitit-core {:mvn/version "0.5.13"}
funcool/beicon {:mvn/version "2021.04.29-0"}
funcool/okulary {:mvn/version "2020.04.14-0"}
funcool/potok {:mvn/version "4.0.0"}
funcool/rumext {:mvn/version "2021.05.12-1"}
funcool/tubax {:mvn/version "2021.05.20-0"}
instaparse/instaparse {:mvn/version "1.4.10"}
}
:aliases
{:outdated
{:extra-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}
org.slf4j/slf4j-nop {:mvn/version "RELEASE"}}
:main-opts ["-m" "antq.core"]}
:dev
{:extra-deps
{thheller/shadow-cljs {:mvn/version "2.14.1"}}}
:shadow-cljs
{:main-opts ["-m" "shadow.cljs.devtools.cli"]}
}}

View file

@ -32,8 +32,7 @@
"postcss": "^8.2.15",
"postcss-clean": "^1.2.2",
"rimraf": "^3.0.0",
"sass": "^1.32.8",
"shadow-cljs": "2.12.6"
"sass": "^1.32.8"
},
"dependencies": {
"date-fns": "^2.21.3",
@ -48,7 +47,7 @@
"react": "~17.0.1",
"react-dom": "~17.0.1",
"react-virtualized": "^9.22.3",
"rxjs": "~7.0.1",
"rxjs": "~7.1.0",
"sax": "^1.2.4",
"source-map-support": "^0.5.16",
"tdigest": "^0.1.1",

View file

@ -1,32 +1,9 @@
{:http {:port 3448}
{:deps {:aliases [:dev]}
:http {:port 3448}
:nrepl {:port 3447}
:jvm-opts ["-Xmx700m" "-Xms100m" "-XX:+UseSerialGC" "-XX:-OmitStackTraceInFastThrow"]
:dev-http {8888 "classpath:public"}
:source-paths ["src", "vendor", "resources", "../common", "tests", "dev"]
:dependencies
[[binaryage/devtools "RELEASE"]
[environ/environ "1.2.0"]
[metosin/reitit-core "0.5.13"]
[expound/expound "0.8.9"]
[danlentz/clj-uuid "0.1.9"]
[frankiesardo/linked "1.3.0"]
[funcool/beicon "2021.04.29-0"]
[funcool/cuerdas "2021.05.09-0"]
[funcool/okulary "2020.04.14-0"]
[funcool/potok "4.0.0"]
[funcool/promesa "6.0.0"]
[funcool/rumext "2021.05.12-1"]
[funcool/tubax "2021.05.20-0"]
[lambdaisland/uri "1.4.54"
:exclusions [org.clojure/data.json]]
[instaparse/instaparse "1.4.10"]]
:builds
{:main
{:target :browser
@ -58,11 +35,11 @@
:anon-fn-naming-policy :off
:source-map-detail-level :all}}}
:tests
:test
{:target :node-test
:output-to "target/tests.js"
:ns-regexp "^app.test-"
:autorun true
:ns-regexp "^app.*-test$"
;; :autorun true
:compiler-options
{:output-feature-set :es8

View file

@ -39,7 +39,7 @@
this)))
(defn tdigest-summary
[td]
[^js td]
(str "samples=" (unchecked-get td "n") "\n"
"Q50=" (.percentile td 0.50) "\n"
"Q75=" (.percentile td 0.75) "\n"

View file

View file

@ -1,4 +1,4 @@
(ns app.test-components-basic
(ns app.components-basic-test
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
@ -29,7 +29,7 @@
(->> state
(the/do-update (dw/select-shape (thp/id :shape1)))
(the/do-watch-update dwl/add-component)
(the/do-watch-update dwl/add-component)
(rx/do
(fn [new-state]
(let [shape1 (thp/get-shape new-state :shape1)
@ -73,7 +73,7 @@
(the/do-update (dw/select-shapes (lks/set
(thp/id :shape1)
(thp/id :shape2))))
(the/do-watch-update dwl/add-component)
(the/do-watch-update dwl/add-component)
(rx/do
(fn [new-state]
(let [shape1 (thp/get-shape new-state :shape1)
@ -125,7 +125,7 @@
(->> state
(the/do-update (dw/select-shape (thp/id :group1)))
(the/do-watch-update dwl/add-component)
(the/do-watch-update dwl/add-component)
(rx/do
(fn [new-state]
(let [[[group shape1 shape2]

View file

@ -1,18 +1,18 @@
(ns app.test-components-sync
(ns app.components-sync-test
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[beicon.core :as rx]
[linked.core :as lks]
[app.test-helpers.events :as the]
[app.test-helpers.pages :as thp]
[app.test-helpers.libraries :as thl]
[app.common.geom.point :as gpt]
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.pages.helpers :as cph]
[app.main.data.workspace.changes :as dwc]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.libraries-helpers :as dwlh]))
[app.main.data.workspace.libraries-helpers :as dwlh]
[app.test-helpers.events :as the]
[app.test-helpers.libraries :as thl]
[app.test-helpers.pages :as thp]
[beicon.core :as rx]
[cljs.pprint :refer [pprint]]
[cljs.test :as t :include-macros true]
[linked.core :as lks]))
(t/use-fixtures :each
{:before thp/reset-idmap!})

View file

@ -0,0 +1,9 @@
(ns app.init-test
(:require
[cljs.test :as t :include-macros true]))
(defmethod t/report [:cljs.test/default :end-run-tests]
[m]
(if (t/successful? m)
(set! (.-exitCode js/process) 0)
(set! (.-exitCode js/process) 1)))

View file

@ -1,16 +1,17 @@
(ns app.test-shapes
(:require [cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[clojure.stacktrace :as stk]
[beicon.core :as rx]
[linked.core :as lks]
[app.test-helpers.events :as the]
[app.test-helpers.pages :as thp]
[app.test-helpers.libraries :as thl]
[app.common.geom.point :as gpt]
[app.common.data :as d]
[app.common.pages.helpers :as cph]
[app.main.data.workspace.libraries :as dwl]))
(ns app.shapes-test
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.pages.helpers :as cph]
[app.main.data.workspace.libraries :as dwl]
[app.test-helpers.events :as the]
[app.test-helpers.libraries :as thl]
[app.test-helpers.pages :as thp]
[beicon.core :as rx]
[cljs.pprint :refer [pprint]]
[cljs.test :as t :include-macros true]
[clojure.stacktrace :as stk]
[linked.core :as lks]))
(t/use-fixtures :each
{:before thp/reset-idmap!})

View file

@ -1,14 +1,15 @@
(ns app.test-helpers.events
(:require [cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[beicon.core :as rx]
[potok.core :as ptk]
[app.common.uuid :as uuid]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.pages :as cp]
[app.common.pages.helpers :as cph]
[app.main.data.workspace :as dw]))
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[beicon.core :as rx]
[potok.core :as ptk]
[app.common.uuid :as uuid]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.pages :as cp]
[app.common.pages.helpers :as cph]
[app.main.data.workspace :as dw]))
;; ---- Helpers to manage global events

View file

@ -1,16 +1,17 @@
(ns app.test-helpers.libraries
(:require [cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[beicon.core :as rx]
[potok.core :as ptk]
[app.common.uuid :as uuid]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.pages :as cp]
[app.common.pages.helpers :as cph]
[app.main.data.workspace :as dw]
[app.main.data.workspace.libraries-helpers :as dwlh]
[app.test-helpers.pages :as thp]))
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[beicon.core :as rx]
[potok.core :as ptk]
[app.common.uuid :as uuid]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.pages :as cp]
[app.common.pages.helpers :as cph]
[app.main.data.workspace :as dw]
[app.main.data.workspace.libraries-helpers :as dwlh]
[app.test-helpers.pages :as thp]))
;; ---- Helpers to manage libraries and synchronization

View file

@ -1,8 +1,9 @@
(ns app.test-util-range-tree
(:require [cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[app.common.geom.point :as gpt]
[app.util.range-tree :as rt]))
(ns app.util.range-tree-test
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[app.common.geom.point :as gpt]
[app.util.range-tree :as rt]))
(defn check-max-height [tree num-nodes])
(defn check-sorted [tree])
@ -109,7 +110,7 @@
(rt/insert 50 :e)
(rt/update 50 :d :xx))]
(t/is (= (rt/get tree 50) [:b :xx :e]))))
(t/testing "Try to update non-existing element"
(let [tree (-> (rt/make-tree)
(rt/insert 100 :a)

View file

@ -1,8 +1,9 @@
(ns app.test-util-simple-math
(:require [cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[app.common.math :as cm]
[app.util.simple-math :as sm]))
(ns app.util.simple-math-test
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[app.common.math :as cm]
[app.util.simple-math :as sm]))
(t/deftest test-parser-inst
(t/testing "Evaluate an empty string"

File diff suppressed because it is too large Load diff