mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
🐛 Fix incorrect boolean shapes generation on builder
This commit is contained in:
parent
77fa235965
commit
89a09346a5
4 changed files with 130 additions and 26 deletions
|
@ -10,13 +10,17 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
;; [app.common.features :as cfeat]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.files.changes :as ch]
|
[app.common.files.changes :as ch]
|
||||||
|
;; [app.common.features :as cfeat]
|
||||||
|
[app.common.files.helpers :as cph]
|
||||||
[app.common.files.migrations :as fmig]
|
[app.common.files.migrations :as fmig]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.svg :as csvg]
|
[app.common.svg :as csvg]
|
||||||
[app.common.types.color :as types.color]
|
[app.common.types.color :as types.color]
|
||||||
|
[app.common.types.component :as types.comp]
|
||||||
|
[app.common.types.container :as types.cont]
|
||||||
[app.common.types.file :as types.file]
|
[app.common.types.file :as types.file]
|
||||||
[app.common.types.page :as types.page]
|
[app.common.types.page :as types.page]
|
||||||
[app.common.types.path :as types.path]
|
[app.common.types.path :as types.path]
|
||||||
|
@ -330,6 +334,35 @@
|
||||||
(commit-change state change :add-container true)))]
|
(commit-change state change :add-container true)))]
|
||||||
(update state ::parent-stack pop))))
|
(update state ::parent-stack pop))))
|
||||||
|
|
||||||
|
(defn- update-bool-style-properties
|
||||||
|
[bool-shape objects]
|
||||||
|
(let [xform
|
||||||
|
(comp
|
||||||
|
(map (d/getf objects))
|
||||||
|
(remove cph/frame-shape?)
|
||||||
|
(remove types.comp/is-variant?)
|
||||||
|
(remove (partial types.cont/has-any-copy-parent? objects)))
|
||||||
|
|
||||||
|
children
|
||||||
|
(->> (get bool-shape :shapes)
|
||||||
|
(into [] xform)
|
||||||
|
(not-empty))]
|
||||||
|
|
||||||
|
(when-not children
|
||||||
|
(ex/raise :type :validation
|
||||||
|
:code :empty-children
|
||||||
|
:hint "expected a group with at least one shape for creating a bool"))
|
||||||
|
|
||||||
|
(let [head (if (= type :difference)
|
||||||
|
(first children)
|
||||||
|
(last children))
|
||||||
|
fills (if (and (contains? head :svg-attrs) (empty? (:fills head)))
|
||||||
|
types.path/default-bool-fills
|
||||||
|
(get head :fills))]
|
||||||
|
(-> bool-shape
|
||||||
|
(assoc :fills fills)
|
||||||
|
(assoc :stroks (get head :strokes))))))
|
||||||
|
|
||||||
(defn add-bool
|
(defn add-bool
|
||||||
[state params]
|
[state params]
|
||||||
(let [{:keys [group-id type]}
|
(let [{:keys [group-id type]}
|
||||||
|
@ -338,33 +371,40 @@
|
||||||
group
|
group
|
||||||
(get-shape state group-id)
|
(get-shape state group-id)
|
||||||
|
|
||||||
children
|
objects
|
||||||
(->> (get group :shapes)
|
(get-current-objects state)
|
||||||
(not-empty))]
|
|
||||||
|
|
||||||
(assert (some? children) "expect group to have at least 1 element")
|
bool
|
||||||
|
(-> group
|
||||||
|
(assoc :type :bool)
|
||||||
|
(assoc :bool-type type)
|
||||||
|
(update-bool-style-properties objects)
|
||||||
|
(types.path/update-bool-shape objects))
|
||||||
|
|
||||||
(let [objects (get-current-objects state)
|
selrect
|
||||||
bool (-> group
|
(get bool :selrect)
|
||||||
(assoc :type :bool)
|
|
||||||
(assoc :bool-type type)
|
|
||||||
(types.path/update-bool-shape objects))
|
|
||||||
change {:type :mod-obj
|
|
||||||
:id (:id bool)
|
|
||||||
:operations
|
|
||||||
[{:type :set :attr :content :val (:content bool) :ignore-touched true}
|
|
||||||
{:type :set :attr :type :val :bool :ignore-touched true}
|
|
||||||
{:type :set :attr :bool-type :val type :ignore-touched true}
|
|
||||||
{:type :set :attr :selrect :val (:selrect bool) :ignore-touched true}
|
|
||||||
{:type :set :attr :points :val (:points bool) :ignore-touched true}
|
|
||||||
{:type :set :attr :x :val (-> bool :selrect :x) :ignore-touched true}
|
|
||||||
{:type :set :attr :y :val (-> bool :selrect :y) :ignore-touched true}
|
|
||||||
{:type :set :attr :width :val (-> bool :selrect :width) :ignore-touched true}
|
|
||||||
{:type :set :attr :height :val (-> bool :selrect :height) :ignore-touched true}]}]
|
|
||||||
|
|
||||||
(-> state
|
operations
|
||||||
(commit-change change :add-container true)
|
[{:type :set :attr :content :val (:content bool) :ignore-touched true}
|
||||||
(assoc ::last-id group-id)))))
|
{:type :set :attr :type :val :bool :ignore-touched true}
|
||||||
|
{:type :set :attr :bool-type :val type :ignore-touched true}
|
||||||
|
{:type :set :attr :selrect :val selrect :ignore-touched true}
|
||||||
|
{:type :set :attr :points :val (:points bool) :ignore-touched true}
|
||||||
|
{:type :set :attr :x :val (get selrect :x) :ignore-touched true}
|
||||||
|
{:type :set :attr :y :val (get selrect :y) :ignore-touched true}
|
||||||
|
{:type :set :attr :width :val (get selrect :width) :ignore-touched true}
|
||||||
|
{:type :set :attr :height :val (get selrect :height) :ignore-touched true}
|
||||||
|
{:type :set :attr :fills :val (:fills bool) :ignore-touched true}
|
||||||
|
{:type :set :attr :strokes :val (:strokes bool) :ignore-touched true}]
|
||||||
|
|
||||||
|
change
|
||||||
|
{:type :mod-obj
|
||||||
|
:id (:id bool)
|
||||||
|
:operations operations}]
|
||||||
|
|
||||||
|
(-> state
|
||||||
|
(commit-change change :add-container true)
|
||||||
|
(assoc ::last-id group-id))))
|
||||||
|
|
||||||
(defn add-shape
|
(defn add-shape
|
||||||
[state params]
|
[state params]
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
[shape (cph/get-position-on-parent objects (:id head))]))
|
[shape (cph/get-position-on-parent objects (:id head))]))
|
||||||
|
|
||||||
(defn group->bool
|
(defn- group->bool
|
||||||
[type group objects]
|
[type group objects]
|
||||||
(let [shapes (->> (:shapes group)
|
(let [shapes (->> (:shapes group)
|
||||||
(map (d/getf objects)))
|
(map (d/getf objects)))
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.0.2
|
||||||
|
|
||||||
|
- Fix incorrect boolean type assignation
|
||||||
|
- Fix fill and stroke handling on boolean shape creation
|
||||||
|
- Add sample-bool.js to the playground directory
|
||||||
|
|
||||||
## 1.0.1
|
## 1.0.1
|
||||||
|
|
||||||
- Make the library generate a .penpot file compatible with penpot 2.7.x
|
- Make the library generate a .penpot file compatible with penpot 2.7.x
|
||||||
|
|
58
library/playground/sample-bool.js
Normal file
58
library/playground/sample-bool.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import * as penpot from "#self";
|
||||||
|
import { writeFile, readFile } from "fs/promises";
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const context = penpot.createBuildContext();
|
||||||
|
|
||||||
|
{
|
||||||
|
context.addFile({ name: "Test File 1" });
|
||||||
|
context.addPage({ name: "Foo Page" });
|
||||||
|
|
||||||
|
const groupId = context.addGroup({
|
||||||
|
name: "Bool Group"
|
||||||
|
})
|
||||||
|
|
||||||
|
context.addRect({
|
||||||
|
name: "Rect 1",
|
||||||
|
x: 20,
|
||||||
|
y: 20,
|
||||||
|
width:100,
|
||||||
|
height:100,
|
||||||
|
});
|
||||||
|
|
||||||
|
context.addRect({
|
||||||
|
name: "Rect 2",
|
||||||
|
x: 90,
|
||||||
|
y: 90,
|
||||||
|
width:100,
|
||||||
|
height:100,
|
||||||
|
fills: [{fillColor: "#fabada", fillOpacity:1}]
|
||||||
|
});
|
||||||
|
|
||||||
|
context.closeGroup();
|
||||||
|
context.addBool({
|
||||||
|
groupId: groupId,
|
||||||
|
type: "union"
|
||||||
|
});
|
||||||
|
|
||||||
|
context.closeBoard();
|
||||||
|
context.closeFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let result = await penpot.exportAsBytes(context);
|
||||||
|
await writeFile("sample-bool.zip", result);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
.catch((cause) => {
|
||||||
|
console.error(cause);
|
||||||
|
|
||||||
|
const innerCause = cause.cause;
|
||||||
|
if (innerCause) {
|
||||||
|
console.error("Inner cause:", innerCause);
|
||||||
|
}
|
||||||
|
process.exit(-1);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue