瀏覽代碼

Working POC!

Gabriel Horner 2 年之前
父節點
當前提交
76c4e49f34

+ 4 - 0
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
 

+ 2 - 0
deps/publish-spa/.gitignore

@@ -0,0 +1,2 @@
+/.clj-kondo/.cache
+.nbb

+ 4 - 0
deps/publish-spa/nbb.edn

@@ -0,0 +1,4 @@
+{:deps
+ {logseq/graph-parser
+  ;; Nbb bug. Should just be "../graph-parser"
+  {:local/root "../../../../graph-parser"}}}

+ 21 - 10
scripts/src/logseq/tasks/dev/publish.cljs → 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*)

+ 122 - 0
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____&amp;")
+      (string/replace "<"  "logseq____&lt;")
+      (string/replace ">"  "logseq____&gt;")
+      (string/replace "\"" "logseq____&quot;")
+      (string/replace "'" "logseq____&apos;")))
+
+;; 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</%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 "<!DOCTYPE html>\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"}]])))))

+ 1 - 0
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))]

+ 2 - 1
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"}]