feat(editor/copy-paste): refactor copy/export in cljs (#8530)

Huge performance improvement for copy and export

Refactor copy/export in cljs instead of Mldoc
This commit is contained in:
rcmerci
2023-02-20 23:08:58 +08:00
committed by GitHub
parent c0f8dc4ee2
commit 2a12ffc331
14 changed files with 2341 additions and 297 deletions

View File

@@ -1,5 +1,8 @@
(ns frontend.components.export
(:require [frontend.context.i18n :refer [t]]
[frontend.handler.export.text :as export-text]
[frontend.handler.export.html :as export-html]
[frontend.handler.export.opml :as export-opml]
[frontend.handler.export :as export]
[frontend.mobile.util :as mobile-util]
[frontend.state :as state]
@@ -21,19 +24,20 @@
(t :export-json)]]
(when (util/electron?)
[:li.mb-4
[:a.font-medium {:on-click #(export/export-repo-as-html! current-repo)}
[:a.font-medium {:on-click #(export/download-repo-as-html! current-repo)}
(t :export-public-pages)]])
(when-not (mobile-util/native-platform?)
[:li.mb-4
[:a.font-medium {:on-click #(export/export-repo-as-markdown! current-repo)}
(t :export-markdown)]]
[:a.font-medium {:on-click #(export-text/export-repo-as-markdown! current-repo)}
(t :export-markdown)]])
(when-not (mobile-util/native-platform?)
[:li.mb-4
[:a.font-medium {:on-click #(export/export-repo-as-opml! current-repo)}
[:a.font-medium {:on-click #(export-opml/export-repo-as-opml! current-repo)}
(t :export-opml)]])
(when-not (mobile-util/native-platform?)
[:li.mb-4
[:a.font-medium {:on-click #(export/export-repo-as-roam-json! current-repo)}
(t :export-roam-json)]])]
[:li.mb-4
[:a.font-medium {:on-click #(export/export-repo-as-roam-json! current-repo)}
(t :export-roam-json)]])]
[:a#download-as-edn-v2.hidden]
[:a#download-as-json-v2.hidden]
[:a#download-as-roam-json.hidden]
@@ -53,49 +57,72 @@
{:label "no-indent"
:selected false}])
(rum/defcs export-blocks
< rum/reactive
(rum/local false ::copied?)
[state root-block-ids]
(defn- export-helper
[block-uuids-or-page-name]
(let [current-repo (state/get-current-repo)
type (rum/react *export-block-type)
text-indent-style (state/sub :copy/export-block-text-indent-style)
text-remove-options (state/sub :copy/export-block-text-remove-options)
copied? (::copied? state)
content
(case type
:text (export/export-blocks-as-markdown current-repo root-block-ids text-indent-style (into [] text-remove-options))
:opml (export/export-blocks-as-opml current-repo root-block-ids)
:html (export/export-blocks-as-html current-repo root-block-ids)
(export/export-blocks-as-markdown current-repo root-block-ids text-indent-style (into [] text-remove-options)))]
text-indent-style (state/get-export-block-text-indent-style)
text-remove-options (set (state/get-export-block-text-remove-options))
tp @*export-block-type]
(case tp
:text (export-text/export-blocks-as-markdown
current-repo block-uuids-or-page-name
{:indent-style text-indent-style :remove-options text-remove-options})
:opml (export-opml/export-blocks-as-opml
current-repo block-uuids-or-page-name {:remove-options text-remove-options})
:html (export-html/export-blocks-as-html
current-repo block-uuids-or-page-name {:remove-options text-remove-options})
"")))
(rum/defcs export-blocks < rum/static
(rum/local false ::copied?)
(rum/local nil ::text-remove-options)
(rum/local nil ::text-indent-style)
(rum/local nil ::content)
{:will-mount (fn [state]
(let [content (export-helper (last (:rum/args state)))]
(reset! (::content state) content)
(reset! (::text-remove-options state) (set (state/get-export-block-text-remove-options)))
(reset! (::text-indent-style state) (state/get-export-block-text-indent-style))
state))}
[state root-block-uuids-or-page-name]
(let [tp @*export-block-type
*text-remove-options (::text-remove-options state)
*text-indent-style (::text-indent-style state)
*copied? (::copied? state)
*content (::content state)]
[:div.export.resize
[:div.flex
{:class "mb-2"}
(ui/button "Text"
:class "mr-4 w-20"
:on-click #(reset! *export-block-type :text))
:on-click #(do (reset! *export-block-type :text)
(reset! *content (export-helper root-block-uuids-or-page-name))))
(ui/button "OPML"
:class "mr-4 w-20"
:on-click #(reset! *export-block-type :opml))
:on-click #(do (reset! *export-block-type :opml)
(reset! *content (export-helper root-block-uuids-or-page-name))))
(ui/button "HTML"
:class "w-20"
:on-click #(reset! *export-block-type :html))]
[:textarea.overflow-y-auto.h-96 {:value content}]
:on-click #(do (reset! *export-block-type :html)
(reset! *content (export-helper root-block-uuids-or-page-name))))]
[:textarea.overflow-y-auto.h-96 {:value @*content :read-only true}]
(let [options (->> text-indent-style-options
(mapv (fn [opt]
(if (= text-indent-style (:label opt))
(if (= @*text-indent-style (:label opt))
(assoc opt :selected true)
opt))))]
[:div [:div.flex.items-center
[:label.mr-4
{:style {:visibility (if (= :text type) "visible" "hidden")}}
{:style {:visibility (if (= :text tp) "visible" "hidden")}}
"Indentation style:"]
[:select.block.my-2.text-lg.rounded.border
{:style {:padding "0 0 0 12px"
:visibility (if (= :text type) "visible" "hidden")}
:visibility (if (= :text tp) "visible" "hidden")}
:on-change (fn [e]
(let [value (util/evalue e)]
(state/set-export-block-text-indent-style! value)))}
(state/set-export-block-text-indent-style! value)
(reset! *text-indent-style value)
(reset! *content (export-helper root-block-uuids-or-page-name))))}
(for [{:keys [label value selected]} options]
[:option (cond->
{:key label
@@ -105,29 +132,41 @@
label])]]
[:div.flex.items-center
(ui/checkbox {:style {:margin-right 6
:visibility (if (= :text type) "visible" "hidden")}
:checked (contains? text-remove-options :page-ref)
:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}
:checked (contains? @*text-remove-options :page-ref)
:on-change (fn [e]
(state/update-export-block-text-remove-options! e :page-ref))})
[:div
{:style {:visibility (if (= :text type) "visible" "hidden")}}
(state/update-export-block-text-remove-options! e :page-ref)
(reset! *text-remove-options (state/get-export-block-text-remove-options))
(reset! *content (export-helper root-block-uuids-or-page-name)))})
[:div {:style {:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}}
"[[text]] -> text"]
(ui/checkbox {:style {:margin-right 6
:margin-left "1em"
:visibility (if (= :text type) "visible" "hidden")}
:checked (contains? text-remove-options :emphasis)
:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}
:checked (contains? @*text-remove-options :emphasis)
:on-change (fn [e]
(state/update-export-block-text-remove-options! e :emphasis))})
(state/update-export-block-text-remove-options! e :emphasis)
(reset! *text-remove-options (state/get-export-block-text-remove-options))
(reset! *content (export-helper root-block-uuids-or-page-name)))})
[:div
{:style {:visibility (if (= :text type) "visible" "hidden")}}
"remove emphasis"]]])
[:div {:style {:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}}
"remove emphasis"]
(ui/checkbox {:style {:margin-right 6
:margin-left "1em"
:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}
:checked (contains? @*text-remove-options :tag)
:on-change (fn [e]
(state/update-export-block-text-remove-options! e :tag)
(reset! *text-remove-options (state/get-export-block-text-remove-options))
(reset! *content (export-helper root-block-uuids-or-page-name)))})
[:div {:style {:visibility (if (#{:text :html :opml} tp) "visible" "hidden")}}
"remove #tags"]]])
[:div.mt-4
(ui/button (if @copied? "Copied to clipboard!" "Copy to clipboard")
:on-click (fn []
(util/copy-to-clipboard! content (when (= type :html)
content))
(reset! copied? true)))]]))
(ui/button (if @*copied? "Copied to clipboard!" "Copy to clipboard")
:on-click (fn []
(util/copy-to-clipboard! @*content (when (= tp :html) @*content))
(reset! *copied? true)))]]))