mirror of
https://github.com/penpot/penpot-plugins.git
synced 2025-01-02 04:40:11 -05:00
fix: i#7593 eslint flat config
This commit is contained in:
parent
b6bf1baaa5
commit
df7f3a21d8
84 changed files with 416 additions and 2292 deletions
|
@ -1 +0,0 @@
|
|||
node_modules
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"root": true,
|
||||
"ignorePatterns": ["**/*"],
|
||||
"plugins": ["@nx"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {
|
||||
"@nx/enforce-module-boundaries": [
|
||||
"error",
|
||||
{
|
||||
"enforceBuildableLibDependency": true,
|
||||
"allow": [],
|
||||
"depConstraints": [
|
||||
{
|
||||
"sourceTag": "*",
|
||||
"onlyDependOnLibsWithTags": ["*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"extends": ["plugin:@nx/typescript"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"extends": ["plugin:@nx/javascript"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
113
.eslintrc.json
113
.eslintrc.json
|
@ -1,113 +0,0 @@
|
|||
{
|
||||
"ignorePatterns": ["**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:deprecation/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unused-vars": ["error"],
|
||||
"no-multiple-empty-lines": [
|
||||
2,
|
||||
{
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.spec.ts"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:deprecation/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
],
|
||||
"extends": ["./.eslintrc.base.json"]
|
||||
}
|
|
@ -8,15 +8,13 @@ There are 2 important folders to keep an eye on: `apps` and `libs`.
|
|||
|
||||
In the `libs` folder you'll find:
|
||||
|
||||
- plugins-data-parser: useful functions to parse the data we get from penpot.
|
||||
It has its own [README](libs/plugins-data-parser/README.md).
|
||||
- plugins-runtime: here you'll find the code that initializes the plugin and sets a few listeners to know when the penpot page/file/selection changes.
|
||||
It has its own [README](libs/plugins-runtime/README.md).
|
||||
- plugins-styles: basic css library with penpot styles in case you need help for styling your plugins.
|
||||
|
||||
In the `apps` folder you'll find some examples that use the libraries mentioned above.
|
||||
|
||||
- example-plugin or contrast-plugin: to run this example check <a href="#create-a-plugin-from-scratch-or-run-the-examples-from-the-apps-folder">Create a plugin from scratch</a>
|
||||
- contrast-plugin: to run this example check <a href="#create-a-plugin-from-scratch-or-run-the-examples-from-the-apps-folder">Create a plugin from scratch</a>
|
||||
|
||||
- example-styles: to run this example you should run
|
||||
|
||||
|
@ -50,14 +48,14 @@ npm run start:example
|
|||
|
||||
or
|
||||
|
||||
npx nx run example-plugin:build --watch & npx nx run example-plugin:preview
|
||||
npm run start:pc-plugin
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
// for the contrast plugin
|
||||
npx nx run contrast-plugin:build --watch & npx nx run contrast-plugin:preview
|
||||
npm run start:contrast-plugin
|
||||
```
|
||||
|
||||
Open in your browser: `http://localhost:4210/`
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "vite.config.ts"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./apps/contrast-plugin/tsconfig.app.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
25
apps/contrast-plugin/eslint.config.js
Normal file
25
apps/contrast-plugin/eslint.config.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import baseConfig from '../../eslint.config.js';
|
||||
import typescriptEslintParser from '@typescript-eslint/parser';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: typescriptEslintParser,
|
||||
parserOptions: { project: './apps/contrast-plugin/tsconfig.app.json' },
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{ ignores: ['vite.config.ts'] },
|
||||
];
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"presets": ["@nx/js/babel"]
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "vite.config.ts"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./apps/example-plugin/tsconfig.app.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
},
|
||||
"target": "es2016"
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>ExamplePlugin</title>
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/src/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "example-plugin",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"sourceRoot": "apps/example-plugin/src",
|
||||
"tags": ["type:plugin"],
|
||||
"targets": {}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"name": "Example plugin",
|
||||
"code": "http://localhost:4201/plugin.js",
|
||||
"permissions": [
|
||||
"page:read",
|
||||
"file:read",
|
||||
"selection:read"
|
||||
]
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
html {
|
||||
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;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-block-end: var(--spacing-12);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
margin-block-end: var(--spacing-12);
|
||||
}
|
||||
|
||||
.help {
|
||||
color: #6b7280;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
padding-inline-start: var(--spacing-12);
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/* eslint-disable */
|
||||
import 'plugins-styles/lib/styles.css';
|
||||
import './app.element.css';
|
||||
|
||||
export class AppElement extends HTMLElement {
|
||||
public static observedAttributes = [];
|
||||
#selection = '';
|
||||
#pageId = '';
|
||||
#fileId = '';
|
||||
#revn = 0;
|
||||
|
||||
refreshPage(pageId: string, name: string) {
|
||||
console.log('refreshPage', pageId, name);
|
||||
|
||||
const projectName = document.getElementById('project-name');
|
||||
this.#pageId = pageId;
|
||||
|
||||
if (projectName) {
|
||||
projectName.innerText = name;
|
||||
}
|
||||
}
|
||||
|
||||
refreshSelectionId(selection: string[]) {
|
||||
this.#selection = selection;
|
||||
|
||||
const selectionId = document.getElementById('selection-id');
|
||||
|
||||
if (selectionId) {
|
||||
selectionId.innerText = this.#selection[0];
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data.type === 'pingpong') {
|
||||
console.log('iframe', event.data.content);
|
||||
} else if (event.data.type === 'file') {
|
||||
this.#fileId = event.data.content.id;
|
||||
this.#revn = event.data.content.revn;
|
||||
} else if (event.data.type === 'page') {
|
||||
this.refreshPage(event.data.content.id, event.data.content.name);
|
||||
} else if (event.data.type === 'selection') {
|
||||
this.refreshSelectionId(event.data.content);
|
||||
} else if (event.data.type === 'init') {
|
||||
this.#fileId = event.data.content.fileId;
|
||||
this.#revn = event.data.content.revn;
|
||||
this.refreshPage(event.data.content.pageId, event.data.content.name);
|
||||
this.refreshSelectionId(event.data.content.selection);
|
||||
this.setAttribute('data-theme', event.data.content.theme);
|
||||
} else if (event.data.type === 'theme') {
|
||||
this.setAttribute('data-theme', event.data.content);
|
||||
}
|
||||
});
|
||||
|
||||
this.innerHTML = `
|
||||
<div class="wrapper">
|
||||
<h1>Test area</h1>
|
||||
|
||||
<p>Current project name: <span id="project-name">Unknown</span></p>
|
||||
<p>Selection id: <span id="selection-id">Unknown</span></p>
|
||||
<div class="profile"></div>
|
||||
|
||||
<p>
|
||||
<button type="button" data-appearance="primary" class="act-ping-pong">Ping Pong message</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button type="button" data-appearance="primary" class="get-profile">API get profile</button>
|
||||
<span class="help">Need the .env file and run "start:rpc-api"</span>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button type="button" data-appearance="primary" class="remove-obj">Remove obj</button>
|
||||
<span class="help">Need the .env file and run "start:rpc-api"</span>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button type="button" data-appearance="primary" data-variant="destructive" class="act-close-plugin">Close plugin</button>
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const pingPongAction = this.querySelector<HTMLElement>('.act-ping-pong');
|
||||
|
||||
pingPongAction?.addEventListener('click', () => {
|
||||
parent.postMessage({ content: 'ping' }, '*');
|
||||
});
|
||||
|
||||
const closeAction = this.querySelector<HTMLElement>('.act-close-plugin');
|
||||
|
||||
closeAction?.addEventListener('click', () => {
|
||||
parent.postMessage({ content: 'close' }, '*');
|
||||
});
|
||||
|
||||
const getProfileAction = this.querySelector<HTMLElement>('.get-profile');
|
||||
|
||||
getProfileAction?.addEventListener('click', () => {
|
||||
fetch('http://localhost:3000/get-profile')
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => {
|
||||
const profile = document.querySelector('.profile');
|
||||
|
||||
if (profile) {
|
||||
profile.innerHTML = '<p>' + JSON.stringify(data) + '</p>';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const removeAction = this.querySelector<HTMLElement>('.remove-obj');
|
||||
|
||||
removeAction?.addEventListener('click', () => {
|
||||
fetch('http://localhost:3000/delete-object', {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({
|
||||
fileId: this.#fileId,
|
||||
revn: this.#revn,
|
||||
pageId: this.#pageId,
|
||||
objectId: this.#selection,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
|
||||
parent.postMessage({ content: 'ready' }, '*');
|
||||
}
|
||||
}
|
||||
customElements.define('app-root', AppElement);
|
|
@ -1 +0,0 @@
|
|||
import './app/app.element';
|
|
@ -1,67 +0,0 @@
|
|||
penpot.log('Hello from plugin');
|
||||
|
||||
penpot.ui.open('Plugin name', 'http://localhost:4201', {
|
||||
width: 500,
|
||||
height: 600,
|
||||
});
|
||||
|
||||
penpot.ui.onMessage<{ content: string }>((message) => {
|
||||
if (message.content === 'ping') {
|
||||
penpot.log('ping received');
|
||||
penpot.ui.sendMessage({ type: 'pingpong', content: 'pong' });
|
||||
} else if (message.content === 'close') {
|
||||
penpot.closePlugin();
|
||||
} else if (message.content === 'ready') {
|
||||
const pageState = penpot.getPage();
|
||||
const fileState = penpot.getFile();
|
||||
|
||||
if (!pageState || !fileState) {
|
||||
return;
|
||||
}
|
||||
|
||||
penpot.ui.sendMessage({
|
||||
type: 'init',
|
||||
content: {
|
||||
name: pageState.name,
|
||||
pageId: pageState.id,
|
||||
fileId: fileState.id,
|
||||
revn: fileState.revn,
|
||||
theme: penpot.getTheme(),
|
||||
selection: penpot.getSelected(),
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
penpot.on('pagechange', () => {
|
||||
const page = penpot.getPage();
|
||||
penpot.ui.sendMessage({
|
||||
type: 'page',
|
||||
content: {
|
||||
name: page.name,
|
||||
id: page.id,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
penpot.on('filechange', () => {
|
||||
const file = penpot.getFile();
|
||||
penpot.ui.sendMessage({
|
||||
type: 'file',
|
||||
content: {
|
||||
name: file.name,
|
||||
id: file.id,
|
||||
revn: file.revn,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
penpot.on('selectionchange', () => {
|
||||
const selected = penpot.getSelected();
|
||||
penpot.ui.sendMessage({ type: 'selection', content: selected });
|
||||
});
|
||||
|
||||
penpot.on('themechange', () => {
|
||||
const theme = penpot.getTheme();
|
||||
penpot.ui.sendMessage({ type: 'theme', content: theme });
|
||||
});
|
|
@ -1 +0,0 @@
|
|||
/* You can add global styles to this file, and also import other style files */
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
|
||||
"include": ["src/**/*.ts", "../../libs/plugin-types/index.d.ts"]
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"noEmit": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["vite/client"]
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": [
|
||||
"vitest/globals",
|
||||
"vitest/importMeta",
|
||||
"vite/client",
|
||||
"node",
|
||||
"vitest"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/example-plugin',
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4201,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
plugins: [nxViteTsPaths()],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../../dist/apps/example-plugin',
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
rollupOptions: {
|
||||
input: {
|
||||
plugin: 'src/plugin.ts',
|
||||
index: './index.html',
|
||||
},
|
||||
output: {
|
||||
entryFileNames: '[name].js',
|
||||
},
|
||||
},
|
||||
sourcemap: true,
|
||||
},
|
||||
|
||||
test: {
|
||||
globals: true,
|
||||
cache: {
|
||||
dir: '../../node_modules/.vitest',
|
||||
},
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/example-plugin',
|
||||
provider: 'v8',
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "vite.config.ts"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./apps/example-styles/tsconfig.app.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
31
apps/example-styles/eslint.config.js
Normal file
31
apps/example-styles/eslint.config.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import baseConfig from '../../eslint.config.js';
|
||||
import typescriptEslintParser from '@typescript-eslint/parser';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: typescriptEslintParser,
|
||||
parserOptions: { project: './apps/example-styles/tsconfig.app.json' },
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{ ignores: ['vite.config.ts'] },
|
||||
];
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json"],
|
||||
"ignorePatterns": ["!**/*", "**/assets/*.js"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "app",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "app",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"extends": ["plugin:@nx/angular-template"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
43
apps/poc-state-plugin/eslint.config.js
Normal file
43
apps/poc-state-plugin/eslint.config.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import baseConfig from '../../eslint.config.js';
|
||||
import { compat } from '../../eslint.base.config.js';
|
||||
|
||||
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'] },
|
||||
];
|
|
@ -4,7 +4,7 @@
|
|||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"sourceRoot": "apps/poc-state-plugin/src",
|
||||
"tags": [],
|
||||
"tags": ["type:plugin"],
|
||||
"targets": {
|
||||
"buildPlugin": {
|
||||
"executor": "@nx/esbuild:esbuild",
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { PenpotText } from '@penpot/plugin-types';
|
||||
|
||||
penpot.ui.open('Plugin name', 'http://localhost:4202', {
|
||||
width: 500,
|
||||
height: 600,
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./apps/rpc-api/tsconfig.app.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
{
|
||||
"name": "rpc-api",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/rpc-api/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/esbuild:esbuild",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"platform": "node",
|
||||
"outputPath": "dist/apps/rpc-api",
|
||||
"format": ["cjs"],
|
||||
"bundle": false,
|
||||
"main": "apps/rpc-api/src/main.ts",
|
||||
"tsConfig": "apps/rpc-api/tsconfig.app.json",
|
||||
"assets": ["apps/rpc-api/src/assets"],
|
||||
"generatePackageJson": true,
|
||||
"esbuildOptions": {
|
||||
"sourcemap": true,
|
||||
"outExtension": {
|
||||
".js": ".js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"development": {},
|
||||
"production": {
|
||||
"esbuildOptions": {
|
||||
"sourcemap": false,
|
||||
"outExtension": {
|
||||
".js": ".js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@nx/js:node",
|
||||
"defaultConfiguration": "development",
|
||||
"options": {
|
||||
"buildTarget": "rpc-api:build"
|
||||
},
|
||||
"configurations": {
|
||||
"development": {
|
||||
"buildTarget": "rpc-api:build:development"
|
||||
},
|
||||
"production": {
|
||||
"buildTarget": "rpc-api:build:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": ["type:app"]
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import * as path from 'path';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import AutoLoad from '@fastify/autoload';
|
||||
|
||||
/* eslint-disable-next-line */
|
||||
export interface AppOptions {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export async function app(fastify: FastifyInstance, opts: AppOptions) {
|
||||
// This loads all plugins defined in plugins
|
||||
// those should be support plugins that are reused
|
||||
// through your application
|
||||
void fastify.register(AutoLoad, {
|
||||
dir: path.join(__dirname, 'plugins'),
|
||||
options: { ...opts },
|
||||
});
|
||||
|
||||
// // This loads all plugins defined in routes
|
||||
// // define your routes in one of these
|
||||
void fastify.register(AutoLoad, {
|
||||
dir: path.join(__dirname, 'routes'),
|
||||
options: { ...opts },
|
||||
});
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
import fp from 'fastify-plugin';
|
||||
import cors from '@fastify/cors';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export default fp(async function (fastify: FastifyInstance) {
|
||||
void fastify.register(cors);
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
import fp from 'fastify-plugin';
|
||||
import sensible from '@fastify/sensible';
|
||||
|
||||
/**
|
||||
* This plugins adds some utilities to handle http errors
|
||||
*
|
||||
* @see https://github.com/fastify/fastify-sensible
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export default fp(async function (fastify: FastifyInstance) {
|
||||
void fastify.register(sensible);
|
||||
});
|
|
@ -1,110 +0,0 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
const token = process.env.ACCESS_TOKEN;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
async function routes(fastify: FastifyInstance) {
|
||||
const apiUrl = process.env.API_URL + '/api/rpc/command';
|
||||
const fakeSessionId = v4();
|
||||
|
||||
// not working
|
||||
// function uploadMediaObject(fileId: string) {
|
||||
// const filePath = '/home/juanfran/tmpImages/example-bg-2.jpg';
|
||||
// const file = fs.readFileSync(filePath);
|
||||
// const fileName = path.basename(filePath);
|
||||
|
||||
// const formData = new FormData();
|
||||
// formData.append('content', new Blob([file]), fileName);
|
||||
// formData.append('file-id', fileId);
|
||||
// formData.append('name', fileName);
|
||||
// formData.append('is-local', 'true');
|
||||
|
||||
// return fetch(`${apiUrl}/upload-file-media-object`, {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/transit+json',
|
||||
// Authorization: `Token ${token}`,
|
||||
// },
|
||||
// body: formData,
|
||||
// });
|
||||
// }
|
||||
|
||||
function deleteObj(
|
||||
fileId: string,
|
||||
revn: number,
|
||||
pageId: string,
|
||||
objectId: string
|
||||
) {
|
||||
const payload = {
|
||||
'~:id': `~u${fileId}`,
|
||||
'~:revn': revn,
|
||||
'~:session-id': `~u${fakeSessionId}`,
|
||||
'~:changes': [
|
||||
{
|
||||
'~:type': '~:del-obj',
|
||||
'~:page-id': `~u${pageId}`,
|
||||
'~:ignore-touched': false,
|
||||
'~:id': `~u${objectId}`,
|
||||
},
|
||||
],
|
||||
'~:features': {
|
||||
'~#set': [
|
||||
'layout/grid',
|
||||
'styles/v2',
|
||||
'fdata/pointer-map',
|
||||
'fdata/objects-map',
|
||||
'fdata/shape-data-type',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
return fetch(`${apiUrl}/update-file?id=${fileId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/transit+json',
|
||||
Authorization: `Token ${token}`,
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}).then((response) => response.json());
|
||||
}
|
||||
|
||||
fastify.get('/get-profile', function () {
|
||||
return fetch(`${apiUrl}/get-profile`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Token ${token}`,
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
|
||||
fastify.delete<{
|
||||
Body: {
|
||||
fileId: string;
|
||||
revn: number;
|
||||
pageId: string;
|
||||
objectId: string;
|
||||
};
|
||||
}>('/delete-object', function (request, reply) {
|
||||
deleteObj(
|
||||
request.body.fileId,
|
||||
request.body.revn,
|
||||
request.body.pageId,
|
||||
request.body.objectId
|
||||
)
|
||||
.then((data) => {
|
||||
console.log('Success:', data);
|
||||
|
||||
return reply.send(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default routes;
|
|
@ -1,23 +0,0 @@
|
|||
import Fastify from 'fastify';
|
||||
import { app } from './app/app';
|
||||
|
||||
const host = process.env.HOST ?? 'localhost';
|
||||
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
|
||||
|
||||
// Instantiate Fastify with some config
|
||||
const server = Fastify({
|
||||
logger: true,
|
||||
});
|
||||
|
||||
// Register your application as a normal plugin.
|
||||
void server.register(app);
|
||||
|
||||
// Start listening.
|
||||
server.listen({ port, host }, (err) => {
|
||||
if (err) {
|
||||
server.log.error(err);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`[ ready ] http://${host}:${port}`);
|
||||
}
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
|
@ -1 +1 @@
|
|||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
||||
export default { extends: ['@commitlint/config-conventional'] };
|
||||
|
|
49
eslint.base.config.js
Normal file
49
eslint.base.config.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
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}'],
|
||||
}
|
||||
];
|
115
eslint.config.js
Normal file
115
eslint.config.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
import baseConfig, { compat } from './eslint.base.config.js';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
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'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
languageOptions: {
|
||||
globals: {
|
||||
penpot: 'readonly',
|
||||
repairIntrinsics: 'readonly',
|
||||
hardenIntrinsics: 'readonly',
|
||||
Compartment: 'readonly',
|
||||
harden: 'readonly',
|
||||
}
|
||||
}
|
||||
},
|
||||
...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']
|
||||
},
|
||||
})),
|
||||
...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
|
||||
}
|
||||
},
|
||||
})),
|
||||
{
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
}
|
||||
];
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
42
libs/plugin-types/eslint.config.js
Normal file
42
libs/plugin-types/eslint.config.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
import baseConfig from '../../eslint.config.js';
|
||||
import jsoncParser from 'jsonc-eslint-parser';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
languageOptions: {
|
||||
globals: {
|
||||
fetch: 'readonly',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['*.json'],
|
||||
languageOptions: {
|
||||
parser: jsoncParser,
|
||||
},
|
||||
rules: {
|
||||
'@nx/dependency-checks': [
|
||||
'error',
|
||||
{
|
||||
ignoredFiles: [
|
||||
'libs/plugin-types/vite.config.ts',
|
||||
'libs/plugin-types/eslint.config.js',
|
||||
'libs/plugin-types/**/*.spec.ts',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
10
libs/plugin-types/index.d.ts
vendored
10
libs/plugin-types/index.d.ts
vendored
|
@ -75,11 +75,6 @@ export interface PenpotShapeBase {
|
|||
resize(width: number, height: number);
|
||||
}
|
||||
|
||||
export interface PenpotText extends PenpotShape {
|
||||
type: 'text';
|
||||
characters: string;
|
||||
}
|
||||
|
||||
export interface PenpotFrame extends PenpotShapeBase {
|
||||
readonly type: 'frame';
|
||||
readonly children: PenpotShape[];
|
||||
|
@ -108,6 +103,11 @@ export interface PenpotText extends PenpotShapeBase {
|
|||
characters: string;
|
||||
}
|
||||
|
||||
export interface PepotFrame extends PenpotShapeBase {
|
||||
readonly type: 'frame';
|
||||
readonly children: PenpotShape[];
|
||||
}
|
||||
|
||||
export interface PenpotCircle extends PenpotShapeBase {
|
||||
type: 'circle';
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"name": "@penpot/plugin-types",
|
||||
"version": "0.1.0",
|
||||
"typings": "./index.d.ts"
|
||||
"typings": "./index.d.ts",
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "vite.config.ts"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./libs/plugins-data-parser/tsconfig.lib.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": [
|
||||
"error",
|
||||
{
|
||||
"ignoredFiles": ["{projectRoot}/vite.config.{js,ts,mjs,mts}"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
# Parser
|
||||
|
||||
This library exports `cleanObject()` and `getSelectedUuids()` funtions and the model `Selection`.
|
||||
|
||||
The `cleanObject()` function cleans up objects from useless properties and transforms the remaining ones to camelCase. It returns `unknown`.
|
||||
|
||||
The `getSelectedUuids()` functions, given an `Selection` object, returns the selected Uuids as an array of string.
|
||||
|
||||
## Helpers
|
||||
|
||||
### File Helper
|
||||
|
||||
#### File Helper functions
|
||||
|
||||
- `setData()`
|
||||
|
||||
You can either pass the data in the constructor or use the `setData()` function.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const fileHelper = new FileHelper();
|
||||
fileHelper.setData(data);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```ts
|
||||
const fileHelper = new FileHelper(data);
|
||||
```
|
||||
|
||||
- `getCleanData()`
|
||||
|
||||
Gets the cleaned up data. It deletes useless properties and and transforms the remaining ones to camelCase.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const clean = fileHelper.getCleanData();
|
||||
```
|
||||
|
||||
### Page Helper
|
||||
|
||||
#### Page Helper functions
|
||||
|
||||
- `setData()`
|
||||
|
||||
You can either pass the data in the constructor or use the `setData()` function.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const pageHelper = new PageHelper();
|
||||
pageHelper.setData(data);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```ts
|
||||
const pageHelper = new PageHelper(data);
|
||||
```
|
||||
|
||||
- `getCleanData()`
|
||||
|
||||
Gets the cleaned up data. It deletes useless properties and and transforms the remaining ones to camelCase.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const clean = pageHelper.getCleanData();
|
||||
```
|
||||
|
||||
- `getObjectsArray()`
|
||||
|
||||
Returns the objects array, which can contain heavily nested arrays with objects data.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const objects = pageHelper.getObjectsArray();
|
||||
```
|
||||
|
||||
- `getObjectById(id: string)`
|
||||
|
||||
Returns an object by given uuid. The object is cleaned up and formatted as a `PObject`.
|
||||
|
||||
```ts
|
||||
const obj: PObject = pageHelper.getObjectById(
|
||||
'3aba0744-11fe-4c41-80fb-1b42aa7ef3e5'
|
||||
);
|
||||
```
|
||||
|
||||
### Selection Helper
|
||||
|
||||
#### Selection Helper functions
|
||||
|
||||
- `static getUuids(selection: Selection)`
|
||||
|
||||
Returns the selected items in an array.
|
||||
|
||||
example:
|
||||
|
||||
```ts
|
||||
const ids = SelectionHelper.getUuids(selection);
|
||||
```
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "plugins-data-parser",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {},
|
||||
"type": "commonjs",
|
||||
"main": "./src/index.js",
|
||||
"typings": "./src/index.d.ts"
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "plugins-data-parser",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "libs/plugins-data-parser/src",
|
||||
"projectType": "library",
|
||||
"targets": {},
|
||||
"tags": ["type:util"]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export { getSelectedUuids, cleanObject, getPartialState } from './lib/utils';
|
||||
export * from './lib/models';
|
||||
export * from './lib/helpers';
|
|
@ -1,22 +0,0 @@
|
|||
import { cleanObject } from '../utils';
|
||||
|
||||
/**
|
||||
* WIP
|
||||
*/
|
||||
export class FileHelper {
|
||||
private data: unknown = null;
|
||||
|
||||
public constructor(data?: unknown) {
|
||||
if (data) {
|
||||
this.setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
public setData(data: unknown): void {
|
||||
this.data = cleanObject(data);
|
||||
}
|
||||
|
||||
public getCleanData(): unknown {
|
||||
return this.data;
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export * from './file.helper';
|
||||
export * from './page.helper';
|
||||
export * from './selection.helper';
|
|
@ -1,97 +0,0 @@
|
|||
import { cleanObject, parseObject, isObject } from '../utils';
|
||||
import { PObject } from '../models';
|
||||
import { Name, Uuid } from '../utils/models/util.model';
|
||||
|
||||
interface PageArr {
|
||||
data?: {
|
||||
arr?: unknown[];
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface PageObject {
|
||||
root?: {
|
||||
arr?: unknown[];
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* WIP
|
||||
*/
|
||||
export class PageHelper {
|
||||
private data: unknown = null;
|
||||
private objects: unknown[] = [];
|
||||
|
||||
public constructor(data?: unknown) {
|
||||
if (data) {
|
||||
this.setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
public setData(data: unknown): void {
|
||||
this.data = cleanObject(data);
|
||||
this.objects = this.getPageObjects(this.data as PageArr);
|
||||
}
|
||||
|
||||
public getCleanData(): unknown {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public getObjectsArray(): unknown[] {
|
||||
return this.objects;
|
||||
}
|
||||
|
||||
public getObjectById(id: string): PObject | null {
|
||||
if (!this.objects) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const foundObject = this.findObject(this.objects, id);
|
||||
return parseObject(foundObject) as PObject;
|
||||
}
|
||||
|
||||
private getPageObjects(obj: PageArr): unknown[] {
|
||||
const dataArr = obj?.data?.arr;
|
||||
|
||||
const objectNameIndex = dataArr?.findIndex(
|
||||
(item) => isObject(item) && (item as Name)?.name === 'objects'
|
||||
);
|
||||
|
||||
if (!objectNameIndex) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const objects = dataArr?.[objectNameIndex + 1] as PageObject;
|
||||
|
||||
return (isObject(objects) && objects?.root?.arr) || [];
|
||||
}
|
||||
|
||||
private findObject(
|
||||
data: unknown,
|
||||
id: string
|
||||
): Record<string, unknown> | null {
|
||||
if (Array.isArray(data)) {
|
||||
for (const item of data) {
|
||||
const foundObject = this.findObject(item, id);
|
||||
if (foundObject !== null) {
|
||||
return foundObject;
|
||||
}
|
||||
}
|
||||
} else if (isObject(data)) {
|
||||
const obj = data as Record<string, unknown>;
|
||||
if ((obj?.['id'] as Uuid)?.uuid === id || obj?.['id'] === id) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(obj)) {
|
||||
const foundObject = this.findObject(obj[key], id);
|
||||
if (foundObject !== null) {
|
||||
return foundObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import { Selection } from '../models';
|
||||
|
||||
/**
|
||||
* WIP
|
||||
*/
|
||||
export class SelectionHelper {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
static getUuids(selection: Selection): string[] {
|
||||
const root = selection?.linked_map?.delegate_map?.root?.arr;
|
||||
|
||||
return (root?.filter((r) => r?.uuid).map((r) => r.uuid) as string[]) || [];
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
import { Point } from '.';
|
||||
|
||||
export interface Extmap {
|
||||
fillColor?: string;
|
||||
strokeStyle?: null | string;
|
||||
none?: unknown;
|
||||
strokeColor?: string;
|
||||
content?: ExtmapContent[];
|
||||
strokeOpacity?: number;
|
||||
strokeAlignment?: unknown;
|
||||
center?: null | ExtmapInner;
|
||||
proportionLock?: null | boolean;
|
||||
constraintsV?: unknown;
|
||||
constraintsH?: unknown;
|
||||
leftright?: unknown;
|
||||
strokes?: Stroke[];
|
||||
proportion?: number;
|
||||
fills?: Fill[];
|
||||
fillOpacity?: number;
|
||||
growType?: unknown;
|
||||
touched?: Touched;
|
||||
shapeRef?: string;
|
||||
topbottom?: unknown;
|
||||
positionData?: PositionData[];
|
||||
overflowText?: unknown;
|
||||
fixed?: unknown;
|
||||
hidden?: null | boolean;
|
||||
componentId?: string;
|
||||
flipX?: unknown;
|
||||
componentFile?: string;
|
||||
flipY?: unknown;
|
||||
shapes?: string[];
|
||||
inner?: ExtmapInner;
|
||||
strokeWidth?: number;
|
||||
shadow: Shadow[];
|
||||
componentRoot?: boolean;
|
||||
rx?: number;
|
||||
ry?: number;
|
||||
autoWidth?: unknown;
|
||||
top?: Top;
|
||||
hideInViewer: null | boolean;
|
||||
exports?: null | Export[];
|
||||
thumbnail?: string;
|
||||
}
|
||||
|
||||
export interface Export {
|
||||
type: null | string;
|
||||
jpeg: unknown;
|
||||
suffix: null | string;
|
||||
scale: number;
|
||||
}
|
||||
|
||||
export interface Top {
|
||||
constraintsH: unknown;
|
||||
leftRight: unknown;
|
||||
hidden: null | boolean;
|
||||
}
|
||||
|
||||
export interface Shadow {
|
||||
color: Partial<Color>;
|
||||
spread: unknown;
|
||||
offsetY: number;
|
||||
style: unknown;
|
||||
dropShadow: unknown;
|
||||
blur: number;
|
||||
hidden: null | boolean;
|
||||
opacity: null | number;
|
||||
id: string;
|
||||
offsetX: null | number;
|
||||
}
|
||||
|
||||
export interface ExtmapInner {
|
||||
shapeRef: string;
|
||||
proportionLock: boolean;
|
||||
}
|
||||
|
||||
export interface Touched {
|
||||
hashMap: HashMap;
|
||||
}
|
||||
|
||||
export interface HashMap {
|
||||
hashMap: GeometryGroup;
|
||||
}
|
||||
|
||||
export interface GeometryGroup {
|
||||
geometryGroup: unknown;
|
||||
}
|
||||
|
||||
export interface PositionData {
|
||||
y?: number;
|
||||
fontStyle?: string;
|
||||
textTransform?: string;
|
||||
fontSize?: string;
|
||||
fontWeight?: string;
|
||||
width?: number;
|
||||
textDecoration?: string;
|
||||
letterSpacing?: string;
|
||||
x?: number;
|
||||
fills?: Fill[];
|
||||
direction?: string;
|
||||
fontFamily?: string;
|
||||
height?: number;
|
||||
text?: string;
|
||||
extmap?: ExtmapContent;
|
||||
x1?: number;
|
||||
y1?: number;
|
||||
x2?: number;
|
||||
y2?: number;
|
||||
}
|
||||
export interface ExtmapBottom {
|
||||
blur: Blur;
|
||||
strokeWidth: number;
|
||||
}
|
||||
|
||||
export interface Fill {
|
||||
fillColor: string;
|
||||
fillOpacity: number;
|
||||
fillColorRefFile?: string;
|
||||
fillColorRefId?: string;
|
||||
}
|
||||
|
||||
export interface Stroke {
|
||||
strokeStyle: unknown;
|
||||
none: unknown;
|
||||
strokeColor: string;
|
||||
strokeOpacity: number;
|
||||
strokeAlignment: unknown;
|
||||
center: unknown;
|
||||
strokeWidth: number;
|
||||
}
|
||||
|
||||
export interface Blur {
|
||||
id: string;
|
||||
type: unknown;
|
||||
layerBlur: unknown;
|
||||
value: number;
|
||||
hidden: unknown;
|
||||
}
|
||||
|
||||
export interface ExtmapContent {
|
||||
command?: unknown;
|
||||
moveTo?: unknown;
|
||||
relative?: unknown;
|
||||
params?: Point;
|
||||
key?: string;
|
||||
type?: string;
|
||||
children?: ExtmapContent[];
|
||||
fillColor?: string;
|
||||
fillOpacity?: number;
|
||||
fontFamily?: string;
|
||||
fontId?: string;
|
||||
fontSize?: string;
|
||||
fontStyle?: string;
|
||||
fontVariantId?: string;
|
||||
fontWeight?: string;
|
||||
text?: string;
|
||||
textDecoration?: string;
|
||||
textTransform?: string;
|
||||
verticalAlign?: string;
|
||||
direction?: string;
|
||||
fills?: Fill[];
|
||||
letterSpacing?: string;
|
||||
}
|
||||
|
||||
export interface ExtmapContentPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
c1x?: number;
|
||||
c1y?: number;
|
||||
c2x?: number;
|
||||
c2y?: number;
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
color: string;
|
||||
opacity: number;
|
||||
id: string;
|
||||
name: string;
|
||||
fileId: string;
|
||||
path: string | null;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export * from './selection.model';
|
||||
export * from './object.model';
|
||||
export * from './extmap.model';
|
|
@ -1,44 +0,0 @@
|
|||
import { Extmap } from '.';
|
||||
|
||||
export interface PObject {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
rotation: number;
|
||||
selrect: Selrect;
|
||||
points: Point[];
|
||||
transform: Transform;
|
||||
transformInverse: Transform;
|
||||
parentId: string;
|
||||
frameId: string;
|
||||
extmap: Extmap;
|
||||
}
|
||||
|
||||
export interface Selrect {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
x1: number;
|
||||
y1: number;
|
||||
x2: number;
|
||||
y2: number;
|
||||
}
|
||||
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface Transform {
|
||||
a: number;
|
||||
b: number;
|
||||
c: number;
|
||||
d: number;
|
||||
e: number;
|
||||
f: number;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
export interface Selection extends CljValues {
|
||||
linked_map: SelLinkedMap;
|
||||
}
|
||||
|
||||
export interface SelLinkedMap extends CljValues {
|
||||
head: SelUuid | null;
|
||||
delegate_map: SelDelegateMap;
|
||||
}
|
||||
|
||||
export interface SelDelegateMap extends CljValues, UnderscoreValues, NilValues {
|
||||
meta: unknown;
|
||||
cnt: number;
|
||||
root: SelRoot | null;
|
||||
}
|
||||
|
||||
export interface SelRoot extends CljValues {
|
||||
edit: unknown;
|
||||
bitmap: number;
|
||||
arr: SelArr[];
|
||||
}
|
||||
|
||||
export interface SelArr extends UnderscoreValues, CljValues {
|
||||
uuid?: string;
|
||||
value: unknown;
|
||||
left?: SelUuid;
|
||||
right?: SelUuid;
|
||||
}
|
||||
|
||||
export interface SelUuid extends CljValues, UnderscoreValues {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface CljValues {
|
||||
cljs$lang$protocol_mask$partition0$: number;
|
||||
cljs$lang$protocol_mask$partition1$: number;
|
||||
}
|
||||
|
||||
export interface UnderscoreValues {
|
||||
__meta?: null | number;
|
||||
__extmap?: null | number;
|
||||
__hash: null | number;
|
||||
}
|
||||
|
||||
export interface NilValues {
|
||||
nil_val: null | boolean;
|
||||
has_nil_QMARK_: null | boolean;
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
import { isObject, toCamelCase, isSingleObjectWithProperty } from '.';
|
||||
import { Arr, Name } from './models/util.model';
|
||||
|
||||
/**
|
||||
* Checks if "arr" property can be turned into an object
|
||||
*/
|
||||
function toObject(arr: unknown): boolean {
|
||||
return (
|
||||
Array.isArray(arr) && arr.some((a) => isSingleObjectWithProperty(a, 'name'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if "arr" property can be turned into an array of objects
|
||||
*/
|
||||
function toArray(arr: unknown): boolean {
|
||||
return (
|
||||
Array.isArray(arr) &&
|
||||
arr.every((a) => isObject(a)) &&
|
||||
arr.every(
|
||||
(a) =>
|
||||
isSingleObjectWithProperty(a, 'uuid') ||
|
||||
isSingleObjectWithProperty(a, 'arr')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a splitted "arr" back into an object if possible.
|
||||
*
|
||||
* If there are objects with a single property "name", that
|
||||
* object and the next one are turned into a key-value pair.
|
||||
*
|
||||
* example:
|
||||
* [{ name: 'foo' }, 'bar', { name: 'baz' }, 'qux'] => { foo: 'bar', baz: 'qux' }
|
||||
*/
|
||||
function arrToObject(arr: unknown): Record<string, unknown> | null {
|
||||
return (
|
||||
(Array.isArray(arr) &&
|
||||
arr.reduce(
|
||||
(result: Record<string, unknown>, value: unknown, index: number) => {
|
||||
if (isSingleObjectWithProperty(value, 'name')) {
|
||||
const next = arr[index + 1] as unknown;
|
||||
if (!!next && !isSingleObjectWithProperty(next, 'name')) {
|
||||
return { ...result, [toCamelCase((value as Name)?.name)]: next };
|
||||
} else {
|
||||
return { ...result, [toCamelCase((value as Name)?.name)]: null };
|
||||
}
|
||||
}
|
||||
return { ...result };
|
||||
},
|
||||
{}
|
||||
)) ||
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a splitted "arr" back into an array of objects.
|
||||
*
|
||||
*/
|
||||
function arrToArray(arr: unknown): unknown[] | null {
|
||||
return (
|
||||
(Array.isArray(arr) &&
|
||||
arr.reduce((result: unknown[], value: unknown) => {
|
||||
if (isSingleObjectWithProperty(value, 'arr')) {
|
||||
return [...result, { ...(value as Arr)?.arr }];
|
||||
}
|
||||
return [...result];
|
||||
}, [])) ||
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks an "arr" property and decides which parse solution to use
|
||||
*/
|
||||
export function parseArrProperty(
|
||||
arr: unknown[]
|
||||
): unknown[] | Record<string, unknown> | null {
|
||||
if (toArray(arr)) {
|
||||
return arrToArray(arr);
|
||||
} else if (toObject(arr)) {
|
||||
return arrToObject(arr);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
export * from './object.util';
|
||||
export * from './parse.util';
|
||||
export * from './selected.util';
|
||||
export * from './arr.util';
|
||||
export * from './string.util';
|
||||
export * from './parse-state';
|
|
@ -1,11 +0,0 @@
|
|||
export interface Name {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Uuid {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface Arr {
|
||||
arr: unknown[];
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* Check if param is an object
|
||||
*/
|
||||
export function isObject(obj: unknown): boolean {
|
||||
return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if param is an object with a single property
|
||||
*/
|
||||
export function isSingleObjectWithProperty(
|
||||
object: unknown,
|
||||
property: string
|
||||
): boolean {
|
||||
if (isObject(object)) {
|
||||
return (
|
||||
Object.keys(object as Record<string, unknown>).length === 1 &&
|
||||
!!(object as Record<string, unknown>)[property]
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if param is an object with a single property from a list
|
||||
*/
|
||||
export function isSingleObjectWithProperties(
|
||||
object: unknown,
|
||||
properties: string[]
|
||||
): boolean {
|
||||
if (isObject(object)) {
|
||||
const keys = Object.keys(object as Record<string, unknown>);
|
||||
|
||||
if (keys.length === 1) {
|
||||
return properties.includes(keys[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if param is a root-tail object
|
||||
*/
|
||||
export function isRootTail(obj: unknown): boolean {
|
||||
if (isObject(obj)) {
|
||||
const keys = Object.keys(obj as Record<string, unknown>);
|
||||
return keys.length === 2 && keys.includes('root') && keys.includes('tail');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import { toCamelCase } from '.';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type UknowCljs = any;
|
||||
|
||||
declare global {
|
||||
const cljs: UknowCljs;
|
||||
const app: UknowCljs;
|
||||
}
|
||||
|
||||
const PATH_SEPARATOR = '/' as const;
|
||||
|
||||
function getPath(path: string): UknowCljs[] {
|
||||
if (path === 'root') {
|
||||
return [];
|
||||
}
|
||||
return path
|
||||
.slice(5)
|
||||
.split(PATH_SEPARATOR)
|
||||
.map((it) => {
|
||||
if (it.startsWith('#')) {
|
||||
return cljs.core.uuid(it.slice(1));
|
||||
} else if (it.startsWith(':')) {
|
||||
return cljs.core.keyword(it.slice(1));
|
||||
} else if (it.startsWith('!')) {
|
||||
return parseInt(it.slice(1), 10);
|
||||
} else {
|
||||
return it;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const expandableTable = {
|
||||
'app:datetime': false,
|
||||
'cljs:uuid': false,
|
||||
'cljs:keyword': false,
|
||||
'cljs:symbol': false,
|
||||
'js:date': false,
|
||||
'js:boolean': false,
|
||||
'js:function': false,
|
||||
'js:number': false,
|
||||
'js:string': false,
|
||||
'js:undefined': false,
|
||||
'js:null': false,
|
||||
'unkwnown:unknown': false,
|
||||
'cljs:vector': true,
|
||||
'cljs:list': true,
|
||||
'cljs:map': true,
|
||||
'cljs:set': true,
|
||||
'js:array': true,
|
||||
'js:object': true,
|
||||
} as const;
|
||||
|
||||
function isCljsArray(key: string) {
|
||||
const valid = ['cljs:vector', 'cljs:list', 'cljs:set'];
|
||||
|
||||
return valid.includes(key);
|
||||
}
|
||||
|
||||
const valueTable = {
|
||||
'app:datetime': (value: unknown) => cljs.core.str(value),
|
||||
'cljs:uuid': (value: unknown) => cljs.core.name(value),
|
||||
'cljs:keyword': (value: unknown) => cljs.core.name(value),
|
||||
'js:date': (value: unknown) => (value as Date).toISOString(),
|
||||
};
|
||||
|
||||
function isTypeExpandable(type: keyof typeof expandableTable) {
|
||||
return expandableTable[type];
|
||||
}
|
||||
|
||||
function getType(value: unknown) {
|
||||
const typeTable = {
|
||||
'app:datetime': app.util.time.datetime_QMARK_,
|
||||
'cljs:uuid': cljs.core.uuid_QMARK_,
|
||||
'cljs:keyword': cljs.core.keyword_QMARK_,
|
||||
'cljs:vector': cljs.core.vector_QMARK_,
|
||||
'cljs:list': cljs.core.list_QMARK_,
|
||||
'cljs:map': cljs.core.map_QMARK_,
|
||||
'cljs:set': cljs.core.set_QMARK_,
|
||||
'cljs:symbol': cljs.core.symbol_QMARK_,
|
||||
'js:date': (value: unknown) => value instanceof Date,
|
||||
'js:array': (value: unknown) => Array.isArray(value),
|
||||
'js:boolean': (value: unknown) => typeof value === 'boolean',
|
||||
'js:function': (value: unknown) => typeof value === 'function',
|
||||
'js:number': (value: unknown) => typeof value === 'number',
|
||||
'js:string': (value: unknown) => typeof value === 'string',
|
||||
'js:undefined': (value: unknown) => typeof value === 'undefined',
|
||||
'js:null': (value: unknown) => value === null,
|
||||
'js:object': (value: unknown) =>
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
value.toString() === '[object Object]',
|
||||
};
|
||||
|
||||
for (const [type, fn] of Object.entries(typeTable)) {
|
||||
if (fn(value)) return type as keyof typeof typeTable;
|
||||
}
|
||||
|
||||
return 'unknown:unknown' as keyof typeof typeTable;
|
||||
}
|
||||
|
||||
function getKeyName(key: string | number) {
|
||||
if (cljs.core.uuid_QMARK_(key)) {
|
||||
return '#' + cljs.core.name(key);
|
||||
} else if (cljs.core.keyword_QMARK_(key)) {
|
||||
return ':' + cljs.core.name(key);
|
||||
} else if (typeof key === 'string') {
|
||||
return key;
|
||||
} else if (typeof key === 'number') {
|
||||
return `!${key}`;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
function getValue(value: unknown, type: string): unknown {
|
||||
return type in valueTable
|
||||
? valueTable[type as keyof typeof valueTable](value)
|
||||
: value;
|
||||
}
|
||||
|
||||
export function getPartialState(path: string, state: UknowCljs): UknowCljs {
|
||||
// const state = cljs.core.deref(app.main.store.state);
|
||||
const statePath = getPath(path);
|
||||
const data = cljs.core.get_in(state, statePath);
|
||||
const type = getType(data);
|
||||
const isArray = isCljsArray(type);
|
||||
const isExpandable = isTypeExpandable(type);
|
||||
|
||||
const map: Record<string, unknown> = {};
|
||||
const list: unknown[] = [];
|
||||
|
||||
function addEntry(
|
||||
childPath: string,
|
||||
propName: string | number,
|
||||
repValue: unknown,
|
||||
isExpandable: boolean
|
||||
) {
|
||||
if (isArray) {
|
||||
list.push(isExpandable ? getPartialState(childPath, state) : repValue);
|
||||
} else {
|
||||
if (isExpandable) {
|
||||
Object.defineProperty(map, propName, {
|
||||
get() {
|
||||
return getPartialState(childPath, state);
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
} else {
|
||||
map[propName] = repValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isExpandable) {
|
||||
if (type.startsWith('cljs:')) {
|
||||
const cljsData = cljs.core.clj__GT_js(cljs.core.to_array(data));
|
||||
|
||||
cljsData.forEach((entry: unknown, index: number) => {
|
||||
if (cljs.core.map_entry_QMARK_(entry)) {
|
||||
const key = cljs.core.first(entry);
|
||||
const name = getKeyName(key);
|
||||
const value = cljs.core.nth(entry, 1);
|
||||
const valueType = getType(value);
|
||||
const repValue = getValue(value, valueType);
|
||||
const isExpandable = isTypeExpandable(valueType);
|
||||
const childPath = path + PATH_SEPARATOR + name;
|
||||
const propName = name.startsWith(':')
|
||||
? toCamelCase(name.slice(1))
|
||||
: name;
|
||||
|
||||
addEntry(childPath, propName, repValue, isExpandable);
|
||||
} else {
|
||||
const valueType = getType(entry);
|
||||
const repValue = getValue(entry, valueType);
|
||||
const isExpandable = isTypeExpandable(valueType);
|
||||
const childPath = path + PATH_SEPARATOR + getKeyName(index);
|
||||
|
||||
addEntry(childPath, index, repValue, isExpandable);
|
||||
}
|
||||
});
|
||||
} else if (type.startsWith('js:')) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
map[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
return isArray ? list : map;
|
||||
}
|
||||
|
||||
const repValue = getValue(data, type);
|
||||
|
||||
return repValue;
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
import {
|
||||
isObject,
|
||||
toCamelCase,
|
||||
parseArrProperty,
|
||||
isRootTail,
|
||||
isSingleObjectWithProperties,
|
||||
isSingleObjectWithProperty,
|
||||
} from '.';
|
||||
import { Arr } from './models/util.model';
|
||||
|
||||
export function parseSingleProperties(
|
||||
obj: unknown,
|
||||
properties: string[]
|
||||
): unknown {
|
||||
let result = obj;
|
||||
|
||||
properties.forEach((property) => {
|
||||
if (isSingleObjectWithProperty(obj, property)) {
|
||||
result = (obj as Record<string, unknown>)[property];
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function parseRootTail(obj: unknown): unknown {
|
||||
if (isObject(obj) && isRootTail(obj)) {
|
||||
const { root, tail } = obj as Record<string, unknown>;
|
||||
|
||||
const hasRoot = Array.isArray(root) && root?.length > 0;
|
||||
const hasTail = Array.isArray(tail) && tail?.length > 0;
|
||||
|
||||
if (hasRoot && hasTail) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (hasTail) {
|
||||
return tail;
|
||||
}
|
||||
|
||||
if (hasRoot) {
|
||||
return root;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively cleans an object from unnecesary properties
|
||||
* and converts snake_case and kebab-case to camelCase
|
||||
*/
|
||||
export function cleanObject(obj: unknown): unknown {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj
|
||||
.filter((p) => p !== null)
|
||||
.map((v: Record<string, unknown>) => cleanObject(v)) as Record<
|
||||
string,
|
||||
unknown
|
||||
>[];
|
||||
} else if (isObject(obj)) {
|
||||
return Object.keys(obj as Record<string, unknown>)
|
||||
.filter(
|
||||
(key) =>
|
||||
!/^(cljs\$|\$hash|ts|ry|\$meta|__hash|_hash|bitmap|meta|ns|fqn|cnt|shift|edit|has_nil_QMARK_|nil_val)/g.test(
|
||||
key
|
||||
)
|
||||
)
|
||||
.reduce((result, key) => {
|
||||
const value = (obj as Record<string, unknown>)[key];
|
||||
if (['extmap', '$extmap'].includes(key) && value === null) {
|
||||
return { ...result };
|
||||
}
|
||||
|
||||
return {
|
||||
...result,
|
||||
[toCamelCase(key)]: cleanObject(
|
||||
(obj as Record<string, unknown>)[key]
|
||||
),
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
return obj as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function parseObject(obj: unknown): unknown {
|
||||
const singleProperties = ['root', 'name', 'uuid', 'guides'];
|
||||
if (isSingleObjectWithProperties(obj, singleProperties)) {
|
||||
const parsed = parseSingleProperties(
|
||||
obj as Record<string, unknown>,
|
||||
singleProperties
|
||||
);
|
||||
return parseObject(parsed);
|
||||
}
|
||||
|
||||
if (isSingleObjectWithProperty(obj, 'arr')) {
|
||||
const parsed = parseArrProperty((obj as Arr).arr);
|
||||
return parseObject(parsed);
|
||||
}
|
||||
|
||||
if (isRootTail(obj)) {
|
||||
const parsed = parseRootTail(obj);
|
||||
return parseObject(parsed);
|
||||
}
|
||||
|
||||
// If it's an array, parse each element
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((v: Record<string, unknown>) => parseObject(v));
|
||||
}
|
||||
|
||||
// If it's an object, parse each property
|
||||
if (isObject(obj)) {
|
||||
return Object.keys(obj as Record<string, unknown>).reduce((result, key) => {
|
||||
return {
|
||||
...result,
|
||||
[key]: parseObject((obj as Record<string, unknown>)[key]),
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { Selection } from '../models/selection.model';
|
||||
|
||||
/**
|
||||
* Gets selected uuids from selection object
|
||||
*/
|
||||
export function getSelectedUuids(selection: Selection): string[] {
|
||||
const root = selection?.linked_map?.delegate_map?.root?.arr;
|
||||
|
||||
if (!root) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return root.map((r) => r.uuid).filter((uuid): uuid is string => !!uuid);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
/**
|
||||
* Converts a string to camelCase from kebab-case and snake_case
|
||||
*/
|
||||
export function toCamelCase(str: string): string {
|
||||
const clean = str.replace(/^(\$|_|-)_?/, '');
|
||||
|
||||
return clean.replace(/(_|-)./g, (x) => x[1].toUpperCase());
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node", "vite/client"]
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import * as path from 'path';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/plugins-data-parser',
|
||||
|
||||
plugins: [
|
||||
nxViteTsPaths(),
|
||||
dts({
|
||||
entryRoot: 'src',
|
||||
tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||
skipDiagnostics: true,
|
||||
}),
|
||||
],
|
||||
|
||||
// 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: {
|
||||
outDir: '../../dist/libs/plugins-data-parser',
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points.
|
||||
entry: 'src/index.ts',
|
||||
name: 'plugins-data-parser',
|
||||
fileName: 'index',
|
||||
// Change this to the formats you want to support.
|
||||
// Don't forget to update your package.json as well.
|
||||
formats: ['es', 'cjs'],
|
||||
},
|
||||
rollupOptions: {
|
||||
// External packages that should not be bundled into your library.
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./libs/plugins-runtime/tsconfig.*?.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": [
|
||||
"error",
|
||||
{
|
||||
"ignoredFiles": ["{projectRoot}/vite.config.{js,ts,mjs,mts}"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
50
libs/plugins-runtime/eslint.config.js
Normal file
50
libs/plugins-runtime/eslint.config.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
import baseConfig from '../../eslint.config.js';
|
||||
import typescriptEslintParser from '@typescript-eslint/parser';
|
||||
import jsoncParser from 'jsonc-eslint-parser';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: typescriptEslintParser,
|
||||
parserOptions: { project: './libs/plugins-runtime/tsconfig.*?.json' },
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
PluginConfig: 'readonly',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['*.json'],
|
||||
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',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
|
@ -1,15 +1,12 @@
|
|||
{
|
||||
"name": "plugins-runtime",
|
||||
"version": "0.1.0",
|
||||
"devDependencies": {
|
||||
"happy-dom": "^13.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@penpot/plugin-types": "^0.1.0",
|
||||
"vitest": "1.2.2",
|
||||
"ses": "^1.1.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"module": "./index.mjs",
|
||||
"typings": "./index.d.ts"
|
||||
"typings": "./index.d.ts",
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import 'ses';
|
||||
import './lib/plugin-modal';
|
||||
import { initInstaller } from './lib/installer';
|
||||
import { initInstaller } from './lib/installer.js';
|
||||
|
||||
import { ɵloadPlugin, setContext } from './lib/load-plugin';
|
||||
import * as api from './lib/api';
|
||||
import { ɵloadPlugin, setContext } from './lib/load-plugin.js';
|
||||
import * as api from './lib/api/index.js';
|
||||
import type { PenpotContext } from '@penpot/plugin-types';
|
||||
|
||||
console.log('%c[PLUGINS] Loading plugin system', 'color: #008d7c');
|
||||
|
||||
|
|
|
@ -8,12 +8,15 @@ import type {
|
|||
PenpotFrame,
|
||||
PenpotGroup,
|
||||
PenpotViewport,
|
||||
PenpotText,
|
||||
PenpotFile,
|
||||
PenpotTheme,
|
||||
} from '@penpot/plugin-types';
|
||||
|
||||
import { Manifest, Permissions } from '../models/manifest.model';
|
||||
import { OpenUIOptions } from '../models/open-ui-options.model';
|
||||
import { setModalTheme } from '../create-modal';
|
||||
import openUIApi from './openUI.api';
|
||||
import { Manifest, Permissions } from '../models/manifest.model.js';
|
||||
import { OpenUIOptions } from '../models/open-ui-options.model.js';
|
||||
import { setModalTheme } from '../create-modal.js';
|
||||
import openUIApi from './openUI.api.js';
|
||||
import z from 'zod';
|
||||
|
||||
type Callback<T> = (message: T) => void;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { PenpotContext } from '@penpot/plugin-types';
|
||||
|
||||
import { PluginConfig } from './models/plugin-config.model';
|
||||
import { createApi } from './api';
|
||||
import { parseManifest } from './parse-manifest';
|
||||
import { PluginConfig } from './models/plugin-config.model.js';
|
||||
import { createApi } from './api/index.js';
|
||||
import { parseManifest } from './parse-manifest.js';
|
||||
|
||||
let isLockedDown = false;
|
||||
let lastApi: ReturnType<typeof createApi> | undefined;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.base.json", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "vite.config.ts"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./libs/plugins-styles/tsconfig.lib.json"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": [
|
||||
"error",
|
||||
{
|
||||
"ignoredFiles": ["{projectRoot}/vite.config.{js,ts,mjs,mts}"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -15,8 +15,7 @@
|
|||
"dependsOn": ["build"]
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"]
|
||||
"command": "echo 0"
|
||||
}
|
||||
},
|
||||
"tags": ["type:ui"]
|
||||
|
|
31
package-lock.json
generated
31
package-lock.json
generated
|
@ -45,6 +45,7 @@
|
|||
"@angular/language-service": "~17.1.0",
|
||||
"@commitlint/cli": "^18.6.0",
|
||||
"@commitlint/config-conventional": "^18.6.0",
|
||||
"@eslint/eslintrc": "^2.1.1",
|
||||
"@fastify/cors": "^9.0.1",
|
||||
"@nx/angular": "^18.0.2",
|
||||
"@nx/esbuild": "18.0.2",
|
||||
|
@ -68,6 +69,7 @@
|
|||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-deprecation": "^2.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"globals": "^15.1.0",
|
||||
"happy-dom": "^13.6.2",
|
||||
"husky": "^9.0.10",
|
||||
"jsdom": "~22.1.0",
|
||||
|
@ -3330,6 +3332,15 @@
|
|||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-classes/node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-computed-properties": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz",
|
||||
|
@ -4217,6 +4228,15 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse/node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
|
||||
|
@ -13821,12 +13841,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"version": "15.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.1.0.tgz",
|
||||
"integrity": "sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "penpot-plugins",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "npx nx run plugins-runtime:build --watch --mode development & npx nx run plugins-runtime:preview",
|
||||
|
@ -30,6 +31,7 @@
|
|||
"@angular/language-service": "~17.1.0",
|
||||
"@commitlint/cli": "^18.6.0",
|
||||
"@commitlint/config-conventional": "^18.6.0",
|
||||
"@eslint/eslintrc": "^2.1.1",
|
||||
"@fastify/cors": "^9.0.1",
|
||||
"@nx/angular": "^18.0.2",
|
||||
"@nx/esbuild": "18.0.2",
|
||||
|
@ -53,6 +55,7 @@
|
|||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-deprecation": "^2.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"globals": "^15.1.0",
|
||||
"happy-dom": "^13.6.2",
|
||||
"husky": "^9.0.10",
|
||||
"jsdom": "~22.1.0",
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@penpot/plugin-types": ["libs/plugin-types/index.d.ts"],
|
||||
"plugins-parser": ["libs/plugins-data-parser/src/index.ts"],
|
||||
"plugins-runtime": ["libs/plugins-runtime/src/index.ts"],
|
||||
"plugins-styles/*": ["libs/plugins-styles/src/*"]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue