diff --git a/examples/web/package.json b/examples/web/package.json index 0c36933..9bd48d9 100644 --- a/examples/web/package.json +++ b/examples/web/package.json @@ -11,7 +11,11 @@ "dependencies": { "@imgly/plugin-background-removal-web": "*", "@imgly/plugin-remote-asset-source-web": "*", + "@imgly/plugin-vectorizer": "*", + "@imgly/plugin-design-essentials": "*", "@cesdk/cesdk-js": "^1.21.0", + "lodash": "^4.17.21", + "react-cmdk": "^1.3.9", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/examples/web/src/App.tsx b/examples/web/src/App.tsx index 627ee3c..65a5d15 100644 --- a/examples/web/src/App.tsx +++ b/examples/web/src/App.tsx @@ -1,57 +1,253 @@ -import CreativeEditorSDK from '@cesdk/cesdk-js'; -import { useRef } from 'react'; +const ENABLE_DEMO_ASSET_SOURCES = false; + +import { useRef, useState } from "react"; +import CreativeEditorSDKComponent from "./components/CreativeEditorSDK"; +import CreativeEditorSDK from "@cesdk/cesdk-js"; + + +// React UI Components +import { CommandPalette } from "./components/CommandPalette" +// Utils +import { downloadBlocks } from "./utils/download"; + +// IMGLY Plugins + + +// Plugins +// import BackgroundRemovalPlugin from '@imgly/plugin-background-removal-web'; +import { PluginContext } from "@imgly/plugin-core"; + +import BackgroundRemovalPlugin from '@imgly/plugin-background-removal-web'; +import VectorizerPlugin from '@imgly/plugin-vectorizer'; +import DesignBatteriesPlugin from "@imgly/plugin-design-essentials"; +import RemoteAssetSourcePlugin from '@imgly/plugin-remote-asset-source-web'; + + + + +declare global { + interface Window { imgly: PluginContext } +} -import addPlugins, { prepareAssetEntries } from './addPlugins'; function App() { - const cesdk = useRef(); - return ( -
{ - if (domElement != null) { - CreativeEditorSDK.create(domElement, { - license: import.meta.env.VITE_CESDK_LICENSE_KEY, - callbacks: { onUpload: 'local' }, - ui: { - elements: { - libraries: { - insert: { - entries: (d) => { - if (!cesdk.current) return; - return prepareAssetEntries(d, cesdk.current!.engine); - } - }, - replace: { - entries: (d) => { - if (!cesdk.current) return; - return prepareAssetEntries(d, cesdk.current!.engine); - } - } - }, - panels: { settings: true } - } - } - }).then(async (instance) => { - // @ts-ignore - window.cesdk = instance; - cesdk.current = instance; - - // Do something with the instance of CreativeEditor SDK, for example: - // Populate the asset library with default / demo asset sources. - await Promise.all([ - instance.addDefaultAssetSources(), - instance.addDemoAssetSources({ sceneMode: 'Design' }) - ]); - await addPlugins(instance); - await instance.createDesignScene(); - }); - } else if (cesdk.current != null) { - cesdk.current.dispose(); + // const cesdkRef = useRef(); + const contextRef = useRef(); + const [commandItems, setCommandItems] = useState>([]) + const [isCommandPaletteOpen, setIsCommandPaletteOpen] = useState(false) + + + const commandPaletteButton = (params: { builder: any }) => { + params + .builder! + .Button("plugin.imgly.commandpalette.id", { + label: "plugin.imgly.commandpalette.label", + icon: undefined, + isActive: isCommandPaletteOpen, + isLoading: false, + isDisabled: isCommandPaletteOpen, + loadingProgress: undefined, // creates infinite spinner + onClick: () => { + setIsCommandPaletteOpen(true) } - }} - >
+ }); + } + + + + const [config, _setConfig] = useState( + { + "license": import.meta.env.VITE_CESDK_LICENSE_KEY, + "callbacks.onUpload": 'local', + "callbacks.onDownload": "download", + "callbacks.onSave": async (str: string) => downloadBlocks(contextRef.current!.engine.block, [new Blob([str])], { mimeType: 'application/imgly' }), + "callbacks.onExport": async (blobs: Array, options: any) => downloadBlocks(contextRef.current!.engine.block, blobs, { mimeType: options.mimeType, pages: options.pages }), + // "callbacks.onLoad": , + // devMode: true, + "theme": "dark", + "role": 'Creator', + "ui.hide": false, + "ui.elements.view": "advanced", + "ui.elements.navigation.action.save": true, + "ui.elements.navigation.action.load": true, + "ui.elements.navigation.action.export": true, + }) + + + const initCallback = async (cesdk: CreativeEditorSDK) => { + + const imgly = new PluginContext(cesdk) + window.imgly = imgly + + + // Init Scene Programatically + await cesdk.createDesignScene(); + cesdk.engine.scene.setDesignUnit("Pixel"); // + + + const backgroundRemovalPlugin = BackgroundRemovalPlugin({ ui: { locations: 'canvasMenu' } }) + const vectorizerPlugin = VectorizerPlugin(imgly, {}) + const commandsPlugin = DesignBatteriesPlugin(imgly, {}) + + // Register Plguins + await Promise.all([ + cesdk.addDefaultAssetSources(), + cesdk.addDemoAssetSources({ sceneMode: "Design" }), + cesdk.unstable_addPlugin(commandsPlugin), + cesdk.unstable_addPlugin(vectorizerPlugin), + cesdk.unstable_addPlugin(backgroundRemovalPlugin), + ...addDemoRemoteAssetSourcesPlugins(cesdk) //FIXME + ]); + + + + // Ui components + imgly.ui?.unstable_registerComponent("plugin.imgly.commandpalette", commandPaletteButton); + + imgly.i18n.setTranslations({ en: { "plugin.imgly.commandpalette.label": "✨ Run .." } }) + // Canvas Menu + const canvasMenuItems = imgly.ui?.unstable_getCanvasMenuOrder() ?? [] + const newCanvasMenuItems = ["plugin.imgly.commandpalette", ...canvasMenuItems]; + imgly.ui?.unstable_setCanvasMenuOrder(newCanvasMenuItems) + + + + // Bind our react command paltte to cesdk command palettes are listen on new commands being created + imgly.engine.event.subscribe([], (events) => { + events + .forEach(_ => { + setCommandItems(generateItems(imgly)) + }) + }) + imgly.commands.subscribe("register", (_label: string) => setCommandItems(generateItems(imgly))) + imgly.commands.subscribe("unregister", (_label: string) => setCommandItems(generateItems(imgly))) + + setCommandItems(generateItems(imgly)) + } + + + return ( + <> + setIsCommandPaletteOpen(val)} /> + + + ); } +const generateItems = (ctx: PluginContext) => { + return [...generateBlockHierarchy(ctx), ...generateCommandItems(ctx), ...generateProperyItems(ctx)] +} + +const generateBlockHierarchy = (ctx: PluginContext) => { + const blocks = ctx.engine.block.findAll() + + return blocks.map((bId: number) => { + const titel = ctx.engine.block.getName(bId) || ctx.engine.block.getUUID(bId).toString() + return { + id: bId, + children: titel, + kind: "block", + group: "Hierarchy", + showType: false, + onClick: () => ctx.engine.block.select(bId) + } + }) +} + +const generateProperyItems = (ctx: PluginContext) => { + const { block } = ctx.engine + const bIds = block.findAllSelected() + const bId = bIds[0] + if (!bId) return [] // for now + + const props = bIds.flatMap((bId: number) => block.findAllProperties(bId)) + const uniqueProps = Array.from(new Set(props)) + + return uniqueProps.map((p) => { + const titel = p + const value = 42 + + return { + id: bId, + children: titel, + kind: "property", + group: "Properties", + showType: false, + onClick: () => prompt(`Change ${p} to`, value.toString()) + } + }) +} + + +const generateCommandItems = (ctx: PluginContext): Array => { + const cmds = ctx + .commands! + .listCommands() + + return cmds + .map((cmdId: string) => { + const titel = ctx.i18n.translate(cmdId) // this comes from the metadata + const desc = ctx.commands.getCommandDescription(cmdId) + if (titel === undefined) throw new Error(`No translation found for command ${cmdId}`) + return { + id: cmdId, + children: titel, + kind: "command", + group: desc?.category || "Commands", + showType: false, + onClick: async () => { + await ctx.commands!.executeCommand(cmdId, {}) + } + } + }) +} + + +// The host of the remote asset source server. +// The server must be running and accessible from the client. +const ASSET_SOURCE_HOST = 'http://localhost:3000'; + +function addDemoRemoteAssetSourcesPlugins( + cesdk: CreativeEditorSDK +): Promise[] { + if (!ENABLE_DEMO_ASSET_SOURCES) return []; + return [ + '/api/assets/v1/image-pexels', + '/api/assets/v1/image-unsplash', + '/api/assets/v1/video-pexels', + '/api/assets/v1/video-giphy' + ].map(async (baseUrl) => { + await cesdk.unstable_addPlugin( + RemoteAssetSourcePlugin({ + baseUrl: ASSET_SOURCE_HOST + baseUrl + }) + ); + }); +} + +// Helper function that automatically adds asset sources to the respective asset source panels: +// If the source starts with 'ly.img.audio', 'ly.img.image', or 'ly.img.video', it will be added to the respective panel. +// Should be used as a callback for the `entries` property of the `libraries.insert`/`libraries.replace` element in the UI configuration. + +export const prepareAssetEntries = (defaultEntries: any, engine: any) => { + if (!engine) return defaultEntries; + + const assetSourceIds = engine.asset.findAllSources() ?? []; + ['ly.img.audio', 'ly.img.image', 'ly.img.video'].forEach((entryId) => { + const entry = defaultEntries.find((entry: any) => { + return entry.id === entryId; + }); + if (entry) { + const assetSources = assetSourceIds + .filter((sourceId: any) => sourceId.startsWith(entryId + '.')) + .filter((sourceId: any) => !entry.sourceIds.includes(sourceId)); + entry.sourceIds = [...entry.sourceIds, ...assetSources]; + } + }); + return defaultEntries; +}; + + + export default App; diff --git a/examples/web/src/addPlugins.ts b/examples/web/src/addPlugins.ts deleted file mode 100644 index 891a138..0000000 --- a/examples/web/src/addPlugins.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type CreativeEditorSDK from '@cesdk/cesdk-js'; - -import BackgroundRemovalPlugin from '@imgly/plugin-background-removal-web'; -import RemoteAssetSourcePlugin from '@imgly/plugin-remote-asset-source-web'; - -const ENABLE_DEMO_ASSET_SOURCES = false; - -async function addPlugins(cesdk: CreativeEditorSDK): Promise { - console.log('Adding plugins', RemoteAssetSourcePlugin); - try { - await Promise.all([ - cesdk.unstable_addPlugin( - BackgroundRemovalPlugin({ ui: { locations: 'canvasMenu' } }) - ), - ...addDemoRemoteAssetSourcesPlugins(cesdk) - ]); - } catch (error) { - console.error('Could not add all plugins: ', error); - } -} - -// The host of the remote asset source server. -// The server must be running and accessible from the client. -const ASSET_SOURCE_HOST = 'http://localhost:3000'; - -function addDemoRemoteAssetSourcesPlugins( - cesdk: CreativeEditorSDK -): Promise[] { - if (!ENABLE_DEMO_ASSET_SOURCES) return []; - return [ - '/api/assets/v1/image-pexels', - '/api/assets/v1/image-unsplash', - '/api/assets/v1/video-pexels', - '/api/assets/v1/video-giphy' - ].map(async (baseUrl) => { - await cesdk.unstable_addPlugin( - RemoteAssetSourcePlugin({ - baseUrl: ASSET_SOURCE_HOST + baseUrl - }) - ); - }); -} - -// Helper function that automatically adds asset sources to the respective asset source panels: -// If the source starts with 'ly.img.audio', 'ly.img.image', or 'ly.img.video', it will be added to the respective panel. -// Should be used as a callback for the `entries` property of the `libraries.insert`/`libraries.replace` element in the UI configuration. - -export const prepareAssetEntries = (defaultEntries: any, engine: any) => { - if (!engine) return defaultEntries; - - const assetSourceIds = engine.asset.findAllSources() ?? []; - ['ly.img.audio', 'ly.img.image', 'ly.img.video'].forEach((entryId) => { - const entry = defaultEntries.find((entry: any) => { - return entry.id === entryId; - }); - if (entry) { - const assetSources = assetSourceIds - .filter((sourceId: any) => sourceId.startsWith(entryId + '.')) - .filter((sourceId: any) => !entry.sourceIds.includes(sourceId)); - entry.sourceIds = [...entry.sourceIds, ...assetSources]; - } - }); - return defaultEntries; -}; - -export default addPlugins; diff --git a/examples/web/src/components/CommandPalette.tsx b/examples/web/src/components/CommandPalette.tsx new file mode 100644 index 0000000..63d86a5 --- /dev/null +++ b/examples/web/src/components/CommandPalette.tsx @@ -0,0 +1,105 @@ +import "react-cmdk/dist/cmdk.css"; +import CMDK, { filterItems, getItemIndex } from "react-cmdk"; +import { useState, useEffect } from "react"; + + +const CommandPrefix = "!" +const BlockPrefix = "#" +const PropertyPrefix = "@" + +import { groupBy } from "lodash"; + +// https://github.com/albingroen/react-cmdk +type Params = { items: Array, isOpen: boolean, setIsOpen: (val: boolean) => void } +export const CommandPalette = (params: Params) => { + const [page, _setPage] = useState<"root">("root"); + const [search, setSearch] = useState(CommandPrefix); + const { isOpen, setIsOpen } = params + const { items } = params + + + + useEffect(() => { + function handleKeyDown(e: KeyboardEvent) { + if ( + (navigator?.userAgent?.toLowerCase().includes("mac") + ? e.metaKey + : e.ctrlKey) && + e.key === "k" + ) { + e.preventDefault(); + e.stopPropagation(); + + setIsOpen(!isOpen); + } + } + + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + + // Support prefixes + + let refinedSearch = search + let refinedItems = items + + if (search.startsWith(CommandPrefix)) { + refinedSearch = search.substring(CommandPrefix.length).trim() + refinedItems = items.filter((item) => item.kind === "command") + } + else if (search.startsWith(BlockPrefix)) { + refinedSearch = search.substring(BlockPrefix.length).trim() + refinedItems = items.filter((item) => item.kind === "block") + } + + else if (search.startsWith(PropertyPrefix)) { + refinedSearch = search.substring(PropertyPrefix.length).trim() + refinedItems = items.filter((item) => item.kind === "property") + } else { + refinedItems = items.filter((item) => item.kind === "command") + } + + const grouped = groupBy(refinedItems, "group") + const filteredItems = filterItems(Object.keys(grouped).map((key) => { + return { + heading: key, + id: key, + items: grouped[key] ?? [] + } + }), refinedSearch, { filterOnListHeading: true}); + + return ( + + + {filteredItems.length ? ( + filteredItems.map((list) => ( + + {list.items.map(({ id, ...rest }) => ( + + ))} + + )) + ) : ( + + )} + + + + ); +} + +/// helper + diff --git a/examples/web/src/components/CreativeEditorSDK.tsx b/examples/web/src/components/CreativeEditorSDK.tsx new file mode 100644 index 0000000..35e53e4 --- /dev/null +++ b/examples/web/src/components/CreativeEditorSDK.tsx @@ -0,0 +1,44 @@ +import { useRef, useState, useEffect } from "react"; +import { type Configuration } from "@cesdk/cesdk-js"; +import type CreativeEditorSDK from "@cesdk/cesdk-js"; +import { unflatten } from "../utils/flatten"; + +type Props = { + config: Configuration, callback: (cesdk: CreativeEditorSDK) => Promise +} +export default function CreativeEditorSDKComponent(props: Props) { + const cesdk_container = useRef(null); + + const [_, setCesdk] = useState(); + + useEffect(() => { + if (!cesdk_container.current) return; + + let cleanedUp = false; + let instance: CreativeEditorSDK; + import("@cesdk/cesdk-js") + .then((module) => module.default.create(cesdk_container!.current!, unflatten(props.config))) + .then(async (instance) => { + if (cleanedUp) { + instance.dispose(); + return; + } + setCesdk(instance); + await props.callback(instance); + } + ); + + return () => { + cleanedUp = true; + instance?.dispose(); + setCesdk(undefined); + }; + }, [cesdk_container, props.config]); + + return ( +
+ ); +} diff --git a/examples/web/src/main.tsx b/examples/web/src/main.tsx index e63eef4..c4c5b6d 100644 --- a/examples/web/src/main.tsx +++ b/examples/web/src/main.tsx @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import App from './App.tsx' +import App from './App' ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/examples/web/src/utils/cesdk.ts b/examples/web/src/utils/cesdk.ts new file mode 100644 index 0000000..44df8e1 --- /dev/null +++ b/examples/web/src/utils/cesdk.ts @@ -0,0 +1,18 @@ +import CreativeEditorSDK from "@cesdk/cesdk-js"; + + +export const readPropValue = (cesdk: CreativeEditorSDK, id: number, propKey: string, propType: string) => { + try { + switch (propType.toLowerCase()) { + case "string": return cesdk.engine.block.getString(id, propKey); + case "float": return cesdk.engine.block.getFloat(id, propKey); + case "double": return cesdk.engine.block.getDouble(id, propKey); + case "color": return cesdk.engine.block.getColor(id, propKey); + case "bool": return cesdk.engine.block.getBool(id, propKey); + case "enum": return cesdk.engine.block.getEnum(id, propKey); + } + } catch(e){ + console.warn("Error reading property value: ", e); + } + return undefined; +}; diff --git a/examples/web/src/utils/download.ts b/examples/web/src/utils/download.ts new file mode 100644 index 0000000..5cde074 --- /dev/null +++ b/examples/web/src/utils/download.ts @@ -0,0 +1,29 @@ +import { BlockAPI } from "@cesdk/cesdk-js"; + + +export function downloadBlob(blob: Blob, filename: string) { + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = filename; + link.click(); + URL.revokeObjectURL(url); +} +export const downloadBlocks = (block: BlockAPI, blobs: Blob[], options: { mimeType: string; pages?: number[]; }) => { + const postfix = options.mimeType.split("/")[1]; + const pageIds = options.pages ?? []; + + blobs.forEach((blob, index) => { + const pageId = pageIds[index]; + let pageName = `page-${index}`; + if (pageId) { + const name = block.getName(pageId); + pageName = name?.length ? name : pageName; + } + const filename = `${pageName}.${postfix}`; + downloadBlob(blob, filename); + }); + return Promise.resolve(); +}; + + diff --git a/examples/web/src/utils/flatten.ts b/examples/web/src/utils/flatten.ts new file mode 100644 index 0000000..03dfe56 --- /dev/null +++ b/examples/web/src/utils/flatten.ts @@ -0,0 +1,46 @@ +export function flatten(obj: any, prefix = ''): any { + const flattened = {}; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const propName = prefix ? `${prefix}.${key}` : key; + + if (typeof obj[key] === 'object' && obj[key] !== null) { + Object.assign(flattened, flatten(obj[key], propName)); + } else { + // @ts-ignore + flattened[propName] = obj[key]; + } + } + } + + return flattened; +} + + +export function unflatten(obj: any): any { + const unflattened = {}; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const value = obj[key]; + const keys = key.split('.'); + + let currentObj = unflattened; + for (let i = 0; i < keys.length - 1; i++) { + const nestedKey = keys[i]; + if (!currentObj.hasOwnProperty(nestedKey)) { + // @ts-ignore + currentObj[nestedKey] = {}; + } + // @ts-ignore + currentObj = currentObj[nestedKey]; + } + + // @ts-ignore + currentObj[keys[keys.length - 1]] = value; + } + } + + return unflattened; +} \ No newline at end of file diff --git a/examples/web/vite.config.ts b/examples/web/vite.config.ts index 7fd700f..0129c15 100644 --- a/examples/web/vite.config.ts +++ b/examples/web/vite.config.ts @@ -1,13 +1,25 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; +import { createLogger } from "./vite/logger"; + + // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + build: { + chunkSizeWarningLimit: 4096, + sourcemap: true + }, + worker: { + format: "es" // Default was "iife" but then import.meta.url for importing worker does not worker + }, server: { headers: { "Cross-Origin-Opener-Policy": "same-origin", "Cross-Origin-Embedder-Policy": "require-corp", }, }, + customLogger: createLogger() }); + diff --git a/examples/web/vite/logger.js b/examples/web/vite/logger.js new file mode 100644 index 0000000..7eda5a3 --- /dev/null +++ b/examples/web/vite/logger.js @@ -0,0 +1,14 @@ +import { createLogger as createViteLogger } from "vite"; + + +export const createLogger = () => { + // We create a custom logger in order to filter messages that are persistent + const logger = createViteLogger(); + const originalWarning = logger.warn; + + logger.warn = (msg, options) => { + if (msg.includes('[plugin:vite:resolve]')) return; + originalWarning(msg, options); + }; + return logger; +} \ No newline at end of file diff --git a/package.json b/package.json index 34cbf61..69276d3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "workspaces": [ "packages/*", - "examples/*" + "examples/web" ], "scripts": { "build": "turbo run build", diff --git a/packages/background-removal/LICENSE.md b/packages/plugin-background-removal/LICENSE.md similarity index 100% rename from packages/background-removal/LICENSE.md rename to packages/plugin-background-removal/LICENSE.md diff --git a/packages/background-removal/README.md b/packages/plugin-background-removal/README.md similarity index 100% rename from packages/background-removal/README.md rename to packages/plugin-background-removal/README.md diff --git a/packages/background-removal/esbuild/config.mjs b/packages/plugin-background-removal/esbuild/config.mjs similarity index 100% rename from packages/background-removal/esbuild/config.mjs rename to packages/plugin-background-removal/esbuild/config.mjs diff --git a/packages/background-removal/esbuild/global.d.ts b/packages/plugin-background-removal/esbuild/global.d.ts similarity index 100% rename from packages/background-removal/esbuild/global.d.ts rename to packages/plugin-background-removal/esbuild/global.d.ts diff --git a/packages/background-removal/package.json b/packages/plugin-background-removal/package.json similarity index 100% rename from packages/background-removal/package.json rename to packages/plugin-background-removal/package.json diff --git a/packages/background-removal/scripts/build.mjs b/packages/plugin-background-removal/scripts/build.mjs similarity index 100% rename from packages/background-removal/scripts/build.mjs rename to packages/plugin-background-removal/scripts/build.mjs diff --git a/packages/background-removal/scripts/watch.mjs b/packages/plugin-background-removal/scripts/watch.mjs similarity index 100% rename from packages/background-removal/scripts/watch.mjs rename to packages/plugin-background-removal/scripts/watch.mjs diff --git a/packages/background-removal/src/constants.ts b/packages/plugin-background-removal/src/constants.ts similarity index 100% rename from packages/background-removal/src/constants.ts rename to packages/plugin-background-removal/src/constants.ts diff --git a/packages/background-removal/src/enableFeatures.ts b/packages/plugin-background-removal/src/enableFeatures.ts similarity index 100% rename from packages/background-removal/src/enableFeatures.ts rename to packages/plugin-background-removal/src/enableFeatures.ts diff --git a/packages/background-removal/src/index.ts b/packages/plugin-background-removal/src/index.ts similarity index 100% rename from packages/background-removal/src/index.ts rename to packages/plugin-background-removal/src/index.ts diff --git a/packages/background-removal/src/plugin.ts b/packages/plugin-background-removal/src/plugin.ts similarity index 100% rename from packages/background-removal/src/plugin.ts rename to packages/plugin-background-removal/src/plugin.ts diff --git a/packages/background-removal/src/processBackgroundRemoval.ts b/packages/plugin-background-removal/src/processBackgroundRemoval.ts similarity index 100% rename from packages/background-removal/src/processBackgroundRemoval.ts rename to packages/plugin-background-removal/src/processBackgroundRemoval.ts diff --git a/packages/background-removal/src/registerComponents.ts b/packages/plugin-background-removal/src/registerComponents.ts similarity index 100% rename from packages/background-removal/src/registerComponents.ts rename to packages/plugin-background-removal/src/registerComponents.ts diff --git a/packages/background-removal/src/types.ts b/packages/plugin-background-removal/src/types.ts similarity index 100% rename from packages/background-removal/src/types.ts rename to packages/plugin-background-removal/src/types.ts diff --git a/packages/background-removal/src/utils.ts b/packages/plugin-background-removal/src/utils.ts similarity index 100% rename from packages/background-removal/src/utils.ts rename to packages/plugin-background-removal/src/utils.ts diff --git a/packages/background-removal/tsconfig.json b/packages/plugin-background-removal/tsconfig.json similarity index 100% rename from packages/background-removal/tsconfig.json rename to packages/plugin-background-removal/tsconfig.json diff --git a/packages/background-removal/yarn.lock b/packages/plugin-background-removal/yarn.lock similarity index 100% rename from packages/background-removal/yarn.lock rename to packages/plugin-background-removal/yarn.lock diff --git a/packages/plugin-core/LICENSE.md b/packages/plugin-core/LICENSE.md new file mode 100644 index 0000000..a099036 --- /dev/null +++ b/packages/plugin-core/LICENSE.md @@ -0,0 +1 @@ +TBD diff --git a/packages/plugin-core/README.md b/packages/plugin-core/README.md new file mode 100644 index 0000000..6acc73e --- /dev/null +++ b/packages/plugin-core/README.md @@ -0,0 +1,40 @@ +# IMG.LY CE.SDK Plugin Vectorizer + +This plugin introduces a vectorizer for the CE.SDK editor. + +## Installation + +You can install the plugin via npm or yarn. Use the following commands to install the package: + +``` +yarn add @imgly/plugin-vectorizer +npm install @imgly/plugin-vectorizer +``` + +## Usage + +Adding the plugin to CE.SDK will automatically add a vectorizer +canvas menu entry for every block with an image fill. + +```typescript +import CreativeEditorSDK from '@cesdk/cesdk-js'; +import VectorizerPlugin from '@imgly/plugin-vectorizer'; + +const config = { + license: '', + callbacks: { + // Please note that the vectorizer plugin depends on an correctly + // configured upload. 'local' will work for local testing, but in + // production you will need something stable. Please take a look at: + // https://img.ly/docs/cesdk/ui/guides/upload-images/ + onUpload: 'local' + } +}; + +const cesdk = await CreativeEditorSDK.create(container, config); +await cesdk.addDefaultAssetSources(), + await cesdk.addDemoAssetSources({ sceneMode: 'Design' }), + await cesdk.unstable_addPlugin(VectorizerPlugin()); + +await cesdk.createDesignScene(); +``` diff --git a/packages/plugin-core/STRUCTURE.md b/packages/plugin-core/STRUCTURE.md new file mode 100644 index 0000000..13b1472 --- /dev/null +++ b/packages/plugin-core/STRUCTURE.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/plugin-core/TODO.md b/packages/plugin-core/TODO.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-core/esbuild/config.mjs b/packages/plugin-core/esbuild/config.mjs new file mode 100644 index 0000000..37b437c --- /dev/null +++ b/packages/plugin-core/esbuild/config.mjs @@ -0,0 +1,58 @@ +import chalk from 'chalk'; +import { readFile } from 'fs/promises'; + +// import packageJson from '../package.json' assert { type: 'json' }; +// Avoid the Experimental Feature warning when using the above. +const packageJson = JSON.parse( + await readFile(new URL('../package.json', import.meta.url)) +); + + +const dependencies = Object.keys(packageJson.dependencies) +const peerDependencies = Object.keys(packageJson.peerDependencies) +const externals = [...dependencies, ...peerDependencies] + +console.log( + chalk.yellow('Building version: '), + chalk.green(packageJson.version) +); + +const configs = [ + { + entryPoints: ['src/index.ts', "src/worker.ts"], + define: { + PLUGIN_VERSION: `"${packageJson.version}"` + }, + minify: true, + bundle: true, + sourcemap: true, + external: externals, + platform: 'node', + format: 'esm', + outdir: 'dist', + outExtension: { '.js': '.mjs' }, + plugins: [ + { + name: 'reporter', + setup(build) { + build.onEnd((result) => { + console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] Build ${ + result.errors.length + ? chalk.red('failed') + : chalk.green('succeeded') + }` + ); + }); + } + } + ] + } +]; + +export default configs; diff --git a/packages/remote-asset-source/esbuild/global.d.ts b/packages/plugin-core/esbuild/global.d.ts similarity index 100% rename from packages/remote-asset-source/esbuild/global.d.ts rename to packages/plugin-core/esbuild/global.d.ts diff --git a/packages/plugin-core/manifest.json b/packages/plugin-core/manifest.json new file mode 100644 index 0000000..a218d68 --- /dev/null +++ b/packages/plugin-core/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "pluginapi-polyfill", + "version": "0.0.1", + "publisher": "IMG.LY GmbH", + "icon": null, + "license": "MIT", + "categories": [ + "polyfill" + ], + "contributes": {} +} \ No newline at end of file diff --git a/packages/plugin-core/package.json b/packages/plugin-core/package.json new file mode 100644 index 0000000..84a7ad7 --- /dev/null +++ b/packages/plugin-core/package.json @@ -0,0 +1,66 @@ +{ + "name": "@imgly/plugin-core", + "version": "0.1.0", + "description": "Polyfill for API plugin for the CE.SDK editor", + "keywords": [ + "CE.SDK", + "plugin", + "polyfill" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/imgly/plugins.git" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "IMG.LY GmbH", + "email": "support@img.ly", + "url": "https://img.ly" + }, + "bugs": { + "email": "support@img.ly" + }, + "source": "./src/index.ts", + "module": "./dist/index.mjs", + "types": "./types/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "types": "./types/index.d.ts" + } + }, + "homepage": "https://img.ly", + "files": [ + "LICENSE.md", + "README.md", + "CHANGELOG.md", + "dist/", + "types/", + "bin/" + ], + "scripts": { + "start": "npm run watch", + "clean": "npx rimraf dist && npx rimraf types", + "build": "yarn run types:create && node scripts/build.mjs", + "dev": "yarn run types:create && node scripts/watch.mjs", + "publish:latest": "npm run clean && npm run build && npm publish --tag latest --access public", + "publish:next": "npm run clean && npm run build && npm publish --tag next --access public", + "check:all": "concurrently -n lint,type,pretty \"yarn check:lint\" \"yarn check:type\" \"yarn check:pretty\"", + "check:lint": "eslint --max-warnings 0 './src/**/*.{ts,tsx}'", + "check:pretty": "prettier --list-different './src/**/*.{ts,tsx}'", + "check:type": "tsc --noEmit", + "types:create": "tsc --emitDeclarationOnly" + }, + "devDependencies": { + "chalk": "^5.3.0", + "concurrently": "^8.2.2", + "esbuild": "^0.19.11", + "eslint": "^8.51.0", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "@cesdk/cesdk-js": "~1.21.0" + }, + "dependencies": { + } +} diff --git a/packages/remote-asset-source/scripts/build.mjs b/packages/plugin-core/scripts/build.mjs similarity index 100% rename from packages/remote-asset-source/scripts/build.mjs rename to packages/plugin-core/scripts/build.mjs diff --git a/packages/remote-asset-source/scripts/watch.mjs b/packages/plugin-core/scripts/watch.mjs similarity index 100% rename from packages/remote-asset-source/scripts/watch.mjs rename to packages/plugin-core/scripts/watch.mjs diff --git a/packages/plugin-core/src/index.ts b/packages/plugin-core/src/index.ts new file mode 100644 index 0000000..c82128a --- /dev/null +++ b/packages/plugin-core/src/index.ts @@ -0,0 +1,7 @@ +import { PluginContext } from "./plugin/PluginContext" + +export { Commands, type CommandCallback, type CommandDescription } from "./plugin/Commands" +export { I18N } from "./plugin/I18n" +export { type Logger } from "./plugin/Logger" +export { PluginContext } from "./plugin/PluginContext" + diff --git a/packages/plugin-core/src/plugin/Commands.ts b/packages/plugin-core/src/plugin/Commands.ts new file mode 100644 index 0000000..dbf73d8 --- /dev/null +++ b/packages/plugin-core/src/plugin/Commands.ts @@ -0,0 +1,65 @@ +import { PluginContext } from './PluginContext'; +import { Subscribable } from './Subscribable'; + +export type CommandCallback = (ctx: PluginContext, params: any) => Promise | any; +export type CommandArgs = { blockIds?: number[] } + +export type CommandEvents = "register" | "unregister" + +export type CommandDescription = { + id?: string, + category?: string + args?: any, //JSONSchema + returns?: any // JSONSchema +} + +export class Commands extends Subscribable { + #entries = new Map() + #descs = new Map() + #ctx: PluginContext; + + constructor(ctx: PluginContext) { + super() + this.#ctx = ctx + } + + listCommands() { + return Array.from(this.#entries.keys()); + } + + registerCommand(label: string, callback: CommandCallback, description: CommandDescription) { + this.#entries.set(label, callback); + this.#descs.set(label, description || {}); + this.notify("register", label) + return () => this.unregisterCommand(label) + } + + unregisterCommand(label: string) { + this.notify("unregister", label) + this.#entries.delete(label); + this.#descs.delete(label); + } + + getCommandCallback(label: string) { + return this.#entries.get(label); + } + getCommandDescription(label: string) { + return this.#descs.get(label); + } + + + async executeCommand

(cmd: string, params: P): Promise { + + const command = this.#entries.get(cmd); + if (command) { + + // this.#ctx.ui?.showNotification({ message: `Running command: ${cmd}`, type: "info" }) + return await command(this.#ctx, params); + } else { + // this.#ctx.ui?.showNotification({ message: `Command not found: ${cmd}`, type: "info" }) + } + } +} + + + diff --git a/packages/plugin-core/src/plugin/I18n.ts b/packages/plugin-core/src/plugin/I18n.ts new file mode 100644 index 0000000..e0681f7 --- /dev/null +++ b/packages/plugin-core/src/plugin/I18n.ts @@ -0,0 +1,62 @@ +import { PluginContext } from './PluginContext'; +import { Subscribable } from './Subscribable'; + + +import { merge } from 'lodash'; +import { flatten } from '../utils/flatten'; + +type Translation = Record +type Translations = { [locale: string]: Translation; } + +export class I18N extends Subscribable<"register", Translations> { + #translations: any = {}; + #locale: string = navigator.language ?? "en"; + #ctx: PluginContext + + + constructor(ctx: PluginContext) { + super() + this.#ctx = ctx + } + + setTranslations(translations: Translations) { + this.#translations = merge(this.#translations, flatten(translations)); + this.notify("register", translations) + } + + translate(key: K, fallback: string | undefined = undefined) { + const translation = this.findTranslation(key, this.#locale) + if (!translation) { + this.#ctx.logger?.warn(`Translation in "${this.#locale}" for key ${key as string} not found!`); + } + return translation ?? fallback ?? key; + } + + findTranslation(key: K, language?: string) { + const [lang, region] = this.#locale.split('-'); + const langLookup = lang.concat('.', key as string); + const langAndRegionLookup = lang.concat('.', key as string); + return this.#translations[langAndRegionLookup] || this.#translations[langLookup] + } + + hasTranslation(key: K, language?: string): boolean { + const locale = language ?? this.#locale; + const lookup = locale.concat('.', key as string); + return !!this.findTranslation(key, language) + } + + setLocale(locale: string) { + this.#locale = locale; + } + locale() { + return this.#locale; + } + + locales() { + return navigator.languages + } + t = this.translate.bind(this) +} + + +export type I18NType = { i18n?: I18N } diff --git a/packages/plugin-core/src/plugin/Logger.ts b/packages/plugin-core/src/plugin/Logger.ts new file mode 100644 index 0000000..03cfdd4 --- /dev/null +++ b/packages/plugin-core/src/plugin/Logger.ts @@ -0,0 +1,9 @@ +export interface Logger { + log: (message: string) => void , + trace: (message: string) => void + debug: (message: string) => void, + info: (message: string) => void, + warn: (message: string) => void, + error: (message: string) => void, + + } \ No newline at end of file diff --git a/packages/plugin-core/src/plugin/PluginContext.ts b/packages/plugin-core/src/plugin/PluginContext.ts new file mode 100644 index 0000000..f8230c2 --- /dev/null +++ b/packages/plugin-core/src/plugin/PluginContext.ts @@ -0,0 +1,45 @@ +import { type CreativeEngine } from "@cesdk/cesdk-js"; +import CreativeEditorSDK from "@cesdk/cesdk-js"; +import { Logger } from "./Logger"; + +import { Commands } from "./Commands"; +import { I18N } from "./I18n"; + +// this is not exposed yet +type UserInterfaceAPI = typeof CreativeEditorSDK.prototype.ui; +type FeatureAPI = typeof CreativeEditorSDK.prototype.feature; + + + +type I18NContributions = { + [key: string]: string +} +type ManifestContributions = { + i18n?: I18NContributions +} +type Manifest = { + contributes: ManifestContributions +} + + +export class PluginContext { + logger?: Logger; + engine: CreativeEngine; + ui?: UserInterfaceAPI; + i18n: I18N; + commands: Commands; + feature: FeatureAPI; + constructor(cesdk: CreativeEditorSDK) { + this.engine = cesdk.engine; + this.ui = cesdk.ui; + this.i18n = new I18N(this as PluginContext) + this.commands = new Commands(this as PluginContext) + this.feature = cesdk.feature; + const _unsubscribe = this.i18n.subscribe("register", (translations) => { + cesdk.setTranslations(translations); + } ) + + } + +}; + diff --git a/packages/plugin-core/src/plugin/Subscribable.ts b/packages/plugin-core/src/plugin/Subscribable.ts new file mode 100644 index 0000000..cab0333 --- /dev/null +++ b/packages/plugin-core/src/plugin/Subscribable.ts @@ -0,0 +1,24 @@ + +export class Subscribable { + #subscribers: Array<{ filter: E[], callback: (event: D) => void }> = [] + + subscribe(toEvent: E, callback: (label: D) => void): () => void { + const entry = { filter: [toEvent], callback } + this.#subscribers.push(entry); + return () => { + const idx = this.#subscribers.indexOf(entry); + if (idx > -1) { + this.#subscribers.splice(idx, 1); + } + } + } + + notify(event: E, data: D) { + this.#subscribers.forEach(({ filter, callback }) => { + if (filter.includes(event)) { + callback(data); + } + }) + } + +} \ No newline at end of file diff --git a/packages/plugin-core/src/utils/flatten.ts b/packages/plugin-core/src/utils/flatten.ts new file mode 100644 index 0000000..03dfe56 --- /dev/null +++ b/packages/plugin-core/src/utils/flatten.ts @@ -0,0 +1,46 @@ +export function flatten(obj: any, prefix = ''): any { + const flattened = {}; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const propName = prefix ? `${prefix}.${key}` : key; + + if (typeof obj[key] === 'object' && obj[key] !== null) { + Object.assign(flattened, flatten(obj[key], propName)); + } else { + // @ts-ignore + flattened[propName] = obj[key]; + } + } + } + + return flattened; +} + + +export function unflatten(obj: any): any { + const unflattened = {}; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const value = obj[key]; + const keys = key.split('.'); + + let currentObj = unflattened; + for (let i = 0; i < keys.length - 1; i++) { + const nestedKey = keys[i]; + if (!currentObj.hasOwnProperty(nestedKey)) { + // @ts-ignore + currentObj[nestedKey] = {}; + } + // @ts-ignore + currentObj = currentObj[nestedKey]; + } + + // @ts-ignore + currentObj[keys[keys.length - 1]] = value; + } + } + + return unflattened; +} \ No newline at end of file diff --git a/packages/plugin-core/src/worker.ts b/packages/plugin-core/src/worker.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-core/tsconfig.json b/packages/plugin-core/tsconfig.json new file mode 100644 index 0000000..07e826a --- /dev/null +++ b/packages/plugin-core/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es2017", + "module": "es2020", + "lib": ["es2018", "dom"], + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "declaration": true, + "declarationDir": "types/", + "skipLibCheck": true + }, + "include": ["src/**/*", "esbuild/global.d.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/plugin-core/types/index.d.ts b/packages/plugin-core/types/index.d.ts new file mode 100644 index 0000000..7588cca --- /dev/null +++ b/packages/plugin-core/types/index.d.ts @@ -0,0 +1,4 @@ +export { Commands, type CommandCallback, type CommandDescription } from "./plugin/Commands"; +export { I18N } from "./plugin/I18n"; +export { type Logger } from "./plugin/Logger"; +export { PluginContext } from "./plugin/PluginContext"; diff --git a/packages/plugin-core/types/manifest.d.ts b/packages/plugin-core/types/manifest.d.ts new file mode 100644 index 0000000..e1ead83 --- /dev/null +++ b/packages/plugin-core/types/manifest.d.ts @@ -0,0 +1,4 @@ +declare const _default: { + id: string; +}; +export default _default; diff --git a/packages/plugin-core/types/plugin/Commands.d.ts b/packages/plugin-core/types/plugin/Commands.d.ts new file mode 100644 index 0000000..89cc3e0 --- /dev/null +++ b/packages/plugin-core/types/plugin/Commands.d.ts @@ -0,0 +1,23 @@ +import { PluginContext } from './PluginContext'; +import { Subscribable } from './Subscribable'; +export type CommandCallback = (ctx: PluginContext, params: any) => Promise | any; +export type CommandArgs = { + blockIds?: number[]; +}; +export type CommandEvents = "register" | "unregister"; +export type CommandDescription = { + id?: string; + category?: string; + args?: any; + returns?: any; +}; +export declare class Commands extends Subscribable { + #private; + constructor(ctx: PluginContext); + listCommands(): string[]; + registerCommand(label: string, callback: CommandCallback, description: CommandDescription): () => void; + unregisterCommand(label: string): void; + getCommandCallback(label: string): CommandCallback | undefined; + getCommandDescription(label: string): CommandDescription | undefined; + executeCommand

(cmd: string, params: P): Promise; +} diff --git a/packages/plugin-core/types/plugin/I18n.d.ts b/packages/plugin-core/types/plugin/I18n.d.ts new file mode 100644 index 0000000..ba0b245 --- /dev/null +++ b/packages/plugin-core/types/plugin/I18n.d.ts @@ -0,0 +1,22 @@ +import { PluginContext } from './PluginContext'; +import { Subscribable } from './Subscribable'; +type Translation = Record; +type Translations = { + [locale: string]: Translation; +}; +export declare class I18N extends Subscribable<"register", Translations> { + #private; + constructor(ctx: PluginContext); + setTranslations(translations: Translations): void; + translate(key: K, fallback?: string | undefined): any; + findTranslation(key: K, language?: string): any; + hasTranslation(key: K, language?: string): boolean; + setLocale(locale: string): void; + locale(): string; + locales(): readonly string[]; + t: (key: K, fallback?: string | undefined) => any; +} +export type I18NType = { + i18n?: I18N; +}; +export {}; diff --git a/packages/plugin-core/types/plugin/Logger.d.ts b/packages/plugin-core/types/plugin/Logger.d.ts new file mode 100644 index 0000000..27f1a10 --- /dev/null +++ b/packages/plugin-core/types/plugin/Logger.d.ts @@ -0,0 +1,8 @@ +export interface Logger { + log: (message: string) => void; + trace: (message: string) => void; + debug: (message: string) => void; + info: (message: string) => void; + warn: (message: string) => void; + error: (message: string) => void; +} diff --git a/packages/plugin-core/types/plugin/PluginContext.d.ts b/packages/plugin-core/types/plugin/PluginContext.d.ts new file mode 100644 index 0000000..5ea39f2 --- /dev/null +++ b/packages/plugin-core/types/plugin/PluginContext.d.ts @@ -0,0 +1,17 @@ +import { type CreativeEngine } from "@cesdk/cesdk-js"; +import CreativeEditorSDK from "@cesdk/cesdk-js"; +import { Logger } from "./Logger"; +import { Commands } from "./Commands"; +import { I18N } from "./I18n"; +type UserInterfaceAPI = typeof CreativeEditorSDK.prototype.ui; +type FeatureAPI = typeof CreativeEditorSDK.prototype.feature; +export declare class PluginContext { + logger?: Logger; + engine: CreativeEngine; + ui?: UserInterfaceAPI; + i18n: I18N; + commands: Commands; + feature: FeatureAPI; + constructor(cesdk: CreativeEditorSDK); +} +export {}; diff --git a/packages/plugin-core/types/plugin/Subscribable.d.ts b/packages/plugin-core/types/plugin/Subscribable.d.ts new file mode 100644 index 0000000..12aefba --- /dev/null +++ b/packages/plugin-core/types/plugin/Subscribable.d.ts @@ -0,0 +1,5 @@ +export declare class Subscribable { + #private; + subscribe(toEvent: E, callback: (label: D) => void): () => void; + notify(event: E, data: D): void; +} diff --git a/packages/plugin-core/types/utils/flatten.d.ts b/packages/plugin-core/types/utils/flatten.d.ts new file mode 100644 index 0000000..f9433a9 --- /dev/null +++ b/packages/plugin-core/types/utils/flatten.d.ts @@ -0,0 +1,2 @@ +export declare function flatten(obj: any, prefix?: string): any; +export declare function unflatten(obj: any): any; diff --git a/packages/plugin-core/types/worker.d.ts b/packages/plugin-core/types/worker.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-design-essentials/.gitignore b/packages/plugin-design-essentials/.gitignore new file mode 100644 index 0000000..9060c20 --- /dev/null +++ b/packages/plugin-design-essentials/.gitignore @@ -0,0 +1,11 @@ +node_modules +packages/*/dist +examples/*/dist +.env.local + +.DS_Store +yarn-error.log + +.turbo +.vercel +types \ No newline at end of file diff --git a/packages/plugin-design-essentials/esbuild/config.mjs b/packages/plugin-design-essentials/esbuild/config.mjs new file mode 100644 index 0000000..37b437c --- /dev/null +++ b/packages/plugin-design-essentials/esbuild/config.mjs @@ -0,0 +1,58 @@ +import chalk from 'chalk'; +import { readFile } from 'fs/promises'; + +// import packageJson from '../package.json' assert { type: 'json' }; +// Avoid the Experimental Feature warning when using the above. +const packageJson = JSON.parse( + await readFile(new URL('../package.json', import.meta.url)) +); + + +const dependencies = Object.keys(packageJson.dependencies) +const peerDependencies = Object.keys(packageJson.peerDependencies) +const externals = [...dependencies, ...peerDependencies] + +console.log( + chalk.yellow('Building version: '), + chalk.green(packageJson.version) +); + +const configs = [ + { + entryPoints: ['src/index.ts', "src/worker.ts"], + define: { + PLUGIN_VERSION: `"${packageJson.version}"` + }, + minify: true, + bundle: true, + sourcemap: true, + external: externals, + platform: 'node', + format: 'esm', + outdir: 'dist', + outExtension: { '.js': '.mjs' }, + plugins: [ + { + name: 'reporter', + setup(build) { + build.onEnd((result) => { + console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] Build ${ + result.errors.length + ? chalk.red('failed') + : chalk.green('succeeded') + }` + ); + }); + } + } + ] + } +]; + +export default configs; diff --git a/packages/plugin-design-essentials/esbuild/global.d.ts b/packages/plugin-design-essentials/esbuild/global.d.ts new file mode 100644 index 0000000..de80fd8 --- /dev/null +++ b/packages/plugin-design-essentials/esbuild/global.d.ts @@ -0,0 +1,3 @@ +// These constants here are added by the base esbuild config + +declare const PLUGIN_VERSION: string; diff --git a/packages/plugin-design-essentials/manifest.json b/packages/plugin-design-essentials/manifest.json new file mode 100644 index 0000000..2c550fa --- /dev/null +++ b/packages/plugin-design-essentials/manifest.json @@ -0,0 +1,83 @@ +{ + "id": "design-batteries", + "version": "1.0.0", + "publisher": "IMG.LY GmbH", + "icon": null, + "categories": [], + "contributes": { + "commands": { + "blockDelete": { + "category": "block" + }, + "blockDuplicate": { + "category": "block" + }, + "blockGroup": { + "category": "block" + }, + "blockUngroup": { + "category": "block" + }, + "exportComponentToFile": { + "category": "export" + }, + "exportJsonToClipboard": { + "category": "export" + }, + "exportJsonToFile": { + "category": "export" + }, + "exportJpegToFile": { + "category": "export" + }, + "exportPdfToFile": { + "category": "export" + }, + "exportPngToClipboard": { + "category": "export" + }, + "exportPngToFile": { + "category": "export" + }, + "exportRgba8ToFile": { + "category": "export" + }, + "exportSceneToClipboard": { + "category": "export" + }, + "exportSceneToFile": { + "category": "export" + }, + "exportWebpToFile": { + "category": "export" + }, + "imageFitModeContain": { + "category": "image" + }, + "imageFitModeCover": { + "category": "image" + }, + "imageFitModeCrop": { + "category": "image" + }, + "layoutHorizontally": { + "category": "layout" + }, + "layoutMasonry": { + "category": "layout" + }, + "layoutVertically": { + "category": "layout" + }, + "playground": { + "category": "playground" + }, + "productSetInstagram": { + "category": "product" + }, + "syncBlockAppearance": { + "category": "sync" + } + } + } +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/package.json b/packages/plugin-design-essentials/package.json new file mode 100644 index 0000000..c034b02 --- /dev/null +++ b/packages/plugin-design-essentials/package.json @@ -0,0 +1,69 @@ +{ + "name": "@imgly/plugin-design-essentials", + "version": "0.1.0", + "description": "Vectorizer plugin for the CE.SDK editor", + "keywords": [ + "CE.SDK", + "plugin", + "svg", + "vectorizer" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/imgly/plugins.git" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "IMG.LY GmbH", + "email": "support@img.ly", + "url": "https://img.ly" + }, + "bugs": { + "email": "support@img.ly" + }, + "source": "./src/index.ts", + "module": "./dist/index.mjs", + "types": "./types/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "types": "./types/index.d.ts" + } + }, + "homepage": "https://img.ly", + "files": [ + "LICENSE.md", + "README.md", + "CHANGELOG.md", + "dist/", + "types/", + "bin/" + ], + "scripts": { + "start": "npm run watch", + "clean": "npx rimraf dist && npx rimraf types", + "build": "yarn run clean && yarn run types:create && node scripts/build.mjs", + "dev": "yarn run types:create && node scripts/watch.mjs", + "publish:latest": "npm run clean && npm run build && npm publish --tag latest --access public", + "publish:next": "npm run clean && npm run build && npm publish --tag next --access public", + "check:all": "concurrently -n lint,type,pretty \"yarn check:lint\" \"yarn check:type\" \"yarn check:pretty\"", + "check:lint": "eslint --max-warnings 0 './src/**/*.{ts,tsx}'", + "check:pretty": "prettier --list-different './src/**/*.{ts,tsx}'", + "check:type": "tsc --noEmit", + "types:create": "tsc --emitDeclarationOnly" + }, + "devDependencies": { + "chalk": "^5.3.0", + "concurrently": "^8.2.2", + "esbuild": "^0.19.11", + "eslint": "^8.51.0", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "@cesdk/cesdk-js": "~1.21.0" + }, + "dependencies": { + "@imgly/plugin-core": "*", + "lodash": "^4.17.21" + } +} diff --git a/packages/plugin-design-essentials/scripts/build.mjs b/packages/plugin-design-essentials/scripts/build.mjs new file mode 100644 index 0000000..13d12e1 --- /dev/null +++ b/packages/plugin-design-essentials/scripts/build.mjs @@ -0,0 +1,5 @@ +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +await Promise.all(configs.map(async (config) => await esbuild.build(config))); diff --git a/packages/plugin-design-essentials/scripts/watch.mjs b/packages/plugin-design-essentials/scripts/watch.mjs new file mode 100644 index 0000000..15dbb21 --- /dev/null +++ b/packages/plugin-design-essentials/scripts/watch.mjs @@ -0,0 +1,19 @@ +import chalk from 'chalk'; +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] ${chalk.green('Watching...')}` +); + +const contexts = await Promise.all( + configs.map((config) => esbuild.context(config)) +); + +await Promise.any(contexts.map((ctx) => ctx.watch())); diff --git a/packages/plugin-design-essentials/src/PluginManifest.ts b/packages/plugin-design-essentials/src/PluginManifest.ts new file mode 100644 index 0000000..4eb5576 --- /dev/null +++ b/packages/plugin-design-essentials/src/PluginManifest.ts @@ -0,0 +1,10 @@ +import Manifest from '../manifest.json'; +import { CommandCallback } from '../../plugin-core/types'; + + +export type Contributions = typeof Manifest;["contributes"] +export type CommandContributions = keyof typeof Manifest["contributes"]["commands"] +export type CommandImports = Record + +export const PluginManifest = Manifest + diff --git a/packages/plugin-design-essentials/src/commands/block.ts b/packages/plugin-design-essentials/src/commands/block.ts new file mode 100644 index 0000000..63663b4 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/block.ts @@ -0,0 +1,119 @@ +import { PluginContext } from "@imgly/plugin-core"; +import { setTransform } from "../utils/setTransform"; +import { createDefaultBlockByType } from "../utils/createDefaultBlockByType"; + + +export const blockDelete = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + ctx.engine.block.isValid(id) && ctx.engine.block.destroy(id) + }); +} + +export const blockDuplicate = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.isValid(id); + const newBlock = block.duplicate(id); + const parent = block.getParent(id); + if (parent && block.isValid(parent)) { + block.appendChild(parent, newBlock); + } + block.setSelected(newBlock, true); // should return the previous state + block.setSelected(id, false); + + }); +} + + +export const blockRename = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.isValid(id); + const name = block.getName(id) + const newName = prompt("Block name", name); + if (newName) { + block.setName(id, newName); + } + }); +} +export const blockBringForward = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.bringForward(id); + }); +} + +export const blockSendBackward = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.sendBackward(id); + }); +} + +export const blockBringToFront = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.bringToFront(id); + }); +} + +export const blockSendToBack = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + blockIds.forEach((id: number) => { + block.sendToBack(id); + }) +} + + +export const blockCreateGraphic = async (ctx: PluginContext, _params: { blockIds?: number[] }) => { + + const { block, scene } = ctx.engine; + // const { blockIds = block.findAllSelected() } = params; + const setTransform = (blockId: number, transform: any) => { + const { x, y, width, height } = transform + x && block.setPositionX(bId, x) + y && block.setPositionY(bId, y) + width && block.setWidth(bId, width) + height && block.setHeight(bId, height) + } + const pId = scene.getCurrentPage() ?? scene.get()! + + const bId = createDefaultBlockByType(ctx, "graphic") + const width = block.getFrameWidth(pId) / 2.0 + const height = block.getFrameHeight(pId) / 2.0 + const x = width - width / 2.0 + const y = height - height / 2.0 + setTransform(bId, { x, y, width, height }) + block.appendChild(pId, bId); + block.setSelected(bId, true) +} + + +export const blockCreateText = async (ctx: PluginContext, _params: { blockIds?: number[] }) => { + const { block, scene } = ctx.engine; + // const { blockIds = block.findAllSelected() } = params; + + const pId = scene.getCurrentPage() ?? scene.get()! + + const bId = createDefaultBlockByType(ctx, "text") + + const width = block.getFrameWidth(pId) / 2.0 + const height = block.getFrameHeight(pId) / 2.0 + const x = width - width / 2.0 + const y = height - height / 2.0 + setTransform(ctx, bId, { x, y, width, height }) + block.appendChild(pId, bId); + block.setSelected(bId, true) +} + + + + diff --git a/packages/plugin-design-essentials/src/commands/components.ts b/packages/plugin-design-essentials/src/commands/components.ts new file mode 100644 index 0000000..7b47648 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/components.ts @@ -0,0 +1,85 @@ +import { MimeType } from "@cesdk/cesdk-js"; +import { PluginContext } from "../../../plugin-core/types"; +import { downloadBlob, loadAsBlob } from "../utils/download"; + +import { inferBlockName } from "../utils/computeBlockName"; +import { exportBlockAs } from "../utils/exportBlockAs"; + +export const exportComponentToFile = async (ctx: PluginContext, params: { blockIds?: number[]; }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + const componentData = await Promise.all(blockIds.map(async (bId) => { + + const thumbnail = await exportBlockAs(ctx, { blockIds: [bId], mimeType: "image/png" as MimeType, width: 256, height: 256 }); + const cesdk = await exportBlockAs(ctx, { blockIds: [bId], mimeType: "application/x-cesdk" }); + return { + thumbnail: thumbnail[0], + cesdk: cesdk[0], + + // zip: zip[0], + }; + })); + + componentData.forEach((data, index) => { + const blockId = blockIds[index]; + const filename = inferBlockName(ctx.engine.block, blockId); + downloadBlob(data.thumbnail, `${filename}.png`); + downloadBlob(data.cesdk, `${filename}.cesdk`); + }); +}; + +export const importComponent = async (ctx: PluginContext, _params: { blockIds?: number[]; }) => { + const { engine } = ctx; + const { scene, block } = engine; + + const data = await loadAsBlob(); + const str = await data.text(); + const bIds = await ctx.engine.block.loadFromString(str); + + const pId = scene.getCurrentPage()!; + bIds.forEach((bId) => { + const name = ctx.engine.block.getName(bId) || ctx.engine.block.getUUID(bId); + const type = ctx.engine.block.getType(bId); + const isGroup = type === "//ly.img.ubq/group"; + console.log("Inserting Block", name); + console.log("Block Type", type); + if (isGroup) { // // ugly workaround for groups after loading. How does duplicate work? + const childIds = block.getChildren(bId); + block.ungroup(bId) + childIds.forEach((childId) => { + block.appendChild(pId, childId); + }) + block.group(childIds); + } else{ + block.appendChild(pId, bId); + } + }); + + + + + +}; +export const exportComponentLibrary = async (ctx: PluginContext, _params: { blockIds?: number[]; }) => { + const { block } = ctx.engine; + const libs = block.findByType("//ly.img.ubq/page"); + + libs.forEach(async (pId) => { + const pName = block.getName(pId) || block.getUUID(pId); + const bIds = block.getChildren(pId); + bIds.forEach(async (bId) => { + const bName = block.getName(bId) || block.getUUID(bId); + const thumbnail = await exportBlockAs(ctx, { blockIds: [bId], mimeType: "image/png" as MimeType, width: 256, height: 256 }); + const cesdk = await exportBlockAs(ctx, { blockIds: [bId], mimeType: "application/x-cesdk" }); + const filename = `${pName}-${bName}`; + downloadBlob(thumbnail[0], `${filename}.png`); + downloadBlob(cesdk[0], `${filename}.cesdk`); + }); + }); + + +}; + + + diff --git a/packages/plugin-design-essentials/src/commands/container.ts b/packages/plugin-design-essentials/src/commands/container.ts new file mode 100644 index 0000000..7a980e3 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/container.ts @@ -0,0 +1,32 @@ +import { PluginContext } from "../../../plugin-core/types"; + + +export const blockGroup = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { + blockIds = block.findAllSelected(), + } = params; + if (blockIds.length < 1) return; + + const group = block.group(blockIds); + blockIds.forEach((id: number) => block.isSelected(id) && block.setSelected(id, false)); + block.setSelected(group, true); +} + + +export const blockUngroup = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + + const { block } = ctx.engine; + const { + blockIds = block.findAllSelected(), + } = params; + if (blockIds.length !== 1) return; + + const blockId = blockIds[0]; + const isSelected = block.isSelected(blockId); + if (block.getType(blockId) !== '//ly.img.ubq/group') return; + const childIds = block.getChildren(blockId); + block.ungroup(blockId); // Note – ungroup should return the IDs + childIds.forEach((id: number) => block.setSelected(id, isSelected)); +} + diff --git a/packages/plugin-design-essentials/src/commands/debug.ts b/packages/plugin-design-essentials/src/commands/debug.ts new file mode 100644 index 0000000..68143fc --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/debug.ts @@ -0,0 +1,161 @@ +import { PluginContext } from "@imgly/plugin-core"; +import { readBlockProperty } from "../utils/cesdk"; + + +export const debugLogBlockProperties = async (ctx: PluginContext, params: { blockIds: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((bId: number) => { + const props = block.findAllProperties(bId) + const propDefinition = new Map() + props.forEach((propKey: string) => { + if (!block.isPropertyReadable(propKey)) return; + const propType = block.getPropertyType(propKey) + const propValue = readBlockProperty(block, bId, propKey, propType) + propDefinition.set(propKey, propValue) + }) + console.debug("Properties for block", bId, JSON.stringify(Object.fromEntries(propDefinition.entries()), null, 2)) + }) +} + + + +export const debugLogBlockCrop = (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((id: number) => { + const x = block.getCropTranslationX(id) + const y = block.getCropTranslationY(id) + const scaleX = block.getCropScaleX(id) + const scaleY = block.getCropScaleY(id) + const fillMode = block.getContentFillMode(id) + const crop = { + x, y, scaleX, scaleY, fillMode + } + console.debug("Crop for block", id, JSON.stringify(crop, null, 2)) + }); + +} + +export const debugLogBlockMetadata = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + + blockIds.forEach((id: number) => { + const keys = block.findAllMetadata(id) + if (keys.length === 0) { + console.debug("No metadata for block", id) + return + } + const map = new Map() + keys.forEach((key: string) => { + const metadata = block.getMetadata(id, key) + const obj = JSON.parse(metadata) + map.set(key, obj) + }) + console.debug("Metadata for block", id, JSON.stringify(Object.fromEntries(map.entries()), null, 2)) + }) + +} + +export const debugLogBlockFill = (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((bId: number) => { + const fId = block.getFill(bId) + const fillType = block.getType(fId) + + const props = block.findAllProperties(fId); + + const propDefinition = new Map() + props.forEach((propKey: string) => { + + if (!block.isPropertyReadable(propKey)) return; + const propValue = readBlockProperty(block, fId, propKey) + propDefinition.set(propKey, propValue) + }) + console.debug("Fill for block", bId, JSON.stringify(Object.fromEntries(propDefinition.entries()), null, 2)) + }); +} + +export const debugLogBlockEffects = (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((bId: number) => { + const eIds = block.getEffects(bId) + + eIds.forEach((eId: number) => { + const props = block.findAllProperties(eId); + + const propDefinition = new Map() + props.forEach((propKey: string) => { + + if (!block.isPropertyReadable(propKey)) return; + const propValue = readBlockProperty(block, eId, propKey) + propDefinition.set(propKey, propValue) + }) + console.debug(`Effects ${eId} for block`, bId, JSON.stringify(Object.fromEntries(propDefinition.entries()), null, 2)) + }) + + + }); +} + + + +export const debugLogBlockBlur = (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((bId: number) => { + if (!block.hasBlur(bId)) { + console.log("No blur for block", bId) + return + }; + const eId = block.getBlur(bId) + if (!block.isValid(eId)) { // that is an error source + console.log("No valid blur for block", bId) + return + }; + + const props = block.findAllProperties(eId); + + const propDefinition = new Map() + props.forEach((propKey: string) => { + + if (!block.isPropertyReadable(propKey)) return; + const propValue = readBlockProperty(block, eId, propKey) + propDefinition.set(propKey, propValue) + + + }) + console.debug(`Blur for block`, bId, JSON.stringify(Object.fromEntries(propDefinition.entries()), null, 2)) + + }); +} + +export const debugLogSceneHierarchy = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block, scene } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + const sId = scene.get()! + + const blockInfo = (bId: number) => { + const name = block.getName(bId) || block.getUUID(bId).toString() + const type = block.getType(bId) + const cIds = block.getChildren(bId) + const children = cIds.map(blockInfo) + const hierarchy = {name, type, id: bId, children} + return hierarchy + } + + const hierarchy = blockInfo(sId); + console.debug("Scene Hierarchy", JSON.stringify(hierarchy, null, 2)) + + + +} diff --git a/packages/plugin-design-essentials/src/commands/export.ts b/packages/plugin-design-essentials/src/commands/export.ts new file mode 100644 index 0000000..fe0abd8 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/export.ts @@ -0,0 +1,74 @@ +import { PluginContext } from "../../../plugin-core/types"; +import { MimeType } from "@cesdk/cesdk-js"; +import { downloadBlob } from "../utils/download"; +import { exportBlockAs } from "../utils/exportBlockAs"; + + + + +export const exportPngToClipboard = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "image/png" as MimeType })).map((blob) => { + return new ClipboardItem({ + ["image/png"]: blob, + }, { presentationStyle: "attachment" }); + }) + await navigator.clipboard.write(items); +}; + +export const exportSceneToClipboard = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/x-cesdk" })).map((blob) => { + return new ClipboardItem({ + ["text/plain"]: blob, + }, { presentationStyle: "attachment" }); + }) + await navigator.clipboard.write(items); +}; + +export const exportJsonToClipboard = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/json" })).map((blob) => { + return new ClipboardItem({ + ["text/plain"]: blob, + }, { presentationStyle: "attachment" }); + }) + await navigator.clipboard.write(items); +}; + +export const exportPngToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "image/png" as MimeType })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.png`) }); +} + +export const exportJpegToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "image/jpeg" as MimeType })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.jpeg`) }); +} + +export const exportWebpToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "image/webp" as MimeType })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.webp`) }); +} + +export const exportPdfToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/pdf" as MimeType })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.pdf`) }); +} + + +export const exportRgba8ToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/octet-stream" as MimeType })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.rgba8`) }); +} + + +export const exportSceneToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/x-cesdk" })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.cesdk`) }); +} + + +export const exportJsonToFile = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const items = (await exportBlockAs(ctx, { ...params, mimeType: "application/json" })) + items.forEach((blob, index) => { downloadBlob(blob, `block-${index}.json`) }); +} + + diff --git a/packages/plugin-design-essentials/src/commands/i18n.ts b/packages/plugin-design-essentials/src/commands/i18n.ts new file mode 100644 index 0000000..86d43f2 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/i18n.ts @@ -0,0 +1,21 @@ + +import { downloadBlob } from "../utils/download"; +import { PluginContext } from "../../../plugin-core/types"; // Add this import statement + +export const i18nDownloadMissingCommandTranslations = (ctx: PluginContext) => { + const { i18n, commands } = ctx; + + const missingCommandTranslations: [string, string][] = commands + .listCommands() + .map((cmd: string): [string, string] | null => { + return i18n.hasTranslation(cmd) ? null : [cmd, cmd.split(".").pop()]; + }) + .filter(Boolean) as [string, string][]; + + if (missingCommandTranslations.length > 0) { + const ob = Object.fromEntries(missingCommandTranslations); + const json = JSON.stringify(ob, null, 2); + const blob = new Blob([json], { type: "application/json" }); + downloadBlob(blob, `${i18n.locale()}.json`); + } +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/commands/image.ts b/packages/plugin-design-essentials/src/commands/image.ts new file mode 100644 index 0000000..bb89625 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/image.ts @@ -0,0 +1,16 @@ +import { PluginContext } from "@imgly/plugin-core"; +import { ContentFillMode } from "@cesdk/cesdk-js" + + +const imageFitWithMode = (ctx: PluginContext, params: { blockIds?: number[], fillMode: ContentFillMode }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected(), fillMode } = params; + blockIds.forEach((id: number) => { + if (!block.hasContentFillMode(id)) return; + block.setContentFillMode(id, fillMode) + }) +} + +export const imageFitModeCrop = async (ctx: PluginContext, params: { blockIds?: number[] }) => imageFitWithMode(ctx, { ...params, fillMode: 'Crop' }) +export const imageFitModeCover = async (ctx: PluginContext, params: { blockIds?: number[] }) => imageFitWithMode(ctx, { ...params, fillMode: 'Cover' }) +export const imageFitModeContain = async (ctx: PluginContext, params: { blockIds?: number[] }) => imageFitWithMode(ctx, { ...params, fillMode: 'Contain' }) diff --git a/packages/plugin-design-essentials/src/commands/import.ts b/packages/plugin-design-essentials/src/commands/import.ts new file mode 100644 index 0000000..67a14bd --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/import.ts @@ -0,0 +1,2 @@ +// .txt, .cesdk, .png, .jpg, .jpeg, .webp, .pdf, +// .csv ... generate a new page from each row and replace the content of the blocks with the values from the row \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/commands/index.ts b/packages/plugin-design-essentials/src/commands/index.ts new file mode 100644 index 0000000..c17e1a3 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/index.ts @@ -0,0 +1,15 @@ +export * from "./block"; +export * from "./export"; +export * from "./image"; +export * from "./container"; +export * from "./layout"; + +export * from "./debug"; +export * from "./plugins"; +export * from "./components"; +export * from "./playground"; +export * from "./i18n"; +export * from "./panels"; +export * from "./turnInto"; +// for convenience I splitted the files into smaller files +export * from "./shape"; \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/commands/layout.ts b/packages/plugin-design-essentials/src/commands/layout.ts new file mode 100644 index 0000000..a548320 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/layout.ts @@ -0,0 +1,104 @@ +import { PluginContext } from "../../../plugin-core/types"; +import { toSafeInteger } from "lodash"; +import { computeMultiSelectionBounds } from "../utils/computeMultiSelectionBounds"; + +export const layoutHorizontally = async (ctx: PluginContext, params: { blockIds?: number[]; padding?: number; }) => { + const { block } = ctx.engine; + const { + blockIds = block.findAllSelected(), padding = 0 + } = params; + + const isGroup = (blockIds.length === 1 && block.getType(blockIds[0]) !== '//ly.img.ubq/group'); + const isMultiSelection = blockIds.length > 1; + + if (!isGroup && !isMultiSelection) { + return; + }; + + const children = isGroup ? block.getChildren(blockIds[0]) : blockIds; + if (children.length === 0) return; + + + let curXPos = block.getPositionX(children[0]); + let curYPos = block.getPositionY(children[0]); + children.forEach((childId: number) => { + block.setPositionY(childId, curYPos); + block.setPositionX(childId, curXPos); + const width = block.getFrameWidth(childId); + curXPos += width; + curXPos += padding; + }); +}; + +export const layoutVertically = async (ctx: PluginContext, params: { blockIds?: number[]; padding?: number; }) => { + const { block } = ctx.engine; + const { + blockIds = block.findAllSelected(), padding = 0 + } = params; + const isGroup = (blockIds.length === 1 && block.getType(blockIds[0]) !== '//ly.img.ubq/group'); + const isMultiSelection = blockIds.length > 1; + + if (!isGroup && !isMultiSelection) { + return; + }; + + const children = isGroup ? block.getChildren(blockIds[0]) : blockIds; + if (children.length === 0) return; + + let curXPos = block.getPositionX(children[0]); + let curYPos = block.getPositionY(children[0]); + children.forEach((childId: number) => { + block.setPositionX(childId, curXPos); + block.setPositionY(childId, curYPos); + const height = block.getFrameHeight(childId); + curYPos += height; + curYPos += padding; + }); +}; + + +export const layoutMasonry = async (ctx: PluginContext, params: { blockIds?: number[]; cols?: number; paddingX?: number; paddingY?: number; }) => { + const { block } = ctx.engine; + let { + blockIds = block.findAllSelected(), paddingX = 16, paddingY = 16, cols = 2 + } = params; + + + cols = toSafeInteger(prompt("Enter the number of columns", "2")); + const isGroup = (blockIds.length === 1 && block.getType(blockIds[0]) !== '//ly.img.ubq/group'); + const isMultiSelection = blockIds.length > 1; + + if (!isGroup && !isMultiSelection) { + return; + }; + + const children = isGroup ? block.getChildren(blockIds[0]) : blockIds; + const groupWidth = isGroup ? block.getFrameWidth(blockIds[0]) : computeMultiSelectionBounds(ctx, blockIds).width; + const childWidth = groupWidth / cols - paddingX; + + console.log(children); + let rowHeights: Array = []; + for (let i = 0; i < cols; i++) { + rowHeights.push(0); + } + + let curXPos = block.getPositionX(children[0]); + let curYPos = block.getPositionY(children[0]); + children.forEach((childId: number) => { + const w = block.getFrameWidth(childId); + const h = block.getFrameHeight(childId); + const aspect = h / w; + const newWidth = childWidth; + const newHeight = aspect * newWidth; + block.setWidth(childId, newWidth); + block.setHeight(childId, newHeight); + // get column with the "lowest" height + const minIndex = rowHeights.indexOf(Math.min(...rowHeights)); + console.log(minIndex, rowHeights[minIndex]); + const xPos = curXPos + minIndex * (childWidth + paddingX); + const yPos = curYPos + rowHeights[minIndex]; + rowHeights[minIndex] += newHeight + paddingY; + block.setPositionX(childId, xPos); + block.setPositionY(childId, yPos); + }); +}; diff --git a/packages/plugin-design-essentials/src/commands/panels.ts b/packages/plugin-design-essentials/src/commands/panels.ts new file mode 100644 index 0000000..3da6b3e --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/panels.ts @@ -0,0 +1,61 @@ +import { PluginContext } from '@imgly/plugin-core' + +const panelIds = [ + '//ly.img.panel/settings', + + '//ly.img.panel/inspector', + '//ly.img.panel/inspector/placeholderSettings', + + '//ly.img.panel/assetLibrary', + '//ly.img.panel/assetLibrary.replace', + + '//ly.img.panel/inspector/image/adjustments', + '//ly.img.panel/inspector/image/filters', + '//ly.img.panel/inspector/image/effects', + '//ly.img.panel/inspector/image/blurs', + + '//ly.img.panel/inspector/crop', + '//ly.img.panel/inspector/adjustments', + '//ly.img.panel/inspector/filters', + '//ly.img.panel/inspector/effects', + '//ly.img.panel/inspector/blur', + '//ly.img.panel/inspector/trim', + '//ly.img.panel/inspector/fill', + '//ly.img.panel/inspector/fill/color', + '//ly.img.panel/inspector/text/properties', + '//ly.img.panel/inspector/stroke/properties', + '//ly.img.panel/inspector/stroke/color', + '//ly.img.panel/inspector/shadow', + '//ly.img.panel/inspector/shadow/color', + '//ly.img.panel/inspector/transform', + '//ly.img.panel/inspector/editColor', + '//ly.img.panel/inspector/colorLibrary', + ]; + +export const panelSettingsOpen = async (ctx: PluginContext) => { + const { ui } = ctx; + ui?.openPanel("//ly.img.panel/settings") +} + +export const panelSettingsClose = async (ctx: PluginContext) => { + const { ui } = ctx; + ui?.closePanel("//ly.img.panel/settings") +} + + + +// export const panelInspectorOpen = async (ctx: PluginContext) => { +// const { ui } = ctx; +// ui?.openPanel("//ly.img.panel/inspector") +// } + +// export const panelInspectorClose = async (ctx: PluginContext) => { +// const { ui } = ctx; +// ui?.closePanel("//ly.img.panel/inspector") +// } + + +// export const panelAssetLibraryOpen = async (ctx: PluginContext) => { +// const { ui } = ctx; +// ui?.openPanel("//ly.img.panel/asset-library") +// } diff --git a/packages/plugin-design-essentials/src/commands/playground.ts b/packages/plugin-design-essentials/src/commands/playground.ts new file mode 100644 index 0000000..79bf1e7 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/playground.ts @@ -0,0 +1,339 @@ +// EXPORT AS LIBRARY +// SYNC BY NAME - two pages, same name + +import { PluginContext } from "../../../plugin-core/types"; +import { readBlockProperty, setBlockProperty } from "../utils/cesdk"; +import { CreativeEngine } from "@cesdk/cesdk-js"; + +const propKeys = [ + 'alwaysOnBottom', + 'alwaysOnTop', + 'blend/mode', 'blur/enabled', 'clipped', + // 'contentFill/mode', + // 'transformLocked', + // 'crop/rotation', 'crop/scaleRatio', 'crop/scaleX', 'crop/scaleY', 'crop/translationX', 'crop/translationY', + // 'position/x', 'position/x/mode', 'position/y', 'position/y/mode', 'rotation', + 'dropShadow/blurRadius/x', 'dropShadow/blurRadius/y', 'dropShadow/clip', 'dropShadow/color', 'dropShadow/enabled', 'dropShadow/offset/x', 'dropShadow/offset/y', + 'fill/enabled', + 'opacity', + 'placeholder/enabled', + 'playback/duration', 'playback/timeOffset', + 'stroke/color', 'stroke/cornerGeometry', 'stroke/enabled', 'stroke/position', 'stroke/style', 'stroke/width', + 'visible'] + + +const syncBlockProperties = (ctx: PluginContext, sourceId: number, destIds: number[], whiteList?: string[], blackList?: string[]) => { + const { block } = ctx.engine; + if (!block.isValid(sourceId)) return + + const propertyKeys = block.findAllProperties(sourceId) + .filter((key: string) => block.isPropertyReadable(key)) + .filter((key: string) => { + if (whiteList && !whiteList.includes(key)) return false + if (blackList && blackList.includes(key)) return false + return true + }) + + propertyKeys.forEach((propertyKey: string) => { + const sourceValue = readBlockProperty(block, sourceId, propertyKey) + destIds.forEach((receiverBlockId: number) => { + if (!block.isValid(receiverBlockId)) return + if (sourceId === receiverBlockId) return; + const receiverValue = readBlockProperty(block, receiverBlockId, propertyKey) + if (receiverValue === sourceValue) return; + setBlockProperty(block, receiverBlockId, propertyKey, sourceValue) + }) + }) +} + + + +// name syntax = "label=appearance(other), rotation(other)" +export const syncBlockAppearance = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block, event } = ctx.engine; + let { blockIds = block.findAllSelected() } = params + console.log("syncBlocks", block.findAllProperties(blockIds[0])) + const propWhiteList: string[] = propKeys + const propBlackList: string[] = [] + // better would be to add a meta data + // const sync = { + // uuid: // appearance: + + // } + + const unsubscribe = event.subscribe(blockIds, (events) => { + events.forEach((event) => { + const bId = event.block; + switch (event.type) { + case 'Created': { + // throw new Error("Not implemented") + break; + } + case 'Updated': { + syncBlockProperties(ctx, bId, blockIds, propWhiteList, propBlackList) + break; + } + case "Destroyed": { + if (blockIds.includes(bId)) { + blockIds.splice(blockIds.indexOf(bId), 1) + } + if (blockIds.length === 1) { + unsubscribe() + } + break; + } + } + }) + }) +} + + + +const products = { + "instagram_story": { + kind: "story", + resolution: { + width: "1080px", height: "1920px" + }, + }, +} + +export const myNewFunctionForTheEditor = async (ctx: PluginContext, _params: { blockIds?: number[] }) => { + const { block, scene } = ctx.engine; + + const pId = scene.getCurrentPage()! + + const bId = block.create("//ly.img.ubq/text") + block.setName(bId, "Hello World") + block.setTextColor(bId, { r: 1, g: 0, b: 0, a: 1 }) + block.replaceText(bId, "Hello World") + + + block.appendChild(pId, bId) + +} + + + + + + +export const productSetInstagram = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + const resolution = products.instagram_story.resolution; + const width = parseValueWithUnit(resolution.width) + const height = parseValueWithUnit(resolution.height) + if (!width || !height) return + + blockIds.forEach((id: number) => { + const widthInDu = unitToDesignUnit(width.value, width.unit, ctx) + const heightInDu = unitToDesignUnit(height.value, height.unit, ctx) + if (!widthInDu || !heightInDu) return + block.setHeight(id, heightInDu) + // block.setHeightMode(id, unitToMode(height.unit)) + block.setWidth(id, widthInDu) + // block.setWidthMode(id, unitToMode(width.unit)) + }) +} + +export const playground = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const { block, event } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + // check distance to parent edges + // type _Distance = { + // top: number; + // left: number; + // centerX: number; + // centerY: number; + // bottom: number; + // right: number; + // } + type Anchors = { + top: boolean; + left: boolean; + centerX: boolean; + centerY: boolean; + bottom: boolean; + right: boolean; + } + + const calcDistance = (fromId: number, toId: number) => { + const bId = fromId + const pId = toId + const bX = block.getGlobalBoundingBoxX(bId) + const bY = block.getGlobalBoundingBoxY(bId) + + const bWidth = block.getGlobalBoundingBoxWidth(bId) + const bheight = block.getGlobalBoundingBoxHeight(bId) + const bCenterX = bX + bWidth / 2 + const bCenterY = bY + bheight / 2 + + const pX = block.getGlobalBoundingBoxX(pId) + const pY = block.getGlobalBoundingBoxY(pId) + const pWidth = block.getGlobalBoundingBoxWidth(pId) + const pheight = block.getGlobalBoundingBoxHeight(pId) + const pCenterX = pX + pWidth / 2 + const pCenterY = pY + pheight / 2 + + const left = pX - bX + const top = pY - bY + const right = pX + pWidth - bX - bWidth + const bottom = pY + pheight - bY - bheight + const centerX = bCenterX - pCenterX + const centerY = bCenterY - pCenterY + + return { left, top, centerX, centerY, right, bottom } + } + + // const distances = blockIds.map((bId: number): Distance => { + // return calcDistance(bId, block.getParent(bId)); + // }) + + + event.subscribe(blockIds, (events) => { + events.forEach((event) => { + switch (event.type) { + case "Created": break; + case "Updated": { + const pId = block.getParent(event.block)! + const dist = calcDistance(event.block, pId) + const height = block.getGlobalBoundingBoxHeight(pId) + const width = block.getGlobalBoundingBoxWidth(pId) + console.log(width, height, dist) + const distInPercent = { + top: (dist.top / height) * 100, + left: (dist.left / width) * 100, + right: (dist.right / width) * 100, + bottom: (dist.bottom / height) * 100, + centerX: (dist.centerX / width) * 100, + centerY: (dist.centerY / height) * 100, + }; + console.log(JSON.stringify(distInPercent, null, 2)); + + const threshold = 1 // percent + const anchors: Anchors = { + top: Math.abs(distInPercent.top) < threshold, + left: Math.abs(distInPercent.left) < threshold, + right: Math.abs(distInPercent.right) < threshold, + bottom: Math.abs(distInPercent.bottom) < threshold, + centerX: Math.abs(distInPercent.centerX) < threshold, + centerY: Math.abs(distInPercent.centerY) < threshold, + } + console.log(JSON.stringify(anchors, null, 2)); + break; + } + case "Destroyed": break; + } + }) + + }) + + // snap to edge with offset + + +} + + + + + + + + + + + + +// Utils + + +type ValueWithUnit = { + value: number; + unit: string; +}; + +function parseValueWithUnit(string: string | number): ValueWithUnit | null { + const isNumber = typeof string === "number" + if (isNumber) { + return { + value: string, + unit: "" + } + } + const regex = /^(\d+(?:\.\d+)?)([a-z%]*)$/i; + const match = string.match(regex); + + if (match) { + return { + value: parseFloat(match[1]), + unit: match[2], + }; + } + return null; +} + +// function unitToMode(unit: string) { +// switch (unit) { +// case "%": return "Percent" +// case "px": +// case "mm": +// case "in": +// default: return "Absolute" +// } +// } + + +function unitToDesignUnit(value: number, unit: string, ctx: PluginContext) { + switch (unit) { + case "%": return value + case "px": return pixelToDesignUnit(ctx.engine, value) + case "mm": return mmToDesignUnit(ctx.engine, value) + case "in": return inToDesignUnit(ctx.engine, value) + } +} + + + + + +const inToDesignUnit = (engine: CreativeEngine, inch: number) => { + const sceneId = engine.scene.get()! + const sceneUnit = engine.block.getEnum(sceneId, 'scene/designUnit'); + const dpi = engine.block.getFloat(sceneId, 'scene/dpi') + + switch (sceneUnit) { + case "Millimeter": return inch * 2.54; + case "Inch": return inch; + case "Pixel": return inch * dpi; + } + +}; + + +const mmToDesignUnit = (engine: CreativeEngine, mm: number) => { + const sceneId = engine.scene.get()! + const sceneUnit = engine.block.getEnum(sceneId, 'scene/designUnit'); + const dpi = engine.block.getFloat(sceneId, 'scene/dpi') + + switch (sceneUnit) { + case "Millimeter": return mm; + case "Inch": return mm / 25.4; + case "Pixel": return mm / 25.4 * dpi; + } + +}; + + +const pixelToDesignUnit = (engine: CreativeEngine, pixel: number) => { + const sceneId = engine.scene.get()! + const sceneUnit = engine.block.getEnum(sceneId, 'scene/designUnit'); + const dpi = engine.block.getFloat(sceneId, 'scene/dpi') + + switch (sceneUnit) { + case "Millimeter": return pixel * 25.4 / dpi; + case "Inch": return pixel / dpi; + case "Pixel": return pixel; + } +}; diff --git a/packages/plugin-design-essentials/src/commands/plugins.ts b/packages/plugin-design-essentials/src/commands/plugins.ts new file mode 100644 index 0000000..4207616 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/plugins.ts @@ -0,0 +1,27 @@ +import { PluginContext } from "../../../plugin-core/types"; + +export const pluginRegisterCustomPanel = async (ctx: PluginContext, _params: { blockIds?: number[] }) => { + const { ui } = ctx; + ui?.unstable_registerCustomPanel('ly.img.foo', (domElement) => { + domElement.appendChild(document.createTextNode('Hello World')); + return () => { + console.log('Apps disposer called'); + }; + }); + + ui?.openPanel('ly.img.foo'); +} + + + +export const pluginOpenCustomPanel = async (ctx: PluginContext, _params: { blockIds?: number[] }) => { + const { ui } = ctx; + ui?.openPanel('ly.img.foo'); +} + + + +export const command = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + + +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/commands/shape.ts b/packages/plugin-design-essentials/src/commands/shape.ts new file mode 100644 index 0000000..ea08159 --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/shape.ts @@ -0,0 +1,20 @@ +import { PluginContext } from "@imgly/plugin-core"; + + +// each export must be a command +export const shapeSetEllipse = async (ctx: PluginContext, params: { blockIds?: number[] }) => { + const {block} = ctx.engine; + const {blockIds = block.findAllSelected()} = params; + + + blockIds.forEach((bId: number) => { + if (!block.hasShape(bId)) return; + const sId = block.getShape(bId); + block.isValid(sId) && block.destroy(sId); + + const eId = block.createShape("//ly.img.ubq/shape/ellipse"); + block.setShape(bId, eId); + }) + + +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/commands/turnInto.ts b/packages/plugin-design-essentials/src/commands/turnInto.ts new file mode 100644 index 0000000..38fae9b --- /dev/null +++ b/packages/plugin-design-essentials/src/commands/turnInto.ts @@ -0,0 +1,24 @@ +import { PluginContext } from "@imgly/plugin-core"; +import { turnBlockInto } from "../utils/turnBlockInto"; + +export const blockTurnIntoGraphic = (ctx: PluginContext, params: { blockIds: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((id) => turnBlockInto(ctx, "graphic", id)) + +} + +export const blockTurnIntoText = (ctx: PluginContext, params: { blockIds: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((id) => turnBlockInto(ctx, "text", id)) +} + +export const blockTurnIntoPage = (ctx: PluginContext, params: { blockIds: number[] }) => { + const { block } = ctx.engine; + const { blockIds = block.findAllSelected() } = params; + + blockIds.forEach((id) => turnBlockInto(ctx, "page", id)) +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/index.ts b/packages/plugin-design-essentials/src/index.ts new file mode 100644 index 0000000..22302fc --- /dev/null +++ b/packages/plugin-design-essentials/src/index.ts @@ -0,0 +1,81 @@ + +import { PluginContext, CommandDescription } from '@imgly/plugin-core'; +import { CommandImports, CommandContributions, PluginManifest } from './PluginManifest'; + +export interface PluginConfiguration { } + +const registerTranslation = (ctx: PluginContext, translations: { [key: string]: any } = {}) => { + ctx.i18n.setTranslations(translations) +} + +const registerCommands = (ctx: PluginContext, imports: CommandImports) => { + for (const command in imports) { + const callback = imports[command as CommandContributions] + + let desc: CommandDescription = PluginManifest.contributes.commands[command as CommandContributions]; + desc ??= {}; + desc.id ??= `${PluginManifest.id}.commands.${command as string}`; + const [category, name] = (command as string).split("_") + desc.category ??= name ? category : "Commands"; + ctx.commands.registerCommand( + desc.id, + async (params: any) => await callback(ctx, params), + desc + ); + } +} + +const loadTranslation = async (ctx: PluginContext, locales: readonly string[] = ctx.i18n.locales()) => { + const translations = await Promise.all(locales.map(async (locale) => { + try { + const translations = await import(`./locale/${locale}.json`) + return { [locale]: translations.default } + } catch (e) { + // when loading of the file fails + return { [locale]: {} } + } + })) + + translations.forEach((t) => registerTranslation(ctx, t)) +} + + +const loadCommands = async (ctx: PluginContext) => { + const commands = await import("./commands") + await registerCommands(ctx, commands) +} + + +const registerPanels = async (ctx: PluginContext, panels: any) => { + for (const panel in panels) { + const id = `${PluginManifest.id}.panels.${panel}` + // ctx.ui?.unstable_registerPanel(panel, ({ builder: any }) => { + // return panels[panel](ctx, builder) + + // }) + } + +} + +const loadPanels = async (ctx: PluginContext) => { + // const panels = await import("./panels/layers") + // await registerPanels(ctx, panels) +} + + + +export const activate = async (ctx: PluginContext) => { + await loadTranslation(ctx) + await loadCommands(ctx) + await loadPanels(ctx) +} + + +export default (ctx: PluginContext, _config: PluginConfiguration) => { + return { + async initializeUserInterface() { + await activate(ctx) + } + }; +}; + diff --git a/packages/plugin-design-essentials/src/locale/en.json b/packages/plugin-design-essentials/src/locale/en.json new file mode 100644 index 0000000..8c8f11f --- /dev/null +++ b/packages/plugin-design-essentials/src/locale/en.json @@ -0,0 +1,54 @@ +{ + "design-batteries.commands.blockBringForward": "Bring Block Forward", + "design-batteries.commands.blockBringToFront": "Bring Block to Front", + "design-batteries.commands.blockCreateText": "Create Text Block", + "design-batteries.commands.blockDelete": "Delete Block", + "design-batteries.commands.blockDuplicate": "Duplicate Block", + "design-batteries.commands.blockGroup": "Group Blocks", + "design-batteries.commands.blockRename": "Rename Block", + "design-batteries.commands.blockSendBackward": "Send Block Backward", + "design-batteries.commands.blockSendToBack": "Send Block to Back", + "design-batteries.commands.blockTurnIntoGraphic": "Turn Block into Graphic", + "design-batteries.commands.blockTurnIntoPage": "Turn Block into Page", + "design-batteries.commands.blockTurnIntoText": "Turn Block into Text", + "design-batteries.commands.blockUngroup": "Ungroup Blocks", + "design-batteries.commands.createDefaultBlockByType": "Create Default Block by Type", + "design-batteries.commands.debugLogBlockBlur": "Debug Log Block Blur", + "design-batteries.commands.debugLogBlockCrop": "Debug Log Block Crop", + "design-batteries.commands.debugLogBlockEffects": "Debug Log Block Effects", + "design-batteries.commands.debugLogBlockFill": "Debug Log Block Fill", + "design-batteries.commands.debugLogBlockMetadata": "Debug Log Block Metadata", + "design-batteries.commands.debugLogBlockProperties": "Debug Log Block Properties", + "design-batteries.commands.debugLogSceneHierarchy": "Debug Log Scene Hierarchy", + "design-batteries.commands.exportComponentLibrary": "Export Component Library", + "design-batteries.commands.exportComponentToFile": "Export Component to File", + "design-batteries.commands.exportJsonToClipboard": "Export JSON to Clipboard", + "design-batteries.commands.exportJsonToFile": "Export JSON to File", + "design-batteries.commands.exportJpegToFile": "Export JPEG to File", + "design-batteries.commands.exportPdfToFile": "Export PDF to File", + "design-batteries.commands.exportPngToClipboard": "Export PNG to Clipboard", + "design-batteries.commands.exportPngToFile": "Export PNG to File", + "design-batteries.commands.exportRgba8ToFile": "Export Raw RGBA8 to File", + "design-batteries.commands.exportSceneToClipboard": "Export Scene to Clipboard", + "design-batteries.commands.exportSceneToFile": "Export Scene to File", + "design-batteries.commands.exportWebpToFile": "Export WEBP to File", + "design-batteries.commands.i18nDownloadMissingCommandTranslations": "Download Missing Command Translations", + "design-batteries.commands.imageFitModeContain": "Set Image Fit Mode to Contain", + "design-batteries.commands.imageFitModeCrop": "Set Image Fit Mode to Crop", + "design-batteries.commands.imageFitModeCover": "Set Image Fit Mode to Cover", + "design-batteries.commands.importComponent": "Import Component", + "design-batteries.commands.layoutHorizontally": "Layout Horizontally", + "design-batteries.commands.layoutMasonry": "Layout Masonry", + "design-batteries.commands.layoutVertically": "Layout Vertically", + "design-batteries.commands.myNewFunctionForTheEditor": "Super Duper Function", + "design-batteries.commands.panelSettingsClose": "Close Settings Panel", + "design-batteries.commands.panelSettingsOpen": "Open Settings Panel", + "design-batteries.commands.pluginOpenCustomPanel": "Open Custom Panel", + "design-batteries.commands.pluginRegisterAndOpenCustomPanel": "Register and Open Custom Panel", + "design-batteries.commands.pluginRegisterCustomPanel": "Register Custom Panel", + "design-batteries.commands.productSetInstagram": "Set Instagram Product", + "design-batteries.commands.replicateSDXL": "Replicate SDXL", + "design-batteries.commands.syncBlockAppearance": "Sync Block Appearance", + "design-batteries.commands.syncBlocks": "Sync Blocks", + "design-batteries.commands.shapeSetEllipse": "Set Ellipse Shape" +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/panels/index.ts b/packages/plugin-design-essentials/src/panels/index.ts new file mode 100644 index 0000000..0e84be7 --- /dev/null +++ b/packages/plugin-design-essentials/src/panels/index.ts @@ -0,0 +1 @@ +// export * from "./layers"; \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/panels/layers.ts b/packages/plugin-design-essentials/src/panels/layers.ts new file mode 100644 index 0000000..473a5d6 --- /dev/null +++ b/packages/plugin-design-essentials/src/panels/layers.ts @@ -0,0 +1,19 @@ +// import { PluginContext } from '@imgly/plugin-core'; + + +// export const layerList = async (ctx: PluginContext, builder: any, params: any) => { +// const { block } = ctx.engine; +// const { Button, Section, Separator } = builder; +// const blockIds = block.findAllSelected(); + +// Section('layer.section', { +// title: 'Layers', +// children: () => +// blockIds.forEach((bId: number) => +// Button(bId.toString(), { +// label: block.getName(bId) || block.getUUID(bId).toString(), +// onClick: () => block.select(bId) +// })) +// }); + +// } diff --git a/packages/plugin-design-essentials/src/utils/cesdk.ts b/packages/plugin-design-essentials/src/utils/cesdk.ts new file mode 100644 index 0000000..d1c6def --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/cesdk.ts @@ -0,0 +1,39 @@ +import { BlockAPI } from "@cesdk/cesdk-js"; + + +export const readBlockProperty = (block: BlockAPI, id: number, propKey: string, propType?: string) => { + const blacklist = ["fill/solid/color", "fill/image/sourceSet"] + if (blacklist.includes(propKey)) return undefined; + if (!propType) propType = block.getPropertyType(propKey) + try { + switch (propType.toLowerCase()) { + case "string": return block.getString(id, propKey); + case "float": return block.getFloat(id, propKey); + case "double": return block.getDouble(id, propKey); + case "color": return block.getColor(id, propKey); + case "bool": return block.getBool(id, propKey); + case "enum": return block.getEnum(id, propKey); + } + } catch (e) { + console.warn("Error reading property value: ", e); + } + return undefined; +}; + + +export const setBlockProperty = (block: BlockAPI, id: number, propKey: string, propValue: any, propType?: string) => { + if (!propType) propType = block.getPropertyType(propKey) + try { + switch (propType.toLowerCase()) { + case "string": return block.setString(id, propKey, propValue); + case "float": return block.setFloat(id, propKey, propValue); + case "double": return block.setDouble(id, propKey, propValue); + case "color": return block.setColor(id, propKey, propValue); + case "bool": return block.setBool(id, propKey, propValue); + case "enum": return block.setEnum(id, propKey, propValue); + } + } catch (e) { + console.warn("Error writing property: ", propKey, propType, propValue); + } + return undefined; +}; diff --git a/packages/plugin-design-essentials/src/utils/computeBlockName.ts b/packages/plugin-design-essentials/src/utils/computeBlockName.ts new file mode 100644 index 0000000..a730434 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/computeBlockName.ts @@ -0,0 +1,8 @@ +import { BlockAPI } from "@cesdk/cesdk-js"; + +export const inferBlockName = (block: BlockAPI, blockId: number) => { + + const uuid = block.getUUID(blockId); + const name = block.getName(blockId) + return name || uuid || blockId +} \ No newline at end of file diff --git a/packages/plugin-design-essentials/src/utils/computeMultiSelectionBounds.ts b/packages/plugin-design-essentials/src/utils/computeMultiSelectionBounds.ts new file mode 100644 index 0000000..d529d12 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/computeMultiSelectionBounds.ts @@ -0,0 +1,20 @@ +import { PluginContext } from "../../../plugin-core/types"; + +export const computeMultiSelectionBounds = (ctx: PluginContext, blockIds: number[]) => { + + const { block } = ctx.engine; + const bounds = blockIds.map((id: number) => { + return { + x: block.getFrameX(id), + y: block.getFrameY(id), + width: block.getFrameWidth(id), + height: block.getFrameHeight(id) + }; + }); + + const x = Math.min(...bounds.map(b => b.x)); + const y = Math.min(...bounds.map(b => b.y)); + const width = Math.max(...bounds.map(b => b.x + b.width)) - x; + const height = Math.max(...bounds.map(b => b.y + b.height)) - y; + return { x, y, width, height }; +}; diff --git a/packages/plugin-design-essentials/src/utils/createDefaultBlockByType.ts b/packages/plugin-design-essentials/src/utils/createDefaultBlockByType.ts new file mode 100644 index 0000000..88ca0f4 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/createDefaultBlockByType.ts @@ -0,0 +1,30 @@ +import { PluginContext } from "@imgly/plugin-core"; + +// UTILS +export const createDefaultBlockByType = (ctx: PluginContext, type: string) => { + const { block } = ctx.engine; + switch (type) { + + case "graphic": { + const bId = block.create("graphic"); + const sId = block.createShape("rect"); + const fId = block.createFill("//ly.img.ubq/fill/image"); + block.setShape(bId, sId); + block.setFill(bId, fId); + block.setName(bId, type.toUpperCase()); + return bId; + } + case "page": { + const bId = block.create("page"); + block.setName(bId, type.toUpperCase()); + return bId; + } + case "text": { + const bId = block.create("graphic"); + block.replaceText(bId, "Hello World"); + block.setName(bId, type.toUpperCase()); + return bId; + } + default: throw new Error("Invalid type"); + } +}; diff --git a/packages/plugin-design-essentials/src/utils/download.ts b/packages/plugin-design-essentials/src/utils/download.ts new file mode 100644 index 0000000..f83c9c5 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/download.ts @@ -0,0 +1,60 @@ +import CreativeEditorSDK from "@cesdk/cesdk-js"; + + + +export async function loadAsBlob(filter: string = "*") { + return new Promise((resolve, reject) => { + const upload = document.createElement("input"); + upload.setAttribute("type", "file"); + upload.setAttribute("accept", filter) + upload.setAttribute("style", "display: none") + upload.onchange = (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + const buffer = e.target?.result + if (buffer instanceof ArrayBuffer) { + const blob = new Blob([buffer]); + upload.remove() + resolve(blob) + } else { + upload.remove() + reject(new Error("Invalid buffer")) + } + } + reader.readAsArrayBuffer(file); + } + } + + upload.click() + }) +} + +export function downloadBlob(blob: Blob, filename: string) { + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = filename; + link.click(); + link.remove(); + URL.revokeObjectURL(url); +} +export const downloadBlocks = (cesdk: CreativeEditorSDK, blobs: Blob[], options: { mimeType: string; pages?: number[]; }) => { + const postfix = options.mimeType.split("/")[1]; + const pageIds = options.pages ?? []; + + blobs.forEach((blob, index) => { + const pageId = pageIds[index]; + let pageName = `page-${index}`; + if (pageId) { + const name = cesdk.engine.block.getName(pageId); + pageName = name?.length ? name : pageName; + } + const filename = `${pageName}.${postfix}`; + downloadBlob(blob, filename); + }); + return Promise.resolve(); +}; + + diff --git a/packages/plugin-design-essentials/src/utils/exportBlockAs.ts b/packages/plugin-design-essentials/src/utils/exportBlockAs.ts new file mode 100644 index 0000000..3185100 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/exportBlockAs.ts @@ -0,0 +1,34 @@ +import { PluginContext } from "../../../plugin-core/types"; +import { type MimeType } from "@cesdk/cesdk-js"; + +export const exportBlockAs = async (ctx: PluginContext, params: { blockIds?: number[], mimeType?: MimeType | 'application/x-cesdk' | 'application/json', width?: number, height?: number }) => { + + const { block } = ctx.engine; + const { + blockIds = block.findAllSelected(), + mimeType = "image/png" as MimeType, + width, + height + } = params; + blockIds.length === 0 && blockIds.push(ctx.engine.scene.get()!); + return await Promise.all(blockIds.map(async (bId: number) => { + switch (mimeType) { + case "application/x-cesdk": { + const str = await block.saveToString([bId]); + return new Blob([str], { type: mimeType }); + + } + case "application/json": { + const str = await block.saveToString([bId]); + const json = str.substring(4) + const decoded = atob(json) + return new Blob([decoded], { type: mimeType }); + + } + default: + return await block.export(bId, mimeType, { targetHeight: height, targetWidth: width }); + } + + })); +}; + diff --git a/packages/plugin-design-essentials/src/utils/getTransform.ts b/packages/plugin-design-essentials/src/utils/getTransform.ts new file mode 100644 index 0000000..6cbd969 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/getTransform.ts @@ -0,0 +1,12 @@ +import { PluginContext } from "@imgly/plugin-core"; + +export const getTransform = (ctx: PluginContext, bId: number) => { + const { block } = ctx.engine; + return { + x: block.getPositionX(bId), + y: block.getPositionY(bId), + width: block.getFrameWidth(bId), + height: block.getFrameHeight(bId) + }; + +}; diff --git a/packages/plugin-design-essentials/src/utils/setTransform.ts b/packages/plugin-design-essentials/src/utils/setTransform.ts new file mode 100644 index 0000000..fa6c938 --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/setTransform.ts @@ -0,0 +1,10 @@ +import { PluginContext } from "@imgly/plugin-core"; + +export const setTransform = (ctx: PluginContext, bId: number, transform: any) => { + const { block } = ctx.engine; + const { x, y, width, height } = transform; + x && block.setPositionX(bId, x); + y && block.setPositionY(bId, y); + width && block.setWidth(bId, width); + height && block.setHeight(bId, height); +}; diff --git a/packages/plugin-design-essentials/src/utils/turnBlockInto.ts b/packages/plugin-design-essentials/src/utils/turnBlockInto.ts new file mode 100644 index 0000000..5cb81be --- /dev/null +++ b/packages/plugin-design-essentials/src/utils/turnBlockInto.ts @@ -0,0 +1,37 @@ +import { PluginContext } from "@imgly/plugin-core"; +import { getTransform } from "./getTransform"; +import { setTransform } from "./setTransform"; +import { createDefaultBlockByType } from "../utils/createDefaultBlockByType"; + +export const turnBlockInto = (ctx: PluginContext, toType: string, id: number) => { + const { block, scene } = ctx.engine; + + const bId = createDefaultBlockByType(ctx, toType); + + if (block.hasFill(id)) { + const fId = block.duplicate(block.getFill(id)); + block.hasFill(bId) && block.setFill(bId, fId); + } + if (block.hasShape(id)) { + const sId = block.duplicate(block.getShape(id)); + block.hasShape(bId) && block.setShape(bId, sId); + } + + setTransform(ctx, bId, getTransform(ctx, id)); + + if (toType === "page") { + console.log("Turning into page"); + let pId = scene.get()!; + const cIds = block.getChildren(pId); + const sId = cIds.find((cId) => block.getType(cId) === "//ly.img.ubq/stack") + const hasStack = sId !== -1 + console.log("Has stack", hasStack); + pId = hasStack ? sId : pId; + block.appendChild(pId, bId); + } else { + const pId = block.getParent(id) ?? scene.getCurrentPage() ?? scene.get()!; + block.appendChild(pId, bId); + } + + block.destroy(id); +}; diff --git a/packages/plugin-design-essentials/src/worker.ts b/packages/plugin-design-essentials/src/worker.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-design-essentials/tsconfig.json b/packages/plugin-design-essentials/tsconfig.json new file mode 100644 index 0000000..0d7577f --- /dev/null +++ b/packages/plugin-design-essentials/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "strict": false, + "target": "es2017", + "module": "es2020", + "lib": ["es2018", "dom"], + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "declaration": true, + "declarationDir": "types/", + "skipLibCheck": true + }, + "include": ["src/**/*", "esbuild/global.d.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/remote-asset-source/LICENSE.md b/packages/plugin-remote-asset-source/LICENSE.md similarity index 100% rename from packages/remote-asset-source/LICENSE.md rename to packages/plugin-remote-asset-source/LICENSE.md diff --git a/packages/remote-asset-source/README.md b/packages/plugin-remote-asset-source/README.md similarity index 100% rename from packages/remote-asset-source/README.md rename to packages/plugin-remote-asset-source/README.md diff --git a/packages/remote-asset-source/esbuild/config.mjs b/packages/plugin-remote-asset-source/esbuild/config.mjs similarity index 100% rename from packages/remote-asset-source/esbuild/config.mjs rename to packages/plugin-remote-asset-source/esbuild/config.mjs diff --git a/packages/plugin-remote-asset-source/esbuild/global.d.ts b/packages/plugin-remote-asset-source/esbuild/global.d.ts new file mode 100644 index 0000000..de80fd8 --- /dev/null +++ b/packages/plugin-remote-asset-source/esbuild/global.d.ts @@ -0,0 +1,3 @@ +// These constants here are added by the base esbuild config + +declare const PLUGIN_VERSION: string; diff --git a/packages/remote-asset-source/package.json b/packages/plugin-remote-asset-source/package.json similarity index 100% rename from packages/remote-asset-source/package.json rename to packages/plugin-remote-asset-source/package.json diff --git a/packages/plugin-remote-asset-source/scripts/build.mjs b/packages/plugin-remote-asset-source/scripts/build.mjs new file mode 100644 index 0000000..13d12e1 --- /dev/null +++ b/packages/plugin-remote-asset-source/scripts/build.mjs @@ -0,0 +1,5 @@ +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +await Promise.all(configs.map(async (config) => await esbuild.build(config))); diff --git a/packages/plugin-remote-asset-source/scripts/watch.mjs b/packages/plugin-remote-asset-source/scripts/watch.mjs new file mode 100644 index 0000000..15dbb21 --- /dev/null +++ b/packages/plugin-remote-asset-source/scripts/watch.mjs @@ -0,0 +1,19 @@ +import chalk from 'chalk'; +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] ${chalk.green('Watching...')}` +); + +const contexts = await Promise.all( + configs.map((config) => esbuild.context(config)) +); + +await Promise.any(contexts.map((ctx) => ctx.watch())); diff --git a/packages/remote-asset-source/src/constants.ts b/packages/plugin-remote-asset-source/src/constants.ts similarity index 100% rename from packages/remote-asset-source/src/constants.ts rename to packages/plugin-remote-asset-source/src/constants.ts diff --git a/packages/remote-asset-source/src/index.ts b/packages/plugin-remote-asset-source/src/index.ts similarity index 100% rename from packages/remote-asset-source/src/index.ts rename to packages/plugin-remote-asset-source/src/index.ts diff --git a/packages/remote-asset-source/src/plugin.ts b/packages/plugin-remote-asset-source/src/plugin.ts similarity index 100% rename from packages/remote-asset-source/src/plugin.ts rename to packages/plugin-remote-asset-source/src/plugin.ts diff --git a/packages/remote-asset-source/src/schemas/assetSchema.ts b/packages/plugin-remote-asset-source/src/schemas/assetSchema.ts similarity index 100% rename from packages/remote-asset-source/src/schemas/assetSchema.ts rename to packages/plugin-remote-asset-source/src/schemas/assetSchema.ts diff --git a/packages/remote-asset-source/src/schemas/assetSourceManifestSchema.ts b/packages/plugin-remote-asset-source/src/schemas/assetSourceManifestSchema.ts similarity index 100% rename from packages/remote-asset-source/src/schemas/assetSourceManifestSchema.ts rename to packages/plugin-remote-asset-source/src/schemas/assetSourceManifestSchema.ts diff --git a/packages/remote-asset-source/src/util.ts b/packages/plugin-remote-asset-source/src/util.ts similarity index 100% rename from packages/remote-asset-source/src/util.ts rename to packages/plugin-remote-asset-source/src/util.ts diff --git a/packages/remote-asset-source/tsconfig.json b/packages/plugin-remote-asset-source/tsconfig.json similarity index 100% rename from packages/remote-asset-source/tsconfig.json rename to packages/plugin-remote-asset-source/tsconfig.json diff --git a/packages/remote-asset-source/yarn.lock b/packages/plugin-remote-asset-source/yarn.lock similarity index 100% rename from packages/remote-asset-source/yarn.lock rename to packages/plugin-remote-asset-source/yarn.lock diff --git a/packages/plugin-replicate-io/.gitignore b/packages/plugin-replicate-io/.gitignore new file mode 100644 index 0000000..9060c20 --- /dev/null +++ b/packages/plugin-replicate-io/.gitignore @@ -0,0 +1,11 @@ +node_modules +packages/*/dist +examples/*/dist +.env.local + +.DS_Store +yarn-error.log + +.turbo +.vercel +types \ No newline at end of file diff --git a/packages/plugin-replicate-io/esbuild/config.mjs b/packages/plugin-replicate-io/esbuild/config.mjs new file mode 100644 index 0000000..37b437c --- /dev/null +++ b/packages/plugin-replicate-io/esbuild/config.mjs @@ -0,0 +1,58 @@ +import chalk from 'chalk'; +import { readFile } from 'fs/promises'; + +// import packageJson from '../package.json' assert { type: 'json' }; +// Avoid the Experimental Feature warning when using the above. +const packageJson = JSON.parse( + await readFile(new URL('../package.json', import.meta.url)) +); + + +const dependencies = Object.keys(packageJson.dependencies) +const peerDependencies = Object.keys(packageJson.peerDependencies) +const externals = [...dependencies, ...peerDependencies] + +console.log( + chalk.yellow('Building version: '), + chalk.green(packageJson.version) +); + +const configs = [ + { + entryPoints: ['src/index.ts', "src/worker.ts"], + define: { + PLUGIN_VERSION: `"${packageJson.version}"` + }, + minify: true, + bundle: true, + sourcemap: true, + external: externals, + platform: 'node', + format: 'esm', + outdir: 'dist', + outExtension: { '.js': '.mjs' }, + plugins: [ + { + name: 'reporter', + setup(build) { + build.onEnd((result) => { + console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] Build ${ + result.errors.length + ? chalk.red('failed') + : chalk.green('succeeded') + }` + ); + }); + } + } + ] + } +]; + +export default configs; diff --git a/packages/plugin-replicate-io/esbuild/global.d.ts b/packages/plugin-replicate-io/esbuild/global.d.ts new file mode 100644 index 0000000..de80fd8 --- /dev/null +++ b/packages/plugin-replicate-io/esbuild/global.d.ts @@ -0,0 +1,3 @@ +// These constants here are added by the base esbuild config + +declare const PLUGIN_VERSION: string; diff --git a/packages/plugin-replicate-io/manifest.json b/packages/plugin-replicate-io/manifest.json new file mode 100644 index 0000000..6942e9c --- /dev/null +++ b/packages/plugin-replicate-io/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "replicate-io", + "version": "0.0.1", + "publisher": "IMG.LY GmbH", + "icon": null, + "categories": [], + "contributes": { + "commands": { + } + } +} \ No newline at end of file diff --git a/packages/plugin-replicate-io/package.json b/packages/plugin-replicate-io/package.json new file mode 100644 index 0000000..95dd850 --- /dev/null +++ b/packages/plugin-replicate-io/package.json @@ -0,0 +1,67 @@ +{ + "name": "@imgly/plugin-replicate-io", + "version": "0.1.0", + "description": "Vectorizer plugin for the CE.SDK editor", + "keywords": [ + "CE.SDK", + "plugin" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/imgly/plugins.git" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "IMG.LY GmbH", + "email": "support@img.ly", + "url": "https://img.ly" + }, + "bugs": { + "email": "support@img.ly" + }, + "source": "./src/index.ts", + "module": "./dist/index.mjs", + "types": "./types/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "types": "./types/index.d.ts" + } + }, + "homepage": "https://img.ly", + "files": [ + "LICENSE.md", + "README.md", + "CHANGELOG.md", + "dist/", + "types/", + "bin/" + ], + "scripts": { + "start": "npm run watch", + "clean": "npx rimraf dist && npx rimraf types", + "build": "yarn run clean && yarn run types:create && node scripts/build.mjs", + "dev": "yarn run types:create && node scripts/watch.mjs", + "publish:latest": "npm run clean && npm run build && npm publish --tag latest --access public", + "publish:next": "npm run clean && npm run build && npm publish --tag next --access public", + "check:all": "concurrently -n lint,type,pretty \"yarn check:lint\" \"yarn check:type\" \"yarn check:pretty\"", + "check:lint": "eslint --max-warnings 0 './src/**/*.{ts,tsx}'", + "check:pretty": "prettier --list-different './src/**/*.{ts,tsx}'", + "check:type": "tsc --noEmit", + "types:create": "tsc --emitDeclarationOnly" + }, + "devDependencies": { + "chalk": "^5.3.0", + "concurrently": "^8.2.2", + "esbuild": "^0.19.11", + "eslint": "^8.51.0", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "@cesdk/cesdk-js": "~1.21.0" + }, + "dependencies": { + "@imgly/plugin-core": "*", + "lodash": "^4.17.21" + } +} diff --git a/packages/plugin-replicate-io/scripts/build.mjs b/packages/plugin-replicate-io/scripts/build.mjs new file mode 100644 index 0000000..13d12e1 --- /dev/null +++ b/packages/plugin-replicate-io/scripts/build.mjs @@ -0,0 +1,5 @@ +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +await Promise.all(configs.map(async (config) => await esbuild.build(config))); diff --git a/packages/plugin-replicate-io/scripts/watch.mjs b/packages/plugin-replicate-io/scripts/watch.mjs new file mode 100644 index 0000000..15dbb21 --- /dev/null +++ b/packages/plugin-replicate-io/scripts/watch.mjs @@ -0,0 +1,19 @@ +import chalk from 'chalk'; +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] ${chalk.green('Watching...')}` +); + +const contexts = await Promise.all( + configs.map((config) => esbuild.context(config)) +); + +await Promise.any(contexts.map((ctx) => ctx.watch())); diff --git a/packages/plugin-replicate-io/src/PluginManifest.ts b/packages/plugin-replicate-io/src/PluginManifest.ts new file mode 100644 index 0000000..f60f3b4 --- /dev/null +++ b/packages/plugin-replicate-io/src/PluginManifest.ts @@ -0,0 +1,10 @@ +import Manifest from '../manifest.json'; +import { CommandCallback } from '@imgly/plugin-core'; + + +export type Contributions = typeof Manifest;["contributes"] +export type CommandContributions = keyof typeof Manifest["contributes"]["commands"] +export type CommandImports = Record + +export const PluginManifest = Manifest + diff --git a/packages/plugin-replicate-io/src/commands/index.ts b/packages/plugin-replicate-io/src/commands/index.ts new file mode 100644 index 0000000..7101546 --- /dev/null +++ b/packages/plugin-replicate-io/src/commands/index.ts @@ -0,0 +1,159 @@ +import { PluginContext } from "@imgly/plugin-core"; + +// TODOS +// https://replicate.com/stability-ai/stable-diffusion-img2img?prediction=63trbdrbookprhnq3eoap6iwz4 +// https://replicate.com/pharmapsychotic/clip-interrogator +// https://replicate.com/batouresearch/high-resolution-controlnet-tile/examples#jq5gj2dbjg6j6l3ih7hf3jfuoa + +// https://replicate.com/mistralai/mixtral-8x7b-instruct-v0.1 + +const REPLICATE_API_TOKEN = "" + +const REPLICATE_HEADERS = { + "Content-Type": 'application/json', + "Authorization": `Token ${REPLICATE_API_TOKEN}` +} + +const proxyForCors = (url: string) => 'https://corsproxy.io/?' + encodeURIComponent(url); + +const MODELS = { + "face2sticker": { + version: "764d4827ea159608a07cdde8ddf1c6000019627515eb02b6b449695fd547e5ef", + input: (iInput) => ({ + "steps": 20, + "width": 1024, + "height": 1024, + "upscale": false, + "upscale_steps": 10, + "negative_prompt": "", + "prompt_strength": 4.5, + "ip_adapter_noise": 0.5, + "ip_adapter_weight": 0.2, + "instant_id_strength": 0.7, + ...iInput + }) + }, + "sdxl": { + version: "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b", + input: (iInput) => ({ + "width": 1024, + "height": 1024, + "refine": "expert_ensemble_refiner", + "scheduler": "K_EULER", + "num_outputs": 1, + "lora_scale": 0.6, + "guidance_scale": 7.5, + "apply_watermark": false, + "high_noise_frac": 0.8, + "negative_prompt": "", + "prompt_strength": 0.8, + "num_inference_steps": 25, + ...iInput + }) + }, + "playgroundai/playground-v2-1024px-aesthetic": { + version: "42fe626e41cc811eaf02c94b892774839268ce1994ea778eba97103fe1ef51b8", + input: (iInput) => ({ + width: 1024, + height: 1024, + scheduler: "K_EULER_ANCESTRAL", + guidance_scale: 3, + apply_watermark: false, + negative_prompt: "", + num_inference_steps: 50, + ...iInput + }) + + } +} + +export const replicateSDXL = async (ctx: PluginContext, params: { blockIds?: number[]; }) => { + const { block } = ctx.engine; + let { + blockIds = block.findAllSelected() + } = params; + const isGroup = (blockIds.length === 1 && block.getType(blockIds[0]) === '//ly.img.ubq/group'); + blockIds = isGroup ? block.getChildren(blockIds[0]) : blockIds; + + const iIds = blockIds.filter((id: number) => { + if (!block.hasFill(id)) return false + const fId = block.getFill(id) + if (!block.isValid(fId)) return false + const fType = block.getType(fId) + return fType === "//ly.img.ubq/fill/image" + }) + + const fIds = iIds.map((id: number) => [id, block.getFill(id)]) + fIds.forEach(async ([bId, fId]) => { + // fake busy + //enssure we have preview + const imageFillUri = block.getString(fId, 'fill/image/imageFileURI'); + const name = block.getName(bId) + block.setString(fId, 'fill/image/previewFileURI', block.getString(fId, 'fill/image/previewFileURI') ?? block.getString(fId, 'fill/image/imageFileURI')); + block.setString(fId, 'fill/image/imageFileURI', ''); + block.setSourceSet(fId, 'fill/image/sourceSet', []); + + + const iPrompt = (name.length === 0) ? prompt("Enter a prompt", name) : name + const iImage = imageFillUri + const iMask = undefined + + + if (!name) block.setName(bId, iPrompt) + // const model = "playgroundai/playground-v2-1024px-aesthetic" + const model = "sdxl" + // const model = "face2sticker" + const replicateIoVersion = MODELS[model].version + const replicateIoinput = MODELS[model].input({ prompt: iPrompt, mask: iMask, image: iImage }) + const images = await callReplicateIo(replicateIoVersion, replicateIoinput) + + const image = images[0] // for now we assume one image but we could gather multiple in batch + block.setString(fId, 'fill/image/imageFileURI', image); + block.setSourceSet(fId, 'fill/image/sourceSet', []); + }) + +} + + + +const callReplicateIo = async (version: string, input: any) => { + const data = { + version, + input + } + + const url = proxyForCors("https://api.replicate.com/v1/predictions") + const res = await fetch(url, { + method: 'POST', + // mode: "no-cors", + headers: REPLICATE_HEADERS, + body: JSON.stringify(data) + }) + + + const json = await res.json() + return await waitForReplicate(json) +} + +const waitForReplicate = async (json: any): Promise => { + return new Promise((resolve, reject) => { + const interval = 1000 + const timeout = setInterval(async () => { + // console.log("Checking status") + const url = proxyForCors(json.urls.get) + const statusRes = await fetch(url, { headers: REPLICATE_HEADERS }) + const statusJson = await statusRes.json() + console.log(statusJson) + if (statusJson.error) { + clearInterval(timeout) + reject(statusJson.error) + } + if (statusJson.status === "succeeded") { + clearInterval(timeout) + const { output } = statusJson + resolve(output?.map((o: string) => proxyForCors(o))) + + } + }, interval) + }) +} \ No newline at end of file diff --git a/packages/plugin-replicate-io/src/index.ts b/packages/plugin-replicate-io/src/index.ts new file mode 100644 index 0000000..2e3dddd --- /dev/null +++ b/packages/plugin-replicate-io/src/index.ts @@ -0,0 +1,82 @@ + +import { PluginContext, CommandDescription } from '@imgly/plugin-core'; +import { CommandImports, CommandContributions, PluginManifest } from './PluginManifest'; + +export interface PluginConfiguration { } + +const registerTranslation = (ctx: PluginContext, translations: { [key: string]: any } = {}) => { + ctx.i18n.setTranslations(translations) +} + +const registerCommands = (ctx: PluginContext, imports: CommandImports) => { + for (const command in imports) { + const callback = imports[command as string] + + let desc: CommandDescription = PluginManifest.contributes.commands[command as CommandContributions]; + desc ??= {}; + desc.id ??= `${PluginManifest.id}.commands.${command as string}`; + const [category, name] = (command as string).split("_") + desc.category ??= name ? category : "Commands"; + ctx.commands.registerCommand( + desc.id, + async (params: any) => await callback(ctx, params), + desc + ); + } +} + +const loadTranslation = async (ctx: PluginContext, locales: readonly string[] = ctx.i18n.locales()) => { + const translations = await Promise.all(locales.map(async (locale) => { + try { + const translations = await import(`./locale/${locale}.json`) + return { [locale]: translations.default } + } catch (e) { + // when loading of the file fails + return { [locale]: {} } + } + })) + + translations.forEach((t) => registerTranslation(ctx, t)) +} + + +const loadCommands = async (ctx: PluginContext) => { + const commands = await import("./commands") + await registerCommands(ctx, commands) +} + + +const registerPanels = async (ctx: PluginContext, panels: any) => { + for (const panel in panels) { + const id = `${PluginManifest.id}.panels.${panel}` + // ctx.ui?.unstable_registerPanel(panel, ({ builder: any }) => { + // return panels[panel](ctx, builder) + + // }) + } + +} + +const loadPanels = async (ctx: PluginContext) => { + // const panels = await import("./panels/layers") + // await registerPanels(ctx, panels) +} + + + +export const activate = async (ctx: PluginContext) => { + await loadTranslation(ctx) + await loadCommands(ctx) + await loadPanels(ctx) +} + + + +export default (ctx: PluginContext, _config: PluginConfiguration) => { + return { + async initializeUserInterface() { + await activate(ctx) + } + }; +}; + diff --git a/packages/plugin-replicate-io/src/locale/en.json b/packages/plugin-replicate-io/src/locale/en.json new file mode 100644 index 0000000..544b7b4 --- /dev/null +++ b/packages/plugin-replicate-io/src/locale/en.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/packages/plugin-replicate-io/src/worker.ts b/packages/plugin-replicate-io/src/worker.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-replicate-io/tsconfig.json b/packages/plugin-replicate-io/tsconfig.json new file mode 100644 index 0000000..0d7577f --- /dev/null +++ b/packages/plugin-replicate-io/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "strict": false, + "target": "es2017", + "module": "es2020", + "lib": ["es2018", "dom"], + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "declaration": true, + "declarationDir": "types/", + "skipLibCheck": true + }, + "include": ["src/**/*", "esbuild/global.d.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/plugin-vectorizer/LICENSE.md b/packages/plugin-vectorizer/LICENSE.md new file mode 100644 index 0000000..a099036 --- /dev/null +++ b/packages/plugin-vectorizer/LICENSE.md @@ -0,0 +1 @@ +TBD diff --git a/packages/plugin-vectorizer/PLAYGROUND.md b/packages/plugin-vectorizer/PLAYGROUND.md new file mode 100644 index 0000000..f9a21fa --- /dev/null +++ b/packages/plugin-vectorizer/PLAYGROUND.md @@ -0,0 +1,180 @@ + +Define feature flags + +Feature Enabled +Feature Permissions + + + + + +```JS +// define +feature.register('featureName') +feature.unregister('featureName') + +// if the feature does not exist it always evaluates to flse +feature.setEnabled('featureName', true) +feature.setEnabled('featureName', false) +feature.setEnabled('featureName', (context) => { return true +}); + +feature.setPermission('featureName', (context) => { return true; +}) +feature.setPermission('featureName', (context) => { return true; +}) +feature.setPermission('featureName', (context) => { return true; +}) + +feature.setSupported('featureName', (context) => { return true +}) + +feature.can(featureName, context) { + if (!this.isSupported(featureName)) return; + if (!this.isAllowed(featureName)) return; + if (!this.isEnabled(featureName)) return; +} + +``` + + +```JS + // check if simd is suppored +feature.register("simd"); +feature.setEnabled("simd", (ctx) => { + if (feature.canUse("browser", ctx)) + return (typeof SIMD !== "undefined"); + }); + + +``` + +feature.isEnabled + + + +# Example share featur +```JS + +// we can register a unique identifier that has potentially dependencies to other features +feature.register("my.command", (ctx) => {}, ["fill", {"opt": { optional: true}}]) + + +// the integrator +feature.setPermission("share.dialog", (ctx) => {}) +feature.setEnabled("share.dialog", (ctx) => {}) + +// register dependecy that also need to be checked + +// can will check if the feature and the dependencies are met + +if (feature.can("my.command",ctx)) { + feature.run("my.command", args, ctx) +} + +feature + .try("my.command")? + .run(args, ctx) + +feature.wrap(func, ["feature"]) { + return () => { + // check features + return T | undefined + } +} + + +``` + + +```JS + +// only run when imgly scope img.ly arrange is set and whatever is in there evaluates to true +feature.register("vectorize", ctx => { + if (ctx.blockIds) // do some checks on the thing +}, ["imgly.arrange", "imgly.block.setPositionX"]) + + +function vectorize(image) { + +} + +export const vectorize = feature.wrap(vectorize, ["vectorize"]) + +//Vectorize will only run if feature is enabled + + +feature.setPermission("vectorize", "deny") // no one will be able to run it +feature.setEnabled("vectorize", true) + + +// checkout cancancan + +FEATURES/PERMISSIONS/SCOPES +// checkout Abilities +// results = Allow +class Abilities { + + #permission = Map() // featureName -> (func: boolean) | boolean + #enabled = Map() // featureName -> (func: boolean) | boolean + #definition = Map() // featureName -> (func: boolean) | boolean + #dependencies = Map() // featureName -> (func: boolean) | boolean + + + // all need allow, defer, deny + + can(featureName, ctx) => { + if (this.#enabled[featureName] && (!this.#enabled[featureName]?.(ctx))) return false; + if (this.#enabled[featureName] && (!this.#permission[featureName]?.(ctx)())) return false; + if (this.#enabled[featureName] && (!this.#definition[featureName]?.(ctx)())() return false; + // when decision s deferred to this feature then don't care + // when deicison is false + const deps = this.dependencies[featureName]?? [] + if (!deps.every(dep => this.isEnabled(dep, ctx))) return false + return true + } + +} + + +abilities.define("read", {blockIds} => { + if (!blockIds) +}) + +abilities.can("read", {blockIds}) + +abilities.define("block.setPositionX", ([id, value] => { + if (!id) return "deny" + // if (!value) we don't care about the value here +// can cehck wether or not to run +})) +abilities.define("block.setPositionX", ["block.arrange"]) + +// put a lock in front of setPosition +// this modifies the prototype +abilities.lock("block.setPositionX", setPosition, Block) + + +abilities.setPermission("block.setPosition") + +block.setPosition.can?(blockId) + +block.setPosition.allowed?(BlockId) + + +block.setPosition?.(blockId, value) +// check feature avaiability else use +blcok = ability.guard(block) //this will create a proxy to the object with each function being overwritten + +if (!block) return +if (!block.setPosition) return +if (!block.getPosition) return +if (!block.value) return + + +//enabled +//permission +//other + + +``` \ No newline at end of file diff --git a/packages/plugin-vectorizer/README.md b/packages/plugin-vectorizer/README.md new file mode 100644 index 0000000..6acc73e --- /dev/null +++ b/packages/plugin-vectorizer/README.md @@ -0,0 +1,40 @@ +# IMG.LY CE.SDK Plugin Vectorizer + +This plugin introduces a vectorizer for the CE.SDK editor. + +## Installation + +You can install the plugin via npm or yarn. Use the following commands to install the package: + +``` +yarn add @imgly/plugin-vectorizer +npm install @imgly/plugin-vectorizer +``` + +## Usage + +Adding the plugin to CE.SDK will automatically add a vectorizer +canvas menu entry for every block with an image fill. + +```typescript +import CreativeEditorSDK from '@cesdk/cesdk-js'; +import VectorizerPlugin from '@imgly/plugin-vectorizer'; + +const config = { + license: '', + callbacks: { + // Please note that the vectorizer plugin depends on an correctly + // configured upload. 'local' will work for local testing, but in + // production you will need something stable. Please take a look at: + // https://img.ly/docs/cesdk/ui/guides/upload-images/ + onUpload: 'local' + } +}; + +const cesdk = await CreativeEditorSDK.create(container, config); +await cesdk.addDefaultAssetSources(), + await cesdk.addDemoAssetSources({ sceneMode: 'Design' }), + await cesdk.unstable_addPlugin(VectorizerPlugin()); + +await cesdk.createDesignScene(); +``` diff --git a/packages/plugin-vectorizer/STRUCTURE.md b/packages/plugin-vectorizer/STRUCTURE.md new file mode 100644 index 0000000..13b1472 --- /dev/null +++ b/packages/plugin-vectorizer/STRUCTURE.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/plugin-vectorizer/TODO.md b/packages/plugin-vectorizer/TODO.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/plugin-vectorizer/esbuild/config.mjs b/packages/plugin-vectorizer/esbuild/config.mjs new file mode 100644 index 0000000..37b437c --- /dev/null +++ b/packages/plugin-vectorizer/esbuild/config.mjs @@ -0,0 +1,58 @@ +import chalk from 'chalk'; +import { readFile } from 'fs/promises'; + +// import packageJson from '../package.json' assert { type: 'json' }; +// Avoid the Experimental Feature warning when using the above. +const packageJson = JSON.parse( + await readFile(new URL('../package.json', import.meta.url)) +); + + +const dependencies = Object.keys(packageJson.dependencies) +const peerDependencies = Object.keys(packageJson.peerDependencies) +const externals = [...dependencies, ...peerDependencies] + +console.log( + chalk.yellow('Building version: '), + chalk.green(packageJson.version) +); + +const configs = [ + { + entryPoints: ['src/index.ts', "src/worker.ts"], + define: { + PLUGIN_VERSION: `"${packageJson.version}"` + }, + minify: true, + bundle: true, + sourcemap: true, + external: externals, + platform: 'node', + format: 'esm', + outdir: 'dist', + outExtension: { '.js': '.mjs' }, + plugins: [ + { + name: 'reporter', + setup(build) { + build.onEnd((result) => { + console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] Build ${ + result.errors.length + ? chalk.red('failed') + : chalk.green('succeeded') + }` + ); + }); + } + } + ] + } +]; + +export default configs; diff --git a/packages/plugin-vectorizer/esbuild/global.d.ts b/packages/plugin-vectorizer/esbuild/global.d.ts new file mode 100644 index 0000000..de80fd8 --- /dev/null +++ b/packages/plugin-vectorizer/esbuild/global.d.ts @@ -0,0 +1,3 @@ +// These constants here are added by the base esbuild config + +declare const PLUGIN_VERSION: string; diff --git a/packages/plugin-vectorizer/manifest.json b/packages/plugin-vectorizer/manifest.json new file mode 100644 index 0000000..d277b70 --- /dev/null +++ b/packages/plugin-vectorizer/manifest.json @@ -0,0 +1,67 @@ +{ + "id": "vectorizer", + "version": "1.0.0", + "publisher": "IMG.LY GmbH", + "icon": "", + "license": "", + "pricing": "free", + "payment": { + "oneTime": 0, + "subscription": 0, + "usage": 0 + }, + "engines": { + "imgly": ">2.0.0" + }, + "categories": [ + "image", + "vector" + ], + "contributes": { + "ui": { + "button": { + "id": "vectorizer.ui.button", + "label": "vectorizer.ui.button" + } + }, + "commands": { + "vectorize": { + "id": "vectorizer.commands.vectorize", + "label": "vectorizer.commands.vectorize", + "group": "convert", + "args": [ + { + "type": "number", + "format": "", + "ui": "slider" + } + ], + "returns": {} + } + }, + "i18n": { + "vectorizer.commands.vectorize": "Convert into Vectorpath", + "vectorizer.commands.category": "Vectorizer", + "vectorizer.config.title": "Vectorizer", + "vectorizer.config.enabled": "Enable Vectorizer", + "vectorizer.config.enabled.description": "Enable or disable the vectorizer" + }, + "errors": { + "validationError": { + "id": "vectorizer.errors.validationError", + "message": "vectorizer.errors.validationError.message" + } + }, + "config": { + "type": "object", + "title": "vectorizer.config.titel", + "settings": { + "enabled": { + "type": "boolean", + "default": true, + "description": "vectorizer.config.settings.enabled.description" + } + } + } + } +} \ No newline at end of file diff --git a/packages/plugin-vectorizer/package.json b/packages/plugin-vectorizer/package.json new file mode 100644 index 0000000..6ac69e3 --- /dev/null +++ b/packages/plugin-vectorizer/package.json @@ -0,0 +1,70 @@ +{ + "name": "@imgly/plugin-vectorizer", + "version": "0.1.0", + "description": "Vectorizer plugin for the CE.SDK editor", + "keywords": [ + "CE.SDK", + "plugin", + "svg", + "vectorizer" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/imgly/plugins.git" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "IMG.LY GmbH", + "email": "support@img.ly", + "url": "https://img.ly" + }, + "bugs": { + "email": "support@img.ly" + }, + "source": "./src/index.ts", + "module": "./dist/index.mjs", + "types": "./types/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "types": "./types/index.d.ts" + } + }, + "homepage": "https://img.ly", + "files": [ + "LICENSE.md", + "README.md", + "CHANGELOG.md", + "dist/", + "types/", + "bin/" + ], + "scripts": { + "start": "npm run watch", + "clean": "npx rimraf dist && npx rimraf types", + "build": "yarn run clean && yarn run types:create && node scripts/build.mjs", + "dev": "yarn run types:create && node scripts/watch.mjs", + "publish:latest": "npm run clean && npm run build && npm publish --tag latest --access public", + "publish:next": "npm run clean && npm run build && npm publish --tag next --access public", + "check:all": "concurrently -n lint,type,pretty \"yarn check:lint\" \"yarn check:type\" \"yarn check:pretty\"", + "check:lint": "eslint --max-warnings 0 './src/**/*.{ts,tsx}'", + "check:pretty": "prettier --list-different './src/**/*.{ts,tsx}'", + "check:type": "tsc --noEmit", + "types:create": "tsc --emitDeclarationOnly" + }, + "devDependencies": { + "chalk": "^5.3.0", + "concurrently": "^8.2.2", + "esbuild": "^0.19.11", + "eslint": "^8.51.0", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "@cesdk/cesdk-js": "~1.21.0" + }, + "dependencies": { + "@imgly/vectorizer": "~0.1.0-rc6", + "@imgly/plugin-core": "*", + "lodash": "^4.17.21" + } +} diff --git a/packages/plugin-vectorizer/scripts/build.mjs b/packages/plugin-vectorizer/scripts/build.mjs new file mode 100644 index 0000000..13d12e1 --- /dev/null +++ b/packages/plugin-vectorizer/scripts/build.mjs @@ -0,0 +1,5 @@ +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +await Promise.all(configs.map(async (config) => await esbuild.build(config))); diff --git a/packages/plugin-vectorizer/scripts/watch.mjs b/packages/plugin-vectorizer/scripts/watch.mjs new file mode 100644 index 0000000..15dbb21 --- /dev/null +++ b/packages/plugin-vectorizer/scripts/watch.mjs @@ -0,0 +1,19 @@ +import chalk from 'chalk'; +import * as esbuild from 'esbuild'; + +import configs from '../esbuild/config.mjs'; + +console.log( + `[${new Date().toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: false + })}] ${chalk.green('Watching...')}` +); + +const contexts = await Promise.all( + configs.map((config) => esbuild.context(config)) +); + +await Promise.any(contexts.map((ctx) => ctx.watch())); diff --git a/packages/plugin-vectorizer/src/PluginManifest.ts b/packages/plugin-vectorizer/src/PluginManifest.ts new file mode 100644 index 0000000..0477289 --- /dev/null +++ b/packages/plugin-vectorizer/src/PluginManifest.ts @@ -0,0 +1,16 @@ +import Manifest from '../manifest.json'; +type ManifestType = typeof Manifest; + +// TODO: Extend this with the builtin commands from other packages + +// Contributions + +export type I18NKeys = keyof ManifestType["contributes"]["i18n"] +export type CommandContributions = keyof ManifestType["contributes"]["commands"] +export type ErrorKeys = keyof ManifestType["contributes"]["errors"] + +export type UIComponentKeys = keyof ManifestType["contributes"]["ui"] +export type ConfigKeys = keyof ManifestType["contributes"]["config"] + +export const PluginManifest = Manifest + diff --git a/packages/plugin-vectorizer/src/activate.ts b/packages/plugin-vectorizer/src/activate.ts new file mode 100644 index 0000000..4e9065a --- /dev/null +++ b/packages/plugin-vectorizer/src/activate.ts @@ -0,0 +1,90 @@ +import { PluginManifest, CommandContributions, UIComponentKeys } from './PluginManifest'; + +import { + fixDuplicateMetadata, + getPluginMetadata, + isDuplicate, +} from './utils/common'; + +import { PluginContext, CommandCallback } from './deps'; +import { update as handleUpdateEvent } from './handler'; + + +export async function activate(ctx: PluginContext) { + // const { engine, logger, i18n, ui, commands } = ctx + + + //@ts-ignore + ctx.logger?.trace("checking if engine has commands", cesdk.engine.commands ? "yes" : "no") + + { + ctx.logger?.trace("Registering commands") + type CommandsDef = Record + const commands: CommandsDef = await import('./commands') + + for (const command in commands) { + const callback = commands[command as CommandContributions] + const desc = PluginManifest.contributes.commands[command as CommandContributions]; + ctx.commands.registerCommand(desc.id, + async (params: any) => await callback(ctx as any, params), + desc + ); + } + } + + { + type UIComponentDefs = Record any> + const uiComponents: UIComponentDefs = await import('./ui') + + for (const key in uiComponents) { + const callback = uiComponents[key as UIComponentKeys] + + ctx.ui?.unstable_registerComponent( + PluginManifest.contributes.ui[key as UIComponentKeys].id, + (params: any) => callback(ctx, params)); + } + } + + + { + // FIXME: This should probablly be done automagically + ctx.logger?.trace("Registering I18N translations") + ctx.i18n.setTranslations({ en: PluginManifest.contributes.i18n }) + } + + + { + ctx.logger?.trace("Subscribing to events"); + const unsubscribe = ctx.engine.event.subscribe([], async (events) => { + events + .filter(e => ctx.engine.block.isValid(e.block) && ctx.engine.block.hasMetadata(e.block, PluginManifest.id)) + .filter(e => e.type === 'Updated') + .forEach(e => handleUpdateEvent(ctx.engine, e.block)) + }); + } + { + const unsubscribe = ctx.engine.event.subscribe([], async (events) => { + events + .filter(({ block: blockId }) => ctx.engine.block.isValid(blockId) && ctx.engine.block.hasMetadata(blockId, PluginManifest.id)) + .forEach(({ type, block: blockId }) => { + if (type === 'Created') { + const metadata = getPluginMetadata(ctx.engine, blockId); + if (isDuplicate(ctx.engine, blockId, metadata)) { + fixDuplicateMetadata(ctx.engine, blockId); + } + } + }); + }); + } + // { + // // THIS DOES not belong here maybe + // ctx.logger?.trace("Defaulting canvas menu order") + // const canvasMenuEntries = [ + // PluginManifest.contributes.ui.button.id, + // ...ctx.ui?.unstable_getCanvasMenuOrder() ?? [] + // ] + // ctx.ui?.unstable_setCanvasMenuOrder(canvasMenuEntries); + // } +} + +// maybe this should be just engine.event.onUpdate() diff --git a/packages/plugin-vectorizer/src/commands.ts b/packages/plugin-vectorizer/src/commands.ts new file mode 100644 index 0000000..6676f50 --- /dev/null +++ b/packages/plugin-vectorizer/src/commands.ts @@ -0,0 +1,197 @@ +import { + getPluginMetadata, + isBlockSupported, + isMetadataConsistent, + recoverInitialImageData, + setPluginMetadata + +} from './utils/common'; + +import { runInWorker } from './utils/worker.shared'; +import { createVectorPathBlocks } from './utils/cesdk+utils'; +import { PluginContext } from './deps'; + +export const vectorize = async (context: PluginContext, params: { blockIds?: number[] }) => { + const uploader: any = undefined; //cesdk.unstable_upload.bind(cesdk) + const {engine} = context; // the only function that needs the ui is the upload function + const blockApi = engine.block; + + + const blockIds = params.blockIds ?? engine.block.findAllSelected(); + + blockIds.forEach(async (blockId: number) => { + // this should happen before already and only be called if the feature is enabled for a certain block + if (!isBlockSupported(engine, blockId)) return; + + + if (!blockApi.hasFill(blockId)) + throw new Error('Block has no fill to vectorize'); + + const fillId = blockApi.getFill(blockId); + + // FIXME: Tis is only needed to tell the engin that we are processing something and it cannot export or save the scene file. + // Practicalle, we are not using the images directly but render the visible part of the block and then process this image + // Get the current image URI and source set as initial values. + const initialSourceSet = blockApi.getSourceSet(fillId, 'fill/image/sourceSet'); + const initialImageFileURI = blockApi.getString(fillId, 'fill/image/imageFileURI'); + const initialPreviewFileURI = blockApi.getString(fillId, 'fill/image/previewFileURI'); + + + const uriToProcess = + // Source sets have priority in the engine + initialSourceSet.length > 0 + ? // Choose the highest resolution image in the source set + initialSourceSet.sort( + (a: any, b: any) => b.width * b.height - a.height * a.width + )[0].uri + : initialImageFileURI; + + if (uriToProcess === undefined || uriToProcess === '') + return; // We shall return early if the uri is not defined or invalid + + try { + // Clear values in the engine to trigger the loading spinner + // @ts-ignore + const blob = await engine.block.export(blockId, "image/png"); + + // go into busy state + blockApi.setString(fillId, 'fill/image/imageFileURI', ''); + blockApi.setSourceSet(fillId, 'fill/image/sourceSet', []); + // ensure we show the last image while processsing. Some images don't have the preview set + if (initialPreviewFileURI === undefined || initialPreviewFileURI === '') { + blockApi.setString(fillId, 'fill/image/previewFileURI', uriToProcess); + } + + const metadata = getPluginMetadata(engine, blockId); + setPluginMetadata(engine, blockId, { + ...metadata, + version: PLUGIN_VERSION, + initialSourceSet, + initialImageFileURI, + blockId, + fillId, + status: 'PROCESSING' + }); + + const vectorized: Blob = await runInWorker(blob) + + if ( + getPluginMetadata(engine, blockId).status !== 'PROCESSING' || + !isMetadataConsistent(engine, blockId) + ) return; + if (engine.block.isValid(blockId)) { + setPluginMetadata(engine, blockId, { + version: PLUGIN_VERSION, + initialSourceSet, + initialImageFileURI, + blockId, + fillId, + status: 'PROCESSED', + }); + } + + + if (vectorized.type.length === 0 || vectorized.type === 'image/svg+xml') { + const pathname = new URL(uriToProcess).pathname; + const parts = pathname.split('/'); + const filename = parts[parts.length - 1]; + + const uploadedAssets = await uploader( + new File([vectorized], filename, { type: vectorized.type }), + () => { + // TODO Delegate process to UI component + } + ); + + // Check for externally changed state while we were uploading and + // do not proceed if the state was reset. + if ( + getPluginMetadata(engine, blockId).status !== 'PROCESSING' || + !isMetadataConsistent(engine, blockId) + ) + return; + + const url = uploadedAssets.meta?.uri;; + if (url == null) { + throw new Error('Could not upload vectorized image'); + } + + // Workaround Processing is done, restore state of the initial block + blockApi.setSourceSet(fillId, 'fill/image/sourceSet', initialSourceSet); + blockApi.setString(fillId, 'fill/image/imageFileURI', initialImageFileURI); + blockApi.setString(fillId, 'fill/image/previewFileURI', initialPreviewFileURI); + + setPluginMetadata(engine, blockId, { + version: PLUGIN_VERSION, + initialSourceSet, + initialImageFileURI, + blockId, + fillId, + status: 'PROCESSED', + }); + + blockApi.setString(fillId, 'fill/image/imageFileURI', url); + } else if (vectorized.type === 'application/json') { + + const json = await vectorized.text() + const blocks = JSON.parse(json) + const blockIds = createVectorPathBlocks(engine, blocks) + + const origRotation = engine.block.getRotation(blockId) + const origX = engine.block.getPositionX(blockId) + const origY = engine.block.getPositionY(blockId) + const origSelected = engine.block.isSelected(blockId) + + switch (engine.block.getType(blockId)) { + case "//ly.img.ubq/page": // this has been disabled + { + const parentId = blockId; + const containerId = engine.block.group(blockIds); + engine.block.appendChild(parentId, containerId); + const scale = engine.block.getFrameWidth(blockId) / engine.block.getFrameWidth(containerId) + engine.block.setPositionX(containerId, origX) + engine.block.setPositionY(containerId, origY) + engine.block.setRotation(containerId, origRotation) + engine.block.scale(containerId, scale) + engine.block.setFillEnabled(parentId, false) + engine.block.setSelected(containerId, origSelected) + break; + } + case "//ly.img.ubq/graphic": + default: { // replace the current block with the a new group of the vectors + const parentId = engine.block.getParent(blockId)! + const containerId = engine.block.group(blockIds); + engine.block.appendChild(parentId, containerId); + const scale = engine.block.getFrameWidth(blockId) / engine.block.getFrameWidth(containerId) + engine.block.setPositionX(containerId, origX) + engine.block.setPositionY(containerId, origY) + engine.block.setRotation(containerId, origRotation) + engine.block.scale(containerId, scale) + engine.block.destroy(blockId) + engine.block.setSelected(containerId, origSelected) + break; + } + } + } + // Finally, create an undo step + engine.editor.addUndoStep(); + + } catch (error) { + if (engine.block.isValid(blockId)) { + setPluginMetadata(engine, blockId, { + version: PLUGIN_VERSION, + initialSourceSet, + initialImageFileURI, + blockId, + fillId, + status: 'ERROR' + }); + + recoverInitialImageData(engine, blockId); + } + // eslint-disable-next-line no-console + console.error(error); + } + }) +} + diff --git a/packages/plugin-vectorizer/src/deps.ts b/packages/plugin-vectorizer/src/deps.ts new file mode 100644 index 0000000..e72ca92 --- /dev/null +++ b/packages/plugin-vectorizer/src/deps.ts @@ -0,0 +1,6 @@ +import { I18NKeys } from "./PluginManifest"; +import { type PluginContext as IPluginContext, CommandCallback } from '@imgly/plugin-core'; +type PluginContext = IPluginContext; + +export { CreativeEngine } from '@cesdk/cesdk-js'; +export { type PluginContext, type CommandCallback } diff --git a/packages/plugin-vectorizer/src/handler.ts b/packages/plugin-vectorizer/src/handler.ts new file mode 100644 index 0000000..16cdf6f --- /dev/null +++ b/packages/plugin-vectorizer/src/handler.ts @@ -0,0 +1,28 @@ +import {CreativeEngine} from "@cesdk/cesdk-js"; + +import { + clearPluginMetadata, + getPluginMetadata, + isMetadataConsistent +} from './utils/common'; +/** + * Handle every possible state of the vectorization state if the block was + * updated. + */ +export async function update(engine: CreativeEngine, blockId: number) { + const metadata = getPluginMetadata(engine, blockId); + switch (metadata.status) { + case 'PROCESSING': + case 'PROCESSED': { + if (!isMetadataConsistent(engine, blockId)) { + clearPluginMetadata(engine, blockId); + } + break; + } + + default: { + // We do not care about other states + } + } + } + \ No newline at end of file diff --git a/packages/plugin-vectorizer/src/index.ts b/packages/plugin-vectorizer/src/index.ts new file mode 100644 index 0000000..ffeba26 --- /dev/null +++ b/packages/plugin-vectorizer/src/index.ts @@ -0,0 +1,26 @@ +import Manifest from '../manifest.json'; +import { PluginContext } from "./deps"; + +import { activate } from './activate'; + + + +export interface PluginConfiguration { + +} + +export { Manifest }; + +export default (ctx: PluginContext, pluginConfiguration: PluginConfiguration) => { + + return { + ...Manifest, + async initializeUserInterface() { + return await activate(ctx) + }, + + // maybe this should be just engine.event.onUpdate() + + }; +}; +'' \ No newline at end of file diff --git a/packages/plugin-vectorizer/src/ui.ts b/packages/plugin-vectorizer/src/ui.ts new file mode 100644 index 0000000..abcf2b2 --- /dev/null +++ b/packages/plugin-vectorizer/src/ui.ts @@ -0,0 +1,29 @@ +import { PluginContext } from './deps'; + +import { PluginManifest } from './PluginManifest'; + +import { + getPluginMetadata, + isBlockSupported, +} from './utils/common'; + + +export const button = (ctx: PluginContext, params: any) => { + const builder = params.builder + + const selected = ctx.engine.block.findAllSelected(); + const candidates = selected.filter((id: number) => isBlockSupported(ctx.engine, id)) + if (candidates.length === 0) return; + const isLoading = candidates.some((id: number) => getPluginMetadata(ctx.engine, id).status === 'PROCESSING') + + // @maerch: Why do we need the Button ID here? + builder.Button(PluginManifest.contributes.ui.button.id, { + label: ctx.i18n.translate("vectorizer.commands.vectorize"), + icon: '@imgly/icons/Vectorize', + isActive: false, + isLoading: isLoading, + isDisabled: isLoading, + loadingProgress: undefined, // creates infinite spinner + onClick: () => ctx.commands.executeCommand(PluginManifest.contributes.commands.vectorize.id, { blockIds: candidates }) + }); +} diff --git a/packages/plugin-vectorizer/src/utils/cesdk+utils.ts b/packages/plugin-vectorizer/src/utils/cesdk+utils.ts new file mode 100644 index 0000000..82fcf7f --- /dev/null +++ b/packages/plugin-vectorizer/src/utils/cesdk+utils.ts @@ -0,0 +1,37 @@ +import { CreativeEngine } from "@cesdk/cesdk-js"; + +export const createVectorPathBlocks = (engine: CreativeEngine, blocks: any[]) => { + const blockIds = blocks.map((block: any) => { + const id = createVectorPathBlock( + engine, block + ) + + return id + }) + + return blockIds +} + + +export const createVectorPathBlock = (engine: CreativeEngine, block: any) => { + + const path = block.shape.path + const color = block.fill.color + const blockId = engine.block.create("//ly.img.ubq/graphic"); + engine.block.setKind(blockId, "shape"); + const shape = engine.block.createShape("//ly.img.ubq/shape/vector_path"); + engine.block.setShape(blockId, shape); + + engine.block.setString(shape, "vector_path/path", path); + engine.block.setFloat(shape, "vector_path/width", block.transform.width); + engine.block.setFloat(shape, "vector_path/height", block.transform.height); + + const fill = engine.block.createFill("color"); + engine.block.setColor(fill, "fill/color/value", { r: color[0], g: color[1], b: color[2], a: color[3] }); + engine.block.setFill(blockId, fill); + engine.block.setFloat(blockId, "width", block.transform.width); + engine.block.setFloat(blockId, "height", block.transform.height); + engine.block.setPositionX(blockId, block.transform.x) + engine.block.setPositionY(blockId, block.transform.y) + return blockId; +} diff --git a/packages/plugin-vectorizer/src/utils/common.ts b/packages/plugin-vectorizer/src/utils/common.ts new file mode 100644 index 0000000..9b2bd81 --- /dev/null +++ b/packages/plugin-vectorizer/src/utils/common.ts @@ -0,0 +1,299 @@ +import { CreativeEngine } from '@cesdk/cesdk-js'; +import isEqual from 'lodash/isEqual'; + +import { + PluginMetadata, + PluginStatusError, + PluginStatusProcessed, + PluginStatusProcessing +} from './types'; + +import { PluginManifest as manifest } from '../PluginManifest'; + + +export const areBlocksSupported = (engine: CreativeEngine, blockIds: number[]) => { + return blockIds.some(id => isBlockSupported(engine, id)) +} +/** + * Checks if a block is supported by the given CreativeEngine. + * @param engine - The CreativeEngine instance. + * @param blockId - The ID of the block to check. + * @returns A boolean indicating whether the block is supported or not. + */ +export const isBlockSupported = (engine: CreativeEngine, blockId: number) => { + if (!engine.block.isValid(blockId)) return false; + const blockType = engine.block.getType(blockId); + if (blockType === "//ly.img.ubq/page") return false; // There is some bug with the page block + + if (engine.block.hasFill(blockId)) { + const fillId = engine.block.getFill(blockId); + const fillType = engine.block.getType(fillId); + if (fillType !== '//ly.img.ubq/fill/image') { + return false; + } + return true + } + + return false; +} + +/** + * Sets the metadata for the plugin state. + */ +export function setPluginMetadata( + engine: CreativeEngine, + id: number, + metadata: PluginMetadata +) { + engine.block.setMetadata(id, manifest.id, JSON.stringify(metadata)); +} + +/** + * Returns the current metadata for the plugin state. If no metadata + * is set on the given block, it will return an IDLE state. + */ +export function getPluginMetadata( + engine: CreativeEngine, + id: number +): PluginMetadata { + if (engine.block.hasMetadata(id, manifest.id)) { + return JSON.parse(engine.block.getMetadata(id, manifest.id)); + } else { + return { + status: 'IDLE' + }; + } +} + +/** + * If plugin metadata is set, it will be cleared. + */ +export function clearPluginMetadata(engine: CreativeEngine, id: number) { + if (engine.block.hasMetadata(id, manifest.id)) { + engine.block.removeMetadata(id, manifest.id); + } +} + +/** + * Detect if the block has been duplicated with processed or processing state. + * In that case the plugin state is still valid, but blockId and fillId have changed. + */ +export function isDuplicate( + engine: CreativeEngine, + blockId: number, + metadata: PluginMetadata +): boolean { + if (!engine.block.isValid(blockId)) return false; + if (metadata.status === 'IDLE' || metadata.status === 'ERROR') + return false; + + if (!engine.block.hasFill(blockId)) return false; + const fillId = engine.block.getFill(blockId); + + // It cannot be a duplicate if the blockId or fillId are the same + if (metadata.blockId === blockId || metadata.fillId === fillId) return false; + + return true; +} + +/** + * Fixes the metadata if the block has been duplicated, i.e. the blockId and + * fillId will be updated to the current block/fill. + * + * Please note: Call this method only on duplicates (see isDuplicate). + */ +export function fixDuplicateMetadata( + engine: CreativeEngine, + blockId: number +) { + const fillId = engine.block.getFill(blockId); + const metadata = getPluginMetadata(engine, blockId); + if ( + metadata.status === 'IDLE' || + // metadata.status === 'PENDING' || + metadata.status === 'ERROR' + ) + return; + setPluginMetadata(engine, blockId, { + ...metadata, + blockId, + fillId + }); +} + +/** + * Check if the image has a consisten metadata state. A inconsistent state is + * caused by outside changes of the fill data. + * + * @returns true if the metadata is consistent, false otherwise + */ +export function isMetadataConsistent( + engine: CreativeEngine, + blockId: number +): boolean { + // In case the block was removed, we just abort and mark it + // as reset by returning true + if (!engine.block.isValid(blockId)) return false; + const metadata = getPluginMetadata(engine, blockId); + if (metadata.status === 'IDLE' + // || metadata.status === 'PENDING' + ) return true; + + if (!engine.block.hasFill(blockId)) return false; + const fillId = engine.block.getFill(blockId); + if (fillId == null) return false; + + if (blockId !== metadata.blockId || fillId !== metadata.fillId) return false; + + const sourceSet = engine.block.getSourceSet( + fillId, + 'fill/image/sourceSet' + ); + const imageFileURI = engine.block.getString( + fillId, + 'fill/image/imageFileURI' + ); + + if ( + sourceSet.length === 0 && + !imageFileURI && + metadata.status === 'PROCESSING' + ) { + // While we process it is OK to have no image file URI and no source set + // (which we cleared to show the spinning loader) + return true; + } + + // Source sets have precedence over imageFileURI so if we have a source set, + // we only need to check if it has changed to something else. + if (sourceSet?.length > 0) { + const initialSourceSet = metadata.initialSourceSet; + // If we have already processed the image, we need to check if the source set + // we need to check against both source sets, the removed and the initial + if ( + metadata.status === 'PROCESSED' + ) { + // const processedAsset = metadata.processedAsset; + if ( + // !isEqual(sourceSet, processedAsset) && + !isEqual(sourceSet, initialSourceSet) + ) { + return false; + } + } else { + if (!isEqual(sourceSet, initialSourceSet)) { + return false; + } + } + } else { + if (metadata.status === 'PROCESSED') { + if ( + imageFileURI !== metadata.initialImageFileURI + // &&imageFileURI !== metadata.processedAsset + ) { + return false; + } + } else { + if (imageFileURI !== metadata.initialImageFileURI) { + return false; + } + } + } + return true; +} + + +/** + * Recover the initial values to avoid the loading spinner and have the same + * state as before the process was started. + */ +export function recoverInitialImageData( + engine: CreativeEngine, + blockId: number +) { + const blockApi = engine.block; + if (!blockApi.hasFill(blockId)) return; // Nothing to recover (no fill anymore) + + const metadata = getPluginMetadata(engine, blockId); + + if ( + // metadata.status === 'PENDING' || + metadata.status === 'IDLE') { + return; + } + + const initialSourceSet = metadata.initialSourceSet; + const initialImageFileURI = metadata.initialImageFileURI; + + const fillId = getValidFill(engine, blockId, metadata); + if (fillId == null) return; + + if (initialImageFileURI) { + engine.block.setString( + fillId, + 'fill/image/imageFileURI', + initialImageFileURI + ); + } + if (initialSourceSet.length > 0) { + engine.block.setSourceSet( + fillId, + 'fill/image/sourceSet', + initialSourceSet + ); + } +} + +/** + * Returns the fill id of the block if it has a valid fill that was used for + * vectorizing. Returns undefined otherwise. + */ +function getValidFill( + engine: CreativeEngine, + blockId: number, + metadata: PluginStatusProcessing | PluginStatusError | PluginStatusProcessed +): number | undefined { + if ( + !engine.block.isValid(blockId) || + !engine.block.hasFill(blockId) || + blockId !== metadata.blockId + ) { + return undefined; + } + const fillId = engine.block.getFill(blockId); + if (fillId !== metadata.fillId) { + return undefined; + } + + return fillId; +} + + + +// These don't belong here + +export class Scheduler { + #queue?: Promise = undefined + + async schedule(task: () => Promise): Promise { + if (this.#queue === undefined) { + this.#queue = task() + } else { + this.#queue = this.#queue.then(async () => { + return await task() + }) + } + return this.#queue + } +} + + +/** + * Generates a unique filename. + * @returns A string representing the unique filename. + */ +export function generateUniqueFilename(): string { + const timestamp = Date.now(); + const randomString = Math.random().toString(36).substring(2, 8); + return `${timestamp}_${randomString}`; +} \ No newline at end of file diff --git a/packages/plugin-vectorizer/src/utils/types.ts b/packages/plugin-vectorizer/src/utils/types.ts new file mode 100644 index 0000000..657f9de --- /dev/null +++ b/packages/plugin-vectorizer/src/utils/types.ts @@ -0,0 +1,52 @@ +import { type Source, type CreativeEngine } from '@cesdk/cesdk-js'; + +export type PluginStatusIdle = { status: 'IDLE' }; +// export type PluginStatusPending = { status: 'PENDING' }; + +export type PluginStatusProcessing = { + version: string; + status: 'PROCESSING'; + + initialImageFileURI: string; + initialSourceSet: Source[]; + + blockId: number; + fillId: number; + + progress?: { + key: string; + current: number; + total: number; + }; +}; + +export type PluginStatusProcessed = { + version: string; + status: 'PROCESSED' + + initialImageFileURI: string; + initialSourceSet: Source[]; + + blockId: number; + fillId: number; +}; + +export type PluginStatusError = { + version: string; + status: 'ERROR'; + + initialImageFileURI: string; + initialSourceSet: Source[]; + + blockId: number; + fillId: number; +}; + +export type PluginMetadata = + | PluginStatusIdle + | PluginStatusError + | PluginStatusProcessing + | PluginStatusProcessed; + + + diff --git a/packages/plugin-vectorizer/src/utils/worker.shared.ts b/packages/plugin-vectorizer/src/utils/worker.shared.ts new file mode 100644 index 0000000..c270865 --- /dev/null +++ b/packages/plugin-vectorizer/src/utils/worker.shared.ts @@ -0,0 +1,25 @@ +export interface MessageBody { + method: 'health' | 'imageToJson' | 'imageToSvg' + data?: any; + error?: Error +} + +const TIMEOUT_DEFAULT = 10000 +// we need a timeout +export const runInWorker = (blob: Blob) => new Promise((resolve, reject) => { + const worker = new Worker(new URL('./worker', import.meta.url), { type: 'module' }); + const msg: MessageBody = { method: "imageToJson", data: blob } + setTimeout(() => reject(new Error("Timeout")), TIMEOUT_DEFAULT); + worker.postMessage(msg) + worker.onmessage = (e: MessageEvent) => { + const msg = e.data + if (msg.error) { + reject(msg.error) + return; + } + resolve(msg.data) + // when done terminate + worker.terminate() + } + +}) diff --git a/packages/plugin-vectorizer/src/worker.ts b/packages/plugin-vectorizer/src/worker.ts new file mode 100644 index 0000000..8fd1eab --- /dev/null +++ b/packages/plugin-vectorizer/src/worker.ts @@ -0,0 +1,34 @@ + +import type { MessageBody } from "./utils/worker.shared"; +import * as vectorizer from '@imgly/vectorizer'; + +self.onmessage = async function (e: MessageEvent) { + try { + const msg = e.data; 0 + const data = msg.data ?? {} + const method = msg.method ?? '' // default to empty string + switch (method) { + case "health": { + postMessage({ data: 'ok' }) + break; + } + case "imageToJson": + { + const json = await vectorizer.imageToJson(data) + postMessage({ data: json }); + break; + } + case "imageToSvg": + { + const svg = await vectorizer.imageToSvg(data) + postMessage({ data: svg }); + + break; + } + default: + postMessage({ error: new Error("Unknown method") }); + } + } catch (err) { + postMessage({ error: err }); + } +} \ No newline at end of file diff --git a/packages/plugin-vectorizer/tsconfig.json b/packages/plugin-vectorizer/tsconfig.json new file mode 100644 index 0000000..445b415 --- /dev/null +++ b/packages/plugin-vectorizer/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es2017", + "module": "es2020", + "lib": ["es2018", "dom"], + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "declaration": true, + "declarationDir": "types/", + "skipLibCheck": true + }, + "include": ["src/**/*", "esbuild/global.d.ts", "manifest.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/plugin-vectorizer/types/PluginManifest.d.ts b/packages/plugin-vectorizer/types/PluginManifest.d.ts new file mode 100644 index 0000000..7913e0c --- /dev/null +++ b/packages/plugin-vectorizer/types/PluginManifest.d.ts @@ -0,0 +1,70 @@ +import Manifest from '../manifest.json'; +type ManifestType = typeof Manifest; +export type I18NKeys = keyof ManifestType["contributes"]["i18n"]; +export type CommandContributions = keyof ManifestType["contributes"]["commands"]; +export type ErrorKeys = keyof ManifestType["contributes"]["errors"]; +export type UIComponentKeys = keyof ManifestType["contributes"]["ui"]; +export type ConfigKeys = keyof ManifestType["contributes"]["config"]; +export declare const PluginManifest: { + id: string; + version: string; + publisher: string; + icon: string; + license: string; + pricing: string; + payment: { + oneTime: number; + subscription: number; + usage: number; + }; + engines: { + imgly: string; + }; + categories: string[]; + contributes: { + ui: { + button: { + id: string; + label: string; + }; + }; + commands: { + vectorize: { + id: string; + label: string; + group: string; + args: { + type: string; + format: string; + ui: string; + }[]; + returns: {}; + }; + }; + i18n: { + "vectorizer.commands.vectorize": string; + "vectorizer.commands.category": string; + "vectorizer.config.title": string; + "vectorizer.config.enabled": string; + "vectorizer.config.enabled.description": string; + }; + errors: { + validationError: { + id: string; + message: string; + }; + }; + config: { + type: string; + title: string; + settings: { + enabled: { + type: string; + default: boolean; + description: string; + }; + }; + }; + }; +}; +export {}; diff --git a/packages/plugin-vectorizer/types/activate.d.ts b/packages/plugin-vectorizer/types/activate.d.ts new file mode 100644 index 0000000..2c2cf5a --- /dev/null +++ b/packages/plugin-vectorizer/types/activate.d.ts @@ -0,0 +1,2 @@ +import { PluginContext } from './deps'; +export declare function activate(ctx: PluginContext): Promise; diff --git a/packages/plugin-vectorizer/types/commands.d.ts b/packages/plugin-vectorizer/types/commands.d.ts new file mode 100644 index 0000000..2932810 --- /dev/null +++ b/packages/plugin-vectorizer/types/commands.d.ts @@ -0,0 +1,4 @@ +import { PluginContext } from './deps'; +export declare const vectorize: (context: PluginContext, params: { + blockIds?: number[]; +}) => Promise; diff --git a/packages/plugin-vectorizer/types/deps.d.ts b/packages/plugin-vectorizer/types/deps.d.ts new file mode 100644 index 0000000..ab2960b --- /dev/null +++ b/packages/plugin-vectorizer/types/deps.d.ts @@ -0,0 +1,5 @@ +import { I18NKeys } from "./PluginManifest"; +import { type PluginContext as IPluginContext, CommandCallback } from '@imgly/plugin-core'; +type PluginContext = IPluginContext; +export { CreativeEngine } from '@cesdk/cesdk-js'; +export { type PluginContext, type CommandCallback }; diff --git a/packages/plugin-vectorizer/types/handler.d.ts b/packages/plugin-vectorizer/types/handler.d.ts new file mode 100644 index 0000000..35d222b --- /dev/null +++ b/packages/plugin-vectorizer/types/handler.d.ts @@ -0,0 +1,6 @@ +import { CreativeEngine } from "@cesdk/cesdk-js"; +/** + * Handle every possible state of the vectorization state if the block was + * updated. + */ +export declare function update(engine: CreativeEngine, blockId: number): Promise; diff --git a/packages/plugin-vectorizer/types/index.d.ts b/packages/plugin-vectorizer/types/index.d.ts new file mode 100644 index 0000000..0cc8e20 --- /dev/null +++ b/packages/plugin-vectorizer/types/index.d.ts @@ -0,0 +1,69 @@ +import Manifest from '../manifest.json'; +import { PluginContext } from "./deps"; +export interface PluginConfiguration { +} +export { Manifest }; +declare const _default: (ctx: PluginContext, pluginConfiguration: PluginConfiguration) => { + initializeUserInterface(): Promise; + id: string; + version: string; + publisher: string; + icon: string; + license: string; + pricing: string; + payment: { + oneTime: number; + subscription: number; + usage: number; + }; + engines: { + imgly: string; + }; + categories: string[]; + contributes: { + ui: { + button: { + id: string; + label: string; + }; + }; + commands: { + vectorize: { + id: string; + label: string; + group: string; + args: { + type: string; + format: string; + ui: string; + }[]; + returns: {}; + }; + }; + i18n: { + "vectorizer.commands.vectorize": string; + "vectorizer.commands.category": string; + "vectorizer.config.title": string; + "vectorizer.config.enabled": string; + "vectorizer.config.enabled.description": string; + }; + errors: { + validationError: { + id: string; + message: string; + }; + }; + config: { + type: string; + title: string; + settings: { + enabled: { + type: string; + default: boolean; + description: string; + }; + }; + }; + }; +}; +export default _default; diff --git a/packages/plugin-vectorizer/types/ui.d.ts b/packages/plugin-vectorizer/types/ui.d.ts new file mode 100644 index 0000000..943cb1c --- /dev/null +++ b/packages/plugin-vectorizer/types/ui.d.ts @@ -0,0 +1,2 @@ +import { PluginContext } from './deps'; +export declare const button: (ctx: PluginContext, params: any) => void; diff --git a/packages/plugin-vectorizer/types/utils/cesdk+utils.d.ts b/packages/plugin-vectorizer/types/utils/cesdk+utils.d.ts new file mode 100644 index 0000000..a5b5a9e --- /dev/null +++ b/packages/plugin-vectorizer/types/utils/cesdk+utils.d.ts @@ -0,0 +1,3 @@ +import { CreativeEngine } from "@cesdk/cesdk-js"; +export declare const createVectorPathBlocks: (engine: CreativeEngine, blocks: any[]) => number[]; +export declare const createVectorPathBlock: (engine: CreativeEngine, block: any) => number; diff --git a/packages/plugin-vectorizer/types/utils/common.d.ts b/packages/plugin-vectorizer/types/utils/common.d.ts new file mode 100644 index 0000000..2166d3f --- /dev/null +++ b/packages/plugin-vectorizer/types/utils/common.d.ts @@ -0,0 +1,56 @@ +import { CreativeEngine } from '@cesdk/cesdk-js'; +import { PluginMetadata } from './types'; +export declare const areBlocksSupported: (engine: CreativeEngine, blockIds: number[]) => boolean; +/** + * Checks if a block is supported by the given CreativeEngine. + * @param engine - The CreativeEngine instance. + * @param blockId - The ID of the block to check. + * @returns A boolean indicating whether the block is supported or not. + */ +export declare const isBlockSupported: (engine: CreativeEngine, blockId: number) => boolean; +/** + * Sets the metadata for the plugin state. + */ +export declare function setPluginMetadata(engine: CreativeEngine, id: number, metadata: PluginMetadata): void; +/** + * Returns the current metadata for the plugin state. If no metadata + * is set on the given block, it will return an IDLE state. + */ +export declare function getPluginMetadata(engine: CreativeEngine, id: number): PluginMetadata; +/** + * If plugin metadata is set, it will be cleared. + */ +export declare function clearPluginMetadata(engine: CreativeEngine, id: number): void; +/** + * Detect if the block has been duplicated with processed or processing state. + * In that case the plugin state is still valid, but blockId and fillId have changed. + */ +export declare function isDuplicate(engine: CreativeEngine, blockId: number, metadata: PluginMetadata): boolean; +/** + * Fixes the metadata if the block has been duplicated, i.e. the blockId and + * fillId will be updated to the current block/fill. + * + * Please note: Call this method only on duplicates (see isDuplicate). + */ +export declare function fixDuplicateMetadata(engine: CreativeEngine, blockId: number): void; +/** + * Check if the image has a consisten metadata state. A inconsistent state is + * caused by outside changes of the fill data. + * + * @returns true if the metadata is consistent, false otherwise + */ +export declare function isMetadataConsistent(engine: CreativeEngine, blockId: number): boolean; +/** + * Recover the initial values to avoid the loading spinner and have the same + * state as before the process was started. + */ +export declare function recoverInitialImageData(engine: CreativeEngine, blockId: number): void; +export declare class Scheduler { + #private; + schedule(task: () => Promise): Promise; +} +/** + * Generates a unique filename. + * @returns A string representing the unique filename. + */ +export declare function generateUniqueFilename(): string; diff --git a/packages/plugin-vectorizer/types/utils/types.d.ts b/packages/plugin-vectorizer/types/utils/types.d.ts new file mode 100644 index 0000000..c00d57f --- /dev/null +++ b/packages/plugin-vectorizer/types/utils/types.d.ts @@ -0,0 +1,34 @@ +import { type Source } from '@cesdk/cesdk-js'; +export type PluginStatusIdle = { + status: 'IDLE'; +}; +export type PluginStatusProcessing = { + version: string; + status: 'PROCESSING'; + initialImageFileURI: string; + initialSourceSet: Source[]; + blockId: number; + fillId: number; + progress?: { + key: string; + current: number; + total: number; + }; +}; +export type PluginStatusProcessed = { + version: string; + status: 'PROCESSED'; + initialImageFileURI: string; + initialSourceSet: Source[]; + blockId: number; + fillId: number; +}; +export type PluginStatusError = { + version: string; + status: 'ERROR'; + initialImageFileURI: string; + initialSourceSet: Source[]; + blockId: number; + fillId: number; +}; +export type PluginMetadata = PluginStatusIdle | PluginStatusError | PluginStatusProcessing | PluginStatusProcessed; diff --git a/packages/plugin-vectorizer/types/utils/worker.shared.d.ts b/packages/plugin-vectorizer/types/utils/worker.shared.d.ts new file mode 100644 index 0000000..bf21f38 --- /dev/null +++ b/packages/plugin-vectorizer/types/utils/worker.shared.d.ts @@ -0,0 +1,6 @@ +export interface MessageBody { + method: 'health' | 'imageToJson' | 'imageToSvg'; + data?: any; + error?: Error; +} +export declare const runInWorker: (blob: Blob) => Promise; diff --git a/packages/plugin-vectorizer/types/worker.d.ts b/packages/plugin-vectorizer/types/worker.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/plugin-vectorizer/types/worker.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/yarn.lock b/yarn.lock index 5795d64..56c98b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -232,6 +232,11 @@ resolved "https://registry.yarnpkg.com/@cesdk/cesdk-js/-/cesdk-js-1.21.0.tgz#0420fe4752a1d094e967214ee143af032691ccb0" integrity sha512-BX6iRshiYPoIetCzt/4BX91jZnq6NswPLm9lk7jlypDpdCAgoXsJT/94HzKi8IglhmWo18Zzggdg9rw8Wc4noQ== +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@esbuild/aix-ppc64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" @@ -379,6 +384,19 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== +"@headlessui/react@^1.6.4": + version "1.7.18" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.18.tgz#30af4634d2215b2ca1aa29d07f33d02bea82d9d7" + integrity sha512-4i5DOrzwN4qSgNsL4Si61VMkUcWbcSKueUV7sFhpHzQcSShdlHENE5+QBntMSRvHt8NyoFO2AGG8si9lq+w4zQ== + dependencies: + "@tanstack/react-virtual" "^3.0.0-beta.60" + client-only "^0.0.1" + +"@heroicons/react@^2.0.13": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.1.1.tgz#422deb80c4d6caf3371aec6f4bee8361a354dc13" + integrity sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA== + "@humanwhocodes/config-array@^0.11.13": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -411,6 +429,38 @@ onnxruntime-web "~1.17.0" zod "~3.21.0" +"@imgly/vectorizer@~0.1.0-rc6": + version "0.1.0-rc6" + resolved "https://registry.yarnpkg.com/@imgly/vectorizer/-/vectorizer-0.1.0-rc6.tgz#509bec4e78d2654e4e3413c19e6e462d9bc62c7f" + integrity sha512-Q3QbRfB74wHZFB/TojJOJsSOAR8ZkV/mLXD8AztcTrwG1dVOPYfrcsrqbFLnHNz7XSxB8xCvSzdZOtylgXXugg== + dependencies: + "@types/lodash" "^4.14.195" + "@types/node" "^20.3.1" + esbuild-plugin-polyfill-node "^0.3.0" + install "^0.13.0" + lodash "^4.17.21" + ndarray "^1.0.19" + npm "^10.3.0" + tslog "^4.9.2" + zod "^3.21.4" + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@isaacs/string-locale-compare@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" + integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== + "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -430,6 +480,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" @@ -443,6 +501,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jspm/core@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@jspm/core/-/core-2.0.1.tgz#3f08c59c60a5f5e994523ed6b0b665ec80adc94e" + integrity sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -464,6 +527,179 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@npmcli/agent@^2.0.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.1.tgz#8aa677d0a4136d57524336a35d5679aedf2d56f7" + integrity sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ== + dependencies: + agent-base "^7.1.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.1" + lru-cache "^10.0.1" + socks-proxy-agent "^8.0.1" + +"@npmcli/arborist@^7.2.1": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-7.4.0.tgz#6be8e6562945cdf87097f8f8c50d72c37b9eb832" + integrity sha512-VFsUaTrV8NR+0E2I+xhp6pPC5eAbMmSMSMZbS57aogLc6du6HWBPATFOaiNWwp1QTFVeP4aLhYixQM9hHfaAsA== + dependencies: + "@isaacs/string-locale-compare" "^1.1.0" + "@npmcli/fs" "^3.1.0" + "@npmcli/installed-package-contents" "^2.0.2" + "@npmcli/map-workspaces" "^3.0.2" + "@npmcli/metavuln-calculator" "^7.0.0" + "@npmcli/name-from-folder" "^2.0.0" + "@npmcli/node-gyp" "^3.0.0" + "@npmcli/package-json" "^5.0.0" + "@npmcli/query" "^3.1.0" + "@npmcli/run-script" "^7.0.2" + bin-links "^4.0.1" + cacache "^18.0.0" + common-ancestor-path "^1.0.1" + hosted-git-info "^7.0.1" + json-parse-even-better-errors "^3.0.0" + json-stringify-nice "^1.1.4" + minimatch "^9.0.0" + nopt "^7.0.0" + npm-install-checks "^6.2.0" + npm-package-arg "^11.0.1" + npm-pick-manifest "^9.0.0" + npm-registry-fetch "^16.0.0" + npmlog "^7.0.1" + pacote "^17.0.4" + parse-conflict-json "^3.0.0" + proc-log "^3.0.0" + promise-all-reject-late "^1.0.0" + promise-call-limit "^3.0.1" + read-package-json-fast "^3.0.2" + semver "^7.3.7" + ssri "^10.0.5" + treeverse "^3.0.0" + walk-up-path "^3.0.1" + +"@npmcli/config@^8.0.2": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-8.2.0.tgz#18774fc7239cfcc124ca9fdc48b1f65bb7bee191" + integrity sha512-YoEYZFg0hRSRP/Chmq+J4FvULFvji6SORUYWQc10FiJ+ReAnViXcDCENg6kM6dID04bAoKNUygrby798+gYBbQ== + dependencies: + "@npmcli/map-workspaces" "^3.0.2" + ci-info "^4.0.0" + ini "^4.1.0" + nopt "^7.0.0" + proc-log "^3.0.0" + read-package-json-fast "^3.0.2" + semver "^7.3.5" + walk-up-path "^3.0.1" + +"@npmcli/disparity-colors@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/disparity-colors/-/disparity-colors-3.0.0.tgz#60ea8c6eb5ba9de2d1950e15b06205b2c3ab7833" + integrity sha512-5R/z157/f20Fi0Ou4ZttL51V0xz0EdPEOauFtPCEYOLInDBRCj1/TxOJ5aGTrtShxEshN2d+hXb9ZKSi5RLBcg== + dependencies: + ansi-styles "^4.3.0" + +"@npmcli/fs@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" + integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + dependencies: + semver "^7.3.5" + +"@npmcli/git@^5.0.0", "@npmcli/git@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-5.0.4.tgz#d18c50f99649e6e89e8b427318134f582498700c" + integrity sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ== + dependencies: + "@npmcli/promise-spawn" "^7.0.0" + lru-cache "^10.0.1" + npm-pick-manifest "^9.0.0" + proc-log "^3.0.0" + promise-inflight "^1.0.1" + promise-retry "^2.0.1" + semver "^7.3.5" + which "^4.0.0" + +"@npmcli/installed-package-contents@^2.0.1", "@npmcli/installed-package-contents@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz#bfd817eccd9e8df200919e73f57f9e3d9e4f9e33" + integrity sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ== + dependencies: + npm-bundled "^3.0.0" + npm-normalize-package-bin "^3.0.0" + +"@npmcli/map-workspaces@^3.0.2", "@npmcli/map-workspaces@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz#15ad7d854292e484f7ba04bc30187a8320dba799" + integrity sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg== + dependencies: + "@npmcli/name-from-folder" "^2.0.0" + glob "^10.2.2" + minimatch "^9.0.0" + read-package-json-fast "^3.0.0" + +"@npmcli/metavuln-calculator@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-7.0.0.tgz#fb59245926d7f677db904177f9aca15ac883d6cb" + integrity sha512-Pw0tyX02VkpqlIQlG2TeiJNsdrecYeUU0ubZZa9pi3N37GCsxI+en43u4hYFdq+eSx1A9a9vwFAUyqEtKFsbHQ== + dependencies: + cacache "^18.0.0" + json-parse-even-better-errors "^3.0.0" + pacote "^17.0.0" + semver "^7.3.5" + +"@npmcli/name-from-folder@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz#c44d3a7c6d5c184bb6036f4d5995eee298945815" + integrity sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg== + +"@npmcli/node-gyp@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz#101b2d0490ef1aa20ed460e4c0813f0db560545a" + integrity sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA== + +"@npmcli/package-json@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-5.0.0.tgz#77d0f8b17096763ccbd8af03b7117ba6e34d6e91" + integrity sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g== + dependencies: + "@npmcli/git" "^5.0.0" + glob "^10.2.2" + hosted-git-info "^7.0.0" + json-parse-even-better-errors "^3.0.0" + normalize-package-data "^6.0.0" + proc-log "^3.0.0" + semver "^7.5.3" + +"@npmcli/promise-spawn@^7.0.0", "@npmcli/promise-spawn@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz#a836de2f42a2245d629cf6fbb8dd6c74c74c55af" + integrity sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg== + dependencies: + which "^4.0.0" + +"@npmcli/query@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/query/-/query-3.1.0.tgz#bc202c59e122a06cf8acab91c795edda2cdad42c" + integrity sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ== + dependencies: + postcss-selector-parser "^6.0.10" + +"@npmcli/run-script@^7.0.0", "@npmcli/run-script@^7.0.2", "@npmcli/run-script@^7.0.4": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-7.0.4.tgz#9f29aaf4bfcf57f7de2a9e28d1ef091d14b2e6eb" + integrity sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg== + dependencies: + "@npmcli/node-gyp" "^3.0.0" + "@npmcli/package-json" "^5.0.0" + "@npmcli/promise-spawn" "^7.0.0" + node-gyp "^10.0.0" + which "^4.0.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -582,6 +818,75 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz#2c1fb69e02a3f1506f52698cfdc3a8b6386df9a6" integrity sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ== +"@sigstore/bundle@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-2.2.0.tgz#e3f555a5c503fe176d8d1e0e829b00f842502e46" + integrity sha512-5VI58qgNs76RDrwXNhpmyN/jKpq9evV/7f1XrcqcAfvxDl5SeVY/I5Rmfe96ULAV7/FK5dge9RBKGBJPhL1WsQ== + dependencies: + "@sigstore/protobuf-specs" "^0.3.0" + +"@sigstore/core@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@sigstore/core/-/core-1.0.0.tgz#0fcdb32d191d4145a70cb837061185353b3b08e3" + integrity sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw== + +"@sigstore/protobuf-specs@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.3.0.tgz#bdcc773671f625bb81591bca86ec5314d57297f3" + integrity sha512-zxiQ66JFOjVvP9hbhGj/F/qNdsZfkGb/dVXSanNRNuAzMlr4MC95voPUBX8//ZNnmv3uSYzdfR/JSkrgvZTGxA== + +"@sigstore/sign@^2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-2.2.3.tgz#f07bcd2cfee654fade867db44ae260f1a0142ba4" + integrity sha512-LqlA+ffyN02yC7RKszCdMTS6bldZnIodiox+IkT8B2f8oRYXCB3LQ9roXeiEL21m64CVH1wyveYAORfD65WoSw== + dependencies: + "@sigstore/bundle" "^2.2.0" + "@sigstore/core" "^1.0.0" + "@sigstore/protobuf-specs" "^0.3.0" + make-fetch-happen "^13.0.0" + +"@sigstore/tuf@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-2.3.1.tgz#86ff3c3c907e271696c88de0108d9063a8cbcc45" + integrity sha512-9Iv40z652td/QbV0o5n/x25H9w6IYRt2pIGbTX55yFDYlApDQn/6YZomjz6+KBx69rXHLzHcbtTS586mDdFD+Q== + dependencies: + "@sigstore/protobuf-specs" "^0.3.0" + tuf-js "^2.2.0" + +"@sigstore/verify@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sigstore/verify/-/verify-1.1.0.tgz#ab617c5dc0bc09ead7f101a848f4870af2d84374" + integrity sha512-1fTqnqyTBWvV7cftUUFtDcHPdSox0N3Ub7C0lRyReYx4zZUlNTZjCV+HPy4Lre+r45dV7Qx5JLKvqqsgxuyYfg== + dependencies: + "@sigstore/bundle" "^2.2.0" + "@sigstore/core" "^1.0.0" + "@sigstore/protobuf-specs" "^0.3.0" + +"@tanstack/react-virtual@^3.0.0-beta.60": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.1.3.tgz#4ef2a7dd819a7dd2b634d50cbd6ba498f06529ec" + integrity sha512-YCzcbF/Ws/uZ0q3Z6fagH+JVhx4JLvbSflgldMgLsuvB8aXjZLLb3HvrEVxY480F9wFlBiXlvQxOyXb5ENPrNA== + dependencies: + "@tanstack/virtual-core" "3.1.3" + +"@tanstack/virtual-core@3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.1.3.tgz#77ced625f19ec9350f6e460f142b3be9bff03866" + integrity sha512-Y5B4EYyv1j9V8LzeAoOVeTg0LI7Fo5InYKgAjkY1Pu9GjtUwX/EKxNcU7ng3sKr99WEf+bPTcktAeybyMOYo+g== + +"@tufjs/canonical-json@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz#a52f61a3d7374833fca945b2549bc30a2dd40d0a" + integrity sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA== + +"@tufjs/models@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-2.0.0.tgz#c7ab241cf11dd29deb213d6817dabb8c99ce0863" + integrity sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg== + dependencies: + "@tufjs/canonical-json" "2.0.0" + minimatch "^9.0.3" + "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -620,6 +925,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "@types/json-schema@^7.0.12": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -630,7 +940,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@~4.14.0": +"@types/lodash@^4.14.195", "@types/lodash@~4.14.0": version "4.14.202" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== @@ -647,6 +957,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^20.3.1": + version "20.11.24" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.24.tgz#cc207511104694e84e9fb17f9a0c4c42d4517792" + integrity sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long== + dependencies: + undici-types "~5.26.4" + "@types/node@~20.3.0": version "20.3.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.3.tgz#329842940042d2b280897150e023e604d11657d6" @@ -871,16 +1188,36 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.0" +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: +acorn@^8.8.2, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -896,6 +1233,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -903,13 +1245,33 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== + +are-we-there-yet@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz#aed25dd0eae514660d49ac2b2366b175c614785a" + integrity sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg== + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1035,6 +1397,26 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bin-links@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.3.tgz#9e4a3c5900830aee3d7f52178b65e01dcdde64a5" + integrity sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA== + dependencies: + cmd-shim "^6.0.0" + npm-normalize-package-bin "^3.0.0" + read-cmd-shim "^4.0.0" + write-file-atomic "^5.0.0" + +binary-extensions@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1067,6 +1449,36 @@ browserslist@^4.22.2: node-releases "^2.0.14" update-browserslist-db "^1.0.13" +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +builtins@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + +cacache@^18.0.0, cacache@^18.0.2: + version "18.0.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.2.tgz#fd527ea0f03a603be5c0da5805635f8eef00c60c" + integrity sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^10.0.1" + minipass "^7.0.3" + minipass-collect "^2.0.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" @@ -1081,6 +1493,14 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + caniuse-lite@^1.0.30001580: version "1.0.30001581" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz#0dfd4db9e94edbdca67d57348ebc070dece279f4" @@ -1108,6 +1528,57 @@ chalk@^5.3.0: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +ci-info@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2" + integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg== + +cidr-regex@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-4.0.3.tgz#07b52c9762d1ff546a50740e92fc2b5b13a6d871" + integrity sha512-HOwDIy/rhKeMf6uOzxtv7FAbrz8zPjmVKfSpM+U7/bNBXC5rtOyr758jxcptiSx6ZZn5LOhPJT5WWxPAGDV8dw== + dependencies: + ip-regex "^5.0.0" + +clean-css@^5.2.2: + version "5.3.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-columns@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-4.0.0.tgz#9fe4d65975238d55218c41bd2ed296a7fa555646" + integrity sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ== + dependencies: + string-width "^4.2.3" + strip-ansi "^6.0.1" + +cli-table3@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1117,6 +1588,16 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +cmd-shim@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.2.tgz#435fd9e5c95340e61715e19f90209ed6fcd9e0a4" + integrity sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1141,6 +1622,34 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +columnify@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" + integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q== + dependencies: + strip-ansi "^6.0.1" + wcwidth "^1.0.0" + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +common-ancestor-path@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" + integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1166,6 +1675,11 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== +console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -1180,6 +1694,27 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -1197,6 +1732,13 @@ date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" +debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1204,18 +1746,18 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" @@ -1239,6 +1781,11 @@ dequal@^2.0.3: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +diff@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1260,6 +1807,56 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.4.648: version "1.4.651" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.651.tgz#ef1e822233c6fc953df3caf943f78c21b254a080" @@ -1275,6 +1872,13 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encoding@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -1282,6 +1886,21 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + es-abstract@^1.22.1: version "1.22.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" @@ -1372,6 +1991,14 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild-plugin-polyfill-node@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/esbuild-plugin-polyfill-node/-/esbuild-plugin-polyfill-node-0.3.0.tgz#e7e3804b8272df51ae4f8ebfb7445a03712504cb" + integrity sha512-SHG6CKUfWfYyYXGpW143NEZtcVVn8S/WHcEOxk62LuDXnY4Zpmc+WmxJKN6GMTgTClXJXhEM5KQlxKY6YjbucQ== + dependencies: + "@jspm/core" "^2.0.1" + import-meta-resolve "^3.0.0" + esbuild@^0.19.11, esbuild@^0.19.3: version "0.19.12" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" @@ -1645,6 +2272,11 @@ execa@^4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1671,6 +2303,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fastest-levenshtein@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + fastq@^1.6.0: version "1.16.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" @@ -1734,6 +2371,28 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-minipass@^3.0.0, fs-minipass@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== + dependencies: + minipass "^7.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1764,6 +2423,20 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-5.0.1.tgz#1efc801b8ff076b86ef3e9a7a280a975df572112" + integrity sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^4.0.1" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -1813,6 +2486,17 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob@^10.2.2, glob@^10.3.10: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -1863,6 +2547,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +graceful-fs@^4.2.11, graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -1912,6 +2601,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + hasown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" @@ -1919,11 +2613,92 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hosted-git-info@^7.0.0, hosted-git-info@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.1.tgz#9985fcb2700467fecf7f33a4d4874e30680b5322" + integrity sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA== + dependencies: + lru-cache "^10.0.1" + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-webpack-plugin@^5.5.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" + integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.1: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ignore-walk@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.4.tgz#89950be94b4f522225eb63a13c56badb639190e9" + integrity sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw== + dependencies: + minimatch "^9.0.0" + ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" @@ -1937,11 +2712,21 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-meta-resolve@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz#75d194ae465d17c15736f414734310c87d4c45d7" + integrity sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1955,6 +2740,29 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@^4.1.0, ini@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.2.tgz#7f646dbd9caea595e61f88ef60bfff8b01f8130a" + integrity sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw== + +init-package-json@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-6.0.2.tgz#0d780b752dd1dd83b8649945df38a07df4f990a6" + integrity sha512-ZQ9bxt6PkqIH6fPU69HPheOMoUqIqVqwZj0qlCBfoSCG4lplQhVM/qB3RS4f0RALK3WZZSrNQxNtCZgphuf3IA== + dependencies: + "@npmcli/package-json" "^5.0.0" + npm-package-arg "^11.0.0" + promzard "^1.0.0" + read "^3.0.1" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + validate-npm-package-name "^5.0.0" + +install@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/install/-/install-0.13.0.tgz#6af6e9da9dd0987de2ab420f78e60d9c17260776" + integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA== + internal-slot@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" @@ -1969,6 +2777,19 @@ iota-array@^1.0.0: resolved "https://registry.yarnpkg.com/iota-array/-/iota-array-1.0.0.tgz#81ef57fe5d05814cd58c2483632a99c30a0e8087" integrity sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA== +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" + +ip-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-5.0.0.tgz#cd313b2ae9c80c07bd3851e12bf4fa4dc5480632" + integrity sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw== + is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -2010,7 +2831,14 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.13.1: +is-cidr@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-5.0.3.tgz#fcf817c0146dd4a318f27938af89e98a9b21bdd5" + integrity sha512-lKkM0tmz07dAxNsr8Ii9MGreExa9ZR34N9j8mTG5op824kcwBqinZPowNjcVWWc7j+jR8XAMMItOmBkniN0jOA== + dependencies: + cidr-regex "4.0.3" + +is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -2055,6 +2883,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: dependencies: is-extglob "^2.1.1" +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + is-map@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" @@ -2158,6 +2991,16 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isexe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" + integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== + +isomorphic.js@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88" + integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw== + iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -2169,6 +3012,15 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2181,6 +3033,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -2191,6 +3048,11 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-even-better-errors@^3.0.0, json-parse-even-better-errors@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" + integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2201,6 +3063,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-nice@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" + integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -2213,6 +3080,11 @@ json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonparse@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -2223,6 +3095,16 @@ json5@^2.2.3: object.assign "^4.1.4" object.values "^1.1.6" +just-diff-apply@^5.2.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f" + integrity sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw== + +just-diff@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-6.0.2.tgz#03b65908543ac0521caf6d8eb85035f7d27ea285" + integrity sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2250,6 +3132,126 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lib0@^0.2.86: + version "0.2.91" + resolved "https://registry.yarnpkg.com/lib0/-/lib0-0.2.91.tgz#a35759d0d9018d12317a8d709d1920ffa35be3d6" + integrity sha512-LRcTp8RmdHexL8olb7qErdROnJ2L6Js5Am99WQo0hiTRDWtk6vyUJJjTB6I/RcW8jwNQshM3NqH598DdhSOajA== + dependencies: + isomorphic.js "^0.2.4" + +libnpmaccess@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-8.0.2.tgz#a13a72fd5b71a1063ea54973fa56d61ec38f718f" + integrity sha512-4K+nsg3OYt4rjryP/3D5zGWluLbZaKozwj6YdtvAyxNhLhUrjCoyxHVoL5AkTJcAnjsd6/ATei52QPVvpSX9Ug== + dependencies: + npm-package-arg "^11.0.1" + npm-registry-fetch "^16.0.0" + +libnpmdiff@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-6.0.7.tgz#5fd7df1c4b8ff58160fa59d5eb97686a00f8fdd3" + integrity sha512-Erca7NHh+MGk4O14mM4yv9S1S+Wc5TgFg6yr8r/g5ykn34dZdAP/GkzhQNJiOpzfD8j1HBhbTpkbGJHVDdgG5Q== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/disparity-colors" "^3.0.0" + "@npmcli/installed-package-contents" "^2.0.2" + binary-extensions "^2.2.0" + diff "^5.1.0" + minimatch "^9.0.0" + npm-package-arg "^11.0.1" + pacote "^17.0.4" + tar "^6.2.0" + +libnpmexec@^7.0.4: + version "7.0.8" + resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-7.0.8.tgz#2bc6ab0468dde95803745ced1fea48bd43b112fc" + integrity sha512-xDzWoYpV1Ok0TIdrY4wuWGxriEv/O3/d8QG924yErBE0sMkkzKsin2dAmlEBsSlR7YRilObs8q+5uNtxKNQHAQ== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/run-script" "^7.0.2" + ci-info "^4.0.0" + npm-package-arg "^11.0.1" + npmlog "^7.0.1" + pacote "^17.0.4" + proc-log "^3.0.0" + read "^2.0.0" + read-package-json-fast "^3.0.2" + semver "^7.3.7" + walk-up-path "^3.0.1" + +libnpmfund@^5.0.1: + version "5.0.5" + resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-5.0.5.tgz#f874005a2f9a92a4c6c4ae7a489ceb16f48690ce" + integrity sha512-BUu2l9Kn4u6nce1Ay8a1uRN1fyU7lbVmtsMYxWcFpcbF+ZPN7qIiPksfcnY9/NDKIRGJYwwv0IXgQQStHDx6Tg== + dependencies: + "@npmcli/arborist" "^7.2.1" + +libnpmhook@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-10.0.1.tgz#3cb9516645f0d6891b4a59c72ffe026bdbb9bd6b" + integrity sha512-FnXCweDpoAko6mnLPSW8qrRYicjfh+GrvY5PuYHQRPvaW4BFtHDUmK3K3aYx4yD3TeGAKpj4IigrEDfUfWuSkA== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmorg@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-6.0.2.tgz#6e5e37ecc5a391082e83c599512689c78e60dc70" + integrity sha512-zK4r6cjVsfXf7hWzWGB6R0LBJidVhKaeMWMZL/1eyZS6ixxAxVijfsPacoEnBRCFaXsNjAtwV3b2RCmYU6+usA== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmpack@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-6.0.7.tgz#0b1cdd7c250f929e77ece95f2a738e9670dcb8ad" + integrity sha512-aVX5ZLiYAioShh5wzoBOGs25GvPskry7SxCpx76gMCjOrd/wKcNtbTOMqStvizd3c+vzq5a1b7FMP09XAtgRFg== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/run-script" "^7.0.2" + npm-package-arg "^11.0.1" + pacote "^17.0.4" + +libnpmpublish@^9.0.2: + version "9.0.4" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-9.0.4.tgz#0222c14578088ca9a758585c36d8133b828c87ad" + integrity sha512-330o6pVsCCg77jQ/+kidyG/RiohXYQKpqmzOC4BjUDWcimb+mXptRBh1Kvy27/Zb/CStZLVrfgGc6tXf5+PE3Q== + dependencies: + ci-info "^4.0.0" + normalize-package-data "^6.0.0" + npm-package-arg "^11.0.1" + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + semver "^7.3.7" + sigstore "^2.2.0" + ssri "^10.0.5" + +libnpmsearch@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-7.0.1.tgz#8fa803a8e5837a33ce750a8cc1c70820d728b91d" + integrity sha512-XyKi6Y94t6PGd5Lk2Ma3+fgiHWD3KSCvXmHOrcLkAOEP7oUejbNjL0Bb/HUDZXgBj6gP1Qk7pJ6jZPFBc2hmXQ== + dependencies: + npm-registry-fetch "^16.0.0" + +libnpmteam@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-6.0.1.tgz#daa1b2e7e4ccef0469bdef661737ca823b53468b" + integrity sha512-1YytqVk1gSkKFNMe4kkCKN49y5rlABrRSx5TrYShQtt2Lb4uQaed49dGE7Ue8TJGxbIkHzvyyVtb3PBiGACVqw== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmversion@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-5.0.2.tgz#aea7b09bc270c778cbc8be7bf02e4b60566989cf" + integrity sha512-6JBnLhd6SYgKRekJ4cotxpURLGbEtKxzw+a8p5o+wNwrveJPMH8yW/HKjeewyHzWmxzzwn9EQ3TkF2onkrwstA== + dependencies: + "@npmcli/git" "^5.0.3" + "@npmcli/run-script" "^7.0.2" + json-parse-even-better-errors "^3.0.0" + proc-log "^3.0.0" + semver "^7.3.7" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -2269,7 +3271,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.21, lodash@~4.17.0: +lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2286,6 +3288,18 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^10.0.1, "lru-cache@^9.1.1 || ^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -2300,6 +3314,23 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-fetch-happen@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0" + integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A== + dependencies: + "@npmcli/agent" "^2.0.0" + cacache "^18.0.0" + http-cache-semantics "^4.1.1" + is-lambda "^1.0.1" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + ssri "^10.0.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2323,7 +3354,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@9.0.3: +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== @@ -2342,6 +3373,83 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +minipass-collect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" + integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== + dependencies: + minipass "^7.0.3" + +minipass-fetch@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" + integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== + dependencies: + minipass "^7.0.3" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-json-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz#7edbb92588fbfc2ff1db2fc10397acb7b6b44aa7" + integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg== + dependencies: + jsonparse "^1.3.1" + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + +minizlib@^2.1.1, minizlib@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mri@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -2352,11 +3460,16 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@^1.0.0, mute-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" @@ -2367,7 +3480,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -ndarray@~1.0.0: +ndarray@^1.0.19, ndarray@~1.0.0: version "1.0.19" resolved "https://registry.yarnpkg.com/ndarray/-/ndarray-1.0.19.tgz#6785b5f5dfa58b83e31ae5b2a058cfd1ab3f694e" integrity sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ== @@ -2375,11 +3488,129 @@ ndarray@~1.0.0: iota-array "^1.0.0" is-buffer "^1.0.2" +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-gyp@^10.0.0, node-gyp@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.1.tgz#205514fc19e5830fa991e4a689f9e81af377a966" + integrity sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^10.3.10" + graceful-fs "^4.2.6" + make-fetch-happen "^13.0.0" + nopt "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + tar "^6.1.2" + which "^4.0.0" + node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +nopt@^7.0.0, nopt@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" + integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + dependencies: + abbrev "^2.0.0" + +normalize-package-data@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.0.tgz#68a96b3c11edd462af7189c837b6b1064a484196" + integrity sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg== + dependencies: + hosted-git-info "^7.0.0" + is-core-module "^2.8.1" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + +npm-audit-report@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-5.0.0.tgz#83ac14aeff249484bde81eff53c3771d5048cf95" + integrity sha512-EkXrzat7zERmUhHaoren1YhTxFwsOu5jypE84k6632SXTHcQE1z8V51GC6GVZt8LxkC+tbBcKMUBZAgk8SUSbw== + +npm-bundled@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-3.0.0.tgz#7e8e2f8bb26b794265028491be60321a25a39db7" + integrity sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ== + dependencies: + npm-normalize-package-bin "^3.0.0" + +npm-install-checks@^6.0.0, npm-install-checks@^6.2.0, npm-install-checks@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.3.0.tgz#046552d8920e801fa9f919cad569545d60e826fe" + integrity sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw== + dependencies: + semver "^7.1.1" + +npm-normalize-package-bin@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== + +npm-package-arg@^11.0.0, npm-package-arg@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.1.tgz#f208b0022c29240a1c532a449bdde3f0a4708ebc" + integrity sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ== + dependencies: + hosted-git-info "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + validate-npm-package-name "^5.0.0" + +npm-packlist@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-8.0.2.tgz#5b8d1d906d96d21c85ebbeed2cf54147477c8478" + integrity sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA== + dependencies: + ignore-walk "^6.0.4" + +npm-pick-manifest@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz#f87a4c134504a2c7931f2bb8733126e3c3bb7e8f" + integrity sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg== + dependencies: + npm-install-checks "^6.0.0" + npm-normalize-package-bin "^3.0.0" + npm-package-arg "^11.0.0" + semver "^7.3.5" + +npm-profile@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-9.0.0.tgz#ffcfa4e3e1b1cb44b17c192f75b44b24b4aae645" + integrity sha512-qv43ixsJ7vndzfxD3XsPNu1Njck6dhO7q1efksTo+0DiOQysKSOsIhK/qDD1/xO2o+2jDOA4Rv/zOJ9KQFs9nw== + dependencies: + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + +npm-registry-fetch@^16.0.0, npm-registry-fetch@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz#10227b7b36c97bc1cf2902a24e4f710cfe62803c" + integrity sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw== + dependencies: + make-fetch-happen "^13.0.0" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-json-stream "^1.0.1" + minizlib "^2.1.2" + npm-package-arg "^11.0.0" + proc-log "^3.0.0" + npm-run-path@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -2387,6 +3618,104 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" +npm-user-validate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-2.0.0.tgz#7b69bbbff6f7992a1d9a8968d52fd6b6db5431b6" + integrity sha512-sSWeqAYJ2dUPStJB+AEj0DyLRltr/f6YNcvCA7phkB8/RMLMnVsQ41GMwHo/ERZLYNDsyB2wPm7pZo1mqPOl7Q== + +npm@^10.3.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/npm/-/npm-10.5.0.tgz#726f91df5b1b14d9637c8819d7e71cb873c395a1" + integrity sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A== + dependencies: + "@isaacs/string-locale-compare" "^1.1.0" + "@npmcli/arborist" "^7.2.1" + "@npmcli/config" "^8.0.2" + "@npmcli/fs" "^3.1.0" + "@npmcli/map-workspaces" "^3.0.4" + "@npmcli/package-json" "^5.0.0" + "@npmcli/promise-spawn" "^7.0.1" + "@npmcli/run-script" "^7.0.4" + "@sigstore/tuf" "^2.3.1" + abbrev "^2.0.0" + archy "~1.0.0" + cacache "^18.0.2" + chalk "^5.3.0" + ci-info "^4.0.0" + cli-columns "^4.0.0" + cli-table3 "^0.6.3" + columnify "^1.6.0" + fastest-levenshtein "^1.0.16" + fs-minipass "^3.0.3" + glob "^10.3.10" + graceful-fs "^4.2.11" + hosted-git-info "^7.0.1" + ini "^4.1.1" + init-package-json "^6.0.0" + is-cidr "^5.0.3" + json-parse-even-better-errors "^3.0.1" + libnpmaccess "^8.0.1" + libnpmdiff "^6.0.3" + libnpmexec "^7.0.4" + libnpmfund "^5.0.1" + libnpmhook "^10.0.0" + libnpmorg "^6.0.1" + libnpmpack "^6.0.3" + libnpmpublish "^9.0.2" + libnpmsearch "^7.0.0" + libnpmteam "^6.0.0" + libnpmversion "^5.0.1" + make-fetch-happen "^13.0.0" + minimatch "^9.0.3" + minipass "^7.0.4" + minipass-pipeline "^1.2.4" + ms "^2.1.2" + node-gyp "^10.0.1" + nopt "^7.2.0" + normalize-package-data "^6.0.0" + npm-audit-report "^5.0.0" + npm-install-checks "^6.3.0" + npm-package-arg "^11.0.1" + npm-pick-manifest "^9.0.0" + npm-profile "^9.0.0" + npm-registry-fetch "^16.1.0" + npm-user-validate "^2.0.0" + npmlog "^7.0.1" + p-map "^4.0.0" + pacote "^17.0.6" + parse-conflict-json "^3.0.1" + proc-log "^3.0.0" + qrcode-terminal "^0.12.0" + read "^2.1.0" + semver "^7.6.0" + spdx-expression-parse "^3.0.1" + ssri "^10.0.5" + supports-color "^9.4.0" + tar "^6.2.0" + text-table "~0.2.0" + tiny-relative-date "^1.3.0" + treeverse "^3.0.0" + validate-npm-package-name "^5.0.0" + which "^4.0.0" + write-file-atomic "^5.0.1" + +npmlog@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-7.0.1.tgz#7372151a01ccb095c47d8bf1d0771a4ff1f53ac8" + integrity sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg== + dependencies: + are-we-there-yet "^4.0.0" + console-control-strings "^1.1.0" + gauge "^5.0.0" + set-blocking "^2.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2528,11 +3857,50 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pacote@^17.0.0, pacote@^17.0.4, pacote@^17.0.6: + version "17.0.6" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-17.0.6.tgz#874bb59cda5d44ab784d0b6530fcb4a7d9b76a60" + integrity sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ== + dependencies: + "@npmcli/git" "^5.0.0" + "@npmcli/installed-package-contents" "^2.0.1" + "@npmcli/promise-spawn" "^7.0.0" + "@npmcli/run-script" "^7.0.0" + cacache "^18.0.0" + fs-minipass "^3.0.0" + minipass "^7.0.2" + npm-package-arg "^11.0.0" + npm-packlist "^8.0.0" + npm-pick-manifest "^9.0.0" + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + promise-retry "^2.0.1" + read-package-json "^7.0.0" + read-package-json-fast "^3.0.0" + sigstore "^2.2.0" + ssri "^10.0.0" + tar "^6.1.11" + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2540,6 +3908,23 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-conflict-json@^3.0.0, parse-conflict-json@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz#67dc55312781e62aa2ddb91452c7606d1969960c" + integrity sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw== + dependencies: + json-parse-even-better-errors "^3.0.0" + just-diff "^6.0.0" + just-diff-apply "^5.2.0" + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2560,6 +3945,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -2585,6 +3978,14 @@ platform@^1.3.6: resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== +postcss-selector-parser@^6.0.10: + version "6.0.15" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" + integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + postcss@^8.4.32: version "8.4.33" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" @@ -2609,6 +4010,14 @@ prettier@^2.8.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + pretty-quick@^3.1.3: version "3.3.1" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.3.1.tgz#cfde97fec77a8d201a0e0c9c71d9990e12587ee2" @@ -2622,6 +4031,41 @@ pretty-quick@^3.1.3: picomatch "^3.0.1" tslib "^2.6.2" +proc-log@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" + integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== + +promise-all-reject-late@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" + integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== + +promise-call-limit@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-3.0.1.tgz#3570f7a3f2aaaf8e703623a552cd74749688cf19" + integrity sha512-utl+0x8gIDasV5X+PI5qWEPqH6fJS0pFtQ/4gZ95xfEFb/89dmh+/b895TbFDBLiafBvxD/PGTKfvxl4kH/pQg== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +promzard@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.0.tgz#3246f8e6c9895a77c0549cefb65828ac0f6c006b" + integrity sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig== + dependencies: + read "^2.0.0" + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2662,11 +4106,25 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-cmdk@^1.3.9: + version "1.3.9" + resolved "https://registry.yarnpkg.com/react-cmdk/-/react-cmdk-1.3.9.tgz#77123f5120a47e35a517a8176550e96731667654" + integrity sha512-MSVmAQZ9iqY7hO3r++XP6yWSHzGfMDGMvY3qlDT8k5RiWoRFwO1CGPlsWzhvcUbPilErzsMKK7uB4McEcX4B6g== + dependencies: + "@headlessui/react" "^1.6.4" + "@heroicons/react" "^2.0.13" + html-webpack-plugin "^5.5.0" + react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -2692,6 +4150,43 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" +read-cmd-shim@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" + integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== + +read-package-json-fast@^3.0.0, read-package-json-fast@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz#394908a9725dc7a5f14e70c8e7556dff1d2b1049" + integrity sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw== + dependencies: + json-parse-even-better-errors "^3.0.0" + npm-normalize-package-bin "^3.0.0" + +read-package-json@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-7.0.0.tgz#d605c9dcf6bc5856da24204aa4e9518ee9714be0" + integrity sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg== + dependencies: + glob "^10.2.2" + json-parse-even-better-errors "^3.0.0" + normalize-package-data "^6.0.0" + npm-normalize-package-bin "^3.0.0" + +read@^2.0.0, read@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read/-/read-2.1.0.tgz#69409372c54fe3381092bc363a00650b6ac37218" + integrity sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ== + dependencies: + mute-stream "~1.0.0" + +read@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/read/-/read-3.0.1.tgz#926808f0f7c83fa95f1ef33c0e2c09dbb28fd192" + integrity sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw== + dependencies: + mute-stream "^1.0.0" + reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -2718,6 +4213,22 @@ regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: define-properties "^1.2.0" set-function-name "^2.0.0" +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -2746,6 +4257,11 @@ resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2813,6 +4329,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.2.2" is-regex "^1.1.4" +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -2825,6 +4346,13 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.0.0, semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -2832,6 +4360,11 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + set-function-length@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" @@ -2883,22 +4416,112 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +sigstore@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-2.2.2.tgz#5e4ff39febeae9e0679bafa22180cb0f445a7e35" + integrity sha512-2A3WvXkQurhuMgORgT60r6pOWiCOO5LlEqY2ADxGBDGVYLSo5HN0uLtb68YpVpuL/Vi8mLTe7+0Dx2Fq8lLqEg== + dependencies: + "@sigstore/bundle" "^2.2.0" + "@sigstore/core" "^1.0.0" + "@sigstore/protobuf-specs" "^0.3.0" + "@sigstore/sign" "^2.2.3" + "@sigstore/tuf" "^2.3.1" + "@sigstore/verify" "^1.1.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" + integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + socks "^2.7.1" + +socks@^2.7.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.1.tgz#22c7d9dd7882649043cba0eafb49ae144e3457af" + integrity sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ== + dependencies: + ip-address "^9.0.5" + smart-buffer "^4.2.0" + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + spawn-command@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== + +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + +ssri@^10.0.0, ssri@^10.0.5: + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== + dependencies: + minipass "^7.0.3" + +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2907,6 +4530,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string.prototype.matchall@^4.0.8: version "4.0.10" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" @@ -2949,13 +4581,20 @@ string.prototype.trimstart@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -2992,16 +4631,53 @@ supports-color@^8.1.1: dependencies: has-flag "^4.0.0" +supports-color@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -text-table@^0.2.0: +tapable@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +tar@^6.1.11, tar@^6.1.2, tar@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +terser@^5.10.0: + version "5.28.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.28.1.tgz#bf00f7537fd3a798c352c2d67d67d65c915d1b28" + integrity sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tiny-relative-date@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" + integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -3019,6 +4695,11 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +treeverse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-3.0.0.tgz#dd82de9eb602115c6ebd77a574aae67003cb48c8" + integrity sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ== + ts-api-utils@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" @@ -3034,11 +4715,25 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.1.0, tslib@^2.6.2: +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslog@^4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-4.9.2.tgz#35de3a073784dfe3849caeaa028010c7a62b7f4a" + integrity sha512-wBM+LRJoNl34Bdu8mYEFxpvmOUedpNUwMNQB/NcuPIZKwdDde6xLHUev3bBjXQU7gdurX++X/YE7gLH8eXYsiQ== + +tuf-js@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-2.2.0.tgz#4daaa8620ba7545501d04dfa933c98abbcc959b9" + integrity sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg== + dependencies: + "@tufjs/models" "2.0.0" + debug "^4.3.4" + make-fetch-happen "^13.0.0" + turbo-darwin-64@1.12.2: version "1.12.2" resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.12.2.tgz#4b5e48065b874b2379a45c2db71ce69d7c35c027" @@ -3152,6 +4847,20 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + update-browserslist-db@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" @@ -3167,6 +4876,31 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== + +validate-npm-package-license@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" + integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== + dependencies: + builtins "^5.0.0" + vite@^5.0.8: version "5.0.12" resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.12.tgz#8a2ffd4da36c132aec4adafe05d7adde38333c47" @@ -3178,6 +4912,18 @@ vite@^5.0.8: optionalDependencies: fsevents "~2.3.3" +walk-up-path@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-3.0.1.tgz#c8d78d5375b4966c717eb17ada73dbd41490e886" + integrity sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA== + +wcwidth@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3235,7 +4981,21 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wrap-ansi@^7.0.0: +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -3244,11 +5004,28 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^5.0.0, write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -3282,11 +5059,23 @@ yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" +yjs@^13.6.14: + version "13.6.14" + resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.6.14.tgz#9326dfa03d1be3fb9af9ef7e41de4bfc78849a9f" + integrity sha512-D+7KcUr0j+vBCUSKXXEWfA+bG4UQBviAwP3gYBhkstkgwy5+8diOPMx0iqLIOxNo/HxaREUimZRxqHGAHCL2BQ== + dependencies: + lib0 "^0.2.86" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zod@^3.21.4: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + zod@~3.21.0: version "3.21.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db"