From 2b33638a8dcf3f334225cd40f83533cca162f574 Mon Sep 17 00:00:00 2001 From: Martin Kavalar Date: Mon, 22 May 2023 10:31:09 +0200 Subject: [PATCH] Improve render performance by only evaluating each render-fn once --- src/nextjournal/clerk/render.cljs | 5 ++++- src/nextjournal/clerk/view.clj | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/nextjournal/clerk/render.cljs b/src/nextjournal/clerk/render.cljs index 86806eb0c..766e0be01 100644 --- a/src/nextjournal/clerk/render.cljs +++ b/src/nextjournal/clerk/render.cljs @@ -698,12 +698,15 @@ (let [re-eval (fn [{:keys [form]}] (viewer/->viewer-fn form))] (w/postwalk (fn [x] (cond-> x (viewer/viewer-fn? x) re-eval)) doc))) +(defn replace-viewer-fns [doc] + (w/postwalk-replace (:hash->viewer doc) (dissoc doc :hash->viewer))) + (defn ^:export set-state! [{:as state :keys [doc]}] (when (contains? state :doc) (when (exists? js/window) ;; TODO: can we restore the scroll position when navigating back? (.scrollTo js/window #js {:top 0})) - (reset! !doc doc)) + (reset! !doc (replace-viewer-fns doc))) ;; (when (and error (contains? @!doc :status)) ;; (swap! !doc dissoc :status)) (when (remount? doc) diff --git a/src/nextjournal/clerk/view.clj b/src/nextjournal/clerk/view.clj index 6f4ea108e..9edf13c08 100644 --- a/src/nextjournal/clerk/view.clj +++ b/src/nextjournal/clerk/view.clj @@ -1,15 +1,25 @@ (ns nextjournal.clerk.view - (:require [nextjournal.clerk.viewer :as v] - [hiccup.page :as hiccup] + (:require [clojure.java.io :as io] + [clojure.set :as set] [clojure.string :as str] - [clojure.java.io :as io]) + [clojure.walk :as walk] + [hiccup.page :as hiccup] + [nextjournal.clerk.viewer :as v]) (:import (java.net URI))) +(defn ^:private extract-hash->viewer [presentation] + (into {} + (map (juxt :hash identity)) + (keep :nextjournal/viewer (tree-seq (some-fn map? vector?) #(cond-> % (map? %) vals) presentation)))) + (defn doc->viewer ([doc] (doc->viewer {} doc)) ([opts {:as doc :keys [ns file]}] (binding [*ns* ns] - (-> (merge doc opts) v/notebook v/present)))) + (let [presentation (-> (merge doc opts) v/notebook v/present) + hash->viewer (extract-hash->viewer presentation)] + (assoc (walk/postwalk-replace (set/map-invert hash->viewer) presentation) + :hash->viewer hash->viewer))))) #_(doc->viewer (nextjournal.clerk/eval-file "notebooks/hello.clj")) #_(nextjournal.clerk/show! "notebooks/test.clj")