Skip to content

Commit

Permalink
app shell up: express.js, less, gzip, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
oakmac committed Oct 2, 2014
1 parent d762c7a commit d7529ec
Show file tree
Hide file tree
Showing 14 changed files with 882 additions and 2 deletions.
24 changes: 24 additions & 0 deletions .gitignore
@@ -0,0 +1,24 @@
pom.xml
*jar
/lib/
/classes/
/out/
/target/
.lein-deps-sum
.lein-repl-history
.lein-plugins/

*.swp

app.js
config.json
/node_modules/
/public/css/main.min.css
/public/js/client.js
/public/js/client.min.js
/public/out/

.DS_Store

# ignore diffs
*.diff
40 changes: 40 additions & 0 deletions Gruntfile.js
@@ -0,0 +1,40 @@
module.exports = function(grunt) {
'use strict';

//------------------------------------------------------------------------------
// Grunt Config
//------------------------------------------------------------------------------

grunt.initConfig({

// LESS conversion
less: {
options: {
compress: true
},

watch: {
files: {
'public/css/main.min.css': 'less/main.less'
}
}
},

watch: {
options: {
atBegin: true
},
files: "less/*.less",
tasks: ["less:watch"]
}

});

// load tasks from npm
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.registerTask('default', ['less']);

// end module.exports
};
3 changes: 1 addition & 2 deletions LICENSE
Expand Up @@ -18,5 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

SOFTWARE.
14 changes: 14 additions & 0 deletions cljs-server/cljsinfo_server/config.cljs
@@ -0,0 +1,14 @@
(ns cljsinfo-server.config
(:require
[clojure.walk :refer [keywordize-keys]]))

;;------------------------------------------------------------------------------
;; Config
;;------------------------------------------------------------------------------

;; TODO: print a useful error if config.json does not exist

(def config
(-> (js/require "./config.json")
js->clj
keywordize-keys))
49 changes: 49 additions & 0 deletions cljs-server/cljsinfo_server/core.cljs
@@ -0,0 +1,49 @@
(ns cljsinfo-server.core
(:require
[cljsinfo-server.config :refer [config]]
[cljsinfo-server.html :as html]
[cljsinfo-server.util :as util]))

(enable-console-print!)

;;------------------------------------------------------------------------------
;; Node libraries
;;------------------------------------------------------------------------------

(def js-compression (js/require "compression"))
(def js-express (js/require "express"))
(def js-http (js/require "http"))

;;------------------------------------------------------------------------------
;; Pages
;;------------------------------------------------------------------------------

(defn- homepage [_js-req js-res]
(.send js-res (html/homepage)))

;;------------------------------------------------------------------------------
;; Main
;;------------------------------------------------------------------------------

(defn -main [& args]
(let [app (js-express)
server (.createServer js-http app)]
;; configure express app
(doto app
;; gzip everything
(.use (js-compression))

;; pages
(.get "/" homepage)

;; serve static files out of /public
(.use (.static js-express (str js/__dirname "/public"))))

;; start server
(if (:host config)
(.listen server (:port config) (:host config))
(.listen server (:port config)))

(util/tlog "clojurescript.info server listening on port " (:port config))))

(set! *main-cli-fn* -main)
48 changes: 48 additions & 0 deletions cljs-server/cljsinfo_server/html.cljs
@@ -0,0 +1,48 @@
(ns cljsinfo-server.html
(:require-macros [hiccups.core :as hiccups])
(:require
hiccups.runtime
[cljsinfo-server.config :refer [config]]
[cljsinfo-server.util :as util]))

(def fs (js/require "fs"))

;;------------------------------------------------------------------------------
;; Hashed Assets
;;------------------------------------------------------------------------------

(def assets
(if (.existsSync fs "assets.json")
(js->clj (js/require "./assets.json"))
{}))

(defn- asset [f]
(get assets f f))

;;------------------------------------------------------------------------------
;; Site Head / Footer
;;------------------------------------------------------------------------------

(hiccups/defhtml site-head [page-title]
"<!doctype html>"
"<html lang='en-us'>"
[:head
[:meta {:charset "utf-8"}]
[:meta {:http-equiv "X-UA-Compatible" :content "IE=edge"}]
[:title "ClojureScript.info &raquo; " page-title]
[:meta {:name "viewport" :content "width=device-width"}]
[:link {:rel "stylesheet" :href (asset "css/main.min.css")}]]
"<body>")

(hiccups/defhtml site-footer []
"</body>"
"</html>")

;;------------------------------------------------------------------------------
;; Homepage
;;------------------------------------------------------------------------------

(hiccups/defhtml homepage []
(site-head "Home")
[:h1 "Welcome to ClojureScript.info!"]
(site-footer))
40 changes: 40 additions & 0 deletions cljs-server/cljsinfo_server/util.cljs
@@ -0,0 +1,40 @@
(ns cljsinfo-server.util)

(def js-moment (js/require "moment"))

;;------------------------------------------------------------------------------
;; Util Functions
;;------------------------------------------------------------------------------

(defn log
"Log a Clojure thing."
[thing]
(.log js/console (pr-str thing)))

(defn js-log
"Log a JavaScript thing."
[& js-things]
(apply (.-log js/console) js-things))

(defn- now []
(.format (js-moment) "YYYY-MM-DD HH:mm:ss"))

;; TODO: investigate using a proper logging library
;; - https://github.com/flatiron/winston
;; - https://github.com/trentm/node-bunyan
(defn tlog
"Timestampped log."
[& msgs]
(js-log (str "[" (now) "] " (apply str msgs))))

(defn uuid []
"Create a UUID."
[]
(apply
str
(map
(fn [x]
(if (= x \0)
(.toString (bit-or (* 16 (.random js/Math)) 0) 16)
x))
"00000000-0000-4000-0000-000000000000")))
3 changes: 3 additions & 0 deletions example.config.json
@@ -0,0 +1,3 @@
{
"port": 9292
}
156 changes: 156 additions & 0 deletions less/elements-0.9.less
@@ -0,0 +1,156 @@
//---------------------------------------------------
// LESS Elements 0.9
//---------------------------------------------------
// A set of useful LESS mixins
// More info at: http://lesselements.com
//---------------------------------------------------

.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) {
background: @color;
background: -webkit-gradient(linear,
left bottom,
left top,
color-stop(0, @start),
color-stop(1, @stop));
background: -ms-linear-gradient(bottom,
@start,
@stop);
background: -moz-linear-gradient(center bottom,
@start 0%,
@stop 100%);
background: -o-linear-gradient(@stop,
@start);
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@stop,@start));
}
.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) {
background: @color;
background: -webkit-gradient(linear,
left bottom,
left top,
color-stop(0, rgb(@start,@start,@start)),
color-stop(1, rgb(@stop,@stop,@stop)));
background: -ms-linear-gradient(bottom,
rgb(@start,@start,@start) 0%,
rgb(@stop,@stop,@stop) 100%);
background: -moz-linear-gradient(center bottom,
rgb(@start,@start,@start) 0%,
rgb(@stop,@stop,@stop) 100%);
background: -o-linear-gradient(rgb(@stop,@stop,@stop),
rgb(@start,@start,@start));
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",rgb(@stop,@stop,@stop),rgb(@start,@start,@start)));
}
.bordered(@top-color: #EEE, @right-color: #EEE, @bottom-color: #EEE, @left-color: #EEE) {
border-top: solid 1px @top-color;
border-left: solid 1px @left-color;
border-right: solid 1px @right-color;
border-bottom: solid 1px @bottom-color;
}
.drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) {
-webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
-moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
}
.rounded(@radius: 2px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
-webkit-border-top-right-radius: @topright;
-webkit-border-bottom-right-radius: @bottomright;
-webkit-border-bottom-left-radius: @bottomleft;
-webkit-border-top-left-radius: @topleft;
-moz-border-radius-topright: @topright;
-moz-border-radius-bottomright: @bottomright;
-moz-border-radius-bottomleft: @bottomleft;
-moz-border-radius-topleft: @topleft;
border-top-right-radius: @topright;
border-bottom-right-radius: @bottomright;
border-bottom-left-radius: @bottomleft;
border-top-left-radius: @topleft;
.background-clip(padding-box);
}
.opacity(@opacity: 0.5) {
-moz-opacity: @opacity;
-khtml-opacity: @opacity;
-webkit-opacity: @opacity;
opacity: @opacity;
@opperc: @opacity * 100;
-ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(opacity=@{opperc})";
filter: ~"alpha(opacity=@{opperc})";
}
.transition-duration(@duration: 0.2s) {
-moz-transition-duration: @duration;
-webkit-transition-duration: @duration;
-o-transition-duration: @duration;
transition-duration: @duration;
}
.transform(...) {
-webkit-transform: @arguments;
-moz-transform: @arguments;
-o-transform: @arguments;
-ms-transform: @arguments;
transform: @arguments;
}
.rotation(@deg:5deg){
.transform(rotate(@deg));
}
.scale(@ratio:1.5){
.transform(scale(@ratio));
}
.transition(@duration:0.2s, @ease:ease-out) {
-webkit-transition: all @duration @ease;
-moz-transition: all @duration @ease;
-o-transition: all @duration @ease;
transition: all @duration @ease;
}
.inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) {
-webkit-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
-moz-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
}
.box-shadow(@arguments) {
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
box-shadow: @arguments;
}
.box-sizing(@sizing: border-box) {
-ms-box-sizing: @sizing;
-moz-box-sizing: @sizing;
-webkit-box-sizing: @sizing;
box-sizing: @sizing;
}
.user-select(@argument: none) {
-webkit-user-select: @argument;
-moz-user-select: @argument;
-ms-user-select: @argument;
user-select: @argument;
}
.columns(@colwidth: 250px, @colcount: 0, @colgap: 50px, @columnRuleColor: #EEE, @columnRuleStyle: solid, @columnRuleWidth: 1px) {
-moz-column-width: @colwidth;
-moz-column-count: @colcount;
-moz-column-gap: @colgap;
-moz-column-rule-color: @columnRuleColor;
-moz-column-rule-style: @columnRuleStyle;
-moz-column-rule-width: @columnRuleWidth;
-webkit-column-width: @colwidth;
-webkit-column-count: @colcount;
-webkit-column-gap: @colgap;
-webkit-column-rule-color: @columnRuleColor;
-webkit-column-rule-style: @columnRuleStyle;
-webkit-column-rule-width: @columnRuleWidth;
column-width: @colwidth;
column-count: @colcount;
column-gap: @colgap;
column-rule-color: @columnRuleColor;
column-rule-style: @columnRuleStyle;
column-rule-width: @columnRuleWidth;
}
.translate(@x:0, @y:0) {
.transform(translate(@x, @y));
}
.background-clip(@argument: padding-box) {
-moz-background-clip: @argument;
-webkit-background-clip: @argument;
background-clip: @argument;
}

0 comments on commit d7529ec

Please sign in to comment.