magnars / stasis Goto Github PK
View Code? Open in Web Editor NEWSome Clojure functions for creating static websites.
Some Clojure functions for creating static websites.
In the static site generator that I'm building which uses Stasis, I want to be able to avoid exporting and serving a page by having a nil
page value or if the page function returns nil
. I only know if a respective page should be rendered after I do some expensive Markdown processing work. I would like to defer this work until each page needs to be rendered.
This would benefit users by allowing the page's function to not only dynamically load the content but also dynamically decide if the page should render at all.
No worries if you aren't feeling this, I can easily grab the source and change it for my needs. I just want to see if you like the idea. It does technically cause a breaking change in behavior, although small.
(use 'stasis.core)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CURENT BEHAVIOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(export-pages {"/" nil} "/tmp/stasis")
; (out) #error {
; (out) :cause nil
; (out) :via
; (out) [{:type java.lang.NullPointerException
; (out) :message nil
; (out) :at [stasis.core$realize_page invokeStatic core.clj 44]}]
; (out) :trace
; (out) [[stasis.core$realize_page invokeStatic core.clj 44]
; (out) [stasis.core$realize_page invoke core.clj 40]
; (out) [stasis.core$export_page invokeStatic core.clj 127]
; (out) [stasis.core$export_page invoke core.clj 124]
; (out) [stasis.core$export_pages invokeStatic core.clj 146]
; (out) [stasis.core$export_pages doInvoke core.clj 142]
(export-pages {"/" (constantly nil)} "/tmp/stasis")
; (out) #error {
; (out) :cause No method in multimethod 'do-copy' for dispatch value: [nil java.io.FileOutputStream]
; (out) :via
; (out) [{:type java.lang.IllegalArgumentException
; (out) :message No method in multimethod 'do-copy' for dispatch value: [nil java.io.FileOutputStream]
; (out) :at [clojure.lang.MultiFn getFn MultiFn.java 156]}]
; (out) :trace
; (out) [[clojure.lang.MultiFn getFn MultiFn.java 156]
; (out) [clojure.lang.MultiFn invoke MultiFn.java 238]
; (out) [clojure.java.io$copy invokeStatic io.clj 406]
; (out) [clojure.java.io$copy doInvoke io.clj 391]
; (out) [clojure.lang.RestFn invoke RestFn.java 425]
; (out) [stasis.core$export_page invokeStatic core.clj 140]
; (out) [stasis.core$export_page invoke core.clj 124]
; (out) [stasis.core$export_pages invokeStatic core.clj 146]
; (out) [stasis.core$export_pages doInvoke core.clj 142]
(-> (serve-pages {"/" nil}) (apply [{:uri "/"}]))
; (out) #error {
; (out) :cause nil
; (out) :via
; (out) [{:type java.lang.NullPointerException
; (out) :message nil
; (out) :at [stasis.core$realize_page invokeStatic core.clj 44]}]
; (out) :trace
; (out) [[stasis.core$realize_page invokeStatic core.clj 44]
; (out) [stasis.core$realize_page invoke core.clj 40]
; (out) [stasis.core$serve_after_finding_all_dependent_pages invokeStatic core.clj 98]
; (out) [stasis.core$serve_after_finding_all_dependent_pages invoke core.clj 96]
; (out) [clojure.core$partial$fn__5912 invoke core.clj 2654]
; (out) [stasis.core$try_serving_dependent_page invokeStatic core.clj 89]
; (out) [stasis.core$try_serving_dependent_page invoke core.clj 80]
; (out) [stasis.core$serve_pages$fn__5375 invoke core.clj 118]
(-> (serve-pages {"/" (constantly nil)}) (apply [{:uri "/"}]))
;; {:status 200, :body nil, :headers {"Content-Type" "text/html"}}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PROPOSED BEHAVIOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(export-pages {"/" nil} "/tmp/stasis")
;; and
(export-pages {"/" (constantly nil)} "/tmp/stasis")
;; act like
(export-pages {} "/tmp/stasis") ; nil
(-> (serve-pages {"/" nil}) (apply [{:uri "/"}]))
;; and
(-> (serve-pages {"/" (constantly nil)}) (apply [{:uri "/"}]))
;; act like
(-> (serve-pages {}) (apply [{:uri "/"}]))
; {:status 404,
; :body "<h1>Page not found</h1>",
; :headers {"Content-Type" "text/html"}}
Clean setup with these dependencies:
:dependencies [[org.clojure/clojure "1.6.0"]
[stasis "2.2.1"]]
Gives warnings running lein deps :tree
when using Leiningen 2.5.0. These are the warnings:
WARNING!!! version ranges found for:
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/parsley "0.9.1"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [noencore "0.1.8"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/parsley "0.9.1"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [noencore "0.1.8"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [noencore "0.1.8"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/parsley "0.9.1"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
[stasis "2.2.1" :exclusions [commons-codec]] -> [inflections "0.9.5"] -> [noencore "0.1.8"] -> [com.keminglabs/cljx "0.3.1"] -> [org.clojars.trptcolin/sjacket "0.1.0.3"] -> [net.cgrand/parsley "0.9.1"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [stasis "2.2.1" :exclusions [org.clojure/clojure commons-codec]].
As per the wonderful building static sites with stasis post I am running a (stasis/empty-directory! export-dir)
before each export.
As the project grows building everything from scratch takes greater and greater amounts of time (especially when factoring in image optimization with many images at various sizes)
Do you have any advice on checking for stale, already output and unmodified since that time, content? I can think of a basic static EDN file that holds export timestamps for each post, against which I check when I run 'export'. I am unsure if this is a good way to proceed though?
Any advice would be greatly appreciated.
I am trying to serve markdown lazily in development. By this, I mean that if I update a markdown file, I wish for the changes to reflect when I refresh the browser. I can do this by serving functions instead of the raw content as strings. I am determining the URL by a slug on the markdown metadata. I am also using slurp-resources
.
While I get my desired behaviour of a browser refresh accurately reflecting the latest changes, it is rendering every page not just the one I refreshed. I will potentially have a lot of pages with a lot of svg in it, so this is not desirable.
What would you recommend to achieve what I seek? One way is to simply re-read the file when the request comes. Is there a better way?
I refer to my stack overflow post
Trying to get this to work but to no avail
Hi there! I'm a huge fan of Stasis. I've been tweeting about the static site generator I'm making with Stasis and I think we're Twitter mutuals now! I just wrote my own Atom feed generator similar to how you describe in the README except that I didn't realize that sexp-as-element
was available (super cool) until I revisted Stasis's README today.
One thing I ran into while writing my Atom feed generator is that clojure.data.xml
automatically prefixes all XML namespaces, and there's no way to turn this off as far as I can tell. ๐ญ I'm not sure when they made this change. This means that you must use prefixed tag names to correctly use an XML namespace.
This is a concise example:
(xml/emit
(xml/sexp-as-element
[:feed {:xmlns "http://www.w3.org/2005/Atom"}
[:id "urn:whattheemacsd-com:feed"]]))
returns:
<?xml version="1.0" encoding="UTF-8"?><feed xmlns:a="http://www.w3.org/2005/Atom"><id>urn:whattheemacsd-com:feed</id></feed>
I have build a project via your description, which went just fine, but I am not sure, how to do hot code reloading with stasis. Could you please help me?
Github pages, when using a custom domain, expects a file called CNAME
in the root of your site - however magnars deliberately doesn't allow publishing a file with no extension, it returns an error:
The following page paths must end in a slash: ("/CNAME")
It would be good to be able to whitelist special cases such as this, somehow.
Could not find artifact statis:statis:jar:1.0.0 in clojars (https://clojars.org/repo/)
I updated my blog and no longer use stasis.
This isn't a problem with stasis/optimus, but ultimately with my hacky org-mode
setup. I just got fed up with the whole thing and switched to a batteries-included SSG for my blog (since most SSGs address that problem well).
The github repo that is linked to is still accurate and (AFAIK) still works, but the blog link is no longer generated with stasis (though I'm not happy with my current setup and may end up going back to stasis soon).
slurp-directory seems to be attempting to slurp the root directory and therefore returning a FileNotFoundException. I guess the solution would be to filter away directories before slurping?
public/
directory inside my project. (Not in the resources directory.)(file-seq (clojure.java.io/file "public/"))
works fine(stasis.core/slurp-directory "public/" #".*")
returns "FileNotFoundException public java.io.FileInputStream.open (FileInputStream.java:-2)"(slurp (first (file-seq (clojure.java.io/file "public/"))))
also returns the same exception which could be a clue?(Perhaps the exception is caused by something else, I'm not best person to say.)
Cheers, Dave.
slurp-resources
fails when it tries to get all the file paths on class paths.
It seems to me as if the chop is superfluous. The canonicalPath provides the full path, not just from the project root, so in trying to chop the path's root dir from the class path, it ends up chopping the first few characters of the absolute path.
Is chop-path necessary?
It would be nice if the exported pages only used relative URLs. This way the static pages would be so static you could just drop the files directly into a browser from local disk. Should be fairly approachable via enlive as well.
hi.
http://cjohansen.no/building-static-sites-in-clojure-with-stasis can't be opened.i searched its snapshot: http://webcache.googleusercontent.com/search?q=cache:xOk4FxU2v2EJ:cjohansen.no/building-static-sites-in-clojure-with-stasis+&cd=1&hl=zh-CN&ct=clnk ,i don't understand which file i should put the following content into:
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"}
?
tks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.