<commit_before>(ns pp-client.html
  (:require
    [pp-client.dom :refer [by-id set-body!]]
    [pp-client.util :refer [js-log log]]
    [quiescent :include-macros true]
    [sablono.core :as sablono :include-macros true]
    [secretary.core :as secretary]
    [pp-client.data :refer [format-input]]))

(def state (atom {:success? false :error? false :value ""}))

;;------------------------------------------------------------------------------
;; URLs
;;------------------------------------------------------------------------------

(defn- url [path] path)
  ;;(if-let [base-href (:base-href config)]
    ;;(str (replace base-href #"/$" "") path)
    ;;path))

;;------------------------------------------------------------------------------
;; Event triggers
;;------------------------------------------------------------------------------
(defn- on-format [response]
  ;;(js-log (str response))
  (swap! state assoc :value response :success? true :error? false))

(defn- on-error [response]
  (if (= (:status response) 400)
    (let [resp (:response response)]
      (swap! state conj resp {:success? false :error? true}))
    (throw (:status-text response))))

(defn- on-style-change [evt]
  (aset js/window "location" "hash" (str "/format/" (.-value (.-target evt)))))

(defn- on-btn-click [evt]
    (format-input state on-format on-error))

;;------------------------------------------------------------------------------
;; Footer
;;------------------------------------------------------------------------------

(def github-url "https://github.com/comamitc/pretty-print.net")
(def issues-url "https://github.com/comamitc/pretty-print.net/issues")
(def docs-url "http://pretty-print.net/#/about")

(defn footer-docs-list []
  (sablono/html
  [:div.col-ace4b
    [:ul
      [:li [:a.ftr-link-67c8e {:href docs-url} "Rationale"]]
      [:li [:a.ftr-link-67c8e {:href github-url} "GitHub"]]
      [:li [:a.ftr-link-67c8e {:href issues-url} "Issues"]]]]))

(quiescent/defcomponent footer-learn-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Learn"]
    [:ul
      [:li [:a.ftr-link-67c8e {:href (url "/rationale")} "Rationale"]]
      [:li [:a.ftr-link-67c8e {:href (url "/faq")} "FAQ"]]]]))

(quiescent/defcomponent footer-community-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Community"]
    [:ul
      ;;[:li [:a.ftr-link-67c8e {:href mailing-list-url}
      ;;  "Mailing List" [:i.fa.fa-external-link]]]
      ;; TODO: either make this a link or figure out how to style it as a non-link
      [:li [:a.ftr-link-67c8e {:href "#"} "IRC: #clojurescript"]]]]))

(quiescent/defcomponent footer-contribute-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Contribute"]
    [:ul
      [:li [:a.ftr-link-67c8e {:href github-url}
        "GitHub" [:i.fa.fa-external-link]]]
      [:li [:a.ftr-link-67c8e {:href issues-url}
        "Issues" [:i.fa.fa-external-link]]]]]))

(def pp-license-url
  "https://github.com/comamitc/pretty-print.net/blob/master/LICENSE.md")

(defn footer-bottom []
  (sablono/html
  [:div.bottom-31b43
    [:div.left-1764b
      [:p.small-14fbc
        "pretty-print.net is released under the "
        [:a {:href pp-license-url} "MIT License"] "."]]
    [:div.right-e461e
      [:a.ftr-home-link-2c3b4 {:href (url "/")} "pretty-print"
        [:span.ftr-info-a5716 ".net"]]]
    [:div.clr-43e49]]))

(defn footer []
  (sablono/html
  [:div.ftr-outer-6bcd3
    [:div.ftr-inner-557c9
      (footer-docs-list)
      ;;(footer-learn-list)
      ;;(footer-community-list)
      ;;(footer-contribute-list)
      [:div.clr-43e49]
      (footer-bottom)]]))

;;------------------------------------------------------------------------------
;; Header
;;------------------------------------------------------------------------------

(quiescent/defcomponent InputOptions [new-state]
  (sablono/html
    [:select#inputSelect.big-select-51b29
      {:on-change #(on-style-change %1) :value (:id new-state)}
      [:optgroup {:label "Clojure"}
        [:option {:value "clj"} "Clojure Code"]
        [:option {:value "edn"} "EDN"]
      ;;[:optgroup {:label "JavaScript"}
      ;;  [:option {:value "js"} "JavaScript Code"]
      ;;  [:option {:value "json"} "JSON"]]
        ]]))

(quiescent/defcomponent Header [state]
  (sablono/html
    [:header.header-outer-c5e7d
      [:div.header-inner-0f889
        [:div.left-9467a
          [:a.home-link-e4c1e {:href ""}
            "pretty-print"
            [:span.net-84e9a ".net"]]]
        [:div.right-1dd94
          (InputOptions state)]
        [:div.clr-217e3]]]))

(defn HeaderNoState []
  (sablono/html
    [:header.header-outer-c5e7d
      [:div.header-inner-0f889
        [:div.left-9467a
          [:a.home-link-e4c1e {:href ""}
            "pretty-print"
            [:span.net-84e9a ".net"]]]
        [:div.clr-217e3]]]))

;;------------------------------------------------------------------------------
;; Body
;;------------------------------------------------------------------------------


(quiescent/defcomponent SettingsAction [settings]
  (sablono/html
    [:div.settings-wrapper-751dc
      [:div.settings-hdr-fa6ca "Settings"]
      (map 
        (fn [[k v]] 
          [:div.setting-e0ddb
            [:input (assoc v :on-change #(swap! (get-in @state [:settings k]) assoc :value (-> % .-target .-value)))]]) settings)]))

(quiescent/defcomponent FormatAction [new-state]
  (sablono/html
    [:div
      [:button#formatBtn.btn-2d976 
          {:on-click #(on-btn-click %1) 
           :disabled (if (empty? (:value new-state)) true false)} 
            "Format"]
        (when (:error? new-state)
          [:div.error-disp-7c4aa
            [:i.fa.fa-times-circle.fa-2] 
            [:span.err-ttl-0867b "Format Error"]
              [:div.msg-6f5ee (:msg new-state)]
              (when (some? (:line new-state))
                [:div.line-b55e8 (str "@line: " (:line new-state))
              (when (some? (:column new-state))
                (str "; column: " (:column new-state)))])])
        (when (:success? new-state)
          [:div.success-disp-3a51b
            [:i.fa.fa-check-circle.fa-2]
            [:span.success-ttl-390ee "Success"]])]))

(quiescent/defcomponent RightBody [new-state]
  (sablono/html
    [:div.right-body-caf9a
      (SettingsAction (:settings new-state))
      (FormatAction new-state)]))

(quiescent/defcomponent LeftBody [new-state]
  (sablono/html
    [:div.left-body-ca07e
      [:textarea#mainTextarea.text-f3988
        {:value (:value new-state)
         :on-change #(swap! state assoc :value (-> % .-target .-value) 
                                        :success? false 
                                        :error? false)}]]))

(quiescent/defcomponent Footer []
  (sablono/html
    [:footer.ftr-outer-6bcd3
      (footer)]))

(quiescent/defcomponent MainPage [state]
  (sablono/html
    [:div#pageWrapper
      (Header state)
      [:div.body-outer-7cb5e
            [:div.body-inner-40af1
              [:h2.instructions-b15d3 (str "Paste " (:desc state) ":")]
              (LeftBody state)
              (RightBody state) 
              [:div.clr-217e3]]]
      (footer)]))

(defn AboutPage []
  (sablono/html
    [:div#pageWrapper
      (HeaderNoState)
      [:div.body-outer-7cb5e
        [:div.body-inner-5a8ac
          [:h2.instructions-b15d3 "Rationale"]
          [:p.text-block-d714f
          (str "EDN is a powerful data interchange format commonly used with " 
            "Clojure  and ClojureScript programs. It also doubles as a literal " 
            "representation of most Clojure data structures, which are often " 
            "printed to a REPL or console environment for debugging purposes. ")]
          [:p.text-block-d714f
            (str "Clojure core comes with clojure.pprint - which is a library to " 
            "format Clojure code (and thus EDN) in a human-readable fashion. ")]
          [:p.text-block-d714f
            (str "As of January 2015, there are numerous online services to pretty " 
            "print various data interchange formats (JSON, YAML, XML, etc), " 
            "but there is no online service for printing an EDN string.")]
          [:p.text-block-d714f 
            (str "This project aims to build such a service and improve the "
            "usability of working with EDN data.")]
        [:div.clr-217e3]]]
      (footer)]))

;;------------------------------------------------------------------------------
;; State Change and Rendering
;;------------------------------------------------------------------------------

(def request-anim-frame (aget js/window "requestAnimationFrame"))
(def cancel-anim-frame (aget js/window "cancelAnimationFrame"))
(def anim-frame-id nil)

(defn- on-change-state [_kwd _the-atom _old-state new-state]
  ;; cancel any previous render functions if they happen before the next
  ;; animation frame
  (when anim-frame-id
    (cancel-anim-frame anim-frame-id)
    (set! anim-frame-id nil))

  ;; put the render function on the next animation frame
  (let [render-fn #(quiescent/render (MainPage new-state) (by-id "bodyWrapper"))]
    (set! anim-frame-id (request-anim-frame render-fn))))

(add-watch state :main on-change-state)
<commit_msg>using assoc-in to swap state<commit_after>(ns pp-client.html
  (:require
    [pp-client.dom :refer [by-id set-body!]]
    [pp-client.util :refer [js-log log]]
    [quiescent :include-macros true]
    [sablono.core :as sablono :include-macros true]
    [secretary.core :as secretary]
    [pp-client.data :refer [format-input]]))

(def state (atom {:success? false :error? false :value ""}))

;;------------------------------------------------------------------------------
;; URLs
;;------------------------------------------------------------------------------

(defn- url [path] path)
  ;;(if-let [base-href (:base-href config)]
    ;;(str (replace base-href #"/$" "") path)
    ;;path))

;;------------------------------------------------------------------------------
;; Event triggers
;;------------------------------------------------------------------------------
(defn- on-format [response]
  ;;(js-log (str response))
  (swap! state assoc :value response :success? true :error? false))

(defn- on-error [response]
  (if (= (:status response) 400)
    (let [resp (:response response)]
      (swap! state conj resp {:success? false :error? true}))
    (throw (:status-text response))))

(defn- on-style-change [evt]
  (aset js/window "location" "hash" (str "/format/" (.-value (.-target evt)))))

(defn- on-btn-click [evt]
    (format-input state on-format on-error))

;;------------------------------------------------------------------------------
;; Footer
;;------------------------------------------------------------------------------

(def github-url "https://github.com/comamitc/pretty-print.net")
(def issues-url "https://github.com/comamitc/pretty-print.net/issues")
(def docs-url "http://pretty-print.net/#/about")

(defn footer-docs-list []
  (sablono/html
  [:div.col-ace4b
    [:ul
      [:li [:a.ftr-link-67c8e {:href docs-url} "Rationale"]]
      [:li [:a.ftr-link-67c8e {:href github-url} "GitHub"]]
      [:li [:a.ftr-link-67c8e {:href issues-url} "Issues"]]]]))

(quiescent/defcomponent footer-learn-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Learn"]
    [:ul
      [:li [:a.ftr-link-67c8e {:href (url "/rationale")} "Rationale"]]
      [:li [:a.ftr-link-67c8e {:href (url "/faq")} "FAQ"]]]]))

(quiescent/defcomponent footer-community-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Community"]
    [:ul
      ;;[:li [:a.ftr-link-67c8e {:href mailing-list-url}
      ;;  "Mailing List" [:i.fa.fa-external-link]]]
      ;; TODO: either make this a link or figure out how to style it as a non-link
      [:li [:a.ftr-link-67c8e {:href "#"} "IRC: #clojurescript"]]]]))

(quiescent/defcomponent footer-contribute-list []
  (sablono/html
  [:div.col-ace4b
    [:h5.hdr-856fa "Contribute"]
    [:ul
      [:li [:a.ftr-link-67c8e {:href github-url}
        "GitHub" [:i.fa.fa-external-link]]]
      [:li [:a.ftr-link-67c8e {:href issues-url}
        "Issues" [:i.fa.fa-external-link]]]]]))

(def pp-license-url
  "https://github.com/comamitc/pretty-print.net/blob/master/LICENSE.md")

(defn footer-bottom []
  (sablono/html
  [:div.bottom-31b43
    [:div.left-1764b
      [:p.small-14fbc
        "pretty-print.net is released under the "
        [:a {:href pp-license-url} "MIT License"] "."]]
    [:div.right-e461e
      [:a.ftr-home-link-2c3b4 {:href (url "/")} "pretty-print"
        [:span.ftr-info-a5716 ".net"]]]
    [:div.clr-43e49]]))

(defn footer []
  (sablono/html
  [:div.ftr-outer-6bcd3
    [:div.ftr-inner-557c9
      (footer-docs-list)
      ;;(footer-learn-list)
      ;;(footer-community-list)
      ;;(footer-contribute-list)
      [:div.clr-43e49]
      (footer-bottom)]]))

;;------------------------------------------------------------------------------
;; Header
;;------------------------------------------------------------------------------

(quiescent/defcomponent InputOptions [new-state]
  (sablono/html
    [:select#inputSelect.big-select-51b29
      {:on-change #(on-style-change %1) :value (:id new-state)}
      [:optgroup {:label "Clojure"}
        [:option {:value "clj"} "Clojure Code"]
        [:option {:value "edn"} "EDN"]
      ;;[:optgroup {:label "JavaScript"}
      ;;  [:option {:value "js"} "JavaScript Code"]
      ;;  [:option {:value "json"} "JSON"]]
        ]]))

(quiescent/defcomponent Header [state]
  (sablono/html
    [:header.header-outer-c5e7d
      [:div.header-inner-0f889
        [:div.left-9467a
          [:a.home-link-e4c1e {:href ""}
            "pretty-print"
            [:span.net-84e9a ".net"]]]
        [:div.right-1dd94
          (InputOptions state)]
        [:div.clr-217e3]]]))

(defn HeaderNoState []
  (sablono/html
    [:header.header-outer-c5e7d
      [:div.header-inner-0f889
        [:div.left-9467a
          [:a.home-link-e4c1e {:href ""}
            "pretty-print"
            [:span.net-84e9a ".net"]]]
        [:div.clr-217e3]]]))

;;------------------------------------------------------------------------------
;; Body
;;------------------------------------------------------------------------------


(quiescent/defcomponent SettingsAction [settings]
  (sablono/html
    [:div.settings-wrapper-751dc
      [:div.settings-hdr-fa6ca "Settings"]
      (map
        (fn [[k v]]
          [:div.setting-e0ddb
            [:input (assoc v :on-change #(swap! state
                                                assoc-in [:settings k :value]
                                                (-> % .-target .-value)))]])
        settings)]))

(quiescent/defcomponent FormatAction [new-state]
  (sablono/html
    [:div
      [:button#formatBtn.btn-2d976
          {:on-click #(on-btn-click %1)
           :disabled (if (empty? (:value new-state)) true false)}
            "Format"]
        (when (:error? new-state)
          [:div.error-disp-7c4aa
            [:i.fa.fa-times-circle.fa-2]
            [:span.err-ttl-0867b "Format Error"]
              [:div.msg-6f5ee (:msg new-state)]
              (when (some? (:line new-state))
                [:div.line-b55e8 (str "@line: " (:line new-state))
              (when (some? (:column new-state))
                (str "; column: " (:column new-state)))])])
        (when (:success? new-state)
          [:div.success-disp-3a51b
            [:i.fa.fa-check-circle.fa-2]
            [:span.success-ttl-390ee "Success"]])]))

(quiescent/defcomponent RightBody [new-state]
  (sablono/html
    [:div.right-body-caf9a
      (SettingsAction (:settings new-state))
      (FormatAction new-state)]))

(quiescent/defcomponent LeftBody [new-state]
  (sablono/html
    [:div.left-body-ca07e
      [:textarea#mainTextarea.text-f3988
        {:value (:value new-state)
         :on-change #(swap! state assoc :value (-> % .-target .-value)
                                        :success? false
                                        :error? false)}]]))

(quiescent/defcomponent Footer []
  (sablono/html
    [:footer.ftr-outer-6bcd3
      (footer)]))

(quiescent/defcomponent MainPage [state]
  (sablono/html
    [:div#pageWrapper
      (Header state)
      [:div.body-outer-7cb5e
            [:div.body-inner-40af1
              [:h2.instructions-b15d3 (str "Paste " (:desc state) ":")]
              (LeftBody state)
              (RightBody state)
              [:div.clr-217e3]]]
      (footer)]))

(defn AboutPage []
  (sablono/html
    [:div#pageWrapper
      (HeaderNoState)
      [:div.body-outer-7cb5e
        [:div.body-inner-5a8ac
          [:h2.instructions-b15d3 "Rationale"]
          [:p.text-block-d714f
          (str "EDN is a powerful data interchange format commonly used with "
            "Clojure  and ClojureScript programs. It also doubles as a literal "
            "representation of most Clojure data structures, which are often "
            "printed to a REPL or console environment for debugging purposes. ")]
          [:p.text-block-d714f
            (str "Clojure core comes with clojure.pprint - which is a library to "
            "format Clojure code (and thus EDN) in a human-readable fashion. ")]
          [:p.text-block-d714f
            (str "As of January 2015, there are numerous online services to pretty "
            "print various data interchange formats (JSON, YAML, XML, etc), "
            "but there is no online service for printing an EDN string.")]
          [:p.text-block-d714f
            (str "This project aims to build such a service and improve the "
            "usability of working with EDN data.")]
        [:div.clr-217e3]]]
      (footer)]))

;;------------------------------------------------------------------------------
;; State Change and Rendering
;;------------------------------------------------------------------------------

(def request-anim-frame (aget js/window "requestAnimationFrame"))
(def cancel-anim-frame (aget js/window "cancelAnimationFrame"))
(def anim-frame-id nil)

(defn- on-change-state [_kwd _the-atom _old-state new-state]
  ;; cancel any previous render functions if they happen before the next
  ;; animation frame
  (when anim-frame-id
    (cancel-anim-frame anim-frame-id)
    (set! anim-frame-id nil))

  ;; put the render function on the next animation frame
  (let [render-fn #(quiescent/render (MainPage new-state) (by-id "bodyWrapper"))]
    (set! anim-frame-id (request-anim-frame render-fn))))

(add-watch state :main on-change-state)

{'fraction_non_alphanumeric': 0.25615284974093266, 'fraction_numerical': 0.0221286701208981, 'mean_word_length': 1.7503339765474246, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2547844', 'n_tokens_mistral': 6453, 'n_tokens_neox': 5924, 'n_words': 1277}