git.fiddlerwoaroof.com
src/index.cljs.hl
cde696c2
 (page "index.html"
ecf50ed7
   (:import goog.html.sanitizer.HtmlSanitizer
            goog.html.sanitizer.HtmlSanitizer.Builder
            goog.html.sanitizer.unsafe
            goog.html.sanitizer.AttributeWhitelist
            goog.string.Const
            goog.functions
            goog.html.SafeUrl
            goog.html.SafeHtml)
c46eb53c
   (:require [cljs.pprint :refer [cl-format] :rename {cl-format format}])
cde696c2
   (:require-macros [feed-archive.let-promise :refer [let-promise]]))
 
 (defc state
c46eb53c
   {"base-url" "http://roachnotes.com"
cde696c2
    "pull-time" ""
ecf50ed7
    "feeds" []
    :items {}})
 
 (defc= base-url
   (get state "base-url")
   #(swap! state assoc-in ["base-url"] %))
cde696c2
 
 (defc= pull-time
   (get state "pull-time"))
 
 (defc= feeds
   (get state "feeds"))
 
 (defn setup-state [base-url]
   (let-promise [[resp (js/fetch (str base-url
                                      "/current"))]
                 [data (.json resp)]]
     (swap! state merge
            (js->clj data))))
 
ecf50ed7
 (cell= (when base-url
          (setup-state base-url)))
cde696c2
 
 (defn make-feed-getter [out-cell]
   (fn [base-url path]
     (let-promise [[resp (js/fetch (str base-url "/" path))]
                   [data (.json resp)]]
       (reset! out-cell (js->clj data)))))
 
 (defn get-feed-entry-cells [base-url feed]
   (let [feed-cell (cell {})
         items (cell= (get feed-cell "items"))
         item-count (cell= (count items))
         get-feed (make-feed-getter feed-cell)
         path (cell= (get feed "path" "<No PATH>"))
         url (cell= (get feed "url" "<No URL>"))
         title (cell= (get feed "title" "<No TITLE>"))]
     (cell= (get-feed base-url path))
     [url title path feed-cell items item-count]))
 
ecf50ed7
 (defn get-sanitizer []
   (let [r (Builder.)
         justification (.from Const "Because images are ok, silly")]
     (.alsoAllowAttributes unsafe justification
                           r #js [#js {:tagName "img" :attributeName "src" :policy nil}])
     (.build r)))
 
 (defn sanitize-html [html]
   (let [result (.sanitize (get-sanitizer) html)]
     (.unwrap SafeHtml result)))
 
c46eb53c
 (defn make-item-getter [out-cell content]
   (fn [base-url feed-path item-path]
     (let-promise [[resp (js/fetch (str base-url "/" feed-path item-path))]
                   [data (.json resp)]]
       (let [data (js->clj data)]
         (reset! content (sanitize-html (get data "content")))
         (reset! out-cell data)))))
 (defn get-item-cells [item content]
ecf50ed7
   (let* [key (get @item "path")
          item-cell (cell= (get (:items state) key)
                           #(swap! state assoc-in [:items key] %))
c46eb53c
          get-item (make-item-getter item-cell content)]
cde696c2
     [get-item
      (cell= (get item "title"))
      (cell= (get item "path"))
      (cell= (get item-cell "link"))
ecf50ed7
      (cell= (sanitize-html (get item-cell "content")))]))
 
 (cell= (.log js/console (clj->js base-url)))
cde696c2
 
c46eb53c
 (defn column-width [len]
   (letfn [(divisible-by [x] (= 0 (mod len x)))]
     (format nil "~d%"
             (- (cond (divisible-by 5) 20
                      (divisible-by 4) 25
                      (divisible-by 3) 33
                      (> len 30) 20
                      (> len 20) 25
                      (> len 10) 33
                      true       50)
                0.5))))
 
 (defelem feed-item [{item :item path :path css :my/css overlay :overlay content-cell :content-cell :as attrs} _]
   (let [[get-item title item-path link content] (get-item-cells item content-cell)
         toggled (cell false)
         leftover-attrs (dissoc attrs :item :path :my/css :overlay :content-cell)]
     (cell= (get-item base-url path item-path))
     (article leftover-attrs :css css
              :class "summary"
              (div :html content)
              (header (h3 (a :href link title)) " "
                      (button :class "show-article"
                              :click #(dosync (get-item @base-url @path @item-path)
                                              (reset! overlay true)
                                              (swap! toggled not))
                              ">>")))))
 
 (defelem feed-view [{feed :feed} _]
   (let [[url title path feed-cell items item-count] (get-feed-entry-cells base-url feed)
         child-width (cell= (column-width item-count))
         overlay-visible (cell false)
         content-cell (cell "")]
     (section :class (cell= {"displayed" overlay-visible})
      (div :class (cell= {"article-overlay" true "displayed" overlay-visible})
           (header (button :click #(reset! overlay-visible false)
                           "X"))
           (article :html content-cell))
      (if-tpl (cell= (> item-count 0))
        (div 
         (header (h2 title) (p url))
         (loop-tpl :bindings [item items]
           (feed-item :path path :item item :overlay overlay-visible :content-cell content-cell :my/css (cell= {:width child-width}))))))))
cde696c2
 
 (html
  (head
   (link :href "app.css" :rel "stylesheet" :type "text/css"))
  (body
c46eb53c
   (header
    (h1 "Roach Notes " (div :class "beta" :html "&beta;"))
    (input :type "text" :value base-url
           :change #(reset! base-url (.-value (.-target %)))))
   (main
    (loop-tpl :bindings [feed feeds]
      (feed-view :feed feed)))))