Skip to content
Browse files

Merge branch 'M002' into props

Conflicts:
        script/deps
  • Loading branch information...
2 parents 934df80 + 15bd995 commit 9c7a6ffb0b63a6a43a722e4b6303ce3c1641bfe3 Brenton Ashworth and Craig Andera committed Jan 24, 2012
View
2 .gitignore
@@ -6,3 +6,5 @@ docs
/wiki
/.lein-deps-sum
*~
+/.lein-failures
+/.lein-git-deps/
View
2 Procfile
@@ -1 +1 @@
-web: lein run
+web: lein run -m script.serve
View
13 README.md
@@ -80,8 +80,15 @@ more information.
The best place to get help is on the
[Clojure Mailing List](https://groups.google.com/group/clojure). You
-can also log issues in the
-[project issue tracker](https://github.com/brentonashworth/one/issues).
+can also log issues in the [project issue tracker][issues].
+
+# Contributing
+
+ClojureScript One welcomes help from the community in the form of pull
+requests, [bug reports][issues], [wiki][wiki] updates, and hugs. If
+you wish to contribute code, please read [How We Work][how-we-work].
+In particular, note that pull requests should target the
+`pull-requests` branch, not `master`.
# Known Issues
@@ -127,3 +134,5 @@ Distributed under the Eclipse Public License, the same as Clojure uses. See the
[lein]: https://github.com/technomancy/leiningen
[wiki]: https://github.com/brentonashworth/one/wiki
[website]: http://clojurescriptone.com
+[how-we-work]: https://github.com/brentonashworth/one/wiki/HowWeWork
+[issues]: https://github.com/brentonashworth/one/issues
View
21 project.clj
@@ -3,9 +3,24 @@
:dependencies [[org.clojure/clojure "1.3.0"]
[ring "1.0.0-RC1"]
[compojure "0.6.4"]
- [enlive "1.0.0"]]
+ [enlive "1.0.0"]
+ [org.mozilla/rhino "1.7R3"]
+ [com.google.javascript/closure-compiler "r1592"]
+ [org.clojure/google-closure-library "0.0-790"]]
:dev-dependencies [[jline "0.9.94"]
[marginalia "0.7.0-SNAPSHOT"]
[lein-marginalia "0.7.0-SNAPSHOT"]]
- :main one.sample.prod-server
- :source-path "src/app/clj")
+ :git-dependencies [["https://github.com/clojure/clojurescript.git"
+ "886d8dc81812962d30a741d6d05ce9d90975160f"]
+ ["https://github.com/levand/domina.git"
+ "8933b2d12c44832c9bfaecf457a1bc5db251a774"]]
+ :repl-init one.sample.repl
+ :source-path "src/app/clj"
+ :extra-classpath-dirs [".lein-git-deps/clojurescript/src/clj"
+ ".lein-git-deps/clojurescript/src/cljs"
+ ".lein-git-deps/domina/src/cljs"
+ "src/app/cljs"
+ "src/app/cljs-macros"
+ "src/lib/clj"
+ "src/lib/cljs"
+ "templates"])
View
2 public/design.html
@@ -19,7 +19,7 @@
HTML for these views is located in the HTML files by the same name
in the <code>templates</code> directory. The templates are
extracted from these files
- in <code>src/app/clj-macros/one/sample/snippets.clj</code>. Changing
+ in <code>src/app/cljs-macros/one/sample/snippets.clj</code>. Changing
these files will update the views in the ClojureScript application.
</p>
<ul>
View
BIN public/favicon.ico
Binary file not shown.
View
23 script/build
@@ -1,24 +1,3 @@
#!/bin/bash
-set -e
-
-cd `dirname $0`/..
-
-mkdir -p out
-
-echo "Creating out/public..."
-cp -a public out/
-rm out/public/index.html
-rm out/public/design.html
-rm -rf out/public/javascripts/*
-
-source script/setup_classpath.sh
-
-echo "Create advanced compiled JavaScript..."
-java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \
-"(use 'one.tools)
- (use 'one.sample.config)
- (build-project config)"
-
-echo "[build complete]"
-
+lein run -m script.build
View
1 script/build.cmd
@@ -0,0 +1 @@
+lein run -m script.build
View
13 script/cljs-repl
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`/..
-
-source script/setup_classpath.sh
-
-java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \
-"(use '[one.sample.dev-server :only (run-server cljs-repl)])
- (use '[clojure.java.browse :only (browse-url)])
- (run-server)
- (future (Thread/sleep 3000) (browse-url \"http://localhost:8080/development\"))
- (cljs-repl)" --repl
-
View
30 script/deps
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-set -e
-
-cd `dirname $0`/..
-
-echo "Getting lein deps..."
-lein deps
-
-cd lib
-
-# change this to levand's repo once he merges in the prop-lookup changes
-git clone https://github.com/fogus/domina.git
-
-git clone https://github.com/clojure/clojurescript.git
-
-cd domina
-git checkout -b clojurescript-one-lib cc2ee723b28fd3de6023156cab23b86daaa72210
-
-cd ../clojurescript
-git checkout -b clojurescript-one-lib3 493213cca55f4d4d112b57a040a7f5363b60a28b
-script/bootstrap
-
-echo "Copy ClojureScript deps to lib directory..."
-
-cp lib/compiler.jar ..
-cp lib/goog.jar ..
-cp lib/js.jar ..
-
-echo "[Deps Completed]"
View
7 script/repl 100755 → 100644
@@ -1,7 +1,6 @@
#!/bin/bash
-cd `dirname $0`/..
+# This is here for convention. Many Emacs users have their
+# inferior-lisp-program set to script/repl.
-source script/setup_classpath.sh
-
-java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main
+lein repl
View
10 script/run
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`/..
-
-source script/setup_classpath.sh
-
-java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \
-"(use 'one.sample.dev-server)
- (run-server)
- (println \"The application is being served from localhost:8080\")" --repl
View
6 script/serve
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Start the production server which will serve the contents of
+# out/public and the API for the sample application.
+
+lein run -m script.serve
View
8 script/setup_classpath.sh
@@ -1,8 +0,0 @@
-CLOJURESCRIPT_HOME=lib/clojurescript
-
-CLJSC_CP='lib/*:lib/dev/*'
-for next in 'src/clj' 'src/cljs' 'test/cljs'; do
- CLJSC_CP=${CLJSC_CP}:$CLOJURESCRIPT_HOME'/'$next
-done
-
-CLJSC_CP=$CLJSC_CP':lib/domina/src/cljs:src/app/clj:src/app/cljs:src/app/cljs-macros:src/lib/clj:src/lib/cljs:test:templates'
View
10 script/test
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`/..
-
-source script/setup_classpath.sh
-
-java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \
-"(use 'one.sample.test.suite)
- (run-all)
- (shutdown-agents)"
View
11 src/app/clj/one/sample/prod_server.clj
@@ -1,6 +1,6 @@
(ns one.sample.prod-server
"Production server serves the backend API. This is only required if
- there is a back end API."
+ there is a back end API."
(:use [ring.adapter.jetty :only (run-jetty)]
[ring.middleware.file :only (wrap-file)]
[ring.middleware.file-info :only (wrap-file-info)]
@@ -11,6 +11,10 @@
(def ^:private root "out/public")
+;; HACK: Something about the defroutes below requires that the
+;; out/public directory exist, or we get a compile error.
+(.mkdirs (java.io.File. "out/public"))
+
(defroutes app-routes
remote-routes
(-> (ANY "*" request (file-response "404.html" {:root root}))
@@ -20,5 +24,6 @@
(def ^:private app (-> app-routes
wrap-params))
-(defn -main [] (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
- (run-jetty (var app) {:join? false :port port})))
+(defn run-server []
+ (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
+ (run-jetty (var app) {:join? false :port port})))
View
29 src/app/clj/one/sample/repl.clj
@@ -0,0 +1,29 @@
+(ns one.sample.repl
+ "The starting namespace for the project. This is the namespace that
+ users will land in when they start a Clojure REPL. It exists to
+ provide convenience functions like 'go' and 'dev-server'."
+ (:use [clojure.repl])
+ (:require [one.tools :as tools]
+ [one.sample.dev-server :as dev]
+ [clojure.java.browse :as browse]))
+
+(defn go
+ "Start a browser-connected REPL and launch a browser to talk to it."
+ []
+ (dev/run-server)
+ (future (Thread/sleep 3000)
+ (browse/browse-url "http://localhost:8080/development"))
+ (tools/cljs-repl))
+
+(defn dev-server
+ "Start the development server and open the host application in the
+ default browser."
+ []
+ (dev/run-server)
+ (future (Thread/sleep 3000)
+ (browse/browse-url "http://localhost:8080")))
+
+(println)
+(println "Type (go) to launch the development server and setup a browser-connected REPL.")
+(println "Type (dev-server) to launch only the development server.")
+(println)
View
20 src/app/clj/script/build.clj
@@ -0,0 +1,20 @@
+(ns script.build
+ "Contains a -main function which builds the production artifacts for
+ the project."
+ (:require [clojure.java.io :as io]
+ [one.tools :as tools]
+ [one.sample.config :as config]))
+
+(defn -main
+ "Compile ClojureScript sources and output them as well as all static
+ resources to the out/public directory."
+ []
+ (println "Creating out/public...")
+ (.mkdir (io/file "out"))
+ (tools/copy-recursive-into "public" "out")
+ (tools/delete "out/public/index.html"
+ "out/public/design.html"
+ "out/public/javascripts")
+ (.mkdir (io/file "out/public/javascripts"))
+ (println "Create advanced compiled JavaScript...")
+ (tools/build-project config/config))
View
9 src/app/clj/script/serve.clj
@@ -0,0 +1,9 @@
+(ns script.serve
+ "Provides a -main function which will start the production server."
+ (:require [one.sample.prod-server :as prod]))
+
+(defn -main
+ "Start the production server which serves the content from
+ out/public as well as the sample application's API."
+ []
+ (prod/run-server))
View
20 src/app/cljs/one/sample/animation.cljs
@@ -3,7 +3,7 @@
one.sample.animation
(:use [one.core :only (start)]
[one.browser.animation :only (bind parallel serial play play-animation)]
- [domina :only (by-id set-html! set-styles! destroy-children! append!)]
+ [domina :only (by-id set-html! set-styles! destroy-children! append! single-node)]
[domina.xpath :only (xpath)])
(:require [goog.dom.forms :as gforms]
[goog.style :as style]))
@@ -25,6 +25,8 @@
(destroy-children! content)
(set-html! content form-html)
(append! content greeting-html)
+ ;; Required for IE8 to work correctly
+ (style/setOpacity (single-node (xpath label)) 1)
(set-styles! (xpath cloud) {:opacity "0" :display "none" :margin-top "-500px"})
(set-styles! (by-id "greet-button") {:opacity "0.2" :disabled true})
(play form form-in {:after #(.focus (by-id "name-input") ())})))
@@ -47,15 +49,15 @@
"Make the passed input field label invisible. Run when the input
field loses focus and contains a valid input value."
[label]
- (play label {:effect :fade :start 1 :end 0 :time 200}))
+ (play label {:effect :fade :end 0 :time 200}))
(def move-down [{:effect :fade :end 1 :time 200}
{:effect :color :end "#BBC4D7" :time 200}
{:effect :slide :down 40 :time 200}])
(def fade-in {:effect :fade :end 1 :time 400})
-(def fade-out {:effect :fade :start 1 :end 0 :time 400})
+(def fade-out {:effect :fade :end 0 :time 400})
(defn label-move-down
"Make the passed input field label visible and move it down into the
@@ -74,12 +76,12 @@
"Move the form out of view and the greeting into view. Run when the
submit button is clicked and the form has valid input."
[]
- (let [e {:effect :fade :start 1 :end 0 :time 500}]
- (play-animation (parallel (bind form e)
- (bind label e) ; Since the label won't fade in IE
- (bind cloud
- {:effect :color :time 500} ; Dummy animation for delay purposes
- {:effect :fade-in-and-show :time 600}))
+ (let [e {:effect :fade :end 0 :time 500}]
+ (play-animation #(parallel (bind form e)
+ (bind label e) ; Since the label won't fade in IE
+ (bind cloud
+ {:effect :color :time 500} ; Dummy animation for delay purposes
+ {:effect :fade-in-and-show :time 600}))
{:before #(gforms/setDisabled (by-id "name-input") true)
;; We need this next one because IE8 won't hide the button
:after #(set-styles! (by-id "greet-button") {:display "none"})})))
View
12 src/app/cljs/one/sample/core.cljs
@@ -1,19 +1,27 @@
(ns ^{:doc "Contains the entry point for the ClojureScript sample application."}
one.sample.core
- (:require [clojure.browser.repl :as repl]
+ (:require [goog.uri.utils :as uri]
+ [clojure.browser.repl :as repl]
[one.dispatch :as dispatch]
[one.sample.view :as view]))
;; **TODO:** Add marginalia comment to explain what `:export` is for.
+(defn- server
+ "Return a string which is the scheme and domain portion of the URL
+ for the server from which this code was served."
+ []
+ (let [location (.toString window.location ())]
+ (str (uri/getScheme location) "://" (uri/getDomain location))))
+
(defn ^:export repl
"Connects to a ClojureScript REPL running on localhost port 9000.
This allows a browser-connected REPL to send JavaScript to the
browser for evaluation. This function should be called from a script
in the development host HTML page."
[]
- (repl/connect "http://localhost:9000/repl"))
+ (repl/connect (str (server) ":9000/repl")))
(defn ^:export start
"Start the application by firing a `:init` event which will cause the
View
3 src/app/cljs/one/sample/view.cljs
@@ -1,7 +1,8 @@
(ns ^{:doc "Render the views for the application."}
one.sample.view
- (:use [domina :only (xpath set-html! set-styles! styles by-id set-style!
+ (:use [domina :only (set-html! set-styles! styles by-id set-style!
by-class value set-value! set-text! nodes single-node)]
+ [domina.xpath :only (xpath)]
[one.browser.animation :only (play)])
(:require-macros [one.sample.snippets :as snippets])
(:require [goog.events.KeyCodes :as key-codes]
View
10 src/leiningen/bootstrap.clj
@@ -0,0 +1,10 @@
+(ns leiningen.bootstrap
+ "Bootstrap the project by running lein deps and lein git-deps."
+ (:require leiningen.deps
+ leiningen.git-deps))
+
+(defn bootstrap
+ "Bootstrap the project by running lein deps and lein git-deps."
+ [project]
+ (leiningen.deps/deps project)
+ (leiningen.git-deps/git-deps project))
View
102 src/leiningen/git_deps.clj
@@ -0,0 +1,102 @@
+(ns leiningen.git-deps
+ "How this works: It clones projects into .lein-git-deps/<whatever>.
+ If the directory already exists, it does a git pull and git checkout."
+ (:require [clojure.java.shell :as sh]
+ [clojure.java.io :as io]
+ [clojure.string :as string]))
+
+(def ^:private git-deps-dir ".lein-git-deps")
+
+(defn- directory-exists?
+ "Return true if the specified directory exists."
+ [dir]
+ (.isDirectory (io/file dir)))
+
+(defn- default-clone-dir
+ "Given a git URL, return the directory it would clone into by default."
+ [uri]
+ (string/join "." (-> uri
+ (string/split #"/")
+ (last)
+ (string/split #"\.")
+ butlast)))
+
+(defn- exec
+ "Run a command, throwing an exception if it fails, returning the
+ result as with clojure.java.shell/sh."
+ [& args]
+ (let [{:keys [exit out err] :as result} (apply sh/sh args)]
+ (if (zero? exit)
+ result
+ (throw
+ (Exception.
+ (format "Command %s failed with exit code %s\n%s\n%s"
+ (apply str (interpose " " args))
+ exit
+ out
+ err))))))
+
+(defn- git-clone
+ "Clone the git repository at url into dir-name while working in
+ directory working-dir."
+ [url dir-name working-dir]
+ (apply exec (remove nil? ["git" "clone" url (str dir-name) :dir working-dir])))
+
+(defn- git-checkout
+ "Check out the specified commit in dir."
+ [commit dir]
+ (println "Running git checkout " commit " in " (str dir))
+ (exec "git" "checkout" commit :dir dir))
+
+(defn- detached-head?
+ "Return true if the git repository in dir has HEAD detached."
+ [dir]
+ (let [{out :out} (exec "git" "branch" "--color=never" :dir dir)
+ lines (string/split-lines out)
+ current-branch (first (filter #(.startsWith % "*") lines))]
+ (when-not current-branch
+ (throw (Exception. "Unable to determine current branch")))
+ (= current-branch "* (no branch)")))
+
+(defn- git-pull
+ "Run 'git-pull' in directory dir, but only if we're on a branch. If
+ HEAD is detached, we only do a fetch, not a full pull."
+ [dir]
+ (println "Running git pull on " (str dir))
+ (if (detached-head? dir)
+ (do
+ (println "Not on a branch, so fetching instead of pulling.")
+ (exec "git" "fetch" :dir dir))
+ (exec "git" "pull" :dir dir)))
+
+(defn git-deps
+ "A leiningen task that will pull dependencies in via git.
+
+ Dependencies should be listed in project.clj under the
+ :git-dependencies key in one of these three forms:
+ :git-dependencies [;; First form: just a URL.
+ [\"https://github.com/foo/bar.git\"]
+
+ ;; Second form: A URL and a ref, which can be anything
+ ;; you can specify for 'git checkout', like a commit ide
+ ;; or a branch name.
+ [\"https://github.com/foo/baz.git\"
+ \"329708b\"]
+
+ ;; Third form: A URL, a commit, and a map
+ [\"https://github.com/foo/quux.git\"
+ \"some-branch\"
+ {:dir \"alternate-directory\"}]]"
+ [project]
+ (when-not (directory-exists? git-deps-dir)
+ (.mkdir (io/file git-deps-dir)))
+ (doseq [dep (:git-dependencies project)]
+ (println "Setting up dependency for " dep)
+ (let [[dep-url commit {clone-dir-name :dir}] dep
+ commit (or commit "master")
+ clone-dir-name (or clone-dir-name (default-clone-dir dep-url))
+ clone-dir (io/file git-deps-dir clone-dir-name)]
+ (if (directory-exists? clone-dir)
+ (git-pull clone-dir)
+ (git-clone dep-url clone-dir-name git-deps-dir))
+ (git-checkout commit clone-dir))))
View
28 src/lib/clj/one/tools.clj
@@ -2,7 +2,9 @@
"Support for building deployment artifacts for a project."
(:use [cljs.closure :only (build)]
[one.host-page :only (application-host)]
- [one.config :only (cljs-build-opts production-js)])
+ [one.config :only (cljs-build-opts production-js)]
+ [cljs.repl :only (repl)]
+ [cljs.repl.browser :only (repl-env)])
(:require [clojure.java.io :as io]))
(defn build-project
@@ -13,3 +15,27 @@
:optimizations :advanced
:output-to (str "out/" (production-js config))))
(spit "out/public/index.html" (application-host config :production)))
+
+(defn cljs-repl
+ "Start a ClojureScript REPL which can connect to the development
+ version of the application. The REPL will not work until the
+ development page connects to it, so you will need to either open or
+ refresh the development page after calling this function."
+ []
+ (repl (repl-env)))
+
+(defn copy-recursive-into
+ "Recursively copy the files in src to dest."
+ [src dest]
+ (doseq [file (remove #(.isDirectory %) (file-seq (io/file src)))]
+ (let [dest-file (io/file dest file)]
+ (.mkdirs (.getParentFile dest-file))
+ (io/copy file dest-file))))
+
+(defn delete
+ "Delete one or more files or directories. Directories are recursively
+ deleted."
+ [& paths]
+ (doseq [path paths
+ file (reverse (file-seq (io/file path)))]
+ (.delete file)))
View
9 src/lib/cljs/one/browser/animation.cljs
@@ -96,7 +96,10 @@
js/Element
(opacity [this]
- (opacity (style/getOpacity this))))
+ (let [op (style/getComputedStyle this "opacity")]
+ (if (= op "")
+ (opacity (style/getOpacity this))
+ op))))
(extend-type goog.fx.AnimationQueue
@@ -707,7 +710,9 @@
(defn- make-animation
"Create the animation to run."
[{:keys [element animation]}]
- (if element (bind element animation) animation))
+ (cond element (bind element animation)
+ (fn? animation) (animation)
+ :else animation))
(defn- play-animations
"Called by a function which has been assigned the task of running
View
1 templates/application.html
@@ -13,6 +13,7 @@
<![endif]-->
<!-- Le styles -->
+ <link href="favicon.ico" rel="shortcut icon" type="image/x-icon">
<link href="css/one.css" rel="stylesheet">
<!-- <link href="css/two.css" rel="stylesheet"> -->
<style type="text/css">
View
22 test/one/sample/test/integration.clj
@@ -2,7 +2,27 @@
"Tests which cross the client server boundary."
(:use [clojure.test]
[one.sample.api :only (*database*)]
- [one.test :only (cljs-eval cljs-wait-for)]))
+ [one.test :only (cljs-eval cljs-wait-for)]
+ [clojure.java.browse :only (browse-url)]
+ [cljs.repl :only (-setup -tear-down)]
+ [cljs.repl.browser :only (repl-env)]
+ [one.test :only (*eval-env*)]
+ [one.sample.dev-server :only (run-server)]))
+
+(defn setup
+ "Start the development server and connect to the browser so that
+ ClojureScript code can be evaluated from tests."
+ [f]
+ (let [server (run-server)
+ eval-env (repl-env)]
+ (-setup eval-env)
+ (browse-url "http://localhost:8080/development")
+ (binding [*eval-env* eval-env]
+ (f))
+ (-tear-down eval-env)
+ (.stop server)))
+
+(use-fixtures :once setup)
(deftest test-enter-new-name
(reset! *database* #{})
View
25 test/one/sample/test/suite.clj
@@ -1,25 +0,0 @@
-(ns one.sample.test.suite
- "Test suites for this application."
- (use [clojure.java.browse :only (browse-url)]
- [clojure.test]
- [cljs.repl :only (-setup -tear-down)]
- [cljs.repl.browser :only (repl-env)]
- [one.test :only (*eval-env*)]
- [one.sample.dev-server :only (run-server)]
- [one.sample.test.api]
- [one.sample.test.integration]))
-
-(defn run-all
- "Run all of the tests for this application. Start the development
- server and connect to the browser so that ClojureScript code can be
- evaluated from tests."
- []
- (let [server (run-server)
- eval-env (repl-env)]
- (-setup eval-env)
- (browse-url "http://localhost:8080/development")
- (binding [*eval-env* eval-env]
- (run-tests 'one.sample.test.api
- 'one.sample.test.integration))
- (-tear-down eval-env)
- (.stop server)))

0 comments on commit 9c7a6ff

Please sign in to comment.
Something went wrong with that request. Please try again.