<commit_before>(ns frontend.utils
  (:require [cljs.core :refer [this-as]]
            [sablono.core :as html]))

(defmacro inspect
  "prints the expression '<name> is <value>', and returns the value"
  [value]
  `(do
     (let [name# (quote ~value)
           result# ~value]
       (print (pr-str name#) "is" (pr-str result#))
       result#)))

(defmacro timing
  "Evaluates expr and prints the label and the time it took.
  Returns the value of expr."
  {:added "1.0"}
  [label expr]
  `(let [global-start# (or (aget js/window "__global_time")
                          (aset js/window "__global_time" (.getTime (js/Date.))))
         start# (.getTime (js/Date.))
         ret# ~expr
         global-time# (- (.getTime (js/Date.)) global-start#)]
     (aset js/window "__global_time" (.getTime (js/Date.)))
     (prn (str ~label " elapsed time: " (- (.getTime (js/Date.)) start#) " ms, " global-time# " ms since last"))
     ret#))

(defmacro swallow-errors
  "wraps errors in a try/catch statement, logging issues to the console
   and optionally rethrowing them if configured to do so."
  [& action]
  `(try
     (try ~@action
          (catch js/Error e#
            (merror e#)
            (when (:rethrow-errors? initial-query-map)
              (js/eval "debugger")
              (throw e#))))
     (catch :default e2#
       (merror e2#)
       (when (:rethrow-errors? initial-query-map)
         (js/eval "debugger")
         (throw e2#)))))

(defmacro defrender
  "defs a function which reifies an IRender component that only has a render
  function and splices the body into the render function"
  [name args & body]
  `(defn ~name ~args
     (reify
       om.core/IDisplayName
       (~'display-name [~'_] ~(str name))
       om.core/IRender
       (~'render [~'_] ~@body))))

(defmacro defrendermethod
  "defs a method which reifies an IRender component that only has a render
  function and splices the body into the render function"
  [multifn dispatch-val args & body]
  `(defmethod ~multifn ~dispatch-val ~args
     (reify
       om.core/IDisplayName
       (~'display-name [~'_] ~(str multifn " (" dispatch-val ")"))
       om.core/IRender
       (~'render [~'_] ~@body))))

(defmacro html [body]
  `(if-not (:render-colors? initial-query-map)
     (html/html ~body)
     (let [body# ~body]
       (try
         (let [[tag# & rest#] body#
               attrs# (if (map? (first rest#))
                        (first rest#)
                        {})
               rest# (if (map? (first rest#))
                       (rest rest#)
                       rest#)]
           (html/html (vec (concat [tag# (assoc-in attrs# [:style :border] (str "5px solid rgb("
                                                                                (rand-int 255)
                                                                                ","
                                                                                (rand-int 255)
                                                                                ","
                                                                                (rand-int 255)
                                                                                ")"))]
                                   rest#))))
         (catch :default e#
           (html/html body#))))))

(def ^:private component-name-symbol
  "A symbol which will be (lexically) bound to the current component name inside
  a component form."
  (gensym "component-name"))

(defmacro component
  "Assigns the current component's name as the data-component attribute of a
  React element. `body` is wrapped in an implicit `do`, and should evaluate to a
  React element (such as a call to `sablono.core/html`). In an Om Next
  component, the component name is the fully-qualified name of the component
  class; in an Om Previous component or a pure functional component, it's the
  fully-qualified name of the (outermost) function generating the component
  contents.

  `component` also sets the component name that `element` will use to build an
  element name.

  Examples:

  ;; Functional stateless component
  (defn fancy-button [on-click title]
    (component
      (html [:button {:on-click on-click} title])))

  ;; Om Previous component
  (defn person [person-data owner]
    (reify
      om/IRender
      (render [_]
        (component
          (html
            [:div
             [:.name (:name person-data)]
             [:.hair-color (:hair-color person-data)]]))))

  ;; Om Next component
  (defui Post
    static om/IQuery
    (query [this]
      [:title :author :content])
    Object
    (render [this]
      (let [{:keys [title author content]} (om/props)]
        (component
          (html
           [:article
            [:h1 title]
            [:h2 \"by \" author]
            [:div.body content]])))))"
  [& body]
  (let [call-component* `(frontend.utils/component* ~component-name-symbol ~@body)]
    (if-let [fn-scope (first (:fn-scope &env))]
      ;; Om Previous or pure functional component
      (let [name (:name fn-scope)
            ns (-> fn-scope :info :ns)
            full-name (str ns "/" name)]
        `(let [~component-name-symbol ~full-name]
           ~call-component*))

      ;; Om Next class
      `(this-as this#
         (assert (goog.object/containsKey (.-constructor this#) "displayName")
                 (str
                  "Couldn't find a name for this component. Make sure the"
                  "component macro is at the top of the component's render"
                  "method."))
         (let [~component-name-symbol (.-displayName (.-constructor this#))]
           ~call-component*)))))

(defmacro element
  "Assigns an element name (a data-element attribute) to a React element.
  `body` is wrapped in an implicit `do`, and should evaluate to a React
  element (such as a call to `sablono.core/html`).`name` is an unqualified
  keyword. The full element name will take the form
  `component-namespace/component-name/element-name`

  The element macro is used to give a component-namespaced identifier to a DOM
  node which is passed to another component as a param. Without this, the
  element's component's stylesheet would have no safe way to select the correct
  DOM node.

  Example:

  (ns example.core)

  (defn card [title content]<commit_msg>Correct spaces in error message<commit_after>(ns frontend.utils
  (:require [cljs.core :refer [this-as]]
            [sablono.core :as html]))

(defmacro inspect
  "prints the expression '<name> is <value>', and returns the value"
  [value]
  `(do
     (let [name# (quote ~value)
           result# ~value]
       (print (pr-str name#) "is" (pr-str result#))
       result#)))

(defmacro timing
  "Evaluates expr and prints the label and the time it took.
  Returns the value of expr."
  {:added "1.0"}
  [label expr]
  `(let [global-start# (or (aget js/window "__global_time")
                          (aset js/window "__global_time" (.getTime (js/Date.))))
         start# (.getTime (js/Date.))
         ret# ~expr
         global-time# (- (.getTime (js/Date.)) global-start#)]
     (aset js/window "__global_time" (.getTime (js/Date.)))
     (prn (str ~label " elapsed time: " (- (.getTime (js/Date.)) start#) " ms, " global-time# " ms since last"))
     ret#))

(defmacro swallow-errors
  "wraps errors in a try/catch statement, logging issues to the console
   and optionally rethrowing them if configured to do so."
  [& action]
  `(try
     (try ~@action
          (catch js/Error e#
            (merror e#)
            (when (:rethrow-errors? initial-query-map)
              (js/eval "debugger")
              (throw e#))))
     (catch :default e2#
       (merror e2#)
       (when (:rethrow-errors? initial-query-map)
         (js/eval "debugger")
         (throw e2#)))))

(defmacro defrender
  "defs a function which reifies an IRender component that only has a render
  function and splices the body into the render function"
  [name args & body]
  `(defn ~name ~args
     (reify
       om.core/IDisplayName
       (~'display-name [~'_] ~(str name))
       om.core/IRender
       (~'render [~'_] ~@body))))

(defmacro defrendermethod
  "defs a method which reifies an IRender component that only has a render
  function and splices the body into the render function"
  [multifn dispatch-val args & body]
  `(defmethod ~multifn ~dispatch-val ~args
     (reify
       om.core/IDisplayName
       (~'display-name [~'_] ~(str multifn " (" dispatch-val ")"))
       om.core/IRender
       (~'render [~'_] ~@body))))

(defmacro html [body]
  `(if-not (:render-colors? initial-query-map)
     (html/html ~body)
     (let [body# ~body]
       (try
         (let [[tag# & rest#] body#
               attrs# (if (map? (first rest#))
                        (first rest#)
                        {})
               rest# (if (map? (first rest#))
                       (rest rest#)
                       rest#)]
           (html/html (vec (concat [tag# (assoc-in attrs# [:style :border] (str "5px solid rgb("
                                                                                (rand-int 255)
                                                                                ","
                                                                                (rand-int 255)
                                                                                ","
                                                                                (rand-int 255)
                                                                                ")"))]
                                   rest#))))
         (catch :default e#
           (html/html body#))))))

(def ^:private component-name-symbol
  "A symbol which will be (lexically) bound to the current component name inside
  a component form."
  (gensym "component-name"))

(defmacro component
  "Assigns the current component's name as the data-component attribute of a
  React element. `body` is wrapped in an implicit `do`, and should evaluate to a
  React element (such as a call to `sablono.core/html`). In an Om Next
  component, the component name is the fully-qualified name of the component
  class; in an Om Previous component or a pure functional component, it's the
  fully-qualified name of the (outermost) function generating the component
  contents.

  `component` also sets the component name that `element` will use to build an
  element name.

  Examples:

  ;; Functional stateless component
  (defn fancy-button [on-click title]
    (component
      (html [:button {:on-click on-click} title])))

  ;; Om Previous component
  (defn person [person-data owner]
    (reify
      om/IRender
      (render [_]
        (component
          (html
            [:div
             [:.name (:name person-data)]
             [:.hair-color (:hair-color person-data)]]))))

  ;; Om Next component
  (defui Post
    static om/IQuery
    (query [this]
      [:title :author :content])
    Object
    (render [this]
      (let [{:keys [title author content]} (om/props)]
        (component
          (html
           [:article
            [:h1 title]
            [:h2 \"by \" author]
            [:div.body content]])))))"
  [& body]
  (let [call-component* `(frontend.utils/component* ~component-name-symbol ~@body)]
    (if-let [fn-scope (first (:fn-scope &env))]
      ;; Om Previous or pure functional component
      (let [name (:name fn-scope)
            ns (-> fn-scope :info :ns)
            full-name (str ns "/" name)]
        `(let [~component-name-symbol ~full-name]
           ~call-component*))

      ;; Om Next class
      `(this-as this#
         (assert (goog.object/containsKey (.-constructor this#) "displayName")
                 (str
                  "Couldn't find a name for this component. Make sure the "
                  "component macro is at the top of the component's render "
                  "method."))
         (let [~component-name-symbol (.-displayName (.-constructor this#))]
           ~call-component*)))))

(defmacro element
  "Assigns an element name (a data-element attribute) to a React element.
  `body` is wrapped in an implicit `do`, and should evaluate to a React
  element (such as a call to `sablono.core/html`).`name` is an unqualified
  keyword. The full element name will take the form
  `component-namespace/component-name/element-name`

  The element macro is used to give a component-namespaced identifier to a DOM
  node which is passed to another component as a param. Without this, the
  element's component's stylesheet would have no safe way to select the correct
  DOM node.

  Example:

  (ns example.core)

  (defn card [title content]
{'fraction_non_alphanumeric': 0.11838790931989925, 'fraction_numerical': 0.0026763224181360202, 'mean_word_length': 1.823960880195599, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 38, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3487656', 'n_tokens_mistral': 3673, 'n_tokens_neox': 3519, 'n_words': 1239}