Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

update of tutorial to clj version >= 1.3 #12

Closed
wants to merge 8 commits into from

2 participants

@magomimmo

Hello David, hope everything is going well and by the way happy new year. I updated your great enlive tutorial to clj version >= 1.3.

My best
Mimmo

@magomimmo magomimmo closed this
@magomimmo magomimmo reopened this
@magomimmo

Sorry David, previously I forgot to update the readme in the parts where some updated source code was referenced. Now should be ok.

@swannodette
Owner

Sorry I don't really track this repo much anymore, I can't merge this one as things have changed. If you have time to update it I will merge it.

@magomimmo
@magomimmo

I opened another pull request which contains the update, so I close this one.

@magomimmo magomimmo closed this
@magomimmo magomimmo deleted the magomimmo:my-update branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
1  .gitignore
@@ -1,3 +1,4 @@
+/target
lib/*
/.emacs.desktop
/.emacs.desktop.lock
View
11 project.clj
@@ -1,9 +1,6 @@
(defproject enlive-tutorial "0.1.0"
:description "Enlive Tutorial"
- :dependencies [[org.clojure/clojure "1.2.0"]
- [org.clojure/clojure-contrib "1.2.0"]
- [enlive "1.0.0-SNAPSHOT"]
- [ring "0.2.5"]
- [net.cgrand/moustache "1.0.0-SNAPSHOT"]]
- :dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]]
- :source-path "src")
+ :dependencies [[org.clojure/clojure "1.4.0"]
+ [enlive "1.0.1"]
+ [ring "1.1.6"]
+ [net.cgrand/moustache "1.1.0"]])
View
14 readme.textile
@@ -258,7 +258,7 @@ If you're not continuing from a previous tutorial you'll need to more specific a
Now this isn't perfect for a variety of reasons but it works well enough for the purposes of demonstration. Let's look at the code. At the top of the file we see that we have a variety of selectors.
<pre>
-(def *story-selector*
+(def ^:dynamic *story-selector*
[[:div.story
(html/but :.advertisement)
(html/but :.autosStory)
@@ -268,7 +268,7 @@ Now this isn't perfect for a variety of reasons but it works well enough for the
Here we are matching any div with the CSS class story that does not also have any of the other classes specified.
<pre>
-(def *headline-selector*
+(def ^:dynamic *headline-selector*
#{[html/root :> :h2 :a],
[html/root :> :h3 :a]
[html/root :> :h5 :a]}))
@@ -282,7 +282,7 @@ Here we know from looking at the markup of the page that headlines might match a
byline (first (html/select [node] *byline-selector*))
summary (first (html/select [node] *summary-selector*))
result (map html/text [headline byline summary])]
- (zipmap [:headline :byline :summary] (map #(re-gsub #"\n" "" %) result))))
+ (zipmap [:headline :byline :summary] (map #(str/replace % #"\n" "") result))))
</pre>
Here we take a node and extract the match. Note that we have to call first on the result of <code>html/select</code> because <code>html/select</code> always returns a sequence of nodes and not a single node. <code>zipmap</code> is a handy function, it allows us to take two sequences and zip them up into a hash-map. So here we take only the text nodes from the matches and remove any newline characters before we finally zip it up into a tidy hash-map.
@@ -381,7 +381,7 @@ The remainder of "*template1.clj*":src/tutorial/template1.clj is specific to Rin
[&] {:status 404
:body "Page Not Found"}))
-(defonce *server* (run-server routes))
+(defonce ^:dynamic *server* (run-server routes))
</pre>
This is the Moustache route defining syntax. A couple things to note <code>render-to-response</code> is not a function of Enlive, it's something I added via "*utils.clj*":src/tutorial/utils.clj in the repository. <code>render-to-response</code> isn't magic it's just a function that looks like this:
@@ -434,7 +434,7 @@ In this tutorial we'd rather use the Enlive functions without having to qualify
After that we declare a variable for holding a dummy context which we're going to pass to our template.
<pre>
-(def *dummy-context*
+(def ^:dynamic *dummy-context*
{:title "Enlive Template2 Tutorial"
:sections [{:title "Clojure"
:links [{:text "Macros"
@@ -484,7 +484,7 @@ First, we want to be able handle the inner loop. On one level, as you're about s
So let's define our link component. We don't want the dummy content so we really only want to match the very first link that satisfies our need, the selector looks something like this:
<pre>
-(def *link-sel* [[:.content (nth-of-type 1)] :> first-child])
+(def ^:dynamic *link-sel* [[:.content (nth-of-type 1)] :> first-child])
</pre>
We only want to match the first ul element that we find that has the content class and only the very first child inside that. This is the selector that gets the job done. It's analogous to:
@@ -533,7 +533,7 @@ Note that unlike the previous example what we're looping over has no "container"
Again our HTML has some dummy content again. We only care about the first range of *h2* and *ul* tags, we don't want to match any more than that. We can define a selector to do this like so:
<pre>
-(def *section-sel* {[:.title] [[:.content (nth-of-type 1)]]})
+(def ^:dynamic *section-sel* {[:.title] [[:.content (nth-of-type 1)]]})
</pre>
There is no CSS selector that can represent this. Again take care to note that since we want to select only the first *ul* that we find, we need an extra pair of brackets around <code>:.content</code>. This is a common mistake to leave these out.
View
2  src/tutorial/scrape1.clj
@@ -1,7 +1,7 @@
(ns tutorial.scrape1
(:require [net.cgrand.enlive-html :as html]))
-(def *base-url* "http://news.ycombinator.com/")
+(def ^:dynamic *base-url* "http://news.ycombinator.com/")
(defn fetch-url [url]
(html/html-resource (java.net.URL. url)))
View
2  src/tutorial/scrape2.clj
@@ -1,7 +1,7 @@
(ns tutorial.scrape2
(:require [net.cgrand.enlive-html :as html]))
-(def *base-url* "http://news.ycombinator.com/")
+(def ^:dynamic *base-url* "http://news.ycombinator.com/")
(defn fetch-url [url]
(html/html-resource (java.net.URL. url)))
View
17 src/tutorial/scrape3.clj
@@ -1,24 +1,23 @@
(ns tutorial.scrape3
- (:require [net.cgrand.enlive-html :as html])
- (:use [clojure.contrib.seq-utils :only [indexed]]
- [clojure.contrib.str-utils :only [re-sub re-gsub]]))
+ (:require [net.cgrand.enlive-html :as html]
+ [clojure.string :as str]))
-(def *base-url* "http://nytimes.com/")
+(def ^:dynamic *base-url* "http://nytimes.com/")
-(def *story-selector*
+(def ^:dynamic *story-selector*
[[:div.story
(html/but :.advertisement)
(html/but :.autosStory)
(html/but :.adCreative)]])
-(def *headline-selector*
+(def ^:dynamic *headline-selector*
#{[html/root :> :h2 :a],
[html/root :> :h3 :a]
[html/root :> :h5 :a]})
-(def *byline-selector* [html/root :> :.byline])
+(def ^:dynamic *byline-selector* [html/root :> :.byline])
-(def *summary-selector* [html/root :> :.summary])
+(def ^:dynamic *summary-selector* [html/root :> :.summary])
(defn fetch-url [url]
(html/html-resource (java.net.URL. url)))
@@ -31,7 +30,7 @@
byline (first (html/select [node] *byline-selector*))
summary (first (html/select [node] *summary-selector*))
result (map html/text [headline byline summary])]
- (zipmap [:headline :byline :summary] (map #(re-gsub #"\n" "" %) result))))
+ (zipmap [:headline :byline :summary] (map #(str/replace % #"\n" "") result))))
(defn empty-story? [node]
(every? (fn [[k v]] (= v "")) node))
View
2  src/tutorial/template1.clj
@@ -20,4 +20,4 @@
[&] {:status 404
:body "Page Not Found"}))
-(defonce *server* (run-server routes))
+(defonce ^:dynamic *server* (run-server routes))
View
8 src/tutorial/template2.clj
@@ -10,7 +10,7 @@
;; Dummy Data
;; =============================================================================
-(def *dummy-context*
+(def ^:dynamic *dummy-context*
{:title "Enlive Template2 Tutorial"
:sections [{:title "Clojure"
:data [{:text "Macros"
@@ -41,7 +41,7 @@
;; =============================================================================
; we only want to select a model link
-(def *link-sel* [[:.content (nth-of-type 1)] :> first-child])
+(def ^:dynamic *link-sel* [[:.content (nth-of-type 1)] :> first-child])
(defsnippet link-model "tutorial/template2.html" *link-sel*
[{:keys [text href]}]
@@ -50,7 +50,7 @@
(set-attr :href href)))
; we only want to select the model h2 ul range
-(def *section-sel* {[:.title] [[:.content (nth-of-type 1)]]})
+(def ^:dynamic *section-sel* {[:.title] [[:.content (nth-of-type 1)]]})
(defsnippet section-model "tutorial/template2.html" *section-sel*
[{:keys [title data]} model]
@@ -71,4 +71,4 @@
;; The App
;; ========================================
-(defonce *server* (run-server routes))
+(defonce ^:dynamic *server* (run-server routes))
View
2  src/tutorial/template3.clj
@@ -71,4 +71,4 @@
;; The App
;; =============================================================================
-(defonce *server* (run-server routes))
+(defonce ^:dynamic *server* (run-server routes))
View
8 src/tutorial/utils.clj
@@ -1,13 +1,13 @@
(ns tutorial.utils
- (:require [net.cgrand.enlive-html :as html])
+ (:require [net.cgrand.enlive-html :as html]
+ [clojure.java.io :as io])
(:use [ring.adapter.jetty :only [run-jetty]]
[ring.util.response :only [response file-response]]
[ring.middleware.reload :only [wrap-reload]]
[ring.middleware.file :only [wrap-file]]
- [ring.middleware.stacktrace :only [wrap-stacktrace]]
- [clojure.contrib.duck-streams :only [pwd]]))
+ [ring.middleware.stacktrace :only [wrap-stacktrace]]))
-(def *webdir* (str (pwd) "/src/tutorial/"))
+(def ^:dynamic *webdir* (str (.getCanonicalFile (io/file ".")) "/src/tutorial/"))
(defn render [t]
(apply str t))
Something went wrong with that request. Please try again.