Skip to content

Commit

Permalink
Allow to disable welcome page (#561)
Browse files Browse the repository at this point in the history
When passing the same `:paths` or `:paths-fn` arg as for `build!` to `serve!` Clerk will no longer the built-in welcome page and instead serve the generated or user-specified index page on root. This is a first step towards enabling easy sharing fully interactive Clerk documents including pagination &c.

Co-authored-by: Andrea Amantini <[email protected]>
  • Loading branch information
mk and zampino authored Oct 23, 2023
1 parent 3fce7ea commit 424bf35
Show file tree
Hide file tree
Showing 13 changed files with 348 additions and 224 deletions.
4 changes: 4 additions & 0 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
:exclusions [org.babashka/sci]}
io.github.nextjournal/clerk-slideshow {:git/sha "11a83fea564da04b9d17734f2031a4921d917893"}}}

:nextjournal/garden {:exec-fn nextjournal.clerk/serve!
:exec-args {:index "book.clj"}
:nextjournal.garden/aliases [:demo]}

:build {:deps {io.github.nextjournal/clerk {:local/root "."}
io.github.nextjournal/cas-client {:git/sha "22ef8360689cd3938e43a3223023ab1b9711818f"}
io.github.clojure/tools.build {:git/tag "v0.6.1" :git/sha "515b334"}
Expand Down
1 change: 1 addition & 0 deletions garden.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:project "book-of-clerk"}
2 changes: 0 additions & 2 deletions notebooks/intern.clj
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ c
(ns-unmap *ns* 'variable)
(ns-unmap (find-ns 'foreign) 'variable)

(reset! nextjournal.clerk.webserver/!doc nextjournal.clerk.webserver/help-doc)

;; inspect recorded interns
(-> @nextjournal.clerk.webserver/!doc
:blocks (->> (mapcat (comp :nextjournal/interned :result))))
Expand Down
9 changes: 7 additions & 2 deletions src/nextjournal/clerk.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[nextjournal.clerk.config :as config]
[nextjournal.clerk.eval :as eval]
[nextjournal.clerk.parser :as parser]
[nextjournal.clerk.paths :as paths]
[nextjournal.clerk.viewer :as v]
[nextjournal.clerk.webserver :as webserver]))

Expand Down Expand Up @@ -51,7 +52,10 @@

:else
file-or-ns)
doc (try (merge opts
doc (try (merge (webserver/get-build-opts)
opts
(when-let [path (paths/path-in-cwd file-or-ns)]
{:file-path path})
{:nav-path (webserver/->nav-path file-or-ns)}
(parser/parse-file {:doc? true} file))
(catch java.io.FileNotFoundException _e
Expand All @@ -63,7 +67,8 @@
e))))
_ (reset! !last-file file)
{:keys [blob->result]} @webserver/!doc
{:keys [result time-ms]} (try (eval/time-ms (eval/+eval-results blob->result (assoc doc :set-status-fn webserver/set-status!)))
{:keys [result time-ms]} (try (eval/time-ms (binding [paths/*build-opts* (webserver/get-build-opts)]
(eval/+eval-results blob->result (assoc doc :set-status-fn webserver/set-status!))))
(catch Exception e
(throw (ex-info (str "`nextjournal.clerk/show!` encountered an eval error with: `" (pr-str file-or-ns) "`") {::doc (assoc doc :blob->result blob->result)} e))))]
(println (str "Clerk evaluated '" file "' in " time-ms "ms."))
Expand Down
119 changes: 6 additions & 113 deletions src/nextjournal/clerk/builder.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@
"Clerk's Static App Builder."
(:require [babashka.fs :as fs]
[babashka.process :refer [sh]]
[clojure.edn :as edn]
[clojure.java.browse :as browse]
[clojure.java.io :as io]
[clojure.string :as str]
[nextjournal.clerk.analyzer :as analyzer]
[nextjournal.clerk.builder-ui :as builder-ui]
[nextjournal.clerk.config :as config]
[nextjournal.clerk.eval :as eval]
[nextjournal.clerk.parser :as parser]
[nextjournal.clerk.paths :as paths]
[nextjournal.clerk.view :as view]
[nextjournal.clerk.viewer :as viewer]
[nextjournal.clerk.webserver :as webserver]
[nextjournal.clerk.config :as config])
(:import (java.net URL)))
[nextjournal.clerk.webserver :as webserver]))

(def clerk-docs
(into ["CHANGELOG.md"
Expand Down Expand Up @@ -127,84 +126,6 @@
(def default-out-path
(str "public" fs/file-separator "build"))

(defn ^:private ensure-not-empty [build-opts {:as opts :keys [error expanded-paths]}]
(if error
opts
(if (empty? expanded-paths)
(merge {:error "nothing to build" :expanded-paths expanded-paths} (select-keys build-opts [:paths :paths-fn :index]))
opts)))

(defn ^:private maybe-add-index [{:as build-opts :keys [index]} {:as opts :keys [expanded-paths]}]
(if-not (contains? build-opts :index)
opts
(if (and (not (instance? URL index))
(not (symbol? index))
(or (not (string? index)) (not (fs/exists? index))))
{:error "`:index` must be either an instance of java.net.URL or a string and point to an existing file"
:index index}
(cond-> opts
(and index (not (contains? (set expanded-paths) index)))
(update :expanded-paths conj index)))))

#_(maybe-add-index {:index "book.clj"} {:expanded-paths ["README.md"]})
#_(maybe-add-index {:index 'book.clj} {:expanded-paths ["README.md"]})

(defn resolve-paths [{:as build-opts :keys [paths paths-fn index]}]
(when (and paths paths-fn)
(binding [*out* *err*]
(println "[info] both `:paths` and `:paths-fn` are set, `:paths` will take precendence.")))
(if (not (or paths paths-fn index))
{:error "must set either `:paths`, `:paths-fn` or `:index`."
:build-opts build-opts}
(cond paths (if (sequential? paths)
{:resolved-paths paths}
{:error "`:paths` must be sequential" :paths paths})
paths-fn (let [ex-msg "`:path-fn` must be a qualified symbol pointing at an existing var."]
(if-not (qualified-symbol? paths-fn)
{:error ex-msg :paths-fn paths-fn}
(if-some [resolved-var (try (requiring-resolve paths-fn)
(catch Exception _e nil))]
(let [{:as opts :keys [error paths]}
(try {:paths (cond-> @resolved-var (fn? @resolved-var) (apply []))}
(catch Exception e
{:error (str "An error occured invoking `" (pr-str resolved-var) "`: " (ex-message e))
:paths-fn paths-fn}))]
(if error
opts
(if-not (sequential? paths)
{:error (str "`:paths-fn` must compute to a sequential value.")
:paths-fn paths-fn :resolved-paths paths}
{:resolved-paths paths})))
{:error ex-msg :paths-fn paths-fn})))
index {:resolved-paths []})))

#_(resolve-paths {:paths ["notebooks/di*.clj"]})
#_(resolve-paths {:paths-fn 'clojure.core/inc})
#_(resolve-paths {:paths-fn 'nextjournal.clerk.builder/clerk-docs})

(defn expand-paths [build-opts]
(let [{:as opts :keys [error resolved-paths]} (resolve-paths build-opts)]
(if error
opts
(->> resolved-paths
(mapcat (fn [path] (if (fs/exists? path)
[path]
(fs/glob "." path))))
(filter (complement fs/directory?))
(mapv (comp str fs/file))
(hash-map :expanded-paths)
(maybe-add-index build-opts)
(ensure-not-empty build-opts)))))

#_(expand-paths {:paths ["notebooks/di*.clj"] :index "src/nextjournal/clerk/index.clj"})
#_(expand-paths {:paths ['notebooks/rule_30.clj]})
#_(expand-paths {:index "book.clj"})
#_(expand-paths {:paths-fn `clerk-docs})
#_(expand-paths {:paths-fn `clerk-docs-2})
#_(do (defn my-paths [] ["notebooks/h*.clj"])§
(expand-paths {:paths-fn `my-paths}))
#_(expand-paths {:paths ["notebooks/viewers**"]})

(def builtin-index
(io/resource "nextjournal/clerk/index.clj"))

Expand All @@ -216,17 +137,15 @@
(let [opts+index (cond-> opts
index (assoc :index (str index)))
{:as opts' :keys [expanded-paths]} (cond-> opts+index
expand-paths? (merge (expand-paths opts+index)))]
expand-paths? (merge (paths/expand-paths opts+index)))]
(-> opts'
(update :resource->url #(merge {} %2 %1) @config/!resource->url)
(cond-> #_opts'
expand-paths?
(dissoc :expand-paths?)
(and (not index) (= 1 (count expanded-paths)))
(assoc :index (first expanded-paths))
(and (not index) (< 1 (count expanded-paths)) (every? (complement viewer/index-path?) expanded-paths))
(as-> opts
(-> opts (assoc :index builtin-index) (update :expanded-paths conj builtin-index))))))))
(-> opts (assoc :index builtin-index) (update :expanded-paths conj builtin-index))))))))

#_(process-build-opts {:index 'book.clj :expand-paths? true})
#_(process-build-opts {:paths ["notebooks/rule_30.clj"] :expand-paths? true})
Expand Down Expand Up @@ -336,31 +255,6 @@
(str (viewer/relative-root-prefix-from (viewer/map-index opts file)) path
(when fragment (str "#" fragment))))))

(defn read-opts-from-deps-edn! []
(if (fs/exists? "deps.edn")
(let [deps-edn (edn/read-string (slurp "deps.edn"))]
(if-some [clerk-alias (get-in deps-edn [:aliases :nextjournal/clerk])]
(get clerk-alias :exec-args
{:error (str "No `:exec-args` found in `:nextjournal/clerk` alias.")})
{:error (str "No `:nextjournal/clerk` alias found in `deps.edn`.")}))
{:error (str "No `deps.edn` found in project.")}))

(def ^:dynamic ^:private *build-opts* nil)
(def build-help-link "\n\nLearn how to [set up your static build](https://book.clerk.vision/#static-building).")
(defn index-paths
([] (index-paths (or *build-opts* (read-opts-from-deps-edn!))))
([{:as opts :keys [index error]}]
(if error
(update opts :error str build-help-link)
(let [{:as result :keys [expanded-paths error]} (expand-paths opts)]
(if error
(update result :error str build-help-link)
{:paths (remove #{index "index.clj"} expanded-paths)})))))

#_(index-paths)
#_(index-paths {:paths ["CHANGELOG.md"]})
#_(index-paths {:paths-fn "boom"})

(defn build-static-app! [{:as opts :keys [bundle?]}]
(let [{:as opts :keys [download-cache-fn upload-cache-fn report-fn compile-css? expanded-paths error]}
(process-build-opts (assoc opts :expand-paths? true))
Expand Down Expand Up @@ -391,11 +285,10 @@
(let [{result :result duration :time-ms} (eval/time-ms
(try
(binding [*ns* *ns*
*build-opts* opts
paths/*build-opts* opts
viewer/doc-url (partial doc-url opts file)]
(let [doc (eval/eval-analyzed-doc doc)]
(assoc doc :viewer (view/doc->viewer (assoc opts
:static-build? true
:nav-path (if (instance? java.net.URL file)
(str "'" (:ns doc))
(str file)))
Expand Down
40 changes: 40 additions & 0 deletions src/nextjournal/clerk/git.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
(ns nextjournal.clerk.git
"Clerk's Git integration for backlinks to source code repos."
(:require [babashka.process :as p]
[clojure.string :as str]))

(defn ^:private shell-out-str
"Shell helper, calls a cmd and returns it output string trimmed."
[cmd]
(str/trim (:out (p/shell {:out :string} cmd))))

#_(shell-out-str "git rev-parse HEAD")
#_(shell-out-str "zonk")

(defn ->github-project [remote-url]
(second (re-find #"^git@github\.com:(.*)\.git$" remote-url)))

(defn ->https-git-url
"Takes a git `remote-url` and tries to convert it into a https url for
backlinks. Currently only works for github, should be extended for
gitlab, etc."
[remote-url]
(cond
(str/starts-with? remote-url "https://")
(str/replace remote-url #"\.git$" "")

(->github-project remote-url)
(str "https://github.com/%s" (->github-project remote-url))))

#_(->https-git-url "https://github.com/nextjournal/clerk.git")
#_(->https-git-url "[email protected]:nextjournal/clerk.git")

(defn read-git-attrs []
(try {:git/sha (shell-out-str "git rev-parse HEAD")
:git/url (some ->https-git-url
(map #(shell-out-str (str "git remote get-url " %))
(str/split-lines (shell-out-str "git remote"))))}
(catch Exception _
{})))

#_(read-git-attrs)
8 changes: 4 additions & 4 deletions src/nextjournal/clerk/home.clj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
(ns nextjournal.clerk.home
{:nextjournal.clerk/visibility {:code :hide :result :hide}}
(:require [clojure.string :as str]
[babashka.fs :as fs]
(:require [babashka.fs :as fs]
[clojure.string :as str]
[nextjournal.clerk :as clerk]
[nextjournal.clerk.builder :as builder]
[nextjournal.clerk.paths :as paths]
[nextjournal.clerk.viewer :as v]))

(defn glob-notebooks []
Expand Down Expand Up @@ -192,7 +192,7 @@
(when-not (seq (:query @!filter))
[:div {:class "w-1/2 pt-6 pl-6"}
[:h4.text-lg "Static Build Index"]
(let [{:keys [paths error]} (builder/index-paths)]
(let [{:keys [paths error]} (paths/index-paths)]
(cond
error [:div {:class "-mx-8"} (clerk/md error)]
paths (let [{:keys [query]} @!filter]
Expand Down
11 changes: 6 additions & 5 deletions src/nextjournal/clerk/index.clj
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
(ns nextjournal.clerk.index
{:nextjournal.clerk/visibility {:code :hide :result :hide}}
{:nextjournal.clerk/visibility {:code :hide :result :hide}
:nextjournal.clerk/no-cache true}
(:require [babashka.fs :as fs]
[clojure.string :as str]
[nextjournal.clerk :as clerk]
[nextjournal.clerk.viewer :as v]
[nextjournal.clerk.builder :as builder]))
[nextjournal.clerk.paths :as paths]
[nextjournal.clerk.viewer :as v]))

(def !paths (delay (builder/index-paths)))
(def !paths (delay (paths/index-paths)))

(def index-item-viewer
{:pred string?
Expand Down Expand Up @@ -41,4 +42,4 @@
(clerk/html
[:div.text-xs.text-slate-400.font-sans.mb-8.not-prose
[:span.block.font-medium "This index page was automatically generated by Clerk."]
"You can customize it by adding a index.clj file to your project’s root directory. See " [:a.text-blue-600.dark:text-blue-300.hover:underline {:href "https://book.clerk.vision/#static-building"} "Static Publishing"] " in the " [:a.text-blue-600.dark:text-blue-300.hover:underline {:href "http://book.clerk.vision"} "Book of Clerk"] "."])
"You can customize it by adding an index.clj file to your project’s root directory. See " [:a.text-blue-600.dark:text-blue-300.hover:underline {:href "https://book.clerk.vision/#static-building"} "Static Publishing"] " in the " [:a.text-blue-600.dark:text-blue-300.hover:underline {:href "http://book.clerk.vision"} "Book of Clerk"] "."])
Loading

0 comments on commit 424bf35

Please sign in to comment.