From 42230f263015538e847260ac833c10c8b602aafd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 25 Jun 2024 14:59:13 +0200 Subject: [PATCH 1/6] :sparkles: Change shapes color --- .../src/app/main/data/workspace/colors.cljs | 3 +- frontend/src/app/plugins/api.cljs | 84 +++++++++++----- frontend/src/app/plugins/format.cljs | 8 ++ frontend/src/app/plugins/parser.cljs | 98 +++++++++++++++++++ 4 files changed, 167 insertions(+), 26 deletions(-) create mode 100644 frontend/src/app/plugins/format.cljs create mode 100644 frontend/src/app/plugins/parser.cljs diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index af771bd4a..dc0a44d4a 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -24,6 +24,7 @@ [app.util.color :as uc] [app.util.storage :refer [storage]] [beicon.v2.core :as rx] + [cuerdas.core :as str] [potok.v2.core :as ptk])) ;; A set of keys that are used for shared state identifiers @@ -377,7 +378,7 @@ (defn color-att->text [color] - {:fill-color (:color color) + {:fill-color (when (:color color) (str/lower (:color color))) :fill-opacity (:opacity color) :fill-color-ref-id (:id color) :fill-color-ref-file (:file-id color) diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index f6157303e..a645bb791 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -13,12 +13,14 @@ [app.common.files.helpers :as cfh] [app.common.geom.point :as gpt] [app.common.record :as cr] + [app.common.schema :as sm] [app.common.text :as txt] [app.common.types.color :as ctc] [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.main.data.changes :as ch] [app.main.data.workspace.bool :as dwb] + [app.main.data.workspace.colors :as dwc] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.media :as dwm] [app.main.store :as st] @@ -27,6 +29,7 @@ [app.plugins.fonts :as fonts] [app.plugins.library :as library] [app.plugins.page :as page] + [app.plugins.parser :as parser] [app.plugins.shape :as shape] [app.plugins.user :as user] [app.plugins.utils :as u] @@ -87,35 +90,66 @@ (let [selection (get-in @st/state [:workspace-local :selected])] (apply array (sequence (map (partial shape/shape-proxy $plugin)) selection)))) - (getColors + (shapesColors [_ shapes] - (let [objects (u/locate-objects) - shapes (->> shapes - (map #(obj/get % "$id")) - (mapcat #(cfh/get-children-with-self objects %))) + (cond + (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) + (u/display-not-valid :shapesColors-shapes shapes) - file-id (:current-file-id @st/state) - shared-libs (:workspace-libraries @st/state) + :else + (let [objects (u/locate-objects) + shapes (->> shapes + (map #(obj/get % "$id")) + (mapcat #(cfh/get-children-with-self objects %))) - colors - (apply - array - (->> (ctc/extract-all-colors shapes file-id shared-libs) - (group-by :attrs) - (map (fn [[color attrs]] - (let [shapes-info (apply array (map (fn [{:keys [prop shape-id index]}] - #js {:property (d/name prop) - :index index - :shapeId (str shape-id)}) attrs)) - color (u/to-js color)] - (obj/set! color "shapeInfo" shapes-info) - color)))))] - colors)) + file-id (:current-file-id @st/state) + shared-libs (:workspace-libraries @st/state) - (changeColor - [_ _shapes _old-color _new-color] - ;; TODO - ) + format-entry + (fn [{:keys [prop shape-id index]}] + #js {:property (d/name prop) + :index index + :shapeId (str shape-id)}) + format-result + (fn [[color attrs]] + (let [shapes-info (apply array (map format-entry attrs)) + color (u/to-js color)] + (obj/set! color "shapeInfo" shapes-info) + color))] + (apply + array + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs) + (map format-result)))))) + + (replaceColor + [_ shapes old-color new-color] + + (let [old-color (parser/parse-color old-color) + new-color (parser/parse-color new-color)] + (cond + (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) + (u/display-not-valid :replaceColor-shapes shapes) + + (not (sm/validate ::ctc/color old-color)) + (u/display-not-valid :replaceColor-oldColor old-color) + + (not (sm/validate ::ctc/color new-color)) + (u/display-not-valid :replaceColor-newColor new-color) + + :else + (let [file-id (:current-file-id @st/state) + shared-libs (:workspace-libraries @st/state) + objects (u/locate-objects) + shapes + (->> shapes + (map #(obj/get % "$id")) + (mapcat #(cfh/get-children-with-self objects %))) + + shapes-by-color + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs))] + (st/emit! (dwc/change-color-in-selected new-color (get shapes-by-color old-color) old-color)))))) (getRoot [_] diff --git a/frontend/src/app/plugins/format.cljs b/frontend/src/app/plugins/format.cljs new file mode 100644 index 000000000..4b2a44c09 --- /dev/null +++ b/frontend/src/app/plugins/format.cljs @@ -0,0 +1,8 @@ +;; 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) KALEIDOS INC + +(ns app.plugins.format) + diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs new file mode 100644 index 000000000..0b12c9643 --- /dev/null +++ b/frontend/src/app/plugins/parser.cljs @@ -0,0 +1,98 @@ +;; 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) KALEIDOS INC + +(ns app.plugins.parser + (:require + [app.common.data :as d] + [app.common.uuid :as uuid] + [app.util.object :as obj] + [cuerdas.core :as str])) + +(defn parse-id + [id] + (when id (uuid/uuid id))) + +(defn parse-keyword + [kw] + (when kw (keyword kw))) + +(defn parse-hex + [color] + (when color (-> color str/lower))) + +;;export type PenpotImageData = { +;; name?: string; +;; width: number; +;; height: number; +;; mtype?: string; +;; id: string; +;; keepApectRatio?: boolean; +;;} +(defn parse-image-data + [^js image-data] + (when image-data + (d/without-nils + {:id (-> (obj/get image-data "id") parse-id) + :name (obj/get image-data "name") + :width (obj/get image-data "width") + :height (obj/get image-data "height") + :mtype (obj/get image-data "mtype") + :keep-aspect-ratio (obj/get image-data "keepApectRatio")}))) + +;; export type PenpotGradient = { +;; type: 'linear' | 'radial'; +;; startX: number; +;; startY: number; +;; endX: number; +;; endY: number; +;; width: number; +;; stops: Array<{ color: string; opacity?: number; offset: number }>; +;; } +(defn parse-gradient-stop + [^js stop] + (when stop + (d/without-nils + {:color (-> (obj/get stop "color") parse-hex) + :opacity (obj/get stop "opacity") + :offset (obj/get stop "offset")}))) + +(defn parse-gradient + [^js gradient] + (when gradient + (d/without-nils + {:type (-> (obj/get gradient "type") parse-keyword) + :start-x (obj/get gradient "startX") + :start-y (obj/get gradient "startY") + :end-x (obj/get gradient "endX") + :end-y (obj/get gradient "endY") + :width (obj/get gradient "width") + :stops (->> (obj/get gradient "stops") + (mapv parse-gradient-stop))}))) + +;; export interface PenpotColor { +;; id?: string; +;; name?: string; +;; path?: string; +;; color?: string; +;; opacity?: number; +;; refId?: string; +;; refFile?: string; +;; gradient?: PenpotGradient; +;; image?: PenpotImageData; +;; } +(defn parse-color + [^js color] + (when color + (d/without-nils + {:id (-> (obj/get color "id") parse-id) + :name (obj/get color "name") + :path (obj/get color "path") + :color (-> (obj/get color "color") parse-hex) + :opacity (obj/get color "opacity") + :ref-id (-> (obj/get color "refId") parse-id) + :ref-file (-> (obj/get color "refFile") parse-id) + :gradient (-> (obj/get color "gradient") parse-gradient) + :image (-> (obj/get color "image") parse-image-data)}))) From ac58a5b8faaffe8a98894d1671f9c1f155b60bdd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 27 Jun 2024 10:11:48 +0200 Subject: [PATCH 2/6] :sparkles: Improved transformation from and to JS for plugins --- frontend/src/app/plugins/api.cljs | 27 +- frontend/src/app/plugins/fonts.cljs | 3 +- frontend/src/app/plugins/format.cljs | 405 +++++++++++- frontend/src/app/plugins/grid.cljs | 11 +- frontend/src/app/plugins/library.cljs | 47 +- frontend/src/app/plugins/page.cljs | 29 +- frontend/src/app/plugins/parser.cljs | 308 ++++++++- frontend/src/app/plugins/public_utils.cljs | 3 +- frontend/src/app/plugins/shape.cljs | 625 ++++-------------- frontend/src/app/plugins/text.cljs | 434 ++++++++++++ frontend/src/app/plugins/user.cljs | 3 +- frontend/src/app/plugins/utils.cljs | 55 -- frontend/src/app/plugins/viewport.cljs | 3 +- frontend/src/app/util/object.cljs | 5 + .../plugins/context_shapes_test.cljs | 23 +- 15 files changed, 1359 insertions(+), 622 deletions(-) create mode 100644 frontend/src/app/plugins/text.cljs diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index a645bb791..2cd3938a7 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -27,6 +27,7 @@ [app.plugins.events :as events] [app.plugins.file :as file] [app.plugins.fonts :as fonts] + [app.plugins.format :as format] [app.plugins.library :as library] [app.plugins.page :as page] [app.plugins.parser :as parser] @@ -101,26 +102,12 @@ shapes (->> shapes (map #(obj/get % "$id")) (mapcat #(cfh/get-children-with-self objects %))) - file-id (:current-file-id @st/state) - shared-libs (:workspace-libraries @st/state) + shared-libs (:workspace-libraries @st/state)] - format-entry - (fn [{:keys [prop shape-id index]}] - #js {:property (d/name prop) - :index index - :shapeId (str shape-id)}) - format-result - (fn [[color attrs]] - (let [shapes-info (apply array (map format-entry attrs)) - color (u/to-js color)] - (obj/set! color "shapeInfo" shapes-info) - color))] - (apply - array - (->> (ctc/extract-all-colors shapes file-id shared-libs) - (group-by :attrs) - (map format-result)))))) + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs) + (format/format-array format/format-color-result))))) (replaceColor [_ shapes old-color new-color] @@ -188,8 +175,8 @@ (p/create (fn [resolve reject] (->> (dwm/upload-media-url name file-id url) - (rx/map u/to-js) (rx/take 1) + (rx/map format/format-image) (rx/subs! resolve reject))))))) (uploadMediaData @@ -205,7 +192,7 @@ :on-image identity :on-svg identity}) (rx/take 1) - (rx/map u/to-js) + (rx/map format/format-image) (rx/subs! resolve reject)))))) (group diff --git a/frontend/src/app/plugins/fonts.cljs b/frontend/src/app/plugins/fonts.cljs index 4902277bc..74631e1a4 100644 --- a/frontend/src/app/plugins/fonts.cljs +++ b/frontend/src/app/plugins/fonts.cljs @@ -12,6 +12,7 @@ [app.main.fonts :as fonts] [app.main.store :as st] [app.plugins.shape :as shape] + [app.plugins.text :as text] [app.plugins.utils :as u] [app.util.object :as obj] [cuerdas.core :as str])) @@ -39,7 +40,7 @@ (applyToRange [_ range variant] (cond - (not (shape/text-range? range)) + (not (text/text-range? range)) (u/display-not-valid :applyToRange range) ;; TODO: Check variant inside font variants diff --git a/frontend/src/app/plugins/format.cljs b/frontend/src/app/plugins/format.cljs index 4b2a44c09..9df43773b 100644 --- a/frontend/src/app/plugins/format.cljs +++ b/frontend/src/app/plugins/format.cljs @@ -4,5 +4,408 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.plugins.format) +(ns app.plugins.format + (:require + [app.common.data :as d] + [app.common.data.macros :as dm] + [app.util.object :as obj])) +(defn format-id + [id] + (when id (dm/str id))) + +(defn format-key + [kw] + (when kw (d/name kw))) + +(defn format-array + [format-fn coll] + (when (some? coll) + (apply array (keep format-fn coll)))) + +;; export type PenpotPoint = { x: number; y: number }; +(defn format-point + [{:keys [x y] :as point}] + (when (some? point) + (obj/clear-empty + #js {:x x :y y}))) + +;;export type PenpotBounds = { +;; x: number; +;; y: number; +;; width: number; +;; height: number; +;;}; +(defn format-bounds + [{:keys [x y width height] :as bounds}] + (when (some? bounds) + (obj/clear-empty + #js {:x x :y y :width width :height height}))) + +;; export interface PenpotColorShapeInfoEntry { +;; readonly property: string; +;; readonly index?: number; +;; readonly shapeId: string; +;; } +(defn format-shape-info + [{:keys [prop shape-id index] :as info}] + (when (some? info) + (obj/clear-empty + #js {:property (d/name prop) + :index index + :shapeId (dm/str shape-id)}))) + +;; export type PenpotGradient = { +;; type: 'linear' | 'radial'; +;; startX: number; +;; startY: number; +;; endX: number; +;; endY: number; +;; width: number; +;; stops: Array<{ color: string; opacity?: number; offset: number }>; +;; }; +(defn format-stop + [{:keys [color opacity offset] :as stop}] + (when (some? stop) + (obj/clear-empty #js {:color color :opacity opacity :offset offset}))) + +(defn format-gradient + [{:keys [type start-x start-y end-x end-y width stops] :as gradient}] + (when (some? gradient) + (obj/clear-empty + #js {:type (format-key type) + :startX start-x + :startY start-y + :endX end-x + :endY end-y + :width width + :stops (format-array format-stop stops)}))) + +;; export type PenpotImageData = { +;; name?: string; +;; width: number; +;; height: number; +;; mtype?: string; +;; id: string; +;; keepApectRatio?: boolean; +;; }; +(defn format-image + [{:keys [name width height mtype id keep-aspect-ratio] :as image}] + (when (some? image) + (obj/clear-empty + #js {:name name + :width width + :height height + :mtype mtype + :id (format-id id) + :keepAspectRatio keep-aspect-ratio}))) + +;; export interface PenpotColor { +;; id?: string; +;; name?: string; +;; path?: string; +;; color?: string; +;; opacity?: number; +;; refId?: string; +;; refFile?: string; +;; gradient?: PenpotGradient; +;; image?: PenpotImageData; +;; } +(defn format-color + [{:keys [id name path color opacity ref-id ref-file gradient image] :as color-data}] + (when (some? color-data) + (obj/clear-empty + #js {:id (format-id id) + :name name + :path path + :color color + :opacity opacity + :refId (format-id ref-id) + :refFile (format-id ref-file) + :gradient (format-gradient gradient) + :image (format-image image)}))) + +;; PenpotColor & PenpotColorShapeInfo +(defn format-color-result + [[color attrs]] + (let [shapes-info (apply array (map format-shape-info attrs)) + color (format-color color)] + (obj/set! color "shapeInfo" shapes-info) + color)) + + +;; export interface PenpotShadow { +;; id?: string; +;; style?: 'drop-shadow' | 'inner-shadow'; +;; offsetX?: number; +;; offsetY?: number; +;; blur?: number; +;; spread?: number; +;; hidden?: boolean; +;; color?: PenpotColor; +;; } +(defn format-shadow + [{:keys [id style offset-x offset-y blur spread hidden color] :as shadow}] + (when (some? shadow) + (obj/clear-empty + #js {:id (-> id format-id) + :style (-> style format-key) + :offsetX offset-x + :offsetY offset-y + :blur blur + :spread spread + :hidden hidden + :color (format-color color)}))) + +(defn format-shadows + [shadows] + (when (some? shadows) + (format-array format-shadow shadows))) + +;;export interface PenpotFill { +;; fillColor?: string; +;; fillOpacity?: number; +;; fillColorGradient?: PenpotGradient; +;; fillColorRefFile?: string; +;; fillColorRefId?: string; +;; fillImage?: PenpotImageData; +;;} +(defn format-fill + [{:keys [fill-color fill-opacity fill-color-gradient fill-color-ref-file fill-color-ref-id fill-image] :as fill}] + (when (some? fill) + (obj/clear-empty + #js {:fillColor fill-color + :fillOpacity fill-opacity + :fillColorGradient (format-gradient fill-color-gradient) + :fillColorRefFile (format-id fill-color-ref-file) + :fillColorRefId (format-id fill-color-ref-id) + :fillImage (format-image fill-image)}))) + +(defn format-fills + [fills] + (when (some? fills) + (format-array format-fill fills))) + +;; export interface PenpotStroke { +;; strokeColor?: string; +;; strokeColorRefFile?: string; +;; strokeColorRefId?: string; +;; strokeOpacity?: number; +;; strokeStyle?: 'solid' | 'dotted' | 'dashed' | 'mixed' | 'none' | 'svg'; +;; strokeWidth?: number; +;; strokeAlignment?: 'center' | 'inner' | 'outer'; +;; strokeCapStart?: PenpotStrokeCap; +;; strokeCapEnd?: PenpotStrokeCap; +;; strokeColorGradient?: PenpotGradient; +;; } +(defn format-stroke + [{:keys [stroke-color stroke-color-ref-file stroke-color-ref-id + stroke-opacity stroke-style stroke-width stroke-alignment + stroke-cap-start stroke-cap-end stroke-color-gradient] :as stroke}] + + (when (some? stroke) + (obj/clear-empty + #js {:strokeColor stroke-color + :strokeColorRefFile (format-id stroke-color-ref-file) + :strokeColorRefId (format-id stroke-color-ref-id) + :strokeOpacity stroke-opacity + :strokeStyle (format-key stroke-style) + :strokeWidth stroke-width + :strokeAlignment (format-key stroke-alignment) + :strokeCapStart (format-key stroke-cap-start) + :strokeCapEnd (format-key stroke-cap-end) + :strokeColorGradient (format-gradient stroke-color-gradient)}))) + +(defn format-strokes + [strokes] + (when (some? strokes) + (format-array format-stroke strokes))) + +;; export interface PenpotBlur { +;; id?: string; +;; type?: 'layer-blur'; +;; value?: number; +;; hidden?: boolean; +;; } +(defn format-blur + [{:keys [id type value hidden] :as blur}] + (when (some? blur) + (obj/clear-empty + #js {:id (format-id id) + :type (format-key type) + :value value + :hidden hidden}))) + +;; export interface PenpotExport { +;; type: 'png' | 'jpeg' | 'svg' | 'pdf'; +;; scale: number; +;; suffix: string; +;; } +(defn format-export + [{:keys [type scale suffix] :as export}] + (when (some? export) + (obj/clear-empty + #js {:type (format-key type) + :scale scale + :suffix suffix}))) + +(defn format-exports + [exports] + (when (some? exports) + (format-array format-export exports))) + +;; export interface PenpotFrameGuideColumnParams { +;; color: { color: string; opacity: number }; +;; type?: 'stretch' | 'left' | 'center' | 'right'; +;; size?: number; +;; margin?: number; +;; itemLength?: number; +;; gutter?: number; +;; } +(defn format-frame-guide-column-params + [{:keys [color type size margin item-length gutter] :as params}] + (when (some? params) + (obj/clear-empty + #js {:color (format-color color) + :type (format-key type) + :size size + :margin margin + :itemLength item-length + :gutter gutter}))) + +;; export interface PenpotFrameGuideColumn { +;; type: 'column'; +;; display: boolean; +;; params: PenpotFrameGuideColumnParams; +;; } +(defn format-frame-guide-column + [{:keys [type display params] :as guide}] + (when (some? guide) + (obj/clear-empty + #js {:type (format-key type) + :display display + :params (format-frame-guide-column-params params)}))) + +;; export interface PenpotFrameGuideRow { +;; type: 'row'; +;; display: boolean; +;; params: PenpotFrameGuideColumnParams; +;; } +(defn format-frame-guide-row + [{:keys [type display params] :as guide}] + (when (some? guide) + (obj/clear-empty + #js {:type (format-key type) + :display display + :params (format-frame-guide-column-params params)}))) + +;;export interface PenpotFrameGuideSquareParams { +;; color: { color: string; opacity: number }; +;; size?: number; +;;} +(defn format-frame-guide-square-params + [{:keys [color size] :as params}] + (when (some? params) + (obj/clear-empty + #js {:color (format-color color) + :size size}))) + +;; export interface PenpotFrameGuideSquare { +;; type: 'square'; +;; display: boolean; +;; params: PenpotFrameGuideSquareParams; +;; } + +(defn format-frame-guide-square + [{:keys [type display params] :as guide}] + (when (some? guide) + (obj/clear-empty + #js {:type (format-key type) + :display display + :params (format-frame-guide-column-params params)}))) + +(defn format-frame-guide + [{:keys [type] :as guide}] + (when (some? guide) + (case type + :column (format-frame-guide-column guide) + :row (format-frame-guide-row guide) + :square (format-frame-guide-square guide)))) + +(defn format-frame-guides + [guides] + (when (some? guides) + (format-array format-frame-guide guides))) + +;;interface PenpotPathCommand { +;; command: +;; | 'M' | 'move-to' +;; | 'Z' | 'close-path' +;; | 'L' | 'line-to' +;; | 'H' | 'line-to-horizontal' +;; | 'V' | 'line-to-vertical' +;; | 'C' | 'curve-to' +;; | 'S' | 'smooth-curve-to' +;; | 'Q' | 'quadratic-bezier-curve-to' +;; | 'T' | 'smooth-quadratic-bezier-curve-to' +;; | 'A' | 'elliptical-arc'; +;; +;; params?: { +;; x?: number; +;; y?: number; +;; c1x: number; +;; c1y: number; +;; c2x: number; +;; c2y: number; +;; rx?: number; +;; ry?: number; +;; xAxisRotation?: number; +;; largeArcFlag?: boolean; +;; sweepFlag?: boolean; +;; }; +;;} +(defn format-command-params + [{:keys [x y c1x c1y c2x c2y rx ry x-axis-rotation large-arc-flag sweep-flag] :as props}] + (when (some? props) + (obj/clear-empty + #js {:x x + :y y + :c1x c1x + :c1y c1y + :c2x c2x + :c2y c2y + :rx rx + :ry ry + :xAxisRotation x-axis-rotation + :largeArcFlag large-arc-flag + :sweepFlag sweep-flag}))) + +(defn format-command + [{:keys [command params] :as props}] + (when (some? props) + (obj/clear-empty + #js {:command (format-key command) + :params (format-command-params params)}))) + +(defn format-path-content + [content] + (when (some? content) + (format-array format-command content))) + +;; export type PenpotTrackType = 'flex' | 'fixed' | 'percent' | 'auto'; +;; +;; export interface PenpotTrack { +;; type: PenpotTrackType; +;; value: number | null; +;; } +(defn format-track + [{:keys [type value] :as track}] + (when (some? track) + (obj/clear-empty + #js {:type (-> type format-key) + :value value}))) + +(defn format-tracks + [tracks] + (when (some? tracks) + (format-array format-track tracks))) diff --git a/frontend/src/app/plugins/grid.cljs b/frontend/src/app/plugins/grid.cljs index a715e0c7a..eb255a008 100644 --- a/frontend/src/app/plugins/grid.cljs +++ b/frontend/src/app/plugins/grid.cljs @@ -13,6 +13,7 @@ [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.transforms :as dwt] [app.main.store :as st] + [app.plugins.format :as format] [app.plugins.utils :as u] [app.util.object :as obj] [potok.v2.core :as ptk])) @@ -20,12 +21,6 @@ ;; Define in `app.plugins.shape` we do this way to prevent circular dependency (def shape-proxy? nil) -(defn- make-tracks - [tracks] - (.freeze - js/Object - (apply array (->> tracks (map u/to-js))))) - (deftype GridLayout [$plugin $file $page $id] Object @@ -190,10 +185,10 @@ (st/emit! (dwsl/update-layout #{id} {:layout-grid-dir value}))))))} {:name "rows" - :get #(-> % u/proxy->shape :layout-grid-rows make-tracks)} + :get #(-> % u/proxy->shape :layout-grid-rows format/format-tracks)} {:name "columns" - :get #(-> % u/proxy->shape :layout-grid-columns make-tracks)} + :get #(-> % u/proxy->shape :layout-grid-columns format/format-tracks)} {:name "alignItems" :get #(-> % u/proxy->shape :layout-align-items d/name) diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index 6c46530eb..7c90146f5 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -22,7 +22,10 @@ [app.main.data.workspace.texts :as dwt] [app.main.repo :as rp] [app.main.store :as st] + [app.plugins.format :as format] + [app.plugins.parser :as parser] [app.plugins.shape :as shape] + [app.plugins.text :as text] [app.plugins.utils :as u] [app.util.object :as obj] [beicon.v2.core :as rx] @@ -49,27 +52,25 @@ (asFill [_] (let [color (u/locate-library-color $file $id)] - (u/to-js - (d/without-nils - {:fill-color (:color color) - :fill-opacity (:opacity color) - :fill-color-gradient (:gradient color) - :fill-color-ref-file $file - :fill-color-ref-id $id - :fill-image (:image color)})))) + (format/format-fill + {:fill-color (:color color) + :fill-opacity (:opacity color) + :fill-color-gradient (:gradient color) + :fill-color-ref-file $file + :fill-color-ref-id $id + :fill-image (:image color)}))) (asStroke [_] (let [color (u/locate-library-color $file $id)] - (u/to-js - (d/without-nils - {:stroke-color (:color color) - :stroke-opacity (:opacity color) - :stroke-color-gradient (:gradient color) - :stroke-color-ref-file $file - :stroke-color-ref-id $id - :stroke-image (:image color) - :stroke-style :solid - :stroke-alignment :inner})))) + (format/format-stroke + {:stroke-color (:color color) + :stroke-opacity (:opacity color) + :stroke-color-gradient (:gradient color) + :stroke-color-ref-file $file + :stroke-color-ref-id $id + :stroke-image (:image color) + :stroke-style :solid + :stroke-alignment :inner}))) (getPluginData [self key] @@ -211,10 +212,10 @@ (st/emit! (dwl/update-color color file-id)))))} {:name "gradient" - :get #(-> % u/proxy->library-color :gradient u/to-js) + :get #(-> % u/proxy->library-color :gradient format/format-gradient) :set (fn [self value] - (let [value (u/from-js value)] + (let [value (parser/parse-gradient value)] (cond (not (sm/validate ::ctc/gradient value)) (u/display-not-valid :library-color-gradient value) @@ -225,10 +226,10 @@ (st/emit! (dwl/update-color color file-id))))))} {:name "image" - :get #(-> % u/proxy->library-color :image u/to-js) + :get #(-> % u/proxy->library-color :image format/format-image) :set (fn [self value] - (let [value (u/from-js value)] + (let [value (parser/parse-image-data value)] (cond (not (sm/validate ::ctc/image-color value)) (u/display-not-valid :library-color-image value) @@ -266,7 +267,7 @@ (applyToTextRange [self range] (cond - (not (shape/text-range? range)) + (not (text/text-range? range)) (u/display-not-valid :applyToText range) :else diff --git a/frontend/src/app/plugins/page.cljs b/frontend/src/app/plugins/page.cljs index 91da5bb0c..66ff1877f 100644 --- a/frontend/src/app/plugins/page.cljs +++ b/frontend/src/app/plugins/page.cljs @@ -13,9 +13,11 @@ [app.common.uuid :as uuid] [app.main.data.workspace :as dw] [app.main.store :as st] + [app.plugins.parser :as parser] [app.plugins.shape :as shape] [app.plugins.utils :as u] - [app.util.object :as obj])) + [app.util.object :as obj] + [cuerdas.core :as str])) (deftype PageProxy [$plugin $file $id] Object @@ -34,11 +36,28 @@ (shape/shape-proxy $plugin $file $id uuid/zero)) (findShapes - [_] + [_ criteria] ;; Returns a lazy (iterable) of all available shapes - (when (and (some? $file) (some? $id)) - (let [page (u/locate-page $file $id)] - (apply array (sequence (map (partial shape/shape-proxy $plugin)) (keys (:objects page))))))) + (let [criteria (parser/parse-criteria criteria) + match-criteria? + (if (some? criteria) + (fn [[_ shape]] + (and + (or (not (:name criteria)) + (= (str/lower (:name criteria)) (str/lower (:name shape)))) + + (or (not (:name-like criteria)) + (str/includes? (str/lower (:name shape)) (str/lower (:name-like criteria)))) + + (or (not (:type criteria)) + (= (:type criteria) (:type shape))))) + identity)] + (when (and (some? $file) (some? $id)) + (let [page (u/locate-page $file $id) + xf (comp + (filter match-criteria?) + (map #(shape/shape-proxy $plugin $file $id (first %))))] + (apply array (sequence xf (:objects page))))))) ;; Plugin data (getPluginData diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs index 0b12c9643..3180a0e4b 100644 --- a/frontend/src/app/plugins/parser.cljs +++ b/frontend/src/app/plugins/parser.cljs @@ -21,7 +21,29 @@ (defn parse-hex [color] - (when color (-> color str/lower))) + (if (string? color) (-> color str/lower) color)) + +;; { +;; name?: string; +;; nameLike?: string; +;; type?: +;; | 'frame' +;; | 'group' +;; | 'bool' +;; | 'rect' +;; | 'path' +;; | 'text' +;; | 'circle' +;; | 'svg-raw' +;; | 'image'; +;; } +(defn parse-criteria + [^js criteria] + (when (some? criteria) + (d/without-nils + {:name (obj/get criteria "name") + :name-like (obj/get criteria "nameLike") + :type (-> (obj/get criteria "type") parse-keyword)}))) ;;export type PenpotImageData = { ;; name?: string; @@ -33,7 +55,7 @@ ;;} (defn parse-image-data [^js image-data] - (when image-data + (when (some? image-data) (d/without-nils {:id (-> (obj/get image-data "id") parse-id) :name (obj/get image-data "name") @@ -53,7 +75,7 @@ ;; } (defn parse-gradient-stop [^js stop] - (when stop + (when (some? stop) (d/without-nils {:color (-> (obj/get stop "color") parse-hex) :opacity (obj/get stop "opacity") @@ -61,7 +83,7 @@ (defn parse-gradient [^js gradient] - (when gradient + (when (some? gradient) (d/without-nils {:type (-> (obj/get gradient "type") parse-keyword) :start-x (obj/get gradient "startX") @@ -85,7 +107,7 @@ ;; } (defn parse-color [^js color] - (when color + (when (some? color) (d/without-nils {:id (-> (obj/get color "id") parse-id) :name (obj/get color "name") @@ -96,3 +118,279 @@ :ref-file (-> (obj/get color "refFile") parse-id) :gradient (-> (obj/get color "gradient") parse-gradient) :image (-> (obj/get color "image") parse-image-data)}))) + +;; export interface PenpotShadow { +;; id?: string; +;; style?: 'drop-shadow' | 'inner-shadow'; +;; offsetX?: number; +;; offsetY?: number; +;; blur?: number; +;; spread?: number; +;; hidden?: boolean; +;; color?: PenpotColor; +;; } +(defn parse-shadow + [^js shadow] + (when (some? shadow) + (d/without-nils + {:id (-> (obj/get shadow "id") parse-id) + :style (-> (obj/get shadow "style") parse-keyword) + :offset-x (obj/get shadow "offsetX") + :offset-y (obj/get shadow "offsetY") + :blur (obj/get shadow "blur") + :spread (obj/get shadow "spread") + :hidden (obj/get shadow "hidden") + :color (-> (obj/get shadow "color") parse-color)}))) + +(defn parse-shadows + [^js shadows] + (when (some? shadows) + (into [] (map parse-shadow) shadows))) + +;;export interface PenpotFill { +;; fillColor?: string; +;; fillOpacity?: number; +;; fillColorGradient?: PenpotGradient; +;; fillColorRefFile?: string; +;; fillColorRefId?: string; +;; fillImage?: PenpotImageData; +;;} +(defn parse-fill + [^js fill] + (when (some? fill) + (d/without-nils + {:fill-color (-> (obj/get fill "fillColor") parse-hex) + :fill-opacity (obj/get fill "fillOpacity") + :fill-color-gradient (-> (obj/get fill "fillColorGradient") parse-gradient) + :fill-color-ref-file (-> (obj/get fill "fillColorRefFile") parse-id) + :fill-color-ref-id (-> (obj/get fill "fillColorRefId") parse-id) + :fill-image (-> (obj/get fill "fillImage") parse-image-data)}))) + +(defn parse-fills + [^js fills] + (when (some? fills) + (into [] (map parse-fill) fills))) + +;; export interface PenpotStroke { +;; strokeColor?: string; +;; strokeColorRefFile?: string; +;; strokeColorRefId?: string; +;; strokeOpacity?: number; +;; strokeStyle?: 'solid' | 'dotted' | 'dashed' | 'mixed' | 'none' | 'svg'; +;; strokeWidth?: number; +;; strokeAlignment?: 'center' | 'inner' | 'outer'; +;; strokeCapStart?: PenpotStrokeCap; +;; strokeCapEnd?: PenpotStrokeCap; +;; strokeColorGradient?: PenpotGradient; +;; } +(defn parse-stroke + [^js stroke] + (when (some? stroke) + (d/without-nils + {:stroke-color (-> (obj/get stroke "strokeColor") parse-hex) + :stroke-color-ref-file (-> (obj/get stroke "strokeColorRefFile") parse-id) + :stroke-color-ref-id (-> (obj/get stroke "strokeColorRefId") parse-id) + :stroke-opacity (obj/get stroke "strokeOpacity") + :stroke-style (-> (obj/get stroke "strokeStyle") parse-keyword) + :stroke-width (obj/get stroke "strokeWidth") + :stroke-alignment (-> (obj/get stroke "strokeAlignment") parse-keyword) + :stroke-cap-start (-> (obj/get stroke "strokeCapStart") parse-keyword) + :stroke-cap-end (-> (obj/get stroke "strokeCapEnd") parse-keyword) + :stroke-color-gradient (-> (obj/get stroke "strokeColorGradient") parse-gradient)}))) + +(defn parse-strokes + [^js strokes] + (when (some? strokes) + (into [] (map parse-stroke) strokes))) + +;; export interface PenpotBlur { +;; id?: string; +;; type?: 'layer-blur'; +;; value?: number; +;; hidden?: boolean; +;; } +(defn parse-blur + [^js blur] + (when (some? blur) + (d/without-nils + {:id (-> (obj/get blur "id") parse-id) + :type (-> (obj/get blur "type") parse-keyword) + :value (obj/get blur "value") + :hidden (obj/get blur "hidden")}))) + + +;; export interface PenpotExport { +;; type: 'png' | 'jpeg' | 'svg' | 'pdf'; +;; scale: number; +;; suffix: string; +;; } +(defn parse-export + [^js export] + (when (some? export) + (d/without-nils + {:type (-> (obj/get export "type") parse-keyword) + :scale (obj/get export "scale") + :suffix (obj/get export "suffix")}))) + +(defn parse-exports + [^js exports] + (when (some? exports) + (into [] (map parse-export) exports))) + +;; export interface PenpotFrameGuideColumnParams { +;; color: { color: string; opacity: number }; +;; type?: 'stretch' | 'left' | 'center' | 'right'; +;; size?: number; +;; margin?: number; +;; itemLength?: number; +;; gutter?: number; +;; } +(defn parse-frame-guide-column-params + [^js params] + (when params + (d/without-nils + {:color (-> (obj/get params "color") parse-color) + :type (-> (obj/get params "type") parse-keyword) + :size (obj/get params "size") + :margin (obj/get params "margin") + :item-length (obj/get params "itemLength") + :gutter (obj/get params "gutter")}))) + +;; export interface PenpotFrameGuideColumn { +;; type: 'column'; +;; display: boolean; +;; params: PenpotFrameGuideColumnParams; +;; } +(defn parse-frame-guide-column + [^js guide] + (when guide + (d/without-nils + {:type (-> (obj/get guide "type") parse-keyword) + :display (obj/get guide "display") + :params (-> (obj/get guide "params") parse-frame-guide-column-params)}))) + +;; export interface PenpotFrameGuideRow { +;; type: 'row'; +;; display: boolean; +;; params: PenpotFrameGuideColumnParams; +;; } + +(defn parse-frame-guide-row + [^js guide] + (when guide + (d/without-nils + {:type (-> (obj/get guide "type") parse-keyword) + :display (obj/get guide "display") + :params (-> (obj/get guide "params") parse-frame-guide-column-params)}))) + +;;export interface PenpotFrameGuideSquareParams { +;; color: { color: string; opacity: number }; +;; size?: number; +;;} +(defn parse-frame-guide-square-params + [^js params] + (when (some? params) + (d/without-nils + {:color (-> (obj/get params "color") parse-color) + :size (obj/get params "size")}))) + +;; export interface PenpotFrameGuideSquare { +;; type: 'square'; +;; display: boolean; +;; params: PenpotFrameGuideSquareParams; +;; } +(defn parse-frame-guide-square + [^js guide] + (when guide + (d/without-nils + {:type (-> (obj/get guide "type") parse-keyword) + :display (obj/get guide "display") + :params (-> (obj/get guide "params") parse-frame-guide-column-params)}))) + +(defn parse-frame-guide + [^js guide] + (when (some? guide) + (case (obj/get guide "type") + "column" + parse-frame-guide-column + + "row" + parse-frame-guide-row + + "square" + (parse-frame-guide-square guide)))) + +(defn parse-frame-guides + [^js guides] + (when (some? guides) + (into [] (map parse-frame-guide) guides))) + +;;interface PenpotPathCommand { +;; command: +;; | 'M' | 'move-to' +;; | 'Z' | 'close-path' +;; | 'L' | 'line-to' +;; | 'H' | 'line-to-horizontal' +;; | 'V' | 'line-to-vertical' +;; | 'C' | 'curve-to' +;; | 'S' | 'smooth-curve-to' +;; | 'Q' | 'quadratic-bezier-curve-to' +;; | 'T' | 'smooth-quadratic-bezier-curve-to' +;; | 'A' | 'elliptical-arc'; +;; +;; params?: { +;; x?: number; +;; y?: number; +;; c1x: number; +;; c1y: number; +;; c2x: number; +;; c2y: number; +;; rx?: number; +;; ry?: number; +;; xAxisRotation?: number; +;; largeArcFlag?: boolean; +;; sweepFlag?: boolean; +;; }; +;;} +(defn parse-command-type + [^string command-type] + (case command-type + "M" :move-to + "Z" :close-path + "L" :line-to + "H" :line-to-horizontal + "V" :line-to-vertical + "C" :curve-to + "S" :smooth-curve-to + "Q" :quadratic-bezier-curve-to + "T" :smooth-quadratic-bezier-curve-to + "A" :elliptical-arc + (parse-keyword command-type))) + +(defn parse-command-params + [^js params] + (when (some? params) + (d/without-nils + {:x (obj/get params "x") + :y (obj/get params "y") + :c1x (obj/get params "c1x") + :c1y (obj/get params "c1y") + :c2x (obj/get params "c2x") + :c2y (obj/get params "c2y") + :rx (obj/get params "rx") + :ry (obj/get params "ry") + :x-axis-rotation (obj/get params "xAxisRotation") + :large-arc-flag (obj/get params "largeArcFlag") + :sweep-flag (obj/get params "sweepFlag")}))) + +(defn parse-command + [^js command] + (when (some? command) + (d/without-nils + {:command (-> (obj/get command "command") parse-command-type) + :params (-> (obj/get command "paras") parse-command-params)}))) + +(defn parse-path-content + [^js content] + (when (some? content) + (into [] (map parse-command) content))) diff --git a/frontend/src/app/plugins/public_utils.cljs b/frontend/src/app/plugins/public_utils.cljs index 4ea08fa57..d3ed6a46e 100644 --- a/frontend/src/app/plugins/public_utils.cljs +++ b/frontend/src/app/plugins/public_utils.cljs @@ -9,6 +9,7 @@ (:require [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] + [app.plugins.format :as format] [app.plugins.shape :as shape] [app.plugins.utils :as u])) @@ -22,4 +23,4 @@ (let [shapes (->> shapes (map u/proxy->shape))] (-> (gsh/shapes->rect shapes) (grc/rect->center) - (u/to-js))))) + (format/format-point))))) diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index 47312f016..fb5a88ff6 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -38,243 +38,18 @@ [app.main.data.workspace.texts :as dwt] [app.main.store :as st] [app.plugins.flex :as flex] + [app.plugins.format :as format] [app.plugins.grid :as grid] + [app.plugins.parser :as parser] + [app.plugins.text :as text] [app.plugins.utils :as u] [app.util.object :as obj] [app.util.path.format :as upf] - [app.util.text-editor :as ted] [cuerdas.core :as str])) (def lib-typography-proxy? nil) (def lib-component-proxy nil) -(deftype TextRange [$plugin $file $page $id start end] - Object - (applyTypography [_ typography] - (let [typography (u/proxy->library-typography typography) - attrs (-> typography - (assoc :typography-ref-file $file) - (assoc :typography-ref-id (:id typography)) - (dissoc :id :name))] - (st/emit! (dwt/update-text-range $id start end attrs))))) - -(defn mixed-value - [values] - (let [s (set values)] - (if (= (count s) 1) (first s) "mixed"))) - -(defn text-range? - [range] - (instance? TextRange range)) - -(defn text-range - [plugin-id file-id page-id id start end] - (-> (TextRange. plugin-id file-id page-id id start end) - (crc/add-properties! - {:name "$plugin" :enumerable false :get (constantly plugin-id)} - {:name "$id" :enumerable false :get (constantly id)} - {:name "$file" :enumerable false :get (constantly file-id)} - {:name "$page" :enumerable false :get (constantly page-id)} - - {:name "shape" - :get #(-> % u/proxy->shape)} - - {:name "characters" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :text) (str/join "")))} - - {:name "fontId" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-id) mixed-value)) - - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontId value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-id value}))))} - - {:name "fontFamily" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-family) mixed-value)) - - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontFamily value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-family value}))))} - - {:name "fontVariantId" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-variant-id) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontVariantId value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-variant-id value}))))} - - {:name "fontSize" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-size) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontSize value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-size value}))))} - - {:name "fontWeight" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-weight) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontWeight value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-weight value}))))} - - {:name "fontStyle" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :font-style) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontStyle value) - - :else - (st/emit! (dwt/update-text-range id start end {:font-style value}))))} - - {:name "lineHeight" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :line-height) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :lineHeight value) - - :else - (st/emit! (dwt/update-text-range id start end {:line-height value}))))} - - {:name "letterSpacing" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :letter-spacing) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :letterSpacing value) - - :else - (st/emit! (dwt/update-text-range id start end {:letter-spacing value}))))} - - {:name "textTransform" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :text-transform) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :textTransform value) - - :else - (st/emit! (dwt/update-text-range id start end {:text-transform value}))))} - - {:name "textDecoration" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :text-decoration) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :textDecoration value) - - :else - (st/emit! (dwt/update-text-range id start end {:text-decoration value}))))} - - {:name "direction" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :direction) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :direction value) - - :else - (st/emit! (dwt/update-text-range id start end {:direction value}))))} - - {:name "align" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :text-align) mixed-value)) - :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :text-align value) - - :else - (st/emit! (dwt/update-text-range id start end {:text-align value}))))} - - {:name "fills" - :get #(let [range-data - (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] - (->> range-data (map :fills) mixed-value u/array-to-js)) - :set - (fn [_ value] - (let [value (mapv #(u/from-js %) value)] - (cond - (not (sm/validate [:vector ::cts/fill] value)) - (u/display-not-valid :fills value) - - :else - (st/emit! (dwt/update-text-range id start end {:fills value})))))}))) - -(declare shape-proxy) - -(defn parse-command - [entry] - (update entry - :command - #(case % - "M" :move-to - "Z" :close-path - "L" :line-to - "H" :line-to-horizontal - "V" :line-to-vertical - "C" :curve-to - "S" :smooth-curve-to - "Q" :quadratic-bezier-curve-to - "T" :smooth-quadratic-bezier-curve-to - "A" :elliptical-arc - (keyword %)))) - (defn text-props [shape] (d/merge @@ -282,6 +57,48 @@ (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}))) +(declare shape-proxy) +(declare shape-proxy?) + +#_(defn parse-command + [entry] + (update entry + :command + #(case % + "M" :move-to + "Z" :close-path + "L" :line-to + "H" :line-to-horizontal + "V" :line-to-vertical + "C" :curve-to + "S" :smooth-curve-to + "Q" :quadratic-bezier-curve-to + "T" :smooth-quadratic-bezier-curve-to + "A" :elliptical-arc + (keyword %)))) + +(defn- shadow-defaults + [shadow] + (d/patch-object + {:id (uuid/next) + :style :drop-shadow + :color {:color clr/black :opacity 0.2} + :offset-x 4 + :offset-y 4 + :blur 4 + :spread 0 + :hidden false} + shadow)) + +(defn- blur-defaults + [blur] + (d/patch-object + {:id (uuid/next) + :type :layer-blur + :value 4 + :hidden false} + blur)) + (deftype ShapeProxy [$plugin $file $page $id] Object (resize @@ -392,67 +209,107 @@ (getChildren [_] (let [shape (u/locate-shape $file $page $id)] - (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) - (apply array (->> (u/locate-shape $file $page $id) - :shapes - (map #(shape-proxy $plugin $file $page %)))) - (u/display-not-valid :getChildren (:type shape))))) + (cond + + (and (not (cfh/frame-shape? shape)) + (not (cfh/group-shape? shape)) + (not (cfh/svg-raw-shape? shape)) + (not (cfh/bool-shape? shape))) + (u/display-not-valid :getChildren (:type shape)) + + :else + (->> (u/locate-shape $file $page $id) + (:shapes) + (format/format-array #(shape-proxy $plugin $file $page %)))))) (appendChild [_ child] (let [shape (u/locate-shape $file $page $id)] - (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) + (cond + (and (not (cfh/frame-shape? shape)) + (not (cfh/group-shape? shape)) + (not (cfh/svg-raw-shape? shape)) + (not (cfh/bool-shape? shape))) + (u/display-not-valid :appendChild (:type shape)) + + (not (shape-proxy? child)) + (u/display-not-valid :appendChild-child child) + + :else (let [child-id (obj/get child "$id")] - (st/emit! (dw/relocate-shapes #{child-id} $id 0))) - (u/display-not-valid :appendChild (:type shape))))) + (st/emit! (dw/relocate-shapes #{child-id} $id 0)))))) (insertChild [_ index child] (let [shape (u/locate-shape $file $page $id)] - (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) + (cond + (and (not (cfh/frame-shape? shape)) + (not (cfh/group-shape? shape)) + (not (cfh/svg-raw-shape? shape)) + (not (cfh/bool-shape? shape))) + (u/display-not-valid :insertChild (:type shape)) + + (not (shape-proxy? child)) + (u/display-not-valid :insertChild-child child) + + :else (let [child-id (obj/get child "$id")] - (st/emit! (dw/relocate-shapes #{child-id} $id index))) - (u/display-not-valid :insertChild (:type shape))))) + (st/emit! (dw/relocate-shapes #{child-id} $id index)))))) ;; Only for frames (addFlexLayout [_] (let [shape (u/locate-shape $file $page $id)] - (if (cfh/frame-shape? shape) + (cond + (not (cfh/frame-shape? shape)) + (u/display-not-valid :addFlexLayout (:type shape)) + + :else (do (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false)) - (grid/grid-layout-proxy $plugin $file $page $id)) - (u/display-not-valid :addFlexLayout (:type shape))))) + (grid/grid-layout-proxy $plugin $file $page $id))))) (addGridLayout [_] (let [shape (u/locate-shape $file $page $id)] - (if (cfh/frame-shape? shape) + (cond + (not (cfh/frame-shape? shape)) + (u/display-not-valid :addGridLayout (:type shape)) + + :else (do (st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false)) - (grid/grid-layout-proxy $plugin $file $page $id)) - (u/display-not-valid :addGridLayout (:type shape))))) + (grid/grid-layout-proxy $plugin $file $page $id))))) ;; Make masks for groups (makeMask [_] (let [shape (u/locate-shape $file $page $id)] - (if (cfh/group-shape? shape) - (st/emit! (dwg/mask-group #{$id})) - (u/display-not-valid :makeMask (:type shape))))) + (cond + (not (cfh/group-shape? shape)) + (u/display-not-valid :makeMask (:type shape)) + + :else + (st/emit! (dwg/mask-group #{$id}))))) (removeMask [_] (let [shape (u/locate-shape $file $page $id)] - (if (cfh/mask-shape? shape) - (st/emit! (dwg/unmask-group #{$id})) - (u/display-not-valid :removeMask (:type shape))))) + (cond + (not (cfh/mask-shape? shape)) + (u/display-not-valid :removeMask (:type shape)) + + :else + (st/emit! (dwg/unmask-group #{$id}))))) ;; Only for path and bool shapes (toD [_] (let [shape (u/locate-shape $file $page $id)] - (if (cfh/path-shape? shape) - (upf/format-path (:content shape)) - (u/display-not-valid :makeMask (:type shape))))) + (cond + (not (cfh/path-shape? shape)) + (u/display-not-valid :makeMask (:type shape)) + + :else + (upf/format-path (:content shape))))) ;; Text shapes (getRange @@ -469,7 +326,7 @@ (u/display-not-valid :getRange-end end) :else - (text-range $plugin $file $page $id start end)))) + (text/text-range $plugin $file $page $id start end)))) (applyTypography [_ typography] @@ -554,11 +411,6 @@ (let [[root component] (u/locate-component objects shape)] (lib-component-proxy $plugin (:component-file root) (:id component))))))) -(crc/define-properties! - ShapeProxy - {:name js/Symbol.toStringTag - :get (fn [] (str "ShapeProxy"))}) - (defn shape-proxy? [p] (instance? ShapeProxy p)) @@ -566,6 +418,11 @@ (do (set! flex/shape-proxy? shape-proxy?) (set! grid/shape-proxy? shape-proxy?)) +(crc/define-properties! + ShapeProxy + {:name js/Symbol.toStringTag + :get (fn [] (str "ShapeProxy"))}) + (defn shape-proxy ([plugin-id id] (shape-proxy plugin-id (:current-file-id @st/state) (:current-page-id @st/state) id)) @@ -782,23 +639,11 @@ (st/emit! (dwsh/update-shapes [id] #(assoc % :blend-mode value))))))} {:name "shadows" - :get #(-> % u/proxy->shape :shadow u/array-to-js) + :get #(-> % u/proxy->shape :shadow format/format-shadows) :set (fn [self value] (let [id (obj/get self "$id") - value (mapv (fn [val] - ;; Merge default shadow properties - (d/patch-object - {:id (uuid/next) - :style :drop-shadow - :color {:color clr/black :opacity 0.2} - :offset-x 4 - :offset-y 4 - :blur 4 - :spread 0 - :hidden false} - (u/from-js val #{:style :type}))) - value)] + value (mapv #(shadow-defaults (parser/parse-shadow %)) value)] (cond (not (sm/validate [:vector ::ctss/shadow] value)) (u/display-not-valid :shadows value) @@ -807,19 +652,13 @@ (st/emit! (dwsh/update-shapes [id] #(assoc % :shadow value))))))} {:name "blur" - :get #(-> % u/proxy->shape :blur u/to-js) + :get #(-> % u/proxy->shape :blur format/format-blur) :set (fn [self value] (if (nil? value) (st/emit! (dwsh/update-shapes [id] #(dissoc % :blur))) (let [id (obj/get self "$id") - value - (d/patch-object - {:id (uuid/next) - :type :layer-blur - :value 4 - :hidden false} - (u/from-js value))] + value (blur-defaults (parser/parse-blur value))] (cond (not (sm/validate ::ctsb/blur value)) (u/display-not-valid :blur value) @@ -828,11 +667,11 @@ (st/emit! (dwsh/update-shapes [id] #(assoc % :blur value)))))))} {:name "exports" - :get #(-> % u/proxy->shape :exports u/array-to-js) + :get #(-> % u/proxy->shape :exports format/format-exports) :set (fn [self value] (let [id (obj/get self "$id") - value (mapv #(u/from-js %) value)] + value (parser/parse-exports value)] (cond (not (sm/validate [:vector ::ctse/export] value)) (u/display-not-valid :exports value) @@ -989,13 +828,13 @@ ;; Strokes and fills {:name "fills" :get #(if (cfh/text-shape? data) - (-> % u/proxy->shape text-props :fills u/array-to-js) - (-> % u/proxy->shape :fills u/array-to-js)) + (-> % u/proxy->shape text-props :fills format/format-fills) + (-> % u/proxy->shape :fills format/format-fills)) :set (fn [self value] (let [shape (u/proxy->shape self) id (:id shape) - value (mapv #(u/from-js %) value)] + value (parser/parse-fills value)] (cond (not (sm/validate [:vector ::cts/fill] value)) (u/display-not-valid :fills value) @@ -1007,11 +846,11 @@ (st/emit! (dwsh/update-shapes [id] #(assoc % :fills value))))))} {:name "strokes" - :get #(-> % u/proxy->shape :strokes u/array-to-js) + :get #(-> % u/proxy->shape :strokes format/format-strokes) :set (fn [self value] (let [id (obj/get self "$id") - value (mapv #(u/from-js % #{:stroke-style :stroke-alignment}) value)] + value (parser/parse-strokes value)] (cond (not (sm/validate [:vector ::cts/stroke] value)) (u/display-not-valid :strokes value) @@ -1068,10 +907,10 @@ (flex/flex-layout-proxy plugin-id file-id page-id id))))} {:name "guides" - :get #(-> % u/proxy->shape :grids u/array-to-js) + :get #(-> % u/proxy->shape :grids format/format-frame-guides) :set (fn [self value] (let [id (obj/get self "$id") - value (mapv #(u/from-js %) value)] + value (parser/parse-frame-guides value)] (cond (not (sm/validate [:vector ::ctg/grid] value)) (u/display-not-valid :guides value) @@ -1105,213 +944,21 @@ :else (st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))}))) - (cond-> (cfh/text-shape? data) - (crc/add-properties! - {:name "characters" - :get #(-> % u/proxy->shape :content txt/content->text) - :set - (fn [self value] - (let [id (obj/get self "$id")] - ;; The user is currently editing the text. We need to update the - ;; editor as well - (cond - (or (not (string? value)) (empty? value)) - (u/display-not-valid :characters value) - - (contains? (:workspace-editor-state @st/state) id) - (let [shape (u/proxy->shape self) - editor - (-> shape - (txt/change-text value) - :content - ted/import-content - ted/create-editor-state)] - (st/emit! (dwt/update-editor-state shape editor))) - - :else - (st/emit! (dwsh/update-shapes [id] #(txt/change-text % value))))))} - - {:name "growType" - :get #(-> % u/proxy->shape :grow-type d/name) - :set - (fn [self value] - (let [id (obj/get self "$id") - value (keyword value)] - (cond - (not (contains? #{:auto-width :auto-height :fixed} value)) - (u/display-not-valid :growType value) - - :else - (st/emit! (dwsh/update-shapes [id] #(assoc % :grow-type value))))))} - - {:name "fontId" - :get #(-> % u/proxy->shape text-props :font-id) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontId value) - - :else - (st/emit! (dwt/update-attrs id {:font-id value})))))} - - {:name "fontFamily" - :get #(-> % u/proxy->shape text-props :font-family) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontFamily value) - - :else - (st/emit! (dwt/update-attrs id {:font-family value})))))} - - {:name "fontVariantId" - :get #(-> % u/proxy->shape text-props :font-variant-id) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontVariantId value) - - :else - (st/emit! (dwt/update-attrs id {:font-variant-id value})))))} - - {:name "fontSize" - :get #(-> % u/proxy->shape text-props :font-size) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontSize value) - - :else - (st/emit! (dwt/update-attrs id {:font-size value})))))} - - {:name "fontWeight" - :get #(-> % u/proxy->shape text-props :font-weight) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontWeight value) - - :else - (st/emit! (dwt/update-attrs id {:font-weight value})))))} - - {:name "fontStyle" - :get #(-> % u/proxy->shape text-props :font-style) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :fontStyle value) - - :else - (st/emit! (dwt/update-attrs id {:font-style value})))))} - - {:name "lineHeight" - :get #(-> % u/proxy->shape text-props :line-height) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :lineHeight value) - - :else - (st/emit! (dwt/update-attrs id {:line-height value})))))} - - {:name "letterSpacing" - :get #(-> % u/proxy->shape text-props :letter-spacing) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :letterSpacing value) - - :else - (st/emit! (dwt/update-attrs id {:letter-spacing value})))))} - - {:name "textTransform" - :get #(-> % u/proxy->shape text-props :text-transform) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :textTransform value) - - :else - (st/emit! (dwt/update-attrs id {:text-transform value})))))} - - {:name "textDecoration" - :get #(-> % u/proxy->shape text-props :text-decoration) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :textDecoration value) - - :else - (st/emit! (dwt/update-attrs id {:text-decoration value})))))} - - {:name "direction" - :get #(-> % u/proxy->shape text-props :text-direction) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :textDecoration value) - - :else - (st/emit! (dwt/update-attrs id {:text-decoration value})))))} - - {:name "align" - :get #(-> % u/proxy->shape text-props :text-align) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :align value) - - :else - (st/emit! (dwt/update-attrs id {:text-align value})))))} - - {:name "verticalAlign" - :get #(-> % u/proxy->shape text-props :vertical-align) - :set - (fn [self value] - (let [id (obj/get self "$id")] - (cond - (not (string? value)) - (u/display-not-valid :verticalAlign value) - - :else - (st/emit! (dwt/update-attrs id {:vertical-align value})))))})) + (cond-> (cfh/text-shape? data) (text/add-text-props)) (cond-> (or (cfh/path-shape? data) (cfh/bool-shape? data)) (crc/add-properties! {:name "content" - :get #(-> % u/proxy->shape :content u/array-to-js) + :get #(-> % u/proxy->shape :content format/format-path-content) :set (fn [_ value] (let [content - (->> value - (map u/from-js) - (mapv parse-command) + (->> (parser/parse-path-content value) (spp/simplify-commands))] (cond + (not (cfh/path-shape? data)) + (u/display-not-valid :content-type type) + (not (sm/validate ::ctsp/content content)) (u/display-not-valid :content value) diff --git a/frontend/src/app/plugins/text.cljs b/frontend/src/app/plugins/text.cljs new file mode 100644 index 000000000..5a05ebaaf --- /dev/null +++ b/frontend/src/app/plugins/text.cljs @@ -0,0 +1,434 @@ +;; 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) KALEIDOS INC + +(ns app.plugins.text + (:require + [app.common.data :as d] + [app.common.record :as crc] + [app.common.schema :as sm] + [app.common.text :as txt] + [app.common.types.shape :as cts] + [app.main.data.workspace.shapes :as dwsh] + [app.main.data.workspace.texts :as dwt] + [app.main.store :as st] + [app.plugins.format :as format] + [app.plugins.parser :as parser] + [app.plugins.utils :as u] + [app.util.object :as obj] + [app.util.text-editor :as ted] + [cuerdas.core :as str])) + +(defn mixed-value + [values] + (let [s (set values)] + (if (= (count s) 1) (first s) "mixed"))) + +(deftype TextRange [$plugin $file $page $id start end] + Object + (applyTypography [_ typography] + (let [typography (u/proxy->library-typography typography) + attrs (-> typography + (assoc :typography-ref-file $file) + (assoc :typography-ref-id (:id typography)) + (dissoc :id :name))] + (st/emit! (dwt/update-text-range $id start end attrs))))) + +(defn text-range? + [range] + (instance? TextRange range)) + +(defn text-props + [shape] + (d/merge + (dwt/current-root-values {:shape shape :attrs txt/root-attrs}) + (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) + (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}))) + +(defn text-range + [plugin-id file-id page-id id start end] + (-> (TextRange. plugin-id file-id page-id id start end) + (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} + {:name "$id" :enumerable false :get (constantly id)} + {:name "$file" :enumerable false :get (constantly file-id)} + {:name "$page" :enumerable false :get (constantly page-id)} + + {:name "shape" + :get #(-> % u/proxy->shape)} + + {:name "characters" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :text) (str/join "")))} + + {:name "fontId" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-id) mixed-value)) + + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontId value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-id value}))))} + + {:name "fontFamily" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-family) mixed-value)) + + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontFamily value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-family value}))))} + + {:name "fontVariantId" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-variant-id) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontVariantId value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-variant-id value}))))} + + {:name "fontSize" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-size) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontSize value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-size value}))))} + + {:name "fontWeight" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-weight) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontWeight value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-weight value}))))} + + {:name "fontStyle" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :font-style) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :fontStyle value) + + :else + (st/emit! (dwt/update-text-range id start end {:font-style value}))))} + + {:name "lineHeight" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :line-height) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :lineHeight value) + + :else + (st/emit! (dwt/update-text-range id start end {:line-height value}))))} + + {:name "letterSpacing" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :letter-spacing) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :letterSpacing value) + + :else + (st/emit! (dwt/update-text-range id start end {:letter-spacing value}))))} + + {:name "textTransform" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :text-transform) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :textTransform value) + + :else + (st/emit! (dwt/update-text-range id start end {:text-transform value}))))} + + {:name "textDecoration" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :text-decoration) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :textDecoration value) + + :else + (st/emit! (dwt/update-text-range id start end {:text-decoration value}))))} + + {:name "direction" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :direction) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :direction value) + + :else + (st/emit! (dwt/update-text-range id start end {:direction value}))))} + + {:name "align" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :text-align) mixed-value)) + :set + (fn [_ value] + (cond + (not (string? value)) + (u/display-not-valid :text-align value) + + :else + (st/emit! (dwt/update-text-range id start end {:text-align value}))))} + + {:name "fills" + :get #(let [range-data + (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] + (->> range-data (map :fills) mixed-value format/format-fills)) + :set + (fn [_ value] + (let [value (parser/parse-fills value)] + (cond + (not (sm/validate [:vector ::cts/fill] value)) + (u/display-not-valid :fills value) + + :else + (st/emit! (dwt/update-text-range id start end {:fills value})))))}))) + +(defn add-text-props + [shape-proxy] + (crc/add-properties! + shape-proxy + {:name "characters" + :get #(-> % u/proxy->shape :content txt/content->text) + :set + (fn [self value] + (let [id (obj/get self "$id")] + ;; The user is currently editing the text. We need to update the + ;; editor as well + (cond + (or (not (string? value)) (empty? value)) + (u/display-not-valid :characters value) + + (contains? (:workspace-editor-state @st/state) id) + (let [shape (u/proxy->shape self) + editor + (-> shape + (txt/change-text value) + :content + ted/import-content + ted/create-editor-state)] + (st/emit! (dwt/update-editor-state shape editor))) + + :else + (st/emit! (dwsh/update-shapes [id] #(txt/change-text % value))))))} + + {:name "growType" + :get #(-> % u/proxy->shape :grow-type d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (cond + (not (contains? #{:auto-width :auto-height :fixed} value)) + (u/display-not-valid :growType value) + + :else + (st/emit! (dwsh/update-shapes [id] #(assoc % :grow-type value))))))} + + {:name "fontId" + :get #(-> % u/proxy->shape text-props :font-id) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontId value) + + :else + (st/emit! (dwt/update-attrs id {:font-id value})))))} + + {:name "fontFamily" + :get #(-> % u/proxy->shape text-props :font-family) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontFamily value) + + :else + (st/emit! (dwt/update-attrs id {:font-family value})))))} + + {:name "fontVariantId" + :get #(-> % u/proxy->shape text-props :font-variant-id) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontVariantId value) + + :else + (st/emit! (dwt/update-attrs id {:font-variant-id value})))))} + + {:name "fontSize" + :get #(-> % u/proxy->shape text-props :font-size) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontSize value) + + :else + (st/emit! (dwt/update-attrs id {:font-size value})))))} + + {:name "fontWeight" + :get #(-> % u/proxy->shape text-props :font-weight) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontWeight value) + + :else + (st/emit! (dwt/update-attrs id {:font-weight value})))))} + + {:name "fontStyle" + :get #(-> % u/proxy->shape text-props :font-style) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :fontStyle value) + + :else + (st/emit! (dwt/update-attrs id {:font-style value})))))} + + {:name "lineHeight" + :get #(-> % u/proxy->shape text-props :line-height) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :lineHeight value) + + :else + (st/emit! (dwt/update-attrs id {:line-height value})))))} + + {:name "letterSpacing" + :get #(-> % u/proxy->shape text-props :letter-spacing) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :letterSpacing value) + + :else + (st/emit! (dwt/update-attrs id {:letter-spacing value})))))} + + {:name "textTransform" + :get #(-> % u/proxy->shape text-props :text-transform) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :textTransform value) + + :else + (st/emit! (dwt/update-attrs id {:text-transform value})))))} + + {:name "textDecoration" + :get #(-> % u/proxy->shape text-props :text-decoration) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :textDecoration value) + + :else + (st/emit! (dwt/update-attrs id {:text-decoration value})))))} + + {:name "direction" + :get #(-> % u/proxy->shape text-props :text-direction) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :textDecoration value) + + :else + (st/emit! (dwt/update-attrs id {:text-decoration value})))))} + + {:name "align" + :get #(-> % u/proxy->shape text-props :text-align) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :align value) + + :else + (st/emit! (dwt/update-attrs id {:text-align value})))))} + + {:name "verticalAlign" + :get #(-> % u/proxy->shape text-props :vertical-align) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (cond + (not (string? value)) + (u/display-not-valid :verticalAlign value) + + :else + (st/emit! (dwt/update-attrs id {:vertical-align value})))))})) diff --git a/frontend/src/app/plugins/user.cljs b/frontend/src/app/plugins/user.cljs index 42cd32f6e..220a5e08c 100644 --- a/frontend/src/app/plugins/user.cljs +++ b/frontend/src/app/plugins/user.cljs @@ -8,6 +8,7 @@ (:require [app.common.record :as crc] [app.config :as cfg] + [app.plugins.format :as format] [app.plugins.utils :as u] [app.util.object :as obj])) @@ -54,5 +55,5 @@ (-> (ActiveUserProxy. plugin-id session-id) (add-user-properties) (crc/add-properties! - {:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point u/to-js))} + {:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point format/format-point))} {:name "zoom" :get (fn [_] (-> (u/locate-presence session-id) :zoom))}))) diff --git a/frontend/src/app/plugins/utils.cljs b/frontend/src/app/plugins/utils.cljs index ab3015a0b..4df6207d8 100644 --- a/frontend/src/app/plugins/utils.cljs +++ b/frontend/src/app/plugins/utils.cljs @@ -9,13 +9,10 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.spec :as us] [app.common.types.container :as ctn] [app.common.types.file :as ctf] - [app.common.uuid :as uuid] [app.main.store :as st] [app.util.object :as obj] - [cuerdas.core :as str] [promesa.core :as p])) (defn locate-file @@ -143,58 +140,6 @@ (-> (get-state self attr) (mapfn)))) -(defn from-js - "Converts the object back to js" - ([obj] - (from-js obj #{:type})) - ([obj keyword-keys] - (when (some? obj) - (let [process-node - (fn process-node [node] - (reduce-kv - (fn [m k v] - (let [k (keyword (str/kebab k)) - v (cond (map? v) - (process-node v) - - (vector? v) - (mapv process-node v) - - (and (string? v) (re-matches us/uuid-rx v)) - (uuid/uuid v) - - (contains? keyword-keys k) - (keyword v) - - :else v)] - (assoc m k v))) - {} - node))] - (process-node (js->clj obj)))))) - -(defn to-js - "Converts to javascript an camelize the keys" - [obj] - (when (some? obj) - (let [result - (reduce-kv - (fn [m k v] - (let [v (cond (object? v) (to-js v) - (uuid? v) (dm/str v) - :else v)] - (assoc m (str/camel (name k)) v))) - {} - obj)] - (clj->js result)))) - -(defn array-to-js - [value] - (if (coll? value) - (.freeze - js/Object - (apply array (->> value (map to-js)))) - value)) - (defn result-p "Creates a pair of atom+promise. The promise will be resolved when the atom gets a value. We use this to return the promise to the library clients and resolve its value when a value is passed diff --git a/frontend/src/app/plugins/viewport.cljs b/frontend/src/app/plugins/viewport.cljs index c42696641..6973f33f7 100644 --- a/frontend/src/app/plugins/viewport.cljs +++ b/frontend/src/app/plugins/viewport.cljs @@ -14,6 +14,7 @@ [app.main.data.workspace.viewport :as dwv] [app.main.data.workspace.zoom :as dwz] [app.main.store :as st] + [app.plugins.format :as format] [app.plugins.utils :as u] [app.util.object :as obj])) @@ -88,6 +89,6 @@ :get (fn [_] (let [vport (dm/get-in @st/state [:workspace-local :vport])] - (.freeze js/Object (clj->js vport))))})) + (.freeze js/Object (format/format-bounds vport))))})) diff --git a/frontend/src/app/util/object.cljs b/frontend/src/app/util/object.cljs index 620303add..30962acc5 100644 --- a/frontend/src/app/util/object.cljs +++ b/frontend/src/app/util/object.cljs @@ -156,3 +156,8 @@ x) :else x))) + +(defn clear-empty + [^js obj] + (when (some? obj) + (js* "Object.entries(~{}).reduce((a, [k,v]) => (v == null ? a : (a[k]=v, a)), {}) " obj))) diff --git a/frontend/test/frontend_tests/plugins/context_shapes_test.cljs b/frontend/test/frontend_tests/plugins/context_shapes_test.cljs index ced9fff4b..e5e85a326 100644 --- a/frontend/test/frontend_tests/plugins/context_shapes_test.cljs +++ b/frontend/test/frontend_tests/plugins/context_shapes_test.cljs @@ -162,9 +162,8 @@ :offset-y 4 :blur 4 :spread 0 - :color {:color "#FABADA" :opacity 1} + :color {:color "#fabada" :opacity 1} :hidden false}])))) - (let [shadow #js {:style "fail"}] (set! (.-shadows shape) #js [shadow]) (t/is (= (-> (. shape -shadows) (aget 0) (aget "style")) "drop-shadow")))) @@ -208,20 +207,20 @@ (t/testing " - fills" (set! (.-fills shape) #js [#js {:fillColor 100}]) - (t/is (= (-> (. shape -fills) (aget 0) (aget "fillColor")) "#B1B2B5")) (t/is (= (get-in @store (get-shape-path :fills)) [{:fill-color "#B1B2B5" :fill-opacity 1}])) + (t/is (= (-> (. shape -fills) (aget 0) (aget "fillColor")) "#B1B2B5")) - (set! (.-fills shape) #js [#js {:fillColor "#FABADA" :fillOpacity 1}]) - (t/is (= (-> (. shape -fills) (aget 0) (aget "fillColor")) "#FABADA")) - (t/is (= (-> (. shape -fills) (aget 0) (aget "fillOpacity")) 1)) - (t/is (= (get-in @store (get-shape-path :fills)) [{:fill-color "#FABADA" :fill-opacity 1}]))) + (set! (.-fills shape) #js [#js {:fillColor "#fabada" :fillOpacity 1}]) + (t/is (= (get-in @store (get-shape-path :fills)) [{:fill-color "#fabada" :fill-opacity 1}])) + (t/is (= (-> (. shape -fills) (aget 0) (aget "fillColor")) "#fabada")) + (t/is (= (-> (. shape -fills) (aget 0) (aget "fillOpacity")) 1))) (t/testing " - strokes" - (set! (.-fills shape) #js [#js {:strokeColor "#FABADA" :strokeOpacity 1 :stroke-width 5}]) - (t/is (= (-> (. shape -fills) (aget 0) (aget "strokeColor")) "#FABADA")) - (t/is (= (-> (. shape -fills) (aget 0) (aget "strokeOpacity")) 1)) - (t/is (= (-> (. shape -fills) (aget 0) (aget "strokeWidth")) 5)) - (t/is (= (get-in @store (get-shape-path :fills)) [{:stroke-color "#FABADA" :stroke-opacity 1 :stroke-width 5}])))) + (set! (.-strokes shape) #js [#js {:strokeColor "#fabada" :strokeOpacity 1 :strokeWidth 5}]) + (t/is (= (get-in @store (get-shape-path :strokes)) [{:stroke-color "#fabada" :stroke-opacity 1 :stroke-width 5}])) + (t/is (= (-> (. shape -strokes) (aget 0) (aget "strokeColor")) "#fabada")) + (t/is (= (-> (. shape -strokes) (aget 0) (aget "strokeOpacity")) 1)) + (t/is (= (-> (. shape -strokes) (aget 0) (aget "strokeWidth")) 5)))) (t/testing "Relative properties" (let [frame (.createFrame context)] From fbce59e81f6e4d9770f7f7222563a7e39e904f05 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 27 Jun 2024 15:17:32 +0200 Subject: [PATCH 3/6] :sparkles: Improved text handling in plugins --- frontend/src/app/main/fonts.cljs | 12 ++ frontend/src/app/plugins/fonts.cljs | 7 +- frontend/src/app/plugins/format.cljs | 17 +- frontend/src/app/plugins/text.cljs | 230 +++++++++++++++++---------- 4 files changed, 175 insertions(+), 91 deletions(-) diff --git a/frontend/src/app/main/fonts.cljs b/frontend/src/app/main/fonts.cljs index 31949e7fe..d563da84e 100644 --- a/frontend/src/app/main/fonts.cljs +++ b/frontend/src/app/main/fonts.cljs @@ -71,6 +71,13 @@ (defn get-font-data [id] (get @fontsdb id)) +(defn find-font-data [data] + (d/seek + (fn [font] + (= (select-keys font (keys data)) + data)) + (vals @fontsdb))) + (defn resolve-variants [id] (get-in @fontsdb [id :variants])) @@ -249,6 +256,11 @@ (or (d/seek #(= (:id %) font-variant-id) variants) (get-default-variant font))) +(defn find-variant + [{:keys [variants] :as font} variant-data] + (let [props (keys variant-data)] + (d/seek #(= (select-keys % props) variant-data) variants))) + ;; Font embedding functions (defn get-node-fonts "Extracts the fonts used by some node" diff --git a/frontend/src/app/plugins/fonts.cljs b/frontend/src/app/plugins/fonts.cljs index 74631e1a4..cc73ee4b1 100644 --- a/frontend/src/app/plugins/fonts.cljs +++ b/frontend/src/app/plugins/fonts.cljs @@ -19,6 +19,9 @@ (deftype PenpotFontVariant [name fontVariantId fontWeight fontStyle]) +(defn variant-proxy? [p] + (instance? PenpotFontVariant p)) + (deftype PenpotFont [name fontId fontFamily fontStyle fontVariantId fontWeight variants] Object @@ -60,13 +63,13 @@ (instance? PenpotFont p)) (defn font-proxy - [{:keys [id name variants] :as font}] + [{:keys [id family name variants] :as font}] (when (some? font) (let [default-variant (fonts/get-default-variant font)] (PenpotFont. name id - id + family (:style default-variant) (:id default-variant) (:weight default-variant) diff --git a/frontend/src/app/plugins/format.cljs b/frontend/src/app/plugins/format.cljs index 9df43773b..4f6047df3 100644 --- a/frontend/src/app/plugins/format.cljs +++ b/frontend/src/app/plugins/format.cljs @@ -23,6 +23,12 @@ (when (some? coll) (apply array (keep format-fn coll)))) +(defn format-mixed + [value] + (if (= value :multiple) + "mixed" + value)) + ;; export type PenpotPoint = { x: number; y: number }; (defn format-point [{:keys [x y] :as point}] @@ -183,7 +189,14 @@ (defn format-fills [fills] - (when (some? fills) + (cond + (= fills :multiple) + "mixed" + + (= fills "mixed") + "mixed" + + (some? fills) (format-array format-fill fills))) ;; export interface PenpotStroke { @@ -393,7 +406,7 @@ (format-array format-command content))) ;; export type PenpotTrackType = 'flex' | 'fixed' | 'percent' | 'auto'; -;; +;; ;; export interface PenpotTrack { ;; type: PenpotTrackType; ;; value: number | null; diff --git a/frontend/src/app/plugins/text.cljs b/frontend/src/app/plugins/text.cljs index 5a05ebaaf..05750c9bb 100644 --- a/frontend/src/app/plugins/text.cljs +++ b/frontend/src/app/plugins/text.cljs @@ -7,12 +7,14 @@ (ns app.plugins.text (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.record :as crc] [app.common.schema :as sm] [app.common.text :as txt] [app.common.types.shape :as cts] [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.texts :as dwt] + [app.main.fonts :as fonts] [app.main.store :as st] [app.plugins.format :as format] [app.plugins.parser :as parser] @@ -21,11 +23,39 @@ [app.util.text-editor :as ted] [cuerdas.core :as str])) +;; This regex seems duplicated but probably in the future when we support diferent units +;; this will need to reflect changes for each property + +(def font-size-re #"^\d*\.?\d*$") +(def line-height-re #"^\d*\.?\d*$") +(def letter-spacing-re #"^\d*\.?\d*$") +(def text-transform-re #"uppercase|capitalize|lowercase|none") +(def text-decoration-re #"underline|line-through|none") +(def text-direction-re #"ltr|rtl") +(def text-align-re #"left|center|right|justify") +(def vertical-align-re #"top|center|bottom") + (defn mixed-value [values] (let [s (set values)] (if (= (count s) 1) (first s) "mixed"))) +(defn font-data + [font variant] + (d/without-nils + {:font-id (:id font) + :font-family (:family font) + :font-variant-id (:id variant) + :font-style (:style variant) + :font-weight (:weight variant)})) + +(defn variant-data + [variant] + (d/without-nils + {:font-variant-id (:id variant) + :font-style (:style variant) + :font-weight (:weight variant)})) + (deftype TextRange [$plugin $file $page $id start end] Object (applyTypography [_ typography] @@ -71,12 +101,14 @@ :set (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontId value) + (let [font (when (string? value) (fonts/get-font-data value)) + variant (fonts/get-default-variant font)] + (cond + (not (some? font)) + (u/display-not-valid :fontId value) - :else - (st/emit! (dwt/update-text-range id start end {:font-id value}))))} + :else + (st/emit! (dwt/update-text-range id start end (font-data font variant))))))} {:name "fontFamily" :get #(let [range-data @@ -85,25 +117,29 @@ :set (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontFamily value) + (let [font (fonts/find-font-data {:font-family value}) + variant (fonts/get-default-variant font)] + (cond + (not (string? value)) + (u/display-not-valid :fontFamily value) - :else - (st/emit! (dwt/update-text-range id start end {:font-family value}))))} + :else + (st/emit! (dwt/update-text-range id start end (font-data font variant))))))} {:name "fontVariantId" :get #(let [range-data (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] (->> range-data (map :font-variant-id) mixed-value)) :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontVariantId value) + (fn [self value] + (let [font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/get-variant font value)] + (cond + (not (string? value)) + (u/display-not-valid :fontVariantId value) - :else - (st/emit! (dwt/update-text-range id start end {:font-variant-id value}))))} + :else + (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} {:name "fontSize" :get #(let [range-data @@ -111,38 +147,43 @@ (->> range-data (map :font-size) mixed-value)) :set (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontSize value) + (let [value (str/trim (dm/str value))] + (cond + (or (empty? value) (not (re-matches font-size-re value))) + (u/display-not-valid :fontSize value) - :else - (st/emit! (dwt/update-text-range id start end {:font-size value}))))} + :else + (st/emit! (dwt/update-text-range id start end {:font-size value})))))} {:name "fontWeight" :get #(let [range-data (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] (->> range-data (map :font-weight) mixed-value)) :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontWeight value) + (fn [self value] + (let [font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/find-variant font {:weight (dm/str value)})] + (cond + (nil? variant) + (u/display-not-valid :fontWeight (dm/str "Font weight '" value "' not supported for the current font")) - :else - (st/emit! (dwt/update-text-range id start end {:font-weight value}))))} + :else + (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} {:name "fontStyle" :get #(let [range-data (-> % u/proxy->shape :content (txt/content-range->text+styles start end))] (->> range-data (map :font-style) mixed-value)) :set - (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :fontStyle value) + (fn [self value] + (let [font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/find-variant font {:weight (dm/str value)})] + (cond + (nil? variant) + (u/display-not-valid :fontStyle (dm/str "Font style '" value "' not supported for the current font")) - :else - (st/emit! (dwt/update-text-range id start end {:font-style value}))))} + :else + (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} {:name "lineHeight" :get #(let [range-data @@ -150,12 +191,13 @@ (->> range-data (map :line-height) mixed-value)) :set (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :lineHeight value) + (let [value (str/trim (dm/str value))] + (cond + (or (empty? value) (not (re-matches line-height-re value))) + (u/display-not-valid :lineHeight value) - :else - (st/emit! (dwt/update-text-range id start end {:line-height value}))))} + :else + (st/emit! (dwt/update-text-range id start end {:line-height value})))))} {:name "letterSpacing" :get #(let [range-data @@ -163,12 +205,13 @@ (->> range-data (map :letter-spacing) mixed-value)) :set (fn [_ value] - (cond - (not (string? value)) - (u/display-not-valid :letterSpacing value) + (let [value (str/trim (dm/str value))] + (cond + (or (empty? value) (re-matches letter-spacing-re value)) + (u/display-not-valid :letterSpacing value) - :else - (st/emit! (dwt/update-text-range id start end {:letter-spacing value}))))} + :else + (st/emit! (dwt/update-text-range id start end {:letter-spacing value})))))} {:name "textTransform" :get #(let [range-data @@ -177,7 +220,7 @@ :set (fn [_ value] (cond - (not (string? value)) + (and (string? value) (re-matches text-transform-re value)) (u/display-not-valid :textTransform value) :else @@ -190,7 +233,7 @@ :set (fn [_ value] (cond - (not (string? value)) + (and (string? value) (re-matches text-decoration-re value)) (u/display-not-valid :textDecoration value) :else @@ -203,7 +246,7 @@ :set (fn [_ value] (cond - (not (string? value)) + (and (string? value) (re-matches text-direction-re value)) (u/display-not-valid :direction value) :else @@ -216,7 +259,7 @@ :set (fn [_ value] (cond - (not (string? value)) + (and (string? value) (re-matches text-align-re value)) (u/display-not-valid :text-align value) :else @@ -278,144 +321,157 @@ (st/emit! (dwsh/update-shapes [id] #(assoc % :grow-type value))))))} {:name "fontId" - :get #(-> % u/proxy->shape text-props :font-id) + :get #(-> % u/proxy->shape text-props :font-id format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + font (when (string? value) (fonts/get-font-data value)) + variant (fonts/get-default-variant font)] (cond - (not (string? value)) + (not (some? font)) (u/display-not-valid :fontId value) :else - (st/emit! (dwt/update-attrs id {:font-id value})))))} + (st/emit! (dwt/update-attrs id (font-data font variant))))))} {:name "fontFamily" - :get #(-> % u/proxy->shape text-props :font-family) + :get #(-> % u/proxy->shape text-props :font-family format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + font (fonts/find-font-data {:font-family value}) + variant (fonts/get-default-variant font)] (cond - (not (string? value)) + (not (some? font)) (u/display-not-valid :fontFamily value) :else - (st/emit! (dwt/update-attrs id {:font-family value})))))} + (st/emit! (dwt/update-attrs id (font-data font variant))))))} {:name "fontVariantId" - :get #(-> % u/proxy->shape text-props :font-variant-id) + :get #(-> % u/proxy->shape text-props :font-variant-id format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/get-variant font value)] (cond - (not (string? value)) + (not (some? variant)) (u/display-not-valid :fontVariantId value) :else - (st/emit! (dwt/update-attrs id {:font-variant-id value})))))} + (st/emit! (dwt/update-attrs id (variant-data variant))))))} {:name "fontSize" - :get #(-> % u/proxy->shape text-props :font-size) + :get #(-> % u/proxy->shape text-props :font-size format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + value (str/trim (dm/str value))] (cond - (not (string? value)) + (or (empty? value) (not (re-matches font-size-re value))) (u/display-not-valid :fontSize value) :else (st/emit! (dwt/update-attrs id {:font-size value})))))} {:name "fontWeight" - :get #(-> % u/proxy->shape text-props :font-weight) + :get #(-> % u/proxy->shape text-props :font-weight format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/find-variant font {:weight (dm/str value)})] (cond - (not (string? value)) - (u/display-not-valid :fontWeight value) + (nil? variant) + (u/display-not-valid :fontWeight (dm/str "Font weight '" value "' not supported for the current font")) :else - (st/emit! (dwt/update-attrs id {:font-weight value})))))} + (st/emit! (dwt/update-attrs id (variant-data variant))))))} {:name "fontStyle" - :get #(-> % u/proxy->shape text-props :font-style) + :get #(-> % u/proxy->shape text-props :font-style format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + font (fonts/get-font-data (obj/get self "fontId")) + variant (fonts/find-variant font {:weight (dm/str value)})] (cond - (not (string? value)) - (u/display-not-valid :fontStyle value) + (nil? variant) + (u/display-not-valid :fontStyle (dm/str "Font style '" value "' not supported for the current font")) :else - (st/emit! (dwt/update-attrs id {:font-style value})))))} + (st/emit! (dwt/update-attrs id (variant-data variant))))))} {:name "lineHeight" - :get #(-> % u/proxy->shape text-props :line-height) + :get #(-> % u/proxy->shape text-props :line-height format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + value (str/trim (dm/str value))] (cond - (not (string? value)) + (or (empty? value) (not (re-matches line-height-re value))) (u/display-not-valid :lineHeight value) :else (st/emit! (dwt/update-attrs id {:line-height value})))))} {:name "letterSpacing" - :get #(-> % u/proxy->shape text-props :letter-spacing) + :get #(-> % u/proxy->shape text-props :letter-spacing format/format-mixed) :set (fn [self value] - (let [id (obj/get self "$id")] + (let [id (obj/get self "$id") + value (str/trim (dm/str value))] (cond - (not (string? value)) + (or (empty? value) (re-matches letter-spacing-re value)) (u/display-not-valid :letterSpacing value) :else (st/emit! (dwt/update-attrs id {:letter-spacing value})))))} {:name "textTransform" - :get #(-> % u/proxy->shape text-props :text-transform) + :get #(-> % u/proxy->shape text-props :text-transform format/format-mixed) :set (fn [self value] (let [id (obj/get self "$id")] (cond - (not (string? value)) + (and (string? value) (re-matches text-transform-re value)) (u/display-not-valid :textTransform value) :else (st/emit! (dwt/update-attrs id {:text-transform value})))))} {:name "textDecoration" - :get #(-> % u/proxy->shape text-props :text-decoration) + :get #(-> % u/proxy->shape text-props :text-decoration format/format-mixed) :set (fn [self value] (let [id (obj/get self "$id")] (cond - (not (string? value)) + (and (string? value) (re-matches text-decoration-re value)) (u/display-not-valid :textDecoration value) :else (st/emit! (dwt/update-attrs id {:text-decoration value})))))} {:name "direction" - :get #(-> % u/proxy->shape text-props :text-direction) + :get #(-> % u/proxy->shape text-props :text-direction format/format-mixed) :set (fn [self value] (let [id (obj/get self "$id")] (cond - (not (string? value)) + (and (string? value) (re-matches text-direction-re value)) (u/display-not-valid :textDecoration value) :else (st/emit! (dwt/update-attrs id {:text-decoration value})))))} {:name "align" - :get #(-> % u/proxy->shape text-props :text-align) + :get #(-> % u/proxy->shape text-props :text-align format/format-mixed) :set (fn [self value] (let [id (obj/get self "$id")] (cond - (not (string? value)) + (and (string? value) (re-matches text-align-re value)) (u/display-not-valid :align value) :else @@ -427,7 +483,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (not (string? value)) + (and (string? value) (re-matches vertical-align-re value)) (u/display-not-valid :verticalAlign value) :else From 741bf3b6664567e3a3683a7ead37bbc328eb6cc3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 1 Jul 2024 15:35:31 +0200 Subject: [PATCH 4/6] :sparkles: New plugins permissions dialog --- frontend/resources/images/icons/oauth-1.svg | 1 + frontend/resources/images/icons/oauth-2.svg | 1 + frontend/resources/images/icons/oauth-3.svg | 1 + frontend/resources/images/icons/puzzle.svg | 1 + frontend/src/app/config.cljs | 1 + frontend/src/app/main/ui/icons.cljs | 4 + .../src/app/main/ui/workspace/main_menu.cljs | 3 +- .../src/app/main/ui/workspace/plugins.cljs | 136 ++++++++++++------ .../src/app/main/ui/workspace/plugins.scss | 88 ++++++++++-- .../app/main/ui/workspace/top_toolbar.cljs | 13 ++ frontend/src/app/plugins.cljs | 33 +++++ frontend/src/app/plugins/events.cljs | 28 ++-- frontend/src/app/plugins/shape.cljs | 17 --- frontend/translations/en.po | 24 ++++ frontend/translations/es.po | 24 ++++ 15 files changed, 291 insertions(+), 84 deletions(-) create mode 100644 frontend/resources/images/icons/oauth-1.svg create mode 100644 frontend/resources/images/icons/oauth-2.svg create mode 100644 frontend/resources/images/icons/oauth-3.svg create mode 100644 frontend/resources/images/icons/puzzle.svg diff --git a/frontend/resources/images/icons/oauth-1.svg b/frontend/resources/images/icons/oauth-1.svg new file mode 100644 index 000000000..49a0dec9b --- /dev/null +++ b/frontend/resources/images/icons/oauth-1.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/images/icons/oauth-2.svg b/frontend/resources/images/icons/oauth-2.svg new file mode 100644 index 000000000..06c59a185 --- /dev/null +++ b/frontend/resources/images/icons/oauth-2.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/images/icons/oauth-3.svg b/frontend/resources/images/icons/oauth-3.svg new file mode 100644 index 000000000..db38820bc --- /dev/null +++ b/frontend/resources/images/icons/oauth-3.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/images/icons/puzzle.svg b/frontend/resources/images/icons/puzzle.svg new file mode 100644 index 000000000..6e978bac5 --- /dev/null +++ b/frontend/resources/images/icons/puzzle.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/app/config.cljs b/frontend/src/app/config.cljs index b2e3d95c4..286a17903 100644 --- a/frontend/src/app/config.cljs +++ b/frontend/src/app/config.cljs @@ -110,6 +110,7 @@ (def privacy-policy-uri (obj/get global "penpotPrivacyPolicyURI" "https://penpot.app/privacy")) (def flex-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/")) (def grid-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/")) +(def plugins-list-uri (obj/get global "penpotPluginsListUri" "https://penpot-docs-plugins.netlify.app/technical-guide/plugins/getting-started/#examples")) (defn- normalize-uri [uri-str] diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 319119424..324eb8098 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -178,6 +178,9 @@ (def ^:icon msg-success (icon-xref :msg-success)) (def ^:icon msg-warning (icon-xref :msg-warning)) (def ^:icon open-link (icon-xref :open-link)) +(def ^:icon oauth-1 (icon-xref :oauth-1)) +(def ^:icon oauth-2 (icon-xref :oauth-2)) +(def ^:icon oauth-3 (icon-xref :oauth-3)) (def ^:icon padding-bottom (icon-xref :padding-bottom)) (def ^:icon padding-extended (icon-xref :padding-extended)) (def ^:icon padding-left (icon-xref :padding-left)) @@ -190,6 +193,7 @@ (def ^:icon picker (icon-xref :picker)) (def ^:icon pin (icon-xref :pin)) (def ^:icon play (icon-xref :play)) +(def ^:icon puzzle (icon-xref :puzzle)) (def ^:icon rectangle (icon-xref :rectangle)) (def ^:icon reload (icon-xref :reload)) (def ^:icon remove-icon (icon-xref :remove)) diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index 2abca79a0..d2356c3f1 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -30,6 +30,7 @@ [app.main.ui.hooks.resize :as r] [app.main.ui.icons :as i] [app.main.ui.workspace.plugins :as uwp] + [app.plugins :as plugins] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [app.util.keyboard :as kbd] @@ -608,7 +609,7 @@ ::mf/wrap [mf/memo]} [{:keys [open-plugins on-close]}] (when (features/active-feature? @st/state "plugins/runtime") - (let [plugins (uwp/load-from-store)] + (let [plugins (plugins/load-from-store)] [:& dropdown-menu {:show true :list-class (stl/css-case :sub-menu true :plugins true) :on-close on-close} diff --git a/frontend/src/app/main/ui/workspace/plugins.cljs b/frontend/src/app/main/ui/workspace/plugins.cljs index cf55b802d..e94015124 100644 --- a/frontend/src/app/main/ui/workspace/plugins.cljs +++ b/frontend/src/app/main/ui/workspace/plugins.cljs @@ -9,22 +9,23 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.uuid :as uuid] + [app.config :as cf] [app.main.data.modal :as modal] + [app.main.store :as st] [app.main.ui.components.search-bar :refer [search-bar]] [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.icons :as i] + [app.plugins :as plugins] [app.util.avatars :as avatars] + [app.util.dom :as dom] [app.util.http :as http] [app.util.i18n :as i18n :refer [tr]] - [app.util.object :as obj] [beicon.v2.core :as rx] [rumext.v2 :as mf])) (def ^:private close-icon (i/icon-xref :close (stl/css :close-icon))) - (mf/defc plugin-entry [{:keys [index manifest on-open-plugin on-remove-plugin]}] @@ -55,20 +56,6 @@ [:button {:class (stl/css :trash-button) :on-click handle-delete-click} i/delete]])) -(defn load-from-store - [] - (let [ls (.-localStorage js/window) - plugins-val (.getItem ls "plugins")] - (when plugins-val - (let [plugins-js (.parse js/JSON plugins-val)] - (js->clj plugins-js {:keywordize-keys true}))))) - -(defn save-to-store - [plugins] - (let [ls (.-localStorage js/window) - plugins-js (clj->js plugins) - plugins-val (.stringify js/JSON plugins-js)] - (.setItem ls "plugins" plugins-val))) (defn open-plugin! [{:keys [plugin-id name description host code icon permissions]}] @@ -123,27 +110,20 @@ (rx/map :body) (rx/subs! (fn [body] - (let [name (obj/get body "name") - desc (obj/get body "description") - code (obj/get body "code") - icon (obj/get body "icon") - permissions (obj/get body "permissions") - origin (obj/get (js/URL. plugin-url) "origin") - plugin-id (str (uuid/next)) + (let [plugin (plugins/parser-manifest plugin-url body) + new-state (vec (conj (seq plugins-state) plugin))] - new-state - (conj plugins-state - {:plugin-id plugin-id - :name name - :description desc - :host origin - :code code - :icon icon - :permissions (->> permissions (mapv str))})] (reset! input-status* :success) (reset! plugin-url* "") (reset! plugins-state* new-state) - (save-to-store new-state))) + + (modal/show! + :plugin-permissions + {:plugin plugin + :on-accept + #(do + (plugins/save-to-store new-state) + (modal/show! :plugin-management {}))}))) (fn [_] (reset! input-status* :error-url)))))) @@ -162,16 +142,15 @@ (keep-indexed (fn [idx item] (when (not= idx plugin-index) item))) plugins-state)] - (reset! plugins-state* new-state) - (save-to-store new-state))))] + (plugins/save-to-store new-state))))] (mf/use-effect (fn [] - (reset! plugins-state* (d/nilv (load-from-store) [])))) + (reset! plugins-state* (d/nilv (plugins/load-from-store) [])))) [:div {:class (stl/css :modal-overlay)} - [:div {:class (stl/css :modal-dialog)} + [:div {:class (stl/css :modal-dialog :plugin-management)} [:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon] [:div {:class (stl/css :modal-title)} (tr "workspace.plugins.title")] @@ -183,7 +162,6 @@ :class (stl/css-case :input-error error?)}] [:button {:class (stl/css :primary-button) - :disabled (empty? plugin-url) :on-click handle-install-click} (tr "workspace.plugins.install")]] (when error? @@ -194,9 +172,9 @@ (if (empty? plugins-state) [:div {:class (stl/css :plugins-empty)} - [:div {:class (stl/css :plugins-empty-logo)} i/rocket] + [:div {:class (stl/css :plugins-empty-logo)} i/puzzle] [:div {:class (stl/css :plugins-empty-text)} (tr "workspace.plugins.empty-plugins")] - [:a {:class (stl/css :plugins-link) :href "#"} + [:a {:class (stl/css :plugins-link) :href cf/plugins-list-uri :target "_blank"} (tr "workspace.plugins.plugin-list-link") i/external-link]] [:* @@ -204,10 +182,84 @@ :title (tr "workspace.plugins.installed-plugins")}] [:div {:class (stl/css :plugins-list)} - (for [[idx manifest] (d/enumerate plugins-state)] [:& plugin-entry {:key (dm/str "plugin-" idx) :index idx :manifest manifest :on-open-plugin handle-open-plugin :on-remove-plugin handle-remove-plugin}])]])]]])) + +(mf/defc plugins-permissions-dialog + {::mf/register modal/components + ::mf/register-as :plugin-permissions} + [{:keys [plugin on-accept]}] + + (let [{:keys [permissions]} plugin + permissions (set permissions) + + handle-accept-dialog + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (st/emit! (modal/hide)) + (on-accept))) + + handle-close-dialog + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (st/emit! (modal/hide))))] + + [:div {:class (stl/css :modal-overlay)} + [:div {:class (stl/css :modal-dialog :plugin-permissions)} + [:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon] + [:div {:class (stl/css :modal-title)} (tr "workspace.plugins.permissions.title")] + + [:div {:class (stl/css :modal-content)} + [:div {:class (stl/css :permissions-list)} + (when (contains? permissions "content:read") + [:div {:class (stl/css :permissions-list-entry)} + i/oauth-1 + [:p {:class (stl/css :permissions-list-text)} + (tr "workspace.plugins.permissions.disclaimer")]]) + + (when (contains? permissions "content:write") + [:div {:class (stl/css :permissions-list-entry)} + i/oauth-1 + [:p {:class (stl/css :permissions-list-text)} + (tr "workspace.plugins.permissions.content-read")]]) + + (when (contains? permissions "user:read") + [:div {:class (stl/css :permissions-list-entry)} + i/oauth-2 + [:p {:class (stl/css :permissions-list-text)} + (tr "workspace.plugins.permissions.content-write")]]) + + (when (contains? permissions "library:read") + [:div {:class (stl/css :permissions-list-entry)} + i/oauth-3 + [:p {:class (stl/css :permissions-list-text)} + (tr "workspace.plugins.permissions.user-read")]]) + + (when (contains? permissions "library:write") + [:div {:class (stl/css :permissions-list-entry)} + i/oauth-3 + [:p {:class (stl/css :permissions-list-text)} + (tr "workspace.plugins.permissions.library-read")]])] + + [:div {:class (stl/css :permissions-disclaimer)} + (tr "workspace.plugins.permissions.library-write")]] + + [:div {:class (stl/css :modal-footer)} + [:div {:class (stl/css :action-buttons)} + [:input + {:class (stl/css :cancel-button :button-expand) + :type "button" + :value (tr "ds.confirm-cancel") + :on-click handle-close-dialog}] + + [:input + {:class (stl/css :primary-button :button-expand) + :type "button" + :value (tr "ds.confirm-allow") + :on-click handle-accept-dialog}]]]]])) diff --git a/frontend/src/app/main/ui/workspace/plugins.scss b/frontend/src/app/main/ui/workspace/plugins.scss index 0ff79d488..fd9114e81 100644 --- a/frontend/src/app/main/ui/workspace/plugins.scss +++ b/frontend/src/app/main/ui/workspace/plugins.scss @@ -13,15 +13,27 @@ .modal-dialog { @extend .modal-container-base; display: grid; - grid-template-rows: auto 1fr; - width: $s-472; - max-width: $s-472; + grid-template-rows: auto 1fr auto; + + &.plugin-permissions { + width: $s-412; + max-width: $s-412; + } + + &.plugin-management { + width: $s-472; + max-width: $s-472; + } hr { border-color: $db-tertiary; } } +.modal-footer { + margin-top: 2rem; +} + .close-btn { @extend .modal-close-btn-base; } @@ -40,8 +52,15 @@ .modal-content { display: flex; flex-direction: column; - height: $s-380; - max-height: $s-380; + + .plugin-permissions & { + gap: $s-20; + } + + .plugin-management & { + height: $s-380; + max-height: $s-380; + } } .primary-button { @@ -50,6 +69,17 @@ padding: $s-0 $s-16; } +.button-expand { + width: 100%; + margin: 0; +} + +.cancel-button { + @extend .button-secondary; + @include headlineSmallTypography; + padding: $s-0 $s-16; +} + .search-icon { @include flexCenter; width: $s-20; @@ -87,7 +117,7 @@ .plugins-list { padding-top: $s-20; overflow-x: hidden; - overflow-y: scroll; + overflow-y: auto; flex: 1; display: flex; flex-direction: column; @@ -148,8 +178,8 @@ svg { width: $s-16; height: $s-16; - fill: $df-secondary; - stroke-width: 0; + stroke: $df-secondary; + fill: none; } } @@ -190,3 +220,45 @@ div.input-error { fill: none; } } + +.plugin-permissions { +} + +.permissions-list { + display: flex; + flex-direction: column; + gap: $s-24; +} + +.permissions-list-entry { + display: grid; + grid-template-columns: 24px 1fr; + gap: $s-16; + align-items: center; + + svg { + width: $s-24; + height: $s-24; + stroke: $da-primary; + fill: none; + } +} + +.permissions-list-text { + @include bodySmallTypography; + margin: 0; + color: $df-secondary; +} + +.permissions-disclaimer { + @include bodySmallTypography; + padding: $s-16; + background: $db-tertiary; + color: $df-secondary; + border-radius: $br-4; +} + +.action-buttons { + display: flex; + gap: $s-12; +} diff --git a/frontend/src/app/main/ui/workspace/top_toolbar.cljs b/frontend/src/app/main/ui/workspace/top_toolbar.cljs index f7b0bcf99..dfbb3fe1a 100644 --- a/frontend/src/app/main/ui/workspace/top_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/top_toolbar.cljs @@ -11,11 +11,13 @@ [app.common.geom.point :as gpt] [app.common.media :as cm] [app.main.data.events :as ev] + [app.main.data.modal :as modal] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.media :as dwm] [app.main.data.workspace.path.state :as pst] [app.main.data.workspace.shortcuts :as sc] + [app.main.features :as features] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.file-uploader :refer [file-uploader]] @@ -192,6 +194,17 @@ :data-testid "path-btn"} i/path]] + (when (features/active-feature? @st/state "plugins/runtime") + [:li + [:button + {:title (tr "workspace.toolbar.plugins" (sc/get-tooltip :plugins)) + :aria-label (tr "workspace.toolbar.plugins" (sc/get-tooltip :plugins)) + :class (stl/css :main-toolbar-options-button) + :on-click #(modal/show! :plugin-management {}) + :data-tool "plugins" + :data-testid "plugins-btn"} + i/puzzle]]) + (when *assert* [:li [:button diff --git a/frontend/src/app/plugins.cljs b/frontend/src/app/plugins.cljs index 36346de27..702633654 100644 --- a/frontend/src/app/plugins.cljs +++ b/frontend/src/app/plugins.cljs @@ -7,6 +7,7 @@ (ns app.plugins "RPC for plugins runtime." (:require + [app.common.uuid :as uuid] [app.main.features :as features] [app.main.store :as st] [app.plugins.api :as api] @@ -33,3 +34,35 @@ (rx/take 1) (rx/tap init-plugins-runtime!) (rx/ignore))))) + +(defn parser-manifest + [plugin-url ^js manifest] + (let [name (obj/get manifest "name") + desc (obj/get manifest "description") + code (obj/get manifest "code") + icon (obj/get manifest "icon") + permissions (obj/get manifest "permissions") + origin (obj/get (js/URL. plugin-url) "origin") + plugin-id (str (uuid/next))] + {:plugin-id plugin-id + :name name + :description desc + :host origin + :code code + :icon icon + :permissions (->> permissions (mapv str))})) + +(defn load-from-store + [] + (let [ls (.-localStorage js/window) + plugins-val (.getItem ls "plugins")] + (when plugins-val + (let [plugins-js (.parse js/JSON plugins-val)] + (js->clj plugins-js {:keywordize-keys true}))))) + +(defn save-to-store + [plugins] + (let [ls (.-localStorage js/window) + plugins-js (clj->js plugins) + plugins-val (.stringify js/JSON plugins-js)] + (.setItem ls "plugins" plugins-val))) diff --git a/frontend/src/app/plugins/events.cljs b/frontend/src/app/plugins/events.cljs index eada65d67..27d926948 100644 --- a/frontend/src/app/plugins/events.cljs +++ b/frontend/src/app/plugins/events.cljs @@ -6,7 +6,6 @@ (ns app.plugins.events (:require - [app.common.data.macros :as dm] [app.main.store :as st] [app.plugins.file :as file] [app.plugins.page :as page] @@ -24,25 +23,19 @@ (defmethod handle-state-change "filechange" [_ plugin-id old-val new-val] - (let [old-file (:workspace-file old-val) - new-file (:workspace-file new-val) - old-data (:workspace-data old-val) - new-data (:workspace-data new-val)] - (if (and (identical? old-file new-file) - (identical? old-data new-data)) + (let [old-file-id (:current-file-id old-val) + new-file-id (:current-file-id new-val)] + (if (identical? old-file-id new-file-id) ::not-changed - (file/file-proxy plugin-id (:id new-file))))) + (file/file-proxy plugin-id new-file-id)))) (defmethod handle-state-change "pagechange" [_ plugin-id old-val new-val] - (let [file-id (:current-file-id new-val) - old-page-id (:current-page-id old-val) - new-page-id (:current-page-id new-val) - old-page (dm/get-in old-val [:workspace-data :pages-index old-page-id]) - new-page (dm/get-in new-val [:workspace-data :pages-index new-page-id])] - (if (identical? old-page new-page) + (let [old-page-id (:current-page-id old-val) + new-page-id (:current-page-id new-val)] + (if (identical? old-page-id new-page-id) ::not-changed - (page/page-proxy plugin-id file-id new-page-id)))) + (page/page-proxy plugin-id (:current-file-id new-val) new-page-id)))) (defmethod handle-state-change "selectionchange" [_ _ old-val new-val] @@ -75,7 +68,10 @@ (fn [_ _ old-val new-val] (let [result (handle-state-change type plugin-id old-val new-val)] (when (not= ::not-changed result) - (callback result))))) + (try + (callback result) + (catch :default cause + (.error js/console cause))))))) ;; return the generated key key)) diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index fb5a88ff6..bc1b53aba 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -60,23 +60,6 @@ (declare shape-proxy) (declare shape-proxy?) -#_(defn parse-command - [entry] - (update entry - :command - #(case % - "M" :move-to - "Z" :close-path - "L" :line-to - "H" :line-to-horizontal - "V" :line-to-vertical - "C" :curve-to - "S" :smooth-curve-to - "Q" :quadratic-bezier-curve-to - "T" :smooth-quadratic-bezier-curve-to - "A" :elliptical-arc - (keyword %)))) - (defn- shadow-defaults [shadow] (d/patch-object diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 7a972067d..8458241ba 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -847,6 +847,9 @@ msgstr "Cancel" msgid "ds.confirm-ok" msgstr "Ok" +msgid "ds.confirm-allow" +msgstr "Allow" + #: src/app/main/ui/confirm.cljs, src/app/main/ui/confirm.cljs msgid "ds.confirm-title" msgstr "Are you sure?" @@ -5290,3 +5293,24 @@ msgstr "Plugins manager" msgid "workspace.plugins.plugin-list-link" msgstr "Plugins List" + +msgid "workspace.plugins.permissions.title" +msgstr "THIS PLUGIN WANTS ACCESS TO:" + +msgid "workspace.plugins.permissions.disclaimer" +msgstr "Note that this plugin has been created by an external party." + +msgid "workspace.plugins.permissions.content-read" +msgstr "Read the content of files that users have access to." + +msgid "workspace.plugins.permissions.content-write" +msgstr "Read and modify the content of files that users have access to." + +msgid "workspace.plugins.permissions.user-read" +msgstr "Read the profile information of the current user." + +msgid "workspace.plugins.permissions.library-read" +msgstr "Read your libraries and assets." + +msgid "workspace.plugins.permissions.library-write" +msgstr "Read and modify your libraries and assets." diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 76a2264ca..187c38f82 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -869,6 +869,9 @@ msgstr "Cancelar" msgid "ds.confirm-ok" msgstr "Ok" +msgid "ds.confirm-allow" +msgstr "Permitir" + #: src/app/main/ui/confirm.cljs, src/app/main/ui/confirm.cljs msgid "ds.confirm-title" msgstr "¿Está Seguro?" @@ -5394,3 +5397,24 @@ msgstr "Gestor de extensiones" msgid "workspace.plugins.plugin-list-link" msgstr "Lista de extensiones" + +msgid "workspace.plugins.permissions.title" +msgstr "LA EXTENSIÓN SOLICITA PERMISO PARA ACCEDER:" + +msgid "workspace.plugins.permissions.disclaimer" +msgstr "Tenga en cuenta que esta extensión ha sido desarrollada por terceros." + +msgid "workspace.plugins.permissions.content-read" +msgstr "Leer el contenido de sus archivos." + +msgid "workspace.plugins.permissions.content-write" +msgstr "Leer y modificar el contenido de sus archivos." + +msgid "workspace.plugins.permissions.user-read" +msgstr "Leer la información del usuario actual." + +msgid "workspace.plugins.permissions.library-read" +msgstr "Leer la información de sus bibliotecas y recursos." + +msgid "workspace.plugins.permissions.library-write" +msgstr "Leer y modificar la información de sus bibliotecas y recursos." From 395a91c00ccd3f65da4d3811e860365294b5f01f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 2 Jul 2024 10:40:46 +0200 Subject: [PATCH 5/6] :sparkles: Plugins permissions review --- .../src/app/main/ui/workspace/main_menu.cljs | 2 +- .../src/app/main/ui/workspace/plugins.cljs | 30 +- frontend/src/app/plugins.cljs | 21 +- frontend/src/app/plugins/file.cljs | 25 +- frontend/src/app/plugins/flex.cljs | 85 +++++ frontend/src/app/plugins/fonts.cljs | 7 +- frontend/src/app/plugins/grid.cljs | 102 +++++- frontend/src/app/plugins/library.cljs | 324 +++++++++++++----- frontend/src/app/plugins/page.cljs | 27 +- frontend/src/app/plugins/register.cljs | 55 +++ frontend/src/app/plugins/shape.cljs | 171 ++++++++- frontend/src/app/plugins/text.cljs | 93 ++++- .../plugins/context_shapes_test.cljs | 2 +- 13 files changed, 773 insertions(+), 171 deletions(-) create mode 100644 frontend/src/app/plugins/register.cljs diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index d2356c3f1..135cdc1b5 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -609,7 +609,7 @@ ::mf/wrap [mf/memo]} [{:keys [open-plugins on-close]}] (when (features/active-feature? @st/state "plugins/runtime") - (let [plugins (plugins/load-from-store)] + (let [plugins @plugins/pluginsdb] [:& dropdown-menu {:show true :list-class (stl/css-case :sub-menu true :plugins true) :on-close on-close} diff --git a/frontend/src/app/main/ui/workspace/plugins.cljs b/frontend/src/app/main/ui/workspace/plugins.cljs index e94015124..5ac397430 100644 --- a/frontend/src/app/main/ui/workspace/plugins.cljs +++ b/frontend/src/app/main/ui/workspace/plugins.cljs @@ -77,7 +77,7 @@ ::mf/register-as :plugin-management} [] - (let [plugins-state* (mf/use-state []) + (let [plugins-state* (mf/use-state @plugins/pluginsdb) plugins-state @plugins-state* plugin-url* (mf/use-state "") @@ -110,20 +110,16 @@ (rx/map :body) (rx/subs! (fn [body] - (let [plugin (plugins/parser-manifest plugin-url body) - new-state (vec (conj (seq plugins-state) plugin))] - - (reset! input-status* :success) - (reset! plugin-url* "") - (reset! plugins-state* new-state) - + (let [plugin (plugins/parser-manifest plugin-url body)] (modal/show! :plugin-permissions {:plugin plugin :on-accept #(do - (plugins/save-to-store new-state) - (modal/show! :plugin-management {}))}))) + (plugins/install-plugin! plugin) + (modal/show! :plugin-management {}))}) + (reset! input-status* :success) + (reset! plugin-url* ""))) (fn [_] (reset! input-status* :error-url)))))) @@ -137,17 +133,9 @@ (mf/use-callback (mf/deps plugins-state) (fn [plugin-index] - (let [new-state - (into [] - (keep-indexed (fn [idx item] - (when (not= idx plugin-index) item))) - plugins-state)] - (reset! plugins-state* new-state) - (plugins/save-to-store new-state))))] - - (mf/use-effect - (fn [] - (reset! plugins-state* (d/nilv (plugins/load-from-store) [])))) + (let [plugin (nth @plugins/pluginsdb plugin-index)] + (plugins/remove-plugin! plugin) + (reset! plugins-state* @plugins/pluginsdb))))] [:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-dialog :plugin-management)} diff --git a/frontend/src/app/plugins.cljs b/frontend/src/app/plugins.cljs index 702633654..21e16d3c2 100644 --- a/frontend/src/app/plugins.cljs +++ b/frontend/src/app/plugins.cljs @@ -12,14 +12,20 @@ [app.main.store :as st] [app.plugins.api :as api] [app.plugins.public-utils] + [app.plugins.register :as register] [app.util.globals :refer [global]] [app.util.object :as obj] [beicon.v2.core :as rx] [potok.v2.core :as ptk])) +(def pluginsdb register/pluginsdb) +(def install-plugin! register/install-plugin!) +(def remove-plugin! register/remove-plugin!) + (defn init-plugins-runtime! [] (when-let [init-runtime (obj/get global "initPluginsRuntime")] + (register/init) (init-runtime (fn [plugin-id] (api/create-context plugin-id))))) (defn initialize @@ -51,18 +57,3 @@ :code code :icon icon :permissions (->> permissions (mapv str))})) - -(defn load-from-store - [] - (let [ls (.-localStorage js/window) - plugins-val (.getItem ls "plugins")] - (when plugins-val - (let [plugins-js (.parse js/JSON plugins-val)] - (js->clj plugins-js {:keywordize-keys true}))))) - -(defn save-to-store - [plugins] - (let [ls (.-localStorage js/window) - plugins-js (clj->js plugins) - plugins-val (.stringify js/JSON plugins-js)] - (.setItem ls "plugins" plugins-val))) diff --git a/frontend/src/app/plugins/file.cljs b/frontend/src/app/plugins/file.cljs index 9dc4d34b4..5cc3810a7 100644 --- a/frontend/src/app/plugins/file.cljs +++ b/frontend/src/app/plugins/file.cljs @@ -12,6 +12,7 @@ [app.main.data.workspace :as dw] [app.main.store :as st] [app.plugins.page :as page] + [app.plugins.register :as r] [app.plugins.utils :as u] [app.util.object :as obj])) @@ -26,7 +27,7 @@ [self key] (cond (not (string? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :getPluginData-key key) :else (let [file (u/proxy->file self)] @@ -36,10 +37,13 @@ [_ key value] (cond (or (not (string? key)) (empty? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :file-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $id :file (keyword "plugin" (str $plugin)) key value)))) @@ -53,10 +57,10 @@ [self namespace key] (cond (not (string? namespace)) - (u/display-not-valid :file-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :getSharedPluginData-key key) :else (let [file (u/proxy->file self)] @@ -67,13 +71,16 @@ (cond (or (not (string? namespace)) (empty? namespace)) - (u/display-not-valid :file-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (or (not (string? key)) (empty? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :file-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $id :file (keyword "shared" namespace) key value)))) @@ -82,7 +89,7 @@ [self namespace] (cond (not (string? namespace)) - (u/display-not-valid :file-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginDataKeys namespace) :else (let [file (u/proxy->file self)] diff --git a/frontend/src/app/plugins/flex.cljs b/frontend/src/app/plugins/flex.cljs index 098d11f2e..9b6e89673 100644 --- a/frontend/src/app/plugins/flex.cljs +++ b/frontend/src/app/plugins/flex.cljs @@ -13,6 +13,7 @@ [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.transforms :as dwt] [app.main.store :as st] + [app.plugins.register :as r] [app.plugins.utils :as u] [app.util.object :as obj] [potok.v2.core :as ptk])) @@ -58,6 +59,9 @@ (not (contains? ctl/flex-direction-types value)) (u/display-not-valid :dir value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :dir "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-flex-dir value}))))))} @@ -71,6 +75,9 @@ (not (contains? ctl/align-items-types value)) (u/display-not-valid :alignItems value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-items value}))))))} @@ -84,6 +91,9 @@ (not (contains? ctl/align-content-types value)) (u/display-not-valid :alignContent value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-content value}))))))} @@ -97,6 +107,9 @@ (not (contains? ctl/justify-items-types value)) (u/display-not-valid :justifyItems value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-items value}))))))} @@ -110,6 +123,9 @@ (not (contains? ctl/justify-content-types value)) (u/display-not-valid :justifyContent value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-content value}))))))} @@ -122,6 +138,9 @@ (not (us/safe-int? value)) (u/display-not-valid :rowGap value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}})))))} @@ -134,6 +153,9 @@ (not (us/safe-int? value)) (u/display-not-valid :columnGap value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}})))))} @@ -146,6 +168,9 @@ (not (us/safe-int? value)) (u/display-not-valid :verticalPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}})))))} @@ -158,6 +183,9 @@ (not (us/safe-int? value)) (u/display-not-valid :horizontalPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))} @@ -171,6 +199,9 @@ (not (us/safe-int? value)) (u/display-not-valid :topPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}})))))} @@ -183,6 +214,9 @@ (not (us/safe-int? value)) (u/display-not-valid :rightPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rightPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}})))))} @@ -195,6 +229,9 @@ (not (us/safe-int? value)) (u/display-not-valid :bottomPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}})))))} @@ -207,6 +244,9 @@ (not (us/safe-int? value)) (u/display-not-valid :leftPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) @@ -234,6 +274,9 @@ (not (boolean? value)) (u/display-not-valid :absolute value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :absolute "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-item-absolute value})))))} @@ -246,6 +289,9 @@ (us/safe-int? value) (u/display-not-valid :zIndex value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :zIndex "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-z-index value})))))} @@ -259,6 +305,9 @@ (not (contains? ctl/item-h-sizing-types value)) (u/display-not-valid :horizontalPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-h-sizing value}))))))} @@ -272,6 +321,9 @@ (not (contains? ctl/item-v-sizing-types value)) (u/display-not-valid :verticalSizing value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalSizing "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-v-sizing value}))))))} @@ -285,6 +337,9 @@ (not (contains? ctl/item-align-self-types value)) (u/display-not-valid :alignSelf value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignSelf "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-align-self value}))))))} @@ -297,6 +352,9 @@ (not (us/safe-number? value)) (u/display-not-valid :verticalMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value :m3 value}})))))} @@ -309,6 +367,9 @@ (not (us/safe-number? value)) (u/display-not-valid :horizontalMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :horizontalMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value :m4 value}})))))} @@ -321,6 +382,9 @@ (not (us/safe-number? value)) (u/display-not-valid :topMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :topMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value}})))))} @@ -333,6 +397,9 @@ (not (us/safe-number? value)) (u/display-not-valid :rightMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rightMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value}})))))} @@ -345,6 +412,9 @@ (not (us/safe-number? value)) (u/display-not-valid :bottomMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :bottomMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m3 value}})))))} @@ -357,6 +427,9 @@ (not (us/safe-number? value)) (u/display-not-valid :leftMargin value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :leftMargin "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m4 value}})))))} @@ -369,6 +442,9 @@ (not (us/safe-number? value)) (u/display-not-valid :maxWidth value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :maxWidth "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-w value})))))} @@ -381,6 +457,9 @@ (not (us/safe-number? value)) (u/display-not-valid :minWidth value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :minWidth "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-w value})))))} @@ -393,6 +472,9 @@ (not (us/safe-number? value)) (u/display-not-valid :maxHeight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :maxHeight "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-h value})))))} @@ -405,6 +487,9 @@ (not (us/safe-number? value)) (u/display-not-valid :minHeight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :minHeight "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-h value})))))}))) diff --git a/frontend/src/app/plugins/fonts.cljs b/frontend/src/app/plugins/fonts.cljs index cc73ee4b1..e07ea77ba 100644 --- a/frontend/src/app/plugins/fonts.cljs +++ b/frontend/src/app/plugins/fonts.cljs @@ -11,6 +11,7 @@ [app.main.data.workspace.texts :as dwt] [app.main.fonts :as fonts] [app.main.store :as st] + [app.plugins.register :as r] [app.plugins.shape :as shape] [app.plugins.text :as text] [app.plugins.utils :as u] @@ -30,7 +31,8 @@ (not (shape/shape-proxy? text)) (u/display-not-valid :applyToText text) - ;; TODO: Check variant inside font variants + (not (r/check-permission (obj/get text "$plugin") "content:write")) + (u/display-not-valid :applyToText "Plugin doesn't have 'content:write' permission") :else (let [id (obj/get text "$id") @@ -46,7 +48,8 @@ (not (text/text-range? range)) (u/display-not-valid :applyToRange range) - ;; TODO: Check variant inside font variants + (not (r/check-permission (obj/get range "$plugin") "content:write")) + (u/display-not-valid :applyToRange "Plugin doesn't have 'content:write' permission") :else (let [id (obj/get range "$id") diff --git a/frontend/src/app/plugins/grid.cljs b/frontend/src/app/plugins/grid.cljs index eb255a008..3035948e2 100644 --- a/frontend/src/app/plugins/grid.cljs +++ b/frontend/src/app/plugins/grid.cljs @@ -14,6 +14,7 @@ [app.main.data.workspace.transforms :as dwt] [app.main.store :as st] [app.plugins.format :as format] + [app.plugins.register :as r] [app.plugins.utils :as u] [app.util.object :as obj] [potok.v2.core :as ptk])) @@ -35,6 +36,9 @@ (not (us/safe-number? value))) (u/display-not-valid :addRow-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addRow "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/add-layout-track #{$id} :row {:type type :value value}))))) @@ -52,6 +56,9 @@ (not (us/safe-number? value))) (u/display-not-valid :addRowAtIndex-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addRowAtIndex "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/add-layout-track #{$id} :row {:type type :value value} index))))) @@ -66,6 +73,9 @@ (not (us/safe-number? value))) (u/display-not-valid :addColumn-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addColumn "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/add-layout-track #{$id} :column {:type type :value value}))))) @@ -82,6 +92,9 @@ (not (us/safe-number? value))) (u/display-not-valid :addColumnAtIndex-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addColumnAtIndex "Plugin doesn't have 'content:write' permission") + :else (let [type (keyword type)] (st/emit! (dwsl/add-layout-track #{$id} :column {:type type :value value} index))))) @@ -92,6 +105,9 @@ (not (us/safe-int? index)) (u/display-not-valid :removeRow index) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :removeRow "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/remove-layout-track #{$id} :row index)))) @@ -101,6 +117,9 @@ (not (us/safe-int? index)) (u/display-not-valid :removeColumn index) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :removeColumn "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/remove-layout-track #{$id} :column index)))) @@ -118,6 +137,9 @@ (not (us/safe-number? value))) (u/display-not-valid :setColumn-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setColumn "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/change-layout-track #{$id} :column index (d/without-nils {:type type :value value})))))) @@ -135,12 +157,20 @@ (not (us/safe-number? value))) (u/display-not-valid :setRow-value value) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setRow "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/change-layout-track #{$id} :row index (d/without-nils {:type type :value value})))))) (remove [_] - (st/emit! (dwsl/remove-layout #{$id}))) + (cond + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :remove "Plugin doesn't have 'content:write' permission") + + :else + (st/emit! (dwsl/remove-layout #{$id})))) (appendChild [_ child row column] @@ -154,6 +184,9 @@ (or (< column 0) (not (us/safe-int? column))) (u/display-not-valid :appendChild-column column) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :appendChild "Plugin doesn't have 'content:write' permission") + :else (let [child-id (obj/get child "$id")] (st/emit! (dwt/move-shapes-to-frame #{child-id} $id nil [row column]) @@ -180,6 +213,9 @@ (not (contains? ctl/grid-direction-types value)) (u/display-not-valid :dir value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :dir "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-grid-dir value}))))))} @@ -199,6 +235,9 @@ (not (contains? ctl/align-items-types value)) (u/display-not-valid :alignItems value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-items value}))))))} @@ -212,6 +251,9 @@ (not (contains? ctl/align-content-types value)) (u/display-not-valid :alignContent value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-content value}))))))} @@ -225,6 +267,9 @@ (not (contains? ctl/justify-items-types value)) (u/display-not-valid :justifyItems value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-items value}))))))} @@ -238,6 +283,9 @@ (not (contains? ctl/justify-content-types value)) (u/display-not-valid :justifyContent value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-content value}))))))} @@ -250,6 +298,9 @@ (not (us/safe-int? value)) (u/display-not-valid :rowGap value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}})))))} @@ -262,6 +313,9 @@ (not (us/safe-int? value)) (u/display-not-valid :columnGap value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}})))))} @@ -274,6 +328,9 @@ (not (us/safe-int? value)) (u/display-not-valid :verticalPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}})))))} @@ -286,6 +343,9 @@ (not (us/safe-int? value)) (u/display-not-valid :horizontalPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))} @@ -298,6 +358,9 @@ (not (us/safe-int? value)) (u/display-not-valid :topPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}})))))} @@ -310,6 +373,9 @@ (not (us/safe-int? value)) (u/display-not-valid :rightPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :righPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}})))))} @@ -322,6 +388,9 @@ (not (us/safe-int? value)) (u/display-not-valid :bottomPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}})))))} @@ -334,6 +403,9 @@ (not (us/safe-int? value)) (u/display-not-valid :leftPadding value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) @@ -365,10 +437,13 @@ shape (u/proxy->shape self)] (cond (not (us/safe-int? value)) - (u/display-not-valid :row value) + (u/display-not-valid :row-value value) (nil? cell) - (u/display-not-valid :cell "cell not found") + (u/display-not-valid :row-cell "cell not found") + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :row "Plugin doesn't have 'content:write' permission") :else (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row value})))))} @@ -386,6 +461,9 @@ (nil? cell) (u/display-not-valid :rowSpan-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rowSpan "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row-span value})))))} @@ -402,6 +480,9 @@ (nil? cell) (u/display-not-valid :column-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :column "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column value})))))} @@ -418,6 +499,9 @@ (nil? cell) (u/display-not-valid :columnSpan-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :columnSpan "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column-span value})))))} @@ -434,6 +518,9 @@ (nil? cell) (u/display-not-valid :areaName-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :areaName "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:area-name value})))))} @@ -451,6 +538,9 @@ (nil? cell) (u/display-not-valid :position-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :position "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/change-cells-mode (:parent-id shape) #{(:id cell)} value)))))} @@ -468,6 +558,9 @@ (nil? cell) (u/display-not-valid :alignSelf-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :alignSelf "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:align-self value})))))} @@ -485,5 +578,8 @@ (nil? cell) (u/display-not-valid :justifySelf-cell "cell not found") + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :justifySelf "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:justify-self value})))))})))) diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index 7c90146f5..1e00d27f3 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -24,6 +24,7 @@ [app.main.store :as st] [app.plugins.format :as format] [app.plugins.parser :as parser] + [app.plugins.register :as r] [app.plugins.shape :as shape] [app.plugins.text :as text] [app.plugins.utils :as u] @@ -40,15 +41,25 @@ (remove [_] - (st/emit! (dwl/delete-color {:id $id}))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :remove "Plugin doesn't have 'library:write' permission") + + :else + (st/emit! (dwl/delete-color {:id $id})))) (clone [_] - (let [color-id (uuid/next) - color (-> (u/locate-library-color $file $id) - (assoc :id color-id))] - (st/emit! (dwl/add-color color {:rename? false})) - (lib-color-proxy $plugin $id color-id))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :clone "Plugin doesn't have 'library:write' permission") + + :else + (let [color-id (uuid/next) + color (-> (u/locate-library-color $file $id) + (assoc :id color-id))] + (st/emit! (dwl/add-color color {:rename? false})) + (lib-color-proxy $plugin $id color-id)))) (asFill [_] (let [color (u/locate-library-color $file $id)] @@ -76,7 +87,7 @@ [self key] (cond (not (string? key)) - (u/display-not-valid :color-plugin-data-key key) + (u/display-not-valid :getPluginData-key key) :else (let [color (u/proxy->library-color self)] @@ -86,13 +97,16 @@ [_ key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :color-edit-non-local-library $file) + (u/display-not-valid :setPluginData-non-local-library $file) (not (string? key)) - (u/display-not-valid :color-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :color-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :color $id (keyword "plugin" (str $plugin)) key value)))) @@ -106,10 +120,10 @@ [self namespace key] (cond (not (string? namespace)) - (u/display-not-valid :color-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :color-plugin-data-key key) + (u/display-not-valid :getSharedPluginData-key key) :else (let [color (u/proxy->library-color self)] @@ -119,16 +133,19 @@ [_ namespace key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :color-edit-non-local-library $file) + (u/display-not-valid :setSharedPluginData-non-local-library $file) (not (string? namespace)) - (u/display-not-valid :color-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :color-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :color-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :color $id (keyword "shared" namespace) key value)))) @@ -137,7 +154,7 @@ [self namespace] (cond (not (string? namespace)) - (u/display-not-valid :color-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginDataKeys-namespace namespace) :else (let [color (u/proxy->library-color self)] @@ -165,7 +182,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-color-name value) + (u/display-not-valid :name value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :name "Plugin doesn't have 'library:write' permission") :else (let [color (u/proxy->library-color self) @@ -178,7 +198,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-color-path value) + (u/display-not-valid :path value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :path "Plugin doesn't have 'library:write' permission") :else (let [color (-> (u/proxy->library-color self) @@ -191,7 +214,10 @@ (fn [self value] (cond (or (not (string? value)) (not (cc/valid-hex-color? value))) - (u/display-not-valid :library-color-color value) + (u/display-not-valid :color value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :color "Plugin doesn't have 'library:write' permission") :else (let [color (-> (u/proxy->library-color self) @@ -204,7 +230,10 @@ (fn [self value] (cond (or (not (number? value)) (< value 0) (> value 1)) - (u/display-not-valid :library-color-opacity value) + (u/display-not-valid :opacity value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :opacity "Plugin doesn't have 'library:write' permission") :else (let [color (-> (u/proxy->library-color self) @@ -218,7 +247,10 @@ (let [value (parser/parse-gradient value)] (cond (not (sm/validate ::ctc/gradient value)) - (u/display-not-valid :library-color-gradient value) + (u/display-not-valid :gradient value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :gradient "Plugin doesn't have 'library:write' permission") :else (let [color (-> (u/proxy->library-color self) @@ -232,7 +264,10 @@ (let [value (parser/parse-image-data value)] (cond (not (sm/validate ::ctc/image-color value)) - (u/display-not-valid :library-color-image value) + (u/display-not-valid :image value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :image "Plugin doesn't have 'library:write' permission") :else (let [color (-> (u/proxy->library-color self) @@ -243,15 +278,25 @@ Object (remove [_] - (st/emit! (dwl/delete-typography {:id $id}))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :remove "Plugin doesn't have 'library:write' permission") + + :else + (st/emit! (dwl/delete-typography {:id $id})))) (clone [_] - (let [typo-id (uuid/next) - typo (-> (u/locate-library-typography $file $id) - (assoc :id typo-id))] - (st/emit! (dwl/add-typography typo false)) - (lib-typography-proxy $plugin $id typo-id))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :clone "Plugin doesn't have 'library:write' permission") + + :else + (let [typo-id (uuid/next) + typo (-> (u/locate-library-typography $file $id) + (assoc :id typo-id))] + (st/emit! (dwl/add-typography typo false)) + (lib-typography-proxy $plugin $id typo-id)))) (applyToText [_ shape] @@ -259,6 +304,9 @@ (not (shape/shape-proxy? shape)) (u/display-not-valid :applyToText shape) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :applyToText "Plugin doesn't have 'content:write' permission") + :else (let [shape-id (obj/get shape "$id") typography (u/locate-library-typography $file $id)] @@ -270,6 +318,9 @@ (not (text/text-range? range)) (u/display-not-valid :applyToText range) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :applyToText "Plugin doesn't have 'content:write' permission") + :else (let [shape-id (obj/get range "$id") start (obj/get range "start") @@ -296,13 +347,16 @@ [_ key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :typography-edit-non-local-library $file) + (u/display-not-valid :setPluginData-non-local-library $file) (not (string? key)) - (u/display-not-valid :typography-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :typography-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :typography $id (keyword "plugin" (str $plugin)) key value)))) @@ -316,10 +370,10 @@ [self namespace key] (cond (not (string? namespace)) - (u/display-not-valid :typography-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :typography-plugin-data-key key) + (u/display-not-valid :getSharedPluginData-key key) :else (let [typography (u/proxy->library-typography self)] @@ -329,16 +383,19 @@ [_ namespace key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :typography-edit-non-local-library $file) + (u/display-not-valid :setSharedPluginData-non-local-library $file) (not (string? namespace)) - (u/display-not-valid :typography-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :typography-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :typography-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :typography $id (keyword "shared" namespace) key value)))) @@ -347,7 +404,7 @@ [self namespace] (cond (not (string? namespace)) - (u/display-not-valid :typography-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginDataKeys-namespace namespace) :else (let [typography (u/proxy->library-typography self)] @@ -376,7 +433,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-name value) + (u/display-not-valid :name value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :name "Plugin doesn't have 'library:write' permission") :else (let [typo (u/proxy->library-typography self) @@ -389,7 +449,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-path value) + (u/display-not-valid :path value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :path "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -402,7 +465,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-id value) + (u/display-not-valid :fontId value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontId "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -415,7 +481,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-family value) + (u/display-not-valid :fontFamily value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontFamily "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -428,7 +497,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-variant-id value) + (u/display-not-valid :fontVariantId value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontVariantId "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -441,7 +513,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-size value) + (u/display-not-valid :fontSize value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontSize "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -454,7 +529,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-weight value) + (u/display-not-valid :fontWeight value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontWeight "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -467,7 +545,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-style value) + (u/display-not-valid :fontStyle value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :fontStyle "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -480,7 +561,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-font-height value) + (u/display-not-valid :lineHeight value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :lineHeight "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -493,7 +577,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-letter-spacing value) + (u/display-not-valid :letterSpacing value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :letterSpacing "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -506,7 +593,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-typography-text-transform value) + (u/display-not-valid :textTransform value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :textTransform "Plugin doesn't have 'library:write' permission") :else (let [typo (-> (u/proxy->library-typography self) @@ -518,13 +608,23 @@ (remove [_] - (st/emit! (dwl/delete-component {:id $id}))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :remove "Plugin doesn't have 'library:write' permission") + + :else + (st/emit! (dwl/delete-component {:id $id})))) (instance [_] - (let [id-ref (atom nil)] - (st/emit! (dwl/instantiate-component $file $id (gpt/point 0 0) {:id-ref id-ref})) - (shape/shape-proxy $plugin @id-ref))) + (cond + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :instance "Plugin doesn't have 'content:write' permission") + + :else + (let [id-ref (atom nil)] + (st/emit! (dwl/instantiate-component $file $id (gpt/point 0 0) {:id-ref id-ref})) + (shape/shape-proxy $plugin @id-ref)))) (getPluginData [self key] @@ -540,13 +640,16 @@ [_ key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :component-edit-non-local-library $file) + (u/display-not-valid :setPluginData-non-local-library $file) (not (string? key)) - (u/display-not-valid :component-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :component-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :component $id (keyword "plugin" (str $plugin)) key value)))) @@ -573,16 +676,19 @@ [_ namespace key value] (cond (not= $file (:current-file-id @st/state)) - (u/display-not-valid :component-edit-non-local-library $file) + (u/display-not-valid :setSharedPluginData-non-local-library $file) (not (string? namespace)) - (u/display-not-valid :component-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :component-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :component-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $file :component $id (keyword "shared" namespace) key value)))) @@ -626,7 +732,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-component-name value) + (u/display-not-valid :name value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :name "Plugin doesn't have 'library:write' permission") :else (let [component (u/proxy->library-component self) @@ -639,7 +748,10 @@ (fn [self value] (cond (not (string? value)) - (u/display-not-valid :library-component-path value) + (u/display-not-valid :path value) + + (not (r/check-permission plugin-id "library:write")) + (u/display-not-valid :path "Plugin doesn't have 'library:write' permission") :else (let [component (u/proxy->library-component self) @@ -653,22 +765,37 @@ (createColor [_] - (let [color-id (uuid/next)] - (st/emit! (dwl/add-color {:id color-id :name "Color" :color "#000000" :opacity 1} {:rename? false})) - (lib-color-proxy $plugin $id color-id))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :createColor "Plugin doesn't have 'library:write' permission") + + :else + (let [color-id (uuid/next)] + (st/emit! (dwl/add-color {:id color-id :name "Color" :color "#000000" :opacity 1} {:rename? false})) + (lib-color-proxy $plugin $id color-id)))) (createTypography [_] - (let [typography-id (uuid/next)] - (st/emit! (dwl/add-typography (ctt/make-typography {:id typography-id :name "Typography"}) false)) - (lib-typography-proxy $plugin $id typography-id))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :createTypography "Plugin doesn't have 'library:write' permission") + + :else + (let [typography-id (uuid/next)] + (st/emit! (dwl/add-typography (ctt/make-typography {:id typography-id :name "Typography"}) false)) + (lib-typography-proxy $plugin $id typography-id)))) (createComponent [_ shapes] - (let [id-ref (atom nil) - ids (into #{} (map #(obj/get % "$id")) shapes)] - (st/emit! (dwl/add-component id-ref ids)) - (lib-component-proxy $plugin $id @id-ref))) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :createComponent "Plugin doesn't have 'library:write' permission") + + :else + (let [id-ref (atom nil) + ids (into #{} (map #(obj/get % "$id")) shapes)] + (st/emit! (dwl/add-component id-ref ids)) + (lib-component-proxy $plugin $id @id-ref)))) ;; Plugin data (getPluginData @@ -685,10 +812,13 @@ [_ key value] (cond (not (string? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :file-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $id :file (keyword "plugin" (str $plugin)) key value)))) @@ -716,13 +846,16 @@ (cond (not (string? namespace)) - (u/display-not-valid :file-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :file-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :file-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'library:write' permission") :else (st/emit! (dw/set-plugin-data $id :file (keyword "shared" namespace) key value)))) @@ -731,7 +864,7 @@ [self namespace] (cond (not (string? namespace)) - (u/display-not-valid :file-plugin-data-namespace namespace) + (u/display-not-valid :namespace namespace) :else (let [file (u/proxy->file self)] @@ -805,21 +938,26 @@ (connectLibrary [_ library-id] - (p/create - (fn [resolve reject] - (cond - (not (string? library-id)) - (do (u/display-not-valid :connectLibrary library-id) - (reject nil)) + (cond + (not (r/check-permission $plugin "library:write")) + (u/display-not-valid :connectLibrary "Plugin doesn't have 'library:write' permission") - :else - (let [file-id (:current-file-id @st/state) - library-id (uuid/uuid library-id)] - (->> st/stream - (rx/filter (ptk/type? ::dwl/attach-library-finished)) - (rx/take 1) - (rx/subs! #(resolve (library-proxy $plugin library-id)) reject)) - (st/emit! (dwl/link-file-to-library file-id library-id)))))))) + :else + (p/create + (fn [resolve reject] + (cond + (not (string? library-id)) + (do (u/display-not-valid :connectLibrary library-id) + (reject nil)) + + :else + (let [file-id (:current-file-id @st/state) + library-id (uuid/uuid library-id)] + (->> st/stream + (rx/filter (ptk/type? ::dwl/attach-library-finished)) + (rx/take 1) + (rx/subs! #(resolve (library-proxy $plugin library-id)) reject)) + (st/emit! (dwl/link-file-to-library file-id library-id))))))))) (defn library-subcontext [plugin-id] diff --git a/frontend/src/app/plugins/page.cljs b/frontend/src/app/plugins/page.cljs index 66ff1877f..712b6293c 100644 --- a/frontend/src/app/plugins/page.cljs +++ b/frontend/src/app/plugins/page.cljs @@ -14,6 +14,7 @@ [app.main.data.workspace :as dw] [app.main.store :as st] [app.plugins.parser :as parser] + [app.plugins.register :as r] [app.plugins.shape :as shape] [app.plugins.utils :as u] [app.util.object :as obj] @@ -74,10 +75,13 @@ [_ key value] (cond (not (string? key)) - (u/display-not-valid :page-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :page-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $file :page $id (keyword "plugin" (str $plugin)) key value)))) @@ -105,13 +109,16 @@ (cond (not (string? namespace)) - (u/display-not-valid :page-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :page-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :page-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $file :page $id (keyword "shared" namespace) key value)))) @@ -151,7 +158,10 @@ (fn [_ value] (cond (not (string? value)) - (u/display-not-valid :page-name value) + (u/display-not-valid :name value) + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :name "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/rename-page id value))))} @@ -167,7 +177,10 @@ (fn [_ value] (cond (or (not (string? value)) (not (cc/valid-hex-color? value))) - (u/display-not-valid :page-background-color value) + (u/display-not-valid :background value) + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :background "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/change-canvas-color id {:color value}))))})) diff --git a/frontend/src/app/plugins/register.cljs b/frontend/src/app/plugins/register.cljs new file mode 100644 index 000000000..ab8fb1d80 --- /dev/null +++ b/frontend/src/app/plugins/register.cljs @@ -0,0 +1,55 @@ +;; 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) KALEIDOS INC + +(ns app.plugins.register + "RPC for plugins runtime." + (:require + [app.common.data :as d])) + +;; TODO: Remove clj->js and parse into a better data structure for accessing the permissions + +(def pluginsdb (atom nil)) + +(defn load-from-store + [] + (let [ls (.-localStorage js/window) + plugins-val (.getItem ls "plugins")] + (when plugins-val + (let [plugins-js (.parse js/JSON plugins-val)] + (js->clj plugins-js {:keywordize-keys true}))))) + +(defn save-to-store + [plugins] + (let [ls (.-localStorage js/window) + plugins-js (clj->js plugins) + plugins-val (.stringify js/JSON plugins-js)] + (.setItem ls "plugins" plugins-val))) + +(defn init + [] + (reset! pluginsdb (load-from-store))) + +(defn install-plugin! + [plugin] + (let [plugins (vec (conj (seq @pluginsdb) plugin))] + (reset! pluginsdb plugins) + (save-to-store plugins))) + +(defn remove-plugin! + [{:keys [plugin-id]}] + (let [plugins + (into [] + (keep (fn [plugin] + (when (not= plugin-id (:plugin-id plugin)) plugin))) + @pluginsdb)] + (reset! pluginsdb plugins) + (save-to-store plugins))) + +(defn check-permission + [plugin-id permission] + (or (= plugin-id "TEST") + (let [{:keys [permissions]} (->> @pluginsdb (d/seek #(= (:plugin-id %) plugin-id)))] + (->> permissions (d/seek #(= % permission)))))) diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index bc1b53aba..727b2c70c 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -41,6 +41,7 @@ [app.plugins.format :as format] [app.plugins.grid :as grid] [app.plugins.parser :as parser] + [app.plugins.register :as r] [app.plugins.text :as text] [app.plugins.utils :as u] [app.util.object :as obj] @@ -93,6 +94,9 @@ (or (not (us/safe-number? height)) (<= height 0)) (u/display-not-valid :resize height) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :resize "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dw/update-dimensions [$id] :width width) (dw/update-dimensions [$id] :height height)))) @@ -107,6 +111,9 @@ (and (some? center) (or (not (number? (:x center))) (not (number? (:y center))))) (u/display-not-valid :rotate-center center) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :rotate "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dw/increase-rotation [id] angle {:center center :delta? true})))))) @@ -114,19 +121,29 @@ (clone [_] (let [ret-v (atom nil)] - (st/emit! (dws/duplicate-shapes #{$id} :change-selection? false :return-ref ret-v)) - (shape-proxy $plugin (deref ret-v)))) + (cond + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :clone "Plugin doesn't have 'content:write' permission") + + :else + (do (st/emit! (dws/duplicate-shapes #{$id} :change-selection? false :return-ref ret-v)) + (shape-proxy $plugin (deref ret-v)))))) (remove [_] - (st/emit! (dwsh/delete-shapes #{$id}))) + (cond + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :remove "Plugin doesn't have 'content:write' permission") + + :else + (st/emit! (dwsh/delete-shapes #{$id})))) ;; Plugin data (getPluginData [self key] (cond (not (string? key)) - (u/display-not-valid :shape-plugin-data-key key) + (u/display-not-valid :getPluginData key) :else (let [shape (u/proxy->shape self)] @@ -136,10 +153,13 @@ [_ key value] (cond (not (string? key)) - (u/display-not-valid :shape-plugin-data-key key) + (u/display-not-valid :setPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :shape-plugin-data value) + (u/display-not-valid :setPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $file :shape $id $page (keyword "plugin" (str $plugin)) key value)))) @@ -153,10 +173,10 @@ [self namespace key] (cond (not (string? namespace)) - (u/display-not-valid :shape-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :shape-plugin-data-key key) + (u/display-not-valid :getSharedPluginData-key key) :else (let [shape (u/proxy->shape self)] @@ -167,13 +187,16 @@ (cond (not (string? namespace)) - (u/display-not-valid :shape-plugin-data-namespace namespace) + (u/display-not-valid :setSharedPluginData-namespace namespace) (not (string? key)) - (u/display-not-valid :shape-plugin-data-key key) + (u/display-not-valid :setSharedPluginData-key key) (and (some? value) (not (string? value))) - (u/display-not-valid :shape-plugin-data value) + (u/display-not-valid :setSharedPluginData-value value) + + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission") :else (st/emit! (dw/set-plugin-data $file :shape $id $page (keyword "shared" namespace) key value)))) @@ -182,7 +205,7 @@ [self namespace] (cond (not (string? namespace)) - (u/display-not-valid :shape-plugin-data-namespace namespace) + (u/display-not-valid :getSharedPluginDataKeys namespace) :else (let [shape (u/proxy->shape self)] @@ -218,6 +241,9 @@ (not (shape-proxy? child)) (u/display-not-valid :appendChild-child child) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :appendChild "Plugin doesn't have 'content:write' permission") + :else (let [child-id (obj/get child "$id")] (st/emit! (dw/relocate-shapes #{child-id} $id 0)))))) @@ -235,6 +261,9 @@ (not (shape-proxy? child)) (u/display-not-valid :insertChild-child child) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :insertChild "Plugin doesn't have 'content:write' permission") + :else (let [child-id (obj/get child "$id")] (st/emit! (dw/relocate-shapes #{child-id} $id index)))))) @@ -247,6 +276,9 @@ (not (cfh/frame-shape? shape)) (u/display-not-valid :addFlexLayout (:type shape)) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addFlexLayout "Plugin doesn't have 'content:write' permission") + :else (do (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false)) (grid/grid-layout-proxy $plugin $file $page $id))))) @@ -258,6 +290,9 @@ (not (cfh/frame-shape? shape)) (u/display-not-valid :addGridLayout (:type shape)) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :addGridLayout "Plugin doesn't have 'content:write' permission") + :else (do (st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false)) (grid/grid-layout-proxy $plugin $file $page $id))))) @@ -270,6 +305,9 @@ (not (cfh/group-shape? shape)) (u/display-not-valid :makeMask (:type shape)) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :makeMask "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwg/mask-group #{$id}))))) @@ -280,6 +318,9 @@ (not (cfh/mask-shape? shape)) (u/display-not-valid :removeMask (:type shape)) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :removeMask "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwg/unmask-group #{$id}))))) @@ -321,6 +362,9 @@ (not (cfh/text-shape? shape)) (u/display-not-valid :applyTypography-shape (:type shape)) + (not (r/check-permission $plugin "content:write")) + (u/display-not-valid :applyTypography "Plugin doesn't have 'content:write' permission") + :else (let [typography (u/proxy->library-typography typography)] (st/emit! (dwt/apply-typography #{$id} typography $file)))))) @@ -442,8 +486,11 @@ (not (str/ends-with? value "/")) (not (str/blank? value)))] (cond + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :name "Plugin doesn't have 'content:write' permission") + (not valid?) - (u/display-not-valid :shape-name value) + (u/display-not-valid :name value) :else (st/emit! (dwsh/update-shapes [id] #(assoc % :name value))))))} @@ -456,6 +503,9 @@ (not (boolean? value)) (u/display-not-valid :blocked value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :blocked "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsh/update-shapes [id] #(assoc % :blocked value))))))} @@ -468,6 +518,9 @@ (not (boolean? value)) (u/display-not-valid :hidden value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :hidden "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsh/update-shapes [id] #(assoc % :hidden value))))))} @@ -480,6 +533,9 @@ (not (boolean? value)) (u/display-not-valid :proportionLock value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :proportionLock "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dwsh/update-shapes [id] #(assoc % :proportion-lock value))))))} @@ -494,6 +550,9 @@ (not (contains? cts/horizontal-constraint-types value)) (u/display-not-valid :constraintsHorizontal value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :constraintsHorizontal "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :constraints-h value))))))} @@ -507,6 +566,9 @@ (not (contains? cts/vertical-constraint-types value)) (u/display-not-valid :constraintsVertical value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :constraintsVertical "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :constraints-v value))))))} @@ -520,6 +582,9 @@ (or (not (us/safe-int? value)) (< value 0)) (u/display-not-valid :borderRadius value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :borderRadius "Plugin doesn't have 'content:write' permission") + (or (not (ctsr/has-radius? shape)) (ctsr/radius-4? shape)) (st/emit! (dwsh/update-shapes [id] #(-> % ctsr/switch-to-radius-1 @@ -538,6 +603,9 @@ (not (us/safe-int? value)) (u/display-not-valid :borderRadiusTopLeft value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :borderRadiusTopLeft "Plugin doesn't have 'content:write' permission") + (or (not (ctsr/has-radius? shape)) (not (ctsr/radius-4? shape))) (st/emit! (dwsh/update-shapes [id] #(-> % (ctsr/switch-to-radius-4) @@ -556,6 +624,9 @@ (not (us/safe-int? value)) (u/display-not-valid :borderRadiusTopRight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :borderRadiusTopRight "Plugin doesn't have 'content:write' permission") + (or (not (ctsr/has-radius? shape)) (not (ctsr/radius-4? shape))) (st/emit! (dwsh/update-shapes [id] #(-> % (ctsr/switch-to-radius-4) @@ -574,6 +645,9 @@ (not (us/safe-int? value)) (u/display-not-valid :borderRadiusBottomRight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :borderRadiusBottomRight "Plugin doesn't have 'content:write' permission") + (or (not (ctsr/has-radius? shape)) (not (ctsr/radius-4? shape))) (st/emit! (dwsh/update-shapes [id] #(-> % (ctsr/switch-to-radius-4) @@ -592,6 +666,9 @@ (not (us/safe-int? value)) (u/display-not-valid :borderRadiusBottomLeft value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :borderRadiusBottomLeft "Plugin doesn't have 'content:write' permission") + (or (not (ctsr/has-radius? shape)) (not (ctsr/radius-4? shape))) (st/emit! (dwsh/update-shapes [id] #(-> % (ctsr/switch-to-radius-4) @@ -605,7 +682,14 @@ :set (fn [self value] (let [id (obj/get self "$id")] - (when (and (us/safe-number? value) (>= value 0) (<= value 1)) + (cond + (or (not (us/safe-number? value)) (< value 0) (> value 1)) + (u/display-not-valid :opacity value) + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :opacity "Plugin doesn't have 'content:write' permission") + + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :opacity value))))))} {:name "blendMode" @@ -618,6 +702,9 @@ (not (contains? cts/blend-modes value)) (u/display-not-valid :blendMode value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :blendMode "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :blend-mode value))))))} @@ -631,6 +718,9 @@ (not (sm/validate [:vector ::ctss/shadow] value)) (u/display-not-valid :shadows value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :shadows "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :shadow value))))))} @@ -646,6 +736,9 @@ (not (sm/validate ::ctsb/blur value)) (u/display-not-valid :blur value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :blur "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :blur value)))))))} @@ -659,6 +752,9 @@ (not (sm/validate [:vector ::ctse/export] value)) (u/display-not-valid :exports value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :exports "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :exports value))))))} @@ -672,6 +768,9 @@ (not (us/safe-number? value)) (u/display-not-valid :x value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :x "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dw/update-position id {:x value})))))} @@ -684,6 +783,9 @@ (not (us/safe-number? value)) (u/display-not-valid :y value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :y "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dw/update-position id {:y value})))))} @@ -699,6 +801,9 @@ (not (us/safe-number? value)) (u/display-not-valid :parentX value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :parentX "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id") parent-id (-> self u/proxy->shape :parent-id) @@ -719,6 +824,9 @@ (not (us/safe-number? value)) (u/display-not-valid :parentY value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :parentY "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id") parent-id (-> self u/proxy->shape :parent-id) @@ -739,6 +847,9 @@ (not (us/safe-number? value)) (u/display-not-valid :frameX value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :frameX "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id") frame-id (-> self u/proxy->shape :frame-id) @@ -759,6 +870,9 @@ (not (us/safe-number? value)) (u/display-not-valid :frameY value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :frameY "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id") frame-id (-> self u/proxy->shape :frame-id) @@ -780,6 +894,9 @@ (not (number? value)) (u/display-not-valid :rotation value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :rotation "Plugin doesn't have 'content:write' permission") + :else (let [shape (u/proxy->shape self)] (st/emit! (dw/increase-rotation #{(:id shape)} value)))))} @@ -792,6 +909,9 @@ (not (boolean? value)) (u/display-not-valid :flipX value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :flipX "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dw/flip-horizontal-selected #{id})))))} @@ -804,6 +924,9 @@ (not (boolean? value)) (u/display-not-valid :flipY value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :flipY "Plugin doesn't have 'content:write' permission") + :else (let [id (obj/get self "$id")] (st/emit! (dw/flip-vertical-selected #{id})))))} @@ -825,6 +948,9 @@ (cfh/text-shape? shape) (st/emit! (dwt/update-attrs id {:fills value})) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fills "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :fills value))))))} @@ -838,6 +964,9 @@ (not (sm/validate [:vector ::cts/stroke] value)) (u/display-not-valid :strokes value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :strokes "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :strokes value))))))} @@ -898,6 +1027,9 @@ (not (sm/validate [:vector ::ctg/grid] value)) (u/display-not-valid :guides value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :guides "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :grids value))))))} @@ -911,6 +1043,9 @@ (not (contains? #{:fix :auto} value)) (u/display-not-valid :horizontalSizing value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :horizontalSizing "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-layout #{id} {:layout-item-h-sizing value})))))} @@ -924,10 +1059,13 @@ (not (contains? #{:fix :auto} value)) (u/display-not-valid :verticalSizing value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalSizing "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))}))) - (cond-> (cfh/text-shape? data) (text/add-text-props)) + (cond-> (cfh/text-shape? data) (text/add-text-props plugin-id)) (cond-> (or (cfh/path-shape? data) (cfh/bool-shape? data)) (crc/add-properties! @@ -945,6 +1083,9 @@ (not (sm/validate ::ctsp/content content)) (u/display-not-valid :content value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :content "Plugin doesn't have 'content:write' permission") + :else (let [selrect (gsh/content->selrect content) points (grc/rect->points selrect)] diff --git a/frontend/src/app/plugins/text.cljs b/frontend/src/app/plugins/text.cljs index 05750c9bb..d0558664c 100644 --- a/frontend/src/app/plugins/text.cljs +++ b/frontend/src/app/plugins/text.cljs @@ -18,6 +18,7 @@ [app.main.store :as st] [app.plugins.format :as format] [app.plugins.parser :as parser] + [app.plugins.register :as r] [app.plugins.utils :as u] [app.util.object :as obj] [app.util.text-editor :as ted] @@ -107,6 +108,9 @@ (not (some? font)) (u/display-not-valid :fontId value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontId "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end (font-data font variant))))))} @@ -123,6 +127,9 @@ (not (string? value)) (u/display-not-valid :fontFamily value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontFamily "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end (font-data font variant))))))} @@ -138,6 +145,9 @@ (not (string? value)) (u/display-not-valid :fontVariantId value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontVariantId "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} @@ -152,6 +162,9 @@ (or (empty? value) (not (re-matches font-size-re value))) (u/display-not-valid :fontSize value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontSize "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:font-size value})))))} @@ -167,6 +180,9 @@ (nil? variant) (u/display-not-valid :fontWeight (dm/str "Font weight '" value "' not supported for the current font")) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontWeight "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} @@ -182,6 +198,9 @@ (nil? variant) (u/display-not-valid :fontStyle (dm/str "Font style '" value "' not supported for the current font")) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontStyle "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end (variant-data variant))))))} @@ -196,6 +215,9 @@ (or (empty? value) (not (re-matches line-height-re value))) (u/display-not-valid :lineHeight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :lineHeight "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:line-height value})))))} @@ -210,6 +232,9 @@ (or (empty? value) (re-matches letter-spacing-re value)) (u/display-not-valid :letterSpacing value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :letterSpacing "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:letter-spacing value})))))} @@ -223,6 +248,9 @@ (and (string? value) (re-matches text-transform-re value)) (u/display-not-valid :textTransform value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :textTransform "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:text-transform value}))))} @@ -236,6 +264,9 @@ (and (string? value) (re-matches text-decoration-re value)) (u/display-not-valid :textDecoration value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :textDecoration "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:text-decoration value}))))} @@ -249,6 +280,9 @@ (and (string? value) (re-matches text-direction-re value)) (u/display-not-valid :direction value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :direction "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:direction value}))))} @@ -260,7 +294,10 @@ (fn [_ value] (cond (and (string? value) (re-matches text-align-re value)) - (u/display-not-valid :text-align value) + (u/display-not-valid :align value) + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :align "Plugin doesn't have 'content:write' permission") :else (st/emit! (dwt/update-text-range id start end {:text-align value}))))} @@ -276,11 +313,14 @@ (not (sm/validate [:vector ::cts/fill] value)) (u/display-not-valid :fills value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fills "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-text-range id start end {:fills value})))))}))) (defn add-text-props - [shape-proxy] + [plugin-id shape-proxy] (crc/add-properties! shape-proxy {:name "characters" @@ -294,6 +334,9 @@ (or (not (string? value)) (empty? value)) (u/display-not-valid :characters value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :characters "Plugin doesn't have 'content:write' permission") + (contains? (:workspace-editor-state @st/state) id) (let [shape (u/proxy->shape self) editor @@ -317,6 +360,9 @@ (not (contains? #{:auto-width :auto-height :fixed} value)) (u/display-not-valid :growType value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :growType "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwsh/update-shapes [id] #(assoc % :grow-type value))))))} @@ -331,6 +377,9 @@ (not (some? font)) (u/display-not-valid :fontId value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontId "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id (font-data font variant))))))} @@ -345,6 +394,9 @@ (not (some? font)) (u/display-not-valid :fontFamily value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontFamily "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id (font-data font variant))))))} @@ -359,6 +411,9 @@ (not (some? variant)) (u/display-not-valid :fontVariantId value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontVariantId "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id (variant-data variant))))))} @@ -372,6 +427,9 @@ (or (empty? value) (not (re-matches font-size-re value))) (u/display-not-valid :fontSize value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontSize "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:font-size value})))))} @@ -386,6 +444,9 @@ (nil? variant) (u/display-not-valid :fontWeight (dm/str "Font weight '" value "' not supported for the current font")) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontWeight "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id (variant-data variant))))))} @@ -400,6 +461,9 @@ (nil? variant) (u/display-not-valid :fontStyle (dm/str "Font style '" value "' not supported for the current font")) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :fontStyle "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id (variant-data variant))))))} @@ -413,6 +477,9 @@ (or (empty? value) (not (re-matches line-height-re value))) (u/display-not-valid :lineHeight value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :lineHeight "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:line-height value})))))} @@ -426,6 +493,9 @@ (or (empty? value) (re-matches letter-spacing-re value)) (u/display-not-valid :letterSpacing value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :letterSpacing "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:letter-spacing value})))))} @@ -438,6 +508,9 @@ (and (string? value) (re-matches text-transform-re value)) (u/display-not-valid :textTransform value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :textTransform "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:text-transform value})))))} @@ -450,6 +523,9 @@ (and (string? value) (re-matches text-decoration-re value)) (u/display-not-valid :textDecoration value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :textDecoration "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:text-decoration value})))))} @@ -460,10 +536,13 @@ (let [id (obj/get self "$id")] (cond (and (string? value) (re-matches text-direction-re value)) - (u/display-not-valid :textDecoration value) + (u/display-not-valid :textDirection value) + + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :textDirection "Plugin doesn't have 'content:write' permission") :else - (st/emit! (dwt/update-attrs id {:text-decoration value})))))} + (st/emit! (dwt/update-attrs id {:text-direction value})))))} {:name "align" :get #(-> % u/proxy->shape text-props :text-align format/format-mixed) @@ -474,6 +553,9 @@ (and (string? value) (re-matches text-align-re value)) (u/display-not-valid :align value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :align "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:text-align value})))))} @@ -486,5 +568,8 @@ (and (string? value) (re-matches vertical-align-re value)) (u/display-not-valid :verticalAlign value) + (not (r/check-permission plugin-id "content:write")) + (u/display-not-valid :verticalAlign "Plugin doesn't have 'content:write' permission") + :else (st/emit! (dwt/update-attrs id {:vertical-align value})))))})) diff --git a/frontend/test/frontend_tests/plugins/context_shapes_test.cljs b/frontend/test/frontend_tests/plugins/context_shapes_test.cljs index e5e85a326..af6638b82 100644 --- a/frontend/test/frontend_tests/plugins/context_shapes_test.cljs +++ b/frontend/test/frontend_tests/plugins/context_shapes_test.cljs @@ -23,7 +23,7 @@ _ (set! st/state store) - context (api/create-context "tests") + context (api/create-context "TEST") page (. context -currentPage) From 58fa10a0d547f0b1c232dc5b34e72aa2d1dfa670 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 2 Jul 2024 11:08:56 +0200 Subject: [PATCH 6/6] :arrow_up: Update plugins runtime --- frontend/resources/plugins-runtime/index.js | 1401 ++++++++++--------- 1 file changed, 710 insertions(+), 691 deletions(-) diff --git a/frontend/resources/plugins-runtime/index.js b/frontend/resources/plugins-runtime/index.js index aa6199d6a..1d75c17b1 100644 --- a/frontend/resources/plugins-runtime/index.js +++ b/frontend/resources/plugins-runtime/index.js @@ -2,7 +2,7 @@ var Vn = (t, e, r) => { if (!e.has(t)) throw TypeError("Cannot " + r); }; -var Se = (t, e, r) => (Vn(t, e, "read from private field"), r ? r.call(t) : e.get(t)), Gr = (t, e, r) => { +var Ee = (t, e, r) => (Vn(t, e, "read from private field"), r ? r.call(t) : e.get(t)), Gr = (t, e, r) => { if (e.has(t)) throw TypeError("Cannot add the same private member more than once"); e instanceof WeakSet ? e.add(t) : e.set(t, r); @@ -15,7 +15,7 @@ const k = globalThis, { JSON: qs, Map: Pe, Math: Ks, - Number: So, + Number: Eo, Object: bn, Promise: Ys, Proxy: Cr, @@ -23,7 +23,7 @@ const k = globalThis, { RegExp: We, Set: Ct, String: pe, - Symbol: Et, + Symbol: St, WeakMap: Me, WeakSet: $t } = globalThis, { @@ -56,7 +56,7 @@ const k = globalThis, { preventExtensions: Qs, setPrototypeOf: ko, values: Po, - fromEntries: mt + fromEntries: ht } = bn, { species: Vr, toStringTag: qe, @@ -65,7 +65,7 @@ const k = globalThis, { unscopables: ea, keyFor: ta, for: ra -} = Et, { isInteger: na } = So, { stringify: Ao } = qs, { defineProperty: oa } = bn, M = (t, e, r) => { +} = St, { isInteger: na } = Eo, { stringify: Ao } = qs, { defineProperty: oa } = bn, M = (t, e, r) => { const n = oa(t, e, r); if (n !== t) throw v( @@ -76,7 +76,7 @@ const k = globalThis, { return n; }, { apply: ne, - construct: mr, + construct: hr, get: sa, getOwnPropertyDescriptor: aa, has: Io, @@ -84,24 +84,24 @@ const k = globalThis, { ownKeys: De, preventExtensions: ca, set: Co -} = Js, { isArray: St, prototype: _e } = Hs, { prototype: Nt } = Pe, { prototype: Rr } = RegExp, { prototype: nr } = Ct, { prototype: Le } = pe, { prototype: Or } = Me, { prototype: $o } = $t, { prototype: En } = Function, { prototype: No } = Ys, { prototype: Ro } = j( +} = Js, { isArray: Et, prototype: _e } = Hs, { prototype: Nt } = Pe, { prototype: Rr } = RegExp, { prototype: nr } = Ct, { prototype: Le } = pe, { prototype: Or } = Me, { prototype: $o } = $t, { prototype: Sn } = Function, { prototype: No } = Ys, { prototype: Ro } = j( // eslint-disable-next-line no-empty-function, func-names function* () { } -), la = j(Uint8Array.prototype), { bind: tn } = En, P = tn.bind(tn.call), oe = P(wn.hasOwnProperty), Ke = P(_e.filter), ut = P(_e.forEach), Mr = P(_e.includes), Rt = P(_e.join), se = ( +), la = j(Uint8Array.prototype), { bind: tn } = Sn, P = tn.bind(tn.call), oe = P(wn.hasOwnProperty), Ke = P(_e.filter), ut = P(_e.forEach), Mr = P(_e.includes), Rt = P(_e.join), se = ( /** @type {any} */ P(_e.map) ), Oo = ( /** @type {any} */ P(_e.flatMap) -), gr = P(_e.pop), X = P(_e.push), ua = P(_e.slice), da = P(_e.some), Mo = P(_e.sort), fa = P(_e[rr]), $e = P(Nt.set), Ue = P(Nt.get), Lr = P(Nt.has), pa = P(Nt.delete), ha = P(Nt.entries), ma = P(Nt[rr]), Sn = P(nr.add); +), gr = P(_e.pop), X = P(_e.push), ua = P(_e.slice), da = P(_e.some), Mo = P(_e.sort), fa = P(_e[rr]), $e = P(Nt.set), Ue = P(Nt.get), Lr = P(Nt.has), pa = P(Nt.delete), ma = P(Nt.entries), ha = P(Nt[rr]), En = P(nr.add); P(nr.delete); const Wn = P(nr.forEach), xn = P(nr.has), ga = P(nr[rr]), kn = P(Rr.test), Pn = P(Rr.exec), ya = P(Rr[To]), Lo = P(Le.endsWith), Fo = P(Le.includes), va = P(Le.indexOf); P(Le.match); const yr = P(Ro.next), Do = P(Ro.throw), vr = ( /** @type {any} */ P(Le.replace) -), _a = P(Le.search), Tn = P(Le.slice), An = P(Le.split), Uo = P(Le.startsWith), ba = P(Le[rr]), wa = P(Or.delete), L = P(Or.get), In = P(Or.has), ie = P(Or.set), Fr = P($o.add), or = P($o.has), Ea = P(En.toString), Sa = P(tn); +), _a = P(Le.search), Tn = P(Le.slice), An = P(Le.split), Uo = P(Le.startsWith), ba = P(Le[rr]), wa = P(Or.delete), L = P(Or.get), In = P(Or.has), ie = P(Or.set), Fr = P($o.add), or = P($o.has), Sa = P(Sn.toString), Ea = P(tn); P(No.catch); const jo = ( /** @type {any} */ @@ -137,32 +137,32 @@ const { freeze: at } = Object, { apply: Aa } = Reflect, $n = (t) => (e, ...r) => r = `${r}${e[n]}${t[n + 1]}`; throw Error(r); }, Bo = (t, e = !1) => { - const r = [], n = (c, u, l = void 0) => { - typeof c == "string" || ir`Environment option name ${nt(c)} must be a string.`, typeof u == "string" || ir`Environment option default setting ${nt( - u + const r = [], n = (c, l, u = void 0) => { + typeof c == "string" || ir`Environment option name ${nt(c)} must be a string.`, typeof l == "string" || ir`Environment option default setting ${nt( + l )} must be a string.`; - let d = u; - const f = t.process || void 0, h = typeof f == "object" && f.env || void 0; - if (typeof h == "object" && c in h) { + let d = l; + const f = t.process || void 0, m = typeof f == "object" && f.env || void 0; + if (typeof m == "object" && c in m) { e || Ia(r, c); - const p = h[c]; + const p = m[c]; typeof p == "string" || ir`Environment option named ${nt( c )}, if present, must have a corresponding string value, got ${nt( p )}`, d = p; } - return l === void 0 || d === u || qn(l, d) || ir`Unrecognized ${nt(c)} value ${nt( + return u === void 0 || d === l || qn(u, d) || ir`Unrecognized ${nt(c)} value ${nt( d - )}. Expected one of ${nt([u, ...l])}`, d; + )}. Expected one of ${nt([l, ...u])}`, d; }; at(n); const o = (c) => { - const u = n(c, ""); - return at(u === "" ? [] : Ca(u, ",")); + const l = n(c, ""); + return at(l === "" ? [] : Ca(l, ",")); }; at(o); - const a = (c, u) => qn(o(c), u), i = () => at([...r]); + const a = (c, l) => qn(o(c), l), i = () => at([...r]); return at(i), at({ getEnvironmentOption: n, getEnvironmentOptionsList: o, @@ -185,26 +185,26 @@ const Ho = (t, e = void 0) => { return null; if (xn(r, a)) return "[Seen]"; - if (Sn(r, a), Dr(a)) + if (En(r, a), Dr(a)) return `[${a.name}: ${a.message}]`; if (qe in a) return `[${a[qe]}]`; - if (St(a)) + if (Et(a)) return a; const i = xo(a); if (i.length < 2) return a; let c = !0; - for (let l = 1; l < i.length; l += 1) - if (i[l - 1] >= i[l]) { + for (let u = 1; u < i.length; u += 1) + if (i[u - 1] >= i[u]) { c = !1; break; } if (c) return a; Mo(i); - const u = se(i, (l) => [l, a[l]]); - return mt(u); + const l = se(i, (u) => [u, a[u]]); + return ht(l); } case "function": return `[Function ${a.name || ""}]`; @@ -263,33 +263,33 @@ const { isSafeInteger: $a } = Number, { freeze: vt } = Object, { toStringTag: Na vt(i); const c = (d, f) => { if (t < 1) - return l; - let h = o(d); - if (h === void 0 && (h = Kn(void 0), Yn(n, h)), !h.data) - for (r += 1, h.data = /* @__PURE__ */ new WeakMap(), e.set(d, h); r > t; ) { + return u; + let m = o(d); + if (m === void 0 && (m = Kn(void 0), Yn(n, m)), !m.data) + for (r += 1, m.data = /* @__PURE__ */ new WeakMap(), e.set(d, m); r > t; ) { const p = n.prev; Kr(p), p.data = void 0, r -= 1; } - return h.data.set(d, f), l; + return m.data.set(d, f), u; }; vt(c); - const u = (d) => { + const l = (d) => { const f = e.get(d); return f === void 0 || (Kr(f), e.delete(d), f.data === void 0) ? !1 : (f.data = void 0, r -= 1, !0); }; - vt(u); - const l = vt({ + vt(l); + const u = vt({ has: a, get: i, set: c, - delete: u, + delete: l, // eslint-disable-next-line jsdoc/check-types [ /** @type {typeof Symbol.toStringTag} */ Na ]: "LRUCacheMap" }); - return l; + return u; }; vt(Vo); const { freeze: pr } = Object, { isSafeInteger: Ra } = Number, Oa = 1e3, Ma = 100, Wo = (t = Oa, e = Ma) => { @@ -366,7 +366,7 @@ const Jo = ({ template: t, args: e }) => { X(r, o, i); } return r[r.length - 1] === "" && gr(r), r; -}, hr = new Me(); +}, mr = new Me(); let nn = 0; const Jn = new Me(), Xo = (t, e = t.name) => { let r = L(Jn, t); @@ -379,20 +379,20 @@ const Jn = new Me(), Xo = (t, e = t.name) => { cause: a = void 0, stack: i = void 0, ...c - } = e, u = De(c); - if (u.length >= 1) { - for (const d of u) + } = e, l = De(c); + if (l.length >= 1) { + for (const d of l) delete t[d]; - const l = z(wn, c); + const u = z(wn, c); Nn( t, - ft`originally with properties ${Je(l)}` + ft`originally with properties ${Je(u)}` ); } - for (const l of De(t)) { - const d = e[l]; - d && oe(d, "get") && M(t, l, { - value: t[l] + for (const u of De(t)) { + const d = e[u]; + d && oe(d, "get") && M(t, u, { + value: t[u] // invoke the getter to convert to data property }); } @@ -407,18 +407,18 @@ const Jn = new Me(), Xo = (t, e = t.name) => { const i = L(Ur, t); if (i === void 0) throw v(`unrecognized details ${Je(t)}`); - const c = qo(i), u = n && { cause: n }; - let l; - return typeof Hr < "u" && e === Hr ? l = Hr(o || [], c, u) : (l = /** @type {ErrorConstructor} */ + const c = qo(i), l = n && { cause: n }; + let u; + return typeof Hr < "u" && e === Hr ? u = Hr(o || [], c, l) : (u = /** @type {ErrorConstructor} */ e( c, - u - ), o !== void 0 && M(l, "errors", { + l + ), o !== void 0 && M(u, "errors", { value: o, writable: !0, enumerable: !1, configurable: !0 - })), ie(hr, l, Jo(i)), r !== void 0 && Xo(l, r), a && Fa(l), l; + })), ie(mr, u, Jo(i)), r !== void 0 && Xo(u, r), a && Fa(u), u; }; y(on); const { addLogArgs: Da, takeLogArgsArray: Ua } = Wo(), sn = new Me(), Nn = (t, e) => { @@ -446,10 +446,10 @@ const ja = (t) => { resetErrorTagNum: () => { nn = 0; }, - getMessageLogArgs: (t) => L(hr, t), + getMessageLogArgs: (t) => L(mr, t), takeMessageLogArgs: (t) => { - const e = L(hr, t); - return wa(hr, t), e; + const e = L(mr, t); + return wa(mr, t), e; }, takeNoteLogArgsArray: (t, e) => { const r = Ua(t); @@ -462,39 +462,39 @@ const ja = (t) => { }; y(br); const jr = (t = void 0, e = !1) => { - const r = e ? Yo : ft, n = r`Check failed`, o = (f = n, h = void 0, p = void 0) => { - const m = on(f, h, p); - throw t !== void 0 && t(m), m; + const r = e ? Yo : ft, n = r`Check failed`, o = (f = n, m = void 0, p = void 0) => { + const h = on(f, m, p); + throw t !== void 0 && t(h), h; }; y(o); - const a = (f, ...h) => o(r(f, ...h)); - function i(f, h = void 0, p = void 0, m = void 0) { - f || o(h, p, m); + const a = (f, ...m) => o(r(f, ...m)); + function i(f, m = void 0, p = void 0, h = void 0) { + f || o(m, p, h); } - const c = (f, h, p = void 0, m = void 0, _ = void 0) => { - Nr(f, h) || o( - p || r`Expected ${f} is same as ${h}`, - m || Xs, + const c = (f, m, p = void 0, h = void 0, _ = void 0) => { + Nr(f, m) || o( + p || r`Expected ${f} is same as ${m}`, + h || Xs, _ ); }; y(c); - const u = (f, h, p) => { - if (typeof f !== h) { - if (typeof h == "string" || a`${Je(h)} must be a string`, p === void 0) { - const m = _r(h); - p = r`${f} must be ${rn(m)}`; + const l = (f, m, p) => { + if (typeof f !== m) { + if (typeof m == "string" || a`${Je(m)} must be a string`, p === void 0) { + const h = _r(m); + p = r`${f} must be ${rn(h)}`; } o(p, v); } }; - y(u); + y(l); const d = $r(i, { error: on, fail: o, equal: c, - typeof: u, - string: (f, h = void 0) => u(f, "string", h), + typeof: l, + string: (f, m = void 0) => l(f, "string", m), note: Nn, details: r, Fail: a, @@ -541,17 +541,17 @@ const Za = (t) => ne(es, t, []) !== void 0, za = (t) => { const f = typeof d; if (f !== "object" && f !== "function") throw v(`Unexpected typeof: ${f}`); - or(t, d) || xn(n, d) || Sn(n, d); + or(t, d) || xn(n, d) || En(n, d); } const a = (d) => { Za(d) ? Ga(d) : y(d); - const f = Ze(d), h = j(d); - o(h), ut(De(f), (p) => { - const m = f[ + const f = Ze(d), m = j(d); + o(m), ut(De(f), (p) => { + const h = f[ /** @type {string} */ p ]; - oe(m, "value") ? o(m.value) : (o(m.get), o(m.set)); + oe(h, "value") ? o(h.value) : (o(h.get), o(h.set)); }); }, i = qr === void 0 && Pa === void 0 ? ( // On platforms without v8's error own stack accessor problem, @@ -573,12 +573,12 @@ const Za = (t) => ne(es, t, []) !== void 0, za = (t) => { return a(d); }, c = () => { Wn(n, i); - }, u = (d) => { + }, l = (d) => { Fr(t, d); - }, l = () => { - Wn(n, u); + }, u = () => { + Wn(n, l); }; - return o(r), c(), l(), r; + return o(r), c(), u(), r; } }; return e; @@ -1923,18 +1923,18 @@ const as = () => { }; y(r); const n = () => { - for (const [c, u] of re(t)) { - if (!Ye(u) || !oe(u, "prototype")) + for (const [c, l] of re(t)) { + if (!Ye(l) || !oe(l, "prototype")) continue; - const l = wr[c]; - if (typeof l != "object") + const u = wr[c]; + if (typeof u != "object") throw v(`Expected permit object at whitelist.${c}`); - const d = l.prototype; + const d = u.prototype; if (!d) throw v(`${c}.prototype property not whitelisted`); if (typeof d != "string" || !oe(wr, d)) throw v(`Unrecognized ${c}.prototype whitelist entry`); - const f = u.prototype; + const f = l.prototype; if (oe(t, d)) { if (t[d] !== f) throw v(`Conflicting bindings of ${d}`); @@ -1967,96 +1967,96 @@ const as = () => { }; function Ya(t, e) { let r = !1; - const n = (h, ...p) => (r || (console.groupCollapsed("Removing unpermitted intrinsics"), r = !0), console[h](...p)), o = ["undefined", "boolean", "number", "string", "symbol"], a = new Pe( - Et ? se( + const n = (m, ...p) => (r || (console.groupCollapsed("Removing unpermitted intrinsics"), r = !0), console[m](...p)), o = ["undefined", "boolean", "number", "string", "symbol"], a = new Pe( + St ? se( Ke( re(wr["%SharedSymbol%"]), - ([h, p]) => p === "symbol" && typeof Et[h] == "symbol" + ([m, p]) => p === "symbol" && typeof St[m] == "symbol" ), - ([h]) => [Et[h], `@@${h}`] + ([m]) => [St[m], `@@${m}`] ) : [] ); - function i(h, p) { + function i(m, p) { if (typeof p == "string") return p; - const m = Ue(a, p); + const h = Ue(a, p); if (typeof p == "symbol") { - if (m) - return m; + if (h) + return h; { const _ = ta(p); return _ !== void 0 ? `RegisteredSymbol(${_})` : `Unique${pe(p)}`; } } - throw v(`Unexpected property name type ${h} ${p}`); + throw v(`Unexpected property name type ${m} ${p}`); } - function c(h, p, m) { + function c(m, p, h) { if (!Ye(p)) - throw v(`Object expected: ${h}, ${p}, ${m}`); + throw v(`Object expected: ${m}, ${p}, ${h}`); const _ = j(p); - if (!(_ === null && m === null)) { - if (m !== void 0 && typeof m != "string") - throw v(`Malformed whitelist permit ${h}.__proto__`); - if (_ !== t[m || "%ObjectPrototype%"]) - throw v(`Unexpected intrinsic ${h}.__proto__ at ${m}`); + if (!(_ === null && h === null)) { + if (h !== void 0 && typeof h != "string") + throw v(`Malformed whitelist permit ${m}.__proto__`); + if (_ !== t[h || "%ObjectPrototype%"]) + throw v(`Unexpected intrinsic ${m}.__proto__ at ${h}`); } } - function u(h, p, m, _) { + function l(m, p, h, _) { if (typeof _ == "object") - return f(h, p, _), !0; + return f(m, p, _), !0; if (_ === !1) return !1; if (typeof _ == "string") { - if (m === "prototype" || m === "constructor") { + if (h === "prototype" || h === "constructor") { if (oe(t, _)) { if (p !== t[_]) - throw v(`Does not match whitelist ${h}`); + throw v(`Does not match whitelist ${m}`); return !0; } } else if (Mr(o, _)) { if (typeof p !== _) throw v( - `At ${h} expected ${_} not ${typeof p}` + `At ${m} expected ${_} not ${typeof p}` ); return !0; } } - throw v(`Unexpected whitelist permit ${_} at ${h}`); + throw v(`Unexpected whitelist permit ${_} at ${m}`); } - function l(h, p, m, _) { - const E = J(p, m); - if (!E) - throw v(`Property ${m} not found at ${h}`); - if (oe(E, "value")) { + function u(m, p, h, _) { + const S = J(p, h); + if (!S) + throw v(`Property ${h} not found at ${m}`); + if (oe(S, "value")) { if (eo(_)) - throw v(`Accessor expected at ${h}`); - return u(h, E.value, m, _); + throw v(`Accessor expected at ${m}`); + return l(m, S.value, h, _); } if (!eo(_)) - throw v(`Accessor not expected at ${h}`); - return u(`${h}`, E.get, m, _.get) && u(`${h}`, E.set, m, _.set); + throw v(`Accessor not expected at ${m}`); + return l(`${m}`, S.get, h, _.get) && l(`${m}`, S.set, h, _.set); } - function d(h, p, m) { - const _ = m === "__proto__" ? "--proto--" : m; + function d(m, p, h) { + const _ = h === "__proto__" ? "--proto--" : h; if (oe(p, _)) return p[_]; - if (typeof h == "function" && oe(an, _)) + if (typeof m == "function" && oe(an, _)) return an[_]; } - function f(h, p, m) { + function f(m, p, h) { if (p == null) return; - const _ = m["[[Proto]]"]; - c(h, p, _), typeof p == "function" && e(p); - for (const E of De(p)) { - const T = i(h, E), N = `${h}.${T}`, x = d(p, m, T); - if (!x || !l(N, p, E, x)) { + const _ = h["[[Proto]]"]; + c(m, p, _), typeof p == "function" && e(p); + for (const S of De(p)) { + const T = i(m, S), N = `${m}.${T}`, x = d(p, h, T); + if (!x || !u(N, p, S, x)) { x !== !1 && n("warn", `Removing ${N}`); try { - delete p[E]; + delete p[S]; } catch (D) { - if (E in p) { - if (typeof p == "function" && E === "prototype" && (p.prototype = void 0, p.prototype === void 0)) { + if (S in p) { + if (typeof p == "function" && S === "prototype" && (p.prototype = void 0, p.prototype === void 0)) { n( "warn", `Tolerating undeletable ${N} === undefined` @@ -2088,10 +2088,10 @@ function Ja() { let a; try { a = (0, eval)(o); - } catch (u) { - if (u instanceof tr) + } catch (l) { + if (l instanceof tr) return; - throw u; + throw l; } const i = j(a), c = function() { throw v( @@ -2136,10 +2136,10 @@ function Xa(t = "safe") { throw v("secure mode Calling %SharedDate%.now() throws"); } }, o = ({ powers: c = "none" } = {}) => { - let u; - return c === "original" ? u = function(...d) { - return new.target === void 0 ? ne(e, void 0, d) : mr(e, d, new.target); - } : u = function(...d) { + let l; + return c === "original" ? l = function(...d) { + return new.target === void 0 ? ne(e, void 0, d) : hr(e, d, new.target); + } : l = function(...d) { if (new.target === void 0) throw v( "secure mode Calling %SharedDate% constructor as a function throws" @@ -2148,8 +2148,8 @@ function Xa(t = "safe") { throw v( "secure mode Calling new %SharedDate%() with no arguments throws" ); - return mr(e, d, new.target); - }, F(u, { + return hr(e, d, new.target); + }, F(l, { length: { value: 7 }, prototype: { value: r, @@ -2169,7 +2169,7 @@ function Xa(t = "safe") { enumerable: !1, configurable: !0 } - }), u; + }), l; }, a = o({ powers: "original" }), i = o({ powers: "none" }); return F(a, { now: { @@ -2221,8 +2221,8 @@ function ei(t = "safe") { if (t !== "safe" && t !== "unsafe") throw v(`unrecognized regExpTaming ${t}`); const e = We.prototype, r = (a = {}) => { - const i = function(...u) { - return new.target === void 0 ? We(...u) : mr(We, u, new.target); + const i = function(...l) { + return new.target === void 0 ? We(...l) : hr(We, l, new.target); }; if (F(i, { length: { value: 2 }, @@ -2425,9 +2425,9 @@ const ti = { }; function ni(t, e, r = []) { const n = new Ct(r); - function o(l, d, f, h) { - if ("value" in h && h.configurable) { - const { value: p } = h, m = xn(n, f), { get: _, set: E } = J( + function o(u, d, f, m) { + if ("value" in m && m.configurable) { + const { value: p } = m, h = xn(n, f), { get: _, set: S } = J( { get [f]() { return p; @@ -2437,9 +2437,9 @@ function ni(t, e, r = []) { throw v( `Cannot assign to read only property '${pe( f - )}' of '${l}'` + )}' of '${u}'` ); - oe(this, f) ? this[f] = T : (m && console.error(v(`Override property ${f}`)), M(this, f, { + oe(this, f) ? this[f] = T : (h && console.error(v(`Override property ${f}`)), M(this, f, { value: T, writable: !0, enumerable: !0, @@ -2456,56 +2456,56 @@ function ni(t, e, r = []) { configurable: !1 }), M(d, f, { get: _, - set: E, - enumerable: h.enumerable, - configurable: h.configurable + set: S, + enumerable: m.enumerable, + configurable: m.configurable }); } } - function a(l, d, f) { - const h = J(d, f); - h && o(l, d, f, h); + function a(u, d, f) { + const m = J(d, f); + m && o(u, d, f, m); } - function i(l, d) { + function i(u, d) { const f = Ze(d); - f && ut(De(f), (h) => o(l, d, h, f[h])); + f && ut(De(f), (m) => o(u, d, m, f[m])); } - function c(l, d, f) { - for (const h of De(f)) { - const p = J(d, h); + function c(u, d, f) { + for (const m of De(f)) { + const p = J(d, m); if (!p || p.get || p.set) continue; - const m = `${l}.${pe(h)}`, _ = f[h]; + const h = `${u}.${pe(m)}`, _ = f[m]; if (_ === !0) - a(m, d, h); + a(h, d, m); else if (_ === "*") - i(m, p.value); + i(h, p.value); else if (Ye(_)) - c(m, p.value, _); + c(h, p.value, _); else - throw v(`Unexpected override enablement plan ${m}`); + throw v(`Unexpected override enablement plan ${h}`); } } - let u; + let l; switch (e) { case "min": { - u = ti; + l = ti; break; } case "moderate": { - u = is; + l = is; break; } case "severe": { - u = ri; + l = ri; break; } default: throw v(`unrecognized overrideTaming ${e}`); } - c("root", t, u); + c("root", t, l); } -const { Fail: cn, quote: Er } = G, oi = /^(\w*[a-z])Locale([A-Z]\w*)$/, cs = { +const { Fail: cn, quote: Sr } = G, oi = /^(\w*[a-z])Locale([A-Z]\w*)$/, cs = { // See https://tc39.es/ecma262/#sec-string.prototype.localecompare localeCompare(t) { if (this === null || this === void 0) @@ -2513,7 +2513,7 @@ const { Fail: cn, quote: Er } = G, oi = /^(\w*[a-z])Locale([A-Z]\w*)$/, cs = { 'Cannot localeCompare with null or undefined "this" value' ); const e = `${this}`, r = `${t}`; - return e < r ? -1 : e > r ? 1 : (e === r || cn`expected ${Er(e)} and ${Er(r)} to compare`, 0); + return e < r ? -1 : e > r ? 1 : (e === r || cn`expected ${Sr(e)} and ${Sr(r)} to compare`, 0); }, toString() { return `${this}`; @@ -2532,13 +2532,13 @@ function ii(t, e = "safe") { for (const o of Dt(n)) { const a = Pn(oi, o); if (a) { - typeof n[o] == "function" || cn`expected ${Er(o)} to be a function`; + typeof n[o] == "function" || cn`expected ${Sr(o)} to be a function`; const i = `${a[1]}${a[2]}`, c = n[i]; - typeof c == "function" || cn`function ${Er(i)} not found`, M(n, o, { value: c }); + typeof c == "function" || cn`function ${Sr(i)} not found`, M(n, o, { value: c }); } } } - M(So.prototype, "toLocaleString", { + M(Eo.prototype, "toLocaleString", { value: ai }); } @@ -2690,7 +2690,7 @@ ${o} ), pi = new Cr( Cn, ps -), hs = (t) => { +), ms = (t) => { const e = { // inherit scopeTerminator behavior ...ps, @@ -2713,8 +2713,8 @@ ${o} r ); }; -y(hs); -const { Fail: hi } = G, mi = () => { +y(ms); +const { Fail: mi } = G, hi = () => { const t = z(null), e = y({ eval: { get() { @@ -2727,7 +2727,7 @@ const { Fail: hi } = G, mi = () => { evalScope: t, allowNextEvalToBeUnsafe() { const { revoked: n } = r; - n !== null && hi`a handler did not reset allowNextEvalToBeUnsafe ${n.err}`, F(t, e); + n !== null && mi`a handler did not reset allowNextEvalToBeUnsafe ${n.err}`, F(t, e); }, /** @type {null | { err: any }} */ revoked: null @@ -2754,15 +2754,15 @@ function On(t, e) { return An(Tn(t, 0, r), ` `).length + n; } -const ms = new We("(?:)", "g"), gs = (t) => { - const e = On(t, ms); +const hs = new We("(?:)", "g"), gs = (t) => { + const e = On(t, hs); if (e < 0) return t; const r = Rn(t); throw tr( `Possible HTML comment rejected at ${r}:${e}. (SES_HTML_COMMENT_REJECTED)` ); -}, ys = (t) => vr(t, ms, (r) => r[0] === "<" ? "< ! --" : "-- >"), vs = new We( +}, ys = (t) => vr(t, hs, (r) => r[0] === "<" ? "< ! --" : "-- >"), vs = new We( "(^|[^.]|\\.\\.\\.)\\bimport(\\s*(?:\\(|/[/*]))", "g" ), _s = (t) => { @@ -2784,7 +2784,7 @@ const ms = new We("(?:)", "g"), gs = (t) => { throw tr( `Possible direct eval expression rejected at ${r}:${e}. (SES_EVAL_REJECTED)` ); -}, Es = (t) => (t = gs(t), t = _s(t), t), Ss = (t, e) => { +}, Ss = (t) => (t = gs(t), t = _s(t), t), Es = (t, e) => { for (const r of e) t = r(t); return t; @@ -2795,8 +2795,8 @@ y({ rejectImportExpressions: y(_s), evadeImportExpressionTest: y(bs), rejectSomeDirectEvalExpressions: y(ws), - mandatoryTransforms: y(Es), - applyTransforms: y(Ss) + mandatoryTransforms: y(Ss), + applyTransforms: y(Es) }); const vi = [ // 11.6.2.1 Keywords @@ -2918,49 +2918,49 @@ const wi = (t) => { } `); return ne(a, t, []); -}, { Fail: Ei } = G, Mn = ({ +}, { Fail: Si } = G, Mn = ({ globalObject: t, moduleLexicals: e = {}, globalTransforms: r = [], sloppyGlobalsMode: n = !1 }) => { - const o = n ? hs(t) : pi, a = mi(), { evalScope: i } = a, c = y({ + const o = n ? ms(t) : pi, a = hi(), { evalScope: i } = a, c = y({ evalScope: i, moduleLexicals: e, globalObject: t, scopeTerminator: o }); - let u; - const l = () => { - u || (u = wi(c)); + let l; + const u = () => { + l || (l = wi(c)); }; - return { safeEvaluate: (f, h) => { - const { localTransforms: p = [] } = h || {}; - l(), f = Ss(f, [ + return { safeEvaluate: (f, m) => { + const { localTransforms: p = [] } = m || {}; + u(), f = Es(f, [ ...p, ...r, - Es + Ss ]); - let m; + let h; try { - return a.allowNextEvalToBeUnsafe(), ne(u, t, [f]); + return a.allowNextEvalToBeUnsafe(), ne(l, t, [f]); } catch (_) { - throw m = _, _; + throw h = _, _; } finally { const _ = "eval" in i; - delete i.eval, _ && (a.revoked = { err: m }, Ei`handler did not reset allowNextEvalToBeUnsafe ${m}`); + delete i.eval, _ && (a.revoked = { err: h }, Si`handler did not reset allowNextEvalToBeUnsafe ${h}`); } } }; -}, Si = ") { [native code] }"; +}, Ei = ") { [native code] }"; let Yr; const xs = () => { if (Yr === void 0) { const t = new $t(); - M(En, "toString", { + M(Sn, "toString", { value: { toString() { - const r = Ea(this); - return Lo(r, Si) || !or(t, this) ? r : `function ${this.name}() { [native code] }`; + const r = Sa(this); + return Lo(r, Ei) || !or(t, this) ? r : `function ${this.name}() { [native code] }`; } }.toString }), Yr = y( @@ -3046,12 +3046,12 @@ const Ln = y([ ]), ki = (t, { shouldResetForDebugging: e = !1 } = {}) => { e && t.resetErrorTagNum(); let r = []; - const n = mt( + const n = ht( se(ks, ([i, c]) => { - const u = (...l) => { - X(r, [i, ...l]); + const l = (...u) => { + X(r, [i, ...u]); }; - return M(u, "name", { value: i }), [i, y(u)]; + return M(l, "name", { value: i }), [i, y(l)]; }) ); y(n); @@ -3075,38 +3075,38 @@ y(it); const Dn = (t, e) => { if (!t) return; - const { getStackString: r, tagError: n, takeMessageLogArgs: o, takeNoteLogArgsArray: a } = e, i = (E, T) => se(E, (x) => Dr(x) ? (X(T, x), `(${n(x)})`) : x), c = (E, T, N, x, D) => { + const { getStackString: r, tagError: n, takeMessageLogArgs: o, takeNoteLogArgsArray: a } = e, i = (S, T) => se(S, (x) => Dr(x) ? (X(T, x), `(${n(x)})`) : x), c = (S, T, N, x, D) => { const B = n(T), H = N === it.MESSAGE ? `${B}:` : `${B} ${N}`, K = i(x, D); - t[E](H, ...K); - }, u = (E, T, N = void 0) => { + t[S](H, ...K); + }, l = (S, T, N = void 0) => { if (T.length === 0) return; if (T.length === 1 && N === void 0) { - f(E, T[0]); + f(S, T[0]); return; } let x; T.length === 1 ? x = "Nested error" : x = `Nested ${T.length} errors`, N !== void 0 && (x = `${x} under ${N}`), t.group(x); try { for (const D of T) - f(E, D); + f(S, D); } finally { t.groupEnd(); } - }, l = new $t(), d = (E) => (T, N) => { + }, u = new $t(), d = (S) => (T, N) => { const x = []; - c(E, T, it.NOTE, N, x), u(E, x, n(T)); - }, f = (E, T) => { - if (or(l, T)) + c(S, T, it.NOTE, N, x), l(S, x, n(T)); + }, f = (S, T) => { + if (or(u, T)) return; const N = n(T); - Fr(l, T); + Fr(u, T); const x = [], D = o(T), B = a( T, - d(E) + d(S) ); - D === void 0 ? t[E](`${N}:`, T.message) : c( - E, + D === void 0 ? t[S](`${N}:`, T.message) : c( + S, T, it.MESSAGE, D, @@ -3115,25 +3115,25 @@ const Dn = (t, e) => { let H = r(T); typeof H == "string" && H.length >= 1 && !Lo(H, ` `) && (H += ` -`), t[E](H), T.cause && c(E, T, it.CAUSE, [T.cause], x), T.errors && c(E, T, it.ERRORS, T.errors, x); +`), t[S](H), T.cause && c(S, T, it.CAUSE, [T.cause], x), T.errors && c(S, T, it.ERRORS, T.errors, x); for (const K of B) - c(E, T, it.NOTE, K, x); - u(E, x, N); - }, h = se(Ln, ([E, T]) => { + c(S, T, it.NOTE, K, x); + l(S, x, N); + }, m = se(Ln, ([S, T]) => { const N = (...x) => { const D = [], B = i(x, D); - t[E](...B), u(E, D); + t[S](...B), l(S, D); }; - return M(N, "name", { value: E }), [E, y(N)]; + return M(N, "name", { value: S }), [S, y(N)]; }), p = Ke( Fn, - ([E, T]) => E in t - ), m = se(p, ([E, T]) => { + ([S, T]) => S in t + ), h = se(p, ([S, T]) => { const N = (...x) => { - t[E](...x); + t[S](...x); }; - return M(N, "name", { value: E }), [E, y(N)]; - }), _ = mt([...h, ...m]); + return M(N, "name", { value: S }), [S, y(N)]; + }), _ = ht([...m, ...h]); return ( /** @type {VirtualConsole} */ y(_) @@ -3144,26 +3144,26 @@ const Pi = (t, e, r) => { const [n, ...o] = An(t, e), a = Oo(o, (i) => [e, ...r, i]); return ["", n, ...a]; }, Ps = (t) => y((r) => { - const n = [], o = (...u) => (n.length > 0 && (u = Oo( - u, - (l) => typeof l == "string" && Fo(l, ` -`) ? Pi(l, ` -`, n) : [l] - ), u = [...n, ...u]), r(...u)), a = (u, l) => ({ [u]: (...d) => l(...d) })[u], i = mt([ - ...se(Ln, ([u]) => [ - u, - a(u, o) + const n = [], o = (...l) => (n.length > 0 && (l = Oo( + l, + (u) => typeof u == "string" && Fo(u, ` +`) ? Pi(u, ` +`, n) : [u] + ), l = [...n, ...l]), r(...l)), a = (l, u) => ({ [l]: (...d) => u(...d) })[l], i = ht([ + ...se(Ln, ([l]) => [ + l, + a(l, o) ]), - ...se(Fn, ([u]) => [ - u, - a(u, (...l) => o(u, ...l)) + ...se(Fn, ([l]) => [ + l, + a(l, (...u) => o(l, ...u)) ]) ]); - for (const u of ["group", "groupCollapsed"]) - i[u] && (i[u] = a(u, (...l) => { - l.length >= 1 && o(...l), X(n, " "); + for (const l of ["group", "groupCollapsed"]) + i[l] && (i[l] = a(l, (...u) => { + u.length >= 1 && o(...u), X(n, " "); })); - return i.groupEnd && (i.groupEnd = a("groupEnd", (...u) => { + return i.groupEnd && (i.groupEnd = a("groupEnd", (...l) => { gr(n); })), harden(i), Dn( /** @type {VirtualConsole} */ @@ -3176,9 +3176,9 @@ const Ti = (t, e, r = void 0) => { const n = Ke( ks, ([i, c]) => i in t - ), o = se(n, ([i, c]) => [i, y((...l) => { - (c === void 0 || e.canLog(c)) && t[i](...l); - })]), a = mt(o); + ), o = se(n, ([i, c]) => [i, y((...u) => { + (c === void 0 || e.canLog(c)) && t[i](...u); + })]), a = ht(o); return ( /** @type {VirtualConsole} */ y(a) @@ -3204,11 +3204,11 @@ const io = (t) => { }, unhandledRejectionHandler: (d, f) => { e += 1; - const h = e; - $e(r, h, d), ie(o, f, h), xa(i, f, h, f); + const m = e; + $e(r, m, d), ie(o, f, m), xa(i, f, m, f); }, processTerminationHandler: () => { - for (const [d, f] of ha(r)) + for (const [d, f] of ma(r)) n(d), t(f); } }; @@ -3228,15 +3228,15 @@ const io = (t) => { // Make a good-enough console for eshost (including only functions that // log at a specific level with no special argument interpretation). // https://console.spec.whatwg.org/#logging - ((l) => y({ debug: l, log: l, info: l, warn: l, error: l }))( + ((u) => y({ debug: u, log: u, info: u, warn: u, error: u }))( // eslint-disable-next-line no-undef co(k.print) ) ) : void 0 ); if (a && a.log) - for (const l of ["warn", "error"]) - a[l] || M(a, l, { + for (const u of ["warn", "error"]) + a[u] || M(a, u, { value: co(a.log, a) }); const i = ( @@ -3244,14 +3244,14 @@ const io = (t) => { t === "unsafe" ? a : Dn(a, o) ), c = k.process || void 0; if (e !== "none" && typeof c == "object" && typeof c.on == "function") { - let l; + let u; if (e === "platform" || e === "exit") { const { exit: d } = c; - typeof d == "function" || Jr("missing process.exit"), l = () => d(c.exitCode || -1); + typeof d == "function" || Jr("missing process.exit"), u = () => d(c.exitCode || -1); } else - e === "abort" && (l = c.abort, typeof l == "function" || Jr("missing process.abort")); + e === "abort" && (u = c.abort, typeof u == "function" || Jr("missing process.abort")); c.on("uncaughtException", (d) => { - i.error(d), l && l(); + i.error(d), u && u(); }); } if (r !== "none" && typeof c == "object" && typeof c.on == "function") { @@ -3260,18 +3260,18 @@ const io = (t) => { }); d && (c.on("unhandledRejection", d.unhandledRejectionHandler), c.on("rejectionHandled", d.rejectionHandledHandler), c.on("exit", d.processTerminationHandler)); } - const u = k.window || void 0; - if (e !== "none" && typeof u == "object" && typeof u.addEventListener == "function" && u.addEventListener("error", (l) => { - l.preventDefault(), i.error(l.error), (e === "exit" || e === "abort") && (u.location.href = "about:blank"); - }), r !== "none" && typeof u == "object" && typeof u.addEventListener == "function") { + const l = k.window || void 0; + if (e !== "none" && typeof l == "object" && typeof l.addEventListener == "function" && l.addEventListener("error", (u) => { + u.preventDefault(), i.error(u.error), (e === "exit" || e === "abort") && (l.location.href = "about:blank"); + }), r !== "none" && typeof l == "object" && typeof l.addEventListener == "function") { const d = io((f) => { i.error("SES_UNHANDLED_REJECTION:", f); }); - d && (u.addEventListener("unhandledrejection", (f) => { + d && (l.addEventListener("unhandledrejection", (f) => { f.preventDefault(), d.unhandledRejectionHandler(f.reason, f.promise); - }), u.addEventListener("rejectionhandled", (f) => { + }), l.addEventListener("rejectionhandled", (f) => { f.preventDefault(), d.rejectionHandledHandler(f.promise); - }), u.addEventListener("beforeunload", (f) => { + }), l.addEventListener("beforeunload", (f) => { d.processTerminationHandler(); })); } @@ -3300,7 +3300,7 @@ const io = (t) => { "toString" // TODO replace to use only whitelisted info ], Ci = (t) => { - const r = mt(se(Ii, (n) => { + const r = ht(se(Ii, (n) => { const o = t[n]; return [n, () => ne(o, t, [])]; })); @@ -3329,21 +3329,21 @@ const io = (t) => { return t; }, zi = (t, e, r, n) => { const o = t.captureStackTrace, a = (p) => n === "verbose" ? !0 : Fi(p.getFileName()), i = (p) => { - let m = `${p}`; - return n === "concise" && (m = Zi(m)), ` - at ${m}`; - }, c = (p, m) => Rt( - se(Ke(m, a), i), + let h = `${p}`; + return n === "concise" && (h = Zi(h)), ` + at ${h}`; + }, c = (p, h) => Rt( + se(Ke(h, a), i), "" - ), u = new Me(), l = { + ), l = new Me(), u = { // The optional `optFn` argument is for cutting off the bottom of // the stack --- for capturing the stack only above the topmost // call to that function. Since this isn't the "real" captureStackTrace // but instead calls the real one, if no other cutoff is provided, // we cut this one off. - captureStackTrace(p, m = l.captureStackTrace) { + captureStackTrace(p, h = u.captureStackTrace) { if (typeof o == "function") { - ne(o, t, [p, m]); + ne(o, t, [p, h]); return; } Co(p, "stack", ""); @@ -3353,34 +3353,34 @@ const io = (t) => { // string associated with an error. // See https://tc39.es/proposal-error-stacks/ getStackString(p) { - let m = L(u, p); - if (m === void 0 && (p.stack, m = L(u, p), m || (m = { stackString: "" }, ie(u, p, m))), m.stackString !== void 0) - return m.stackString; - const _ = c(p, m.callSites); - return ie(u, p, { stackString: _ }), _; + let h = L(l, p); + if (h === void 0 && (p.stack, h = L(l, p), h || (h = { stackString: "" }, ie(l, p, h))), h.stackString !== void 0) + return h.stackString; + const _ = c(p, h.callSites); + return ie(l, p, { stackString: _ }), _; }, - prepareStackTrace(p, m) { + prepareStackTrace(p, h) { if (r === "unsafe") { - const _ = c(p, m); - return ie(u, p, { stackString: _ }), `${p}${_}`; + const _ = c(p, h); + return ie(l, p, { stackString: _ }), `${p}${_}`; } else - return ie(u, p, { callSites: m }), ""; + return ie(l, p, { callSites: h }), ""; } - }, d = l.prepareStackTrace; + }, d = u.prepareStackTrace; t.prepareStackTrace = d; - const f = new $t([d]), h = (p) => { + const f = new $t([d]), m = (p) => { if (or(f, p)) return p; - const m = { - prepareStackTrace(_, E) { - return ie(u, _, { callSites: E }), p(_, $i(E)); + const h = { + prepareStackTrace(_, S) { + return ie(l, _, { callSites: S }), p(_, $i(S)); } }; - return Fr(f, m.prepareStackTrace), m.prepareStackTrace; + return Fr(f, h.prepareStackTrace), h.prepareStackTrace; }; return F(e, { captureStackTrace: { - value: l.captureStackTrace, + value: u.captureStackTrace, writable: !0, enumerable: !1, configurable: !0 @@ -3391,15 +3391,15 @@ const io = (t) => { }, set(p) { if (typeof p == "function") { - const m = h(p); - t.prepareStackTrace = m; + const h = m(p); + t.prepareStackTrace = h; } else t.prepareStackTrace = d; }, enumerable: !1, configurable: !0 } - }), l.getStackString; + }), u.getStackString; }, lo = J(ue.prototype, "stack"), uo = lo && lo.get, Gi = { getStackString(t) { return typeof uo == "function" ? ne(uo, t, []) : "stack" in t ? `${t.stack}` : ""; @@ -3410,10 +3410,10 @@ function Bi(t = "safe", e = "concise") { throw v(`unrecognized errorTaming ${t}`); if (e !== "concise" && e !== "verbose") throw v(`unrecognized stackFiltering ${e}`); - const r = ue.prototype, n = typeof ue.captureStackTrace == "function" ? "v8" : "unknown", { captureStackTrace: o } = ue, a = (l = {}) => { - const d = function(...h) { + const r = ue.prototype, n = typeof ue.captureStackTrace == "function" ? "v8" : "unknown", { captureStackTrace: o } = ue, a = (u = {}) => { + const d = function(...m) { let p; - return new.target === void 0 ? p = ne(ue, this, h) : p = mr(ue, h, new.target), n === "v8" && ne(o, ue, [p, d]), p; + return new.target === void 0 ? p = ne(ue, this, m) : p = hr(ue, m, new.target), n === "v8" && ne(o, ue, [p, d]), p; }; return F(d, { length: { value: 1 }, @@ -3428,17 +3428,17 @@ function Bi(t = "safe", e = "concise") { F(r, { constructor: { value: c } }); - for (const l of os) - ko(l, c); + for (const u of os) + ko(u, c); F(i, { stackTraceLimit: { get() { if (typeof ue.stackTraceLimit == "number") return ue.stackTraceLimit; }, - set(l) { - if (typeof l == "number" && typeof ue.stackTraceLimit == "number") { - ue.stackTraceLimit = l; + set(u) { + if (typeof u == "number" && typeof ue.stackTraceLimit == "number") { + ue.stackTraceLimit = u; return; } }, @@ -3450,7 +3450,7 @@ function Bi(t = "safe", e = "concise") { stackTraceLimit: { get() { }, - set(l) { + set(u) { }, enumerable: !1, configurable: !0 @@ -3460,14 +3460,14 @@ function Bi(t = "safe", e = "concise") { get() { return () => ""; }, - set(l) { + set(u) { }, enumerable: !1, configurable: !0 }, captureStackTrace: { - value: (l, d) => { - M(l, "stack", { + value: (u, d) => { + M(u, "stack", { value: "" }); }, @@ -3476,8 +3476,8 @@ function Bi(t = "safe", e = "concise") { configurable: !0 } }); - let u = Gi.getStackString; - return n === "v8" ? u = zi( + let l = Gi.getStackString; + return n === "v8" ? l = zi( ue, i, t, @@ -3485,12 +3485,12 @@ function Bi(t = "safe", e = "concise") { ) : t === "unsafe" ? F(r, { stack: { get() { - return u(this); + return l(this); }, - set(l) { + set(u) { F(this, { stack: { - value: l, + value: u, writable: !0, enumerable: !0, configurable: !0 @@ -3503,10 +3503,10 @@ function Bi(t = "safe", e = "concise") { get() { return `${this}`; }, - set(l) { + set(u) { F(this, { stack: { - value: l, + value: u, writable: !0, enumerable: !0, configurable: !0 @@ -3515,7 +3515,7 @@ function Bi(t = "safe", e = "concise") { } } }), { - "%InitialGetStackString%": u, + "%InitialGetStackString%": l, "%InitialError%": i, "%SharedError%": c }; @@ -3555,20 +3555,20 @@ const Ki = (t, e) => y({ n[o] = a; } return y(n); -}, fo = (t, e, r, n, o, a, i, c, u) => { - const { resolveHook: l, moduleRecords: d } = L( +}, fo = (t, e, r, n, o, a, i, c, l) => { + const { resolveHook: u, moduleRecords: d } = L( t, r ), f = Yi( o.imports, - l, + u, n - ), h = y({ + ), m = y({ compartment: r, staticModuleRecord: o, moduleSpecifier: n, resolvedImports: f, - importMeta: u + importMeta: l }); for (const p of Po(f)) a(Ut, [ @@ -3580,21 +3580,21 @@ const Ki = (t, e) => y({ i, c ]); - return $e(d, n, h), h; + return $e(d, n, m), m; }; function* Ji(t, e, r, n, o, a, i) { - const { importHook: c, importNowHook: u, moduleMap: l, moduleMapHook: d, moduleRecords: f } = L(t, r); - let h = l[n]; - if (h === void 0 && d !== void 0 && (h = d(n)), typeof h == "string") + const { importHook: c, importNowHook: l, moduleMap: u, moduleMapHook: d, moduleRecords: f } = L(t, r); + let m = u[n]; + if (m === void 0 && d !== void 0 && (m = d(n)), typeof m == "string") G.fail( un`Cannot map module ${xe(n)} to ${xe( - h + m )} in parent compartment, not yet implemented`, v ); - else if (h !== void 0) { - const m = L(e, h); - m === void 0 && G.fail( + else if (m !== void 0) { + const h = L(e, m); + h === void 0 && G.fail( un`Cannot map module ${xe( n )} because the value is not a module exports namespace, or is from another realm`, @@ -3603,8 +3603,8 @@ function* Ji(t, e, r, n, o, a, i) { const _ = yield Ut( t, e, - m.compartment, - m.specifier, + h.compartment, + h.specifier, o, a, i @@ -3615,7 +3615,7 @@ function* Ji(t, e, r, n, o, a, i) { return Ue(f, n); const p = yield a( c, - u + l )(n); if ((p === null || typeof p != "object") && Hi`importHook must return a promise for an object, for module ${xe( n @@ -3626,16 +3626,16 @@ function* Ji(t, e, r, n, o, a, i) { "Cannot redirect to an explicit record with a specified compartment" ); const { - compartment: m = r, + compartment: h = r, specifier: _ = n, - record: E, + record: S, importMeta: T } = p, N = fo( t, e, - m, + h, _, - E, + S, o, a, i, @@ -3648,7 +3648,7 @@ function* Ji(t, e, r, n, o, a, i) { throw v( "Cannot redirect to an implicit record with a specified importMeta" ); - const m = yield Ut( + const h = yield Ut( t, e, p.compartment, @@ -3657,7 +3657,7 @@ function* Ji(t, e, r, n, o, a, i) { a, i ); - return $e(f, n, m), m; + return $e(f, n, h), h; } throw v("Unnexpected RedirectStaticModuleInterface record shape"); } @@ -3677,10 +3677,10 @@ const Ut = (t, e, r, n, o, a, i) => { t, r ); - let u = Ue(i, r); - u === void 0 && (u = new Pe(), $e(i, r, u)); - let l = Ue(u, n); - return l !== void 0 || (l = a(Wi, qi)( + let l = Ue(i, r); + l === void 0 && (l = new Pe(), $e(i, r, l)); + let u = Ue(l, n); + return u !== void 0 || (u = a(Wi, qi)( Ji, [ t, @@ -3699,12 +3699,12 @@ const Ut = (t, e, r, n, o, a, i) => { )}` ), d; } - ), $e(u, n, l)), l; + ), $e(l, n, u)), u; }; function Xi() { const t = new Ct(), e = []; return { enqueueJob: (o, a) => { - Sn( + En( t, jo(o(...a), Vi, (i) => { X(e, i); @@ -3741,9 +3741,9 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { ec, a ]); - const u = await c(); + const l = await c(); Ts({ - errors: u, + errors: l, errorPrefix: `Failed to load module ${xe(n)} in package ${xe( o )}` @@ -3752,9 +3752,9 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { const { name: o } = L( t, r - ), a = new Pe(), i = [], c = (u, l) => { + ), a = new Pe(), i = [], c = (l, u) => { try { - u(...l); + l(...u); } catch (d) { X(i, d); } @@ -3913,41 +3913,41 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { // Note default on } = r, c = [...n]; o === !0 && X(c, ys), a === !0 && X(c, bs), i === !0 && X(c, ws); - const { safeEvaluate: u } = nc( + const { safeEvaluate: l } = nc( t, r ); - return u(e, { + return l(e, { localTransforms: c }); }, { quote: cr } = G, oc = (t, e, r, n, o, a) => { - const { exportsProxy: i, exportsTarget: c, activate: u } = Un( + const { exportsProxy: i, exportsTarget: c, activate: l } = Un( r, L(t, r), n, o - ), l = z(null); + ), u = z(null); if (e.exports) { - if (!St(e.exports) || da(e.exports, (f) => typeof f != "string")) + if (!Et(e.exports) || da(e.exports, (f) => typeof f != "string")) throw v( `SES third-party static module record "exports" property must be an array of strings for module ${o}` ); ut(e.exports, (f) => { - let h = c[f]; + let m = c[f]; const p = []; M(c, f, { - get: () => h, - set: (E) => { - h = E; + get: () => m, + set: (S) => { + m = S; for (const T of p) - T(E); + T(S); }, enumerable: !0, configurable: !1 - }), l[f] = (E) => { - X(p, E), E(h); + }), u[f] = (S) => { + X(p, S), S(m); }; - }), l["*"] = (f) => { + }), u["*"] = (f) => { f(c); }; } @@ -3955,13 +3955,13 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { activated: !1 }; return y({ - notifiers: l, + notifiers: u, exportsProxy: i, execute() { if (Io(d, "errorFromExecute")) throw d.errorFromExecute; if (!d.activated) { - u(), d.activated = !0; + l(), d.activated = !0; try { e.execute( c, @@ -3981,22 +3981,22 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { staticModuleRecord: i, importMeta: c } = r, { - reexports: u = [], - __syncModuleProgram__: l, + reexports: l = [], + __syncModuleProgram__: u, __fixedExportMap__: d = {}, __liveExportMap__: f = {}, - __reexportMap__: h = {}, + __reexportMap__: m = {}, __needsImportMeta__: p = !1, - __syncModuleFunctor__: m - } = i, _ = L(t, o), { __shimTransforms__: E, importMetaHook: T } = _, { exportsProxy: N, exportsTarget: x, activate: D } = Un( + __syncModuleFunctor__: h + } = i, _ = L(t, o), { __shimTransforms__: S, importMetaHook: T } = _, { exportsProxy: N, exportsTarget: x, activate: D } = Un( o, _, e, a - ), B = z(null), H = z(null), K = z(null), ze = z(null), he = z(null); - c && $r(he, c), p && T && T(a, he); + ), B = z(null), H = z(null), K = z(null), ze = z(null), me = z(null); + c && $r(me, c), p && T && T(a, me); const Ge = z(null), rt = z(null); - ut(re(d), ([me, [V]]) => { + ut(re(d), ([he, [V]]) => { let W = Ge[V]; if (!W) { let ee, te = !0, ce = []; @@ -4012,8 +4012,8 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { ee = we; const Hn = ce; ce = null, te = !1; - for (const Ee of Hn || []) - Ee(we); + for (const Se of Hn || []) + Se(we); return we; }); W = { @@ -4023,39 +4023,39 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { } }, Ge[V] = W, K[V] = be; } - B[me] = { + B[he] = { get: W.get, set: void 0, enumerable: !0, configurable: !1 - }, rt[me] = W.notify; + }, rt[he] = W.notify; }), ut( re(f), - ([me, [V, W]]) => { + ([he, [V, W]]) => { let ee = Ge[V]; if (!ee) { let te, ce = !0; const Y = [], be = () => { if (ce) throw lt( - `binding ${cr(me)} not yet initialized` + `binding ${cr(he)} not yet initialized` ); return te; - }, gt = y((Ee) => { - te = Ee, ce = !1; + }, gt = y((Se) => { + te = Se, ce = !1; for (const zr of Y) - zr(Ee); - }), we = (Ee) => { + zr(Se); + }), we = (Se) => { if (ce) throw lt(`binding ${cr(V)} not yet initialized`); - te = Ee; + te = Se; for (const zr of Y) - zr(Ee); + zr(Se); }; ee = { get: be, - notify: (Ee) => { - Ee !== gt && (X(Y, Ee), ce || Ee(te)); + notify: (Se) => { + Se !== gt && (X(Y, Se), ce || Se(te)); } }, Ge[V] = ee, W && M(H, V, { get: be, @@ -4064,22 +4064,22 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { configurable: !1 }), ze[V] = gt; } - B[me] = { + B[he] = { get: ee.get, set: void 0, enumerable: !0, configurable: !1 - }, rt[me] = ee.notify; + }, rt[he] = ee.notify; } ); - const Be = (me) => { - me(x); + const Be = (he) => { + he(x); }; rt["*"] = Be; - function ar(me) { + function ar(he) { const V = z(null); V.default = !1; - for (const [W, ee] of me) { + for (const [W, ee] of he) { const te = Ue(n, W); te.execute(); const { notifiers: ce } = te; @@ -4092,13 +4092,13 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { for (const we of be) gt(we); } - if (Mr(u, W)) + if (Mr(l, W)) for (const [Y, be] of re( ce )) V[Y] === void 0 ? V[Y] = be : V[Y] = !1; - if (h[W]) - for (const [Y, be] of h[W]) + if (m[W]) + for (const [Y, be] of m[W]) V[be] = ce[Y]; } for (const [W, ee] of re(V)) @@ -4120,23 +4120,23 @@ const Qi = (t, e) => e, ec = (t, e) => t, po = async (t, e, r, n) => { ), y(x), D(); } let Ot; - m !== void 0 ? Ot = m : Ot = As(_, l, { + h !== void 0 ? Ot = h : Ot = As(_, u, { globalObject: o.globalThis, - transforms: E, + transforms: S, __moduleShimLexicals__: H }); let Gn = !1, Bn; function Bs() { if (Ot) { - const me = Ot; + const he = Ot; Ot = null; try { - me( + he( y({ imports: y(ar), onceVar: y(K), liveVar: y(ze), - importMeta: he + importMeta: me }) ); } catch (V) { @@ -4180,7 +4180,7 @@ function cc(t) { } function lc(t, e) { const { exports: r } = t; - St(r) || ct`Property 'exports' of a third-party static module record must be an array, got ${q( + Et(r) || ct`Property 'exports' of a third-party static module record must be an array, got ${q( r )}, for module ${q(e)}`; } @@ -4189,11 +4189,11 @@ function uc(t, e) { t )}, for module ${q(e)}`; const { imports: r, exports: n, reexports: o = [] } = t; - St(r) || ct`Property 'imports' of a static module record must be an array, got ${q( + Et(r) || ct`Property 'imports' of a static module record must be an array, got ${q( r - )}, for module ${q(e)}`, St(n) || ct`Property 'exports' of a precompiled module record must be an array, got ${q( + )}, for module ${q(e)}`, Et(n) || ct`Property 'exports' of a precompiled module record must be an array, got ${q( n - )}, for module ${q(e)}`, St(o) || ct`Property 'reexports' of a precompiled module record must be an array if present, got ${q( + )}, for module ${q(e)}`, Et(o) || ct`Property 'reexports' of a precompiled module record must be an array if present, got ${q( o )}, for module ${q(e)}`; } @@ -4202,17 +4202,17 @@ const dc = (t, e, r) => { if (Lr(c, o)) return Ue(c, o); uc(i, o); - const u = new Pe(); - let l; + const l = new Pe(); + let u; if (ac(i)) - ic(i, o), l = sc( + ic(i, o), u = sc( t, e, r, - u + l ); else if (cc(i)) - lc(i, o), l = oc( + lc(i, o), u = oc( t, i, n, @@ -4226,17 +4226,17 @@ const dc = (t, e, r) => { i )}` ); - $e(c, o, l); + $e(c, o, u); for (const [d, f] of re(a)) { - const h = Is( + const m = Is( t, e, n, f ); - $e(u, d, h); + $e(l, d, m); } - return l; + return u; }, { quote: Xr } = G, bt = new Me(), Ce = new Me(), lr = (t) => { const { importHook: e, resolveHook: r } = L(Ce, t); if (typeof e != "function" || typeof r != "function") @@ -4247,7 +4247,7 @@ const dc = (t, e, r) => { throw v( "Compartment.prototype.constructor is not a valid constructor." ); -}, ho = (t, e) => { +}, mo = (t, e) => { const { execute: r, exportsProxy: n } = Is( Ce, bt, @@ -4294,7 +4294,7 @@ const dc = (t, e, r) => { throw v("first argument of import() must be a string"); return lr(this), jo( po(Ce, bt, this, t), - () => ({ namespace: ho( + () => ({ namespace: mo( /** @type {Compartment} */ this, t @@ -4309,7 +4309,7 @@ const dc = (t, e, r) => { importNow(t) { if (typeof t != "string") throw v("first argument of importNow() must be a string"); - return lr(this), tc(Ce, bt, this, t), ho( + return lr(this), tc(Ce, bt, this, t), mo( /** @type {Compartment} */ this, t @@ -4335,14 +4335,14 @@ const dn = (t, e, r) => { ); const { name: c = "", - transforms: u = [], - __shimTransforms__: l = [], + transforms: l = [], + __shimTransforms__: u = [], resolveHook: d, importHook: f, - importNowHook: h, + importNowHook: m, moduleMapHook: p, - importMetaHook: m - } = i, _ = [...u, ...l], E = new Pe(), T = new Pe(), N = new Pe(); + importMetaHook: h + } = i, _ = [...l, ...u], S = new Pe(), T = new Pe(), N = new Pe(); for (const [B, H] of re(a || {})) { if (typeof H == "string") throw v( @@ -4380,12 +4380,12 @@ const dn = (t, e, r) => { safeEvaluate: D, resolveHook: d, importHook: f, - importNowHook: h, + importNowHook: m, moduleMap: a, moduleMapHook: p, - importMetaHook: m, - moduleRecords: E, - __shimTransforms__: l, + importMetaHook: h, + moduleRecords: S, + __shimTransforms__: u, deferredExports: N, instances: T }); @@ -4399,10 +4399,10 @@ function fc() { return arguments; } const pc = () => { - const t = ve.prototype.constructor, e = J(fc(), "callee"), r = e && e.get, n = ba(new pe()), o = j(n), a = Rr[To] && ya(/./), i = a && j(a), c = fa([]), u = j(c), l = j(Ws), d = ma(new Pe()), f = j(d), h = ga(new Ct()), p = j(h), m = j(u); + const t = ve.prototype.constructor, e = J(fc(), "callee"), r = e && e.get, n = ba(new pe()), o = j(n), a = Rr[To] && ya(/./), i = a && j(a), c = fa([]), l = j(c), u = j(Ws), d = ha(new Pe()), f = j(d), m = ga(new Ct()), p = j(m), h = j(l); function* _() { } - const E = Qr(_), T = E.prototype; + const S = Qr(_), T = S.prototype; async function* N() { } const x = Qr( @@ -4410,40 +4410,40 @@ const pc = () => { ), D = x.prototype, B = D.prototype, H = j(B); async function K() { } - const ze = Qr(K), he = { + const ze = Qr(K), me = { "%InertFunction%": t, - "%ArrayIteratorPrototype%": u, + "%ArrayIteratorPrototype%": l, "%InertAsyncFunction%": ze, "%AsyncGenerator%": D, "%InertAsyncGeneratorFunction%": x, "%AsyncGeneratorPrototype%": B, "%AsyncIteratorPrototype%": H, "%Generator%": T, - "%InertGeneratorFunction%": E, - "%IteratorPrototype%": m, + "%InertGeneratorFunction%": S, + "%IteratorPrototype%": h, "%MapIteratorPrototype%": f, "%RegExpStringIteratorPrototype%": i, "%SetIteratorPrototype%": p, "%StringIteratorPrototype%": o, "%ThrowTypeError%": r, - "%TypedArray%": l, + "%TypedArray%": u, "%InertCompartment%": jn }; - return k.Iterator && (he["%IteratorHelperPrototype%"] = j( + return k.Iterator && (me["%IteratorHelperPrototype%"] = j( // eslint-disable-next-line @endo/no-polymorphic-call k.Iterator.from([]).take(0) - ), he["%WrapForValidIteratorPrototype%"] = j( + ), me["%WrapForValidIteratorPrototype%"] = j( // eslint-disable-next-line @endo/no-polymorphic-call k.Iterator.from({ next() { } }) - )), k.AsyncIterator && (he["%AsyncIteratorHelperPrototype%"] = j( + )), k.AsyncIterator && (me["%AsyncIteratorHelperPrototype%"] = j( // eslint-disable-next-line @endo/no-polymorphic-call k.AsyncIterator.from([]).take(0) - ), he["%WrapForValidAsyncIteratorPrototype%"] = j( + ), me["%WrapForValidAsyncIteratorPrototype%"] = j( // eslint-disable-next-line @endo/no-polymorphic-call k.AsyncIterator.from({ next() { } }) - )), he; + )), me; }, Cs = (t, e) => { if (e !== "safe" && e !== "unsafe") throw v(`unrecognized fakeHardenOption ${e}`); @@ -4453,8 +4453,8 @@ const pc = () => { return r.isFake = !0, y(r); }; y(Cs); -const hc = () => { - const t = Et, e = t.prototype, r = Sa(Et, void 0); +const mc = () => { + const t = St, e = t.prototype, r = Ea(St, void 0); F(e, { constructor: { value: r @@ -4463,20 +4463,20 @@ const hc = () => { }); const n = re( Ze(t) - ), o = mt( + ), o = ht( se(n, ([a, i]) => [ a, { ...i, configurable: !0 } ]) ); return F(r, o), { "%SharedSymbol%": r }; -}, mc = (t) => { +}, hc = (t) => { try { return t(), !1; } catch { return !0; } -}, mo = (t, e, r) => { +}, ho = (t, e, r) => { if (t === void 0) return !1; const n = J(t, e); @@ -4488,19 +4488,19 @@ const hc = () => { const i = "Seems to be a setter", c = { __proto__: null }; if (ne(a, c, [i]), c[e] !== i) return !1; - const u = { __proto__: t }; - return ne(a, u, [i]), u[e] !== i || !mc(() => ne(a, t, [r])) || "originalValue" in o || n.configurable === !1 ? !1 : (M(t, e, { + const l = { __proto__: t }; + return ne(a, l, [i]), l[e] !== i || !hc(() => ne(a, t, [r])) || "originalValue" in o || n.configurable === !1 ? !1 : (M(t, e, { value: r, writable: !0, enumerable: n.enumerable, configurable: !0 }), !0); }, gc = (t) => { - mo( + ho( t["%IteratorPrototype%"], "constructor", t.Iterator - ), mo( + ), ho( t["%IteratorPrototype%"], qe, "Iterator" @@ -4542,24 +4542,24 @@ const yc = Ba(), vc = () => { le("LOCKDOWN_CONSOLE_TAMING", "safe") ), overrideTaming: c = le("LOCKDOWN_OVERRIDE_TAMING", "moderate"), - stackFiltering: u = le("LOCKDOWN_STACK_FILTERING", "concise"), - domainTaming: l = le("LOCKDOWN_DOMAIN_TAMING", "safe"), + stackFiltering: l = le("LOCKDOWN_STACK_FILTERING", "concise"), + domainTaming: u = le("LOCKDOWN_DOMAIN_TAMING", "safe"), evalTaming: d = le("LOCKDOWN_EVAL_TAMING", "safeEval"), overrideDebug: f = Ke( An(le("LOCKDOWN_OVERRIDE_DEBUG", ""), ","), /** @param {string} debugName */ (Be) => Be !== "" ), - __hardenTaming__: h = le("LOCKDOWN_HARDEN_TAMING", "safe"), + __hardenTaming__: m = le("LOCKDOWN_HARDEN_TAMING", "safe"), dateTaming: p = "safe", // deprecated - mathTaming: m = "safe", + mathTaming: h = "safe", // deprecated ..._ } = t; d === "unsafeEval" || d === "safeEval" || d === "noEval" || go`lockdown(): non supported option evalTaming: ${vo(d)}`; - const E = De(_); - if (E.length === 0 || go`lockdown(): non supported option ${vo(E)}`, ur === void 0 || // eslint-disable-next-line @endo/no-polymorphic-call + const S = De(_); + if (S.length === 0 || go`lockdown(): non supported option ${vo(S)}`, ur === void 0 || // eslint-disable-next-line @endo/no-polymorphic-call G.fail( yo`Already locked down at ${ur} (SES_ALREADY_LOCKED_DOWN)`, v @@ -4572,18 +4572,18 @@ const yc = Ba(), vc = () => { throw v( "Already locked down but not by this SES instance (SES_MULTIPLE_INSTANCES)" ); - xi(l); - const N = xs(), { addIntrinsics: x, completePrototypes: D, finalIntrinsics: B } = as(), H = Cs(yc, h); - x({ harden: H }), x(Ja()), x(Xa(p)), x(Bi(e, u)), x(Qa(m)), x(ei(o)), x(hc()), x(pc()), D(); + xi(u); + const N = xs(), { addIntrinsics: x, completePrototypes: D, finalIntrinsics: B } = as(), H = Cs(yc, m); + x({ harden: H }), x(Ja()), x(Xa(p)), x(Bi(e, l)), x(Qa(h)), x(ei(o)), x(mc()), x(pc()), D(); const K = B(), ze = { __proto__: null }; typeof k.Buffer == "function" && (ze.Buffer = k.Buffer); - let he; - e !== "unsafe" && (he = K["%InitialGetStackString%"]); + let me; + e !== "unsafe" && (me = K["%InitialGetStackString%"]); const Ge = Ai( i, r, n, - he + me ); if (k.console = /** @type {Console} */ Ge.console, typeof /** @type {any} */ @@ -4657,18 +4657,18 @@ const bc = Ps(br), wc = ra( "MAKE_CAUSAL_CONSOLE_FROM_LOGGER_KEY_FOR_SES_AVA" ); k[wc] = bc; -const Ec = (t, e) => { +const Sc = (t, e) => { let r = { x: 0, y: 0 }, n = { x: 0, y: 0 }, o = { x: 0, y: 0 }; - const a = (u) => { - const { clientX: l, clientY: d } = u, f = l - o.x + n.x, h = d - o.y + n.y; - r = { x: f, y: h }, t.style.transform = `translate(${f}px, ${h}px)`, e == null || e(); + const a = (l) => { + const { clientX: u, clientY: d } = l, f = u - o.x + n.x, m = d - o.y + n.y; + r = { x: f, y: m }, t.style.transform = `translate(${f}px, ${m}px)`, e == null || e(); }, i = () => { document.removeEventListener("mousemove", a), document.removeEventListener("mouseup", i); - }, c = (u) => { - o = { x: u.clientX, y: u.clientY }, n = { x: r.x, y: r.y }, document.addEventListener("mousemove", a), document.addEventListener("mouseup", i); + }, c = (l) => { + o = { x: l.clientX, y: l.clientY }, n = { x: r.x, y: r.y }, document.addEventListener("mousemove", a), document.addEventListener("mouseup", i); }; return t.addEventListener("mousedown", c), i; -}, Sc = ":host{--spacing-4: .25rem;--spacing-8: calc(var(--spacing-4) * 2);--spacing-12: calc(var(--spacing-4) * 3);--spacing-16: calc(var(--spacing-4) * 4);--spacing-20: calc(var(--spacing-4) * 5);--spacing-24: calc(var(--spacing-4) * 6);--spacing-28: calc(var(--spacing-4) * 7);--spacing-32: calc(var(--spacing-4) * 8);--spacing-36: calc(var(--spacing-4) * 9);--spacing-40: calc(var(--spacing-4) * 10);--font-weight-regular: 400;--font-weight-bold: 500;--font-line-height-s: 1.2;--font-line-height-m: 1.4;--font-line-height-l: 1.5;--font-size-s: 12px;--font-size-m: 14px;--font-size-l: 16px}[data-theme]{background-color:var(--color-background-primary);color:var(--color-foreground-secondary)}.wrapper{box-sizing:border-box;display:flex;flex-direction:column;position:fixed;inset-block-start:var(--modal-block-start);inset-inline-end:var(--modal-inline-end);z-index:1000;padding:25px;border-radius:15px;border:2px solid var(--color-background-quaternary);box-shadow:0 0 10px #0000004d}.wrapper[data-theme=light]{border:none}.header{align-items:center;display:flex;justify-content:space-between;border-block-end:2px solid var(--color-background-quaternary);padding-block-end:var(--spacing-4)}button{background:transparent;border:0;cursor:pointer;padding:0}h1{font-size:var(--font-size-s);font-weight:var(--font-weight-bold);margin:0;margin-inline-end:var(--spacing-4);-webkit-user-select:none;user-select:none}iframe{border:none;inline-size:100%;block-size:100%}", xc = ` +}, Ec = ":host{--spacing-4: .25rem;--spacing-8: calc(var(--spacing-4) * 2);--spacing-12: calc(var(--spacing-4) * 3);--spacing-16: calc(var(--spacing-4) * 4);--spacing-20: calc(var(--spacing-4) * 5);--spacing-24: calc(var(--spacing-4) * 6);--spacing-28: calc(var(--spacing-4) * 7);--spacing-32: calc(var(--spacing-4) * 8);--spacing-36: calc(var(--spacing-4) * 9);--spacing-40: calc(var(--spacing-4) * 10);--font-weight-regular: 400;--font-weight-bold: 500;--font-line-height-s: 1.2;--font-line-height-m: 1.4;--font-line-height-l: 1.5;--font-size-s: 12px;--font-size-m: 14px;--font-size-l: 16px}[data-theme]{background-color:var(--color-background-primary);color:var(--color-foreground-secondary)}.wrapper{box-sizing:border-box;display:flex;flex-direction:column;position:fixed;inset-block-start:var(--modal-block-start);inset-inline-end:var(--modal-inline-end);z-index:1000;padding:25px;border-radius:15px;border:2px solid var(--color-background-quaternary);box-shadow:0 0 10px #0000004d}.header{align-items:center;display:flex;justify-content:space-between;border-block-end:2px solid var(--color-background-quaternary);padding-block-end:var(--spacing-4)}button{background:transparent;border:0;cursor:pointer;padding:0}h1{font-size:var(--font-size-s);font-weight:var(--font-weight-bold);margin:0;margin-inline-end:var(--spacing-4);-webkit-user-select:none;user-select:none}iframe{border:none;inline-size:100%;block-size:100%}", xc = ` `; var de, er; class kc extends HTMLElement { @@ -4679,11 +4679,11 @@ class kc extends HTMLElement { this.attachShadow({ mode: "open" }); } setTheme(r) { - Se(this, de) && Se(this, de).setAttribute("data-theme", r); + Ee(this, de) && Ee(this, de).setAttribute("data-theme", r); } disconnectedCallback() { var r; - (r = Se(this, er)) == null || r.call(this); + (r = Ee(this, er)) == null || r.call(this); } calculateZIndex() { const r = document.querySelectorAll("plugin-modal"), n = Array.from(r).filter((a) => a !== this).map((a) => Number(a.style.zIndex)), o = Math.max(...n, 0); @@ -4695,24 +4695,24 @@ class kc extends HTMLElement { throw new Error("title and iframe-src attributes are required"); if (!this.shadowRoot) throw new Error("Error creating shadow root"); - Br(this, de, document.createElement("div")), Se(this, de).classList.add("wrapper"), Se(this, de).style.inlineSize = `${o}px`, Se(this, de).style.blockSize = `${a}px`, Br(this, er, Ec(Se(this, de), () => { + Br(this, de, document.createElement("div")), Ee(this, de).classList.add("wrapper"), Ee(this, de).style.inlineSize = `${o}px`, Ee(this, de).style.blockSize = `${a}px`, Br(this, er, Sc(Ee(this, de), () => { this.calculateZIndex(); })); const i = document.createElement("div"); i.classList.add("header"); const c = document.createElement("h1"); c.textContent = r, i.appendChild(c); - const u = document.createElement("button"); - u.setAttribute("type", "button"), u.innerHTML = `
${xc}
`, u.addEventListener("click", () => { + const l = document.createElement("button"); + l.setAttribute("type", "button"), l.innerHTML = `
${xc}
`, l.addEventListener("click", () => { this.shadowRoot && this.shadowRoot.dispatchEvent( new CustomEvent("close", { composed: !0, bubbles: !0 }) ); - }), i.appendChild(u); - const l = document.createElement("iframe"); - l.src = n, l.allow = "", l.sandbox.add( + }), i.appendChild(l); + const u = document.createElement("iframe"); + u.src = n, u.allow = "", u.sandbox.add( "allow-scripts", "allow-forms", "allow-modals", @@ -4720,10 +4720,10 @@ class kc extends HTMLElement { "allow-popups-to-escape-sandbox", "allow-storage-access-by-user-activation" ), this.addEventListener("message", (f) => { - l.contentWindow && l.contentWindow.postMessage(f.detail, "*"); - }), this.shadowRoot.appendChild(Se(this, de)), Se(this, de).appendChild(i), Se(this, de).appendChild(l); + u.contentWindow && u.contentWindow.postMessage(f.detail, "*"); + }), this.shadowRoot.appendChild(Ee(this, de)), Ee(this, de).appendChild(i), Ee(this, de).appendChild(u); const d = document.createElement("style"); - d.textContent = Sc, this.shadowRoot.appendChild(d), this.calculateZIndex(); + d.textContent = Ec, this.shadowRoot.appendChild(d), this.calculateZIndex(); } } de = new WeakMap(), er = new WeakMap(); @@ -4859,10 +4859,10 @@ class fe extends Error { else if (i.path.length === 0) n._errors.push(r(i)); else { - let c = n, u = 0; - for (; u < i.path.length; ) { - const l = i.path[u]; - u === i.path.length - 1 ? (c[l] = c[l] || { _errors: [] }, c[l]._errors.push(r(i))) : c[l] = c[l] || { _errors: [] }, c = c[l], u++; + let c = n, l = 0; + for (; l < i.path.length; ) { + const u = i.path[l]; + l === i.path.length - 1 ? (c[u] = c[u] || { _errors: [] }, c[u]._errors.push(r(i))) : c[u] = c[u] || { _errors: [] }, c = c[u], l++; } } }; @@ -4952,7 +4952,7 @@ let Ns = Tt; function Tc(t) { Ns = t; } -function Sr() { +function Er() { return Ns; } const xr = (t) => { @@ -4967,9 +4967,9 @@ const xr = (t) => { message: o.message }; let c = ""; - const u = n.filter((l) => !!l).slice().reverse(); - for (const l of u) - c = l(i, { data: e, defaultError: c }).message; + const l = n.filter((u) => !!u).slice().reverse(); + for (const u of l) + c = u(i, { data: e, defaultError: c }).message; return { ...o, path: a, @@ -4977,7 +4977,7 @@ const xr = (t) => { }; }, Ac = []; function b(t, e) { - const r = Sr(), n = xr({ + const r = Er(), n = xr({ issueData: e, data: t.data, path: t.path, @@ -5034,7 +5034,7 @@ class Q { } const I = Object.freeze({ status: "aborted" -}), wt = (t) => ({ status: "dirty", value: t }), ae = (t) => ({ status: "valid", value: t }), pn = (t) => t.status === "aborted", hn = (t) => t.status === "dirty", jt = (t) => t.status === "valid", Zt = (t) => typeof Promise < "u" && t instanceof Promise; +}), wt = (t) => ({ status: "dirty", value: t }), ae = (t) => ({ status: "valid", value: t }), pn = (t) => t.status === "aborted", mn = (t) => t.status === "dirty", jt = (t) => t.status === "valid", Zt = (t) => typeof Promise < "u" && t instanceof Promise; function kr(t, e, r, n) { if (typeof e == "function" ? t !== e || !n : !e.has(t)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); @@ -5045,10 +5045,10 @@ function Rs(t, e, r, n, o) { throw new TypeError("Cannot write private member to an object whose class did not declare it"); return e.set(t, r), r; } -var S; +var E; (function(t) { t.errToObj = (e) => typeof e == "string" ? { message: e } : e || {}, t.toString = (e) => typeof e == "string" ? e : e == null ? void 0 : e.message; -})(S || (S = {})); +})(E || (E = {})); var Mt, Lt; class Re { constructor(e, r, n, o) { @@ -5080,9 +5080,9 @@ function C(t) { if (e && (r || n)) throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); return e ? { errorMap: e, description: o } : { errorMap: (i, c) => { - var u, l; + var l, u; const { message: d } = t; - return i.code === "invalid_enum_value" ? { message: d ?? c.defaultError } : typeof c.data > "u" ? { message: (u = d ?? n) !== null && u !== void 0 ? u : c.defaultError } : i.code !== "invalid_type" ? { message: c.defaultError } : { message: (l = d ?? r) !== null && l !== void 0 ? l : c.defaultError }; + return i.code === "invalid_enum_value" ? { message: d ?? c.defaultError } : typeof c.data > "u" ? { message: (l = d ?? n) !== null && l !== void 0 ? l : c.defaultError } : i.code !== "invalid_type" ? { message: c.defaultError } : { message: (u = d ?? r) !== null && u !== void 0 ? u : c.defaultError }; }, description: o }; } class $ { @@ -5178,7 +5178,7 @@ class $ { code: g.custom, ...n(o) }); - return typeof Promise < "u" && i instanceof Promise ? i.then((u) => u ? !0 : (c(), !1)) : i ? !0 : (c(), !1); + return typeof Promise < "u" && i instanceof Promise ? i.then((l) => l ? !0 : (c(), !1)) : i ? !0 : (c(), !1); }); } refinement(e, r) { @@ -5434,7 +5434,7 @@ class ke extends $ { return this.refinement((o) => e.test(o), { validation: r, code: g.invalid_string, - ...S.errToObj(n) + ...E.errToObj(n) }); } _addCheck(e) { @@ -5444,34 +5444,34 @@ class ke extends $ { }); } email(e) { - return this._addCheck({ kind: "email", ...S.errToObj(e) }); + return this._addCheck({ kind: "email", ...E.errToObj(e) }); } url(e) { - return this._addCheck({ kind: "url", ...S.errToObj(e) }); + return this._addCheck({ kind: "url", ...E.errToObj(e) }); } emoji(e) { - return this._addCheck({ kind: "emoji", ...S.errToObj(e) }); + return this._addCheck({ kind: "emoji", ...E.errToObj(e) }); } uuid(e) { - return this._addCheck({ kind: "uuid", ...S.errToObj(e) }); + return this._addCheck({ kind: "uuid", ...E.errToObj(e) }); } nanoid(e) { - return this._addCheck({ kind: "nanoid", ...S.errToObj(e) }); + return this._addCheck({ kind: "nanoid", ...E.errToObj(e) }); } cuid(e) { - return this._addCheck({ kind: "cuid", ...S.errToObj(e) }); + return this._addCheck({ kind: "cuid", ...E.errToObj(e) }); } cuid2(e) { - return this._addCheck({ kind: "cuid2", ...S.errToObj(e) }); + return this._addCheck({ kind: "cuid2", ...E.errToObj(e) }); } ulid(e) { - return this._addCheck({ kind: "ulid", ...S.errToObj(e) }); + return this._addCheck({ kind: "ulid", ...E.errToObj(e) }); } base64(e) { - return this._addCheck({ kind: "base64", ...S.errToObj(e) }); + return this._addCheck({ kind: "base64", ...E.errToObj(e) }); } ip(e) { - return this._addCheck({ kind: "ip", ...S.errToObj(e) }); + return this._addCheck({ kind: "ip", ...E.errToObj(e) }); } datetime(e) { var r, n; @@ -5486,7 +5486,7 @@ class ke extends $ { precision: typeof (e == null ? void 0 : e.precision) > "u" ? null : e == null ? void 0 : e.precision, offset: (r = e == null ? void 0 : e.offset) !== null && r !== void 0 ? r : !1, local: (n = e == null ? void 0 : e.local) !== null && n !== void 0 ? n : !1, - ...S.errToObj(e == null ? void 0 : e.message) + ...E.errToObj(e == null ? void 0 : e.message) }); } date(e) { @@ -5500,17 +5500,17 @@ class ke extends $ { }) : this._addCheck({ kind: "time", precision: typeof (e == null ? void 0 : e.precision) > "u" ? null : e == null ? void 0 : e.precision, - ...S.errToObj(e == null ? void 0 : e.message) + ...E.errToObj(e == null ? void 0 : e.message) }); } duration(e) { - return this._addCheck({ kind: "duration", ...S.errToObj(e) }); + return this._addCheck({ kind: "duration", ...E.errToObj(e) }); } regex(e, r) { return this._addCheck({ kind: "regex", regex: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } includes(e, r) { @@ -5518,42 +5518,42 @@ class ke extends $ { kind: "includes", value: e, position: r == null ? void 0 : r.position, - ...S.errToObj(r == null ? void 0 : r.message) + ...E.errToObj(r == null ? void 0 : r.message) }); } startsWith(e, r) { return this._addCheck({ kind: "startsWith", value: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } endsWith(e, r) { return this._addCheck({ kind: "endsWith", value: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } min(e, r) { return this._addCheck({ kind: "min", value: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } max(e, r) { return this._addCheck({ kind: "max", value: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } length(e, r) { return this._addCheck({ kind: "length", value: e, - ...S.errToObj(r) + ...E.errToObj(r) }); } /** @@ -5561,7 +5561,7 @@ class ke extends $ { * @see {@link ZodString.min} */ nonempty(e) { - return this.min(1, S.errToObj(e)); + return this.min(1, E.errToObj(e)); } trim() { return new ke({ @@ -5695,16 +5695,16 @@ class Xe extends $ { return { status: o.value, value: e.data }; } gte(e, r) { - return this.setLimit("min", e, !0, S.toString(r)); + return this.setLimit("min", e, !0, E.toString(r)); } gt(e, r) { - return this.setLimit("min", e, !1, S.toString(r)); + return this.setLimit("min", e, !1, E.toString(r)); } lte(e, r) { - return this.setLimit("max", e, !0, S.toString(r)); + return this.setLimit("max", e, !0, E.toString(r)); } lt(e, r) { - return this.setLimit("max", e, !1, S.toString(r)); + return this.setLimit("max", e, !1, E.toString(r)); } setLimit(e, r, n, o) { return new Xe({ @@ -5715,7 +5715,7 @@ class Xe extends $ { kind: e, value: r, inclusive: n, - message: S.toString(o) + message: E.toString(o) } ] }); @@ -5729,7 +5729,7 @@ class Xe extends $ { int(e) { return this._addCheck({ kind: "int", - message: S.toString(e) + message: E.toString(e) }); } positive(e) { @@ -5737,7 +5737,7 @@ class Xe extends $ { kind: "min", value: 0, inclusive: !1, - message: S.toString(e) + message: E.toString(e) }); } negative(e) { @@ -5745,7 +5745,7 @@ class Xe extends $ { kind: "max", value: 0, inclusive: !1, - message: S.toString(e) + message: E.toString(e) }); } nonpositive(e) { @@ -5753,7 +5753,7 @@ class Xe extends $ { kind: "max", value: 0, inclusive: !0, - message: S.toString(e) + message: E.toString(e) }); } nonnegative(e) { @@ -5761,20 +5761,20 @@ class Xe extends $ { kind: "min", value: 0, inclusive: !0, - message: S.toString(e) + message: E.toString(e) }); } multipleOf(e, r) { return this._addCheck({ kind: "multipleOf", value: e, - message: S.toString(r) + message: E.toString(r) }); } finite(e) { return this._addCheck({ kind: "finite", - message: S.toString(e) + message: E.toString(e) }); } safe(e) { @@ -5782,12 +5782,12 @@ class Xe extends $ { kind: "min", inclusive: !0, value: Number.MIN_SAFE_INTEGER, - message: S.toString(e) + message: E.toString(e) })._addCheck({ kind: "max", inclusive: !0, value: Number.MAX_SAFE_INTEGER, - message: S.toString(e) + message: E.toString(e) }); } get minValue() { @@ -5857,16 +5857,16 @@ class Qe extends $ { return { status: o.value, value: e.data }; } gte(e, r) { - return this.setLimit("min", e, !0, S.toString(r)); + return this.setLimit("min", e, !0, E.toString(r)); } gt(e, r) { - return this.setLimit("min", e, !1, S.toString(r)); + return this.setLimit("min", e, !1, E.toString(r)); } lte(e, r) { - return this.setLimit("max", e, !0, S.toString(r)); + return this.setLimit("max", e, !0, E.toString(r)); } lt(e, r) { - return this.setLimit("max", e, !1, S.toString(r)); + return this.setLimit("max", e, !1, E.toString(r)); } setLimit(e, r, n, o) { return new Qe({ @@ -5877,7 +5877,7 @@ class Qe extends $ { kind: e, value: r, inclusive: n, - message: S.toString(o) + message: E.toString(o) } ] }); @@ -5893,7 +5893,7 @@ class Qe extends $ { kind: "min", value: BigInt(0), inclusive: !1, - message: S.toString(e) + message: E.toString(e) }); } negative(e) { @@ -5901,7 +5901,7 @@ class Qe extends $ { kind: "max", value: BigInt(0), inclusive: !1, - message: S.toString(e) + message: E.toString(e) }); } nonpositive(e) { @@ -5909,7 +5909,7 @@ class Qe extends $ { kind: "max", value: BigInt(0), inclusive: !0, - message: S.toString(e) + message: E.toString(e) }); } nonnegative(e) { @@ -5917,14 +5917,14 @@ class Qe extends $ { kind: "min", value: BigInt(0), inclusive: !0, - message: S.toString(e) + message: E.toString(e) }); } multipleOf(e, r) { return this._addCheck({ kind: "multipleOf", value: e, - message: S.toString(r) + message: E.toString(r) }); } get minValue() { @@ -6016,14 +6016,14 @@ class pt extends $ { return this._addCheck({ kind: "min", value: e.getTime(), - message: S.toString(r) + message: E.toString(r) }); } max(e, r) { return this._addCheck({ kind: "max", value: e.getTime(), - message: S.toString(r) + message: E.toString(r) }); } get minDate() { @@ -6197,19 +6197,19 @@ class Te extends $ { min(e, r) { return new Te({ ...this._def, - minLength: { value: e, message: S.toString(r) } + minLength: { value: e, message: E.toString(r) } }); } max(e, r) { return new Te({ ...this._def, - maxLength: { value: e, message: S.toString(r) } + maxLength: { value: e, message: E.toString(r) } }); } length(e, r) { return new Te({ ...this._def, - exactLength: { value: e, message: S.toString(r) } + exactLength: { value: e, message: E.toString(r) } }); } nonempty(e) { @@ -6253,48 +6253,48 @@ class U extends $ { } _parse(e) { if (this._getType(e) !== w.object) { - const l = this._getOrReturnCtx(e); - return b(l, { + const u = this._getOrReturnCtx(e); + return b(u, { code: g.invalid_type, expected: w.object, - received: l.parsedType + received: u.parsedType }), I; } const { status: n, ctx: o } = this._processInputParams(e), { shape: a, keys: i } = this._getCached(), c = []; if (!(this._def.catchall instanceof je && this._def.unknownKeys === "strip")) - for (const l in o.data) - i.includes(l) || c.push(l); - const u = []; - for (const l of i) { - const d = a[l], f = o.data[l]; - u.push({ - key: { status: "valid", value: l }, - value: d._parse(new Re(o, f, o.path, l)), - alwaysSet: l in o.data + for (const u in o.data) + i.includes(u) || c.push(u); + const l = []; + for (const u of i) { + const d = a[u], f = o.data[u]; + l.push({ + key: { status: "valid", value: u }, + value: d._parse(new Re(o, f, o.path, u)), + alwaysSet: u in o.data }); } if (this._def.catchall instanceof je) { - const l = this._def.unknownKeys; - if (l === "passthrough") + const u = this._def.unknownKeys; + if (u === "passthrough") for (const d of c) - u.push({ + l.push({ key: { status: "valid", value: d }, value: { status: "valid", value: o.data[d] } }); - else if (l === "strict") + else if (u === "strict") c.length > 0 && (b(o, { code: g.unrecognized_keys, keys: c }), n.dirty()); - else if (l !== "strip") + else if (u !== "strip") throw new Error("Internal ZodObject error: invalid unknownKeys value."); } else { - const l = this._def.catchall; + const u = this._def.catchall; for (const d of c) { const f = o.data[d]; - u.push({ + l.push({ key: { status: "valid", value: d }, - value: l._parse( + value: u._parse( new Re(o, f, o.path, d) //, ctx.child(key), value, getParsedType(value) ), @@ -6303,33 +6303,33 @@ class U extends $ { } } return o.common.async ? Promise.resolve().then(async () => { - const l = []; - for (const d of u) { - const f = await d.key, h = await d.value; - l.push({ + const u = []; + for (const d of l) { + const f = await d.key, m = await d.value; + u.push({ key: f, - value: h, + value: m, alwaysSet: d.alwaysSet }); } - return l; - }).then((l) => Q.mergeObjectSync(n, l)) : Q.mergeObjectSync(n, u); + return u; + }).then((u) => Q.mergeObjectSync(n, u)) : Q.mergeObjectSync(n, l); } get shape() { return this._def.shape(); } strict(e) { - return S.errToObj, new U({ + return E.errToObj, new U({ ...this._def, unknownKeys: "strict", ...e !== void 0 ? { errorMap: (r, n) => { var o, a, i, c; - const u = (i = (a = (o = this._def).errorMap) === null || a === void 0 ? void 0 : a.call(o, r, n).message) !== null && i !== void 0 ? i : n.defaultError; + const l = (i = (a = (o = this._def).errorMap) === null || a === void 0 ? void 0 : a.call(o, r, n).message) !== null && i !== void 0 ? i : n.defaultError; return r.code === "unrecognized_keys" ? { - message: (c = S.errToObj(e).message) !== null && c !== void 0 ? c : u + message: (c = E.errToObj(e).message) !== null && c !== void 0 ? c : l } : { - message: u + message: l }; } } : {} @@ -6567,26 +6567,26 @@ class Ht extends $ { { let a; const i = []; - for (const u of n) { - const l = { + for (const l of n) { + const u = { ...r, common: { ...r.common, issues: [] }, parent: null - }, d = u._parseSync({ + }, d = l._parseSync({ data: r.data, path: r.path, - parent: l + parent: u }); if (d.status === "valid") return d; - d.status === "dirty" && !a && (a = { result: d, ctx: l }), l.common.issues.length && i.push(l.common.issues); + d.status === "dirty" && !a && (a = { result: d, ctx: u }), u.common.issues.length && i.push(u.common.issues); } if (a) return r.common.issues.push(...a.ctx.common.issues), a.result; - const c = i.map((u) => new fe(u)); + const c = i.map((l) => new fe(l)); return b(r, { code: g.invalid_union, unionErrors: c @@ -6665,17 +6665,17 @@ class Zr extends $ { }); } } -function mn(t, e) { +function hn(t, e) { const r = Ve(t), n = Ve(e); if (t === e) return { valid: !0, data: t }; if (r === w.object && n === w.object) { const o = O.objectKeys(e), a = O.objectKeys(t).filter((c) => o.indexOf(c) !== -1), i = { ...t, ...e }; for (const c of a) { - const u = mn(t[c], e[c]); - if (!u.valid) + const l = hn(t[c], e[c]); + if (!l.valid) return { valid: !1 }; - i[c] = u.data; + i[c] = l.data; } return { valid: !0, data: i }; } else if (r === w.array && n === w.array) { @@ -6683,10 +6683,10 @@ function mn(t, e) { return { valid: !1 }; const o = []; for (let a = 0; a < t.length; a++) { - const i = t[a], c = e[a], u = mn(i, c); - if (!u.valid) + const i = t[a], c = e[a], l = hn(i, c); + if (!l.valid) return { valid: !1 }; - o.push(u.data); + o.push(l.data); } return { valid: !0, data: o }; } else @@ -6697,8 +6697,8 @@ class Vt extends $ { const { status: r, ctx: n } = this._processInputParams(e), o = (a, i) => { if (pn(a) || pn(i)) return I; - const c = mn(a.value, i.value); - return c.valid ? ((hn(a) || hn(i)) && r.dirty(), { status: r.value, value: c.data }) : (b(n, { + const c = hn(a.value, i.value); + return c.valid ? ((mn(a) || mn(i)) && r.dirty(), { status: r.value, value: c.data }) : (b(n, { code: g.invalid_intersection_types }), I); }; @@ -6755,8 +6755,8 @@ class Oe extends $ { type: "array" }), r.dirty()); const a = [...n.data].map((i, c) => { - const u = this._def.items[c] || this._def.rest; - return u ? u._parse(new Re(n, i, n.path, c)) : null; + const l = this._def.items[c] || this._def.rest; + return l ? l._parse(new Re(n, i, n.path, c)) : null; }).filter((i) => !!i); return n.common.async ? Promise.all(a).then((i) => Q.mergeArray(r, i)) : Q.mergeArray(r, a); } @@ -6836,28 +6836,28 @@ class Ar extends $ { expected: w.map, received: n.parsedType }), I; - const o = this._def.keyType, a = this._def.valueType, i = [...n.data.entries()].map(([c, u], l) => ({ - key: o._parse(new Re(n, c, n.path, [l, "key"])), - value: a._parse(new Re(n, u, n.path, [l, "value"])) + const o = this._def.keyType, a = this._def.valueType, i = [...n.data.entries()].map(([c, l], u) => ({ + key: o._parse(new Re(n, c, n.path, [u, "key"])), + value: a._parse(new Re(n, l, n.path, [u, "value"])) })); if (n.common.async) { const c = /* @__PURE__ */ new Map(); return Promise.resolve().then(async () => { - for (const u of i) { - const l = await u.key, d = await u.value; - if (l.status === "aborted" || d.status === "aborted") + for (const l of i) { + const u = await l.key, d = await l.value; + if (u.status === "aborted" || d.status === "aborted") return I; - (l.status === "dirty" || d.status === "dirty") && r.dirty(), c.set(l.value, d.value); + (u.status === "dirty" || d.status === "dirty") && r.dirty(), c.set(u.value, d.value); } return { status: r.value, value: c }; }); } else { const c = /* @__PURE__ */ new Map(); - for (const u of i) { - const l = u.key, d = u.value; - if (l.status === "aborted" || d.status === "aborted") + for (const l of i) { + const u = l.key, d = l.value; + if (u.status === "aborted" || d.status === "aborted") return I; - (l.status === "dirty" || d.status === "dirty") && r.dirty(), c.set(l.value, d.value); + (u.status === "dirty" || d.status === "dirty") && r.dirty(), c.set(u.value, d.value); } return { status: r.value, value: c }; } @@ -6869,7 +6869,7 @@ Ar.create = (t, e, r) => new Ar({ typeName: A.ZodMap, ...C(r) }); -class ht extends $ { +class mt extends $ { _parse(e) { const { status: r, ctx: n } = this._processInputParams(e); if (n.parsedType !== w.set) @@ -6895,28 +6895,28 @@ class ht extends $ { message: o.maxSize.message }), r.dirty()); const a = this._def.valueType; - function i(u) { - const l = /* @__PURE__ */ new Set(); - for (const d of u) { + function i(l) { + const u = /* @__PURE__ */ new Set(); + for (const d of l) { if (d.status === "aborted") return I; - d.status === "dirty" && r.dirty(), l.add(d.value); + d.status === "dirty" && r.dirty(), u.add(d.value); } - return { status: r.value, value: l }; + return { status: r.value, value: u }; } - const c = [...n.data.values()].map((u, l) => a._parse(new Re(n, u, n.path, l))); - return n.common.async ? Promise.all(c).then((u) => i(u)) : i(c); + const c = [...n.data.values()].map((l, u) => a._parse(new Re(n, l, n.path, u))); + return n.common.async ? Promise.all(c).then((l) => i(l)) : i(c); } min(e, r) { - return new ht({ + return new mt({ ...this._def, - minSize: { value: e, message: S.toString(r) } + minSize: { value: e, message: E.toString(r) } }); } max(e, r) { - return new ht({ + return new mt({ ...this._def, - maxSize: { value: e, message: S.toString(r) } + maxSize: { value: e, message: E.toString(r) } }); } size(e, r) { @@ -6926,7 +6926,7 @@ class ht extends $ { return this.min(1, e); } } -ht.create = (t, e) => new ht({ +mt.create = (t, e) => new mt({ valueType: t, minSize: null, maxSize: null, @@ -6945,56 +6945,56 @@ class xt extends $ { expected: w.function, received: r.parsedType }), I; - function n(c, u) { + function n(c, l) { return xr({ data: c, path: r.path, errorMaps: [ r.common.contextualErrorMap, r.schemaErrorMap, - Sr(), + Er(), Tt - ].filter((l) => !!l), + ].filter((u) => !!u), issueData: { code: g.invalid_arguments, - argumentsError: u + argumentsError: l } }); } - function o(c, u) { + function o(c, l) { return xr({ data: c, path: r.path, errorMaps: [ r.common.contextualErrorMap, r.schemaErrorMap, - Sr(), + Er(), Tt - ].filter((l) => !!l), + ].filter((u) => !!u), issueData: { code: g.invalid_return_type, - returnTypeError: u + returnTypeError: l } }); } const a = { errorMap: r.common.contextualErrorMap }, i = r.data; if (this._def.returns instanceof It) { const c = this; - return ae(async function(...u) { - const l = new fe([]), d = await c._def.args.parseAsync(u, a).catch((p) => { - throw l.addIssue(n(u, p)), l; + return ae(async function(...l) { + const u = new fe([]), d = await c._def.args.parseAsync(l, a).catch((p) => { + throw u.addIssue(n(l, p)), u; }), f = await Reflect.apply(i, this, d); return await c._def.returns._def.type.parseAsync(f, a).catch((p) => { - throw l.addIssue(o(f, p)), l; + throw u.addIssue(o(f, p)), u; }); }); } else { const c = this; - return ae(function(...u) { - const l = c._def.args.safeParse(u, a); - if (!l.success) - throw new fe([n(u, l.error)]); - const d = Reflect.apply(i, this, l.data), f = c._def.returns.safeParse(d, a); + return ae(function(...l) { + const u = c._def.args.safeParse(l, a); + if (!u.success) + throw new fe([n(l, u.error)]); + const d = Reflect.apply(i, this, u.data), f = c._def.returns.safeParse(d, a); if (!f.success) throw new fe([o(d, f.error)]); return f.data; @@ -7215,12 +7215,12 @@ class Ae extends $ { return Promise.resolve(i).then(async (c) => { if (r.value === "aborted") return I; - const u = await this._def.schema._parseAsync({ + const l = await this._def.schema._parseAsync({ data: c, path: n.path, parent: n }); - return u.status === "aborted" ? I : u.status === "dirty" || r.value === "dirty" ? wt(u.value) : u; + return l.status === "aborted" ? I : l.status === "dirty" || r.value === "dirty" ? wt(l.value) : l; }); { if (r.value === "aborted") @@ -7235,10 +7235,10 @@ class Ae extends $ { } if (o.type === "refinement") { const i = (c) => { - const u = o.refinement(c, a); + const l = o.refinement(c, a); if (n.common.async) - return Promise.resolve(u); - if (u instanceof Promise) + return Promise.resolve(l); + if (l instanceof Promise) throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); return c; }; @@ -7460,8 +7460,8 @@ function Ds(t, e = {}, r) { return t ? At.create().superRefine((n, o) => { var a, i; if (!t(n)) { - const c = typeof e == "function" ? e(n) : typeof e == "string" ? { message: e } : e, u = (i = (a = c.fatal) !== null && a !== void 0 ? a : r) !== null && i !== void 0 ? i : !0, l = typeof c == "string" ? { message: c } : c; - o.addIssue({ code: "custom", ...l, fatal: u }); + const c = typeof e == "function" ? e(n) : typeof e == "string" ? { message: e } : e, l = (i = (a = c.fatal) !== null && a !== void 0 ? a : r) !== null && i !== void 0 ? i : !0, u = typeof c == "string" ? { message: c } : c; + o.addIssue({ code: "custom", ...u, fatal: l }); } }) : At.create(); } @@ -7474,7 +7474,7 @@ var A; })(A || (A = {})); const Vc = (t, e = { message: `Input not instance of ${t.name}` -}) => Ds((r) => r instanceof t, e), Us = ke.create, js = Xe.create, Wc = Ir.create, qc = Qe.create, Zs = zt.create, Kc = pt.create, Yc = Pr.create, Jc = Gt.create, Xc = Bt.create, Qc = At.create, el = dt.create, tl = je.create, rl = Tr.create, nl = Te.create, ol = U.create, sl = U.strictCreate, al = Ht.create, il = Zr.create, cl = Vt.create, ll = Oe.create, ul = Wt.create, dl = Ar.create, fl = ht.create, pl = xt.create, hl = qt.create, ml = Kt.create, gl = et.create, yl = Yt.create, vl = It.create, bo = Ae.create, _l = Ne.create, bl = tt.create, wl = Ae.createWithPreprocess, El = sr.create, Sl = () => Us().optional(), xl = () => js().optional(), kl = () => Zs().optional(), Pl = { +}) => Ds((r) => r instanceof t, e), Us = ke.create, js = Xe.create, Wc = Ir.create, qc = Qe.create, Zs = zt.create, Kc = pt.create, Yc = Pr.create, Jc = Gt.create, Xc = Bt.create, Qc = At.create, el = dt.create, tl = je.create, rl = Tr.create, nl = Te.create, ol = U.create, sl = U.strictCreate, al = Ht.create, il = Zr.create, cl = Vt.create, ll = Oe.create, ul = Wt.create, dl = Ar.create, fl = mt.create, pl = xt.create, ml = qt.create, hl = Kt.create, gl = et.create, yl = Yt.create, vl = It.create, bo = Ae.create, _l = Ne.create, bl = tt.create, wl = Ae.createWithPreprocess, Sl = sr.create, El = () => Us().optional(), xl = () => js().optional(), kl = () => Zs().optional(), Pl = { string: (t) => ke.create({ ...t, coerce: !0 }), number: (t) => Xe.create({ ...t, coerce: !0 }), boolean: (t) => zt.create({ @@ -7488,7 +7488,7 @@ var Z = /* @__PURE__ */ Object.freeze({ __proto__: null, defaultErrorMap: Tt, setErrorMap: Tc, - getErrorMap: Sr, + getErrorMap: Er, makeIssue: xr, EMPTY_PATH: Ac, addIssueToContext: b, @@ -7497,7 +7497,7 @@ var Z = /* @__PURE__ */ Object.freeze({ DIRTY: wt, OK: ae, isAborted: pn, - isDirty: hn, + isDirty: mn, isValid: jt, isAsync: Zt, get util() { @@ -7530,7 +7530,7 @@ var Z = /* @__PURE__ */ Object.freeze({ ZodTuple: Oe, ZodRecord: Wt, ZodMap: Ar, - ZodSet: ht, + ZodSet: mt, ZodFunction: xt, ZodLazy: qt, ZodLiteral: Kt, @@ -7567,8 +7567,8 @@ var Z = /* @__PURE__ */ Object.freeze({ function: pl, instanceof: Vc, intersection: cl, - lazy: hl, - literal: ml, + lazy: ml, + literal: hl, map: dl, nan: Wc, nativeEnum: yl, @@ -7580,8 +7580,8 @@ var Z = /* @__PURE__ */ Object.freeze({ oboolean: kl, onumber: xl, optional: _l, - ostring: Sl, - pipeline: El, + ostring: El, + pipeline: Sl, preprocess: wl, promise: vl, record: ul, @@ -7607,20 +7607,20 @@ const Al = Z.object({ function Il(t, e, r, n) { const o = document.createElement("plugin-modal"); o.setTheme(r); - const a = 200, i = 200, c = 335, u = 590, l = { + const a = 200, i = 200, c = 335, l = 590, u = { blockStart: 40, inlineEnd: 320 }; o.style.setProperty( "--modal-block-start", - `${l.blockStart}px` + `${u.blockStart}px` ), o.style.setProperty( "--modal-inline-end", - `${l.inlineEnd}px` + `${u.inlineEnd}px` ); - const d = window.innerWidth - l.inlineEnd, f = window.innerHeight - l.blockStart; - let h = Math.min((n == null ? void 0 : n.width) || c, d), p = Math.min((n == null ? void 0 : n.height) || u, f); - return h = Math.max(h, a), p = Math.max(p, i), o.setAttribute("title", t), o.setAttribute("iframe-src", e), o.setAttribute("width", String(h)), o.setAttribute("height", String(p)), document.body.appendChild(o), o; + const d = window.innerWidth - u.inlineEnd, f = window.innerHeight - u.blockStart; + let m = Math.min((n == null ? void 0 : n.width) || c, d), p = Math.min((n == null ? void 0 : n.height) || l, f); + return m = Math.max(m, a), p = Math.max(p, i), o.setAttribute("title", t), o.setAttribute("iframe-src", e), o.setAttribute("width", String(m)), o.setAttribute("height", String(p)), document.body.appendChild(o), o; } const Cl = Z.function().args( Z.string(), @@ -7636,11 +7636,11 @@ const Cl = Z.function().args( description: Z.string().max(200).optional(), permissions: Z.array( Z.enum([ - "page:read", - "page:write", - "file:read", - "file:write", - "selection:read" + "content:read", + "content:write", + "library:read", + "library:write", + "user:read" ]) ) }); @@ -7673,8 +7673,12 @@ const gn = [ let yn = [], vn = /* @__PURE__ */ new Set([]); const Ft = /* @__PURE__ */ new Map(); window.addEventListener("message", (t) => { - for (const e of yn) - e(t.data); + try { + for (const e of yn) + e(t.data); + } catch (e) { + console.error(e); + } }); function Ol(t, e) { t === "themechange" && vn.forEach((n) => { @@ -7691,14 +7695,14 @@ function Ml(t, e) { }; return { ui: { - open: (i, c, u) => { - const l = t.getTheme(); + open: (i, c, l) => { + const u = t.getTheme(); r = Cl( i, zs(e.host, c), - l, - u - ), r.setTheme(l), r.addEventListener("close", n, { + u, + l + ), r.setTheme(u), r.addEventListener("close", n, { once: !0 }), vn.add(r); }, @@ -7750,87 +7754,102 @@ function Ml(t, e) { }, closePlugin: n, on(i, c) { - Z.enum(gn).parse(i), Z.function().parse(c), i === "pagechange" ? o("page:read") : i === "filechange" ? o("file:read") : i === "selectionchange" && o("selection:read"); - const u = Ft.get(i) || []; - u.push(c), Ft.set(i, u); + Z.enum(gn).parse(i), Z.function().parse(c), o("content:read"); + const l = Ft.get(i) || []; + l.push(c), Ft.set(i, l); }, off(i, c) { Z.enum(gn).parse(i), Z.function().parse(c); - const u = Ft.get(i) || []; + const l = Ft.get(i) || []; Ft.set( i, - u.filter((l) => l !== c) + l.filter((u) => u !== c) ); }, // Penpot State API get root() { - return o("page:read"), t.root; + return o("content:read"), t.root; }, get currentPage() { - return o("page:read"), t.currentPage; + return o("content:read"), t.currentPage; }, get selection() { - return o("selection:read"), t.selection; + return o("content:read"), t.selection; }, get viewport() { return t.viewport; }, get library() { - return t.library; + return o("library:read"), t.library; }, get fonts() { - return t.fonts; + return o("content:read"), t.fonts; }, get currentUser() { - return t.currentUser; + return o("user:read"), t.currentUser; }, get activeUsers() { - return t.activeUsers; + return o("user:read"), t.activeUsers; }, getFile() { - return o("file:read"), t.getFile(); + return o("content:read"), t.getFile(); }, getPage() { - return o("page:read"), t.getPage(); + return o("content:read"), t.getPage(); }, getSelected() { - return o("selection:read"), t.getSelected(); + return o("content:read"), t.getSelected(); }, getSelectedShapes() { - return o("selection:read"), t.getSelectedShapes(); + return o("content:read"), t.getSelectedShapes(); + }, + shapesColors(i) { + return o("content:read"), t.shapesColors(i); + }, + replaceColor(i, c, l) { + return o("content:write"), t.replaceColor(i, c, l); }, getTheme() { return t.getTheme(); }, createFrame() { - return t.createFrame(); + return o("content:write"), t.createFrame(); }, createRectangle() { - return t.createRectangle(); + return o("content:write"), t.createRectangle(); }, createEllipse() { - return t.createEllipse(); + return o("content:write"), t.createEllipse(); }, createText(i) { - return t.createText(i); + return o("content:write"), t.createText(i); }, createPath() { - return t.createPath(); + return o("content:write"), t.createPath(); }, createBoolean(i, c) { - return t.createBoolean(i, c); + return o("content:write"), t.createBoolean(i, c); }, createShapeFromSvg(i) { - return t.createShapeFromSvg(i); + return o("content:write"), t.createShapeFromSvg(i); }, group(i) { - return t.group(i); + return o("content:write"), t.group(i); }, ungroup(i, ...c) { - t.ungroup(i, ...c); + o("content:write"), t.ungroup(i, ...c); }, uploadMediaUrl(i, c) { - return t.uploadMediaUrl(i, c); + return o("content:write"), t.uploadMediaUrl(i, c); + }, + uploadMediaData(i, c, l) { + return o("content:write"), t.uploadMediaData(i, c, l); + }, + generateMarkup(i, c) { + return o("content:read"), t.generateMarkup(i, c); + }, + generateStyle(i, c) { + return o("content:read"), t.generateStyle(i, c); } }; } @@ -7891,10 +7910,10 @@ repairIntrinsics({ errorTaming: "unsafe", consoleTaming: "unsafe" }); -const Eo = globalThis; -Eo.initPluginsRuntime = (t) => { +const So = globalThis; +So.initPluginsRuntime = (t) => { try { - console.log("%c[PLUGINS] Initialize runtime", "color: #008d7c"), Fl(t), Eo.ɵcontext = t("TEST"), globalThis.ɵloadPlugin = Gs, globalThis.ɵloadPluginByUrl = Dl; + console.log("%c[PLUGINS] Initialize runtime", "color: #008d7c"), Fl(t), So.ɵcontext = t("TEST"), globalThis.ɵloadPlugin = Gs, globalThis.ɵloadPluginByUrl = Dl; } catch (e) { console.error(e); }