Compare commits

...

1 Commits

Author SHA1 Message Date
alonso.torres
1c05ab27ac WIP 2026-01-08 10:41:30 +01:00
9 changed files with 70 additions and 13 deletions

View File

@@ -54,7 +54,7 @@
"devDependencies": {
"@penpot/draft-js": "portal:./packages/draft-js",
"@penpot/mousetrap": "portal:./packages/mousetrap",
"@penpot/plugins-runtime": "1.3.2",
"@penpot/plugins-runtime": "portal:../plugins/dist/plugins-runtime",
"@penpot/svgo": "penpot/svgo#v3.2",
"@penpot/text-editor": "portal:./text-editor",
"@playwright/test": "1.57.0",

View File

@@ -51,8 +51,23 @@
(update [_ state]
(update-in state [:workspace-local :open-plugins] (fnil disj #{}) id))))
(defn start-plugin!
[{:keys [plugin-id name description host code icon permissions allow-background]} ^js extensions]
(.ɵloadPlugin
^js ug/global
#js {:pluginId plugin-id
:name name
:description description
:host host
:code code
:icon icon
:allowBackground (boolean allow-background)
:permissions (apply array permissions)}
nil
extensions))
(defn- load-plugin!
[{:keys [plugin-id name description host code icon permissions]}]
[{:keys [plugin-id name description host code icon permissions] :as params}]
(try
(st/emit! (save-current-plugin plugin-id))
(.ɵloadPlugin

View File

@@ -210,7 +210,32 @@
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dp/check-open-plugin)
(fdf/fix-deleted-fonts-for-local-library file-id)))))
(fdf/fix-deleted-fonts-for-local-library file-id)))
ptk/EffectEvent
(effect [_ _ _]
(dp/start-plugin!
{:url "http://localhost:4400/manifest.json"
:code "plugin.js"
:host "http://localhost:4400"
:name "Penpot MCP Plugin"
:plugin-id "96dfa740-005d-8020-8007-55ede24a2bae"
:description "This plugin enables interaction with the Penpot MCP server"
:allow-background true
:permissions
#{"library:read"
"library:write"
"comment:read"
"content:write"
"comment:write"
"content:read"}}
#js
{:mcp
#js
{:getToken (fn [] "xxxxx")
:getServerUrl (fn [] "ws://localhost:4402")
:setMcpStatus (fn [status] (.log js/console status))}}))))
(defn- bundle-fetched
[{:keys [file file-id thumbnails] :as bundle}]

View File

@@ -1198,16 +1198,15 @@ __metadata:
languageName: node
linkType: hard
"@penpot/plugins-runtime@npm:1.3.2":
version: 1.3.2
resolution: "@penpot/plugins-runtime@npm:1.3.2"
"@penpot/plugins-runtime@portal:../external/penpot-plugins/dist/plugins-runtime::locator=frontend%40workspace%3A.":
version: 0.0.0-use.local
resolution: "@penpot/plugins-runtime@portal:../external/penpot-plugins/dist/plugins-runtime::locator=frontend%40workspace%3A."
dependencies:
"@penpot/plugin-types": "npm:^1.3.2"
ses: "npm:^1.1.0"
zod: "npm:^3.22.4"
checksum: 10c0/b6d2cb3a57bcbe58232db52b8224d1817495e96b34997bfa72421629b5f34a8c9cc71357c315dcab9d52ea036ed632a5efe0ac50f52e730901c02d498dfa1313
languageName: node
linkType: hard
linkType: soft
"@penpot/svgo@penpot/svgo#v3.2":
version: 4.0.0
@@ -4176,7 +4175,7 @@ __metadata:
dependencies:
"@penpot/draft-js": "portal:./packages/draft-js"
"@penpot/mousetrap": "portal:./packages/mousetrap"
"@penpot/plugins-runtime": "npm:1.3.2"
"@penpot/plugins-runtime": "portal:../external/penpot-plugins/dist/plugins-runtime"
"@penpot/svgo": "penpot/svgo#v3.2"
"@penpot/text-editor": "portal:./text-editor"
"@playwright/test": "npm:1.57.0"

View File

@@ -24,6 +24,10 @@ export function createModal(
inlineStart: window.innerWidth - width - 290,
};
if ((options as any).hidden) {
modal.style.setProperty('display', 'none');
}
modal.style.setProperty(
'--modal-block-start',
`${initialPosition.blockStart}px`,

View File

@@ -7,6 +7,7 @@ export async function createPlugin(
context: Context,
manifest: Manifest,
onCloseCallback: () => void,
apiExtensions?: Object,
) {
const evaluateSandbox = async () => {
try {
@@ -30,7 +31,7 @@ export async function createPlugin(
},
);
const sandbox = createSandbox(plugin);
const sandbox = createSandbox(plugin, apiExtensions);
evaluateSandbox();

View File

@@ -2,8 +2,10 @@ import type { Penpot } from '@penpot/plugin-types';
import type { createPluginManager } from './plugin-manager';
import { createApi } from './api';
import { ses } from './ses.js';
export function createSandbox(
plugin: Awaited<ReturnType<typeof createPluginManager>>,
apiExtensions?: Object,
) {
ses.hardenIntrinsics();
@@ -51,7 +53,7 @@ export function createSandbox(
});
};
const publicPluginApi = {
let publicPluginApi = {
penpot: proxyApi,
fetch: ses.harden(safeFetch),
setTimeout: ses.harden(
@@ -123,6 +125,11 @@ export function createSandbox(
structuredClone: ses.harden(window.structuredClone),
};
if (apiExtensions) {
publicPluginApi = Object.assign(publicPluginApi, apiExtensions);
}
const compartment = ses.createCompartment(publicPluginApi);
return {

View File

@@ -19,7 +19,9 @@ export const getPlugins = () => plugins;
const closeAllPlugins = () => {
plugins.forEach((pluginApi) => {
pluginApi.plugin.close();
if (!(pluginApi.manifest as any).allowBackground) {
pluginApi.plugin.close();
}
});
plugins = [];
@@ -38,6 +40,7 @@ window.addEventListener('message', (event) => {
export const loadPlugin = async function (
manifest: Manifest,
closeCallback?: () => void,
apiExtensions?: Object,
) {
try {
const context = contextBuilder && contextBuilder(manifest.pluginId);
@@ -55,6 +58,7 @@ export const loadPlugin = async function (
plugins = plugins.filter((api) => api !== plugin);
closeCallback && closeCallback();
},
apiExtensions,
);
plugins.push(plugin);
@@ -67,8 +71,9 @@ export const loadPlugin = async function (
export const ɵloadPlugin = async function (
manifest: Manifest,
closeCallback?: () => void,
apiExtensions?: Object
) {
loadPlugin(manifest, closeCallback);
loadPlugin(manifest, closeCallback, apiExtensions);
};
export const ɵloadPluginByUrl = async function (manifestUrl: string) {

View File

@@ -3,4 +3,5 @@ import { z } from 'zod';
export const openUISchema = z.object({
width: z.number().positive(),
height: z.number().positive(),
hidden: z.boolean().optional(),
});