♻️ Remove Nx and rely on pnpm monorepo features

This commit is contained in:
Juanfran
2026-02-04 13:16:07 +01:00
committed by Andrey Antukh
parent 45d04942cc
commit 96b682aa12
79 changed files with 1498 additions and 9053 deletions

1
plugins/.npmrc Normal file
View File

@@ -0,0 +1 @@
ignore-workspace-root-check=true

View File

@@ -1,7 +1,3 @@
{
"recommendations": [
"nrwl.angular-console",
"prettier.prettier-vscode",
"dbaeumer.vscode-eslint"
]
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
}

493
plugins/angular.json Normal file
View File

@@ -0,0 +1,493 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "apps",
"projects": {
"contrast-plugin": {
"projectType": "application",
"root": "apps/contrast-plugin",
"sourceRoot": "apps/contrast-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/contrast-plugin",
"index": "apps/contrast-plugin/src/index.html",
"browser": "apps/contrast-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/contrast-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": { "buildTarget": "contrast-plugin:build:production" },
"development": {
"buildTarget": "contrast-plugin:build:development",
"host": "0.0.0.0",
"port": 4302
}
},
"defaultConfiguration": "development"
}
}
},
"icons-plugin": {
"projectType": "application",
"root": "apps/icons-plugin",
"sourceRoot": "apps/icons-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/icons-plugin",
"index": "apps/icons-plugin/src/index.html",
"browser": "apps/icons-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/icons-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": { "buildTarget": "icons-plugin:build:production" },
"development": {
"buildTarget": "icons-plugin:build:development",
"host": "0.0.0.0",
"port": 4303
}
},
"defaultConfiguration": "development"
}
}
},
"lorem-ipsum-plugin": {
"projectType": "application",
"root": "apps/lorem-ipsum-plugin",
"sourceRoot": "apps/lorem-ipsum-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/lorem-ipsum-plugin",
"index": "apps/lorem-ipsum-plugin/src/index.html",
"browser": "apps/lorem-ipsum-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/lorem-ipsum-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "lorem-ipsum-plugin:build:production"
},
"development": {
"buildTarget": "lorem-ipsum-plugin:build:development",
"host": "0.0.0.0",
"port": 4304
}
},
"defaultConfiguration": "development"
}
}
},
"table-plugin": {
"projectType": "application",
"root": "apps/table-plugin",
"sourceRoot": "apps/table-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/table-plugin",
"index": "apps/table-plugin/src/index.html",
"browser": "apps/table-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/table-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": { "buildTarget": "table-plugin:build:production" },
"development": {
"buildTarget": "table-plugin:build:development",
"host": "0.0.0.0",
"port": 4306
}
},
"defaultConfiguration": "development"
}
}
},
"rename-layers-plugin": {
"projectType": "application",
"root": "apps/rename-layers-plugin",
"sourceRoot": "apps/rename-layers-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/rename-layers-plugin",
"index": "apps/rename-layers-plugin/src/index.html",
"browser": "apps/rename-layers-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/rename-layers-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "rename-layers-plugin:build:production"
},
"development": {
"buildTarget": "rename-layers-plugin:build:development",
"host": "0.0.0.0",
"port": 4307
}
},
"defaultConfiguration": "development"
}
}
},
"colors-to-tokens-plugin": {
"projectType": "application",
"root": "apps/colors-to-tokens-plugin",
"sourceRoot": "apps/colors-to-tokens-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/colors-to-tokens-plugin",
"index": "apps/colors-to-tokens-plugin/src/index.html",
"browser": "apps/colors-to-tokens-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/colors-to-tokens-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "colors-to-tokens-plugin:build:production"
},
"development": {
"buildTarget": "colors-to-tokens-plugin:build:development",
"host": "0.0.0.0",
"port": 4308
}
},
"defaultConfiguration": "development"
}
}
},
"poc-state-plugin": {
"projectType": "application",
"root": "apps/poc-state-plugin",
"sourceRoot": "apps/poc-state-plugin/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/apps/poc-state-plugin",
"index": "apps/poc-state-plugin/src/index.html",
"browser": "apps/poc-state-plugin/src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "apps/poc-state-plugin/tsconfig.app.json",
"assets": [
"apps/poc-state-plugin/src/favicon.ico",
"apps/poc-state-plugin/src/assets"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/poc-state-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "poc-state-plugin:build:production"
},
"development": {
"buildTarget": "poc-state-plugin:build:development",
"host": "0.0.0.0",
"port": 4309
}
},
"defaultConfiguration": "development"
}
}
}
},
"cli": {
"analytics": false
}
}

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "colors-to-tokens-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build colors-to-tokens-plugin",
"build:dev": "ng build colors-to-tokens-plugin --configuration development",
"serve": "ng serve colors-to-tokens-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,81 +0,0 @@
{
"name": "colors-to-tokens-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/colors-to-tokens-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/colors-to-tokens-plugin",
"index": "apps/colors-to-tokens-plugin/src/index.html",
"browser": "apps/colors-to-tokens-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/colors-to-tokens-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "colors-to-tokens-plugin:build:production"
},
"development": {
"buildTarget": "colors-to-tokens-plugin:build:development",
"host": "0.0.0.0",
"port": 4308
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "colors-to-tokens-plugin:build"
}
}
}
}

View File

@@ -41,7 +41,7 @@ penpot.ui.onMessage<PluginUIEvent>((message) => {
function resize(width: number, height: number) {
if ('resize' in penpot.ui) {
(penpot as any).ui.resize(width, height);
penpot.ui.resize(width, height);
}
}

View File

@@ -1,15 +1,11 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
root: __dirname,
cacheDir: '../node_modules/.vite/colors-to-tokens-plugin',
test: {
watch: false,
globals: true,
cache: {
dir: '../node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "contrast-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build contrast-plugin",
"build:dev": "ng build contrast-plugin --configuration development",
"serve": "ng serve contrast-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,81 +0,0 @@
{
"name": "contrast-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/contrast-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/contrast-plugin",
"index": "apps/contrast-plugin/src/index.html",
"browser": "apps/contrast-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/contrast-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "contrast-plugin:build:production"
},
"development": {
"buildTarget": "contrast-plugin:build:development",
"host": "0.0.0.0",
"port": 4302
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "contrast-plugin:build"
}
}
}
}

View File

@@ -1,14 +1,10 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
root: __dirname,
cacheDir: '../node_modules/.vite/contrast-plugin',
test: {
globals: true,
cache: {
dir: '../node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],

View File

@@ -1,3 +0,0 @@
{
"presets": ["@nx/js/babel"]
}

View File

@@ -1,8 +0,0 @@
{
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2016"
}
}

View File

@@ -0,0 +1,14 @@
{
"name": "create-palette-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:watch": "vite build --watch --mode development",
"preview": "vite preview",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,8 +0,0 @@
{
"name": "create-palette-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"sourceRoot": "apps/create-palette-plugin/src",
"tags": ["type:plugin"],
"targets": {}
}

View File

@@ -1,12 +1,9 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/create-palette-plugin',
server: {
port: 4305,
host: '0.0.0.0',
@@ -16,14 +13,7 @@ export default defineConfig({
port: 4305,
host: '0.0.0.0',
},
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
plugins: [tsconfigPaths()],
build: {
outDir: '../../dist/apps/create-palette-plugin',
reportCompressedSize: true,
@@ -40,12 +30,8 @@ export default defineConfig({
},
},
},
test: {
globals: true,
cache: {
dir: '../../node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],

View File

@@ -7,7 +7,7 @@ export default [
{
languageOptions: {
parser: typescriptEslintParser,
parserOptions: { project: './apps/e2e/tsconfig.json' },
parserOptions: { project: './tsconfig.json' },
},
},
{

View File

@@ -0,0 +1,10 @@
{
"name": "e2e",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"test": "vitest",
"lint": "eslint ."
}
}

View File

@@ -1,8 +0,0 @@
{
"name": "e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"implicitDependencies": [],
"tags": ["type:e2e"],
"targets": {}
}

View File

@@ -107,6 +107,7 @@ export async function Agent() {
console.log('Running plugin code...');
await page.evaluate((testingPlugin) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).ɵloadPlugin({
pluginId: 'TEST',
name: 'Test',

View File

@@ -1,16 +1,12 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/e2e',
test: {
testTimeout: 20000,
watch: false,
globals: true,
cache: {
dir: '../node_modules/.vitest',
},
environment: 'happy-dom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],

View File

@@ -1,3 +0,0 @@
{
"presets": ["@nx/js/babel"]
}

View File

@@ -1,8 +0,0 @@
{
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2016"
}
}

View File

@@ -0,0 +1,13 @@
{
"name": "example-styles",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:watch": "vite build --watch --mode development",
"preview": "vite preview",
"lint": "eslint ."
}
}

View File

@@ -1,8 +0,0 @@
{
"name": "example-styles",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"sourceRoot": "apps/example-styles/src",
"tags": ["type:app"],
"targets": {}
}

View File

@@ -25,7 +25,8 @@ export class AppElement extends HTMLElement {
el.remove();
});
(window as any).hljs.highlightAll();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).hljs?.highlightAll();
}
getIndentationSize(str: string) {

View File

@@ -1,12 +1,9 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/example-styles',
server: {
port: 4201,
host: '0.0.0.0',
@@ -17,12 +14,7 @@ export default defineConfig({
host: '0.0.0.0',
},
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
plugins: [tsconfigPaths()],
build: {
outDir: '../../dist/apps/example-styles',
@@ -34,9 +26,6 @@ export default defineConfig({
test: {
globals: true,
cache: {
dir: '../../node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "icons-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build icons-plugin",
"build:dev": "ng build icons-plugin --configuration development",
"serve": "ng serve icons-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,81 +0,0 @@
{
"name": "icons-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/icons-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/icons-plugin",
"index": "apps/icons-plugin/src/index.html",
"browser": "apps/icons-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/icons-plugin/src/styles.css"
],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
},
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "icons-plugin:build:production"
},
"development": {
"buildTarget": "icons-plugin:build:development",
"host": "0.0.0.0",
"port": 4303
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "icons-plugin:build"
}
}
}
}

View File

@@ -1,7 +1,6 @@
import { Component, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { FeatherIconNames, icons } from 'feather-icons';
import { SafeHtmlPipe } from './pipes/safe-html.pipe';
import { IconButtonComponent } from './components/icon-button/icon-button.component';
import { IconSearchComponent } from './components/icon-search/icon-search.component';
import { toSignal } from '@angular/core/rxjs-interop';
@@ -10,12 +9,7 @@ import { PluginMessageEvent } from '../model';
@Component({
selector: 'app-root',
imports: [
RouterModule,
SafeHtmlPipe,
IconButtonComponent,
IconSearchComponent,
],
imports: [RouterModule, IconButtonComponent, IconSearchComponent],
styleUrl: './app.component.css',
template: `<div class="icons-plugin">
<div class="icons-search">

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "lorem-ipsum-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build lorem-ipsum-plugin",
"build:dev": "ng build lorem-ipsum-plugin --configuration development",
"serve": "ng serve lorem-ipsum-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,81 +0,0 @@
{
"name": "lorem-ipsum-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/lorem-ipsum-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/lorem-ipsum-plugin",
"index": "apps/lorem-ipsum-plugin/src/index.html",
"browser": "apps/lorem-ipsum-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/lorem-ipsum-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "lorem-ipsum-plugin:build:production"
},
"development": {
"buildTarget": "lorem-ipsum-plugin:build:development",
"host": "0.0.0.0",
"port": 4304
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "lorem-ipsum-plugin:build"
}
}
}
}

View File

@@ -101,7 +101,7 @@ export function generateCharacters(count: number, startWithLorem = true) {
}
export function generateWords(count: number, startWithLorem = true) {
let words = [];
const words = [];
if (startWithLorem) {
words.push(...lorem.split(' ').slice(0, count));
@@ -115,9 +115,9 @@ export function generateWords(count: number, startWithLorem = true) {
}
export function generateSentences(count: number, startWithLorem = true) {
let sentences = [];
const sentences = [];
for (let i = 0; i < count; i++) {
let sentenceLength = Math.floor(Math.random() * 10) + 3; // between 3 and 12 words per sentence
const sentenceLength = Math.floor(Math.random() * 10) + 3; // between 3 and 12 words per sentence
let sentence = generateWords(sentenceLength, false);
if (startWithLorem && i === 0) {
@@ -131,9 +131,9 @@ export function generateSentences(count: number, startWithLorem = true) {
}
export function generateParagraphs(count: number, startWithLorem = true) {
let paragraphs = [];
const paragraphs = [];
for (let i = 0; i < count; i++) {
let paragraphLength = Math.floor(Math.random() * 5) + 3; // between 3 and 7 sentences per paragraph
const paragraphLength = Math.floor(Math.random() * 5) + 3; // between 3 and 7 sentences per paragraph
paragraphs.push(
generateSentences(paragraphLength, startWithLorem && i === 0),
);

View File

@@ -1,15 +1,11 @@
/// <reference types='vitest' />
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
root: __dirname,
cacheDir: '../node_modules/.vite/lorem-ipsum-plugin',
test: {
watch: false,
globals: true,
cache: {
dir: '../node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,15 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "poc-state-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build poc-state-plugin",
"build:dev": "ng build poc-state-plugin --configuration development",
"serve": "ng serve poc-state-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,80 +0,0 @@
{
"name": "poc-state-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/poc-state-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/poc-state-plugin",
"index": "apps/poc-state-plugin/src/index.html",
"browser": "apps/poc-state-plugin/src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "apps/poc-state-plugin/tsconfig.app.json",
"assets": [
"apps/poc-state-plugin/src/favicon.ico",
"apps/poc-state-plugin/src/assets"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/poc-state-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "poc-state-plugin:build:production"
},
"development": {
"buildTarget": "poc-state-plugin:build:development",
"port": 4301,
"host": "0.0.0.0"
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "poc-state-plugin:build"
}
}
}
}

View File

@@ -533,7 +533,7 @@ async function exportSelected() {
const selection = await penpot.selection[0];
if (selection) {
let data = await selection.export({ type: 'png', skipChildren: true });
const data = await selection.export({ type: 'png', skipChildren: true });
penpot.ui.sendMessage({
type: 'start-download',
name: 'export.png',
@@ -547,8 +547,8 @@ async function resizeModal() {
}
async function saveLocalStorage() {
let oldvalue = penpot.localStorage.getItem('test');
let newvalue = oldvalue ? parseInt(oldvalue, 10) + 1 : 1;
const oldvalue = penpot.localStorage.getItem('test');
const newvalue = oldvalue ? parseInt(oldvalue, 10) + 1 : 1;
console.log(newvalue);
penpot.localStorage.setItem('test', newvalue);
}

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "poc-tokens-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build colors-to-tokens-plugin",
"build:dev": "ng build colors-to-tokens-plugin --configuration development",
"serve": "ng serve colors-to-tokens-plugin",
"lint": "eslint .",
"test": "exit 0"
}
}

View File

@@ -1,79 +0,0 @@
{
"name": "poc-tokens-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/poc-tokens-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/poc-tokens-plugin",
"index": "apps/poc-tokens-plugin/src/index.html",
"browser": "apps/poc-tokens-plugin/src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "apps/poc-tokens-plugin/tsconfig.app.json",
"assets": [
"apps/poc-tokens-plugin/src/favicon.ico",
"apps/poc-tokens-plugin/src/assets"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/poc-tokens-plugin/src/styles.css"
],
"scripts": [],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "poc-tokens-plugin:build:production"
},
"development": {
"buildTarget": "poc-tokens-plugin:build:development",
"port": 4309,
"host": "0.0.0.0"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "poc-tokens-plugin:build"
}
}
}
}

View File

@@ -0,0 +1,17 @@
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
root: __dirname,
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: '../coverage/poc-tokens-plugins',
provider: 'v8',
},
},
});

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "rename-layers-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build rename-layers-plugin",
"build:dev": "ng build rename-layers-plugin --configuration development",
"serve": "ng serve rename-layers-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,81 +0,0 @@
{
"name": "rename-layers-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/rename-layers-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/rename-layers-plugin",
"index": "apps/rename-layers-plugin/src/index.html",
"browser": "apps/rename-layers-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/rename-layers-plugin/src/styles.css"
],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
},
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "rename-layers-plugin:build:production"
},
"development": {
"buildTarget": "rename-layers-plugin:build:development",
"host": "0.0.0.0",
"port": 4307
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "rename-layers-plugin:build"
}
}
}
}

View File

@@ -25,7 +25,6 @@ penpot.ui.onMessage<PluginMessageEvent>((message) => {
});
shapesToUpdate?.forEach((shape) => {
shape.name = shape.name.replace(
// eslint-disable-next-line
message.content.search,
message.content.replace,
);

View File

@@ -1,46 +1,33 @@
import baseConfig from '../../eslint.config.js';
import { compat } from '../../eslint.base.config.js';
import angular from '@angular-eslint/eslint-plugin';
import angularTemplate from '@angular-eslint/eslint-plugin-template';
import angularTemplateParser from '@angular-eslint/template-parser';
export default [
...baseConfig,
...compat
.config({
extends: [
'plugin:@nx/angular',
'plugin:@angular-eslint/template/process-inline-templates',
],
})
.map((config) => ({
...config,
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
})),
...compat
.config({ extends: ['plugin:@nx/angular-template'] })
.map((config) => ({
...config,
files: ['**/*.html'],
rules: {},
})),
{ ignores: ['**/assets/*.js'] },
{
files: ['**/*.ts'],
plugins: {
'@angular-eslint': angular,
},
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
@@ -48,4 +35,16 @@ export default [
},
},
},
{
files: ['**/*.html'],
plugins: {
'@angular-eslint/template': angularTemplate,
},
languageOptions: {
parser: angularTemplateParser,
},
processor: '@angular-eslint/template/extract-inline-html',
rules: {},
},
{ ignores: ['**/assets/*.js'] },
];

View File

@@ -0,0 +1,13 @@
{
"name": "table-plugin",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "ng build table-plugin",
"build:dev": "ng build table-plugin --configuration development",
"serve": "ng serve table-plugin",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,80 +0,0 @@
{
"name": "table-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/table-plugin/src",
"tags": ["type:plugin"],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/table-plugin",
"index": "apps/table-plugin/src/index.html",
"browser": "apps/table-plugin/src/main.ts",
"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"
],
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/table-plugin/src/styles.css"
],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
},
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production",
"dependsOn": ["buildPlugin"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "table-plugin:build:production"
},
"development": {
"buildTarget": "table-plugin:build:development",
"port": 4306
}
},
"defaultConfiguration": "development",
"continuous": true
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "table-plugin:build"
}
}
}
}

View File

@@ -69,7 +69,7 @@ export class AppComponent {
target.files[0] &&
target.files[0].type === 'text/csv'
) {
var reader = new FileReader();
const reader = new FileReader();
reader.readAsText(target.files[0]);
reader.onload = (e) => {
this.table = (e?.target?.result as string)

View File

@@ -1,986 +0,0 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-nx-welcome',
standalone: true,
imports: [CommonModule],
template: `
<!--
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
This is a starter component and can be deleted.
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
Delete this file and get started with your project!
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
-->
<style>
html {
-webkit-text-size-adjust: 100%;
font-family:
ui-sans-serif,
system-ui,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Arial,
'Noto Sans',
sans-serif,
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'Noto Color Emoji';
line-height: 1.5;
tab-size: 4;
scroll-behavior: smooth;
}
body {
font-family: inherit;
line-height: inherit;
margin: 0;
}
h1,
h2,
p,
pre {
margin: 0;
}
*,
::before,
::after {
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: currentColor;
}
h1,
h2 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
text-decoration: inherit;
}
pre {
font-family:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
}
svg {
display: block;
vertical-align: middle;
}
svg {
shape-rendering: auto;
text-rendering: optimizeLegibility;
}
pre {
background-color: rgba(55, 65, 81, 1);
border-radius: 0.25rem;
color: rgba(229, 231, 235, 1);
font-family:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
overflow: scroll;
padding: 0.5rem 0.75rem;
}
.shadow {
box-shadow:
0 0 #0000,
0 0 #0000,
0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.rounded {
border-radius: 1.5rem;
}
.wrapper {
width: 100%;
}
.container {
margin-left: auto;
margin-right: auto;
max-width: 768px;
padding-bottom: 3rem;
padding-left: 1rem;
padding-right: 1rem;
color: rgba(55, 65, 81, 1);
width: 100%;
}
#welcome {
margin-top: 2.5rem;
}
#welcome h1 {
font-size: 3rem;
font-weight: 500;
letter-spacing: -0.025em;
line-height: 1;
}
#welcome span {
display: block;
font-size: 1.875rem;
font-weight: 300;
line-height: 2.25rem;
margin-bottom: 0.5rem;
}
#hero {
align-items: center;
background-color: hsla(214, 62%, 21%, 1);
border: none;
box-sizing: border-box;
color: rgba(55, 65, 81, 1);
display: grid;
grid-template-columns: 1fr;
margin-top: 3.5rem;
}
#hero .text-container {
color: rgba(255, 255, 255, 1);
padding: 3rem 2rem;
}
#hero .text-container h2 {
font-size: 1.5rem;
line-height: 2rem;
position: relative;
}
#hero .text-container h2 svg {
color: hsla(162, 47%, 50%, 1);
height: 2rem;
left: -0.25rem;
position: absolute;
top: 0;
width: 2rem;
}
#hero .text-container h2 span {
margin-left: 2.5rem;
}
#hero .text-container a {
background-color: rgba(255, 255, 255, 1);
border-radius: 0.75rem;
color: rgba(55, 65, 81, 1);
display: inline-block;
margin-top: 1.5rem;
padding: 1rem 2rem;
text-decoration: inherit;
}
#hero .logo-container {
display: none;
justify-content: center;
padding-left: 2rem;
padding-right: 2rem;
}
#hero .logo-container svg {
color: rgba(255, 255, 255, 1);
width: 66.666667%;
}
#middle-content {
align-items: flex-start;
display: grid;
gap: 4rem;
grid-template-columns: 1fr;
margin-top: 3.5rem;
}
#learning-materials {
padding: 2.5rem 2rem;
}
#learning-materials h2 {
font-weight: 500;
font-size: 1.25rem;
letter-spacing: -0.025em;
line-height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
}
.list-item-link {
align-items: center;
border-radius: 0.75rem;
display: flex;
margin-top: 1rem;
padding: 1rem;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
width: 100%;
}
.list-item-link svg:first-child {
margin-right: 1rem;
height: 1.5rem;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
width: 1.5rem;
}
.list-item-link > span {
flex-grow: 1;
font-weight: 400;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.list-item-link > span > span {
color: rgba(107, 114, 128, 1);
display: block;
flex-grow: 1;
font-size: 0.75rem;
font-weight: 300;
line-height: 1rem;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.list-item-link svg:last-child {
height: 1rem;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
width: 1rem;
}
.list-item-link:hover {
color: rgba(255, 255, 255, 1);
background-color: hsla(162, 47%, 50%, 1);
}
.list-item-link:hover > span {
}
.list-item-link:hover > span > span {
color: rgba(243, 244, 246, 1);
}
.list-item-link:hover svg:last-child {
transform: translateX(0.25rem);
}
#other-links {
}
.button-pill {
padding: 1.5rem 2rem;
margin-bottom: 2rem;
transition-duration: 300ms;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
align-items: center;
display: flex;
}
.button-pill svg {
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
flex-shrink: 0;
width: 3rem;
}
.button-pill > span {
letter-spacing: -0.025em;
font-weight: 400;
font-size: 1.125rem;
line-height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
}
.button-pill span span {
display: block;
font-size: 0.875rem;
font-weight: 300;
line-height: 1.25rem;
}
.button-pill:hover svg,
.button-pill:hover {
color: rgba(255, 255, 255, 1) !important;
}
.nx-console:hover {
background-color: rgba(0, 122, 204, 1);
}
.nx-console svg {
color: rgba(0, 122, 204, 1);
}
.nx-console-jetbrains {
margin-top: 2rem;
}
.nx-console-jetbrains:hover {
background-color: rgba(255, 49, 140, 1);
}
.nx-console-jetbrains svg {
color: rgba(255, 49, 140, 1);
}
#nx-repo:hover {
background-color: rgba(24, 23, 23, 1);
}
#nx-repo svg {
color: rgba(24, 23, 23, 1);
}
#nx-cloud {
margin-bottom: 2rem;
margin-top: 2rem;
padding: 2.5rem 2rem;
}
#nx-cloud > div {
align-items: center;
display: flex;
}
#nx-cloud > div svg {
border-radius: 0.375rem;
flex-shrink: 0;
width: 3rem;
}
#nx-cloud > div h2 {
font-size: 1.125rem;
font-weight: 400;
letter-spacing: -0.025em;
line-height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
}
#nx-cloud > div h2 span {
display: block;
font-size: 0.875rem;
font-weight: 300;
line-height: 1.25rem;
}
#nx-cloud p {
font-size: 1rem;
line-height: 1.5rem;
margin-top: 1rem;
}
#nx-cloud pre {
margin-top: 1rem;
}
#nx-cloud a {
color: rgba(107, 114, 128, 1);
display: block;
font-size: 0.875rem;
line-height: 1.25rem;
margin-top: 1.5rem;
text-align: right;
}
#nx-cloud a:hover {
text-decoration: underline;
}
#commands {
padding: 2.5rem 2rem;
margin-top: 3.5rem;
}
#commands h2 {
font-size: 1.25rem;
font-weight: 400;
letter-spacing: -0.025em;
line-height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
}
#commands p {
font-size: 1rem;
font-weight: 300;
line-height: 1.5rem;
margin-top: 1rem;
padding-left: 1rem;
padding-right: 1rem;
}
details {
align-items: center;
display: flex;
margin-top: 1rem;
padding-left: 1rem;
padding-right: 1rem;
width: 100%;
}
details pre > span {
color: rgba(181, 181, 181, 1);
}
summary {
border-radius: 0.5rem;
display: flex;
font-weight: 400;
padding: 0.5rem;
cursor: pointer;
transition-property:
background-color,
border-color,
color,
fill,
stroke,
opacity,
box-shadow,
transform,
filter,
backdrop-filter,
-webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
summary:hover {
background-color: rgba(243, 244, 246, 1);
}
summary svg {
height: 1.5rem;
margin-right: 1rem;
width: 1.5rem;
}
#love {
color: rgba(107, 114, 128, 1);
font-size: 0.875rem;
line-height: 1.25rem;
margin-top: 3.5rem;
opacity: 0.6;
text-align: center;
}
#love svg {
color: rgba(252, 165, 165, 1);
width: 1.25rem;
height: 1.25rem;
display: inline;
margin-top: -0.25rem;
}
@media screen and (min-width: 768px) {
#hero {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
#hero .logo-container {
display: flex;
}
#middle-content {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
</style>
<div class="wrapper">
<div class="container">
<!-- WELCOME -->
<div id="welcome">
<h1>
<span> Hello there, </span>
Welcome table-plugin 👋
</h1>
</div>
<!-- HERO -->
<div id="hero" class="rounded">
<div class="text-container">
<h2>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"
/>
</svg>
<span>You&apos;re up and running</span>
</h2>
<a href="#commands"> What&apos;s next? </a>
</div>
<div class="logo-container">
<svg
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z"
/>
</svg>
</div>
</div>
<!-- MIDDLE CONTENT -->
<div id="middle-content">
<div id="learning-materials" class="rounded shadow">
<h2>Learning materials</h2>
<a
href="https://nx.dev/getting-started/intro?utm_source=nx-project"
target="_blank"
rel="noreferrer"
class="list-item-link"
>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
/>
</svg>
<span>
Documentation
<span> Everything is in there </span>
</span>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
/>
</svg>
</a>
<a
href="https://blog.nrwl.io/?utm_source=nx-project"
target="_blank"
rel="noreferrer"
class="list-item-link"
>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
/>
</svg>
<span>
Blog
<span> Changelog, features & events </span>
</span>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
/>
</svg>
</a>
<a
href="https://www.youtube.com/@NxDevtools/videos?utm_source=nx-project&sub_confirmation=1"
target="_blank"
rel="noreferrer"
class="list-item-link"
>
<svg
role="img"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<title>YouTube</title>
<path
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
/>
</svg>
<span>
YouTube channel
<span> Nx Show, talks & tutorials </span>
</span>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
/>
</svg>
</a>
<a
href="https://nx.dev/angular-tutorial/1-code-generation?utm_source=nx-project"
target="_blank"
rel="noreferrer"
class="list-item-link"
>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
/>
</svg>
<span>
Interactive tutorials
<span> Create an app, step-by-step </span>
</span>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
/>
</svg>
</a>
<a
href="https://nxplaybook.com/?utm_source=nx-project"
target="_blank"
rel="noreferrer"
class="list-item-link"
>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M12 14l9-5-9-5-9 5 9 5z" />
<path
d="M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222"
/>
</svg>
<span>
Video courses
<span> Nx custom courses </span>
</span>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
/>
</svg>
</a>
</div>
<div id="other-links">
<a
class="button-pill rounded shadow nx-console"
href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&utm_source=nx-project"
target="_blank"
rel="noreferrer"
>
<svg
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Visual Studio Code</title>
<path
d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z"
/>
</svg>
<span>
Install Nx Console for VSCode
<span>The official VSCode extension for Nx.</span>
</span>
</a>
<a
class="button-pill rounded shadow nx-console-jetbrains"
href="https://plugins.jetbrains.com/plugin/21060-nx-console"
target="_blank"
rel="noreferrer"
>
<svg
height="48"
width="48"
viewBox="20 20 60 60"
xmlns="http://www.w3.org/2000/svg"
>
<path d="m22.5 22.5h60v60h-60z" />
<g fill="#fff">
<path d="m29.03 71.25h22.5v3.75h-22.5z" />
<path
d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z"
/>
<path
d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z"
/>
<path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
<path
d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z"
/>
<path
d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z"
/>
<path
d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z"
/>
<path d="m56.46 43.05h2.6v9.37h-2.6z" />
<path
d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z"
/>
<path
d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z"
/>
</g>
</svg>
<span>
Install Nx Console for JetBrains
<span
>Available for WebStorm, Intellij IDEA Ultimate and
more!</span
>
</span>
</a>
<div id="nx-cloud" class="rounded shadow">
<div>
<svg
id="nx-cloud-logo"
role="img"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="transparent"
viewBox="0 0 24 24"
>
<path
stroke-width="2"
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
/>
<path
stroke-width="2"
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
/>
</svg>
<h2>
Nx Cloud
<span> Enable faster CI & better DX </span>
</h2>
</div>
<p>
You can activate distributed tasks executions and caching by
running:
</p>
<pre>nx connect-to-nx-cloud</pre>
<a
href="https://nx.app/?utm_source=nx-project"
target="_blank"
rel="noreferrer"
>
What is Nx Cloud?
</a>
</div>
<a
id="nx-repo"
class="button-pill rounded shadow"
href="https://github.com/nrwl/nx?utm_source=nx-project"
target="_blank"
rel="noreferrer"
>
<svg
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
/>
</svg>
<span>
Nx is open source
<span> Love Nx? Give us a star! </span>
</span>
</a>
</div>
</div>
<!-- COMMANDS -->
<div id="commands" class="rounded shadow">
<h2>Next steps</h2>
<p>Here are some things you can do with Nx:</p>
<details>
<summary>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Add UI library
</summary>
<pre><span># Generate UI lib</span>
nx g &#64;nx/angular:lib ui
<span># Add a component</span>
nx g &#64;nx/angular:component ui/src/lib/button</pre>
</details>
<details>
<summary>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
View project details
</summary>
<pre>nx show project table-plugin --web</pre>
</details>
<details>
<summary>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
View interactive project graph
</summary>
<pre>nx graph</pre>
</details>
<details>
<summary>
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Run affected commands
</summary>
<pre><span># see what&apos;s been affected by changes</span>
nx affected:graph
<span># run tests for current changes</span>
nx affected:test
<span># run e2e tests for current changes</span>
nx affected:e2e</pre>
</details>
</div>
<p id="love">
Carefully crafted with
<svg
fill="currentColor"
stroke="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
</p>
</div>
</div>
`,
styles: [],
encapsulation: ViewEncapsulation.None,
})
export class NxWelcomeComponent {}

View File

@@ -10,12 +10,17 @@ 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:
First, you need to create the scaffolding for your plugin. Use the Angular CLI to generate a new application:
```sh
pnpx nx g @nx/angular:app example-plugin --directory=apps/example-plugin --bundler=esbuild
cd apps
ng new example-plugin --style=css --routing=false --skip-git --skip-install
cd ..
pnpm install
```
Then register it in `angular.json` by adding a new project entry (see existing plugins for reference).
### 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.
@@ -38,40 +43,41 @@ Next, create a `manifest.json` file inside the `/src/assets` directory. This fil
### 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.
Update `angular.json` to configure the build for your plugin. Add to the project's `architect.build.options`:
```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,
"styles": [
"libs/plugins-styles/src/lib/styles.css",
"apps/example-plugin/src/styles.css"
],
"optimization": {
"scripts": true,
"styles": true,
"fonts": false
}
```
Add a custom port to `architect.serve.options`:
```json
"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.
Create a `package.json` in your plugin folder with build scripts:
```json
{
"name": "example-plugin",
"scripts": {
"build": "ng build example-plugin",
"serve": "ng serve example-plugin",
"lint": "eslint src --ext .ts,.html"
}
}
```
### Step 4: Modify TypeScript Configuration
Create ``tsconfig.plugin.json` next to the `tsconfig.json`:
@@ -125,10 +131,10 @@ console.log('Hello Plugin');
Run this command:
```sh
pnpx nx run example-plugin:init
pnpm --filter example-plugin serve
```
This will run two tasks: `serve`, the usual Angular server, and `buildPlugin`, which will compile the `plugin.ts` file.
This will start the Angular development server.
### Step 8: Load the Plugin in Penpot
@@ -142,8 +148,8 @@ You can also open the Plugin manager modal via:
### Step 9: Build plugin
```
pnpx nx run example-plugin:build
```sh
pnpm --filter example-plugin build
```
### Learn More About Plugin Development

View File

@@ -10,15 +10,50 @@ 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:
First, you need to create the scaffolding for your plugin. Create a new folder for your plugin:
```sh
pnpx nx g @nx/web:application example-plugin --directory=apps/example-plugin
mkdir -p apps/example-plugin/src apps/example-plugin/public
```
### Step 2: Migrate eslint to ESM
Create a basic `package.json` in `apps/example-plugin`:
Replace `module.exports = [` with `export default [` and const `baseConfig = require('../../eslint.base.config.js');` with `import baseConfig from '../../eslint.config.js';`.
```json
{
"name": "example-plugin",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint src --ext .ts"
}
}
```
Create a `vite.config.ts` file (see `apps/create-palette-plugin/vite.config.ts` for reference).
### Step 2: Create ESLint Config
Create an `eslint.config.js` file:
```js
import tseslint from 'typescript-eslint';
import eslintConfigPrettier from 'eslint-config-prettier';
export default tseslint.config(
...tseslint.configs.recommended,
eslintConfigPrettier,
{
languageOptions: {
parserOptions: {
project: './tsconfig.*?.json',
tsconfigRootDir: import.meta.dirname,
},
},
},
);
```
### Step 3: Configure the Manifest
@@ -73,25 +108,16 @@ Update your `tsconfig.app.json` to include the necessary TypeScript files for yo
To preview your plugin, start a static server by running:
```sh
pnpx nx run example-plugin:build --watch & pnpx nx run example-plugin:preview
pnpm --filter example-plugin dev
```
### Step 7: Add TS parser to eslint
Or for production preview:
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,
},
},
},
```sh
pnpm --filter example-plugin build && pnpm --filter example-plugin preview
```
### Step 8: Load the Plugin in Penpot
### Step 7: 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.

View File

@@ -11,15 +11,6 @@ packages and managing releases.
Before generating the release, please, check the update the changelog with
the changes that will be released.
## Problem with pnpm
There is an issue with dependencies and release with pnpm. For it to work
you need to add the following into your `.npmrc`
```
link-workspace-packages=true
```
## NPM Authentication
You need to generate a temporary access token in the NPM website.
@@ -45,21 +36,28 @@ expected, run the following command:
```shell
git checkout main
pnpm run release
pnpm run release -- --version patch
```
The `--version` option accepts:
- `patch` - Increments the patch version (1.0.0 → 1.0.1)
- `minor` - Increments the minor version (1.0.0 → 1.1.0)
- `major` - Increments the major version (1.0.0 → 2.0.0)
- An exact version like `1.5.0`
### Generating a Real Release
To create an actual release, disable the dry-run option:
```shell
pnpm run release -- --dry-run false
pnpm run release -- --version patch --dry-run false
```
This command will:
- Update the library's `package.json` version
- Generate a commit
- Build all packages
- Publish to NPM with the `latest` tag
Ensure everything is correct before proceeding with the git push. Once
@@ -70,20 +68,17 @@ git commit -m ":arrow_up: Updated plugins release to X.X.X"
git push
```
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
pnpm run release -- --dry-run false --latest false --preid next
pnpm run release -- --version prepatch --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.
For example, if the current version is `0.8.0` and you use `prepatch`,
it will generate the version `0.8.1-next.0` and publish it with the
`next` tag on npm.
### Help
@@ -104,4 +99,3 @@ pnpm run release -- --help
- **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`

View File

@@ -1,49 +0,0 @@
import { FlatCompat } from '@eslint/eslintrc';
import nxEslintPlugin from '@nx/eslint-plugin';
import js from '@eslint/js';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
export default [
js.configs.recommended,
{ plugins: { '@nx': nxEslintPlugin } },
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: [],
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
},
],
},
],
},
},
...compat.config({ extends: ['plugin:@nx/typescript'] }).map((config) => ({
...config,
files: ['**/*.ts', '**/*.tsx'],
rules: {},
})),
...compat.config({ extends: ['plugin:@nx/javascript'] }).map((config) => ({
...config,
files: ['**/*.js', '**/*.jsx'],
rules: {},
})),
{
ignores: ['eslint.config.js', 'vite.config.{js,ts,mjs,mts}'],
},
];

View File

@@ -1,122 +1,66 @@
import baseConfig, { compat } from './eslint.base.config.js';
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import globals from 'globals';
import eslintConfigPrettier from 'eslint-config-prettier';
export default [
...baseConfig,
js.configs.recommended,
...tseslint.configs.recommended.map((config) => ({
...config,
files: config.files || ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
})),
eslintConfigPrettier,
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: [],
depConstraints: [
{
sourceTag: 'type:plugin',
onlyDependOnLibsWithTags: [
'type:util',
'type:ui',
'type:feature',
],
},
{
sourceTag: 'type:app',
onlyDependOnLibsWithTags: [
'type:util',
'type:ui',
'type:feature',
],
},
{
sourceTag: 'type:feature',
onlyDependOnLibsWithTags: [
'type:feature',
'type:ui',
'type:util',
],
},
{
sourceTag: 'type:ui',
onlyDependOnLibsWithTags: ['type:ui', 'type:util'],
},
{
sourceTag: 'type:util',
onlyDependOnLibsWithTags: ['type:util'],
},
{
sourceTag: 'type:e2e',
onlyDependOnLibsWithTags: ['type:ui', 'type:util'],
},
],
},
],
},
languageOptions: {
globals: {
...globals.browser,
...globals.node,
penpot: 'readonly',
repairIntrinsics: 'readonly',
hardenIntrinsics: 'readonly',
Compartment: 'readonly',
harden: 'readonly',
},
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
'no-multiple-empty-lines': ['error', { max: 1 }],
quotes: ['error', 'single', { avoidEscape: true }],
},
},
...compat
.config({
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:deprecation/recommended',
'prettier',
],
})
.map((config) => ({
...config,
files: ['**/*.ts', '**/*.tsx'],
rules: {
'@typescript-eslint/no-unused-vars': ['error'],
'no-multiple-empty-lines': [2, { max: 1 }],
quotes: ['error', 'single', { avoidEscape: true }],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
{
files: ['**/*.spec.ts', '**/*.test.ts'],
languageOptions: {
globals: {
...globals.jest,
},
})),
...compat
.config({
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:deprecation/recommended',
'prettier',
],
})
.map((config) => ({
...config,
files: ['**/*.spec.ts'],
rules: {
'@typescript-eslint/no-unused-vars': ['error'],
'no-multiple-empty-lines': [2, { max: 1 }],
quotes: ['error', 'single', { avoidEscape: true }],
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@ngrx/prefix-selectors-with-select': 'off',
},
languageOptions: {
globals: {
...globals.jest,
},
},
})),
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
{
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
{
ignores: ['**/vite.config.*.timestamp*', '**/vitest.config.*.timestamp*'],
ignores: [
'node_modules',
'dist',
'**/dist/**',
'**/.vite/**',
'eslint.config.js',
'vite.config.{js,ts,mjs,mts}',
'**/vite.config.*.timestamp*',
'**/vitest.config.*.timestamp*',
],
},
];

View File

@@ -2,5 +2,9 @@
"name": "@penpot/plugin-types",
"version": "1.4.2",
"typings": "./index.d.ts",
"type": "module"
"type": "module",
"scripts": {
"build": "node ../../tools/scripts/build-types.mjs",
"lint": "tsc -p . --noEmit"
}
}

View File

@@ -3,16 +3,5 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/plugin-types",
"projectType": "library",
"targets": {
"lint": {
"command": "tsc -p {projectRoot} --noEmit"
},
"build": {
"command": "node tools/scripts/build-types.mjs",
"options": {
"outputPath": "dist/plugin-types"
}
}
},
"tags": ["type:ui"]
"targets": {}
}

View File

@@ -31,17 +31,6 @@ export default [
languageOptions: {
parser: jsoncParser,
},
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: [
'libs/plugins-runtime/vite.config.ts',
'libs/plugins-runtime/eslint.config.js',
'libs/plugins-runtime/**/*.spec.ts',
],
},
],
},
rules: {},
},
];

View File

@@ -8,5 +8,12 @@
},
"module": "./index.mjs",
"typings": "./index.d.ts",
"type": "module"
"type": "module",
"scripts": {
"build": "vite build",
"build:watch": "vite build --watch --mode development",
"preview": "vite preview",
"lint": "eslint .",
"test": "vitest"
}
}

View File

@@ -1,14 +1,7 @@
{
"name": "plugins-runtime",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "plugins-runtime/src",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/plugins-runtime/src",
"projectType": "library",
"targets": {
"preview": {
"command": "vite preview",
"options": { "cwd": "libs/plugins-runtime" },
"_": "Delete this targets:preview when https://github.com/nrwl/nx/issues/26800 is fixed"
}
},
"tags": ["type:feature"]
"targets": {}
}

View File

@@ -21,6 +21,7 @@ repairIntrinsics({
unhandledRejectionTrapping: 'none',
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const globalThisAny$ = globalThis as any;
export const initPluginsRuntime = (contextBuilder: (id: string) => Context) => {

View File

@@ -85,6 +85,7 @@ export function createApi(
utils: {
geometry: {
center(shapes: Shape[]) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (window as any).app.plugins.public_utils.centerShapes(shapes);
},
},

View File

@@ -53,11 +53,11 @@ export function resizeModal(
const minPluginWidth = 200;
const minPluginHeight = 200;
let wrapper = modal.shadowRoot?.querySelector('.wrapper');
const wrapper = modal.shadowRoot?.querySelector('.wrapper');
let curX = 0;
let curY = 0;
if (wrapper) {
let rect = wrapper.getBoundingClientRect();
const rect = wrapper.getBoundingClientRect();
curX = rect.x;
curY = rect.y;
}

View File

@@ -117,7 +117,7 @@ export function createSandbox(
// Window properties
console: ses.harden(window.console),
devicePixelRatio: ses.harden(window.devicePixelRatio),
devicePixelRatio: window.devicePixelRatio,
atob: ses.harden(window.atob.bind(null)),
btoa: ses.harden(window.btoa.bind(null)),
structuredClone: ses.harden(window.structuredClone),

View File

@@ -53,7 +53,10 @@ export const loadPlugin = async function (
manifest,
() => {
plugins = plugins.filter((api) => api !== plugin);
closeCallback && closeCallback();
if (closeCallback) {
closeCallback();
}
},
);

View File

@@ -7,10 +7,10 @@ export const ses = {
hardenIntrinsics();
}
},
createCompartment: (globals?: Object) => {
createCompartment: (globals?: object) => {
return new Compartment(globals);
},
harden: (obj: Object) => {
harden: (obj: object) => {
return harden(obj);
},
safeReturn<T>(value: T): T {

View File

@@ -4,7 +4,7 @@ import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import * as path from 'path';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import tsconfigPaths from 'vite-tsconfig-paths';
import checker from 'vite-plugin-checker';
export default defineConfig({
@@ -12,7 +12,7 @@ export default defineConfig({
cacheDir: '../node_modules/.vite/plugins-runtime',
plugins: [
nxViteTsPaths(),
tsconfigPaths(),
dts({
entryRoot: 'src',
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
@@ -32,11 +32,6 @@ export default defineConfig({
}),
],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
@@ -67,9 +62,6 @@ export default defineConfig({
test: {
watch: false,
globals: true,
cache: {
dir: '../node_modules/.vitest',
},
environment: 'happy-dom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],

View File

@@ -1,5 +1,9 @@
{
"name": "@penpot/plugin-styles",
"version": "1.4.2",
"dependencies": {}
"dependencies": {},
"scripts": {
"build": "node ../../tools/scripts/build-css.mjs",
"lint": "echo 0"
}
}

View File

@@ -1,18 +1,7 @@
{
"name": "plugins-styles",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "plugins-styles/src",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/plugins-styles/src",
"projectType": "library",
"targets": {
"build": {
"command": "node tools/scripts/build-css.mjs",
"options": {
"outputPath": "dist/plugins-styles"
}
},
"lint": {
"command": "echo 0"
}
},
"tags": ["type:ui"]
"targets": {}
}

View File

@@ -1,145 +0,0 @@
{
"pluginsConfig": {
"@nx/js": {
"analyzeSourceFiles": true
}
},
"cli": {
"packageManager": "pnpm"
},
"release": {
"projects": [
"libs/plugins-styles",
"libs/plugin-types",
"libs/plugins-runtime"
]
},
"extends": "nx/presets/npm.json",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"targetDefaults": {
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectName}"
}
},
"@nx/vite:build": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["default", "^default"]
},
"@nx/esbuild:esbuild": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["default", "^default"]
},
"@nx/js:tsc": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["default", "^default"]
},
"@angular-devkit/build-angular:application": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["default", "^default"]
}
},
"plugins": [
{
"plugin": "./tools/plugins/plugin-tasks.ts"
},
{
"plugin": "@nx/vite/plugin",
"options": {
"buildTargetName": "build",
"previewTargetName": "preview",
"serveTargetName": "serve",
"serveStaticTargetName": "serve-static"
}
},
{
"plugin": "@nx/eslint/plugin",
"options": {
"targetName": "lint"
}
},
{
"plugin": "@nx/vitest",
"options": {
"testTargetName": "test"
}
}
],
"generators": {
"@nx/web:application": {
"style": "css",
"linter": "eslint",
"unitTestRunner": "vitest",
"e2eTestRunner": "none",
"projectNameAndRootFormat": "as-provided",
"bundler": "vite"
},
"@nx/angular:application": {
"e2eTestRunner": "none",
"linter": "eslint",
"style": "css",
"unitTestRunner": "none",
"projectNameAndRootFormat": "as-provided"
},
"@nx/angular:component": {
"type": "component"
},
"@schematics/angular:component": {
"type": "component"
},
"@nx/angular:directive": {
"type": "directive"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@nx/angular:service": {
"type": "service"
},
"@schematics/angular:service": {
"type": "service"
},
"@nx/angular:scam": {
"type": "component"
},
"@nx/angular:scam-directive": {
"type": "directive"
},
"@nx/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@nx/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@nx/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@nx/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@nx/angular:resolver": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
},
"useLegacyCache": false,
"nxCloudId": "69720151957fca05c743ec9a"
}

View File

@@ -6,28 +6,26 @@
"packageManager": "pnpm@10.26.2+sha512.0e308ff2005fc7410366f154f625f6631ab2b16b1d2e70238444dd6ae9d630a8482d92a451144debc492416896ed16f7b114a86ec68b8404b2443869e68ffda6",
"scripts": {
"start": "pnpm run start:app:runtime",
"start:app:runtime": "concurrently --kill-others --names build,server \"nx run plugins-runtime:build --watch --mode development\" \"nx run plugins-runtime:preview\"",
"start:app:styles-example": "nx run example-styles:serve --host 0.0.0.0 --port 4201",
"start:app:runtime": "concurrently --kill-others --names build,server \"pnpm --filter @penpot/plugins-runtime run build:watch\" \"pnpm --filter @penpot/plugins-runtime run preview\"",
"start:app:styles-example": "pnpm --filter example-styles dev",
"start:plugin:all": "concurrently --kill-others \"pnpm:start:plugin:*(!all)\"",
"start:plugin:poc-state": "nx run poc-state-plugin:init",
"start:plugin:contrast": "nx run contrast-plugin:init",
"start:plugin:icons": "nx run icons-plugin:init",
"start:plugin:loremipsum": "nx run lorem-ipsum-plugin:init",
"start:plugin:palette": "nx run create-palette-plugin:build --watch & nx run create-palette-plugin:preview",
"start:plugin:table": "nx run table-plugin:init",
"start:plugin:renamelayers": "nx run rename-layers-plugin:init",
"start:plugin:colors-to-tokens": "nx run colors-to-tokens-plugin:init",
"start:plugin:poc-tokens": "nx run poc-tokens-plugin:init",
"build": "nx build plugins-runtime --emptyOutDir=true",
"build:plugins": "nx run-many -t build --parallel -p tag:type:plugin --exclude=poc-state-plugin",
"build:styles-example": "nx run example-styles:build",
"lint": "nx run-many --all --target=lint --parallel",
"format": "nx format:write --libs-and-apps",
"format:check": "nx format:check --libs-and-apps",
"lint:affected": "nx affected --target=lint",
"test": "nx run-many -t test --parallel -p plugins-runtime lorem-ipsum-plugin colors-to-tokens-plugin",
"test:e2e": "nx test e2e",
"registry": "nx local-registry",
"start:plugin:poc-state": "pnpm --filter poc-state-plugin serve",
"start:plugin:contrast": "pnpm --filter contrast-plugin serve",
"start:plugin:icons": "pnpm --filter icons-plugin serve",
"start:plugin:loremipsum": "pnpm --filter lorem-ipsum-plugin serve",
"start:plugin:palette": "pnpm --filter create-palette-plugin build:watch & pnpm --filter create-palette-plugin preview",
"start:plugin:table": "pnpm --filter table-plugin serve",
"start:plugin:renamelayers": "pnpm --filter rename-layers-plugin serve",
"start:plugin:colors-to-tokens": "pnpm --filter colors-to-tokens-plugin serve",
"start:plugin:poc-tokens": "pnpm --filter poc-tokens serve",
"build": "pnpm --filter @penpot/plugins-runtime build",
"build:plugins": "pnpm --filter './apps/*-plugin' --filter '!poc-state-plugin' build",
"build:styles-example": "pnpm --filter example-styles build",
"lint": "pnpm -r --parallel lint",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,html,css}\"",
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,html,css}\"",
"test": "pnpm --filter @penpot/plugins-runtime --filter lorem-ipsum-plugin --filter colors-to-tokens-plugin test",
"test:e2e": "pnpm --filter e2e test",
"build:doc": "typedoc --tsconfig libs/plugins-runtime/tsconfig.lib.json --customCss ./tools/typedoc.css --out dist/doc",
"release": "tsx ./tools/scripts/publish.ts"
},
@@ -42,24 +40,11 @@
"@angular/cli": "21.1.1",
"@angular/compiler-cli": "21.1.1",
"@angular/language-service": "21.1.1",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "9.39.2",
"@nx/angular": "22.4.0",
"@nx/devkit": "^22.4.0",
"@nx/esbuild": "22.4.0",
"@nx/eslint": "22.4.0",
"@nx/eslint-plugin": "22.4.0",
"@nx/js": "22.4.0",
"@nx/node": "22.4.0",
"@nx/vite": "22.4.0",
"@nx/vitest": "22.4.0",
"@nx/web": "22.4.0",
"@schematics/angular": "21.1.1",
"@swc-node/register": "1.11.1",
"@swc/core": "1.15.10",
"@swc/helpers": "0.5.18",
"@types/feather-icons": "^4.29.4",
"@types/node": "25.0.10",
"@types/yargs": "^17.0.35",
"@typescript-eslint/eslint-plugin": "8.53.1",
"@typescript-eslint/parser": "8.53.1",
"@typescript-eslint/utils": "^8.53.1",
@@ -81,9 +66,7 @@
"jiti": "2.6.1",
"jsdom": "~27.4.0",
"jsonc-eslint-parser": "^2.4.2",
"nx": "22.4.0",
"prettier": "^3.8.1",
"swc-loader": "0.2.7",
"tsx": "^4.21.0",
"typedoc": "^0.28.16",
"typescript": "5.9.3",
@@ -92,7 +75,9 @@
"vite-plugin-checker": "^0.12.0",
"vite-plugin-dts": "4.5.4",
"vite-plugin-static-copy": "^3.1.5",
"vitest": "4.0.17"
"vite-tsconfig-paths": "^6.0.5",
"vitest": "4.0.17",
"yargs": "^17.7.2"
},
"dependencies": {
"@angular/animations": "21.1.1",
@@ -112,8 +97,5 @@
"uuid": "^13.0.0",
"zod": "^4.3.5",
"zone.js": "0.16.0"
},
"nx": {
"includedScripts": []
}
}

6591
plugins/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
{
"name": "penpot-plugins",
"$schema": "node_modules/nx/schemas/project-schema.json",
"targets": {}
}

View File

@@ -1,56 +0,0 @@
import { CreateNodesV2, readJsonFile, logger } from '@nx/devkit';
import { createNodesFromFiles } from '@nx/devkit';
import { dirname } from 'path';
export const createNodesV2: CreateNodesV2 = [
'**/project.json',
async (configFiles, options, context) => {
return await createNodesFromFiles(
(configFile) => {
const projectConfiguration = readJsonFile(configFile);
if (
!projectConfiguration.tags ||
!projectConfiguration?.tags.includes('type:plugin') ||
!projectConfiguration?.targets.build
) {
return {};
}
const projectRoot = dirname(configFile);
return {
projects: {
[projectRoot]: {
root: projectRoot,
targets: {
init: {
executor: 'nx:run-commands',
options: {
command: `nx run-many --parallel --targets=buildPlugin,serve --projects=${projectConfiguration.name} --watch`,
},
},
buildPlugin: {
executor: '@nx/esbuild:esbuild',
outputs: ['{options.outputPath}'],
options: {
minify: true,
outputPath: `${projectConfiguration.sourceRoot}/assets/`,
main: `${projectConfiguration.sourceRoot}/plugin.ts`,
tsConfig: `${projectRoot}/tsconfig.plugin.json`,
generatePackageJson: false,
format: ['esm'],
deleteOutputPath: false,
},
},
},
},
},
};
},
configFiles,
options,
context,
);
},
];

View File

@@ -1,8 +1,15 @@
import { execSync } from 'child_process';
import { releaseChangelog, releasePublish, releaseVersion } from 'nx/release';
import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
const PACKAGES = [
'libs/plugin-types',
'libs/plugins-styles',
'libs/plugins-runtime',
];
const determineArgs = async () => {
return await yargs(hideBin(process.argv))
.version(false)
@@ -21,9 +28,9 @@ const determineArgs = async () => {
})
.option('version', {
description:
'Explicit version specifier to use, if overriding conventional commits',
'Explicit version specifier to use (e.g., 1.5.0, patch, minor, major)',
type: 'string',
default: undefined,
demandOption: true,
})
.option('skip-publish', {
description: 'Skip publishing the package to the registry',
@@ -31,7 +38,7 @@ const determineArgs = async () => {
default: false,
})
.option('preid', {
description: 'The prerelease identifier to use',
description: 'The prerelease identifier to use (e.g., next, beta, alpha)',
type: 'string',
default: undefined,
})
@@ -40,41 +47,170 @@ const determineArgs = async () => {
type: 'boolean',
default: true,
})
.option('first-release', {
description: 'Whether or not this is the first release',
type: 'boolean',
default: false,
})
.parseAsync();
};
interface PackageJson {
name: string;
version: string;
[key: string]: unknown;
}
const readPackageJson = (packagePath: string): PackageJson => {
const filePath = join(process.cwd(), packagePath, 'package.json');
return JSON.parse(readFileSync(filePath, 'utf-8'));
};
const writePackageJson = (packagePath: string, content: PackageJson): void => {
const filePath = join(process.cwd(), packagePath, 'package.json');
writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n');
};
const incrementVersion = (
currentVersion: string,
specifier: string,
preid?: string,
): string => {
const [major, minor, patch] = currentVersion
.split('-')[0]
.split('.')
.map(Number);
switch (specifier) {
case 'major':
return preid ? `${major + 1}.0.0-${preid}.0` : `${major + 1}.0.0`;
case 'minor':
return preid
? `${major}.${minor + 1}.0-${preid}.0`
: `${major}.${minor + 1}.0`;
case 'patch':
return preid
? `${major}.${minor}.${patch + 1}-${preid}.0`
: `${major}.${minor}.${patch + 1}`;
case 'premajor':
return `${major + 1}.0.0-${preid || 'next'}.0`;
case 'preminor':
return `${major}.${minor + 1}.0-${preid || 'next'}.0`;
case 'prepatch':
return `${major}.${minor}.${patch + 1}-${preid || 'next'}.0`;
case 'prerelease': {
const preMatch = currentVersion.match(/-([^.]+)\.(\d+)$/);
if (preMatch) {
const preId = preid || preMatch[1];
const preNum = parseInt(preMatch[2], 10) + 1;
return `${major}.${minor}.${patch}-${preId}.${preNum}`;
}
return `${major}.${minor}.${patch + 1}-${preid || 'next'}.0`;
}
default:
// If specifier is an exact version (e.g., "1.5.0"), use it directly
if (/^\d+\.\d+\.\d+/.test(specifier)) {
return specifier;
}
throw new Error(`Unknown version specifier: ${specifier}`);
}
};
const log = (message: string, verbose: boolean, forceLog = false): void => {
if (verbose || forceLog) {
console.log(message);
}
};
(async () => {
const args = await determineArgs();
const result = await releaseVersion({
dryRun: args.dryRun,
specifier: args.version,
gitCommit: false,
gitTag: false,
stageChanges: true,
verbose: args.verbose,
preid: args.preid,
});
// Get current version from one of the packages
const currentPkg = readPackageJson(PACKAGES[0]);
const currentVersion = currentPkg.version;
execSync(
'npx nx run-many -t build -p plugins-runtime plugins-styles plugin-types --parallel',
{
cwd: process.cwd(),
stdio: 'inherit',
},
);
const newVersion = incrementVersion(currentVersion, args.version, args.preid);
console.log(`\n📦 Release: ${currentVersion}${newVersion}`);
console.log(` Mode: ${args.dryRun ? 'DRY RUN' : 'REAL RELEASE'}`);
console.log(` Tag: ${args.latest ? 'latest' : 'next'}\n`);
// Update version in all packages
for (const packagePath of PACKAGES) {
const pkg = readPackageJson(packagePath);
const oldVersion = pkg.version;
pkg.version = newVersion;
// Update internal dependencies
const deps = pkg['dependencies'] as Record<string, string> | undefined;
if (deps && typeof deps === 'object') {
for (const dep of Object.keys(deps)) {
if (dep.startsWith('@penpot/')) {
deps[dep] = `^${newVersion}`;
}
}
}
log(` ${pkg.name}: ${oldVersion}${newVersion}`, args.verbose, true);
if (!args.dryRun) {
writePackageJson(packagePath, pkg);
}
}
console.log('\n🔨 Building packages...\n');
// Build all packages
if (!args.dryRun) {
execSync(
'pnpm --filter @penpot/plugins-runtime --filter @penpot/plugin-styles --filter @penpot/plugin-types build',
{
cwd: process.cwd(),
stdio: 'inherit',
},
);
} else {
console.log(' [DRY RUN] Skipping build\n');
}
// Publish packages
if (!args.skipPublish) {
await releasePublish({
dryRun: args.dryRun,
verbose: args.verbose,
tag: args.latest ? 'latest' : 'next',
});
console.log('\n📤 Publishing packages...\n');
const tag = args.latest ? 'latest' : 'next';
for (const packagePath of PACKAGES) {
const pkg = readPackageJson(packagePath);
const distPath = join('dist', packagePath.split('/').pop()!);
if (args.dryRun) {
console.log(
` [DRY RUN] Would publish ${pkg.name}@${newVersion} with tag "${tag}"`,
);
} else {
try {
execSync(
`pnpm publish --tag ${tag} --access public --no-git-checks`,
{
cwd: join(process.cwd(), distPath),
stdio: args.verbose ? 'inherit' : 'pipe',
},
);
console.log(` ✅ Published ${pkg.name}@${newVersion}`);
} catch (error) {
console.error(` ❌ Failed to publish ${pkg.name}`);
throw error;
}
}
}
} else {
console.log('\n⏭ Skipping publish (--skip-publish)\n');
}
console.log('\n✨ Release complete!\n');
if (!args.dryRun) {
console.log('Next steps:');
console.log(` 1. Review the changes`);
console.log(
` 2. Commit: git commit -am ":arrow_up: Updated plugins release to ${newVersion}"`,
);
console.log(` 3. Push: git push\n`);
}
process.exit(0);