0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-15 17:21:17 -05:00
penpot/frontend/src/uxbox/util/data.cljs

186 lines
4.6 KiB
Text
Raw Normal View History

2016-03-01 20:18:42 +02:00
;; 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) 2015-2019 Andrey Antukh <niwi@niwi.nz>
2016-03-01 20:18:42 +02:00
(ns uxbox.util.data
"A collection of data transformation utils."
(:require [cljs.reader :as r]
[cuerdas.core :as str]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data structure manipulation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn index-by
"Return a indexed map of the collection
keyed by the result of executing the getter
over each element of the collection."
[getter coll]
2015-12-28 13:31:12 +02:00
(persistent!
(reduce #(assoc! %1 (getter %2) %2) (transient {}) coll)))
(def index-by-id #(index-by :id %))
2015-12-26 15:18:36 +02:00
(defn remove-nil-vals
"Given a map, return a map removing key-value
pairs when value is `nil`."
[data]
(into {} (remove (comp nil? second) data)))
2015-12-29 15:51:32 +02:00
(defn without-keys
"Return a map without the keys provided
in the `keys` parameter."
[data keys]
(persistent!
(reduce #(dissoc! %1 %2) (transient data) keys)))
(defn dissoc-in
[m [k & ks :as keys]]
(if ks
(if-let [nextmap (get m k)]
(let [newmap (dissoc-in nextmap ks)]
(if (seq newmap)
(assoc m k newmap)
(dissoc m k)))
m)
(dissoc m k)))
(defn index-of
"Return the first index when appears the `v` value
in the `coll` collection."
[coll v]
(first (keep-indexed (fn [idx x]
(when (= v x) idx))
coll)))
2016-03-30 20:56:44 +03:00
(defn replace-by-id
2017-03-25 19:35:54 +01:00
([value]
(map (fn [item]
2016-03-30 20:56:44 +03:00
(if (= (:id item) (:id value))
value
2017-03-25 19:35:54 +01:00
item))))
([coll value]
(sequence (replace-by-id value) coll)))
2016-04-02 11:17:51 +03:00
(defn deep-merge
"Like merge, but merges maps recursively."
[& maps]
(if (every? map? maps)
(apply merge-with deep-merge maps)
(last maps)))
(defn conj-or-disj
"Given a set, and an element remove that element from set
if it exists or add it if it does not exists."
[s v]
(if (contains? s v)
(disj s v)
(conj s v)))
2017-03-25 19:35:54 +01:00
(defn seek
([pred coll]
(seek pred coll nil))
([pred coll not-found]
(reduce (fn [_ x]
(if (pred x)
(reduced x)
not-found))
not-found coll)))
2016-09-22 22:33:04 +03:00
;; --- String utils
(def +uuid-re+
2016-11-06 18:03:50 +01:00
#"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
2016-09-22 22:33:04 +03:00
(defn uuid-str?
[v]
(and (string? v)
(re-seq +uuid-re+ v)))
;; --- Interop
(defn jscoll->vec
"Convert array like js object into vector."
[v]
(-> (clj->js [])
(.-slice)
(.call v)
(js->clj)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Numbers Parsing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2016-01-06 21:04:50 +02:00
(defn nan?
[v]
(js/isNaN v))
(defn read-string
[v]
(r/read-string v))
(defn parse-int
([v]
2016-07-09 15:04:24 +03:00
(parse-int v nil))
([v default]
(let [v (js/parseInt v 10)]
(if (or (not v) (nan? v))
default
v))))
2016-01-07 01:24:11 +02:00
(defn parse-float
([v]
2016-07-09 15:04:24 +03:00
(parse-float v nil))
2016-01-07 01:24:11 +02:00
([v default]
(let [v (js/parseFloat v)]
(if (or (not v) (nan? v))
default
v))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Other
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn classnames
[& params]
{:pre [(even? (count params))]}
(str/join " " (reduce (fn [acc [k v]]
(if (true? v)
(conj acc (name k))
acc))
[]
(partition 2 params))))
;; (defn normalize-attrs
;; [m]
;; (letfn [(transform [[k v]]
;; (cond
;; (or (= k :class) (= k :class-name))
;; ["className" v]
;; (or (keyword? k) (string? k))
;; [(str/camel (name k)) v]
;; :else
;; [k v]))
;; (walker [x]
;; (if (map? x)
;; (into {} (map tf) x)
;; x))]
;; (walk/postwalk walker m)))
(defn normalize-props
[props]
(clj->js props :keyword-fn (fn [key]
(if (or (= key :class) (= key :class-name))
"className"
(str/camel (name key))))))
;; (defmacro mirror-map [& fields]
;; (let [keys# (map #(keyword (name %)) fields)
;; vals# fields]
;; (apply hash-map (interleave keys# vals#))))