mirror of
https://github.com/penpot/penpot.git
synced 2025-01-09 08:20:45 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
c1daa4a4c4
7 changed files with 160 additions and 164 deletions
|
@ -11,7 +11,7 @@
|
|||
(:require
|
||||
#?(:clj [clojure.spec.alpha :as s]
|
||||
:cljs [cljs.spec.alpha :as s])
|
||||
|
||||
[app.common.data.macros :as dm]
|
||||
;; NOTE: don't remove this, causes exception on advanced build
|
||||
;; because of some strange interaction with cljs.spec.alpha and
|
||||
;; modules splitting.
|
||||
|
@ -31,88 +31,179 @@
|
|||
(def max-safe-int (int 1e6))
|
||||
(def min-safe-int (int -1e6))
|
||||
|
||||
;; --- Conformers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; DEFAULT SPECS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn uuid-conformer
|
||||
[v]
|
||||
(if (uuid? v)
|
||||
v
|
||||
(if (string? v)
|
||||
(if (re-matches uuid-rx v)
|
||||
(uuid/uuid v)
|
||||
::s/invalid)
|
||||
::s/invalid)))
|
||||
;; --- SPEC: uuid
|
||||
|
||||
(defn boolean-conformer
|
||||
[v]
|
||||
(if (boolean? v)
|
||||
v
|
||||
(if (string? v)
|
||||
(if (re-matches #"^(?:t|true|false|f|0|1)$" v)
|
||||
(contains? #{"t" "true" "1"} v)
|
||||
::s/invalid)
|
||||
::s/invalid)))
|
||||
(letfn [(conformer [v]
|
||||
(if (uuid? v)
|
||||
v
|
||||
(if (string? v)
|
||||
(if (re-matches uuid-rx v)
|
||||
(uuid/uuid v)
|
||||
::s/invalid)
|
||||
::s/invalid)))
|
||||
(unformer [v]
|
||||
(dm/str v))]
|
||||
(s/def ::uuid (s/conformer conformer unformer)))
|
||||
|
||||
(defn boolean-unformer
|
||||
[v]
|
||||
(if v "true" "false"))
|
||||
;; --- SPEC: boolean
|
||||
|
||||
(defn- number-conformer
|
||||
[v]
|
||||
(cond
|
||||
(number? v) v
|
||||
(str/numeric? v)
|
||||
#?(:clj (Double/parseDouble v)
|
||||
:cljs (js/parseFloat v))
|
||||
:else ::s/invalid))
|
||||
(letfn [(conformer [v]
|
||||
(if (boolean? v)
|
||||
v
|
||||
(if (string? v)
|
||||
(if (re-matches #"^(?:t|true|false|f|0|1)$" v)
|
||||
(contains? #{"t" "true" "1"} v)
|
||||
::s/invalid)
|
||||
::s/invalid)))
|
||||
(unformer [v]
|
||||
(if v "true" "false"))]
|
||||
(s/def ::boolean (s/conformer conformer unformer)))
|
||||
|
||||
(defn- integer-conformer
|
||||
[v]
|
||||
(cond
|
||||
(integer? v) v
|
||||
(string? v)
|
||||
(if (re-matches #"^[-+]?\d+$" v)
|
||||
#?(:clj (Long/parseLong v)
|
||||
:cljs (js/parseInt v 10))
|
||||
::s/invalid)
|
||||
:else ::s/invalid))
|
||||
;; --- SPEC: number
|
||||
|
||||
(defn- color-conformer
|
||||
[v]
|
||||
(if (and (string? v) (re-matches #"^#(?:[0-9a-fA-F]{3}){1,2}$" v))
|
||||
v
|
||||
::s/invalid))
|
||||
(letfn [(conformer [v]
|
||||
(cond
|
||||
(number? v) v
|
||||
(str/numeric? v) #?(:cljs (js/parseFloat v)
|
||||
:clj (Double/parseDouble v))
|
||||
:else ::s/invalid))]
|
||||
(s/def ::number (s/conformer conformer str)))
|
||||
|
||||
(defn keyword-conformer
|
||||
[v]
|
||||
(cond
|
||||
(keyword? v)
|
||||
v
|
||||
;; --- SPEC: integer
|
||||
|
||||
(string? v)
|
||||
(keyword v)
|
||||
(letfn [(conformer [v]
|
||||
(cond
|
||||
(integer? v) v
|
||||
(string? v)
|
||||
(if (re-matches #"^[-+]?\d+$" v)
|
||||
#?(:clj (Long/parseLong v)
|
||||
:cljs (js/parseInt v 10))
|
||||
::s/invalid)
|
||||
:else ::s/invalid))]
|
||||
(s/def ::integer (s/conformer conformer str)))
|
||||
|
||||
:else
|
||||
::s/invalid))
|
||||
;; --- SPEC: keyword
|
||||
|
||||
(letfn [(conformer [v]
|
||||
(cond
|
||||
(keyword? v) v
|
||||
(string? v) (keyword v)
|
||||
:else ::s/invalid))
|
||||
|
||||
;; --- Default Specs
|
||||
(unformer [v]
|
||||
(name v))]
|
||||
(s/def ::keyword (s/conformer conformer unformer)))
|
||||
|
||||
;; --- SPEC: email
|
||||
|
||||
(def email-re #"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+")
|
||||
|
||||
(defn parse-email
|
||||
[s]
|
||||
(some->> s (re-seq email-re) first))
|
||||
|
||||
(letfn [(conformer [v]
|
||||
(or (parse-email v) ::s/invalid))
|
||||
(unformer [v]
|
||||
(dm/str v))]
|
||||
(s/def ::email (s/conformer conformer unformer)))
|
||||
|
||||
;; -- SPEC: uri
|
||||
|
||||
(letfn [(conformer [s]
|
||||
(cond
|
||||
(u/uri? s) s
|
||||
(string? s) (u/uri s)
|
||||
:else ::s/invalid))
|
||||
(unformer [v]
|
||||
(dm/str v))]
|
||||
(s/def ::uri (s/conformer conformer unformer)))
|
||||
|
||||
;; --- SPEC: color string
|
||||
|
||||
(letfn [(conformer [v]
|
||||
(if (and (string? v) (re-matches #"^#(?:[0-9a-fA-F]{3}){1,2}$" v))
|
||||
v
|
||||
::s/invalid))
|
||||
(unformer [v]
|
||||
(dm/str v))]
|
||||
(s/def ::rgb-color-str (s/conformer conformer unformer)))
|
||||
|
||||
;; --- SPEC: set of Keywords
|
||||
|
||||
(letfn [(conform-fn [dest s]
|
||||
(let [xform (keep (fn [s]
|
||||
(cond
|
||||
(string? s) (keyword s)
|
||||
(keyword? s) s
|
||||
:else nil)))]
|
||||
(cond
|
||||
(set? s) (into dest xform s)
|
||||
(string? s) (into dest xform (str/words s))
|
||||
:else ::s/invalid)))]
|
||||
|
||||
(s/def ::set-of-keywords
|
||||
(s/conformer
|
||||
(fn [s] (conform-fn #{} s))
|
||||
(fn [s] (str/join " " (map name s)))))
|
||||
|
||||
(s/def ::vec-of-keywords
|
||||
(s/conformer
|
||||
(fn [s] (conform-fn [] s))
|
||||
(fn [s] (str/join " " (map name s))))))
|
||||
|
||||
;; --- SPEC: set-of-emails
|
||||
|
||||
(letfn [(conformer [v]
|
||||
(cond
|
||||
(string? v)
|
||||
(into #{} (re-seq email-re v))
|
||||
|
||||
(or (set? v) (sequential? v))
|
||||
(->> (str/join " " v)
|
||||
(re-seq email-re)
|
||||
(into #{}))
|
||||
|
||||
:else ::s/invalid))
|
||||
(unformer [v]
|
||||
(str/join " " v))]
|
||||
(s/def ::set-of-emails (s/conformer conformer unformer)))
|
||||
|
||||
;; --- SPEC: set-of-str
|
||||
|
||||
(def non-empty-strings-xf
|
||||
(comp
|
||||
(filter string?)
|
||||
(remove str/empty?)
|
||||
(remove str/blank?)))
|
||||
|
||||
(letfn [(conformer [s]
|
||||
(cond
|
||||
(string? s) (->> (str/split s #"\s*,\s*")
|
||||
(into #{} non-empty-strings-xf))
|
||||
(set? s) (into #{} non-empty-strings-xf s)
|
||||
:else ::s/invalid))
|
||||
(unformer [s]
|
||||
(str/join "," s))]
|
||||
(s/def ::set-of-str (s/conformer conformer unformer)))
|
||||
|
||||
;; --- SPECS WITHOUT CONFORMER
|
||||
|
||||
(s/def ::keyword (s/conformer keyword-conformer name))
|
||||
(s/def ::inst inst?)
|
||||
(s/def ::string string?)
|
||||
(s/def ::color (s/conformer color-conformer str))
|
||||
(s/def ::uuid (s/conformer uuid-conformer str))
|
||||
(s/def ::boolean (s/conformer boolean-conformer boolean-unformer))
|
||||
(s/def ::number (s/conformer number-conformer str))
|
||||
(s/def ::integer (s/conformer integer-conformer str))
|
||||
(s/def ::not-empty-string (s/and string? #(not (str/empty? %))))
|
||||
(s/def ::url string?)
|
||||
(s/def ::fn fn?)
|
||||
(s/def ::id ::uuid)
|
||||
|
||||
(s/def ::set-of-string (s/every string? :kind set?))
|
||||
(s/def ::coll-of-uuid (s/every uuid?))
|
||||
;; NOTE: this is a coercerless version of `::set-of-str` spec
|
||||
(s/def ::set-of-string (s/every ::string :kind set?))
|
||||
(s/def ::coll-of-uuid (s/every ::uuid))
|
||||
(s/def ::set-of-uuid (s/every ::uuid :kind set?))
|
||||
|
||||
(defn bytes?
|
||||
"Test if a first parameter is a byte
|
||||
|
@ -140,87 +231,6 @@
|
|||
(>= % min-safe-int)
|
||||
(<= % max-safe-int)))
|
||||
|
||||
|
||||
;; --- SPEC: set of Keywords
|
||||
|
||||
(letfn [(conform-fn [dest s]
|
||||
(let [xform (keep (fn [s]
|
||||
(cond
|
||||
(string? s) (keyword s)
|
||||
(keyword? s) s
|
||||
:else nil)))]
|
||||
(cond
|
||||
(set? s) (into dest xform s)
|
||||
(string? s) (into dest xform (str/words s))
|
||||
:else ::s/invalid)))]
|
||||
|
||||
(s/def ::set-of-keywords
|
||||
(s/conformer
|
||||
(fn [s] (conform-fn #{} s))
|
||||
(fn [s] (str/join " " (map name s)))))
|
||||
|
||||
(s/def ::vec-of-keywords
|
||||
(s/conformer
|
||||
(fn [s] (conform-fn [] s))
|
||||
(fn [s] (str/join " " (map name s))))))
|
||||
|
||||
;; --- SPEC: email
|
||||
|
||||
(def email-re #"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+")
|
||||
|
||||
(defn parse-email
|
||||
[s]
|
||||
(some->> s (re-seq email-re) first))
|
||||
|
||||
(s/def ::email
|
||||
(s/conformer
|
||||
(fn [v]
|
||||
(or (parse-email v) ::s/invalid))
|
||||
str))
|
||||
|
||||
(s/def ::set-of-emails
|
||||
(s/conformer
|
||||
(fn [v]
|
||||
(cond
|
||||
(string? v)
|
||||
(into #{} (re-seq email-re v))
|
||||
|
||||
(or (set? v) (sequential? v))
|
||||
(->> (str/join " " v)
|
||||
(re-seq email-re)
|
||||
(into #{}))
|
||||
|
||||
:else ::s/invalid))
|
||||
|
||||
(fn [v]
|
||||
(str/join " " v))))
|
||||
|
||||
(s/def ::uri
|
||||
(s/conformer
|
||||
(fn [s]
|
||||
(cond
|
||||
(u/uri? s) s
|
||||
(string? s) (u/uri s)
|
||||
:else ::s/invalid))
|
||||
str))
|
||||
|
||||
;; --- SPEC: set-of-str
|
||||
|
||||
(s/def ::set-of-str
|
||||
(s/conformer
|
||||
(fn [s]
|
||||
(let [xform (comp
|
||||
(filter string?)
|
||||
(remove str/empty?)
|
||||
(remove str/blank?))]
|
||||
(cond
|
||||
(string? s) (->> (str/split s #"\s*,\s*")
|
||||
(into #{} xform))
|
||||
(set? s) (into #{} xform s)
|
||||
:else ::s/invalid)))
|
||||
(fn [s]
|
||||
(str/join "," s))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; MACROS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -433,7 +433,7 @@
|
|||
(defn detach-comment-thread
|
||||
"Detach comment threads that are inside a frame when that frame is deleted"
|
||||
[ids]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(us/assert! ::us/coll-of-uuid ids)
|
||||
|
||||
(ptk/reify ::detach-comment-thread
|
||||
ptk/WatchEvent
|
||||
|
|
|
@ -54,9 +54,6 @@
|
|||
:opt-un [::created-at
|
||||
::modified-at]))
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every ::us/uuid :kind set?))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Initialization
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -783,7 +780,7 @@
|
|||
|
||||
(defn move-files
|
||||
[{:keys [ids project-id] :as params}]
|
||||
(us/assert ::set-of-uuid ids)
|
||||
(us/assert ::us/set-of-uuid ids)
|
||||
(us/assert ::us/uuid project-id)
|
||||
(ptk/reify ::move-files
|
||||
IDeref
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
[app.main.streams :as ms]
|
||||
[app.util.router :as rt]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(declare handle-interrupt)
|
||||
|
@ -141,11 +140,10 @@
|
|||
(rx/catch #(rx/throw {:type :update-comment-thread-position}))
|
||||
(rx/ignore))))))))
|
||||
|
||||
|
||||
;; Move comment threads that are inside a frame when that frame is moved"
|
||||
(defmethod ptk/resolve ::move-frame-comment-threads
|
||||
[_ ids]
|
||||
(us/assert! :spec (s/coll-of uuid?) :val ids)
|
||||
(us/assert! ::us/coll-of-uuid ids)
|
||||
(ptk/reify ::move-frame-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
|
|
@ -33,15 +33,9 @@
|
|||
[linked.set :as lks]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every uuid? :kind set?))
|
||||
|
||||
(s/def ::ordered-set-of-uuid
|
||||
(s/every uuid? :kind d/ordered-set?))
|
||||
|
||||
(s/def ::set-of-string
|
||||
(s/every string? :kind set?))
|
||||
|
||||
(defn interrupt? [e] (= e :interrupt))
|
||||
|
||||
;; --- Selection Rect
|
||||
|
|
|
@ -130,12 +130,9 @@
|
|||
(rx/of (dch/commit-changes changes))
|
||||
(rx/empty))))))
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every ::us/uuid :kind set?))
|
||||
|
||||
(defn delete-shapes
|
||||
[ids]
|
||||
(us/assert ::set-of-uuid ids)
|
||||
(us/assert ::us/set-of-uuid ids)
|
||||
(ptk/reify ::delete-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
|
|
|
@ -162,4 +162,4 @@
|
|||
|
||||
(s/def ::email ::us/email)
|
||||
(s/def ::not-empty-string ::us/not-empty-string)
|
||||
(s/def ::color ::us/color)
|
||||
(s/def ::color ::us/rgb-color-str)
|
||||
|
|
Loading…
Reference in a new issue