mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
Merge pull request #6590 from penpot/niwinz-develop-library-fixes
✨ Add minor enhancements to penpot library
This commit is contained in:
@@ -1,5 +1,60 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
lint:
|
||||||
|
docker:
|
||||||
|
- image: penpotapp/devenv:latest
|
||||||
|
|
||||||
|
working_directory: ~/repo
|
||||||
|
resource_class: medium+
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "fmt check"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn install
|
||||||
|
yarn run fmt:clj:check
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint clj common"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn run lint:clj:common
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint clj frontend"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn run lint:clj:frontend
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint clj backend"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn run lint:clj:backend
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint clj exporter"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn run lint:clj:exporter
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint clj library"
|
||||||
|
working_directory: "."
|
||||||
|
command: |
|
||||||
|
yarn run lint:clj:library
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: "lint scss on frontend"
|
||||||
|
working_directory: "./frontend"
|
||||||
|
command: |
|
||||||
|
yarn install
|
||||||
|
yarn run lint:scss
|
||||||
|
|
||||||
test-common:
|
test-common:
|
||||||
docker:
|
docker:
|
||||||
- image: penpotapp/devenv:latest
|
- image: penpotapp/devenv:latest
|
||||||
@@ -19,14 +74,6 @@ jobs:
|
|||||||
keys:
|
keys:
|
||||||
- v1-dependencies-{{ checksum "common/deps.edn"}}
|
- v1-dependencies-{{ checksum "common/deps.edn"}}
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "fmt check & linter"
|
|
||||||
working_directory: "./common"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run fmt:clj:check
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: "JVM tests"
|
name: "JVM tests"
|
||||||
working_directory: "./common"
|
working_directory: "./common"
|
||||||
@@ -37,6 +84,7 @@ jobs:
|
|||||||
name: "NODE tests"
|
name: "NODE tests"
|
||||||
working_directory: "./common"
|
working_directory: "./common"
|
||||||
command: |
|
command: |
|
||||||
|
yarn install
|
||||||
yarn run test
|
yarn run test
|
||||||
|
|
||||||
- save_cache:
|
- save_cache:
|
||||||
@@ -63,23 +111,6 @@ jobs:
|
|||||||
keys:
|
keys:
|
||||||
- v1-dependencies-{{ checksum "frontend/deps.edn"}}
|
- v1-dependencies-{{ checksum "frontend/deps.edn"}}
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "prepopulate linter cache"
|
|
||||||
working_directory: "./common"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "fmt check & linter"
|
|
||||||
working_directory: "./frontend"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run fmt:clj:check
|
|
||||||
yarn run fmt:js:check
|
|
||||||
yarn run lint:scss
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: "unit tests"
|
name: "unit tests"
|
||||||
working_directory: "./frontend"
|
working_directory: "./frontend"
|
||||||
@@ -115,8 +146,8 @@ jobs:
|
|||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
working_directory: "./frontend"
|
working_directory: "./frontend"
|
||||||
command: |
|
command: |
|
||||||
yarn
|
yarn install
|
||||||
npx playwright install --with-deps
|
yarn run playwright install --with-deps chromium
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build Storybook
|
name: Build Storybook
|
||||||
@@ -185,21 +216,6 @@ jobs:
|
|||||||
keys:
|
keys:
|
||||||
- v1-dependencies-{{ checksum "backend/deps.edn" }}
|
- v1-dependencies-{{ checksum "backend/deps.edn" }}
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "prepopulate linter cache"
|
|
||||||
working_directory: "./common"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "fmt check & linter"
|
|
||||||
working_directory: "./backend"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run fmt:clj:check
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: "tests"
|
name: "tests"
|
||||||
working_directory: "./backend"
|
working_directory: "./backend"
|
||||||
@@ -217,35 +233,6 @@ jobs:
|
|||||||
- ~/.m2
|
- ~/.m2
|
||||||
key: v1-dependencies-{{ checksum "backend/deps.edn" }}
|
key: v1-dependencies-{{ checksum "backend/deps.edn" }}
|
||||||
|
|
||||||
test-exporter:
|
|
||||||
docker:
|
|
||||||
- image: penpotapp/devenv:latest
|
|
||||||
|
|
||||||
working_directory: ~/repo
|
|
||||||
resource_class: medium+
|
|
||||||
|
|
||||||
environment:
|
|
||||||
JAVA_OPTS: -Xmx4g -Xms100m -XX:+UseSerialGC
|
|
||||||
NODE_OPTIONS: --max-old-space-size=4096
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "prepopulate linter cache"
|
|
||||||
working_directory: "./common"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: "fmt check & linter"
|
|
||||||
working_directory: "./exporter"
|
|
||||||
command: |
|
|
||||||
yarn install
|
|
||||||
yarn run fmt:clj:check
|
|
||||||
yarn run lint:clj
|
|
||||||
|
|
||||||
test-render-wasm:
|
test-render-wasm:
|
||||||
docker:
|
docker:
|
||||||
- image: penpotapp/devenv:latest
|
- image: penpotapp/devenv:latest
|
||||||
@@ -278,10 +265,25 @@ jobs:
|
|||||||
workflows:
|
workflows:
|
||||||
penpot:
|
penpot:
|
||||||
jobs:
|
jobs:
|
||||||
- test-frontend
|
- lint
|
||||||
- test-components
|
- test-frontend:
|
||||||
- test-integration
|
requires:
|
||||||
- test-backend
|
- lint: success
|
||||||
- test-common
|
|
||||||
- test-exporter
|
- test-components:
|
||||||
|
requires:
|
||||||
|
- lint: success
|
||||||
|
|
||||||
|
- test-integration:
|
||||||
|
requires:
|
||||||
|
- lint: success
|
||||||
|
|
||||||
|
- test-backend:
|
||||||
|
requires:
|
||||||
|
- lint: success
|
||||||
|
|
||||||
|
- test-common:
|
||||||
|
requires:
|
||||||
|
- lint: success
|
||||||
|
|
||||||
- test-render-wasm
|
- test-render-wasm
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
(: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.features :as cfeat]
|
||||||
[app.common.files.changes :as ch]
|
[app.common.files.changes :as ch]
|
||||||
[app.common.files.migrations :as fmig]
|
[app.common.files.migrations :as fmig]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
@@ -133,20 +133,6 @@
|
|||||||
(def decode-add-component
|
(def decode-add-component
|
||||||
(sm/decode-fn schema:add-component sm/json-transformer))
|
(sm/decode-fn schema:add-component sm/json-transformer))
|
||||||
|
|
||||||
(def schema:add-component-instance
|
|
||||||
[:map
|
|
||||||
[:component-id ::sm/uuid]
|
|
||||||
[:file-id {:optional true} ::sm/uuid]
|
|
||||||
[:frame-id {:optional true} ::sm/uuid]
|
|
||||||
[:page-id {:optional true} ::sm/uuid]])
|
|
||||||
|
|
||||||
(def ^:private check-add-component-instance
|
|
||||||
(sm/check-fn schema:add-component-instance
|
|
||||||
:hint "invalid arguments passed for add-component-instance"))
|
|
||||||
|
|
||||||
(def decode-add-component-instance
|
|
||||||
(sm/decode-fn schema:add-component-instance sm/json-transformer))
|
|
||||||
|
|
||||||
(def schema:add-bool
|
(def schema:add-bool
|
||||||
[:map
|
[:map
|
||||||
[:group-id ::sm/uuid]
|
[:group-id ::sm/uuid]
|
||||||
@@ -198,11 +184,31 @@
|
|||||||
(-> (get-current-objects state)
|
(-> (get-current-objects state)
|
||||||
(get shape-id)))
|
(get shape-id)))
|
||||||
|
|
||||||
|
;; WORKAROUND: A copy of features from staging for make the library
|
||||||
|
;; generate files compatible with version released right now. This
|
||||||
|
;; should be removed and replaced with cfeat/default-features when 2.8
|
||||||
|
;; version is released
|
||||||
|
|
||||||
|
(def default-features
|
||||||
|
#{"fdata/shape-data-type"
|
||||||
|
"styles/v2"
|
||||||
|
"layout/grid"
|
||||||
|
"components/v2"
|
||||||
|
"plugins/runtime"
|
||||||
|
"design-tokens/v1"})
|
||||||
|
|
||||||
|
;; WORKAROUND: the same as features
|
||||||
|
(def available-migrations
|
||||||
|
(-> fmig/available-migrations
|
||||||
|
(disj "003-convert-path-content")
|
||||||
|
(disj "0002-clean-shape-interactions")
|
||||||
|
(disj "0003-fix-root-shape")))
|
||||||
|
|
||||||
(defn add-file
|
(defn add-file
|
||||||
[state params]
|
[state params]
|
||||||
(let [params (-> params
|
(let [params (-> params
|
||||||
(assoc :features cfeat/default-features)
|
(assoc :features default-features)
|
||||||
(assoc :migrations fmig/available-migrations)
|
(assoc :migrations available-migrations)
|
||||||
(update :id default-uuid))
|
(update :id default-uuid))
|
||||||
file (types.file/make-file params :create-page false)]
|
file (types.file/make-file params :create-page false)]
|
||||||
(-> state
|
(-> state
|
||||||
@@ -432,33 +438,6 @@
|
|||||||
(commit-change change1)
|
(commit-change change1)
|
||||||
(commit-change change2))))
|
(commit-change change2))))
|
||||||
|
|
||||||
|
|
||||||
(defn add-component-instance
|
|
||||||
[state params]
|
|
||||||
|
|
||||||
(let [{:keys [component-id file-id frame-id page-id]}
|
|
||||||
(check-add-component-instance params)
|
|
||||||
|
|
||||||
file-id
|
|
||||||
(or file-id (get state ::current-file-id))
|
|
||||||
|
|
||||||
frame-id
|
|
||||||
(or frame-id (get state ::current-frame-id))
|
|
||||||
|
|
||||||
page-id
|
|
||||||
(or page-id (get state ::current-page-id))
|
|
||||||
|
|
||||||
change
|
|
||||||
{:type :mod-obj
|
|
||||||
:id frame-id
|
|
||||||
:page-id page-id
|
|
||||||
:operations
|
|
||||||
[{:type :set :attr :component-root :val true}
|
|
||||||
{:type :set :attr :component-id :val component-id}
|
|
||||||
{:type :set :attr :component-file :val file-id}]}]
|
|
||||||
|
|
||||||
(commit-change state change)))
|
|
||||||
|
|
||||||
(defn delete-shape
|
(defn delete-shape
|
||||||
[file id]
|
[file id]
|
||||||
(commit-change
|
(commit-change
|
||||||
|
|||||||
12
library/CHANGES.md
Normal file
12
library/CHANGES.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
- Make the library generate a .penpot file compatible with penpot 2.7.x
|
||||||
|
- Remove useless method `addComponentInstance`
|
||||||
|
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
- Initial release after big refactor (from the first MVP prototype)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@penpot/library",
|
"name": "@penpot/library",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"author": "Kaleidos INC",
|
"author": "Kaleidos INC",
|
||||||
"packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538",
|
"packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538",
|
||||||
|
|||||||
106
library/playground/sample2.js
Normal file
106
library/playground/sample2.js
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import * as penpot from "#self";
|
||||||
|
import { writeFile, readFile } from "fs/promises";
|
||||||
|
import { createWriteStream } from "fs";
|
||||||
|
import { Writable } from "stream";
|
||||||
|
|
||||||
|
// console.log(penpot);
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const context = penpot.createBuildContext();
|
||||||
|
|
||||||
|
{
|
||||||
|
context.addFile({ name: "Test File 1" });
|
||||||
|
context.addPage({ name: "Foo Page" });
|
||||||
|
|
||||||
|
// Add image media
|
||||||
|
const buffer = await readFile("./playground/sample.jpg");
|
||||||
|
const blob = new Blob([buffer], { type: "image/jpeg" });
|
||||||
|
|
||||||
|
const mediaId = context.addFileMedia(
|
||||||
|
{
|
||||||
|
name: "avatar.jpg",
|
||||||
|
width: 512,
|
||||||
|
height: 512,
|
||||||
|
},
|
||||||
|
blob
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add image color asset
|
||||||
|
const assetColorId = context.addLibraryColor({
|
||||||
|
name: "Avatar",
|
||||||
|
opacity: 1,
|
||||||
|
image: {
|
||||||
|
...context.getMediaAsImage(mediaId),
|
||||||
|
keepAspectRatio: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const boardId = context.addBoard({
|
||||||
|
name: "Foo Board",
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 500,
|
||||||
|
height: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fill = {
|
||||||
|
fillColorRefId: assetColorId,
|
||||||
|
fillColorRefFile: context.currentFileId,
|
||||||
|
fillImage: {
|
||||||
|
...context.getMediaAsImage(mediaId),
|
||||||
|
keepAspectRatio: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const stroke = {
|
||||||
|
strokeColorRefId: assetColorId,
|
||||||
|
strokeColorRefFile: context.currentFileId,
|
||||||
|
strokeWidth: 48,
|
||||||
|
strokeAlignment: "inner",
|
||||||
|
strokeStyle: "solid",
|
||||||
|
strokeOpacity: 1,
|
||||||
|
strokeImage: {
|
||||||
|
...context.getMediaAsImage(mediaId),
|
||||||
|
keepAspectRatio: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
context.addRect({
|
||||||
|
name: "Rect 1",
|
||||||
|
x: 20,
|
||||||
|
y: 20,
|
||||||
|
width: 500,
|
||||||
|
height: 1000,
|
||||||
|
fills: [fill],
|
||||||
|
strokes: [stroke],
|
||||||
|
});
|
||||||
|
|
||||||
|
context.closeBoard();
|
||||||
|
context.closeFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let result = await penpot.exportAsBytes(context);
|
||||||
|
await writeFile("sample-sync.zip", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// // Create a file stream to write the zip to
|
||||||
|
// const output = createWriteStream('sample-stream.zip');
|
||||||
|
// // Wrap Node's stream in a WHATWG WritableStream
|
||||||
|
// const writable = Writable.toWeb(output);
|
||||||
|
// await penpot.exportStream(context, writable);
|
||||||
|
// }
|
||||||
|
})()
|
||||||
|
.catch((cause) => {
|
||||||
|
console.error(cause);
|
||||||
|
|
||||||
|
const innerCause = cause.cause;
|
||||||
|
if (innerCause) {
|
||||||
|
console.error("Inner cause:", innerCause);
|
||||||
|
}
|
||||||
|
process.exit(-1);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
68
library/playground/sample3.js
Normal file
68
library/playground/sample3.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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 pathContent = [
|
||||||
|
{
|
||||||
|
"command": "move-to",
|
||||||
|
"params": {
|
||||||
|
"x": 480.0,
|
||||||
|
"y": 839.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "line-to",
|
||||||
|
"params": {
|
||||||
|
"x": 439.0,
|
||||||
|
"y": 802.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "curve-to",
|
||||||
|
"params": {
|
||||||
|
"c1x": 368.0,
|
||||||
|
"c1y": 737.0,
|
||||||
|
"c2x": 310.0,
|
||||||
|
"c2y": 681.0,
|
||||||
|
"x": 264.0,
|
||||||
|
"y": 634.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "close-path",
|
||||||
|
"params": {}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
context.addPath({
|
||||||
|
name: "Path 1",
|
||||||
|
content: pathContent
|
||||||
|
});
|
||||||
|
|
||||||
|
context.closeBoard();
|
||||||
|
context.closeFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let result = await penpot.exportAsBytes(context);
|
||||||
|
await writeFile("sample-path.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);
|
||||||
|
});
|
||||||
@@ -230,16 +230,6 @@
|
|||||||
(catch :default cause
|
(catch :default cause
|
||||||
(handle-exception cause))))
|
(handle-exception cause))))
|
||||||
|
|
||||||
:addComponentInstance
|
|
||||||
(fn [params]
|
|
||||||
(try
|
|
||||||
(let [params (-> (decode-params params)
|
|
||||||
(fb/decode-add-component-instance))]
|
|
||||||
(-> (swap! state fb/add-component-instance params)
|
|
||||||
(get-last-id)))
|
|
||||||
(catch :default cause
|
|
||||||
(handle-exception cause))))
|
|
||||||
|
|
||||||
:addFileMedia
|
:addFileMedia
|
||||||
(fn [params blob]
|
(fn [params blob]
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,14 @@
|
|||||||
:is-shared
|
:is-shared
|
||||||
:version})
|
:version})
|
||||||
|
|
||||||
|
(defn- encode-shape*
|
||||||
|
[{:keys [type] :as shape}]
|
||||||
|
(let [shape (if (or (= type :path)
|
||||||
|
(= type :bool))
|
||||||
|
(update shape :content vec)
|
||||||
|
shape)]
|
||||||
|
(-> shape encode-shape json/encode)))
|
||||||
|
|
||||||
(defn- generate-file-export-procs
|
(defn- generate-file-export-procs
|
||||||
[{:keys [id data] :as file}]
|
[{:keys [id data] :as file}]
|
||||||
(cons
|
(cons
|
||||||
@@ -109,7 +117,7 @@
|
|||||||
(map (fn [[shape-id shape]]
|
(map (fn [[shape-id shape]]
|
||||||
(let [shape (assoc shape :page-id page-id)]
|
(let [shape (assoc shape :page-id page-id)]
|
||||||
[(str "files/" id "/pages/" page-id "/" shape-id ".json")
|
[(str "files/" id "/pages/" page-id "/" shape-id ".json")
|
||||||
(delay (-> shape encode-shape json/encode))]))
|
(delay (encode-shape* shape))]))
|
||||||
objects)))))))
|
objects)))))))
|
||||||
|
|
||||||
(->> (get data :components)
|
(->> (get data :components)
|
||||||
|
|||||||
Reference in New Issue
Block a user