Skip to content

Instantly share code, notes, and snippets.

Created Feb 21, 2014
Embed
What would you like to do?
The ClojureScript source code powering http://cite.neocities.org
; Compile for development:
; $ cljsc cite.cljs '{:optimizations :whitespace :pretty-print true}' > cite.js
; Compile for deployment:
; $ cljsc cite.cljs '{:optimizations :advanced}' > cite.js
(ns cite
(:require [goog.net.XhrIo :as xhr])
(:use [clojure.string :only [join replace-first replace]]))
(defn GET [url callback]
"Returns the contents of the file at url.
See: https://developers.google.com/closure/library/docs/xhrio"
(xhr/send url (fn [r] (callback (.getResponse (.-target r))))))
; Used for debugging
;(defn alert [msg]
; (.alert js/window msg))
;
;(defn console-log [ob]
; (.log (.-console js/window) ob))
(defn element
[id]
(.getElementById js/document (name id)))
(defn put-html
[elem html]
(aset elem "innerHTML" html))
(defn create-element
"Create a new HTML element like 'input', 'div', etc.
and set its attributes from a map, e.g. {\"value\" \"Click here\"}."
[tag attributes]
(let [e (.createElement js/document tag)]
(doseq [[k v] attributes]
(.setAttribute e k v))
e))
(defn with-links
"Transform plain text containing occurences of http://... URLs
into the same text but with clickable <a href=\"...\">http://...</a> URLs."
[text]
(let [URLs (re-seq #"https?://[^ \n,]+" text)]
(reduce (fn [s URL]
(replace-first s URL (str "<a href=" URL ">" URL "</a>")))
text
URLs)))
(defn parse-quotes
"Split the text at lines containing '^===$',
trim empty lines at the beginning and end of the block containing one quote,
split each quote block into lines,
and put the last line as the origin, and the rest as the quote."
[text]
(map (fn [subblocks index]
{:quote (join "<br /><br />" (butlast subblocks))
:origin (last subblocks)
:index index})
(map (fn [block]
(map (comp #(replace % "\n" "<br />") with-links)
(.split (.trim block) "\n\n")))
(.split text "\n===\n"))
(iterate inc 0)))
(defn show
[quote]
(put-html (element "quote") (:quote quote))
(put-html (element "author") (:origin quote))
(let [permalink (element "permalink")]
(if-let [index (:index quote)]
(aset permalink "href" (str "?" index))
(aset permalink "href" "/#"))))
(defn show-next
"Cycle through the shuffled list of quotes."
[]
(let [quote (first (swap! quotes next))]
(show quote)))
(def quotes (atom nil))
(defn load-quotes
"Load and parse the txt file containing quotes,
shuffle the list of quotes and store it in the quotes atom."
[callback]
(GET "quotes.html"
(fn [text]
(swap! quotes #(cycle (shuffle (map vector (range)
(parse-quotes text)))))
(callback))))
(defn insert-Next-button
[]
(let [button (create-element "input" {"type" "button"
"value" "Next"})]
(aset button "onclick" show-next)
(.appendChild (element "content") button)))
(defn insert-permalink
[]
(let [p (create-element "p" {})
a (create-element "a" {"href" "#"
"id" "permalink"})]
(aset a "innerText" "permalink")
(.appendChild p a)
(.appendChild (element "content") p)))
(defn read-permalink
"Find an index appended to the url with ?<number>"
[]
(let [url (aget js/document "URL")
i (.indexOf url "?")]
(when-not (= -1 i)
(int (.substring url (inc i))))))
(defn wrong-permalink
[index]
{:index nil
:quote (str "Could not find quote #" index)
:author ""})
(defn ^:export init []
(GET "quotes.html"
(fn [text]
(insert-permalink)
(insert-Next-button)
(let [qs (vec (parse-quotes text))
index (read-permalink)
quote (if index
(if (and (> index -1)
(< index (count qs)))
(qs index)
(wrong-permalink index)))]
(swap! quotes #(cycle (shuffle qs)))
(if quote
(show quote)
(show-next))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment