Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
Charlotte Allen | ee2f6dcded | |
Charlotte Allen | 1f3183d9f6 | |
Charlotte Allen | 462fef7cf6 | |
Charlotte Allen | 0674314e0d |
|
@ -19,6 +19,7 @@
|
||||||
[metosin/reitit "0.3.10"]
|
[metosin/reitit "0.3.10"]
|
||||||
[metosin/ring-http-response "0.9.1"]
|
[metosin/ring-http-response "0.9.1"]
|
||||||
[mount "0.1.16"]
|
[mount "0.1.16"]
|
||||||
|
[duratom "0.5.2"]
|
||||||
[nrepl "0.6.0"]
|
[nrepl "0.6.0"]
|
||||||
[org.clojure/clojure "1.10.1"]
|
[org.clojure/clojure "1.10.1"]
|
||||||
[org.clojure/tools.cli "0.4.2"]
|
[org.clojure/tools.cli "0.4.2"]
|
||||||
|
@ -29,6 +30,8 @@
|
||||||
[ring-webjars "0.2.0"]
|
[ring-webjars "0.2.0"]
|
||||||
[ring/ring-core "1.8.0"]
|
[ring/ring-core "1.8.0"]
|
||||||
[ring/ring-defaults "0.3.2"]
|
[ring/ring-defaults "0.3.2"]
|
||||||
|
[lein-cljfmt "0.6.6"]
|
||||||
|
|
||||||
[selmer "1.12.18"]]
|
[selmer "1.12.18"]]
|
||||||
|
|
||||||
:min-lein-version "2.0.0"
|
:min-lein-version "2.0.0"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
(ns shapey-shifty.context.core
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[shapey-shifty.posts.core :as posts]
|
||||||
|
[shapey-shifty.index.index :as index]))
|
||||||
|
|
||||||
|
(s/def ::posts (s/coll-of :posts/post))
|
||||||
|
(s/def ::index :index/index)
|
||||||
|
|
||||||
|
(s/def ::context (s/keys :req [::posts ::current-time ::index]))
|
|
@ -2,10 +2,12 @@
|
||||||
(:require
|
(:require
|
||||||
[shapey-shifty.handler :as handler]
|
[shapey-shifty.handler :as handler]
|
||||||
[shapey-shifty.nrepl :as nrepl]
|
[shapey-shifty.nrepl :as nrepl]
|
||||||
|
[shapey-shifty.index.index :as index]
|
||||||
[luminus.http-server :as http]
|
[luminus.http-server :as http]
|
||||||
[shapey-shifty.config :refer [env]]
|
[shapey-shifty.config :refer [env]]
|
||||||
[clojure.tools.cli :refer [parse-opts]]
|
[clojure.tools.cli :refer [parse-opts]]
|
||||||
[clojure.tools.logging :as log]
|
[clojure.tools.logging :as log]
|
||||||
|
[shapey-shifty.posts.post-io :as io]
|
||||||
[mount.core :as mount])
|
[mount.core :as mount])
|
||||||
(:gen-class))
|
(:gen-class))
|
||||||
|
|
||||||
|
@ -21,6 +23,11 @@
|
||||||
[["-p" "--port PORT" "Port number"
|
[["-p" "--port PORT" "Port number"
|
||||||
:parse-fn #(Integer/parseInt %)]])
|
:parse-fn #(Integer/parseInt %)]])
|
||||||
|
|
||||||
|
(mount/defstate index :start (if-let [path (env :index-path)]
|
||||||
|
(index/create-index path)
|
||||||
|
(index/create-index "resources/index.edn")))
|
||||||
|
(mount/defstate file-keeper :start)
|
||||||
|
|
||||||
(mount/defstate ^{:on-reload :noop} http-server
|
(mount/defstate ^{:on-reload :noop} http-server
|
||||||
:start
|
:start
|
||||||
(http/start
|
(http/start
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
(ns shapey-shifty.index.index
|
(ns shapey-shifty.index.index
|
||||||
(:require [clucy.core :as clucy]
|
(:require
|
||||||
[shapey-shifty.posts.posts-io :as post-io]))
|
[clojure.spec.alpha :as s]
|
||||||
|
[duratom.core :as dur]
|
||||||
|
[shapey-shifty.posts.posts-io :as post-io]))
|
||||||
|
|
||||||
(def index-path (atom "resources/index"))
|
(s/def ::index-item (s/keys :req [::filename ::key ::created-date ::stub]))
|
||||||
|
(s/def ::index (s/coll-of ::index-item))
|
||||||
|
|
||||||
(def post-index (clucy/disk-index @index-path))
|
(defn create-index [index-path]
|
||||||
|
(let [index (dur/duratom :local-file :file-path index-path :init [])]
|
||||||
|
index))
|
||||||
|
|
||||||
(defn add-post-to-index [post]
|
(defn add-post-to-index [index post]
|
||||||
(clucy/add post-index post))
|
(let [metadata (dissoc post :content)]
|
||||||
|
(if-let [existing-post (empty (filter #(= (:key %) (:key post)) index))]
|
||||||
|
(conj index metadata))))
|
||||||
|
|
||||||
(defn crawl-posts!
|
(defn crawl-posts!
|
||||||
([path]
|
([path]
|
||||||
|
@ -17,5 +24,5 @@
|
||||||
clojure.java.io/file
|
clojure.java.io/file
|
||||||
file-seq
|
file-seq
|
||||||
(filter #(.isFile %))
|
(filter #(.isFile %))
|
||||||
(mapv #(parsing-fn %))
|
(mapv parsing-fn)
|
||||||
(apply add-post-to-index))))
|
(apply add-post-to-index))))
|
||||||
|
|
|
@ -1,6 +1,38 @@
|
||||||
(ns shapey-shifty.posts.core)
|
(ns shapey-shifty.posts.core
|
||||||
|
(:require [clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
(defn create-empty-post [] {:type nil :properties {:name nil :author nil :published nil :content nil}})
|
(defn create-empty-post [] {::type :note ::key (java.util.UUID/randomUUID) ::content ""
|
||||||
|
::properties
|
||||||
|
{::name nil
|
||||||
|
::author nil
|
||||||
|
::published nil
|
||||||
|
::created (java.time.LocalDateTime/now)
|
||||||
|
::stub nil
|
||||||
|
::filename nil
|
||||||
|
::status :preview}})
|
||||||
|
|
||||||
|
(s/def ::name (s/nilable string?))
|
||||||
|
(s/def ::author (s/nilable string?))
|
||||||
|
(s/def ::published (s/nilable keyword?))
|
||||||
|
(s/def ::content (s/nilable string?))
|
||||||
|
(s/def ::stub (s/nilable string?))
|
||||||
|
(s/def ::filename (s/nilable string?))
|
||||||
|
(s/def ::type keyword?)
|
||||||
|
(s/def ::key uuid?)
|
||||||
|
(s/def ::status keyword?)
|
||||||
|
|
||||||
|
(s/def ::properties
|
||||||
|
(s/keys :req-un [::name ::author ::published ::stub ::filename ::created]))
|
||||||
|
|
||||||
|
(s/def ::post
|
||||||
|
(s/keys :req-un [::type ::properties ::content]))
|
||||||
|
|
||||||
|
(defprotocol PostKeeper
|
||||||
|
(create-post [this post])
|
||||||
|
(search-posts [this post-filter index])
|
||||||
|
(get-all-posts [this])
|
||||||
|
(update-post [this post])
|
||||||
|
(delete-post [this post]))
|
||||||
|
|
||||||
(defn set-publish-date [post date]
|
(defn set-publish-date [post date]
|
||||||
(assoc-in post [:properties :published] date))
|
(assoc-in post [:properties :published] date))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
[shapey-shifty.posts.core :as core]
|
[shapey-shifty.posts.core :as core]
|
||||||
[shapey-shifty.authors.author-core :as author]))
|
[shapey-shifty.authors.author-core :as author]))
|
||||||
|
|
||||||
(def post-filename "post.json")
|
(def post-filename "post.edn")
|
||||||
(def base-posts-path "resources/posts")
|
(def base-posts-path "resources/posts")
|
||||||
|
|
||||||
(defn create-path-by-date [year month day]
|
(defn create-path-by-date [year month day]
|
||||||
|
@ -43,3 +43,29 @@
|
||||||
(let [path (format "%s/%s/%s/%s" base-posts-path (pathmap-to-path dt-path) n post-filename)
|
(let [path (format "%s/%s/%s/%s" base-posts-path (pathmap-to-path dt-path) n post-filename)
|
||||||
f (clojure.java.io/file path)]
|
f (clojure.java.io/file path)]
|
||||||
(read-post f))))
|
(read-post f))))
|
||||||
|
|
||||||
|
(defn datetime-filename-resolver [post]
|
||||||
|
(if (:filename post)
|
||||||
|
(:filename post)))
|
||||||
|
|
||||||
|
(defrecord FileBasedPostKeeper [filename-resolver base-path filename index]
|
||||||
|
core/PostKeeper
|
||||||
|
(create-post [this post]
|
||||||
|
(let [path (str base-path (filename-resolver post) filename)]
|
||||||
|
(clojure.java.io/make-parents path)
|
||||||
|
(spit path post)))
|
||||||
|
(search-posts [this post-filter index]
|
||||||
|
(-> index
|
||||||
|
post-filter
|
||||||
|
(partial map #(:filename %))
|
||||||
|
(partial map #(clojure.java.io/file))
|
||||||
|
file-seq
|
||||||
|
(partial map read-post)))
|
||||||
|
(get-all-posts [this]
|
||||||
|
(->> base-path
|
||||||
|
clojure.java.io/file
|
||||||
|
file-seq
|
||||||
|
(filter #(.isFile %))
|
||||||
|
(map read-post)))
|
||||||
|
(update-post [this post] nil)
|
||||||
|
(delete-post [this post] nil))
|
||||||
|
|
|
@ -31,5 +31,4 @@
|
||||||
{:middleware @middleware}
|
{:middleware @middleware}
|
||||||
["/" {:get home-page}]
|
["/" {:get home-page}]
|
||||||
["/about/:name" {:get about-page}]
|
["/about/:name" {:get about-page}]
|
||||||
["/:year/:month/:day/:n" {:get post-view}]])
|
["/blog/:year/:month/:day/:n" {:get post-view}]])
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
||||||
|
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
||||||
|
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
||||||
|
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 0.0.0 //
|
||||||
|
-main src/clj/shapey_shifty/core.clj /^(defn -main [& args]$/;" f namespace:shapey-shifty.core
|
||||||
|
.material-icons resources/public/css/screen.css /^.material-icons {$/;" c
|
||||||
|
Error: {{status}} resources/html/error.html /^ <h1><span class="is-size-4 has-text-danger">Error: {{status}}<\/span><\/h1>$/;" h
|
||||||
|
License README.md /^## License$/;" s
|
||||||
|
Managing your middleware resources/docs/docs.md /^#### Managing your middleware$/;" t
|
||||||
|
Need some help? resources/docs/docs.md /^#### Need some help?$/;" t
|
||||||
|
Organizing the routes resources/docs/docs.md /^#### Organizing the routes$/;" t
|
||||||
|
Prerequisites README.md /^## Prerequisites$/;" s
|
||||||
|
Running README.md /^## Running$/;" s
|
||||||
|
Why are you seeing this page? resources/docs/docs.md /^#### Why are you seeing this page?$/;" t
|
||||||
|
about-page src/clj/shapey_shifty/routes/home.clj /^(defn about-page [request]$/;" f namespace:shapey-shifty.routes.home
|
||||||
|
add-load-post-step src/clj/shapey_shifty/pipeline/core.clj /^(defn add-load-post-step [f]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
add-pipeline src/clj/shapey_shifty/pipeline/core.clj /^(defn add-pipeline [k v]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
add-post-to-index src/clj/shapey_shifty/index/index.clj /^(defn add-post-to-index [index post]$/;" f namespace:shapey-shifty.index.index
|
||||||
|
add-render-post-step src/clj/shapey_shifty/pipeline/core.clj /^(defn add-render-post-step [f]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
add-write-post-step src/clj/shapey_shifty/pipeline/core.clj /^(defn add-write-post-step [f]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
app src/clj/shapey_shifty/handler.clj /^(defn app []$/;" f namespace:shapey-shifty.handler
|
||||||
|
assoc-author src/clj/shapey_shifty/posts/posts_io.clj /^(defn assoc-author [post]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
body resources/public/css/screen.css /^body {$/;" s
|
||||||
|
count-posts-in-date src/clj/shapey_shifty/posts/posts_io.clj /^(defn count-posts-in-date [dt-path]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
crawl-posts! src/clj/shapey_shifty/index/index.clj /^(defn crawl-posts!$/;" f namespace:shapey-shifty.index.index
|
||||||
|
create-author src/clj/shapey_shifty/authors/author_core.clj /^(defn create-author []$/;" f namespace:shapey-shifty.authors.author-core
|
||||||
|
create-empty-post src/clj/shapey_shifty/posts/core.clj /^(defn create-empty-post [] {::type :note ::key (java.util.UUID\/randomUUID) ::content ""$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
create-index src/clj/shapey_shifty/index/index.clj /^(defn create-index [index-path]$/;" f namespace:shapey-shifty.index.index
|
||||||
|
create-path-by-date src/clj/shapey_shifty/posts/posts_io.clj /^(defn create-path-by-date [year month day]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
datetime-filename-resolver src/clj/shapey_shifty/posts/posts_io.clj /^(defn datetime-filename-resolver [post]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
error-page src/clj/shapey_shifty/layout.clj /^(defn error-page$/;" f namespace:shapey-shifty.layout
|
||||||
|
execute-pipeline src/clj/shapey_shifty/pipeline/core.clj /^(defn execute-pipeline [k params]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
get-post src/clj/shapey_shifty/routes/post_router.clj /^(defn get-post$/;" f namespace:shapey-shifty.routes.post-router
|
||||||
|
home-page src/clj/shapey_shifty/routes/home.clj /^(defn home-page [request]$/;" f namespace:shapey-shifty.routes.home
|
||||||
|
home-routes src/clj/shapey_shifty/routes/home.clj /^(defn home-routes []$/;" f namespace:shapey-shifty.routes.home
|
||||||
|
html resources/public/css/screen.css /^html,$/;" s
|
||||||
|
load-all-authors src/clj/shapey_shifty/authors/author_core.clj /^(defn load-all-authors []$/;" f namespace:shapey-shifty.authors.author-core
|
||||||
|
load-author src/clj/shapey_shifty/authors/author_core.clj /^(defn load-author [author-name]$/;" f namespace:shapey-shifty.authors.author-core
|
||||||
|
nav-menu resources/html/base.html /^ <div id="nav-menu" class="navbar-menu">$/;" I
|
||||||
|
parse-json test/clj/shapey_shifty/test/handler.clj /^(defn parse-json [body]$/;" f namespace:shapey-shifty.test.handler
|
||||||
|
pathmap-to-path src/clj/shapey_shifty/posts/posts_io.clj /^(defn pathmap-to-path [{:keys [year month day]}]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
post-view src/clj/shapey_shifty/routes/home.clj /^(defn post-view [request]$/;" f namespace:shapey-shifty.routes.home
|
||||||
|
read-post src/clj/shapey_shifty/posts/posts_io.clj /^(defn read-post$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
render src/clj/shapey_shifty/layout.clj /^(defn render$/;" f namespace:shapey-shifty.layout
|
||||||
|
restart env/dev/clj/user.clj /^(defn restart$/;" f namespace:user
|
||||||
|
set-author src/clj/shapey_shifty/posts/core.clj /^(defn set-author [post author]$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
set-content src/clj/shapey_shifty/posts/core.clj /^(defn set-content [post post-content]$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
set-name src/clj/shapey_shifty/posts/core.clj /^(defn set-name [post post-name]$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
set-publish-date src/clj/shapey_shifty/posts/core.clj /^(defn set-publish-date [post date]$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
set-type src/clj/shapey_shifty/posts/core.clj /^(defn set-type [post post-type]$/;" f namespace:shapey-shifty.posts.core
|
||||||
|
shapey-shifty README.md /^# shapey-shifty$/;" c
|
||||||
|
shapey-shifty.authors.author-core src/clj/shapey_shifty/authors/author_core.clj /^(ns shapey-shifty.authors.author-core$/;" n
|
||||||
|
shapey-shifty.config src/clj/shapey_shifty/config.clj /^(ns shapey-shifty.config$/;" n
|
||||||
|
shapey-shifty.core src/clj/shapey_shifty/core.clj /^(ns shapey-shifty.core$/;" n
|
||||||
|
shapey-shifty.dev-middleware env/dev/clj/shapey_shifty/dev_middleware.clj /^(ns shapey-shifty.dev-middleware$/;" n
|
||||||
|
shapey-shifty.env env/dev/clj/shapey_shifty/env.clj /^(ns shapey-shifty.env$/;" n
|
||||||
|
shapey-shifty.env env/prod/clj/shapey_shifty/env.clj /^(ns shapey-shifty.env$/;" n
|
||||||
|
shapey-shifty.handler src/clj/shapey_shifty/handler.clj /^(ns shapey-shifty.handler$/;" n
|
||||||
|
shapey-shifty.index.index src/clj/shapey_shifty/index/index.clj /^(ns shapey-shifty.index.index$/;" n
|
||||||
|
shapey-shifty.layout src/clj/shapey_shifty/layout.clj /^(ns shapey-shifty.layout$/;" n
|
||||||
|
shapey-shifty.middleware src/clj/shapey_shifty/middleware.clj /^(ns shapey-shifty.middleware$/;" n
|
||||||
|
shapey-shifty.middleware.formats src/clj/shapey_shifty/middleware/formats.clj /^(ns shapey-shifty.middleware.formats$/;" n
|
||||||
|
shapey-shifty.nrepl src/clj/shapey_shifty/nrepl.clj /^(ns shapey-shifty.nrepl$/;" n
|
||||||
|
shapey-shifty.pipeline.core src/clj/shapey_shifty/pipeline/core.clj /^(ns shapey-shifty.pipeline.core)$/;" n
|
||||||
|
shapey-shifty.posts.core src/clj/shapey_shifty/posts/core.clj /^(ns shapey-shifty.posts.core$/;" n
|
||||||
|
shapey-shifty.posts.posts-io src/clj/shapey_shifty/posts/posts_io.clj /^(ns shapey-shifty.posts.posts-io$/;" n
|
||||||
|
shapey-shifty.routes.home src/clj/shapey_shifty/routes/home.clj /^(ns shapey-shifty.routes.home$/;" n
|
||||||
|
shapey-shifty.routes.post-router src/clj/shapey_shifty/routes/post_router.clj /^(ns shapey-shifty.routes.post-router$/;" n
|
||||||
|
shapey-shifty.test.handler test/clj/shapey_shifty/test/handler.clj /^(ns shapey-shifty.test.handler$/;" n
|
||||||
|
start env/dev/clj/user.clj /^(defn start$/;" f namespace:user
|
||||||
|
start src/clj/shapey_shifty/nrepl.clj /^(defn start$/;" f namespace:shapey-shifty.nrepl
|
||||||
|
start-app src/clj/shapey_shifty/core.clj /^(defn start-app [args]$/;" f namespace:shapey-shifty.core
|
||||||
|
stop env/dev/clj/user.clj /^(defn stop$/;" f namespace:user
|
||||||
|
stop src/clj/shapey_shifty/nrepl.clj /^(defn stop [server]$/;" f namespace:shapey-shifty.nrepl
|
||||||
|
stop-app src/clj/shapey_shifty/core.clj /^(defn stop-app []$/;" f namespace:shapey-shifty.core
|
||||||
|
update-pipeline src/clj/shapey_shifty/pipeline/core.clj /^(defn update-pipeline [k f]$/;" f namespace:shapey-shifty.pipeline.core
|
||||||
|
user env/dev/clj/user.clj /^(ns user$/;" n
|
||||||
|
wrap-base src/clj/shapey_shifty/middleware.clj /^(defn wrap-base [handler]$/;" f namespace:shapey-shifty.middleware
|
||||||
|
wrap-csrf src/clj/shapey_shifty/middleware.clj /^(defn wrap-csrf [handler]$/;" f namespace:shapey-shifty.middleware
|
||||||
|
wrap-dev env/dev/clj/shapey_shifty/dev_middleware.clj /^(defn wrap-dev [handler]$/;" f namespace:shapey-shifty.dev-middleware
|
||||||
|
wrap-formats src/clj/shapey_shifty/middleware.clj /^(defn wrap-formats [handler]$/;" f namespace:shapey-shifty.middleware
|
||||||
|
wrap-internal-error src/clj/shapey_shifty/middleware.clj /^(defn wrap-internal-error [handler]$/;" f namespace:shapey-shifty.middleware
|
||||||
|
write-post src/clj/shapey_shifty/posts/posts_io.clj /^(defn write-post [post dt-path]$/;" f namespace:shapey-shifty.posts.posts-io
|
||||||
|
{{post.name}} resources/html/post.html /^ <h1 class="p-name">{{post.name}}<\/h1>$/;" h
|
||||||
|
{{title}} resources/html/error.html /^ <h2 class="without-margin">{{title}}<\/h2>$/;" i
|
Loading…
Reference in New Issue