🎉 Import penpot-plugins repository

As commit 819a549e4928d2b1fa98e52bee82d59aec0f70d8
This commit is contained in:
Andrey Antukh
2025-12-29 14:13:49 +01:00
parent 22a36d59d8
commit ec1af4ad96
286 changed files with 50545 additions and 0 deletions

23
plugins/docs/api-docs.md Normal file
View File

@@ -0,0 +1,23 @@
### Plugins API Documentation
This document shows you how to create API documentation.
#### On your local
If you want to see what the document will look like (the HTML that's generated), you can run the following command:
```shell
npm run create:api-docs
```
Once you've done that, you'll find the result in `./dist/apps/api-doc`
#### Deploy the API Documentation
Just move to the `stable` branch in this repository and rebase it with 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.
#### Styles
If you want to make some style changes you can do it in `/tools/typedoc.css`.

View File

@@ -0,0 +1,153 @@
# Creating a Plugin
This guide walks you through the steps to create an Angular plugin for our platform. You'll start by setting up the basic structure, configuring necessary files, and then running a local server to preview your plugin.
If you prefer to create the plugin without a specific framework there's also [Creating a Plugin](./create-plugin.md).
Keep in mind that this guide is for creating a plugin **inside `penpot-plugins` monorepo**. If you want to create a plugin outside our environment you can check the [Penpot Plugin Starter Template](https://github.com/penpot/penpot-plugin-starter-template) or the documentation at [Create a Plugin](https://help.penpot.app/plugins/create-a-plugin/).
Let's dive in.
### Step 1: Initialize the Plugin
First, you need to create the scaffolding for your plugin. Use the following command, replacing `example-plugin` with the name of your plugin:
```sh
npx nx g @nx/angular:app example-plugin --directory=apps/example-plugin --bundler=esbuild
```
### Step 2: Configure the Manifest
Next, create a `manifest.json` file inside the `/src/assets` directory. This file is crucial as it defines key properties of your plugin, including permissions and the entry point script.
```json
{
"name": "Example plugin",
"host": "http://localhost:4200",
"code": "/assets/plugin.js",
"icon": "/assets/icon.png",
"permissions": [
"content:write",
"library:write",
"user:read",
"comment:read",
"allow:downloads"
]
}
```
### Step 3: Update Project Configuration
Now, add the plugin tag.
```typescript
"tags": ["type:plugin"],
```
Also, update `targets.build` with the following code to allow the use of Penpot styles and build the plugin code.
```json
"options": {
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/example-plugin/src/styles.css"
],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"dependsOn": ["buildPlugin"]
```
Add the default port to the `serve.configurations.development` task:
```json
"development": {
// ...
"port": 4302,
}
```
For choosing the port go check the Sample Plugins table at the [README](../README.md) so your plugin doesn't use a duplicate port. We're using the range 4300-4399.
### Step 4: Modify TypeScript Configuration
Create ``tsconfig.plugin.json` next to the `tsconfig.json`:
```json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": []
},
"files": ["src/plugin.ts"],
"include": ["../../libs/plugin-types/index.d.ts"]
}
```
Add the reference to the main tsconfig.json:
```json
"references": [
{
"path": "./tsconfig.plugin.json"
}
],
```
### Step 5: Add TS parser to eslint
Add these options to the end of the `eslint.config.js` file to allow linting with type information:
```js
{
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
tsconfigRootDir: import.meta.dirname,
},
},
},
```
### Strep 6: Hello world plugin code
Create the file `apps/example-plugin/src/plugin.ts` with the following code:
```ts
console.log('Hello Plugin');
```
### Step 7: Run the plugin
Run this command:
```sh
npx nx run example-plugin:init
```
This will run two tasks: `serve`, the usual Angular server, and `buildPlugin`, which will compile the `plugin.ts` file.
### Step 8: Load the Plugin in Penpot
To load your plugin into Penpot you can use the shortcut `Ctrl + Alt + P` to directly open the Plugin manager modal. There you need to provide the plugin's manifest URL (example: `http://plugin.example/manifest.json`) for the installation. If there's no issues the plugin will be installed and then you would be able to open it whenever you like.
You can also open the Plugin manager modal via:
- Menu
![Penpot's menu image](./images/plugin-menu.png)
### Step 9: Build plugin
```
npx nx run example-plugin:build
```
### Learn More About Plugin Development
For more detailed information on plugin development, check out our guides:
- [Plugin Usage Documentation](,/plugin-usage.md)

View File

@@ -0,0 +1,18 @@
# Create API
Add your API in `libs/plugins-runtime/src/lib/api/index.ts`.
Try to use `zod` to validate the input an output, for example:
```ts
{
sum: z.function()
.args(z.number(), z.number())
.returns(z.number())
.implement((callback, time) => {
setTimeout(callback, time);
});
}
```
Update `/libs/plugins-runtime/src/lib/api/index.d.ts`.

View File

@@ -0,0 +1,108 @@
# Creating a Plugin
This guide walks you through the steps to create a plugin for our platform. You'll start by setting up the basic structure, configuring necessary files, and then running a local server to preview your plugin.
If you prefer to create the plugin with angular, there's also a [Creating a Plugin (angular)](./create-angular-plugin.md).
Keep in mind that this guide is for creating a plugin **inside `penpot-plugins` monorepo**. If you want to create a plugin outside our environment you can check the [Penpot Plugin Starter Template](https://github.com/penpot/penpot-plugin-starter-template) or the documentation at [Create a Plugin](https://help.penpot.app/plugins/create-a-plugin/).
Let's dive in.
### Step 1: Initialize the Plugin
First, you need to create the scaffolding for your plugin. Use the following command, replacing `example-plugin` with the name of your plugin:
```sh
npx nx g @nx/web:application example-plugin --directory=apps/example-plugin
```
### Step 2: Migrate eslint to ESM
Replace `module.exports = [` with `export default [` and const `baseConfig = require('../../eslint.base.config.js');` with `import baseConfig from '../../eslint.config.js';`.
### Step 3: Configure the Manifest
Next, create a `manifest.json` file inside the `/public` directory. This file is crucial as it defines key properties of your plugin, including permissions and the entry point script.
```json
{
"name": "Example Plugin",
"host": "http://localhost:4201",
"code": "/plugin.js",
"icon": "/icon.png",
"permissions": [
"content:write",
"library:write",
"user:read",
"comment:read",
"allow:downloads"
]
}
```
### Step 4: Update Vite Configuration
Now, add the following configuration to your `vite.config.ts` to specify the entry points for the build process:
```typescript
build: {
rollupOptions: {
input: {
plugin: 'src/plugin.ts',
index: './index.html',
},
output: {
entryFileNames: '[name].js',
},
},
}
```
### Step 5: Modify TypeScript Configuration
Update your `tsconfig.app.json` to include the necessary TypeScript files for your plugin:
```json
{
"include": ["src/**/*.ts", "../../libs/plugin-types/index.d.ts"]
}
```
### Step 6: Run a Static Server
To preview your plugin, start a static server by running:
```sh
npx nx run example-plugin:build --watch & npx nx run example-plugin:preview
```
### Step 7: Add TS parser to eslint
Add these options to the end of the `eslint.config.js` file to allow linting with type information:
```js
{
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
tsconfigRootDir: import.meta.dirname,
},
},
},
```
### Step 8: Load the Plugin in Penpot
To load your plugin into Penpot you can use the shortcut `Ctrl + Alt + P` to directly open the Plugin manager modal. There you need to provide the plugin's manifest URL (example: `http://plugin.example/manifest.json`) for the installation. If there's no issues the plugin will be installed and then you would be able to open it whenever you like.
You can also open the Plugin manager modal via:
- Menu
![Penpot's menu image](./images/plugin-menu.png)
### Learn More About Plugin Development
For more detailed information on plugin development, check out our guides:
- [Create API Documentation](./create-api.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,84 @@
# Publishing Packages
## Introduction
This guide details the process of publishing `plugin-types`, `plugins-styles` and `plugins-runtime` packages, which are essential for plugin development. Below is a walkthrough for publishing these packages and managing releases.
## Publishing Libraries
Publishing packages enables the distribution of types and styles libraries. Currently, all packages share the same version, meaning some releases might not contain updates but will still increment the version. Follow the steps below for the automated publishing processes.
### Previewing a Release
To generate a preview of the release to check if everything is as expected, run the following command:
```shell
git checkout main
npm run release
```
### Generating a Real Release
To create an actual release, disable the dry-run option:
```shell
npm run release -- --dry-run false
```
This command will:
- Update the `CHANGELOG.md`
- Update the library's `package.json` version
- Generate a commit
- Create a new git tag
- Publish to NPM with the `latest` tag
Ensure everything is correct before proceeding with the git push. Once verified, execute the following commands:
```shell
git push
git push origin vX.X.X
```
Replace `vX.X.X` with the new version number.
> 📘 To update the documentation site, you must also update the `stable` branch:
```shell
git checkout stable
git merge main
git push origin stable
```
For detailed information, refer to the [Nx Release Documentation](https://nx.dev/recipes/nx-release/get-started-with-nx-release).
### Creating a Preview Version
To generate a preview version and avoid publishing it as the latest release, use:
```shell
npm run release -- --dry-run false --latest false --preid next
```
For example, if the current version is `0.8.0` and you select the `prepatch` option as a version specifier, it will generate the version `0.8.1-next.0` and publish it with the next tag on npm.
### Help
To see more options, run:
```shell
npm run release -- --help
```
## Important Reminders
- Ensure to update the [penpot](https://github.com/penpot/penpot/blob/develop/frontend/package.json) and [penpot-plugin-starter-template](https://github.com/penpot/penpot-plugin-starter-template) with every release to provide developers with the latest configuration and features.
- Update the API documentations following [this documentation](api-docs.md).
## Relevant Files and Scripts
- **CSS Build Script**: `./tools/scripts/build-css.mjs`
- **Types Build Script**: `./tools/scripts/build-types.mjs`
- **Release Script**: `./tools/scripts/publish.ts`
- **Publish config**: `./nx.json`

82
plugins/docs/test-e2e.md Normal file
View File

@@ -0,0 +1,82 @@
## End-to-End (E2E) Testing Guide
### Setting Up
1. **Configure Environment Variables**
Create and populate the `.env` file with a valid user mail & password:
```env
E2E_LOGIN_EMAIL="test@penpot.app"
E2E_LOGIN_PASSWORD="123123123"
E2E_SCREENSHOTS= "true"
```
2. **Run E2E Tests**
Use the following command to execute the E2E tests:
```bash
npm run test:e2e
```
### Writing Tests
1. **Adding Tests**
Place your test files in the `/apps/e2e/src/**/*.spec.ts` directory. Below is an example of a test file:
```ts
import testingPlugin from './plugins/create-board-text-rect';
import { Agent } from './utils/agent';
describe('Plugins', () => {
it('create board - text - rectangle', async () => {
const agent = await Agent();
const result = await agent.runCode(testingPlugin.toString());
expect(result).toMatchSnapshot();
});
});
```
**Explanation**:
- `Agent` opens a browser, logs into Penpot, and creates a file.
- `runCode` executes the plugin code and returns the file state after execution.
2. **Using `runCode` Method**
The `runCode` method takes the plugin code as a string:
```ts
const result = await agent.runCode(testingPlugin.toString());
```
It can also accept an options object:
```ts
const result = await agent.runCode(testingPlugin.toString(), {
autoFinish: false, // default: true
screenshot: 'test-name', // default: ''
});
// Finish will close the browser & delete the file
agent.finish();
```
3. **Snapshot Testing**
The `toMatchSnapshot` method stores the result and throws an error if the content does not match the previous result:
```ts
expect(result).toMatchSnapshot();
```
Snapshots are stored in the `apps/e2e/src/__snapshots__/*.spec.ts.snap` directory.
If you need to refresh all the snapshopts run the test with the update option:
```bash
npm run test:e2e -- --update
```