mirror of
https://github.com/penpot/penpot.git
synced 2026-01-29 08:41:55 -05:00
Compare commits
26 Commits
2.13.0-RC8
...
2.13.0-RC1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f65292a13c | ||
|
|
94722fdec2 | ||
|
|
28509e0418 | ||
|
|
9569fa2bcb | ||
|
|
852b31c3a0 | ||
|
|
84b3f5d7c6 | ||
|
|
cc81e56d82 | ||
|
|
a9e2fc8d94 | ||
|
|
18aca16f98 | ||
|
|
c6465e27e3 | ||
|
|
1834a18263 | ||
|
|
d220d07875 | ||
|
|
9ca76c745f | ||
|
|
3112b240a0 | ||
|
|
56fd66b91a | ||
|
|
1ce0b60e3d | ||
|
|
ef80901400 | ||
|
|
5306bed548 | ||
|
|
92a319ddd1 | ||
|
|
68a6d4c9a8 | ||
|
|
f07495ae95 | ||
|
|
23d5fc7408 | ||
|
|
8632b18eec | ||
|
|
33e650242c | ||
|
|
e03ad25118 | ||
|
|
5d7e6afd76 |
@@ -45,6 +45,15 @@
|
||||
:potok/reify-type
|
||||
{:level :error}
|
||||
|
||||
:redundant-primitive-coercion
|
||||
{:level :off}
|
||||
|
||||
:unused-excluded-var
|
||||
{:level :off}
|
||||
|
||||
:unresolved-excluded-var
|
||||
{:level :off}
|
||||
|
||||
:missing-protocol-method
|
||||
{:level :off}
|
||||
|
||||
|
||||
2
.github/workflows/build-tag.yml
vendored
2
.github/workflows/build-tag.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
MATTERMOST_CHANNEL: bot-alerts-cicd
|
||||
TEXT: |
|
||||
🐳 *[PENPOT] Docker image available: {{ github.ref_name }}*
|
||||
🐳 *[PENPOT] Docker image available: ${{ github.ref_name }}*
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@infra
|
||||
|
||||
|
||||
42
.github/workflows/plugins-deploy-api-doc.yml
vendored
42
.github/workflows/plugins-deploy-api-doc.yml
vendored
@@ -7,11 +7,11 @@ on:
|
||||
- staging
|
||||
- main
|
||||
paths:
|
||||
- "plugins/libs/plugin-types/index.d.ts"
|
||||
- "plugins/libs/plugin-types/REAME.md"
|
||||
- "plugins/tools/typedoc.css"
|
||||
- "plugins/CHANGELOG.md"
|
||||
- "plugins/wrangle-penpot-plugins-api-doc.toml"
|
||||
- 'plugins/libs/plugin-types/index.d.ts'
|
||||
- 'plugins/libs/plugin-types/REAME.md'
|
||||
- 'plugins/tools/typedoc.css'
|
||||
- 'plugins/CHANGELOG.md'
|
||||
- 'plugins/wrangler-penpot-plugins-api-doc.toml'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
gh_ref:
|
||||
@@ -86,16 +86,40 @@ jobs:
|
||||
run: |
|
||||
REF="${{ steps.vars.outputs.gh_ref }}"
|
||||
case "$REF" in
|
||||
main) echo "WORKER_NAME=penpot-plugins-api-doc-pro" >> $GITHUB_ENV ;;
|
||||
staging) echo "WORKER_NAME=penpot-plugins-api-doc-pre" >> $GITHUB_ENV ;;
|
||||
develop) echo "WORKER_NAME=penpot-plugins-api-doc-hourly" >> $GITHUB_ENV ;;
|
||||
main)
|
||||
echo "WORKER_NAME=penpot-plugins-api-doc-pro" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=doc.plugins.penpot.app" >> $GITHUB_ENV ;;
|
||||
staging)
|
||||
echo "WORKER_NAME=penpot-plugins-api-doc-pre" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=doc.plugins.penpot.dev" >> $GITHUB_ENV ;;
|
||||
develop)
|
||||
echo "WORKER_NAME=penpot-plugins-api-doc-hourly" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=doc.plugins.hourly.penpot.dev" >> $GITHUB_ENV ;;
|
||||
*) echo "Unsupported branch ${REF}" && exit 1 ;;
|
||||
esac
|
||||
|
||||
- name: Set the custom url
|
||||
working-directory: plugins
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i "s/WORKER_URI/${{ env.WORKER_URI }}/g" wrangler-penpot-plugins-api-doc.toml
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
workingDirectory: plugins
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy --config wrangle-penpot-plugins-api-doc.toml --name ${{ env.WORKER_NAME }}
|
||||
command: deploy --config wrangler-penpot-plugins-api-doc.toml --name ${{ env.WORKER_NAME }}
|
||||
|
||||
- name: Notify Mattermost
|
||||
if: failure()
|
||||
uses: mattermost/action-mattermost-notify@master
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
MATTERMOST_CHANNEL: bot-alerts-cicd
|
||||
TEXT: |
|
||||
❌ 🧩📚 *[PENPOT PLUGINS] Error deploying API documentation.*
|
||||
📄 Triggered from ref: `${{ inputs.gh_ref }}`
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@infra
|
||||
|
||||
127
.github/workflows/plugins-deploy-package.yml
vendored
Normal file
127
.github/workflows/plugins-deploy-package.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
name: Plugins/package deployer
|
||||
|
||||
on:
|
||||
# Deploy package from manual action
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
gh_ref:
|
||||
description: 'Name of the branch'
|
||||
type: choice
|
||||
required: true
|
||||
default: 'develop'
|
||||
options:
|
||||
- develop
|
||||
- staging
|
||||
- main
|
||||
plugin_name:
|
||||
description: 'Pluging name (like plugins/apps/<plugin_name>-plugin)'
|
||||
type: string
|
||||
required: true
|
||||
workflow_call:
|
||||
inputs:
|
||||
gh_ref:
|
||||
description: 'Name of the branch'
|
||||
type: string
|
||||
required: true
|
||||
default: 'develop'
|
||||
plugin_name:
|
||||
description: 'Publig name (from plugins/apps/<plugin_name>-plugin)'
|
||||
type: string
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: penpot-runner-01
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.gh_ref }}
|
||||
|
||||
# START: Setup Node and PNPM enabling cache
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
|
||||
- name: Enable PNPM
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: |
|
||||
corepack enable;
|
||||
corepack install;
|
||||
|
||||
- name: Get pnpm store path
|
||||
id: pnpm-store
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache pnpm store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-${{ hashFiles('plugins/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-
|
||||
# END: Setup Node and PNPM enabling cache
|
||||
|
||||
- name: Install deps
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm install --no-frozen-lockfile;
|
||||
pnpm add -D -w wrangler@latest;
|
||||
|
||||
- name: "Build package for ${{ inputs.plugin_name }}-plugin"
|
||||
working-directory: plugins
|
||||
shell: bash
|
||||
run: npx nx build ${{ inputs.plugin_name }}-plugin
|
||||
|
||||
- name: Select Worker name
|
||||
run: |
|
||||
REF="${{ inputs.gh_ref }}"
|
||||
case "$REF" in
|
||||
main)
|
||||
echo "WORKER_NAME=${{ inputs.plugin_name }}-plugin-pro" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=${{ inputs.plugin_name }}.plugins.penpot.app" >> $GITHUB_ENV ;;
|
||||
staging)
|
||||
echo "WORKER_NAME=${{ inputs.plugin_name }}-plugin-pre" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=${{ inputs.plugin_name }}.plugins.penpot.dev" >> $GITHUB_ENV ;;
|
||||
develop)
|
||||
echo "WORKER_NAME=${{ inputs.plugin_name }}-plugin-hourly" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=${{ inputs.plugin_name }}.plugins.hourly.penpot.dev" >> $GITHUB_ENV ;;
|
||||
*) echo "Unsupported branch ${REF}" && exit 1 ;;
|
||||
esac
|
||||
|
||||
- name: Set the custom url
|
||||
working-directory: plugins
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i "s/WORKER_URI/${{ env.WORKER_URI }}/g" apps/${{ inputs.plugin_name }}-plugin/wrangler.toml
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
workingDirectory: plugins
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy --config apps/${{ inputs.plugin_name }}-plugin/wrangler.toml --name ${{ env.WORKER_NAME }}
|
||||
|
||||
- name: Notify Mattermost
|
||||
if: failure()
|
||||
uses: mattermost/action-mattermost-notify@master
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
MATTERMOST_CHANNEL: bot-alerts-cicd
|
||||
TEXT: |
|
||||
❌ 🧩📦 *[PENPOT PLUGINS] Error deploying ${{ env.WORKER_NAME }}.*
|
||||
📄 Triggered from ref: `${{ inputs.gh_ref }}`
|
||||
Plugin name: `${{ inputs.plugin_name }}-plugin`
|
||||
Cloudflare worker name: `${{ env.WORKER_NAME }}`
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@infra
|
||||
143
.github/workflows/plugins-deploy-packages.yml
vendored
Normal file
143
.github/workflows/plugins-deploy-packages.yml
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
name: Plugins/packages deployer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- staging
|
||||
- main
|
||||
paths:
|
||||
- 'plugins/apps/*-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
gh_ref:
|
||||
description: 'Name of the branch'
|
||||
type: choice
|
||||
required: true
|
||||
default: 'develop'
|
||||
options:
|
||||
- develop
|
||||
- staging
|
||||
- main
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
colors_to_tokens: ${{ steps.filter.outputs.colors_to_tokens }}
|
||||
create_palette: ${{ steps.filter.outputs.create_palette }}
|
||||
lorem_ipsum: ${{ steps.filter.outputs.lorem_ipsum }}
|
||||
rename_layers: ${{ steps.filter.outputs.rename_layers }}
|
||||
contrast: ${{ steps.filter.outputs.contrast }}
|
||||
icons: ${{ steps.filter.outputs.icons }}
|
||||
poc_state: ${{ steps.filter.outputs.poc_state }}
|
||||
table: ${{ steps.filter.outputs.table }}
|
||||
# [For new plugins]
|
||||
# Add more outputs here
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: filter
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
colors_to_tokens:
|
||||
- 'plugins/apps/colors-to-tokens-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
contrast:
|
||||
- 'plugins/apps/contrast-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
create_palette:
|
||||
- 'plugins/apps/create-palette-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
icons:
|
||||
- 'plugins/apps/icons-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
lorem_ipsum:
|
||||
- 'plugins/apps/lorem-ipsum-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
rename_layers:
|
||||
- 'plugins/apps/rename-layers-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
table:
|
||||
- 'plugins/apps/table-plugin/**'
|
||||
- 'libs/plugins-styles/**'
|
||||
# [For new plugins]
|
||||
# Add more plugin filters here
|
||||
# another_plugin:
|
||||
# - 'plugins/apps/another-plugin/**'
|
||||
# - 'libs/plugins-styles/**'
|
||||
|
||||
colors-to-tokens-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.colors_to_tokens == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: colors-to-tokens
|
||||
|
||||
contrast-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.contrast == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: contrast
|
||||
|
||||
create-palette-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.create_palette == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: create-palette
|
||||
|
||||
icons-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.icons == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: icons
|
||||
|
||||
lorem-ipsum-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.lorem_ipsum == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: lorem-ipsum
|
||||
|
||||
rename-layers-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.rename_layers == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: rename-layers
|
||||
|
||||
table-plugin:
|
||||
needs: detect-changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.table == 'true'
|
||||
uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
plugin_name: table
|
||||
|
||||
# [For new plugins]
|
||||
# Add more jobs for other plugins below, following the same pattern
|
||||
# another-plugin:
|
||||
# needs: detect-changes
|
||||
# if: github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.another_plugin == 'true'
|
||||
# uses: ./.github/workflows/plugins-deploy-package.yml
|
||||
# secrets: inherit
|
||||
# with:
|
||||
# gh_ref: "${{ inputs.gh_ref || github.ref_name }}"
|
||||
# plugin_name: another
|
||||
123
.github/workflows/plugins-deploy-styles-doc.yml
vendored
Normal file
123
.github/workflows/plugins-deploy-styles-doc.yml
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
name: Plugins/styles-doc deployer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- staging
|
||||
- main
|
||||
paths:
|
||||
- 'plugins/apps/example-styles/**'
|
||||
- 'plugins/libs/plugins-styles/**'
|
||||
- 'plugins/wrangler-penpot-plugins-styles-doc.toml'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
gh_ref:
|
||||
description: 'Name of the branch'
|
||||
type: choice
|
||||
required: true
|
||||
default: 'develop'
|
||||
options:
|
||||
- develop
|
||||
- staging
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Extract some useful variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "gh_ref=${{ inputs.gh_ref || github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ steps.vars.outputs.gh_ref }}
|
||||
|
||||
# START: Setup Node and PNPM enabling cache
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
|
||||
- name: Enable PNPM
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: |
|
||||
corepack enable;
|
||||
corepack install;
|
||||
|
||||
- name: Get pnpm store path
|
||||
id: pnpm-store
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache pnpm store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-${{ hashFiles('plugins/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-
|
||||
# END: Setup Node and PNPM enabling cache
|
||||
|
||||
- name: Install deps
|
||||
working-directory: ./plugins
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm install --no-frozen-lockfile;
|
||||
pnpm add -D -w wrangler@latest;
|
||||
|
||||
- name: Build styles
|
||||
working-directory: plugins
|
||||
shell: bash
|
||||
run: npx nx run example-styles:build
|
||||
|
||||
- name: Select Worker name
|
||||
run: |
|
||||
REF="${{ steps.vars.outputs.gh_ref }}"
|
||||
case "$REF" in
|
||||
main)
|
||||
echo "WORKER_NAME=penpot-plugins-styles-doc-pro" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=styles-doc.plugins.penpot.app" >> $GITHUB_ENV ;;
|
||||
staging)
|
||||
echo "WORKER_NAME=penpot-plugins-styles-doc-pre" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=styles-doc.plugins.penpot.dev" >> $GITHUB_ENV ;;
|
||||
develop)
|
||||
echo "WORKER_NAME=penpot-plugins-styles-doc-hourly" >> $GITHUB_ENV
|
||||
echo "WORKER_URI=styles-doc.plugins.hourly.penpot.dev" >> $GITHUB_ENV ;;
|
||||
*) echo "Unsupported branch ${REF}" && exit 1 ;;
|
||||
esac
|
||||
|
||||
- name: Set the custom url
|
||||
working-directory: plugins
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i "s/WORKER_URI/${{ env.WORKER_URI }}/g" wrangler-penpot-plugins-styles-doc.toml
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
workingDirectory: plugins
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy --config wrangler-penpot-plugins-styles-doc.toml --name ${{ env.WORKER_NAME }}
|
||||
|
||||
- name: Notify Mattermost
|
||||
if: failure()
|
||||
uses: mattermost/action-mattermost-notify@master
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
MATTERMOST_CHANNEL: bot-alerts-cicd
|
||||
TEXT: |
|
||||
❌ 🧩💅 *[PENPOT PLUGINS] Error deploying Styles documentation.*
|
||||
📄 Triggered from ref: `${{ inputs.gh_ref }}`
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@infra
|
||||
25
.github/workflows/tests.yml
vendored
25
.github/workflows/tests.yml
vendored
@@ -21,7 +21,7 @@ concurrency:
|
||||
jobs:
|
||||
lint:
|
||||
name: "Linter"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
test-common:
|
||||
name: "Common Tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -53,7 +53,8 @@ jobs:
|
||||
|
||||
test-plugins:
|
||||
name: Plugins Runtime Linter & Tests
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -98,7 +99,7 @@ jobs:
|
||||
|
||||
test-frontend:
|
||||
name: "Frontend Tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -119,7 +120,7 @@ jobs:
|
||||
|
||||
test-render-wasm:
|
||||
name: "Render WASM Tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -143,7 +144,7 @@ jobs:
|
||||
|
||||
test-backend:
|
||||
name: "Backend Tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
services:
|
||||
@@ -182,7 +183,7 @@ jobs:
|
||||
|
||||
test-library:
|
||||
name: "Library Tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -196,7 +197,7 @@ jobs:
|
||||
|
||||
build-integration:
|
||||
name: "Build Integration Bundle"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
|
||||
steps:
|
||||
@@ -217,7 +218,7 @@ jobs:
|
||||
|
||||
test-integration-1:
|
||||
name: "Integration Tests 1/4"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
needs: build-integration
|
||||
|
||||
@@ -247,7 +248,7 @@ jobs:
|
||||
|
||||
test-integration-2:
|
||||
name: "Integration Tests 2/4"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
needs: build-integration
|
||||
|
||||
@@ -277,7 +278,7 @@ jobs:
|
||||
|
||||
test-integration-3:
|
||||
name: "Integration Tests 3/4"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
needs: build-integration
|
||||
|
||||
@@ -307,7 +308,7 @@ jobs:
|
||||
|
||||
test-integration-4:
|
||||
name: "Integration Tests 4/4"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: penpot-runner-02
|
||||
container: penpotapp/devenv:latest
|
||||
needs: build-integration
|
||||
|
||||
|
||||
@@ -32,6 +32,15 @@
|
||||
- Fix unhandled exception tokens creation dialog [Github #8110](https://github.com/penpot/penpot/issues/8110)
|
||||
- Fix allow negative spread values on shadow token creation [Taiga #13167](https://tree.taiga.io/project/penpot/issue/13167)
|
||||
- Fix spanish translations on import export token modal [Taiga #13171](https://tree.taiga.io/project/penpot/issue/13171)
|
||||
- Remove whitespaces from asset export filename [Github #8133](https://github.com/penpot/penpot/pull/8133)
|
||||
- Fix exception on uploading large fonts [Github #8135](https://github.com/penpot/penpot/pull/8135)
|
||||
- Fix unhandled exception on open-new-window helper [Github #7787](https://github.com/penpot/penpot/issues/7787)
|
||||
- Fix incorrect handling of input values on layout gap and padding inputs [Github #8113](https://github.com/penpot/penpot/issues/8113)
|
||||
- Fix several race conditions on path editor [Github #8187](https://github.com/penpot/penpot/pull/8187)
|
||||
- Fix app freeze when introducing an error on a very long token name [Taiga #13214](https://tree.taiga.io/project/penpot/issue/13214)
|
||||
- Fix import a file with shadow tokens [Taiga #13229](https://tree.taiga.io/project/penpot/issue/13229)
|
||||
- Fix allow spaces on token description [Taiga #13184](https://tree.taiga.io/project/penpot/issue/13184)
|
||||
- Fix error when creating a token with an invalid name [Taiga #13219](https://tree.taiga.io/project/penpot/issue/13219)
|
||||
|
||||
## 2.12.1
|
||||
|
||||
|
||||
@@ -873,11 +873,8 @@
|
||||
(import-storage-objects cfg)
|
||||
|
||||
(let [files (get manifest :files)
|
||||
result (reduce (fn [result {:keys [id] :as file}]
|
||||
result (reduce (fn [result file]
|
||||
(let [name' (get file :name)
|
||||
name' (if (map? name)
|
||||
(get name id)
|
||||
name')
|
||||
file (assoc file :name name')]
|
||||
(conj result (import-file cfg file))))
|
||||
[]
|
||||
|
||||
@@ -27,7 +27,17 @@
|
||||
[app.rpc.helpers :as rph]
|
||||
[app.rpc.quotes :as quotes]
|
||||
[app.storage :as sto]
|
||||
[app.util.services :as sv]))
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.services :as sv]
|
||||
[datoteka.io :as io])
|
||||
(:import
|
||||
java.io.InputStream
|
||||
java.io.OutputStream
|
||||
java.io.SequenceInputStream
|
||||
java.util.Collections))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
|
||||
(def valid-weight #{100 200 300 400 500 600 700 800 900 950})
|
||||
(def valid-style #{"normal" "italic"})
|
||||
@@ -105,7 +115,7 @@
|
||||
|
||||
(defn create-font-variant
|
||||
[{:keys [::sto/storage ::db/conn]} {:keys [data] :as params}]
|
||||
(letfn [(generate-missing! [data]
|
||||
(letfn [(generate-missing [data]
|
||||
(let [data (media/run {:cmd :generate-fonts :input data})]
|
||||
(when (and (not (contains? data "font/otf"))
|
||||
(not (contains? data "font/ttf"))
|
||||
@@ -116,8 +126,26 @@
|
||||
:hint "invalid font upload, unable to generate missing font assets"))
|
||||
data))
|
||||
|
||||
(process-chunks [chunks]
|
||||
(let [tmp (tmp/tempfile :prefix "penpot.tempfont." :suffix "")
|
||||
streams (map io/input-stream chunks)
|
||||
streams (Collections/enumeration streams)]
|
||||
(with-open [^OutputStream output (io/output-stream tmp)
|
||||
^InputStream input (SequenceInputStream. streams)]
|
||||
(io/copy input output))
|
||||
tmp))
|
||||
|
||||
(join-chunks [data]
|
||||
(reduce-kv (fn [data mtype content]
|
||||
(if (vector? content)
|
||||
(assoc data mtype (process-chunks content))
|
||||
data))
|
||||
data
|
||||
data))
|
||||
|
||||
(prepare-font [data mtype]
|
||||
(when-let [resource (get data mtype)]
|
||||
|
||||
(let [hash (sto/calculate-hash resource)
|
||||
content (-> (sto/content resource)
|
||||
(sto/wrap-with-hash hash))]
|
||||
@@ -156,7 +184,8 @@
|
||||
:otf-file-id (:id otf)
|
||||
:ttf-file-id (:id ttf)}))]
|
||||
|
||||
(let [data (generate-missing! data)
|
||||
(let [data (join-chunks data)
|
||||
data (generate-missing data)
|
||||
assets (persist-fonts-files! data)
|
||||
result (insert-font-variant! assets)]
|
||||
(vary-meta result assoc ::audit/replace-props (update params :data (comp vec keys))))))
|
||||
|
||||
@@ -97,9 +97,12 @@
|
||||
(def token-types
|
||||
(into #{} (keys token-type->dtcg-token-type)))
|
||||
|
||||
(def token-name-validation-regex
|
||||
#"^[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*$")
|
||||
|
||||
(def token-name-ref
|
||||
[:re {:title "TokenNameRef" :gen/gen sg/text}
|
||||
#"^(?!\$)([a-zA-Z0-9-$_]+\.?)*(?<!\.)$"])
|
||||
token-name-validation-regex])
|
||||
|
||||
(def ^:private schema:color
|
||||
[:map
|
||||
|
||||
@@ -1462,11 +1462,12 @@ Will return a value that matches this schema:
|
||||
(def ^:private schema:dtcg-node
|
||||
[:schema {:registry
|
||||
{::simple-value
|
||||
[:or :string :int :double]
|
||||
[:or :string :int :double ::sm/boolean]
|
||||
::value
|
||||
[:or
|
||||
[:ref ::simple-value]
|
||||
[:vector ::simple-value]
|
||||
[:vector [:map-of :string ::simple-value]]
|
||||
[:map-of :string [:or
|
||||
[:ref ::simple-value]
|
||||
[:vector ::simple-value]]]]}}
|
||||
|
||||
@@ -6,4 +6,4 @@ desc: Create, deploy, and use the Penpot plugin API with our comprehensive docum
|
||||
|
||||
# Penpot plugins API
|
||||
|
||||
We've got all the documentation you need for the API right <a target="_blank" href="https://penpot-plugins-api-doc.pages.dev/">here</a>.
|
||||
We've got all the documentation you need for the API right <a target="_blank" href="https://doc.plugins.penpot.app/">here</a>.
|
||||
|
||||
@@ -9,13 +9,13 @@ desc: See the Penpot plugin API changelog for version 1.0! Find breaking changes
|
||||
### <g-emoji class="g-emoji" alias="boom" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f680.png"><img class="emoji" alt="boom" height="20" width="20" src="https://github.githubassets.com/images/icons/emoji/unicode/1f680.png"></g-emoji> Epics and highlights</code>
|
||||
- This marks the release of version 1.0, and from this point forward, we’ll do our best to avoid making any more breaking changes (or make deprecations backward compatible).
|
||||
- We’ve redone the documentation. You can check the API here:
|
||||
[https://penpot-plugins-api-doc.pages.dev/](https://penpot-plugins-api-doc.pages.dev/)
|
||||
[https://doc.plugins.penpot.app/](https://doc.plugins.penpot.app/)
|
||||
- New samples repository with lots of samples to use the API:
|
||||
[https://github.com/penpot/penpot-plugins-samples](https://github.com/penpot/penpot-plugins-samples)
|
||||
|
||||
### <g-emoji class="g-emoji" alias="boom" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f4a5.png"><img class="emoji" alt="boom" height="20" width="20" src="https://github.githubassets.com/images/icons/emoji/unicode/1f4a5.png"></g-emoji> Breaking changes & Deprecations
|
||||
|
||||
- Changed types names to remove the Penpot prefix. So for example: <code class="language-js">PenpotShape</code> becomes <code class="language-js">Shape</code>; <code class="language-js">PenpotFile</code> becomes <code class="language-js">File</code>, and so on. Check the [API documentation](https://penpot-plugins-api-doc.pages.dev/) for more details.
|
||||
- Changed types names to remove the Penpot prefix. So for example: <code class="language-js">PenpotShape</code> becomes <code class="language-js">Shape</code>; <code class="language-js">PenpotFile</code> becomes <code class="language-js">File</code>, and so on. Check the [API documentation](https://doc.plugins.penpot.app/) for more details.
|
||||
- Changes on the <code class="language-js">penpot.on</code> and <code class="language-js">penpot.off</code> methods.
|
||||
Previously you had to send the original callback to the off method in order to remove an event listener. Now, <code class="language-js">penpot.on</code> will return an *id* that you can pass to the <code class="language-js">penpot.off</code> method in order to remove the listener.
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ There are two libraries that can help you with your plugin's development. They a
|
||||
|
||||
### Plugin styles
|
||||
|
||||
<code class="language-js">@penpot/plugin-styles</code> contains styles to help build the UI for Penpot plugins. To check the styles go to <a target="_blank" href="https://penpot-plugins-styles.pages.dev/">Plugin styles</a>.
|
||||
<code class="language-js">@penpot/plugin-styles</code> contains styles to help build the UI for Penpot plugins. To check the styles go to <a target="_blank" href="https://styles-doc.plugins.penpot.app/">Plugin styles</a>.
|
||||
|
||||
```bash
|
||||
npm install @penpot/plugin-styles
|
||||
@@ -139,7 +139,7 @@ parent.postMessage(responseMessage, targetOrigin);
|
||||
|
||||
By using these message-based events, any data retrieved through the Penpot API can be communicated to and from your plugin interface seamlessly.
|
||||
|
||||
For more detailed information, refer to the [Penpot Plugins API Documentation](https://penpot-plugins-api-doc.pages.dev/).
|
||||
For more detailed information, refer to the [Penpot Plugins API Documentation](https://doc.plugins.penpot.app/).
|
||||
|
||||
## 2.5. Step 5. Build the plugin file
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ penpot.library.local.createTypography();
|
||||
|
||||
Penpot has dark and light modes, and you can easily add this to your plugin so your interface adapts to both themes. When you add theme support, your plugin will automatically sync with Penpot's interface settings, so the user experience is consistent no matter which mode is selected. This makes your plugin look better and also ensures it stays in line with Penpot's overall design.
|
||||
|
||||
Just a heads-up: if you use the <a target="_blank" href="https://penpot-plugins-styles.pages.dev/">plugin-styles library</a>, many elements will automatically adapt to dark or light mode without any extra effort from you. However, if you need to customize specific elements, be sure to use the selectors provided in the <code class="language-bash">styles.css</code> of the example.
|
||||
Just a heads-up: if you use the <a target="_blank" href="https://styles-doc.plugins.penpot.app/">plugin-styles library</a>, many elements will automatically adapt to dark or light mode without any extra effort from you. However, if you need to customize specific elements, be sure to use the selectors provided in the <code class="language-bash">styles.css</code> of the example.
|
||||
|
||||
<a target="_blank" href="https://github.com/penpot/penpot-plugins-samples/tree/main/theme">Theme example</a>
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ The plugin <a target="_blank" href="https://www.npmjs.com/package/@penpot/plugin
|
||||
|
||||
### Is the API ready to use the prototyping features?
|
||||
|
||||
Absolutely! You can definitely create flows and interactions in the same elements as in the interface, like frames, shapes, and groups. Just check out the API documentation for the methods: createFlow, addInteraction, or removeInteraction. And if you need more help, you can always check out the <a target="_blank" href="https://penpot-plugins-api-doc.pages.dev/interfaces/PenpotFlow">PenpotFlow</a> or <a target="_blank" href="https://penpot-plugins-api-doc.pages.dev/interfaces/PenpotInteraction">PenpotInteraction</a> interfaces.
|
||||
Absolutely! You can definitely create flows and interactions in the same elements as in the interface, like frames, shapes, and groups. Just check out the API documentation for the methods: createFlow, addInteraction, or removeInteraction. And if you need more help, you can always check out the <a target="_blank" href="https://doc.plugins.penpot.app/interfaces/Flow">Flow</a> or <a target="_blank" href="https://doc.plugins.penpot.app/interfaces/Interaction">Interaction</a> interfaces.
|
||||
|
||||
### Are there any security or quality criteria I should be aware of?
|
||||
|
||||
@@ -48,7 +48,8 @@ There are no set requirements. However, we can recommend the use of <a target="_
|
||||
|
||||
### Is it necessary to create plugins with a UI?
|
||||
|
||||
No, it’s completely optional, in fact, we have an example of a plugin without UI. Try the plugin using this url to install it: <code class="language-js">https:\/\/create-palette-penpot-plugin.pages.dev/assets/manifest.json</code> or check the code <a target="_blank" href="https://github.com/penpot/penpot-plugins/tree/main/apps/create-palette-plugin">here</a>
|
||||
No, it’s completely optional, in fact, we have an example of a plugin without UI. Try the plugin using this url to install it: <code class="language-js">https:\/\/create-palette.plugins.penpot.app/assets/manifest.json</code> or check the code <a target="_blank" href="https://github.com/penpot/penpot/tree/main/plugins/apps/create-palette-plugin">here</a>
|
||||
|
||||
|
||||
### Can I create components?
|
||||
|
||||
@@ -58,7 +59,7 @@ Yes, it is possible to create components using:
|
||||
createComponent(shapes: Shape[]): LibraryComponent;
|
||||
```
|
||||
|
||||
Take a look at the Penpot Library methods in the <a target="_blank" href="https://penpot-plugins-api-doc.pages.dev/interfaces/Library">API documentation</a> or this <a target="_blank" href="https://github.com/penpot/penpot-plugins-samples/tree/main/components-library">simple example</a>.
|
||||
Take a look at the Penpot Library methods in the <a target="_blank" href="https://doc.plugins.penpot.app/interfaces/Library">API documentation</a> or this <a target="_blank" href="https://github.com/penpot/penpot-plugins-samples/tree/main/components-library">simple example</a>.
|
||||
|
||||
### Is there a place where I can share my plugin?
|
||||
|
||||
|
||||
@@ -69,12 +69,13 @@ You need to provide the plugin's manifest URL for the installation. If there are
|
||||
|
||||
| Name | URL |
|
||||
| ------------- | ------------------------------------------------------------------- |
|
||||
| Lorem Ipsum | https://lorem-ipsum-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Contrast | https://contrast-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Feather icons | https://icons-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Tables | https://table-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Color palette | https://create-palette-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Rename layers | https://rename-layers-penpot-plugin.pages.dev/assets/manifest.json |
|
||||
| Color palette | https://create-palette.plugins.penpot.app/assets/manifest.json |
|
||||
| Contrast | https://contrast.plugins.penpot.app/assets/manifest.json |
|
||||
| Feather icons | https://icons.plugins.penpot.app/assets/manifest.json |
|
||||
| Lorem ipsum | https://lorem-ipsum.plugins.penpot.app/assets/manifest.json |
|
||||
| Rename layers | https://rename-layers.plugins.penpot.app/assets/manifest.json |
|
||||
| Tables | https://table.plugins.penpot.app/assets/manifest.json |
|
||||
|
||||
|
||||
## 1.4. Plugin's basics
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
{:path path
|
||||
:mtype (mime/get type)
|
||||
:name name
|
||||
:filename (str/concat name (mime/get-extension type))
|
||||
:filename (str/concat (str/slug name) (mime/get-extension type))
|
||||
:id task-id}))
|
||||
|
||||
(defn create-zip
|
||||
|
||||
@@ -110,7 +110,7 @@ test("Update an already created text shape by prepending text", async ({
|
||||
await workspace.textEditor.stopEditing();
|
||||
});
|
||||
|
||||
test("Update an already created text shape by inserting text in between", async ({
|
||||
test.skip("Update an already created text shape by inserting text in between", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
@@ -151,7 +151,7 @@ test("Update a new text shape appending text by pasting text", async ({
|
||||
await workspace.textEditor.stopEditing();
|
||||
});
|
||||
|
||||
test("Update a new text shape prepending text by pasting text", async ({
|
||||
test.skip("Update a new text shape prepending text by pasting text", async ({
|
||||
page,
|
||||
context,
|
||||
}) => {
|
||||
|
||||
@@ -24,6 +24,20 @@
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(def ^:const default-chunk-size
|
||||
(* 1024 1024 4)) ;; 4MiB
|
||||
|
||||
(defn- chunk-array
|
||||
[data chunk-size]
|
||||
(let [total-size (alength data)]
|
||||
(loop [offset 0
|
||||
chunks []]
|
||||
(if (< offset total-size)
|
||||
(let [end (min (+ offset chunk-size) total-size)
|
||||
chunk (.subarray ^js data offset end)]
|
||||
(recur end (conj chunks chunk)))
|
||||
chunks))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; General purpose events & IMPL
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -116,9 +130,9 @@
|
||||
(not= hhea-descender win-descent)
|
||||
(and f-selection (or
|
||||
(not= hhea-ascender os2-ascent)
|
||||
(not= hhea-descender os2-descent))))]
|
||||
|
||||
{:content {:data (js/Uint8Array. data)
|
||||
(not= hhea-descender os2-descent))))
|
||||
data (js/Uint8Array. data)]
|
||||
{:content {:data (chunk-array data default-chunk-size)
|
||||
:name name
|
||||
:type type}
|
||||
:font-family (or family "")
|
||||
|
||||
@@ -70,20 +70,22 @@
|
||||
(= (-> content last :command) :move-to))
|
||||
(into [] (take (dec (count content)) content))
|
||||
content)]
|
||||
(-> state
|
||||
(st/set-content content))))
|
||||
(st/set-content state content)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
id (dm/get-in state [:workspace-local :edition])
|
||||
old-content (dm/get-in state [:workspace-local :edit-path id :old-content])
|
||||
shape (st/get-path state)]
|
||||
local (get state :workspace-local)
|
||||
id (get local :edition)
|
||||
objects (dsh/lookup-page-objects state page-id)]
|
||||
|
||||
(if (and (some? old-content) (some? (:id shape)))
|
||||
(let [changes (generate-path-changes it objects page-id shape old-content (:content shape))]
|
||||
(rx/of (dch/commit-changes changes)))
|
||||
(rx/empty)))))))
|
||||
;; NOTE: we proceed only if the shape is present on the
|
||||
;; objects, if shape is a ephimeral drawing shape, we should
|
||||
;; do nothing
|
||||
(when-let [shape (get objects id)]
|
||||
(when-let [old-content (dm/get-in local [:edit-path id :old-content])]
|
||||
(let [new-content (get shape :content)
|
||||
changes (generate-path-changes it objects page-id shape old-content new-content)]
|
||||
(rx/of (dch/commit-changes changes))))))))))
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.path.helpers :as path.helpers]
|
||||
@@ -289,34 +288,34 @@
|
||||
|
||||
(declare stop-path-edit)
|
||||
|
||||
|
||||
(defn start-path-edit
|
||||
[id]
|
||||
(ptk/reify ::start-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edit-path (dm/get-in state [:workspace-local :edit-path id])
|
||||
content (st/get-path state :content)
|
||||
state (cond-> state
|
||||
(cfh/path-shape? objects id)
|
||||
(st/set-content (path/close-subpaths content)))]
|
||||
shape (get objects id)]
|
||||
|
||||
(cond-> state
|
||||
(or (not edit-path)
|
||||
(= :draw (:edit-mode edit-path)))
|
||||
(assoc-in [:workspace-local :edit-path id] {:edit-mode :move
|
||||
:selected #{}
|
||||
:snap-toggled false})
|
||||
(and (some? edit-path)
|
||||
(= :move (:edit-mode edit-path)))
|
||||
(assoc-in [:workspace-local :edit-path id :edit-mode] :draw))))
|
||||
(-> state
|
||||
(st/set-content (path/close-subpaths (:content shape)))
|
||||
(update-in [:workspace-local :edit-path id]
|
||||
(fn [state]
|
||||
(let [state (if state
|
||||
(if (= :move (:edit-mode state))
|
||||
(assoc state :edit-mode :draw)
|
||||
state)
|
||||
{:edit-mode :move
|
||||
:selected #{}
|
||||
:snap-toggled false})]
|
||||
(assoc state :old-content (:content shape))))))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(let [stopper (->> stream
|
||||
(rx/filter #(let [type (ptk/type %)]
|
||||
(= type ::dwe/clear-edition-mode)
|
||||
(= type ::start-path-edit))))]
|
||||
(let [stopper (rx/filter #(let [type (ptk/type %)]
|
||||
(= type ::dwe/clear-edition-mode)
|
||||
(= type ::start-path-edit))
|
||||
stream)]
|
||||
(rx/concat
|
||||
(rx/of (undo/start-path-undo))
|
||||
(->> stream
|
||||
@@ -325,7 +324,8 @@
|
||||
(rx/map #(stop-path-edit id))
|
||||
(rx/take-until stopper)))))))
|
||||
|
||||
(defn stop-path-edit [id]
|
||||
(defn stop-path-edit
|
||||
[id]
|
||||
(ptk/reify ::stop-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
@@ -335,13 +335,12 @@
|
||||
(watch [_ _ _]
|
||||
(rx/of (ptk/data-event :layout/update {:ids [id]})))))
|
||||
|
||||
(defn split-segments
|
||||
[{:keys [from-p to-p t]}]
|
||||
(defn- split-segments
|
||||
[id {:keys [from-p to-p t]}]
|
||||
(ptk/reify ::split-segments
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (st/get-path-id state)
|
||||
content (st/get-path state :content)]
|
||||
(let [content (st/get-path state :content)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :old-content] content)
|
||||
(st/set-content (-> content
|
||||
@@ -353,10 +352,10 @@
|
||||
(rx/of (changes/save-path-content {:preserve-move-to true})))))
|
||||
|
||||
(defn create-node-at-position
|
||||
[event]
|
||||
[params]
|
||||
(ptk/reify ::create-node-at-position
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [id (st/get-path-id state)]
|
||||
(rx/of (dwsh/update-shapes [id] path/convert-to-path)
|
||||
(split-segments event))))))
|
||||
(split-segments id params))))))
|
||||
|
||||
@@ -36,10 +36,12 @@
|
||||
|
||||
(defn- hide-popover
|
||||
[node]
|
||||
(dom/unset-css-property! node "block-size")
|
||||
(dom/unset-css-property! node "inset-block-start")
|
||||
(dom/unset-css-property! node "inset-inline-start")
|
||||
(.hidePopover ^js node))
|
||||
(when (and (some? node)
|
||||
(fn? (.-hidePopover node)))
|
||||
(dom/unset-css-property! node "block-size")
|
||||
(dom/unset-css-property! node "inset-block-start")
|
||||
(dom/unset-css-property! node "inset-inline-start")
|
||||
(.hidePopover ^js node)))
|
||||
|
||||
(defn- calculate-placement-bounding-rect
|
||||
"Given a placement, calcultates the bounding rect for it taking in
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
(def context (mf/create-context nil))
|
||||
|
||||
(mf/defc form-input*
|
||||
[{:keys [name] :rest props}]
|
||||
[{:keys [name trim] :rest props}]
|
||||
|
||||
(let [form (mf/use-ctx context)
|
||||
input-name name
|
||||
@@ -33,7 +33,7 @@
|
||||
(mf/deps input-name)
|
||||
(fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-input-value)]
|
||||
(fm/on-input-change form input-name value true))))
|
||||
(fm/on-input-change form input-name value trim))))
|
||||
|
||||
props
|
||||
(mf/spread-props props {:on-change on-change
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change ids)
|
||||
(fn [value attr event]
|
||||
(if (or (string? value) (int? value))
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change :simple attr value event)
|
||||
(do
|
||||
(let [resolved-value (:resolved-value (first value))
|
||||
@@ -489,7 +489,7 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change ids)
|
||||
(fn [value attr event]
|
||||
(if (or (string? value) (int? value))
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change :multiple attr value event)
|
||||
(do
|
||||
(let [resolved-value (:resolved-value (first value))]
|
||||
@@ -724,7 +724,7 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change wrap-type ids)
|
||||
(fn [value event attr]
|
||||
(if (or (string? value) (int? value))
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change (= "nowrap" wrap-type) attr value event)
|
||||
(do
|
||||
(let [resolved-value (:resolved-value (first value))]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.color :as cl]
|
||||
[app.common.types.token :as cto]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.style-dictionary :as sd]
|
||||
[app.main.data.tinycolor :as tinycolor]
|
||||
@@ -51,12 +52,15 @@
|
||||
;; Both variants provide identical color-picker and text-input behavior, but
|
||||
;; differ in how they persist the value within the form’s nested structure.
|
||||
|
||||
|
||||
(defn- resolve-value
|
||||
[tokens prev-token token-name value]
|
||||
(let [token
|
||||
(let [valid-token-name?
|
||||
(and (string? token-name)
|
||||
(re-matches cto/token-name-validation-regex token-name))
|
||||
|
||||
token
|
||||
{:value value
|
||||
:name (if (str/blank? token-name)
|
||||
:name (if (or (not valid-token-name?) (str/blank? token-name))
|
||||
"__PENPOT__TOKEN__NAME__PLACEHOLDER__"
|
||||
token-name)}
|
||||
|
||||
|
||||
@@ -50,9 +50,13 @@
|
||||
|
||||
(defn- resolve-value
|
||||
[tokens prev-token token-name value]
|
||||
(let [token
|
||||
(let [valid-token-name?
|
||||
(and (string? token-name)
|
||||
(re-matches cto/token-name-validation-regex token-name))
|
||||
|
||||
token
|
||||
{:value (cto/split-font-family value)
|
||||
:name (if (str/blank? token-name)
|
||||
:name (if (or (not valid-token-name?) (str/blank? token-name))
|
||||
"__PENPOT__TOKEN__NAME__PLACEHOLDER__"
|
||||
token-name)}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.files.tokens :as cft]
|
||||
[app.common.types.token :as cto]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.style-dictionary :as sd]
|
||||
[app.main.data.workspace.tokens.format :as dwtf]
|
||||
@@ -140,9 +141,13 @@
|
||||
|
||||
(defn- resolve-value
|
||||
[tokens prev-token token-name value]
|
||||
(let [token
|
||||
(let [valid-token-name?
|
||||
(and (string? token-name)
|
||||
(re-matches cto/token-name-validation-regex token-name))
|
||||
|
||||
token
|
||||
{:value value
|
||||
:name (if (str/blank? token-name)
|
||||
:name (if (or (not valid-token-name?) (str/blank? token-name))
|
||||
"__PENPOT__TOKEN__NAME__PLACEHOLDER__"
|
||||
token-name)}
|
||||
tokens
|
||||
|
||||
@@ -230,6 +230,7 @@
|
||||
:placeholder (tr "workspace.tokens.enter-token-name" token-title)
|
||||
:max-length max-input-length
|
||||
:variant "comfortable"
|
||||
:trim true
|
||||
:auto-focus true}]
|
||||
|
||||
(when (and warning-name-change? (= action "edit"))
|
||||
|
||||
@@ -106,17 +106,20 @@
|
||||
|
||||
(defn stop-propagation
|
||||
[^js event]
|
||||
(when event
|
||||
(when (and (some? event)
|
||||
(fn? (.-stopPropagation event)))
|
||||
(.stopPropagation event)))
|
||||
|
||||
(defn stop-immediate-propagation
|
||||
[^js event]
|
||||
(when event
|
||||
(when (and (some? event)
|
||||
(fn? (.-stopImmediatePropagation event)))
|
||||
(.stopImmediatePropagation event)))
|
||||
|
||||
(defn prevent-default
|
||||
[^js event]
|
||||
(when event
|
||||
(when (and (some? event)
|
||||
(fn? (.-preventDefault event)))
|
||||
(.preventDefault event)))
|
||||
|
||||
(defn get-target
|
||||
@@ -802,9 +805,10 @@
|
||||
([uri name]
|
||||
(open-new-window uri name "noopener,noreferrer"))
|
||||
([uri name features]
|
||||
(let [new-window (.open js/window (str uri) name features)]
|
||||
(when-let [new-window (.open js/window (str uri) name features)]
|
||||
(when (not= name "_blank")
|
||||
(.reload (.-location new-window))))))
|
||||
(when-let [location (.-location new-window)]
|
||||
(.reload location))))))
|
||||
|
||||
(defn browser-back
|
||||
[]
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
(ns app.util.keyboard
|
||||
(:require
|
||||
[app.config :as cfg]
|
||||
[app.util.dom :as dom]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defrecord KeyboardEvent [type key shift ctrl alt meta mod editing native-event]
|
||||
Object
|
||||
(preventDefault [_]
|
||||
(.preventDefault native-event))
|
||||
(dom/prevent-default native-event))
|
||||
|
||||
(stopPropagation [_]
|
||||
(.stopPropagation native-event)))
|
||||
(dom/stop-propagation native-event)))
|
||||
|
||||
(defn keyboard-event?
|
||||
[o]
|
||||
|
||||
@@ -7,7 +7,7 @@ different parts of the platform, please refer to `docs/` directory.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
We are using [GitHub Issues](https://github.com/penpot/penpot-plugins/issues)
|
||||
We are using [GitHub Issues](https://github.com/penpot/penpot/issues)
|
||||
for our public bugs. We keep a close eye on this and try to make it
|
||||
clear when we have an internal fix in progress. Before filing a new
|
||||
task, try to make sure your problem doesn't already exist.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/colors-to-tokens-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/colors-to-tokens-plugin/src/_headers",
|
||||
"apps/colors-to-tokens-plugin/src/favicon.ico",
|
||||
"apps/colors-to-tokens-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/colors-to-tokens-plugin/src/_headers
Normal file
4
plugins/apps/colors-to-tokens-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/colors-to-tokens-plugin/wrangler.toml
Normal file
8
plugins/apps/colors-to-tokens-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "color-to-tokens-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/colors-to-tokens-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/contrast-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/contrast-plugin/src/_headers",
|
||||
"apps/contrast-plugin/src/favicon.ico",
|
||||
"apps/contrast-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/contrast-plugin/src/_headers
Normal file
4
plugins/apps/contrast-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/contrast-plugin/wrangler.toml
Normal file
8
plugins/apps/contrast-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "contrast-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/contrast-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
4
plugins/apps/create-palette-plugin/public/_headers
Normal file
4
plugins/apps/create-palette-plugin/public/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/create-palette-plugin/wrangler.toml
Normal file
8
plugins/apps/create-palette-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "create-palette-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/create-palette-plugin" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/icons-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/icons-plugin/src/_headers",
|
||||
"apps/icons-plugin/src/favicon.ico",
|
||||
"apps/icons-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/icons-plugin/src/_headers
Normal file
4
plugins/apps/icons-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/icons-plugin/wrangler.toml
Normal file
8
plugins/apps/icons-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "icons-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/icons-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/lorem-ipsum-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/lorem-ipsum-plugin/src/_headers",
|
||||
"apps/lorem-ipsum-plugin/src/favicon.ico",
|
||||
"apps/lorem-ipsum-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/lorem-ipsum-plugin/src/_headers
Normal file
4
plugins/apps/lorem-ipsum-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/lorem-ipsum-plugin/wrangler.toml
Normal file
8
plugins/apps/lorem-ipsum-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "lorem-ipsum-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/lorem-ipsum-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/rename-layers-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/rename-layers-plugin/src/_headers",
|
||||
"apps/rename-layers-plugin/src/favicon.ico",
|
||||
"apps/rename-layers-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/rename-layers-plugin/src/_headers
Normal file
4
plugins/apps/rename-layers-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/rename-layers-plugin/wrangler.toml
Normal file
8
plugins/apps/rename-layers-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "rename-layers-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/rename-layers-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -16,6 +16,7 @@
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/table-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/table-plugin/src/_headers",
|
||||
"apps/table-plugin/src/favicon.ico",
|
||||
"apps/table-plugin/src/assets"
|
||||
],
|
||||
|
||||
4
plugins/apps/table-plugin/src/_headers
Normal file
4
plugins/apps/table-plugin/src/_headers
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type
|
||||
8
plugins/apps/table-plugin/wrangler.toml
Normal file
8
plugins/apps/table-plugin/wrangler.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "table-plugin"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "../../dist/apps/table-plugin/browser" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
@@ -19,7 +19,7 @@ the latest changes from the `main` branch. This will trigger the
|
||||
deployment at Cloudfare if the `libs/plugin-types/index.d.ts` or the
|
||||
`tools/typedoc.css` files have been updated.
|
||||
|
||||
Take a look at the [Penpot plugins API](https://penpot-plugins-api-doc.pages.dev/) to see what's new.
|
||||
Take a look at the [Penpot plugins API](https://doc.plugins.penpot.app/) to see what's new.
|
||||
|
||||
#### Styles
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Import the CSS file into your project:
|
||||
|
||||
For detailed examples and to see how to use the styles and components, visit the documentation at:
|
||||
|
||||
[Penpot Plugin Styles Documentation](https://penpot-plugins-styles.pages.dev)
|
||||
[Penpot Plugin Styles Documentation](https://styles-doc.plugins.penpot.app)
|
||||
|
||||
#### Icons
|
||||
|
||||
|
||||
@@ -2,3 +2,7 @@ name = "penpot-plugins-api-doc"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "dist/doc" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
8
plugins/wrangler-penpot-plugins-styles-doc.toml
Normal file
8
plugins/wrangler-penpot-plugins-styles-doc.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
name = "penpot-plugins-style-doc"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
assets = { directory = "dist/apps/example-styles" }
|
||||
|
||||
[[routes]]
|
||||
pattern = "WORKER_URI"
|
||||
custom_domain = true
|
||||
Reference in New Issue
Block a user