mirror of
https://github.com/logseq/logseq.git
synced 2026-02-01 22:47:36 +00:00
Working prototype yay!
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -16,6 +16,10 @@ node_modules/
|
||||
/resources/static/js/main.js
|
||||
/resources/static/js/cljs-runtime
|
||||
/resources/static/js/manifest.edn
|
||||
/resources/static/js/publishing/*.map
|
||||
/resources/static/js/publishing/main.js
|
||||
/resources/static/js/publishing/cljs-runtime
|
||||
/resources/static/js/publishing/manifest.edn
|
||||
/resources/static/style.css
|
||||
tauri-release/
|
||||
|
||||
@@ -37,4 +41,4 @@ strings.csv
|
||||
resources/static/style.css
|
||||
|
||||
.calva
|
||||
web/.calva
|
||||
web/.calva
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
"tailwindcss": "^1.3.4"
|
||||
},
|
||||
"scripts": {
|
||||
"watch": "clojure -A:cljs watch app",
|
||||
"release": "clojure -A:cljs release app",
|
||||
"watch": "clojure -A:cljs watch app publishing",
|
||||
"release": "clojure -A:cljs release app publishing",
|
||||
"debug": "clojure -A:cljs release app --debug",
|
||||
"report": "clojure -A:cljs run shadow.cljs.build-report app report.html",
|
||||
"clean": "/usr/bin/rm -rf target; /usr/bin/rm -rf ../resources/static/js/compiled; /usr/bin/rm -rf ../resources/static/js/cljs-runtime;"
|
||||
|
||||
@@ -21,6 +21,23 @@
|
||||
;; :public-dir "resources/static/css"})]
|
||||
:devtools
|
||||
;; before live-reloading any code call this function
|
||||
{:before-load frontend.core/stop
|
||||
;; after live-reloading finishes call this function
|
||||
:after-load frontend.core/start
|
||||
:preloads [devtools.preload]}}
|
||||
:publishing
|
||||
{:target :browser
|
||||
:modules {:main {:init-fn frontend.publishing/init}}
|
||||
|
||||
:output-dir "../resources/static/js/publishing"
|
||||
:asset-path "/static/js"
|
||||
|
||||
:compiler-options {:infer-externs :auto
|
||||
:output-feature-set :es6
|
||||
:externs ["datascript/externs.js"
|
||||
"externs.js"]}
|
||||
:devtools
|
||||
;; before live-reloading any code call this function
|
||||
{:before-load frontend.core/stop
|
||||
;; after live-reloading finishes call this function
|
||||
:after-load frontend.core/start
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.export :as export]
|
||||
[frontend.config :as config]
|
||||
[frontend.keyboards :as keyboards]
|
||||
[dommy.core :as d]
|
||||
@@ -93,6 +94,8 @@
|
||||
token (state/sub :encrypt/token)
|
||||
;; TODO: remove this
|
||||
daily-migrating? (state/sub [:daily/migrating?])]
|
||||
(prn {:repo (state/get-current-repo)
|
||||
:conns (db/get-conn)})
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div.max-w-7xl.mx-auto
|
||||
(cond
|
||||
@@ -331,7 +334,12 @@
|
||||
[:a svg/user]])])
|
||||
(let [logged? (:name me)]
|
||||
(->>
|
||||
[(when current-repo
|
||||
[(when (and logged? current-repo)
|
||||
{:title (t :publishing)
|
||||
:options {:on-click (fn []
|
||||
(export/export-repo-as-zip! current-repo))}
|
||||
:icon nil})
|
||||
(when current-repo
|
||||
{:title (t :graph)
|
||||
:options {:href (rfe/href :graph)}
|
||||
:icon svg/graph-sm})
|
||||
@@ -374,6 +382,8 @@
|
||||
(remove nil?)))
|
||||
{})
|
||||
|
||||
[:a#download-as-zip.hidden]
|
||||
|
||||
[:a.hover:text-gray-900.text-gray-500.ml-3.hidden.md:block
|
||||
{:on-click (fn []
|
||||
(state/toggle-sidebar-open?!))}
|
||||
|
||||
@@ -292,6 +292,7 @@ title: How to take dummy notes?
|
||||
:search "Search or Create Page"
|
||||
:new-page "New page"
|
||||
:graph "Graph"
|
||||
:publishing "publishing"
|
||||
:all-repos "All repos"
|
||||
:all-pages "All pages"
|
||||
:all-files "All files"
|
||||
@@ -531,6 +532,7 @@ title: How to take dummy notes?
|
||||
:search "搜索或者创建新页面"
|
||||
:new-page "新页面"
|
||||
:graph "图谱"
|
||||
:publishing "发布/下载 HTML 文件"
|
||||
:all-repos "所有库"
|
||||
:all-pages "所有页面"
|
||||
:all-files "所有文件"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
[frontend.util :as util]
|
||||
[cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[goog.dom :as gdom]))
|
||||
[goog.dom :as gdom]
|
||||
[frontend.publishing.html :as html]))
|
||||
|
||||
(defn copy-block!
|
||||
[block-id]
|
||||
@@ -50,3 +51,14 @@
|
||||
(.setAttribute anchor "href" url)
|
||||
(.setAttribute anchor "download" file-path)
|
||||
(.click anchor))))))
|
||||
|
||||
(defn export-repo-as-zip!
|
||||
[repo]
|
||||
(when-let [db (db/get-conn repo)]
|
||||
(let [db-str (db/db->string db)
|
||||
html-str (str "data:text/html;charset=UTF-8,"
|
||||
(js/encodeURIComponent (html/publishing-html db-str)))]
|
||||
(when-let [anchor (gdom/getElement "download-as-zip")]
|
||||
(.setAttribute anchor "href" html-str)
|
||||
(.setAttribute anchor "download" (str (last (string/split repo #"/")) ".html"))
|
||||
(.click anchor)))))
|
||||
|
||||
@@ -11,38 +11,41 @@
|
||||
|
||||
(defn render-local-images!
|
||||
[]
|
||||
(let [images (array-seq (gdom/getElementsByTagName "img"))
|
||||
get-src (fn [image] (.getAttribute image "src"))
|
||||
local-images (filter
|
||||
(fn [image]
|
||||
(let [src (get-src image)]
|
||||
(and src
|
||||
(not (or (util/starts-with? src "http://")
|
||||
(util/starts-with? src "https://"))))))
|
||||
images)]
|
||||
(doseq [img local-images]
|
||||
(gobj/set img
|
||||
"onerror"
|
||||
(fn []
|
||||
(gobj/set (gobj/get img "style")
|
||||
"display" "none")))
|
||||
(let [path (get-src img)
|
||||
path (string/replace-first path "file:" "")
|
||||
path (if (= (first path) \.)
|
||||
(subs path 1)
|
||||
path)]
|
||||
(util/p-handle
|
||||
(fs/read-file-2 (util/get-repo-dir (state/get-current-repo))
|
||||
path)
|
||||
(fn [blob]
|
||||
(let [blob (js/Blob. (array blob) (clj->js {:type "image"}))
|
||||
img-url (image/create-object-url blob)]
|
||||
(gobj/set img "src" img-url)
|
||||
(gobj/set (gobj/get img "style")
|
||||
"display" "initial")))
|
||||
(fn [error]
|
||||
(println "Can't read local image file: ")
|
||||
(js/console.dir error)))))))
|
||||
(try
|
||||
(let [images (array-seq (gdom/getElementsByTagName "img"))
|
||||
get-src (fn [image] (.getAttribute image "src"))
|
||||
local-images (filter
|
||||
(fn [image]
|
||||
(let [src (get-src image)]
|
||||
(and src
|
||||
(not (or (util/starts-with? src "http://")
|
||||
(util/starts-with? src "https://"))))))
|
||||
images)]
|
||||
(doseq [img local-images]
|
||||
(gobj/set img
|
||||
"onerror"
|
||||
(fn []
|
||||
(gobj/set (gobj/get img "style")
|
||||
"display" "none")))
|
||||
(let [path (get-src img)
|
||||
path (string/replace-first path "file:" "")
|
||||
path (if (= (first path) \.)
|
||||
(subs path 1)
|
||||
path)]
|
||||
(util/p-handle
|
||||
(fs/read-file-2 (util/get-repo-dir (state/get-current-repo))
|
||||
path)
|
||||
(fn [blob]
|
||||
(let [blob (js/Blob. (array blob) (clj->js {:type "image"}))
|
||||
img-url (image/create-object-url blob)]
|
||||
(gobj/set img "src" img-url)
|
||||
(gobj/set (gobj/get img "style")
|
||||
"display" "initial")))
|
||||
(fn [error]
|
||||
(println "Can't read local image file: ")
|
||||
(js/console.dir error))))))
|
||||
(catch js/Error e
|
||||
nil)))
|
||||
|
||||
(defn request-presigned-url
|
||||
[file filename mime-type uploading? url-handler on-processing]
|
||||
|
||||
@@ -15,13 +15,25 @@
|
||||
;; Both files and git libraries can be removed.
|
||||
;; Maybe we can remove some handlers and components too.
|
||||
|
||||
;; There should be two publishing modes:
|
||||
;; 1. Graph version, similar to logseq.com
|
||||
;; 2. Traditional blog version, much faster to load
|
||||
;; We might host the pages or blocks directly on logseq.com in the future.
|
||||
|
||||
;; How to publish?
|
||||
;; 1. When you click a publish button, it'll downloads a zip which includes the
|
||||
;; html, css, javascript and other files (image, mp3, etc.), the serialized
|
||||
;; data should include all the public pages and blocks.
|
||||
;; 2. Built-in sync with Github Pages, you should specify a Github repo for publishing.
|
||||
|
||||
(defn restore-from-transit-str!
|
||||
[]
|
||||
(state/set-current-repo! "local")
|
||||
(when-let [data js/window.logseq_db]
|
||||
(let [db-conn (d/create-conn db-schema/schema)
|
||||
_ (swap! db/conns assoc "local" db-conn)
|
||||
db (string->db logseq_db)]
|
||||
(let [data (js/JSON.stringify data)
|
||||
db-conn (d/create-conn db-schema/schema)
|
||||
_ (swap! db/conns assoc "logseq-db/local" db-conn)
|
||||
db (db/string->db data)]
|
||||
(reset! db-conn db))))
|
||||
|
||||
(defn set-router!
|
||||
@@ -42,7 +54,7 @@
|
||||
;; this is called in the index.html and must be exported
|
||||
;; so it is available even in :advanced release builds
|
||||
|
||||
(db/restore-from-transit-str!)
|
||||
(restore-from-transit-str!)
|
||||
(start))
|
||||
|
||||
(defn stop []
|
||||
|
||||
70
web/src/main/frontend/publishing/html.cljs
Normal file
70
web/src/main/frontend/publishing/html.cljs
Normal file
@@ -0,0 +1,70 @@
|
||||
(ns frontend.publishing.html
|
||||
(:require-macros [hiccups.core :as hiccups :refer [html]])
|
||||
(:require [frontend.config :as config]))
|
||||
|
||||
(defn publishing-html
|
||||
[transit-db]
|
||||
(let [icon (config/asset-uri "/static/img/logo.png")
|
||||
project "Logseq"
|
||||
project-twitter "logseq"
|
||||
title "A local-first knowledge base."
|
||||
description "A local-first knowledge base which can be synced using Git."]
|
||||
(html
|
||||
[: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 (config/asset-uri "/static/style.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 "summary", :name "twitter:card"}]
|
||||
[:meta
|
||||
{:content description
|
||||
:name "twitter:description"}]
|
||||
(if project-twitter
|
||||
[:meta {:content (str "@" project-twitter), :name "twitter:site"}])
|
||||
[:meta {:content title, :name "twitter:title"}]
|
||||
[:meta
|
||||
{:content icon,
|
||||
:name "twitter:image:src"}]
|
||||
[:meta
|
||||
{:content description, :name "twitter:image:alt"}]
|
||||
[:meta {:content title, :property "og:title"}]
|
||||
[:meta {:content "site", :property "og:type"}]
|
||||
;; FIXME: get current url
|
||||
[:meta {:content "https://logseq.com", :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#root]
|
||||
[:script (str "window.logseq_db=" transit-db)]
|
||||
[:script {:src (config/asset-uri "/static/js/mldoc.min.js")}]
|
||||
[:script {:src (config/asset-uri "/static/js/publishing.js")}]
|
||||
;; TODO: should make this configurable
|
||||
[:script {:src (config/asset-uri "/static/js/highlight.min.js")}]])))
|
||||
@@ -31,8 +31,8 @@
|
||||
(let [{:keys [slide] :as directives} (db/get-page-directives page-name)
|
||||
slide? slide
|
||||
blocks (if (:block/pre-block? (first blocks))
|
||||
(rest blocks)
|
||||
blocks)]
|
||||
(rest blocks)
|
||||
blocks)]
|
||||
(if (seq blocks)
|
||||
(let [config {:html-export? true :slide? slide?}
|
||||
hiccup (if slide?
|
||||
|
||||
Reference in New Issue
Block a user