mirror of
https://github.com/penpot/penpot.git
synced 2025-05-27 20:46:12 +02:00
185 lines
5.3 KiB
Clojure
185 lines
5.3 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) UXBOX Labs SL
|
|
|
|
(ns app.util.text-editor
|
|
"Draft related abstraction functions."
|
|
(:require
|
|
["./text_editor_impl.js" :as impl]
|
|
["draft-js" :as draft]
|
|
[app.common.text :as txt]))
|
|
|
|
;; --- CONVERSION
|
|
|
|
(defn immutable-map->map
|
|
[obj]
|
|
(let [data (into {} (map (fn [[k v]] [(keyword k) v])) (seq obj))]
|
|
(assoc data :fills (js->clj (:fills data) :keywordize-keys true))))
|
|
|
|
;; --- DRAFT-JS HELPERS
|
|
|
|
(defn create-editor-state
|
|
([]
|
|
(impl/createEditorState nil nil))
|
|
([content]
|
|
(impl/createEditorState content nil))
|
|
([content decorator]
|
|
(impl/createEditorState content decorator)))
|
|
|
|
(defn create-decorator
|
|
[type component]
|
|
(impl/createDecorator type component))
|
|
|
|
(defn import-content
|
|
[content]
|
|
(-> content txt/convert-to-draft clj->js draft/convertFromRaw))
|
|
|
|
(defn export-content
|
|
[content]
|
|
(-> content
|
|
(draft/convertToRaw)
|
|
(js->clj :keywordize-keys true)
|
|
(txt/convert-from-draft)))
|
|
|
|
(defn get-editor-current-content
|
|
[state]
|
|
(.getCurrentContent ^js state))
|
|
|
|
(defn ^boolean content-has-text?
|
|
[content]
|
|
(.hasText ^js content))
|
|
|
|
(defn editor-select-all
|
|
[state]
|
|
(impl/selectAll state))
|
|
|
|
(defn get-editor-block-data
|
|
[block]
|
|
(-> (.getData ^js block)
|
|
(immutable-map->map)))
|
|
|
|
(defn get-editor-block-type
|
|
[block]
|
|
(.getType ^js block))
|
|
|
|
(defn get-editor-current-block-data
|
|
[state]
|
|
(let [block (impl/getCurrentBlock state)]
|
|
(get-editor-block-data block)))
|
|
|
|
(defn get-editor-current-inline-styles
|
|
[state]
|
|
(if (impl/isCurrentEmpty state)
|
|
(get-editor-current-block-data state)
|
|
(-> (.getCurrentInlineStyle ^js state)
|
|
(txt/styles-to-attrs)
|
|
(dissoc :text-align :text-direction))))
|
|
|
|
(defn update-editor-current-block-data
|
|
[state attrs]
|
|
(impl/updateCurrentBlockData state (clj->js attrs)))
|
|
|
|
(defn update-editor-current-inline-styles
|
|
[state attrs]
|
|
(let [update-blocks
|
|
(fn [state block-key]
|
|
(if (empty? (impl/getBlockContent state block-key))
|
|
(impl/updateBlockData state block-key (clj->js attrs))
|
|
|
|
(let [attrs (-> (impl/getInlineStyle state block-key 0)
|
|
(txt/styles-to-attrs)
|
|
(dissoc :text-align :text-direction))]
|
|
(impl/updateBlockData state block-key (clj->js attrs)))))
|
|
|
|
state (impl/applyInlineStyle state (txt/attrs-to-styles attrs))
|
|
selected (impl/getSelectedBlocks state)]
|
|
(reduce update-blocks state selected)))
|
|
|
|
(defn update-editor-current-inline-styles-fn
|
|
[state update-fn]
|
|
(let [attrs (-> (.getCurrentInlineStyle ^js state)
|
|
(txt/styles-to-attrs)
|
|
(update-fn))]
|
|
(impl/applyInlineStyle state (txt/attrs-to-styles attrs))))
|
|
|
|
(defn editor-split-block
|
|
[state]
|
|
(impl/splitBlockPreservingData state))
|
|
|
|
(defn add-editor-blur-selection
|
|
[state]
|
|
(impl/addBlurSelectionEntity state))
|
|
|
|
(defn remove-editor-blur-selection
|
|
[state]
|
|
(impl/removeBlurSelectionEntity state))
|
|
|
|
(defn cursor-to-end
|
|
[state]
|
|
(impl/cursorToEnd state))
|
|
|
|
(defn setup-block-styles
|
|
[state blocks attrs]
|
|
(if (empty? blocks)
|
|
state
|
|
(->> blocks
|
|
(reduce
|
|
(fn [state block-key]
|
|
(impl/updateBlockData state block-key (clj->js attrs)))
|
|
state))))
|
|
|
|
(defn apply-block-styles-to-content
|
|
[state blocks]
|
|
(if (empty? blocks)
|
|
state
|
|
(let [selection (impl/getSelection state)
|
|
redfn
|
|
(fn [state bkey]
|
|
(let [attrs (-> (impl/getBlockData state bkey)
|
|
(js->clj :keywordize-keys true))]
|
|
(-> state
|
|
(impl/selectBlock bkey)
|
|
(impl/applyInlineStyle (txt/attrs-to-styles attrs)))))]
|
|
(as-> state $
|
|
(reduce redfn $ blocks)
|
|
(impl/setSelection $ selection)))))
|
|
|
|
(defn insert-text [state text attrs]
|
|
(let [style (txt/attrs-to-styles attrs)]
|
|
(impl/insertText state text (clj->js attrs) (clj->js style))))
|
|
|
|
(defn get-style-override [state]
|
|
(.getInlineStyleOverride state))
|
|
|
|
(defn set-style-override [state inline-style]
|
|
(impl/setInlineStyleOverride state inline-style))
|
|
|
|
(defn content-equals [state other]
|
|
(.equals (.getCurrentContent state) (.getCurrentContent other)))
|
|
|
|
(defn selection-equals [state other]
|
|
(impl/selectionEquals (.getSelection state) (.getSelection other)))
|
|
|
|
(defn get-content-changes
|
|
[old-state state]
|
|
(let [old-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js old-state)))
|
|
:keywordize-keys false)
|
|
new-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js state)))
|
|
:keywordize-keys false)]
|
|
(merge
|
|
(into {}
|
|
(comp (filter #(contains? new-blocks (first %)))
|
|
(map (fn [[bkey bstate]]
|
|
[bkey
|
|
{:old (get bstate "text")
|
|
:new (get-in new-blocks [bkey "text"])}])))
|
|
old-blocks)
|
|
(into {}
|
|
(comp (filter #(not (contains? old-blocks (first %))))
|
|
(map (fn [[bkey bstate]]
|
|
[bkey
|
|
{:old nil
|
|
:new (get bstate "text")}])))
|
|
new-blocks))))
|