diff --git a/.gitignore b/.gitignore index 8a6f5cf..240b48c 100644 --- a/.gitignore +++ b/.gitignore @@ -141,4 +141,5 @@ copies TODO.md # Synced typings -src/designer-extension-typings/ \ No newline at end of file +src/designer-extension-typings/ +pnpm-lock.yaml \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b7c6ad0..e221282 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "dotenv": "^16.4.5", "fs-extra": "^11.2.0", "prismjs": "^1.29.0", + "react": "^18.2.0", "react-dom": "^18.2.0", "react-resizable": "^3.0.5", "source-map": "^0.7.4", @@ -86,7 +87,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1694,7 +1694,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -1792,7 +1791,6 @@ "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.5.tgz", "integrity": "sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ==", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1833,7 +1831,6 @@ "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.5.tgz", "integrity": "sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ==", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -3130,7 +3127,6 @@ "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.13.1.tgz", "integrity": "sha512-GEF1pxqLc80osIMZmE8j9UKZSaTm2hX2lql8tgIH/O9yK4wnF06k6LL5Ah+wJt+oJv6Dj55ri/MoxMP4SXoPNA==", "dev": true, - "peer": true, "dependencies": { "@module-federation/runtime": "0.13.1", "@module-federation/webpack-bundler-runtime": "0.13.1" @@ -3237,7 +3233,6 @@ "version": "6.1.9", "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.9.tgz", "integrity": "sha512-NwqIN0bdsgzSbZd5JFcC+2ez0XW/XNs8uiV2PDHrqQ4qf/FEasFJG1z6g8JbCN0YlTrHZekVb17X0Fv0qcYJfQ==", - "peer": true, "dependencies": { "@babel/runtime": "^7.26.0", "@mui/core-downloads-tracker": "^6.1.9", @@ -3427,7 +3422,6 @@ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", "dev": true, - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -3777,6 +3771,7 @@ "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.3.15.tgz", "integrity": "sha512-utNPuJglLO5lW9XbwIqjB7+2ilMo6JkuVLTVdnNVKU94FW7asn9F/qV+d+MgjUVqU1QPCGm0NuGO9xhbgeJ7pg==", "dev": true, + "peer": true, "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.3.15", "@rspack/binding-darwin-x64": "1.3.15", @@ -3800,7 +3795,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rspack/binding-darwin-x64": { "version": "1.3.15", @@ -3813,7 +3809,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rspack/binding-linux-arm64-gnu": { "version": "1.3.15", @@ -3826,7 +3823,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rspack/binding-linux-arm64-musl": { "version": "1.3.15", @@ -3839,7 +3837,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rspack/binding-linux-x64-gnu": { "version": "1.3.15", @@ -3852,7 +3851,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rspack/binding-linux-x64-musl": { "version": "1.3.15", @@ -3865,7 +3865,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rspack/binding-win32-arm64-msvc": { "version": "1.3.15", @@ -3878,7 +3879,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rspack/binding-win32-ia32-msvc": { "version": "1.3.15", @@ -3891,7 +3893,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rspack/binding-win32-x64-msvc": { "version": "1.3.15", @@ -3904,7 +3907,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rspack/core": { "version": "1.3.15", @@ -3933,13 +3937,15 @@ "version": "0.14.3", "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.14.3.tgz", "integrity": "sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@rspack/core/node_modules/@module-federation/runtime": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.14.3.tgz", "integrity": "sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw==", "dev": true, + "peer": true, "dependencies": { "@module-federation/error-codes": "0.14.3", "@module-federation/runtime-core": "0.14.3", @@ -3951,6 +3957,7 @@ "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.14.3.tgz", "integrity": "sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q==", "dev": true, + "peer": true, "dependencies": { "@module-federation/error-codes": "0.14.3", "@module-federation/sdk": "0.14.3" @@ -3961,6 +3968,7 @@ "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.14.3.tgz", "integrity": "sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw==", "dev": true, + "peer": true, "dependencies": { "@module-federation/runtime": "0.14.3", "@module-federation/webpack-bundler-runtime": "0.14.3" @@ -3970,13 +3978,15 @@ "version": "0.14.3", "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.14.3.tgz", "integrity": "sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@rspack/core/node_modules/@module-federation/webpack-bundler-runtime": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.14.3.tgz", "integrity": "sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA==", "dev": true, + "peer": true, "dependencies": { "@module-federation/runtime": "0.14.3", "@module-federation/sdk": "0.14.3" @@ -3987,6 +3997,7 @@ "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz", "integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==", "dev": true, + "peer": true, "engines": { "node": ">=16.0.0" } @@ -4126,7 +4137,6 @@ "version": "18.2.48", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", - "peer": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -4470,7 +4480,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4522,7 +4531,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5027,7 +5035,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", @@ -8230,7 +8237,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -8475,7 +8481,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -8487,7 +8492,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -9537,8 +9541,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/tsscmp": { "version": "1.0.6", @@ -9598,7 +9601,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9742,7 +9744,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", "dev": true, - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -9896,7 +9897,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", "dev": true, - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -10021,7 +10021,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, - "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index b4da408..3aee138 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "type": "module", "scripts": { + "vite:dev": "vite --port 1337", "dev": "vite build && concurrently \"webflow extension serve\" \"vite\"", "build": "vite build && webflow extension bundle", "sync-dev": "nodemon --watch github/copies --exec \"node github/gh-sync-dev.mjs\"", @@ -43,6 +44,7 @@ "dotenv": "^16.4.5", "fs-extra": "^11.2.0", "prismjs": "^1.29.0", + "react": "^18.2.0", "react-dom": "^18.2.0", "react-resizable": "^3.0.5", "source-map": "^0.7.4", diff --git a/src/components/APIExplorer.tsx b/src/components/APIExplorer.tsx index 32b0cd8..67a9a38 100644 --- a/src/components/APIExplorer.tsx +++ b/src/components/APIExplorer.tsx @@ -202,6 +202,8 @@ const APIExplorer: React.FC = () => { : topCategory[selectedFunctionName] if (funcToExecute) { + // Save original console before try block so it's accessible in finally + const originalConsole = { ...console } try { setApiOutput('') @@ -235,7 +237,9 @@ const APIExplorer: React.FC = () => { : [] const apiConsole = createAPIConsole(setApiOutput) - const originalConsole = { ...console } + ;(window as any).ogConsole = (window as any).ogConsole || { + ...console, + } Object.assign(console, apiConsole) if (typeof funcToExecute === 'function') { @@ -247,7 +251,7 @@ const APIExplorer: React.FC = () => { } catch (error) { console.error('Error executing function:', error) } finally { - Object.assign(console, console) + Object.assign(console, originalConsole) } } } diff --git a/src/examples/utilities.ts b/src/examples/utilities.ts index 341ffdc..695a700 100644 --- a/src/examples/utilities.ts +++ b/src/examples/utilities.ts @@ -231,4 +231,29 @@ export const Utilities = { const pseudoMode = await webflow.getPseudoMode() console.log('Pseudo Mode:', pseudoMode) }, + + getElementSnapshot: async () => { + // Get the currently selected element + const selectedElement = await webflow.getSelectedElement() + + if (selectedElement) { + // Capture a screenshot of the element + console.log('Getting screenshot of element...') + const screenshot = await webflow.getElementSnapshot(selectedElement) + + if (screenshot) { + console.log('Screenshot captured successfully!') + console.log('Base64 string:', screenshot.substring(0, 100) + '...') + + console.log( + '%c ', + `font-size:400px; background:url(${screenshot}) no-repeat; background-size: contain;`, + ) + } else { + console.log('Failed to capture screenshot') + } + } else { + console.log('No element selected. Please select an element first.') + } + }, } diff --git a/src/utils/console-utils.ts b/src/utils/console-utils.ts index b187a48..eb76ef8 100644 --- a/src/utils/console-utils.ts +++ b/src/utils/console-utils.ts @@ -2,36 +2,47 @@ import type { APIConsole } from '../types/api-explorer.types' type SetOutputFunction = React.Dispatch> +// Helper to safely get the original console, falling back to native console +const getOriginalConsole = (): Console => (window as any).ogConsole ?? console + export const createAPIConsole = (setOutput: SetOutputFunction): APIConsole => ({ - log: (...args: any[]) => + log: (...args: any[]) => { + getOriginalConsole().log(...args) setOutput( (prev: string) => prev + args.map((arg) => formatConsoleArg(arg)).join(' ') + '\n', - ), - error: (...args: any[]) => + ) + }, + error: (...args: any[]) => { + getOriginalConsole().error(...args) setOutput( (prev: string) => prev + '[Error] ' + args.map((arg) => formatConsoleArg(arg)).join(' ') + '\n', - ), - warn: (...args: any[]) => + ) + }, + warn: (...args: any[]) => { + getOriginalConsole().warn(...args) setOutput( (prev: string) => prev + '[Warn] ' + args.map((arg) => formatConsoleArg(arg)).join(' ') + '\n', - ), - info: (...args: any[]) => + ) + }, + info: (...args: any[]) => { + getOriginalConsole().info(...args) setOutput( (prev: string) => prev + '[Info] ' + args.map((arg) => formatConsoleArg(arg)).join(' ') + '\n', - ), + ) + }, }) const formatConsoleArg = (arg: any): string => {