diff --git a/.eslintignore b/.eslintignore index 92c7bb0609c..9a50fea6ae4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,4 +13,5 @@ packages/element esm doc-site public -package \ No newline at end of file +package +assets diff --git a/.github/workflows/release-devtools.yml b/.github/workflows/release-devtools.yml new file mode 100644 index 00000000000..0f039503d10 --- /dev/null +++ b/.github/workflows/release-devtools.yml @@ -0,0 +1,62 @@ +name: Release Devtools +on: + workflow_dispatch: + inputs: + remote_debug: + description: 'Enable remote debug session?' + type: boolean + required: false + default: false + +jobs: + build: + runs-on: ubuntu-latest + + env: + DEVTOOLS_ZIP_PATH: devtools/chrome-extension/build/chrome-mv3-prod.zip + DEVTOOLS_ARTIFACT_NAME: formily-devtools + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Start debug session (when enabled) + if: ${{ inputs.remote_debug }} + uses: lhotari/action-upterm@v1 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 16 + registry-url: https://registry.npmjs.org/ + cache: yarn + + - name: Verify environment + run: | + node --version + yarn -v + + - name: Maintain debug session (when enabled) + run: | + sleep 3600 + if: ${{ inputs.remote_debug }} + + - name: Install dependencies + run: | + yarn install --ignore-engines + + - name: Build packages + run: | + yarn build + env: + # avoid core dump, see: https://github.com/parcel-bundler/parcel/issues/10081 + PARCEL_WORKER_BACKEND: process + + - name: Validate artifact + run: test -f ${{ env.DEVTOOLS_ZIP_PATH }} + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.DEVTOOLS_ARTIFACT_NAME }} + path: ${{ env.DEVTOOLS_ZIP_PATH }} diff --git a/devtools/chrome-extension/.gitignore b/devtools/chrome-extension/.gitignore new file mode 100644 index 00000000000..171698d64bc --- /dev/null +++ b/devtools/chrome-extension/.gitignore @@ -0,0 +1,36 @@ + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +out/ +build/ +dist/ + +# plasmo +.plasmo + +# typescript +.tsbuildinfo + +# backend.js is generated from src/webAccessible/backend.ts +assets/backend.js diff --git a/devtools/chrome-extension/.npmignore b/devtools/chrome-extension/.npmignore deleted file mode 100644 index 1ff337420fd..00000000000 --- a/devtools/chrome-extension/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -node_modules -*.log -build -docs -doc-site -__tests__ -.eslintrc -jest.config.js -tsconfig.json -.umi -src \ No newline at end of file diff --git a/devtools/chrome-extension/.prettierrc.mjs b/devtools/chrome-extension/.prettierrc.mjs new file mode 100644 index 00000000000..27060b8cb29 --- /dev/null +++ b/devtools/chrome-extension/.prettierrc.mjs @@ -0,0 +1,26 @@ +/** + * @type {import('prettier').Options} + */ +export default { + printWidth: 80, + tabWidth: 2, + useTabs: false, + semi: false, + singleQuote: true, + trailingComma: 'all', + bracketSpacing: true, + bracketSameLine: true, + plugins: ['@ianvs/prettier-plugin-sort-imports'], + importOrder: [ + '', // Node.js built-in modules + '', // Imports not matched by other special words or groups. + '', // Empty line + '^@plasmo/(.*)$', + '', + '^@plasmohq/(.*)$', + '', + '^~(.*)$', + '', + '^[./]', + ], +} diff --git a/devtools/chrome-extension/README.md b/devtools/chrome-extension/README.md new file mode 100644 index 00000000000..14279247748 --- /dev/null +++ b/devtools/chrome-extension/README.md @@ -0,0 +1,58 @@ +# Formily DevTools + +This is a [Plasmo extension](https://docs.plasmo.com/) project bootstrapped with [`plasmo init`](https://www.npmjs.com/package/plasmo). + +## 🚀 Getting Started + +### Development Setup + +1. **Install dependencies**: + ```bash + yarn install + ``` + +2. **Start the development server**: + ```bash + yarn run dev + ``` + +3. **Load the extension in your browser**: + • For Chrome (Manifest V3): + Navigate to `build/chrome-mv3-dev` using your browser's extension developer mode + + +Open your browser and load the appropriate development build. For example, if you are developing for the chrome browser, using manifest v3, use: `build/chrome-mv3-dev`. + +You can start editing the popup by modifying `popup.tsx`. It should auto-update as you make changes. To add an options page, simply add a `options.tsx` file to the root of the project, with a react component default exported. Likewise to add a content page, add a `content.ts` file to the root of the project, importing some module and do some logic, then reload the extension on your browser. + +For further guidance, [visit our Documentation](https://docs.plasmo.com/) + +### 🔥 Hot Reload Notes + +**Special Case for webAccessibleResources/backend.ts**: +```bash +# After modifying webAccessibleResources/backend.ts +# 1. Stop the dev server (Ctrl+C) +# 2. Rerun the dev command to pick up changes: +yarn run dev +``` + +This is due to Plasmo's limitations. + +## Making production build + +Run the following: + +```bash +# Build the extension for production +yarn run build + +# Package the extension into zip file for distribution +yarn run package +``` + +This should create a production bundle for your extension, ready to be published to the stores. + +## Submit to the webstores + +The easiest way to deploy your Plasmo extension is to use the built-in [bpp](https://bpp.browser.market) GitHub action. Prior to using this action however, make sure to build your extension and upload the first version to the store to establish the basic credentials. Then, simply follow [this setup instruction](https://docs.plasmo.com/framework/workflows/submit) and you should be on your way for automated submission! diff --git a/devtools/chrome-extension/assets/img/logo/scalable.png b/devtools/chrome-extension/assets/icon.png similarity index 100% rename from devtools/chrome-extension/assets/img/logo/scalable.png rename to devtools/chrome-extension/assets/icon.png diff --git a/devtools/chrome-extension/assets/img/loading.svg b/devtools/chrome-extension/assets/img/loading.svg deleted file mode 100644 index ad9cb74d4b8..00000000000 --- a/devtools/chrome-extension/assets/img/loading.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/devtools/chrome-extension/assets/img/logo/128x128.png b/devtools/chrome-extension/assets/img/logo/128x128.png deleted file mode 100644 index 08b6b14420f..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/128x128.png and /dev/null differ diff --git a/devtools/chrome-extension/assets/img/logo/16x16.png b/devtools/chrome-extension/assets/img/logo/16x16.png deleted file mode 100644 index bdc7d05548c..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/16x16.png and /dev/null differ diff --git a/devtools/chrome-extension/assets/img/logo/38x38.png b/devtools/chrome-extension/assets/img/logo/38x38.png deleted file mode 100644 index 091ebf51210..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/38x38.png and /dev/null differ diff --git a/devtools/chrome-extension/assets/img/logo/48x48.png b/devtools/chrome-extension/assets/img/logo/48x48.png deleted file mode 100644 index e39fa339388..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/48x48.png and /dev/null differ diff --git a/devtools/chrome-extension/assets/img/logo/error.png b/devtools/chrome-extension/assets/img/logo/error.png deleted file mode 100644 index f3d601b7758..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/error.png and /dev/null differ diff --git a/devtools/chrome-extension/assets/img/logo/gray.png b/devtools/chrome-extension/assets/img/logo/gray.png deleted file mode 100644 index 80ae7d717af..00000000000 Binary files a/devtools/chrome-extension/assets/img/logo/gray.png and /dev/null differ diff --git a/devtools/chrome-extension/config/webpack.base.ts b/devtools/chrome-extension/config/webpack.base.ts deleted file mode 100644 index b0cec868578..00000000000 --- a/devtools/chrome-extension/config/webpack.base.ts +++ /dev/null @@ -1,73 +0,0 @@ -import path from 'path' -import fs from 'fs-extra' - -const getEntry = (src) => { - return [path.resolve(__dirname, '../src/extension/', src)] -} - -fs.copy( - path.resolve(__dirname, '../assets'), - path.resolve(__dirname, '../package') -) - -fs.copy( - path.resolve(__dirname, '../src/extension/manifest.json'), - path.resolve(__dirname, '../package/manifest.json') -) - -export default { - mode: 'development', - devtool: 'inline-source-map', // 嵌入到源文件中 - entry: { - popup: getEntry('./popup.tsx'), - devtools: getEntry('./devtools.tsx'), - devpanel: getEntry('./devpanel.tsx'), - content: getEntry('./content.ts'), - backend: getEntry('./backend.ts'), - demo: getEntry('../app/demo.tsx'), - inject: getEntry('./inject.ts'), - background: getEntry('./background.ts'), - }, - output: { - path: path.resolve(__dirname, '../package'), - filename: 'js/[name].bundle.js', - }, - resolve: { - modules: ['node_modules'], - extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], - }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: [ - { - loader: require.resolve('ts-loader'), - options: { - transpileOnly: true, - }, - }, - ], - }, - { - test: /\.css$/, - use: [ - { - loader: require.resolve('style-loader'), - options: { - singleton: true, - }, - }, - require.resolve('css-loader'), - ], - }, - { - test: /\.html?$/, - loader: require.resolve('file-loader'), - options: { - name: '[name].[ext]', - }, - }, - ], - }, -} diff --git a/devtools/chrome-extension/config/webpack.dev.ts b/devtools/chrome-extension/config/webpack.dev.ts deleted file mode 100644 index 2377da4e6b3..00000000000 --- a/devtools/chrome-extension/config/webpack.dev.ts +++ /dev/null @@ -1,47 +0,0 @@ -import baseConfig from './webpack.base' -import HtmlWebpackPlugin from 'html-webpack-plugin' -import webpack from 'webpack' -import path from 'path' - -const PORT = 3000 - -const createPages = (pages) => { - return pages.map(({ filename, template, chunk }) => { - return new HtmlWebpackPlugin({ - filename, - template, - inject: 'body', - chunks: [chunk], - }) - }) -} - -for (let key in baseConfig.entry) { - if (Array.isArray(baseConfig.entry[key])) { - baseConfig.entry[key].push( - require.resolve('webpack/hot/dev-server'), - `${require.resolve('webpack-dev-server/client')}?http://localhost:${PORT}` - ) - } -} - -module.exports = { - ...baseConfig, - plugins: [ - ...createPages([ - { - filename: 'index.html', - template: path.resolve( - __dirname, - '../src/extension/views/devtools.ejs' - ), - chunk: 'demo', - }, - ]), - new webpack.HotModuleReplacementPlugin(), - ], - devServer: { - open: true, - port: PORT, - }, -} diff --git a/devtools/chrome-extension/config/webpack.prod.ts b/devtools/chrome-extension/config/webpack.prod.ts deleted file mode 100644 index fbe6ae51494..00000000000 --- a/devtools/chrome-extension/config/webpack.prod.ts +++ /dev/null @@ -1,44 +0,0 @@ -import baseConfig from './webpack.base' -import HtmlWebpackPlugin from 'html-webpack-plugin' -import path from 'path' - -const createPages = (pages) => { - return pages.map(({ filename, template, chunk }) => { - return new HtmlWebpackPlugin({ - filename, - template, - inject: 'body', - chunks: [chunk], - }) - }) -} - -module.exports = { - ...baseConfig, - mode: 'production', - plugins: [ - ...createPages([ - { - filename: 'popup.html', - template: path.resolve(__dirname, '../src/extension/views/popup.ejs'), - chunk: 'popup', - }, - { - filename: 'devtools.html', - template: path.resolve( - __dirname, - '../src/extension/views/devtools.ejs' - ), - chunk: 'devtools', - }, - { - filename: 'devpanel.html', - template: path.resolve( - __dirname, - '../src/extension/views/devpanel.ejs' - ), - chunk: 'devpanel', - }, - ]), - ], -} diff --git a/devtools/chrome-extension/package.json b/devtools/chrome-extension/package.json index 46b9c0ff8a9..b18ba3d7eee 100644 --- a/devtools/chrome-extension/package.json +++ b/devtools/chrome-extension/package.json @@ -1,35 +1,58 @@ { "name": "@formily/chrome-extension", - "version": "2.3.2", + "version": "3.0.0", + "displayName": "Formily DevTools", + "description": "Formily DevTools for debugging application's state changes.", "private": true, "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/alibaba/formily.git" }, - "types": "esm/index.d.ts", "bugs": { "url": "https://github.com/alibaba/formily/issues" }, "homepage": "https://github.com/alibaba/formily#readme", - "engines": { - "npm": ">=3.0.0" - }, "scripts": { - "build:devtools": "webpack-cli --config config/webpack.prod.ts", - "build:zip": "rimraf package.zip && zip -r package.zip package", - "start": "webpack-dev-server --config config/webpack.dev.ts" + "cleanup": "rm -rf .plasmo build", + "dev": "yarn run build:backend && yarn run cleanup && yarn run dev:plasmo", + "dev:plasmo": "plasmo dev", + "build": "yarn run build:backend && yarn run cleanup && yarn run build:plasmo", + "build:backend": "tsc src/webAccessible/backend.ts --outFile assets/backend.js", + "build:plasmo": "plasmo build --zip", + "package": "plasmo package" }, "dependencies": { - "@formily/core": "2.3.2", "@formily/shared": "2.3.2", - "react": "^18.0.0", - "react-dom": "^18.0.0", + "plasmo": "0.90.3", + "react": "18.3.1", + "react-dom": "18.3.1", "react-json-view": "^1.19.1", "react-treebeard": "^3.2.4" }, - "publishConfig": { - "access": "public" + "devDependencies": { + "@ianvs/prettier-plugin-sort-imports": "4.1.1", + "@types/chrome": "0.0.258", + "@types/node": "20.11.5", + "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", + "prettier": "3.2.4", + "typescript": "5.3.3" }, - "gitHead": "2c44ae410a73f02735c63c6430e021a50e21f3ec" + "manifest": { + "homepage_url": "https://formilyjs.org/", + "host_permissions": [ + "" + ], + "web_accessible_resources": [ + { + "resources": [ + "~assets/backend.js" + ], + "matches": [ + "" + ] + } + ] + } } diff --git a/devtools/chrome-extension/src/app/components/Tabs.tsx b/devtools/chrome-extension/src/app/components/Tabs.tsx deleted file mode 100644 index f45da26eb2c..00000000000 --- a/devtools/chrome-extension/src/app/components/Tabs.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import { toArr } from '@formily/shared' - -export const Tabs = styled(({ className, dataSource, current, onChange }) => { - current = current || 0 - return ( -
- {toArr(dataSource).map((item, index) => { - return ( -
{ - if (onChange) { - onChange(index) - } - }} - > - Form#{index + 1} -
- ) - })} -
- ) -})` - height: 36px; - border-bottom: 1px solid #3d424a; - display: flex; - line-height: 36px; - width: 100%; - overflow: scroll; - &::-webkit-scrollbar { - display: none; - } - .tab-item { - cursor: pointer; - transition: 0.15s all ease-in-out; - border-right: 1px solid #3d424a; - padding: 0 10px; - font-size: 12px; - &:hover { - background: #1d1f25; - } - &.active { - background: #1d1f25; - } - } -` diff --git a/devtools/chrome-extension/src/extension/background.ts b/devtools/chrome-extension/src/background.ts similarity index 100% rename from devtools/chrome-extension/src/extension/background.ts rename to devtools/chrome-extension/src/background.ts diff --git a/devtools/chrome-extension/src/extension/content.ts b/devtools/chrome-extension/src/contents/content.ts similarity index 60% rename from devtools/chrome-extension/src/extension/content.ts rename to devtools/chrome-extension/src/contents/content.ts index 59f8f31a822..ebc49d1b407 100644 --- a/devtools/chrome-extension/src/extension/content.ts +++ b/devtools/chrome-extension/src/contents/content.ts @@ -1,3 +1,11 @@ +import type { PlasmoCSConfig } from 'plasmo' + +export const config: PlasmoCSConfig = { + matches: [''], + run_at: 'document_start', + all_frames: true, +} + window.addEventListener( 'message', (event) => { diff --git a/devtools/chrome-extension/src/contents/inject.ts b/devtools/chrome-extension/src/contents/inject.ts new file mode 100644 index 00000000000..ed3410336b2 --- /dev/null +++ b/devtools/chrome-extension/src/contents/inject.ts @@ -0,0 +1,16 @@ +import type { PlasmoCSConfig } from 'plasmo' + +export const config: PlasmoCSConfig = { + matches: [''], + run_at: 'document_start', + all_frames: true, +} + +const injectScript = (url) => { + const script = document.createElement('script') + script.src = url + document.documentElement?.appendChild(script) + script.parentNode?.removeChild(script) +} + +injectScript(chrome.runtime.getURL('assets/backend.js')) diff --git a/devtools/chrome-extension/src/app/components/FieldTree.tsx b/devtools/chrome-extension/src/devPanels/formily/app/components/FieldTree.tsx similarity index 85% rename from devtools/chrome-extension/src/app/components/FieldTree.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/components/FieldTree.tsx index be2fb049840..0aa4621402f 100644 --- a/devtools/chrome-extension/src/app/components/FieldTree.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/components/FieldTree.tsx @@ -1,7 +1,7 @@ -import React, { useState, useEffect, useRef } from 'react' -import styled from 'styled-components' import { FormPath, isObj } from '@formily/shared' -import { Treebeard, decorators } from 'react-treebeard' +import React, { useEffect, useRef, useState } from 'react' +import { decorators, Treebeard } from 'react-treebeard' + import * as filters from './filter' import SearchBox from './SearchBox' @@ -159,7 +159,7 @@ const Header = (props) => { const title = node.data?.title ? node.data.title : '' return (
{ node.toggled = false @@ -182,10 +182,10 @@ const Header = (props) => { {node.name} - {isObj(title) ? ((title as any).title ?? '') : title} + {isObj(title) ? (title as any).title ?? '' : title}
@@ -193,19 +193,11 @@ const Header = (props) => { ) } -const ToolBar = styled.div` - border-bottom: 1px solid #3d424a; - height: 20px; - padding: 10px 10px; - padding: 5px; - overflow: auto; - position: sticky; - top: 0; - background: #282c34; - z-index: 100; -` +const ToolBar = ({ children }) => { + return
{children}
+} -export const FieldTree = styled(({ className, dataSource, onSelect }) => { +export const FieldTree = ({ dataSource, onSelect }) => { const allDataRef = useRef(createTree(dataSource)) const cursor = useRef(allDataRef.current) const [keyword, setKeyword] = useState('') @@ -244,7 +236,7 @@ export const FieldTree = styled(({ className, dataSource, onSelect }) => { }, [dataSource]) return ( -
+
@@ -260,23 +252,4 @@ export const FieldTree = styled(({ className, dataSource, onSelect }) => { />
) -})` - position: relative; - overflow: auto; - height: calc(100% - 40px); - user-select: none; - .highlight { - position: absolute; - top: 0; - right: 0; - left: -100%; - height: 100%; - z-index: 0; - &.active { - background: #3d424a; - } - } - .node-header:hover .highlight { - background: #3d424a; - } -` +} diff --git a/devtools/chrome-extension/src/app/components/LeftPanel.tsx b/devtools/chrome-extension/src/devPanels/formily/app/components/LeftPanel.tsx similarity index 77% rename from devtools/chrome-extension/src/app/components/LeftPanel.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/components/LeftPanel.tsx index 2e6f1e16dfa..3f88cab4f83 100644 --- a/devtools/chrome-extension/src/app/components/LeftPanel.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/components/LeftPanel.tsx @@ -1,12 +1,12 @@ import React, { useState } from 'react' -import { Tabs } from './Tabs' + import { FieldTree } from './FieldTree' -import styled from 'styled-components' +import { Tabs } from './Tabs' -export const LeftPanel = styled(({ className, dataSource, onSelect }) => { +export const LeftPanel = ({ dataSource, onSelect }) => { const [current, setCurrent] = useState(0) return ( -
+
{ />
) -})` - width: 50%; - min-width: 50%; -` +} diff --git a/devtools/chrome-extension/src/app/components/RightPanel.tsx b/devtools/chrome-extension/src/devPanels/formily/app/components/RightPanel.tsx similarity index 56% rename from devtools/chrome-extension/src/app/components/RightPanel.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/components/RightPanel.tsx index 60d1bb1c587..07196d7d5b2 100644 --- a/devtools/chrome-extension/src/app/components/RightPanel.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/components/RightPanel.tsx @@ -1,10 +1,9 @@ import React from 'react' -import styled from 'styled-components' import ReactJson from 'react-json-view' -export const RightPanel = styled(({ className, dataSource }) => { +export const RightPanel = ({ dataSource }) => { return ( -
+
{ />
) -})` - border-left: 1px solid #3d424a; - flex-grow: 2; - overflow: auto; - padding: 10px; - .react-json-view { - background: none !important; - font-size: 12px !important; - } -` +} diff --git a/devtools/chrome-extension/src/app/components/SearchBox.tsx b/devtools/chrome-extension/src/devPanels/formily/app/components/SearchBox.tsx similarity index 75% rename from devtools/chrome-extension/src/app/components/SearchBox.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/components/SearchBox.tsx index 721b3fe55ba..23d620dcb6f 100644 --- a/devtools/chrome-extension/src/app/components/SearchBox.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/components/SearchBox.tsx @@ -1,26 +1,11 @@ import React from 'react' -import styled from 'styled-components' -const SerachBox = styled.div` - display: flex; - align-items: center; - height: 100%; - .input-addon { - padding: 0 5px; - } - .form-control { - width: 50%; - border: none; - background: transparent; - color: white; - outline: none; - } -` +const SearchBox = ({ children }) =>
{children}
const SearchIcon = () => { return ( { export default ({ onSearch }) => { return ( - -
+ +
- +
) } diff --git a/devtools/chrome-extension/src/devPanels/formily/app/components/Tabs.tsx b/devtools/chrome-extension/src/devPanels/formily/app/components/Tabs.tsx new file mode 100644 index 00000000000..859c8db9993 --- /dev/null +++ b/devtools/chrome-extension/src/devPanels/formily/app/components/Tabs.tsx @@ -0,0 +1,25 @@ +import { toArr } from '@formily/shared' +import React from 'react' + +export const Tabs = ({ dataSource, current, onChange }) => { + current = current || 0 + return ( +
+ {toArr(dataSource).map((item, index) => { + return ( +
{ + if (onChange) { + onChange(index) + } + }} + > + Form#{index + 1} +
+ ) + })} +
+ ) +} diff --git a/devtools/chrome-extension/src/app/components/filter.ts b/devtools/chrome-extension/src/devPanels/formily/app/components/filter.ts similarity index 100% rename from devtools/chrome-extension/src/app/components/filter.ts rename to devtools/chrome-extension/src/devPanels/formily/app/components/filter.ts diff --git a/devtools/chrome-extension/src/app/demo.tsx b/devtools/chrome-extension/src/devPanels/formily/app/demo.tsx similarity index 99% rename from devtools/chrome-extension/src/app/demo.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/demo.tsx index b401e9aecc6..51b7d8ed612 100644 --- a/devtools/chrome-extension/src/app/demo.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/demo.tsx @@ -1,6 +1,8 @@ import React from 'react' import ReactDOM from 'react-dom' -import App from './index' + +import { App } from './index' + const dataSource = [ { '': { diff --git a/devtools/chrome-extension/src/app/index.tsx b/devtools/chrome-extension/src/devPanels/formily/app/index.tsx similarity index 76% rename from devtools/chrome-extension/src/app/index.tsx rename to devtools/chrome-extension/src/devPanels/formily/app/index.tsx index c2f9cee8255..1621b90a900 100644 --- a/devtools/chrome-extension/src/app/index.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/app/index.tsx @@ -1,15 +1,15 @@ import React, { useState } from 'react' + import { LeftPanel } from './components/LeftPanel' import { RightPanel } from './components/RightPanel' -import styled from 'styled-components' -export default styled(({ className, dataSource }) => { +export const App = ({ dataSource }) => { const [selected, select] = useState({ current: 0, key: '', }) return ( -
+
{ @@ -35,14 +35,4 @@ export default styled(({ className, dataSource }) => { />
) -})` - display: flex; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - overflow: hidden; - color: #36d4c7; - background: #282c34; -` +} diff --git a/devtools/chrome-extension/src/devPanels/formily/index.css b/devtools/chrome-extension/src/devPanels/formily/index.css new file mode 100644 index 00000000000..2968f1b32c3 --- /dev/null +++ b/devtools/chrome-extension/src/devPanels/formily/index.css @@ -0,0 +1,126 @@ +::-webkit-scrollbar { + width: 5px; + height: 5px; +} + +::-webkit-scrollbar-thumb { + background: #101114; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background: #494e5f; +} + +::-webkit-scrollbar-track { + background: transparent; + border-radius: 10px; +} + +.app { + display: flex; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + overflow: hidden; + color: #36d4c7; + background: #282c34; +} + +.fieldTree { + position: relative; + overflow: auto; + height: calc(100% - 40px); + user-select: none; +} + +.fieldTreeHighlight { + position: absolute; + top: 0; + right: 0; + left: -100%; + height: 100%; + z-index: 0; + &.active { + background: #3d424a; + } +} +.fieldTreeNodeHeader:hover .fieldTreeHighlight { + background: #3d424a; +} + +.filedTreeToolBar { + border-bottom: 1px solid #3d424a; + height: 20px; + padding: 10px 10px; + padding: 5px; + overflow: auto; + position: sticky; + top: 0; + background: #282c34; + z-index: 100; +} + +.leftPanel { + width: 50%; + min-width: 50%; +} + +.rightPanel { + border-left: 1px solid #3d424a; + flex-grow: 2; + overflow: auto; + padding: 10px; +} + +.rightPanel .react-json-view { + background: none !important; + font-size: 12px !important; +} + +.searchBox { + display: flex; + align-items: center; + height: 100%; +} + +.searchBoxInputAddon { + padding: 0 5px; +} +.searchBoxFormControl { + width: 50%; + border: none; + background: transparent; + color: white; + outline: none; +} + +.tabs { + height: 36px; + border-bottom: 1px solid #3d424a; + display: flex; + line-height: 36px; + width: 100%; + overflow: scroll; +} + +.tabs::-webkit-scrollbar { + display: none; +} +.tabs .tabItem { + cursor: pointer; + transition: 0.15s all ease-in-out; + border-right: 1px solid #3d424a; + padding: 0 10px; + font-size: 12px; +} + +.tabs .tabItem:hover { + background: #1d1f25; +} + +.tabs .tabItem.active { + background: #1d1f25; +} diff --git a/devtools/chrome-extension/src/devPanels/formily/index.html b/devtools/chrome-extension/src/devPanels/formily/index.html new file mode 100644 index 00000000000..bc270f2adec --- /dev/null +++ b/devtools/chrome-extension/src/devPanels/formily/index.html @@ -0,0 +1,13 @@ + + + + Formily devtools panel + + + + + +
+ + + diff --git a/devtools/chrome-extension/src/extension/devpanel.tsx b/devtools/chrome-extension/src/devPanels/formily/index.tsx similarity index 87% rename from devtools/chrome-extension/src/extension/devpanel.tsx rename to devtools/chrome-extension/src/devPanels/formily/index.tsx index be2a23bf88e..74957725f16 100644 --- a/devtools/chrome-extension/src/extension/devpanel.tsx +++ b/devtools/chrome-extension/src/devPanels/formily/index.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react' -import ReactDOM from 'react-dom' -import App from '../app' +import { createRoot } from 'react-dom/client' + +import { App } from './app' const backgroundPageConnection = chrome.runtime.connect({ name: '@formily-devtools-panel-script', @@ -46,4 +47,5 @@ const Devtools = () => { return } -ReactDOM.render(, document.getElementById('root')) +const root = createRoot(document.getElementById('root')) +root.render() diff --git a/devtools/chrome-extension/src/devtools.tsx b/devtools/chrome-extension/src/devtools.tsx new file mode 100644 index 00000000000..9391d8eb165 --- /dev/null +++ b/devtools/chrome-extension/src/devtools.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import formilyDevPanel from 'url:./devPanels/formily/index.html' + +const createPanel = () => { + chrome.devtools.panels.create( + '🍀Formily', + null, + formilyDevPanel.split('/').pop() + ) +} + +let created = false + +const checkForFormilyPresence = () => { + if (created) { + return + } + + chrome.devtools.inspectedWindow.eval( + 'window.__FORMILY_DEV_TOOLS_HOOK__ && window.__FORMILY_DEV_TOOLS_HOOK__.hasFormilyInstance', + (hasFormily: boolean, error) => { + if (created || !hasFormily || error) { + return + } + + created = true + + clearInterval(loadCheckInterval) + + createPanel() + } + ) +} + +const loadCheckInterval = setInterval(checkForFormilyPresence, 1000) + +checkForFormilyPresence() + +const IndexDevtools = () =>

Formily devtools is running

+ +export default IndexDevtools diff --git a/devtools/chrome-extension/src/extension/devtools.tsx b/devtools/chrome-extension/src/extension/devtools.tsx deleted file mode 100644 index dad7a08d5a7..00000000000 --- a/devtools/chrome-extension/src/extension/devtools.tsx +++ /dev/null @@ -1,30 +0,0 @@ -declare let chrome: any - -let created = false - -const createPanel = () => { - if (created) { - return - } - - chrome.devtools.inspectedWindow.eval( - 'window.__FORMILY_DEV_TOOLS_HOOK__ && window.__FORMILY_DEV_TOOLS_HOOK__.hasFormilyInstance', - (hasFormily: boolean) => { - if (!hasFormily) return - created = true - clearInterval(loadCheckInterval) - chrome.devtools.panels.create( - 'Formily', - 'img/logo/scalable.png', - './devpanel.html', - function () {} - ) - } - ) -} - -const loadCheckInterval = setInterval(function () { - createPanel() -}, 1000) - -createPanel() diff --git a/devtools/chrome-extension/src/extension/inject.ts b/devtools/chrome-extension/src/extension/inject.ts deleted file mode 100644 index e9d05e1e235..00000000000 --- a/devtools/chrome-extension/src/extension/inject.ts +++ /dev/null @@ -1,26 +0,0 @@ -import backend from 'raw-loader!./backend' -function nullthrows(x: any, message?: string) { - if (x != null) { - return x - } - const error: any = new Error( - message !== undefined ? message : 'Got unexpected ' + x - ) - error.framesToPop = 1 // Skip nullthrows's own stack frame. - throw error -} - -function injectCode(code) { - const script = document.createElement('script') - script.textContent = code - - // This script runs before the element is created, - // so we add the script to instead. - nullthrows(document.documentElement).appendChild(script) - nullthrows(script.parentNode).removeChild(script) -} - -injectCode(`;(function(){ - var exports = {}; - ${backend} -})()`) diff --git a/devtools/chrome-extension/src/extension/manifest.json b/devtools/chrome-extension/src/extension/manifest.json deleted file mode 100644 index 0e6776176b7..00000000000 --- a/devtools/chrome-extension/src/extension/manifest.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "version": "0.1.13", - "name": "Formily DevTools", - "short_name": "Formily DevTools", - "description": "Formily DevTools for debugging application's state changes.", - "homepage_url": "https://github.com/alibaba/formily", - "manifest_version": 2, - "page_action": { - "default_icon": "img/logo/scalable.png", - "default_title": "Formily DevTools", - "default_popup": "popup.html" - }, - "commands": { - "devtools-left": { - "description": "DevTools window to left" - }, - "devtools-right": { - "description": "DevTools window to right" - }, - "devtools-bottom": { - "description": "DevTools window to bottom" - }, - "devtools-remote": { - "description": "Remote DevTools" - }, - "_execute_page_action": { - "suggested_key": { - "default": "Ctrl+Shift+E" - } - } - }, - "icons": { - "16": "img/logo/16x16.png", - "48": "img/logo/48x48.png", - "128": "img/logo/128x128.png" - }, - "background": { - "scripts": ["js/background.bundle.js"], - "persistent": false - }, - "content_scripts": [ - { - "matches": [""], - "exclude_globs": ["https://www.google*"], - "js": ["js/content.bundle.js", "js/inject.bundle.js"], - "run_at": "document_start", - "all_frames": true - } - ], - "devtools_page": "devtools.html", - "web_accessible_resources": ["js/backend.bundle.js"], - "externally_connectable": { - "ids": ["*"] - }, - "permissions": ["file:///*", "http://*/*", "https://*/*"], - "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'; style-src * 'unsafe-inline'; img-src 'self' data:;", - "update_url": "https://clients2.google.com/service/update2/crx" -} diff --git a/devtools/chrome-extension/src/extension/popup.tsx b/devtools/chrome-extension/src/extension/popup.tsx deleted file mode 100644 index 39e49f32f59..00000000000 --- a/devtools/chrome-extension/src/extension/popup.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom' - -ReactDOM.render(
hello world
, document.getElementById('root')) diff --git a/devtools/chrome-extension/src/extension/views/devpanel.ejs b/devtools/chrome-extension/src/extension/views/devpanel.ejs deleted file mode 100644 index 5cd2f708d06..00000000000 --- a/devtools/chrome-extension/src/extension/views/devpanel.ejs +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Formily Devtools - - - - - -
-
- \ No newline at end of file diff --git a/devtools/chrome-extension/src/extension/views/devtools.ejs b/devtools/chrome-extension/src/extension/views/devtools.ejs deleted file mode 100644 index 237c58c53ee..00000000000 --- a/devtools/chrome-extension/src/extension/views/devtools.ejs +++ /dev/null @@ -1,10 +0,0 @@ - - - - Formily Devtools - - - -
-
- \ No newline at end of file diff --git a/devtools/chrome-extension/src/extension/views/popup.ejs b/devtools/chrome-extension/src/extension/views/popup.ejs deleted file mode 100644 index 237c58c53ee..00000000000 --- a/devtools/chrome-extension/src/extension/views/popup.ejs +++ /dev/null @@ -1,10 +0,0 @@ - - - - Formily Devtools - - - -
-
- \ No newline at end of file diff --git a/devtools/chrome-extension/src/popup.tsx b/devtools/chrome-extension/src/popup.tsx new file mode 100644 index 00000000000..389c55fdde0 --- /dev/null +++ b/devtools/chrome-extension/src/popup.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +const IndexPopup = () => ( +
+

Formily devtools is running!

+

+ Find out more about formily at{' '} + + formilyjs.org + + . +

+
+) + +export default IndexPopup diff --git a/devtools/chrome-extension/src/extension/backend.ts b/devtools/chrome-extension/src/webAccessible/backend.ts similarity index 84% rename from devtools/chrome-extension/src/extension/backend.ts rename to devtools/chrome-extension/src/webAccessible/backend.ts index aa52254d0db..01e39531717 100644 --- a/devtools/chrome-extension/src/extension/backend.ts +++ b/devtools/chrome-extension/src/webAccessible/backend.ts @@ -97,25 +97,33 @@ const HOOK = { form, }) let timer = null - const task = () => { - globalThis.requestIdleCallback((deadline: IIdleDeadline) => { - if (this.store[id]) { - if (deadline.timeRemaining() < 16) { - task() - } else { - send({ - type: 'update', - id, - form, - }) - } - } + const idleCallback = (deadline: IIdleDeadline) => { + const busy = deadline.timeRemaining() === 0 + if (busy) { + globalThis.requestIdleCallback(idleCallback) + return + } + + const registered = this.store[id] + + if (!registered) { + return + } + + send({ + type: 'update', + id, + form, }) } + const emit = () => { + globalThis.requestIdleCallback(idleCallback) + } + form.subscribe(() => { if (!this.hasOpenDevtools) return clearTimeout(timer) - timer = setTimeout(task, 300) + timer = setTimeout(emit, 300) }) }, update() { diff --git a/devtools/chrome-extension/tsconfig.build.json b/devtools/chrome-extension/tsconfig.build.json deleted file mode 100644 index 184756042d2..00000000000 --- a/devtools/chrome-extension/tsconfig.build.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./lib", - "paths": { - "@formily/*": ["packages/*", "devtools/*"] - }, - "declaration": true - } -} diff --git a/devtools/chrome-extension/tsconfig.json b/devtools/chrome-extension/tsconfig.json index c6865c25a75..435bb86c1c1 100644 --- a/devtools/chrome-extension/tsconfig.json +++ b/devtools/chrome-extension/tsconfig.json @@ -1,5 +1,11 @@ { - "extends": "../../tsconfig.json", - "include": ["./src/**/*.ts", "./src/**/*.tsx"], - "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"] + "extends": "plasmo/templates/tsconfig.base", + "exclude": ["node_modules"], + "include": [".plasmo/index.d.ts", "./**/*.ts", "./**/*.tsx"], + "compilerOptions": { + "paths": { + "~*": ["./src/*"] + }, + "baseUrl": "." + } }