├── README.md ├── env ├── dev │ ├── clj │ │ ├── cljs_eval_example │ │ │ ├── middleware.clj │ │ │ └── repl.clj │ │ └── user.clj │ └── cljs │ │ └── cljs_eval_example │ │ └── dev.cljs └── prod │ ├── clj │ └── cljs_eval_example │ │ └── middleware.clj │ └── cljs │ └── cljs_eval_example │ └── prod.cljs ├── project.clj ├── resources └── public │ └── css │ └── site.css └── src ├── clj └── cljs_eval_example │ ├── handler.clj │ └── server.clj ├── cljc └── cljs_eval_example │ └── util.cljc └── cljs └── cljs_eval_example └── core.cljs /README.md: -------------------------------------------------------------------------------- 1 | # cljs-eval-example 2 | 3 | This is the cljs-eval-example project. 4 | 5 | ## Development mode 6 | 7 | To start the Figwheel compiler, navigate to the project folder and run the following command in the terminal: 8 | 9 | ``` 10 | lein figwheel 11 | ``` 12 | 13 | Figwheel will automatically push cljs changes to the browser. The server will be available at [http://localhost:3449](http://localhost:3449) once Figwheel starts up. 14 | 15 | Figwheel also starts `nREPL` using the value of the `:nrepl-port` in the `:figwheel` 16 | config found in `project.clj`. By default the port is set to `7002`. 17 | 18 | The figwheel server can have unexpected behaviors in some situations such as when using 19 | websockets. In this case it's recommended to run a standalone instance of a web server as follows: 20 | 21 | ``` 22 | lein do clean, run 23 | ``` 24 | 25 | The application will now be available at [http://localhost:3000](http://localhost:3000). 26 | 27 | 28 | ### Optional development tools 29 | 30 | Start the browser REPL: 31 | 32 | ``` 33 | $ lein repl 34 | ``` 35 | The Jetty server can be started by running: 36 | 37 | ```clojure 38 | (start-server) 39 | ``` 40 | and stopped by running: 41 | ```clojure 42 | (stop-server) 43 | ``` 44 | 45 | 46 | ## Building for release 47 | 48 | ``` 49 | lein do clean, uberjar 50 | ``` 51 | 52 | ## Deploying to Heroku 53 | 54 | Make sure you have [Git](http://git-scm.com/downloads) and [Heroku toolbelt](https://toolbelt.heroku.com/) installed, then simply follow the steps below. 55 | 56 | Optionally, test that your application runs locally with foreman by running. 57 | 58 | ``` 59 | foreman start 60 | ``` 61 | 62 | Now, you can initialize your git repo and commit your application. 63 | 64 | ``` 65 | git init 66 | git add . 67 | git commit -m "init" 68 | ``` 69 | create your app on Heroku 70 | 71 | ``` 72 | heroku create 73 | ``` 74 | 75 | optionally, create a database for the application 76 | 77 | ``` 78 | heroku addons:add heroku-postgresql 79 | ``` 80 | 81 | The connection settings can be found at your [Heroku dashboard](https://dashboard.heroku.com/apps/) under the add-ons for the app. 82 | 83 | deploy the application 84 | 85 | ``` 86 | git push heroku master 87 | ``` 88 | 89 | Your application should now be deployed to Heroku! 90 | For further instructions see the [official documentation](https://devcenter.heroku.com/articles/clojure). 91 | -------------------------------------------------------------------------------- /env/dev/clj/cljs_eval_example/middleware.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.middleware 2 | (:require 3 | [ring.middleware.content-type :refer [wrap-content-type]] 4 | [ring.middleware.params :refer [wrap-params]] 5 | [prone.middleware :refer [wrap-exceptions]] 6 | [ring.middleware.reload :refer [wrap-reload]] 7 | [ring.middleware.defaults :refer [site-defaults wrap-defaults]])) 8 | 9 | (def middleware 10 | [#(wrap-defaults % site-defaults) 11 | wrap-exceptions 12 | wrap-reload]) 13 | -------------------------------------------------------------------------------- /env/dev/clj/cljs_eval_example/repl.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.repl 2 | (:use cljs-eval-example.handler 3 | figwheel-sidecar.repl-api 4 | ring.server.standalone 5 | [ring.middleware file-info file])) 6 | 7 | (defonce server (atom nil)) 8 | 9 | (defn get-handler [] 10 | ;; #'app expands to (var app) so that when we reload our code, 11 | ;; the server is forced to re-resolve the symbol in the var 12 | ;; rather than having its own copy. When the root binding 13 | ;; changes, the server picks it up without having to restart. 14 | (-> #'app 15 | ; Makes static assets in $PROJECT_DIR/resources/public/ available. 16 | (wrap-file "resources") 17 | ; Content-Type, Content-Length, and Last Modified headers for files in body 18 | (wrap-file-info))) 19 | 20 | (defn start-server 21 | "used for starting the server in development mode from REPL" 22 | [& [port]] 23 | (let [port (if port (Integer/parseInt port) 3000)] 24 | (reset! server 25 | (serve (get-handler) 26 | {:port port 27 | :auto-reload? true 28 | :join? false})) 29 | (println (str "You can view the site at http://localhost:" port)))) 30 | 31 | (defn stop-server [] 32 | (.stop @server) 33 | (reset! server nil)) 34 | -------------------------------------------------------------------------------- /env/dev/clj/user.clj: -------------------------------------------------------------------------------- 1 | (ns user 2 | (:require [figwheel-sidecar.repl-api :as ra])) 3 | 4 | (defn start-fw [] 5 | (ra/start-figwheel!)) 6 | 7 | (defn stop-fw [] 8 | (ra/stop-figwheel!)) 9 | 10 | (defn cljs [] 11 | (ra/cljs-repl)) 12 | -------------------------------------------------------------------------------- /env/dev/cljs/cljs_eval_example/dev.cljs: -------------------------------------------------------------------------------- 1 | (ns ^:figwheel-no-load cljs-eval-example.dev 2 | (:require 3 | [cljs-eval-example.core :as core] 4 | [devtools.core :as devtools])) 5 | 6 | (extend-protocol IPrintWithWriter 7 | js/Symbol 8 | (-pr-writer [sym writer _] 9 | (-write writer (str "\"" (.toString sym) "\"")))) 10 | 11 | (devtools/install!) 12 | 13 | (enable-console-print!) 14 | 15 | (core/init!) 16 | -------------------------------------------------------------------------------- /env/prod/clj/cljs_eval_example/middleware.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.middleware 2 | (:require 3 | [ring.middleware.defaults :refer [site-defaults wrap-defaults]])) 4 | 5 | (def middleware 6 | [#(wrap-defaults % site-defaults)]) 7 | -------------------------------------------------------------------------------- /env/prod/cljs/cljs_eval_example/prod.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.prod 2 | (:require [cljs-eval-example.core :as core])) 3 | 4 | ;;ignore println statements in prod 5 | (set! *print-fn* (fn [& _])) 6 | 7 | (core/init!) 8 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject cljs-eval-example "0.1.0-SNAPSHOT" 2 | :description "FIXME: write description" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | 7 | :dependencies [[org.clojure/clojure "1.10.3"] 8 | [ring-server "0.5.0"] 9 | [reagent "1.0.0"] 10 | [ring "1.8.1"] 11 | [ring/ring-defaults "0.3.2"] 12 | [hiccup "1.0.5"] 13 | [yogthos/config "1.1.7"] 14 | [org.clojure/clojurescript "1.10.844" 15 | :scope "provided"] 16 | [metosin/reitit "0.5.12"]] 17 | 18 | :jvm-opts ["-Xmx1G"] 19 | 20 | :plugins [[lein-environ "1.1.0"] 21 | [lein-cljsbuild "1.1.7"] 22 | [lein-asset-minifier "0.4.6" 23 | :exclusions [org.clojure/clojure]]] 24 | 25 | :ring {:handler cljs-eval-example.handler/app 26 | :uberwar-name "cljs-eval-example.war"} 27 | 28 | :min-lein-version "2.5.0" 29 | :uberjar-name "cljs-eval-example.jar" 30 | :main cljs-eval-example.server 31 | :clean-targets ^{:protect false} 32 | [:target-path 33 | [:cljsbuild :builds :app :compiler :output-dir] 34 | [:cljsbuild :builds :app :compiler :output-to]] 35 | 36 | :source-paths ["src/clj" "src/cljc" "src/cljs"] 37 | :resource-paths ["resources" "target/cljsbuild"] 38 | 39 | :minify-assets 40 | [[:css {:source "resources/public/css/site.css" 41 | :target "resources/public/css/site.min.css"}]] 42 | 43 | :cljsbuild 44 | {:builds {:min 45 | {:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"] 46 | :compiler 47 | {:output-to "target/cljsbuild/public/js/app.js" 48 | :output-dir "target/cljsbuild/public/js" 49 | :source-map "target/cljsbuild/public/js/app.js.map" 50 | :optimizations :advanced 51 | :infer-externs true 52 | :pretty-print false}} 53 | :app 54 | {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"] 55 | :figwheel {:on-jsload "cljs-eval-example.core/mount-root"} 56 | :compiler 57 | {:main "cljs-eval-example.dev" 58 | :asset-path "/js/out" 59 | :output-to "target/cljsbuild/public/js/app.js" 60 | :output-dir "target/cljsbuild/public/js/out" 61 | :source-map true 62 | :optimizations :none 63 | :pretty-print true}}}} 64 | 65 | :figwheel 66 | {:http-server-root "public" 67 | :server-port 3449 68 | :nrepl-port 7002 69 | :nrepl-middleware [cider.piggieback/wrap-cljs-repl 70 | ] 71 | :css-dirs ["resources/public/css"] 72 | :ring-handler cljs-eval-example.handler/app} 73 | 74 | :profiles {:dev {:repl-options {:init-ns cljs-eval-example.repl} 75 | :dependencies [[cider/piggieback "0.5.2"] 76 | [binaryage/devtools "1.0.2"] 77 | [prone "2020-01-17"] 78 | [figwheel-sidecar "0.5.20"] 79 | [nrepl "0.8.3"] 80 | [pjstadig/humane-test-output "0.10.0"]] 81 | 82 | :source-paths ["env/dev/clj"] 83 | :plugins [[lein-figwheel "0.5.20"] 84 | ] 85 | 86 | :injections [(require 'pjstadig.humane-test-output) 87 | (pjstadig.humane-test-output/activate!)] 88 | 89 | :env {:dev true}} 90 | 91 | :uberjar {:hooks [minify-assets.plugin/hooks] 92 | :source-paths ["env/prod/clj"] 93 | :prep-tasks ["compile" ["cljsbuild" "once" "min"]] 94 | :env {:production true} 95 | :aot :all 96 | :omit-source true}}) 97 | -------------------------------------------------------------------------------- /resources/public/css/site.css: -------------------------------------------------------------------------------- 1 | .body-container { 2 | font-family: 'Helvetica Neue', Verdana, Helvetica, Arial, sans-serif; 3 | max-width: 640px; 4 | margin: 0 auto; 5 | padding-top: 72px; 6 | -webkit-font-smoothing: antialiased; 7 | font-size: 1.125em; 8 | color: #333; 9 | line-height: 1.5em; 10 | } 11 | 12 | h1, h2, h3 { 13 | color: #000; 14 | } 15 | h1 { 16 | font-size: 2.5em 17 | } 18 | 19 | h2 { 20 | font-size: 2em 21 | } 22 | 23 | h3 { 24 | font-size: 1.5em 25 | } 26 | 27 | a { 28 | text-decoration: none; 29 | color: #09f; 30 | } 31 | 32 | a:hover { 33 | text-decoration: underline; 34 | } 35 | -------------------------------------------------------------------------------- /src/clj/cljs_eval_example/handler.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.handler 2 | (:require 3 | [reitit.ring :as reitit-ring] 4 | [cljs-eval-example.middleware :refer [middleware]] 5 | [hiccup.page :refer [include-js include-css html5]] 6 | [config.core :refer [env]])) 7 | 8 | (def mount-target 9 | [:div#app 10 | [:h2 "Welcome to cljs-eval-example"] 11 | [:p "please wait while Figwheel is waking up ..."] 12 | [:p "(Check the js console for hints if nothing exciting happens.)"]]) 13 | 14 | (defn head [] 15 | [:head 16 | [:meta {:charset "utf-8"}] 17 | [:meta {:name "viewport" 18 | :content "width=device-width, initial-scale=1"}] 19 | (include-css 20 | (if (env :dev) "/css/site.css" "/css/site.min.css") 21 | "//cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.min.css" 22 | "//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/default.min.css" 23 | (if (env :dev) "css/site.css" "css/site.min.css")) 24 | (include-js 25 | "//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js" 26 | "//cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.min.js" 27 | "//cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/mode/clojure/clojure.min.js")]) 28 | 29 | (defn loading-page [] 30 | (html5 31 | (head) 32 | [:body {:class "body-container"} 33 | mount-target 34 | (include-js "/js/app.js")])) 35 | 36 | 37 | (defn index-handler 38 | [_request] 39 | {:status 200 40 | :headers {"Content-Type" "text/html"} 41 | :body (loading-page)}) 42 | 43 | (def app 44 | (reitit-ring/ring-handler 45 | (reitit-ring/router 46 | [["/" {:get {:handler index-handler}}] 47 | ["/items" 48 | ["" {:get {:handler index-handler}}] 49 | ["/:item-id" {:get {:handler index-handler 50 | :parameters {:path {:item-id int?}}}}]] 51 | ["/about" {:get {:handler index-handler}}]]) 52 | (reitit-ring/routes 53 | (reitit-ring/create-resource-handler {:path "/" :root "/public"}) 54 | (reitit-ring/create-default-handler)) 55 | {:middleware middleware})) 56 | -------------------------------------------------------------------------------- /src/clj/cljs_eval_example/server.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.server 2 | (:require 3 | [cljs-eval-example.handler :refer [app]] 4 | [config.core :refer [env]] 5 | [ring.adapter.jetty :refer [run-jetty]]) 6 | (:gen-class)) 7 | 8 | (defn -main [& args] 9 | (let [port (or (env :port) 3000)] 10 | (run-jetty #'app {:port port :join? false}))) 11 | -------------------------------------------------------------------------------- /src/cljc/cljs_eval_example/util.cljc: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.util) 2 | 3 | (defn foo-cljc [x] 4 | "I don't do a whole lot." 5 | [x] 6 | (println x "Hello, World!")) 7 | -------------------------------------------------------------------------------- /src/cljs/cljs_eval_example/core.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-eval-example.core 2 | (:require 3 | [reagent.dom :as dom] 4 | [reagent.core :as reagent :refer [atom]] 5 | [cljs.js :refer [empty-state eval-str js-eval]] 6 | [cljs.pprint :refer [pprint]])) 7 | 8 | (defn evaluate [s cb] 9 | (eval-str 10 | (empty-state) 11 | s 12 | nil 13 | {:eval js-eval 14 | :source-map true 15 | :context :expr} 16 | cb)) 17 | 18 | (defn editor-did-mount [input] 19 | (fn [this] 20 | (let [cm (.fromTextArea js/CodeMirror 21 | (dom/dom-node this) 22 | #js {:mode "clojure" 23 | :lineNumbers true})] 24 | (.on cm "change" #(reset! input (.getValue %)))))) 25 | 26 | (defn editor [input] 27 | (reagent/create-class 28 | {:render (fn [] [:textarea 29 | {:default-value "" 30 | :auto-complete "off"}]) 31 | :component-did-mount (editor-did-mount input)})) 32 | 33 | (defn render-code [this] 34 | (->> this dom/dom-node (.highlightBlock js/hljs))) 35 | 36 | (defn result-view [output] 37 | (reagent/create-class 38 | {:render (fn [] 39 | [:pre>code.clj 40 | (with-out-str (pprint @output))]) 41 | :component-did-update render-code})) 42 | 43 | (defn home-page [] 44 | (let [input (atom nil) 45 | output (atom nil)] 46 | (fn [] 47 | [:div 48 | [editor input] 49 | [:div 50 | [:button 51 | {:on-click #(evaluate @input (fn [result] (reset! output (str result))))} 52 | "run"]] 53 | [:div 54 | [result-view output]]]))) 55 | 56 | (defn mount-root [] 57 | (dom/render [home-page] (.getElementById js/document "app"))) 58 | 59 | (defn init! [] 60 | (mount-root)) 61 | --------------------------------------------------------------------------------