mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 13:29:07 +00:00
improved options
This commit is contained in:
parent
e3367c8534
commit
abd290eba1
@ -49,6 +49,7 @@
|
||||
[:map {:title "ProfileProps"}
|
||||
[:plugins {:optional true} schema:plugin-registry]
|
||||
[:renderer {:optional true} [::sm/one-of #{:svg :wasm}]]
|
||||
[:japanese-layout-all-files {:optional true} ::sm/boolean]
|
||||
[:mcp-enabled {:optional true} ::sm/boolean]
|
||||
[:newsletter-updates {:optional true} ::sm/boolean]
|
||||
[:newsletter-news {:optional true} ::sm/boolean]
|
||||
|
||||
@ -150,6 +150,21 @@
|
||||
(t/is (nil? (:error out)))
|
||||
(t/is (nil? (:photo-id (:result out))))))))
|
||||
|
||||
(t/deftest update-profile-japanese-layout-setting
|
||||
(let [profile (th/create-profile* 1)
|
||||
params {::th/type :update-profile-props
|
||||
::rpc/profile-id (:id profile)
|
||||
:props {:japanese-layout-all-files true}}
|
||||
out (th/command! params)]
|
||||
(t/is (nil? (:error out)))
|
||||
(t/is (true? (get-in out [:result :japanese-layout-all-files])))
|
||||
|
||||
(let [params {::th/type :get-profile
|
||||
::rpc/profile-id (:id profile)}
|
||||
out (th/command! params)]
|
||||
(t/is (nil? (:error out)))
|
||||
(t/is (true? (get-in out [:result :props :japanese-layout-all-files]))))))
|
||||
|
||||
(t/deftest profile-deletion-1
|
||||
(let [prof (th/create-profile* 1)
|
||||
file (th/create-file* 1 {:profile-id (:id prof)
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"text-editor/v2-html-paste"
|
||||
"text-editor/v2"
|
||||
"text-editor-wasm/v1"
|
||||
"japanese-layout/v1"
|
||||
"render-wasm/v1"
|
||||
"variants/v1"})
|
||||
|
||||
@ -82,7 +81,6 @@
|
||||
"text-editor/v2-html-paste"
|
||||
"text-editor/v2"
|
||||
"text-editor-wasm/v1"
|
||||
"japanese-layout/v1"
|
||||
"tokens/numeric-input"
|
||||
"render-wasm/v1"})
|
||||
|
||||
@ -133,7 +131,6 @@
|
||||
:feature-text-editor-v2 "text-editor/v2"
|
||||
:feature-text-editor-v2-html-paste "text-editor/v2-html-paste"
|
||||
:feature-text-editor-wasm "text-editor-wasm/v1"
|
||||
:feature-japanese-layout "japanese-layout/v1"
|
||||
:feature-render-wasm "render-wasm/v1"
|
||||
:feature-variants "variants/v1"
|
||||
:feature-token-input "tokens/numeric-input"
|
||||
|
||||
@ -427,7 +427,12 @@
|
||||
[:set-base-font-size
|
||||
[:map {:title "ModBaseFontSize"}
|
||||
[:type [:= :set-base-font-size]]
|
||||
[:base-font-size :string]]]])
|
||||
[:base-font-size :string]]]
|
||||
|
||||
[:set-japanese-layout
|
||||
[:map {:title "SetJapaneseLayout"}
|
||||
[:type [:= :set-japanese-layout]]
|
||||
[:enabled ::sm/boolean]]]])
|
||||
|
||||
(def schema:changes
|
||||
[:sequential {:gen/max 5 :gen/min 1} schema:change])
|
||||
@ -1065,6 +1070,10 @@
|
||||
[data {:keys [base-font-size]}]
|
||||
(ctf/set-base-font-size data base-font-size))
|
||||
|
||||
(defmethod process-change :set-japanese-layout
|
||||
[data {:keys [enabled]}]
|
||||
(ctf/set-japanese-layout-enabled data enabled))
|
||||
|
||||
|
||||
;; === Operations
|
||||
|
||||
|
||||
@ -1084,6 +1084,18 @@
|
||||
:base-font-size previous-font-size})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn set-japanese-layout
|
||||
[changes enabled?]
|
||||
(assert-file-data! changes)
|
||||
(let [file-data (::file-data (meta changes))
|
||||
previous-enabled (ctf/japanese-layout-enabled? file-data)]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :set-japanese-layout
|
||||
:enabled enabled?})
|
||||
(update :undo-changes conj {:type :set-japanese-layout
|
||||
:enabled previous-enabled})
|
||||
(apply-changes-local))))
|
||||
|
||||
;; Misc changes
|
||||
|
||||
(defn reorder-children
|
||||
|
||||
@ -75,7 +75,8 @@
|
||||
(def schema:options
|
||||
[:map {:title "FileOptions"}
|
||||
[:components-v2 {:optional true} ::sm/boolean]
|
||||
[:base-font-size {:optional true} :string]])
|
||||
[:base-font-size {:optional true} :string]
|
||||
[:japanese-layout {:optional true} ::sm/boolean]])
|
||||
|
||||
(def schema:data
|
||||
[:map {:title "FileData"}
|
||||
@ -1225,6 +1226,19 @@
|
||||
(assoc-in file-data [:options :base-font-size] base-font-size))
|
||||
|
||||
|
||||
;; Japanese text layout
|
||||
|
||||
(defn japanese-layout-enabled?
|
||||
[file-data]
|
||||
(true? (get-in file-data [:options :japanese-layout])))
|
||||
|
||||
(defn set-japanese-layout-enabled
|
||||
[file-data enabled?]
|
||||
(if enabled?
|
||||
(assoc-in file-data [:options :japanese-layout] true)
|
||||
(d/update-in-when file-data [:options] dissoc :japanese-layout)))
|
||||
|
||||
|
||||
;; Ref Chains
|
||||
(defn get-ref-chain-until-target-ref
|
||||
"Returns a vector with the shape ref chain until target-ref, including itself"
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
;; Ruby (furigana) annotation text and customization carried per span.
|
||||
(def text-ruby-attrs
|
||||
[:ruby
|
||||
:ruby-hidden
|
||||
:ruby-size
|
||||
:ruby-align
|
||||
:ruby-overhang
|
||||
|
||||
@ -24,6 +24,26 @@
|
||||
(binding [ffeat/*current* #{"components/v2"}]
|
||||
(ctf/make-file-data file-id page-id)))
|
||||
|
||||
(t/deftest set-japanese-layout-file-option
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
page-id (uuid/custom 1 1)
|
||||
data (make-file-data file-id page-id)
|
||||
enabled (ch/process-changes data [{:type :set-japanese-layout
|
||||
:enabled true}])
|
||||
disabled (ch/process-changes enabled [{:type :set-japanese-layout
|
||||
:enabled false}])
|
||||
changes (-> (pcb/empty-changes)
|
||||
(pcb/with-file-data data)
|
||||
(pcb/set-japanese-layout true))]
|
||||
(t/is (false? (ctf/japanese-layout-enabled? data)))
|
||||
(t/is (true? (ctf/japanese-layout-enabled? enabled)))
|
||||
(t/is (false? (ctf/japanese-layout-enabled? disabled)))
|
||||
(t/is (not (contains? (:options disabled) :japanese-layout)))
|
||||
(t/is (= [{:type :set-japanese-layout :enabled true}]
|
||||
(:redo-changes changes)))
|
||||
(t/is (= '({:type :set-japanese-layout :enabled false})
|
||||
(:undo-changes changes)))))
|
||||
|
||||
(t/deftest add-obj
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
page-id (uuid/custom 1 1)
|
||||
|
||||
@ -604,6 +604,17 @@
|
||||
(dm/export layout/toggle-layout-flag)
|
||||
(dm/export layout/remove-layout-flag)
|
||||
|
||||
(defn set-japanese-layout
|
||||
[enabled?]
|
||||
(ptk/reify ::set-japanese-layout
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-file-data file-data)
|
||||
(pcb/set-japanese-layout enabled?))]
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
;; --- Profile
|
||||
|
||||
(defn update-nudge
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
(declare v2-sync-wasm-text-layout)
|
||||
|
||||
(def ruby-presentation-attrs
|
||||
[:ruby-size :ruby-align :ruby-overhang :ruby-side])
|
||||
[:ruby-hidden :ruby-size :ruby-align :ruby-overhang :ruby-side])
|
||||
|
||||
;; -- Content helpers
|
||||
|
||||
@ -340,7 +340,6 @@
|
||||
|
||||
(count (:text node)))))
|
||||
|
||||
|
||||
(defn decorate-range-info
|
||||
"Adds information about ranges inside the metadata of the text nodes"
|
||||
[content]
|
||||
|
||||
@ -115,10 +115,37 @@
|
||||
:on-change handle-render-change}]]
|
||||
[:> text* {:typography t/body-medium :class (stl/css :feedback)} [:a {:href "#" :on-click go-settings-feedback :class (stl/css :link)} (tr "dashboard.webgl-switch.feedback") [:> icon* {:icon-id "arrow-up-right" :size "s"}]]]]))
|
||||
|
||||
(mf/defc japanese-layout-settings*
|
||||
[{:keys [enabled]}]
|
||||
(let [handle-change
|
||||
(mf/use-fn
|
||||
(fn [enabled?]
|
||||
(st/emit! (ev/event {::ev/name (if enabled?
|
||||
"enable-japanese-layout-all-files"
|
||||
"disable-japanese-layout-all-files")
|
||||
::ev/origin "settings"})
|
||||
(du/update-profile-props
|
||||
{:japanese-layout-all-files enabled?})
|
||||
(ntf/success (tr "notifications.profile-saved")))))]
|
||||
[:section {:class (stl/css :japanese-layout-container)}
|
||||
[:> heading* {:class (stl/css :title)
|
||||
:level 2
|
||||
:typography t/title-large}
|
||||
(tr "dashboard.japanese-layout.title")]
|
||||
[:> text* {:class (stl/css :description) :typography t/body-medium}
|
||||
(tr "dashboard.japanese-layout.description")]
|
||||
[:form {:class (stl/css :japanese-layout-form)}
|
||||
[:> switch* {:label (tr "dashboard.japanese-layout.enable-all-files")
|
||||
:default-checked enabled
|
||||
:on-change handle-change}]]]))
|
||||
|
||||
(mf/defc options-page*
|
||||
[]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
renderer (or (-> profile :props :renderer) :svg)]
|
||||
renderer (or (-> profile :props :renderer) :svg)
|
||||
japanese-layout-enabled (true? (-> profile
|
||||
:props
|
||||
:japanese-layout-all-files))]
|
||||
(mf/use-effect
|
||||
#(dom/set-html-title (tr "title.settings.options")))
|
||||
|
||||
@ -127,5 +154,6 @@
|
||||
[:div {:class (stl/css :form-container) :data-testid "settings-form"}
|
||||
[:h2 (tr "labels.settings")]
|
||||
[:> options-form*]]
|
||||
[:> japanese-layout-settings* {:enabled japanese-layout-enabled}]
|
||||
(when (contains? cf/flags :render-switch)
|
||||
[:> webgl-settings* {:renderer renderer}])]]))
|
||||
|
||||
@ -21,9 +21,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Copied from profile.scss .form-container, but without included nested
|
||||
rules, since we want custom styles for it */
|
||||
.webgl-container {
|
||||
/* Settings sections with standalone controls. */
|
||||
.webgl-container,
|
||||
.japanese-layout-container {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
gap: var(--sp-s);
|
||||
@ -34,6 +34,10 @@
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.japanese-layout-form {
|
||||
padding-block-start: var(--sp-xs);
|
||||
}
|
||||
|
||||
.webgl-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -22,7 +22,9 @@
|
||||
(sts/generate-text-styles shape parent)
|
||||
(sts/generate-text-styles shape node))
|
||||
ruby (:ruby node)
|
||||
ruby? (and (string? ruby) (not (str/blank? ruby)))]
|
||||
ruby? (and (not (true? (:ruby-hidden node)))
|
||||
(string? ruby)
|
||||
(not (str/blank? ruby)))]
|
||||
(if ruby?
|
||||
[:ruby.ruby-node {:style (sts/generate-ruby-container-styles node)}
|
||||
[:span.text-node {:style style} text]
|
||||
|
||||
@ -22,7 +22,9 @@
|
||||
(sts/generate-text-styles shape node))
|
||||
class (when is-code (:$id node))
|
||||
ruby (:ruby node)
|
||||
ruby? (and (string? ruby) (not (str/blank? ruby)))]
|
||||
ruby? (and (not (true? (:ruby-hidden node)))
|
||||
(string? ruby)
|
||||
(not (str/blank? ruby)))]
|
||||
(if ruby?
|
||||
[:ruby.ruby-node {:style (sts/generate-ruby-container-styles node)}
|
||||
[:span.text-node {:style style :class class} text]
|
||||
|
||||
@ -97,7 +97,8 @@
|
||||
font-features (:font-features data)
|
||||
annotation-clearance (:annotation-clearance data)
|
||||
annotation-layers (if (= "auto" annotation-clearance)
|
||||
(+ (if (and (string? (:ruby data))
|
||||
(+ (if (and (not (true? (:ruby-hidden data)))
|
||||
(string? (:ruby data))
|
||||
(seq (:ruby data))) 1 0)
|
||||
(if (and (string? text-emphasis)
|
||||
(not= "none" text-emphasis)) 1 0))
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.data.common :as dcm]
|
||||
@ -228,8 +229,13 @@
|
||||
(mf/defc preferences-menu*
|
||||
{::mf/private true
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [layout profile toggle-flag on-close toggle-theme toggle-render]}]
|
||||
(let [renderer (or (-> profile :props :renderer) :svg)
|
||||
[{:keys [japanese-layout-enabled layout profile toggle-flag on-close
|
||||
toggle-theme toggle-render toggle-japanese-layout]}]
|
||||
(let [renderer (or (-> profile :props :renderer) :svg)
|
||||
japanese-layout-all-files? (true? (-> profile
|
||||
:props
|
||||
:japanese-layout-all-files))
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
show-nudge-options
|
||||
(mf/use-fn
|
||||
@ -312,6 +318,19 @@
|
||||
:id "file-menu-nudge"}
|
||||
[:span {:class (stl/css :item-name)} (tr "modals.nudge-title")]]
|
||||
|
||||
(when-not (or read-only? japanese-layout-all-files?)
|
||||
[:> dropdown-menu-item* {:on-click toggle-japanese-layout
|
||||
:class (stl/css :base-menu-item :submenu-item)
|
||||
:on-key-down (fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(toggle-japanese-layout event)))
|
||||
:data-testid "japanese-layout"
|
||||
:id "file-menu-japanese-layout"}
|
||||
[:span {:class (stl/css :item-name)}
|
||||
(if japanese-layout-enabled
|
||||
(tr "workspace.header.menu.disable-japanese-layout")
|
||||
(tr "workspace.header.menu.enable-japanese-layout"))]])
|
||||
|
||||
[:> dropdown-menu-item* {:on-click toggle-theme
|
||||
:class (stl/css :base-menu-item :submenu-item)
|
||||
:on-key-down (fn [event]
|
||||
@ -881,6 +900,9 @@
|
||||
(mf/defc menu*
|
||||
[{:keys [layout file]}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
file-data (mf/deref refs/workspace-data)
|
||||
japanese-layout-enabled
|
||||
(ctf/japanese-layout-enabled? file-data)
|
||||
|
||||
show-menu* (mf/use-state false)
|
||||
show-menu? (deref show-menu*)
|
||||
@ -949,6 +971,15 @@
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (du/toggle-theme))))
|
||||
|
||||
toggle-japanese-layout
|
||||
(mf/use-fn
|
||||
(mf/deps japanese-layout-enabled)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/set-japanese-layout (not japanese-layout-enabled)))
|
||||
(reset! show-menu* false)
|
||||
(reset! selected-sub-menu* nil)))
|
||||
|
||||
toggle-render
|
||||
(mf/use-fn
|
||||
(mf/deps profile)
|
||||
@ -1145,9 +1176,11 @@
|
||||
:preferences
|
||||
[:> preferences-menu* {:layout layout
|
||||
:profile profile
|
||||
:japanese-layout-enabled japanese-layout-enabled
|
||||
:toggle-flag toggle-flag
|
||||
:toggle-theme toggle-theme
|
||||
:toggle-render toggle-render
|
||||
:toggle-japanese-layout toggle-japanese-layout
|
||||
:on-close close-sub-menu}]
|
||||
|
||||
:plugins
|
||||
|
||||
@ -314,6 +314,8 @@
|
||||
(get n-values :text-emphasis))
|
||||
(identical? (get o-values :ruby)
|
||||
(get n-values :ruby))
|
||||
(identical? (get o-values :ruby-hidden)
|
||||
(get n-values :ruby-hidden))
|
||||
(identical? (get o-values :ruby-size)
|
||||
(get n-values :ruby-size))
|
||||
(identical? (get o-values :ruby-align)
|
||||
@ -342,10 +344,17 @@
|
||||
|
||||
(let [;; --- UI state
|
||||
menu-state* (mf/use-state {:main-menu true
|
||||
:more-options false})
|
||||
:more-options false
|
||||
:japanese-layout true})
|
||||
menu-state (deref menu-state*)
|
||||
main-menu-open? (:main-menu menu-state)
|
||||
more-options-open? (:more-options menu-state)
|
||||
japanese-layout-open? (:japanese-layout menu-state)
|
||||
|
||||
profile (mf/deref refs/profile)
|
||||
file-data (mf/deref refs/workspace-data)
|
||||
japanese-layout-config-enabled?
|
||||
(tjl/japanese-layout-config-enabled? file-data profile)
|
||||
|
||||
token-dropdown-open* (mf/use-state false)
|
||||
token-dropdown-open? (deref token-dropdown-open*)
|
||||
@ -431,6 +440,10 @@
|
||||
(mf/use-fn
|
||||
#(swap! menu-state* update :more-options not))
|
||||
|
||||
toggle-japanese-layout
|
||||
(mf/use-fn
|
||||
#(swap! menu-state* update :japanese-layout not))
|
||||
|
||||
toggle-token-dropdown
|
||||
(mf/use-fn
|
||||
#(swap! token-dropdown-open* not))
|
||||
@ -555,94 +568,104 @@
|
||||
(when token-dropdown-open?
|
||||
(ts/schedule 0 #(some-> (mf/ref-val dropdown-ref) dom/focus!))))
|
||||
|
||||
[:section {:class (stl/css :element-set)
|
||||
:aria-label (tr "workspace.options.text-options.text-section")}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:> title-bar* {:collapsable true
|
||||
:collapsed (not main-menu-open?)
|
||||
:on-collapsed toggle-main-menu
|
||||
:title label
|
||||
:class (stl/css :title-spacing-text)}
|
||||
[:*
|
||||
(when (and token-typography-row-enabled? (some? (resolve-delay typography-tokens)) (not typography))
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
|
||||
:on-click toggle-token-dropdown
|
||||
:tooltip-placement "top-left"
|
||||
:icon i/tokens}])
|
||||
(when (and (not typography) (not multiple?) (not applied-token-name))
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.options.convert-to-typography")
|
||||
:on-click on-convert-to-typography
|
||||
:tooltip-placement "top-left"
|
||||
:icon i/add}])]]
|
||||
(when (and token-typography-row-enabled? token-dropdown-open?)
|
||||
[:> searchable-options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options (resolve-delay dropdown-options)
|
||||
:selected selected-token-id
|
||||
:align "right"
|
||||
:placeholder (tr "workspace.tokens.search-by-token")
|
||||
:ref set-option-ref}])]
|
||||
|
||||
(when main-menu-open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
(cond
|
||||
(and token-typography-row-enabled? (= :multiple current-token-name) (= typography-id :multiple))
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-tokens-and-assets")]]
|
||||
|
||||
(and token-typography-row-enabled? (= :multiple current-token-name))
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-tokens")]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.libraries.text.multiple-token-tooltip")
|
||||
[:*
|
||||
[:section {:class (stl/css :element-set)
|
||||
:aria-label (tr "workspace.options.text-options.text-section")}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:> title-bar* {:collapsable true
|
||||
:collapsed (not main-menu-open?)
|
||||
:on-collapsed toggle-main-menu
|
||||
:title label
|
||||
:class (stl/css :title-spacing-text)}
|
||||
[:*
|
||||
(when (and token-typography-row-enabled? (some? (resolve-delay typography-tokens)) (not typography))
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
|
||||
:on-click toggle-token-dropdown
|
||||
:tooltip-placement "top-left"
|
||||
:on-click handle-detach-all-tokens
|
||||
:icon i/detach}]]
|
||||
|
||||
(and token-typography-row-enabled? current-token-name)
|
||||
[:> token-typography-row* {:token-name current-token-name
|
||||
:detach-token detach-token
|
||||
:active-tokens (resolve-delay typography-tokens)}]
|
||||
|
||||
(= typography-id :multiple)
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-typography")]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.libraries.text.multiple-assets-tooltip")
|
||||
:on-click handle-detach-typography
|
||||
:icon i/tokens}])
|
||||
(when (and (not typography) (not multiple?) (not applied-token-name))
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.options.convert-to-typography")
|
||||
:on-click on-convert-to-typography
|
||||
:tooltip-placement "top-left"
|
||||
:icon i/detach}]]
|
||||
:icon i/add}])]]
|
||||
(when (and token-typography-row-enabled? token-dropdown-open?)
|
||||
[:> searchable-options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options (resolve-delay dropdown-options)
|
||||
:selected selected-token-id
|
||||
:align "right"
|
||||
:placeholder (tr "workspace.tokens.search-by-token")
|
||||
:ref set-option-ref}])]
|
||||
|
||||
typography
|
||||
[:> typography-entry* {:file-id typography-file-id
|
||||
:typography typography
|
||||
:is-local (= typography-file-id file-id)
|
||||
:on-detach handle-detach-typography
|
||||
:on-change handle-change-typography}]
|
||||
(when main-menu-open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
(cond
|
||||
(and token-typography-row-enabled? (= :multiple current-token-name) (= typography-id :multiple))
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-tokens-and-assets")]]
|
||||
|
||||
(and token-typography-row-enabled? (= :multiple current-token-name))
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-tokens")]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.libraries.text.multiple-token-tooltip")
|
||||
:tooltip-placement "top-left"
|
||||
:on-click handle-detach-all-tokens
|
||||
:icon i/detach}]]
|
||||
|
||||
(and token-typography-row-enabled? current-token-name)
|
||||
[:> token-typography-row* {:token-name current-token-name
|
||||
:detach-token detach-token
|
||||
:active-tokens (resolve-delay typography-tokens)}]
|
||||
|
||||
:else
|
||||
[:> text-options* common-props])
|
||||
(= typography-id :multiple)
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)}
|
||||
(tr "workspace.libraries.text.mixed-typography")]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.libraries.text.multiple-assets-tooltip")
|
||||
:on-click handle-detach-typography
|
||||
:tooltip-placement "top-left"
|
||||
:icon i/detach}]]
|
||||
|
||||
[:div {:class (stl/css :text-align-options)}
|
||||
[:> text-align-options* common-props]
|
||||
[:> grow-options* common-props]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "labels.options")
|
||||
:data-testid "text-align-options-button"
|
||||
:on-click toggle-more-options
|
||||
:icon i/menu}]]
|
||||
typography
|
||||
[:> typography-entry* {:file-id typography-file-id
|
||||
:typography typography
|
||||
:is-local (= typography-file-id file-id)
|
||||
:on-detach handle-detach-typography
|
||||
:on-change handle-change-typography}]
|
||||
|
||||
(when more-options-open?
|
||||
[:*
|
||||
:else
|
||||
[:> text-options* common-props])
|
||||
|
||||
[:div {:class (stl/css :text-align-options)}
|
||||
[:> text-align-options* common-props]
|
||||
[:> grow-options* common-props]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "labels.options")
|
||||
:data-testid "text-align-options-button"
|
||||
:on-click toggle-more-options
|
||||
:icon i/menu}]]
|
||||
|
||||
(when more-options-open?
|
||||
[:div {:class (stl/css :text-decoration-options)}
|
||||
[:> vertical-align* common-props]
|
||||
[:> text-decoration-options* (mf/spread-props common-props {:token-applied current-token-name})]
|
||||
[:> text-direction-options* common-props]]
|
||||
[:> text-direction-options* common-props]])])]
|
||||
|
||||
(when japanese-layout-config-enabled?
|
||||
[:section {:class (stl/css :element-set)
|
||||
:aria-label (tr "workspace.options.text-options.japanese-layout")}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:> title-bar* {:collapsable true
|
||||
:collapsed (not japanese-layout-open?)
|
||||
:on-collapsed toggle-japanese-layout
|
||||
:title (tr "workspace.options.text-options.japanese-layout")
|
||||
:class (stl/css :title-spacing-text)}]]
|
||||
(when japanese-layout-open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
[:> tjl/japanese-layout-options* japanese-layout-props]])])]))
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.features :as features]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.controls.input :refer [input*]]
|
||||
@ -71,6 +71,13 @@
|
||||
(#{"horizontal-tb" "vertical-rl"} writing-mode) true
|
||||
:else false)))
|
||||
|
||||
(defn japanese-layout-config-enabled?
|
||||
"Japanese layout controls are available when enabled for the current file or
|
||||
globally in the user's profile."
|
||||
[file-data profile]
|
||||
(or (ctf/japanese-layout-enabled? file-data)
|
||||
(true? (get-in profile [:props :japanese-layout-all-files]))))
|
||||
|
||||
(defn japanese-layout-toggle-attrs
|
||||
"Attrs emitted by the Japanese layout switch. A nil writing mode removes the
|
||||
persisted paragraph attribute, restoring the normal horizontal default."
|
||||
@ -136,7 +143,7 @@
|
||||
|
||||
[:div {:class (stl/css :japanese-layout-toggle)}
|
||||
[:> switch* {:default-checked enabled
|
||||
:label (tr "workspace.options.text-options.japanese-layout")
|
||||
:label (tr "workspace.options.text-options.japanese-layout-enable-for-text")
|
||||
:on-change handle-change}]]))
|
||||
|
||||
(mf/defc writing-mode-options*
|
||||
@ -330,6 +337,26 @@
|
||||
:on-change on-change
|
||||
:on-blur on-blur}))
|
||||
|
||||
(mf/defc ruby-hidden-option*
|
||||
[{:keys [values on-change on-blur]}]
|
||||
(let [value (:ruby-hidden values)
|
||||
enabled? (cond
|
||||
(mixed-span-value? value) nil
|
||||
(true? value) true
|
||||
:else false)
|
||||
label (tr "workspace.options.text-options.ruby-hidden")
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-change on-blur)
|
||||
(fn [checked?]
|
||||
(on-change {:ruby-hidden checked?})
|
||||
(when (some? on-blur) (on-blur))))]
|
||||
[:div {:class (stl/css :ruby-hidden-option :japanese-select-option)}
|
||||
[:span {:class (stl/css :japanese-option-label)} label]
|
||||
[:> switch* {:default-checked enabled?
|
||||
:aria-label label
|
||||
:on-change handle-change}]]))
|
||||
|
||||
(mf/defc ruby-customization-options*
|
||||
[{:keys [values on-change on-blur]}]
|
||||
(let [common-props (ruby-common-props values on-change on-blur)
|
||||
@ -345,6 +372,7 @@
|
||||
side-options [{:id "over" :label (tr "workspace.options.text-options.ruby-side-over")}
|
||||
{:id "under" :label (tr "workspace.options.text-options.ruby-side-under")}]]
|
||||
[:div {:class (stl/css :japanese-layout-controls)}
|
||||
[:> ruby-hidden-option* common-props]
|
||||
[:> ruby-select-option* (mf/spread-props common-props
|
||||
{:attr :ruby-size
|
||||
:default-value "half"
|
||||
@ -530,13 +558,10 @@
|
||||
:options options
|
||||
:on-change handle-change}]]))
|
||||
|
||||
|
||||
|
||||
(mf/defc japanese-layout-options*
|
||||
[{:keys [ids values ruby-values text-selection-active
|
||||
on-change on-ruby-presentation-change on-blur]}]
|
||||
(let [enabled? (features/use-feature "japanese-layout/v1")
|
||||
selection-key (hash ids)
|
||||
(let [selection-key (hash ids)
|
||||
previous-selection-key-ref (mf/use-ref selection-key)
|
||||
active* (mf/use-state #(japanese-layout-enabled? values))
|
||||
active? (deref active*)
|
||||
@ -564,28 +589,26 @@
|
||||
selection-changed?))
|
||||
(mf/set-ref-val! previous-selection-key-ref selection-key)))
|
||||
|
||||
(when ^boolean enabled?
|
||||
[:div {:class (stl/css :japanese-layout-options)}
|
||||
[:> japanese-layout-toggle* toggle-props]
|
||||
(when ^boolean active?
|
||||
[:div {:class (stl/css :japanese-layout-controls)}
|
||||
[:div {:class (stl/css :japanese-icon-options)}
|
||||
[:> writing-mode-options* common-props]
|
||||
(when ^boolean vertical?
|
||||
[:*
|
||||
[:> text-orientation-options* common-props]
|
||||
[:> text-combine-upright-options*
|
||||
(mf/spread-props common-props
|
||||
{:text-selection-active text-selection-active})]])
|
||||
(when ^boolean text-selection-active
|
||||
[:> warichu-options* common-props])]
|
||||
(when ^boolean vertical?
|
||||
[:> text-combine-upright-count-options* common-props])
|
||||
[:> font-features-options* common-props]
|
||||
(when ^boolean text-selection-active
|
||||
[:> text-emphasis-options* common-props])
|
||||
[:> annotation-clearance-options* common-props]
|
||||
(if text-selection-active
|
||||
[:> ruby-advanced-options* common-props]
|
||||
[:> ruby-presentation-options* ruby-presentation-props])])])))
|
||||
|
||||
[:div {:class (stl/css :japanese-layout-options)}
|
||||
[:> japanese-layout-toggle* toggle-props]
|
||||
(when ^boolean active?
|
||||
[:div {:class (stl/css :japanese-layout-controls)}
|
||||
[:div {:class (stl/css :japanese-icon-options)}
|
||||
[:> writing-mode-options* common-props]
|
||||
(when ^boolean vertical?
|
||||
[:*
|
||||
[:> text-orientation-options* common-props]
|
||||
[:> text-combine-upright-options*
|
||||
(mf/spread-props common-props
|
||||
{:text-selection-active text-selection-active})]])
|
||||
(when ^boolean text-selection-active
|
||||
[:> warichu-options* common-props])]
|
||||
(when ^boolean vertical?
|
||||
[:> text-combine-upright-count-options* common-props])
|
||||
[:> font-features-options* common-props]
|
||||
(when ^boolean text-selection-active
|
||||
[:> text-emphasis-options* common-props])
|
||||
[:> annotation-clearance-options* common-props]
|
||||
(if text-selection-active
|
||||
[:> ruby-advanced-options* common-props]
|
||||
[:> ruby-presentation-options* ruby-presentation-props])])]))
|
||||
|
||||
@ -55,8 +55,7 @@
|
||||
}
|
||||
|
||||
.japanese-layout-options {
|
||||
padding-block-start: var(--sp-xs);
|
||||
border-block-start: $b-1 solid var(--color-background-quaternary);
|
||||
padding-block: var(--sp-xs);
|
||||
}
|
||||
|
||||
.japanese-layout-toggle {
|
||||
@ -65,6 +64,10 @@
|
||||
min-block-size: $sz-32;
|
||||
}
|
||||
|
||||
.ruby-hidden-option {
|
||||
min-block-size: $sz-32;
|
||||
}
|
||||
|
||||
.japanese-icon-options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@ -91,7 +91,6 @@
|
||||
|
||||
(def ^:private snapshot-capture-debounce-ms 250)
|
||||
|
||||
|
||||
(defn initialized?
|
||||
"True when the WASM render context is ready to receive design-state
|
||||
operations. Use it to skip WASM work during transient states (e.g. while
|
||||
@ -99,7 +98,6 @@
|
||||
[]
|
||||
(and wasm/context-initialized? (not @wasm/context-lost?)))
|
||||
|
||||
|
||||
(defn set-transition-image-from-background!
|
||||
"Sets `transition-image*` to a data URL representing a solid background color."
|
||||
[background]
|
||||
@ -511,7 +509,6 @@
|
||||
(when (initialized?)
|
||||
(h/call wasm/internal-module "_render_preview")))
|
||||
|
||||
|
||||
(defonce pending-render (atom false))
|
||||
(defonce shapes-loading? (atom false))
|
||||
(defonce deferred-render? (atom false))
|
||||
@ -735,7 +732,6 @@
|
||||
[string]
|
||||
(+ (count string) 1))
|
||||
|
||||
|
||||
(defn- get-texture-id-for-gl-object
|
||||
"Registers a WebGL texture with Emscripten's GL object system and returns its ID"
|
||||
[texture]
|
||||
@ -1666,7 +1662,6 @@
|
||||
noop-fn)))))))]
|
||||
(process-next-chunk 0 [] [] []))))))
|
||||
|
||||
|
||||
;; This is a version of process-pending that doesn't have sideffects
|
||||
;; with like request render or update layout.
|
||||
(defn- process-pending-no-sideffects
|
||||
@ -1859,7 +1854,6 @@
|
||||
heapu32 (mem/get-heap-u32)
|
||||
heapf32 (mem/get-heap-f32)]
|
||||
|
||||
|
||||
(reduce (fn [offset {:keys [type parent id index value]}]
|
||||
(-> offset
|
||||
(mem.h32/write-u32 heapu32 (sr/translate-structure-modifier-type type))
|
||||
@ -2537,7 +2531,11 @@
|
||||
[element _start-pos _end-pos]
|
||||
(let [text (:text element)
|
||||
ruby (:ruby element)]
|
||||
(when (and (string? text) (seq text) (string? ruby) (seq ruby))
|
||||
(when (and (not (true? (:ruby-hidden element)))
|
||||
(string? text)
|
||||
(seq text)
|
||||
(string? ruby)
|
||||
(seq ruby))
|
||||
ruby)))
|
||||
|
||||
(defn- ruby-strip-entry
|
||||
@ -2546,7 +2544,8 @@
|
||||
gutter placement the canvas paints."
|
||||
[element {:keys [start-pos end-pos x y width height]}]
|
||||
(let [ruby (get element :ruby)]
|
||||
(when (string? ruby)
|
||||
(when (and (not (true? (:ruby-hidden element)))
|
||||
(string? ruby))
|
||||
(let [text (subs ruby
|
||||
(min start-pos (count ruby))
|
||||
(min end-pos (count ruby)))
|
||||
@ -2655,7 +2654,10 @@
|
||||
(when (= "auto" clearance) clearance))
|
||||
:annotation-has-ruby
|
||||
(let [ruby (get element :ruby)]
|
||||
(when (and (string? ruby) (seq ruby)) true))
|
||||
(when (and (not (true? (:ruby-hidden element)))
|
||||
(string? ruby)
|
||||
(seq ruby))
|
||||
true))
|
||||
;; Horizontal position data has no separate ruby
|
||||
;; strip, so carry the annotation on the base entry
|
||||
;; for static SVG export. Vertical ruby has its own
|
||||
|
||||
@ -50,7 +50,6 @@
|
||||
padding-fills (max 0 (- MAX-TEXT-FILLS (count fills)))]
|
||||
(+ new-ofset (* padding-fills types.fills.impl/FILL-U8-SIZE))))
|
||||
|
||||
|
||||
(defn- write-paragraph
|
||||
[offset dview paragraph]
|
||||
(let [text-align (sr/translate-text-align (get paragraph :text-align))
|
||||
@ -100,7 +99,9 @@
|
||||
text-buffer (encode-text (get span :text ""))
|
||||
text-length (mem/size text-buffer)
|
||||
|
||||
ruby-buffer (encode-text (get span :ruby ""))
|
||||
ruby-buffer (encode-text (if (true? (:ruby-hidden span))
|
||||
""
|
||||
(get span :ruby "")))
|
||||
ruby-length (mem/size ruby-buffer)
|
||||
|
||||
fills (take MAX-TEXT-FILLS (get span :fills []))
|
||||
@ -206,7 +207,10 @@
|
||||
text-buffer (encode-text text)
|
||||
text-size (mem/size text-buffer)
|
||||
|
||||
ruby-text (apply str (map #(get % :ruby "") normalized-spans))
|
||||
ruby-text (apply str (map #(if (true? (:ruby-hidden %))
|
||||
""
|
||||
(get % :ruby ""))
|
||||
normalized-spans))
|
||||
ruby-buffer (encode-text ruby-text)
|
||||
ruby-size (mem/size ruby-buffer)
|
||||
|
||||
|
||||
@ -648,6 +648,7 @@
|
||||
{:text-combine-upright "none"
|
||||
:text-emphasis "none"
|
||||
:ruby ""
|
||||
:ruby-hidden false
|
||||
:ruby-size "half"
|
||||
:ruby-align "space-around"
|
||||
:ruby-overhang "auto"
|
||||
|
||||
@ -23,6 +23,12 @@
|
||||
(def mapping
|
||||
{:fills [encode decode]
|
||||
:ruby [identity #(when-not (= "" %) %)]
|
||||
:ruby-hidden [(fn [value] (when (some? value) (str value)))
|
||||
(fn [value]
|
||||
(case value
|
||||
"true" true
|
||||
"false" false
|
||||
nil))]
|
||||
:ruby-size [identity #(when-not (= "" %) %)]
|
||||
:ruby-align [identity #(when-not (= "" %) %)]
|
||||
:ruby-overhang [identity #(when-not (= "" %) %)]
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
(t/is (= {:text-combine-upright "none"
|
||||
:text-emphasis "filled-dot"
|
||||
:ruby "にち"
|
||||
:ruby-hidden false
|
||||
:ruby-size "half"
|
||||
:ruby-align "space-around"
|
||||
:ruby-overhang "auto"
|
||||
@ -58,6 +59,7 @@
|
||||
(t/is (= {:text-combine-upright "none"
|
||||
:text-emphasis "none"
|
||||
:ruby ""
|
||||
:ruby-hidden false
|
||||
:ruby-size "half"
|
||||
:ruby-align "space-around"
|
||||
:ruby-overhang "auto"
|
||||
@ -74,17 +76,20 @@
|
||||
:text-combine-upright "digits2"
|
||||
:text-emphasis "filled-dot"
|
||||
:ruby "へいせい"
|
||||
:ruby-hidden true
|
||||
:ruby-size "third"
|
||||
:ruby-align "center"
|
||||
:ruby-overhang "none"
|
||||
:ruby-side "under"
|
||||
:annotation-clearance "auto"}
|
||||
{:text "年"
|
||||
:ruby-hidden false
|
||||
:warichu "warichu"
|
||||
:font-features "vpal"}])]
|
||||
(t/is (= {:text-combine-upright :multiple
|
||||
:text-emphasis :multiple
|
||||
:ruby :multiple
|
||||
:ruby-hidden :multiple
|
||||
:ruby-size :multiple
|
||||
:ruby-align :multiple
|
||||
:ruby-overhang :multiple
|
||||
@ -181,6 +186,27 @@
|
||||
(t/is (= [2 3 1 1 0 0]
|
||||
(mapv #(.getUint8 dview %) (range 10 16))))))
|
||||
|
||||
(t/deftest write-spans-omits-hidden-ruby-bytes
|
||||
(let [buffer (js/ArrayBuffer. 256)
|
||||
dview (js/DataView. buffer)
|
||||
paragraph {:font-size "16"
|
||||
:font-weight "400"
|
||||
:line-height "1"}]
|
||||
(write-spans 0 dview [{:text "日"
|
||||
:ruby "にち"
|
||||
:ruby-hidden true
|
||||
:font-size "16"
|
||||
:font-weight "400"}]
|
||||
paragraph)
|
||||
(t/is (= 0 (.getInt32 dview 72 true)))
|
||||
(write-spans 0 dview [{:text "日"
|
||||
:ruby "にち"
|
||||
:ruby-hidden false
|
||||
:font-size "16"
|
||||
:font-weight "400"}]
|
||||
paragraph)
|
||||
(t/is (pos? (.getInt32 dview 72 true)))))
|
||||
|
||||
(t/deftest write-spans-serializes-counted-digits-tcy
|
||||
(let [sentinel (js-obj)
|
||||
previous (if (.hasOwnProperty wasm/serializers "text-combine-upright")
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
["react-dom/server" :as rds]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.ui.ds.controls.select :as select]
|
||||
[app.main.ui.shapes.text.html-text :as html-text]
|
||||
[app.main.ui.shapes.text.styles :as text-styles]
|
||||
[app.main.ui.workspace.sidebar.options.menus.text-japanese-layout :as tjl]
|
||||
[app.util.text.content.styles :as content-styles]
|
||||
@ -20,6 +21,7 @@
|
||||
[:text-combine-upright
|
||||
:text-emphasis
|
||||
:ruby
|
||||
:ruby-hidden
|
||||
:ruby-size
|
||||
:ruby-align
|
||||
:ruby-overhang
|
||||
@ -34,6 +36,18 @@
|
||||
(def ^:private with-mixed-span-option @#'tjl/with-mixed-span-option)
|
||||
(def ^:private ruby-common-props @#'tjl/ruby-common-props)
|
||||
|
||||
(t/deftest japanese-layout-controls-follow-file-or-profile-configuration
|
||||
(t/is (false? (tjl/japanese-layout-config-enabled? {} {})))
|
||||
(t/is (true? (tjl/japanese-layout-config-enabled?
|
||||
{:options {:japanese-layout true}}
|
||||
{})))
|
||||
(t/is (true? (tjl/japanese-layout-config-enabled?
|
||||
{}
|
||||
{:props {:japanese-layout-all-files true}})))
|
||||
(t/is (true? (tjl/japanese-layout-config-enabled?
|
||||
{:options {:japanese-layout true}}
|
||||
{:props {:japanese-layout-all-files false}}))))
|
||||
|
||||
(t/deftest text-emphasis-select-reports-and-restores-canonical-values
|
||||
(let [options (tjl/text-emphasis-options identity)
|
||||
reported-id (:id (select/get-option options "filled-dot"))]
|
||||
@ -71,6 +85,27 @@
|
||||
(t/is (str/includes? markup "aria-expanded=\"false\""))
|
||||
(t/is (str/includes? markup "workspace.options.text-options.ruby-advanced-options"))))
|
||||
|
||||
(t/deftest advanced-furigana-options-include-hide-toggle
|
||||
(let [markup (rds/renderToStaticMarkup
|
||||
(mf/element tjl/ruby-customization-options*
|
||||
#js {:values {:ruby-hidden true}
|
||||
:on-change identity
|
||||
:on-blur identity}))]
|
||||
(t/is (str/includes? markup "workspace.options.text-options.ruby-hidden"))
|
||||
(t/is (str/includes? markup "role=\"switch\""))
|
||||
(t/is (str/includes? markup "aria-checked=\"true\""))))
|
||||
|
||||
(t/deftest hidden-furigana-renders-base-text-without-ruby-layout
|
||||
(let [markup (rds/renderToStaticMarkup
|
||||
(mf/element html-text/render-text*
|
||||
#js {:node {:text "日"
|
||||
:ruby "にち"
|
||||
:ruby-hidden true}
|
||||
:parent {}
|
||||
:shape {}}))]
|
||||
(t/is (str/includes? markup ">日</span>"))
|
||||
(t/is (not (str/includes? markup "<ruby")))))
|
||||
|
||||
(t/deftest advanced-furigana-options-preserve-change-callbacks
|
||||
(let [on-change identity
|
||||
on-blur identity
|
||||
@ -88,17 +123,23 @@
|
||||
:children
|
||||
[{:text "日"
|
||||
:ruby "にち"
|
||||
:ruby-hidden false
|
||||
:ruby-size "half"}
|
||||
{:text "本"
|
||||
:ruby ""
|
||||
:ruby-hidden false
|
||||
:ruby-size "quarter"}]}]}]}}
|
||||
values (dwt/current-ruby-values {:shape shape
|
||||
:attrs dwt/ruby-presentation-attrs})
|
||||
updated (dwt/update-ruby-presentation-attrs shape {:ruby-size "third"})
|
||||
updated (dwt/update-ruby-presentation-attrs
|
||||
shape {:ruby-hidden true :ruby-size "third"})
|
||||
spans (get-in updated [:content :children 0 :children 0 :children])]
|
||||
(t/is (= "half" (:ruby-size values)))
|
||||
(t/is (false? (:ruby-hidden values)))
|
||||
(t/is (= "third" (:ruby-size (first spans))))
|
||||
(t/is (= "quarter" (:ruby-size (second spans))))))
|
||||
(t/is (true? (:ruby-hidden (first spans))))
|
||||
(t/is (= "quarter" (:ruby-size (second spans))))
|
||||
(t/is (false? (:ruby-hidden (second spans))))))
|
||||
|
||||
(t/deftest mixed-japanese-span-values-have-distinct-control-states
|
||||
(let [options (with-mixed-span-option
|
||||
@ -122,6 +163,7 @@
|
||||
:text-combine-upright "digits2"
|
||||
:text-emphasis "filled-dot"
|
||||
:ruby "にち"
|
||||
:ruby-hidden true
|
||||
:ruby-size "third"
|
||||
:ruby-align "center"
|
||||
:ruby-overhang "none"
|
||||
@ -133,6 +175,7 @@
|
||||
:text-combine-upright "none"
|
||||
:text-emphasis "none"
|
||||
:ruby ""
|
||||
:ruby-hidden false
|
||||
:ruby-size "half"
|
||||
:ruby-align "space-around"
|
||||
:ruby-overhang "auto"
|
||||
@ -176,6 +219,16 @@
|
||||
(content-styles/styles->attrs
|
||||
{"text-combine-upright" "digits 3"}))))
|
||||
|
||||
(t/deftest hidden-furigana-round-trips-through-editor-styles
|
||||
(t/is (= "true"
|
||||
(unchecked-get
|
||||
(content-styles/attrs->styles {:ruby-hidden true})
|
||||
"--ruby-hidden")))
|
||||
(t/is (= {:ruby-hidden false}
|
||||
(content-styles/styles->attrs {"--ruby-hidden" "false"})))
|
||||
(t/is (= {:ruby-hidden nil}
|
||||
(content-styles/styles->attrs {"--ruby-hidden" ""}))))
|
||||
|
||||
(t/deftest japanese-layout-is-explicitly-enabled-by-writing-mode
|
||||
(t/is (false? (tjl/japanese-layout-enabled? {})))
|
||||
(t/is (false? (tjl/japanese-layout-enabled? {:writing-mode nil})))
|
||||
|
||||
@ -1320,6 +1320,18 @@ msgstr "Unpublish Library"
|
||||
msgid "dashboard.update-settings"
|
||||
msgstr "Update settings"
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.description"
|
||||
msgstr "Makes Japanese text layout controls available in every file."
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.enable-all-files"
|
||||
msgstr "Enable Japanese text layout for all files"
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.title"
|
||||
msgstr "Japanese text layout"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1328
|
||||
msgid "dashboard.upgrade-plan.no-limits"
|
||||
msgstr "No limits on creativity"
|
||||
@ -6724,6 +6736,10 @@ msgstr "Disable snap to pixel"
|
||||
msgid "workspace.header.menu.disable-snap-ruler-guides"
|
||||
msgstr "Disable snap to ruler guides"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs
|
||||
msgid "workspace.header.menu.disable-japanese-layout"
|
||||
msgstr "Disable Japanese text layout"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs:336
|
||||
msgid "workspace.header.menu.disable-webgl"
|
||||
msgstr "Disable WebGL rendering (beta)"
|
||||
@ -6732,6 +6748,10 @@ msgstr "Disable WebGL rendering (beta)"
|
||||
msgid "workspace.header.menu.enable-dynamic-alignment"
|
||||
msgstr "Enable dynamic alignment"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs
|
||||
msgid "workspace.header.menu.enable-japanese-layout"
|
||||
msgstr "Enable Japanese text layout"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs:250
|
||||
msgid "workspace.header.menu.enable-scale-content"
|
||||
msgstr "Enable proportional scale"
|
||||
@ -8522,6 +8542,10 @@ msgstr "Normal"
|
||||
msgid "workspace.options.text-options.japanese-layout"
|
||||
msgstr "Japanese text layout"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs
|
||||
msgid "workspace.options.text-options.japanese-layout-enable-for-text"
|
||||
msgstr "Enable for this text"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs
|
||||
msgid "workspace.options.text-options.text-combine-upright-all"
|
||||
msgstr "Tate-chu-yoko"
|
||||
@ -8626,6 +8650,10 @@ msgstr "Furigana"
|
||||
msgid "workspace.options.text-options.ruby-advanced-options"
|
||||
msgstr "Advanced furigana options"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs
|
||||
msgid "workspace.options.text-options.ruby-hidden"
|
||||
msgstr "Hide furigana"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs
|
||||
msgid "workspace.options.text-options.ruby-size"
|
||||
msgstr "Ruby size"
|
||||
@ -10301,4 +10329,4 @@ msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Click to close the path"
|
||||
|
||||
msgid "notifications.invitation-canceled"
|
||||
msgstr "This invitation is no longer available."
|
||||
msgstr "This invitation is no longer available."
|
||||
|
||||
@ -992,6 +992,10 @@ msgstr "通常"
|
||||
msgid "workspace.options.text-options.japanese-layout"
|
||||
msgstr "日本語組版"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs
|
||||
msgid "workspace.options.text-options.japanese-layout-enable-for-text"
|
||||
msgstr "このテキストで有効にする"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs
|
||||
msgid "workspace.options.text-options.text-combine-upright-all"
|
||||
msgstr "縦中横"
|
||||
@ -1096,6 +1100,10 @@ msgstr "ふりがな"
|
||||
msgid "workspace.options.text-options.ruby-advanced-options"
|
||||
msgstr "ふりがなの詳細設定"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs
|
||||
msgid "workspace.options.text-options.ruby-hidden"
|
||||
msgstr "ふりがなを非表示"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs
|
||||
msgid "workspace.options.text-options.ruby-size"
|
||||
msgstr "ルビの大きさ"
|
||||
@ -1171,3 +1179,23 @@ msgstr "横書き"
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs
|
||||
msgid "workspace.options.text-options.writing-mode-vertical"
|
||||
msgstr "縦書き(右から左)"
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.description"
|
||||
msgstr "すべてのファイルで日本語組版コントロールを利用できるようにします。"
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.enable-all-files"
|
||||
msgstr "すべてのファイルで日本語組版を有効にする"
|
||||
|
||||
#: src/app/main/ui/settings/options.cljs
|
||||
msgid "dashboard.japanese-layout.title"
|
||||
msgstr "日本語組版"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs
|
||||
msgid "workspace.header.menu.disable-japanese-layout"
|
||||
msgstr "日本語組版を無効にする"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs
|
||||
msgid "workspace.header.menu.enable-japanese-layout"
|
||||
msgstr "日本語組版を有効にする"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user