mirror of https://github.com/logseq/logseq
Working POC!
parent
a748b4f6b3
commit
76c4e49f34
4
bb.edn
4
bb.edn
|
@ -34,6 +34,10 @@
|
||||||
dev:build-publishing
|
dev:build-publishing
|
||||||
logseq.tasks.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
|
dev:npx-cap-run-ios
|
||||||
logseq.tasks.dev.mobile/npx-cap-run-ios
|
logseq.tasks.dev.mobile/npx-cap-run-ios
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
/.clj-kondo/.cache
|
||||||
|
.nbb
|
|
@ -0,0 +1,4 @@
|
||||||
|
{:deps
|
||||||
|
{logseq/graph-parser
|
||||||
|
;; Nbb bug. Should just be "../graph-parser"
|
||||||
|
{:local/root "../../../../graph-parser"}}}
|
|
@ -1,16 +1,19 @@
|
||||||
(ns logseq.tasks.dev.publish
|
(ns logseq.publish-spa
|
||||||
(:require [promesa.core :as p]
|
(:require [promesa.core :as p]
|
||||||
["path" :as path]
|
["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
|
(defn- handle-export-publish-assets
|
||||||
[html custom-css-path export-css-path repo-path asset-filenames output-path]
|
[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
|
root-dir output-path
|
||||||
static-dir (path/join root-dir "static")
|
static-dir (path/join root-dir "static")
|
||||||
assets-from-dir (path/join repo-path "assets")
|
assets-from-dir (path/join repo-path "assets")
|
||||||
assets-to-dir (path/join root-dir "assets")
|
assets-to-dir (path/join root-dir "assets")
|
||||||
index-html-path (path/join root-dir "index.html")]
|
index-html-path (path/join root-dir "index.html")]
|
||||||
(p/let [_ (. fs ensureDir static-dir)
|
(p/let [_ (. fs ensureDir static-dir)
|
||||||
_ (. fs ensureDir assets-to-dir)
|
_ (. fs ensureDir assets-to-dir)
|
||||||
_ (p/all (concat
|
_ (p/all (concat
|
||||||
|
@ -61,17 +64,25 @@
|
||||||
{:type "success"
|
{:type "success"
|
||||||
:payload (str "Export public pages and publish assets to " root-dir " successfully 🎉")}))))
|
: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
|
(defn -main
|
||||||
[args]
|
[& args]
|
||||||
(let [repo-path (or (first args)
|
(let [repo-path (or (first args)
|
||||||
(throw (ex-info "GRAPH DIR required" {})))
|
(throw (ex-info "GRAPH DIR required" {})))
|
||||||
output-path (or (second args)
|
output-path (or (second args)
|
||||||
(throw (ex-info "OUT DIR required" {})))
|
(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")
|
custom-css-path (path/join repo-path "logseq" "custom.css")
|
||||||
export-css-path (path/join repo-path "logseq" "export.css")
|
export-css-path (path/join repo-path "logseq" "export.css")
|
||||||
;; TODO: Read from repo-path
|
;; TODO: Read from repo-path
|
||||||
asset-filenames []]
|
asset-filenames []]
|
||||||
(handle-export-publish-assets html custom-css-path export-css-path repo-path asset-filenames output-path)))
|
(handle-export-publish-assets html custom-css-path export-css-path repo-path asset-filenames output-path)))
|
||||||
|
|
||||||
(-main *command-line-args*)
|
|
|
@ -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</%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"}]])))))
|
|
@ -89,6 +89,7 @@
|
||||||
:config])
|
:config])
|
||||||
state (update state :config (fn [config]
|
state (update state :config (fn [config]
|
||||||
{"local" (get config repo)}))
|
{"local" (get config repo)}))
|
||||||
|
_ (prn :STATE state)
|
||||||
raw-html-str (html/publishing-html db-str (pr-str state))
|
raw-html-str (html/publishing-html db-str (pr-str state))
|
||||||
html-str (str "data:text/html;charset=UTF-8,"
|
html-str (str "data:text/html;charset=UTF-8,"
|
||||||
(js/encodeURIComponent raw-html-str))]
|
(js/encodeURIComponent raw-html-str))]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(defn publishing-html
|
(defn publishing-html
|
||||||
[transit-db app-state]
|
[transit-db app-state]
|
||||||
|
(prn :PROJECT (:project (state/get-config)))
|
||||||
(let [{:keys [icon name alias title description url]} (:project (state/get-config))
|
(let [{:keys [icon name alias title description url]} (:project (state/get-config))
|
||||||
icon (or icon "static/img/logo.png")
|
icon (or icon "static/img/logo.png")
|
||||||
project (or alias name)]
|
project (or alias name)]
|
||||||
|
@ -84,7 +85,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(window.location))"]
|
}(window.location))"]
|
||||||
;; TODO: should make this configurable
|
;; TODO: should make this configurable
|
||||||
[:script {:src "static/js/main.js"}]
|
[:script {:src "static/js/main.js"}]
|
||||||
[:script {:src "static/js/highlight.min.js"}]
|
[:script {:src "static/js/highlight.min.js"}]
|
||||||
[:script {:src "static/js/interact.min.js"}]
|
[:script {:src "static/js/interact.min.js"}]
|
||||||
|
|
Loading…
Reference in New Issue