diff --git a/bb.edn b/bb.edn index 3828160dfea..eae94fccb8b 100644 --- a/bb.edn +++ b/bb.edn @@ -34,6 +34,10 @@ dev:build-publishing logseq.tasks.dev/build-publishing + dev:publish + (apply shell {:dir "deps/publish-spa"} "nbb-logseq -cp src -m logseq.publish-spa" + *command-line-args*) + dev:npx-cap-run-ios logseq.tasks.dev.mobile/npx-cap-run-ios diff --git a/deps/publish-spa/.gitignore b/deps/publish-spa/.gitignore new file mode 100644 index 00000000000..24976af0bd1 --- /dev/null +++ b/deps/publish-spa/.gitignore @@ -0,0 +1,2 @@ +/.clj-kondo/.cache +.nbb diff --git a/deps/publish-spa/nbb.edn b/deps/publish-spa/nbb.edn new file mode 100644 index 00000000000..e91920a09fb --- /dev/null +++ b/deps/publish-spa/nbb.edn @@ -0,0 +1,4 @@ +{:deps + {logseq/graph-parser + ;; Nbb bug. Should just be "../graph-parser" + {:local/root "../../../../graph-parser"}}} diff --git a/scripts/src/logseq/tasks/dev/publish.cljs b/deps/publish-spa/src/logseq/publish_spa.cljs similarity index 57% rename from scripts/src/logseq/tasks/dev/publish.cljs rename to deps/publish-spa/src/logseq/publish_spa.cljs index 397d04e1b74..625074f564d 100644 --- a/scripts/src/logseq/tasks/dev/publish.cljs +++ b/deps/publish-spa/src/logseq/publish_spa.cljs @@ -1,16 +1,19 @@ -(ns logseq.tasks.dev.publish +(ns logseq.publish-spa (:require [promesa.core :as p] ["path" :as path] - ["fs-extra$default" :as fs])) + ["fs-extra$default" :as fs] + [datascript.transit :as dt] + [logseq.graph-parser.cli :as gp-cli] + [logseq.publish-spa.html :as html])) (defn- handle-export-publish-assets [html custom-css-path export-css-path repo-path asset-filenames output-path] - (let [app-path "static" + (let [app-path "../../static" root-dir output-path static-dir (path/join root-dir "static") - assets-from-dir (path/join repo-path "assets") - assets-to-dir (path/join root-dir "assets") - index-html-path (path/join root-dir "index.html")] + assets-from-dir (path/join repo-path "assets") + assets-to-dir (path/join root-dir "assets") + index-html-path (path/join root-dir "index.html")] (p/let [_ (. fs ensureDir static-dir) _ (. fs ensureDir assets-to-dir) _ (p/all (concat @@ -61,17 +64,25 @@ {:type "success" :payload (str "Export public pages and publish assets to " root-dir " successfully 🎉")})))) +(defn- get-app-state + [] + {:ui/theme "dark", :ui/sidebar-collapsed-blocks {}, :ui/show-recent? false + :config {"local" {:feature/enable-whiteboards? true, :shortcuts {:editor/right ["mod+l" "right"], :ui/toggle-theme "t z"}, :ignored-page-references-keywords #{:description :desc}, :repo/dir-version 3, :default-templates {:journals ""}, :macros {"poem" "Rose is $1, violet's $2. Life's ordered: Org assists you."}, :shortcut/doc-mode-enter-for-new-block? false, :favorites ["foob"], :ui/show-empty-bullets? false, :preferred-file-format :edn, :preferred-workflow :now, :publishing/all-pages-public? true, :ref/default-open-blocks-level 2, :feature/enable-block-timestamps? false, :ref/linked-references-collapsed-threshold 50, :commands [], :meta/version 1, :hidden [], :default-queries {:journals '[{:title "🔨 NOW", :query [:find (pull ?h [*]) :in $ ?start ?today :where [?h :block/marker ?marker] [(contains? #{"NOW" "DOING"} ?marker)] [?h :block/page ?p] [?p :block/journal? true] [?p :block/journal-day ?d] [(>= ?d ?start)] [(<= ?d ?today)]], :inputs [:14d :today], :result-transform (fn [result] (sort-by (fn [h] (get h :block/priority "Z")) result)), :collapsed? false} {:title "📅 NEXT", :query [:find (pull ?h [*]) :in $ ?start ?next :where [?h :block/marker ?marker] [(contains? #{"NOW" "LATER" "TODO"} ?marker)] [?h :block/ref-pages ?p] [?p :block/journal? true] [?p :block/journal-day ?d] [(> ?d ?start)] [(< ?d ?next)]], :inputs [:today :7d-after], :collapsed? false}]}, :ui/enable-tooltip? true, :rich-property-values? false, :property/separated-by-commas #{:comma-prop}, :property-pages/excludelist #{:author}, :graph/settings {:journal? true, :excluded-pages? true, :orphan-pages? false, :builtin-pages? false}, :property-pages/enabled? true, :ui/show-command-doc? true, :preferred-format :markdown}}}) + +(defn- get-db [graph-dir] + (let [{:keys [conn]} (gp-cli/parse-graph graph-dir {:verbose false})] @conn)) + (defn -main - [args] + [& args] (let [repo-path (or (first args) (throw (ex-info "GRAPH DIR required" {}))) output-path (or (second args) (throw (ex-info "OUT DIR required" {}))) - html "WOOHOO" + ; html "WOOHOO" + db-str (dt/write-transit-str (get-db repo-path)) + html (html/publishing-html db-str (pr-str (get-app-state))) custom-css-path (path/join repo-path "logseq" "custom.css") export-css-path (path/join repo-path "logseq" "export.css") ;; TODO: Read from repo-path asset-filenames []] (handle-export-publish-assets html custom-css-path export-css-path repo-path asset-filenames output-path))) - -(-main *command-line-args*) diff --git a/deps/publish-spa/src/logseq/publish_spa/html.cljs b/deps/publish-spa/src/logseq/publish_spa/html.cljs new file mode 100644 index 00000000000..f87663998cb --- /dev/null +++ b/deps/publish-spa/src/logseq/publish_spa/html.cljs @@ -0,0 +1,122 @@ +(ns ^:no-doc logseq.publish-spa.html + ; (:require-macros [hiccups.core]) + (:require [clojure.string :as string] + [goog.string :as gstring] + [goog.string.format] + #_[hiccups.runtime])) + +(defn- escape-html + "Change special characters into HTML character entities." + [text] + (-> text + (string/replace "&" "logseq____&") + (string/replace "<" "logseq____<") + (string/replace ">" "logseq____>") + (string/replace "\"" "logseq____"") + (string/replace "'" "logseq____'"))) + +;; from https://github.com/babashka/babashka/blob/8c1077af00c818ade9e646dfe1297bbe24b17f4d/examples/notes.clj#L21 +(defn html [v] + (cond (vector? v) + (let [tag (first v) + attrs (second v) + attrs (when (map? attrs) attrs) + elts (if attrs (nnext v) (next v)) + tag-name (name tag)] + (gstring/format "<%s%s>%s\n" tag-name (html attrs) (html elts) tag-name)) + (map? v) + (string/join "" + (map (fn [[k v]] + (gstring/format " %s=\"%s\"" (name k) v)) v)) + (seq? v) + (string/join " " (map html v)) + :else (str v))) + +(defn publishing-html + [transit-db app-state] + ;; TODO: Implement get-config + (let [{:keys [icon name alias title description url]} (:project {} #_(state/get-config)) + icon (or icon "static/img/logo.png") + project (or alias name)] + (str "\n" + (html + (list + [:head + [:meta {:charset "utf-8"}] + [:meta + {:content + "minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no", + :name "viewport"}] + [:link {:type "text/css", :href "static/css/tabler-icons.min.css", :rel "stylesheet"}] + [:link {:type "text/css", :href "static/css/style.css", :rel "stylesheet"}] + [:link {:type "text/css", :href "static/css/custom.css", :rel "stylesheet"}] + [:link {:type "text/css", :href "static/css/export.css", :rel "stylesheet"}] + [:link + {:href icon + :type "image/png", + :rel "shortcut icon"}] + [:link + {:href icon + :sizes "192x192", + :rel "shortcut icon"}] + [:link + {:href icon + :rel "apple-touch-icon"}] + + [:meta {:name "apple-mobile-web-app-title" :content project}] + [:meta {:name "apple-mobile-web-app-capable" :content "yes"}] + [:meta {:name "apple-touch-fullscreen" :content "yes"}] + [:meta {:name "apple-mobile-web-app-status-bar-style" :content "black-translucent"}] + [:meta {:name "mobile-web-app-capable" :content "yes"}] + + [:meta {:content title, :property "og:title"}] + [:meta {:content "site", :property "og:type"}] + (when url [:meta {:content url, :property "og:url"}]) + [:meta + {:content icon + :property "og:image"}] + [:meta + {:content description + :property "og:description"}] + [:title title] + [:meta {:content project, :property "og:site_name"}] + [:meta + {:description description}]] + [:body + [:div {:id "root"}] + [:script (gstring/format "window.logseq_db=%s" (js/JSON.stringify (escape-html transit-db)))] + [:script (str "window.logseq_state=" (js/JSON.stringify app-state))] + [:script {:type "text/javascript"} + "// Single Page Apps for GitHub Pages + // https://github.com/rafgraph/spa-github-pages + // Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License + // ---------------------------------------------------------------------- + // This script checks to see if a redirect is present in the query string + // and converts it back into the correct url and adds it to the + // browser's history using window.history.replaceState(...), + // which won't cause the browser to attempt to load the new url. + // When the single page app is loaded further down in this file, + // the correct url will be waiting in the browser's history for + // the single page app to route accordingly. + (function(l) { + if (l.search) { + var q = {}; + l.search.slice(1).split('&').forEach(function(v) { + var a = v.split('='); + q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&'); + }); + if (q.p !== undefined) { + window.history.replaceState(null, null, + l.pathname.slice(0, -1) + (q.p || '') + + (q.q ? ('?' + q.q) : '') + + l.hash + ); + } + } + }(window.location))"] + ;; TODO: should make this configurable + [:script {:src "static/js/main.js"}] + [:script {:src "static/js/highlight.min.js"}] + [:script {:src "static/js/interact.min.js"}] + [:script {:src "static/js/katex.min.js"}] + [:script {:src "static/js/code-editor.js"}]]))))) diff --git a/src/main/frontend/handler/export.cljs b/src/main/frontend/handler/export.cljs index 992866e68b8..19f0ffcbaae 100644 --- a/src/main/frontend/handler/export.cljs +++ b/src/main/frontend/handler/export.cljs @@ -89,6 +89,7 @@ :config]) state (update state :config (fn [config] {"local" (get config repo)})) + _ (prn :STATE state) raw-html-str (html/publishing-html db-str (pr-str state)) html-str (str "data:text/html;charset=UTF-8," (js/encodeURIComponent raw-html-str))] diff --git a/src/main/frontend/publishing/html.cljs b/src/main/frontend/publishing/html.cljs index d04fad52111..2fb425f0538 100644 --- a/src/main/frontend/publishing/html.cljs +++ b/src/main/frontend/publishing/html.cljs @@ -6,6 +6,7 @@ (defn publishing-html [transit-db app-state] + (prn :PROJECT (:project (state/get-config))) (let [{:keys [icon name alias title description url]} (:project (state/get-config)) icon (or icon "static/img/logo.png") project (or alias name)] @@ -84,7 +85,7 @@ } } }(window.location))"] - ;; TODO: should make this configurable + ;; TODO: should make this configurable [:script {:src "static/js/main.js"}] [:script {:src "static/js/highlight.min.js"}] [:script {:src "static/js/interact.min.js"}]