├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── config.yml
│ └── feature_request.md
└── workflows
│ ├── ci.yml
│ └── codesee-arch-diagram.yml
├── .gitignore
├── .mocharc.yml
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── .yarnrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── cspell.json
├── img
├── codemod-icon-mask.svg
├── codemod-square.png
├── codemod-square.svg
├── intuita.svg
└── intuita_square128.png
├── intuita-webview
├── .npmrc
├── index.html
├── package.json
├── pnpm-lock.yaml
├── public
│ └── index.html
├── src
│ ├── CreateIssue
│ │ ├── index.tsx
│ │ ├── style.module.css
│ │ └── tiptap.css
│ ├── assets
│ │ ├── Split.svg
│ │ ├── Unified.svg
│ │ ├── arrow-down.svg
│ │ ├── case.svg
│ │ ├── copy.svg
│ │ ├── intuita_square128.png
│ │ ├── material-icons
│ │ │ ├── check_box.svg
│ │ │ ├── check_box_outline_blank.svg
│ │ │ └── indeterminate_check_box.svg
│ │ ├── slack.svg
│ │ └── youtube.svg
│ ├── campaignManager
│ │ ├── App.tsx
│ │ └── style.module.css
│ ├── codemodList
│ │ ├── App.tsx
│ │ ├── CodemodArguments
│ │ │ ├── FormField
│ │ │ │ ├── index.tsx
│ │ │ │ └── style.module.css
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── CodemodNodeRenderer
│ │ │ ├── Codemod.tsx
│ │ │ ├── Directory.tsx
│ │ │ ├── index.tsx
│ │ │ └── style.module.css
│ │ ├── TreeView
│ │ │ ├── ActionButton.tsx
│ │ │ ├── InfiniteProgress.module.css
│ │ │ ├── InfiniteProgress.tsx
│ │ │ ├── ProgressBar.tsx
│ │ │ ├── index.tsx
│ │ │ └── style.module.css
│ │ ├── components
│ │ │ ├── DirectorySelector.tsx
│ │ │ └── style.module.css
│ │ ├── style.module.css
│ │ └── useProgressBar.tsx
│ ├── communityTab
│ │ ├── CommunityTab.tsx
│ │ └── style.module.css
│ ├── errors
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ └── style.module.css
│ ├── fileExplorer
│ │ ├── ActionsFooter
│ │ │ ├── index.tsx
│ │ │ └── style.module.css
│ │ ├── App.tsx
│ │ ├── FileExplorerTreeNode.tsx
│ │ ├── explorerNodeRenderer.tsx
│ │ └── style.module.css
│ ├── intuitaTreeView.tsx
│ ├── jobDiffView
│ │ ├── App.tsx
│ │ ├── Components
│ │ │ ├── Collapsable.css
│ │ │ ├── Collapsable.tsx
│ │ │ └── LoadingProgress
│ │ │ │ ├── index.tsx
│ │ │ │ └── style.module.css
│ │ ├── DiffViewer
│ │ │ ├── Container.css
│ │ │ ├── Container.tsx
│ │ │ ├── Diff.tsx
│ │ │ ├── DiffItem.css
│ │ │ ├── DiffItem.tsx
│ │ │ ├── Header
│ │ │ │ ├── index.tsx
│ │ │ │ └── style.module.css
│ │ │ ├── configure.ts
│ │ │ └── index.tsx
│ │ ├── hooks
│ │ │ ├── useElementSize.ts
│ │ │ └── useKey.ts
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── style.module.css
│ │ └── util.ts
│ ├── main
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── CodemodRuns.tsx
│ │ ├── index.html
│ │ └── index.tsx
│ ├── react-app-env.d.ts
│ └── shared
│ │ ├── IntuitaPopover
│ │ └── index.tsx
│ │ ├── Panel.tsx
│ │ ├── Progress
│ │ ├── index.tsx
│ │ └── style.module.css
│ │ ├── SearchBar
│ │ ├── index.tsx
│ │ └── style.module.css
│ │ ├── SectionHeader
│ │ ├── index.tsx
│ │ └── style.module.css
│ │ ├── Snippet
│ │ ├── calculateDiff.tsx
│ │ ├── detectTheme.ts
│ │ └── useTheme.ts
│ │ ├── TreeItem
│ │ ├── index.tsx
│ │ └── style.module.css
│ │ ├── WarningMessage
│ │ ├── index.tsx
│ │ └── style.module.css
│ │ ├── constants.ts
│ │ ├── index.css
│ │ ├── types.ts
│ │ ├── util.css
│ │ └── utilities
│ │ ├── debounce.ts
│ │ ├── throttle.ts
│ │ └── vscode.ts
├── tsconfig.json
├── vite.config.dev.ts
└── vite.config.ts
├── package.json
├── pnpm-lock.yaml
├── resources
├── codicon.css
└── codicon.ttf
├── src
├── axios
│ └── index.ts
├── cases
│ ├── caseManager.ts
│ └── types.ts
├── codemods
│ └── types.ts
├── commands
│ └── clearStateCommand.ts
├── components
│ ├── bootstrapExecutablesService.ts
│ ├── buildArguments.ts
│ ├── downloadService.ts
│ ├── engineService.ts
│ ├── fileService.ts
│ ├── fileSystemUtilities.ts
│ ├── jobManager.ts
│ ├── messageBus.ts
│ ├── textDocumentContentProvider.ts
│ ├── userService.ts
│ └── webview
│ │ ├── CodemodDescriptionProvider.ts
│ │ ├── ErrorWebviewProvider.ts
│ │ ├── IntuitaPanelProvider.ts
│ │ ├── MainProvider.ts
│ │ ├── WebviewResolver.ts
│ │ ├── panelViewProps.ts
│ │ └── webviewEvents.ts
├── configuration.ts
├── container.ts
├── data
│ ├── codemodConfigSchema.ts
│ ├── index.ts
│ ├── privateCodemodsEnvelopeSchema.ts
│ ├── readHomeDirectoryCases.ts
│ ├── schemata
│ │ └── argumentRecordSchema.ts
│ ├── slice.ts
│ ├── storage.ts
│ └── urlParamsEnvelopeSchema.ts
├── errors
│ └── types.ts
├── extension.ts
├── github
│ └── types.ts
├── jobs
│ ├── acceptJobs.ts
│ ├── buildJobHash.ts
│ └── types.ts
├── leftRightHashes
│ └── leftRightHashSetManager.ts
├── packageJsonAnalyzer
│ └── types.ts
├── persistedState
│ ├── codecs.ts
│ └── explorerNodeCodec.ts
├── selectors
│ ├── comparePersistedJobs.ts
│ ├── selectCodemodRunsTree.ts
│ ├── selectCodemodTree.ts
│ ├── selectErrorWebviewViewProps.ts
│ ├── selectExplorerTree.ts
│ ├── selectMainWebviewViewProps.ts
│ └── selectSourceControlTabProps.ts
├── telemetry
│ ├── hashes.ts
│ ├── telemetry.ts
│ └── vscodeTelemetry.ts
├── types
│ ├── reset.d.ts
│ └── vscode.d.ts
├── uris
│ ├── buildUriHash.ts
│ └── types.ts
└── utilities.ts
├── test
└── dowloadService.test.ts
├── tsconfig.json
└── webpack.config.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "extends": [
9 | "eslint:recommended",
10 | "plugin:@typescript-eslint/eslint-recommended",
11 | "plugin:@typescript-eslint/recommended",
12 | "prettier"
13 | ],
14 | "plugins": ["@typescript-eslint"],
15 | "ignorePatterns": ["out", "dist", "**/*.d.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[bug] example bug in extension"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | > :warning: Use this to report bugs related to the Intuita VS Code extension, not codemod-specific issues and improvements. For codemod-specific issues, please [submit an issue in the codemod registry](https://github.com/codemod-com/codemod-registry/issues).
11 |
12 | ### Describe the bug
13 | A clear and concise description of what the bug is.
14 |
15 | ### Steps to Reproduce
16 | Steps to reproduce the behavior:
17 | 1. Go to '...'
18 | 2. Click on '....'
19 | 3. Scroll down to '....'
20 | 4. See error
21 |
22 | ### Screenshots
23 | If applicable, add screenshots to help explain your problem.
24 |
25 | ### Actual behavior
26 | A clear and concise description of what actually happened.
27 |
28 | ### Expected behavior
29 | A clear and concise description of what you expected to happen.
30 |
31 | ### Environment:
32 | - Intuita extension version: [e.g. v0.36.5]
33 | - OS: [e.g. MacOS 13.0.1]
34 | - Node.js version: [e.g. v16.16.0]
35 |
36 | ### Additional context
37 | Add any other context about the problem here.
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | contact_links:
2 | - name: Questions
3 | url: https://intuita.io/community
4 | about: Ask us any questions on our Slack community.
5 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a feature you want
4 | title: "[feat] example feature request"
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Is your feature request related to a problem? Please describe.
11 | A clear and concise description of what the problem is. [e.g. I get frustrated when...]
12 |
13 | ### Describe the solution you'd like
14 | A clear and concise description of what you want to happen. [e.g. I would love to see...]
15 |
16 | ### Describe alternatives you've considered
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | ### Additional context
20 | Add any other context or screenshots about the feature request here.
21 |
22 | ### Documents
23 | Add any other documents that might help describe the feature you want. [e.g. prototypes, design illustrations, POCs, etc.]
24 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | on: [push]
2 |
3 | name: CI
4 |
5 | jobs:
6 | SpellCheck:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/setup-node@v3
10 | with:
11 | node-version: 16
12 | - uses: actions/checkout@v2
13 | - name: Install modules
14 | uses: pnpm/action-setup@v2
15 | with:
16 | version: 8
17 | - name: Install dependencies
18 | run: pnpm install
19 | - name: Check spelling
20 | run: pnpm spellcheck
21 | Build:
22 | runs-on: ubuntu-latest
23 | steps:
24 | - uses: actions/setup-node@v3
25 | with:
26 | node-version: 16
27 | - uses: actions/checkout@v2
28 | - name: Install modules
29 | uses: pnpm/action-setup@v2
30 | with:
31 | version: 8
32 | - name: Install vsce
33 | run: pnpm add -g @vscode/vsce
34 | - name: Install dependencies
35 | run: pnpm install
36 | - name: Package using webpack
37 | run: pnpm run build
38 | Lint:
39 | runs-on: ubuntu-latest
40 | steps:
41 | - uses: actions/setup-node@v3
42 | with:
43 | node-version: 16
44 | - uses: actions/checkout@v2
45 | - name: Install modules
46 | uses: pnpm/action-setup@v2
47 | with:
48 | version: 8
49 | - name: Install dependencies
50 | run: pnpm install
51 | - name: Run ESLint
52 | run: pnpm eslint src --ext ts
53 | Prettier:
54 | runs-on: ubuntu-latest
55 | steps:
56 | - uses: actions/setup-node@v3
57 | with:
58 | node-version: 16
59 | - uses: actions/checkout@v2
60 | - name: Install modules
61 | uses: pnpm/action-setup@v2
62 | with:
63 | version: 8
64 | - name: Install dependencies
65 | run: pnpm install
66 | - name: Ensure Prettier was run
67 | run: pnpm prettier --check .
68 |
--------------------------------------------------------------------------------
/.github/workflows/codesee-arch-diagram.yml:
--------------------------------------------------------------------------------
1 | # This workflow was added by CodeSee. Learn more at https://codesee.io/
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request_target:
7 | types: [opened, synchronize, reopened]
8 |
9 | name: CodeSee
10 |
11 | permissions: read-all
12 |
13 | jobs:
14 | codesee:
15 | runs-on: ubuntu-latest
16 | continue-on-error: true
17 | name: Analyze the repo with CodeSee
18 | steps:
19 | - uses: Codesee-io/codesee-action@v2
20 | with:
21 | codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }}
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 | .idea
7 | *.js
8 | yarn-error.log
9 | .DS_Store
10 |
11 | build
12 |
13 | .trunk
--------------------------------------------------------------------------------
/.mocharc.yml:
--------------------------------------------------------------------------------
1 | require:
2 | - 'ts-node/register'
3 | - 'source-map-support/register'
4 | full-trace: true
5 | bail: true
6 | spec: './test/**/*.test.ts'
7 | timeout: 10000
8 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | img
3 | resources
4 | *.md
5 | pnpm-lock.yaml
6 | yarn.lock
7 | intuita-webview/build
8 |
9 | .trunk
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "useTabs": true,
4 | "semi": true,
5 | "singleQuote": true,
6 | "quoteProps": "as-needed",
7 | "trailingComma": "all",
8 | "bracketSpacing": true,
9 | "arrowParens": "always",
10 | "endOfLine": "lf"
11 | }
12 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint",
6 | "amodio.tsl-problem-matcher",
7 | "streetsidesoftware.code-spell-checker"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
13 | "outFiles": ["${workspaceFolder}/dist/**/*.js"],
14 | "preLaunchTask": "${defaultBuildTask}"
15 | },
16 | {
17 | "name": "Extension Tests",
18 | "type": "extensionHost",
19 | "request": "launch",
20 | "args": [
21 | "--extensionDevelopmentPath=${workspaceFolder}",
22 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
23 | ],
24 | "outFiles": [
25 | "${workspaceFolder}/out/**/*.js",
26 | "${workspaceFolder}/dist/**/*.js"
27 | ],
28 | "preLaunchTask": "tasks: watch-tests"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files
5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true, // set this to false to include "out" folder in search results
9 | "dist": true // set this to false to include "dist" folder in search results
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off",
13 | "typescript.tsdk": "node_modules/typescript/lib"
14 | }
15 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": ["$ts-webpack-watch", "$tslint-webpack-watch"],
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never",
13 | "group": "watchers"
14 | },
15 | "group": {
16 | "kind": "build",
17 | "isDefault": true
18 | }
19 | },
20 | {
21 | "type": "npm",
22 | "script": "watch-tests",
23 | "problemMatcher": "$tsc-watch",
24 | "isBackground": true,
25 | "presentation": {
26 | "reveal": "never",
27 | "group": "watchers"
28 | },
29 | "group": "build"
30 | },
31 | {
32 | "label": "tasks: watch-tests",
33 | "dependsOn": ["npm: watch", "npm: watch-tests"],
34 | "problemMatcher": []
35 | }
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | node_modules/**
5 | src/**
6 | test/**
7 | .gitignore
8 | .yarnrc
9 | webpack.config.js
10 | vsc-extension-quickstart.md
11 | **/tsconfig.json
12 | **/.eslintrc.json
13 | **/*.map
14 | **/*.ts
15 | .idea
16 | .github
17 |
18 | intuita-webview/node_modules/**
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | --ignore-engines true
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | This page lists highlights, releases, bug fixes, and progress for official releases of Intuita VSCode Extension.
4 |
5 | > **Tip:** If there are features you would like to see in the upcoming releases, please let us know though our [feedback page](https://feedback.intuita.io), or directly through our [Slack community](https://intuita.io/community).
6 |
7 | ## Version 0.37.0
8 |
9 | _Release date: December 1, 2023_
10 |
11 | ### **Highlights**
12 |
13 | - 🔲 Fetch the latest codemods from codemod registry every 15 minutes ([#831](https://github.com/codemod-com/intuita-vscode-extension/pull/831))
14 | - 🐍 Another item
15 |
16 | **Notable Changes**
17 |
18 | - ⌛ Some time saving highlight ([#1234](https://github.com), [#1234](https://github.com)).
19 | - 🏃 Some performance improvement ([#1234](https://github.com), [#1234](https://github.com)).
20 | - 🛁 Some code cleanup ([#1234](https://github.com), [#1234](https://github.com)).
21 | - 💅 Some visual improvement ([#1234](https://github.com), [#1234](https://github.com)).
22 |
23 | **Bug fixes & other changes**
24 |
25 | - 🦗 Bug fix: Description of bug fix ([#1234](https://github.com/)). Thanks, [Community Member](https://github.com)!
26 | - 🦎 Bug fix: Description of another bug fix ([#1234](https://github.com/), [#1234](https://github.com/), [#1234](https://github.com/)). Thanks, [Community Member](https://github.com)!
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **⚠️ This repository is deprecated and no longer maintained.**
2 |
3 | **Please Note:** This repository was migrated to a monorepo called [codemod](https://github.com/codemod-com/codemod/tree/main/apps/vsce).
4 |
5 | # A better way to discover & run community-led codemods
6 |
7 | Upgrade your projects with the help of codemods created by experts in the community, one framework at a time, starting with Next.js v13.4.
8 |
9 | > 🎁 What frameworks should we support next? [Let us know →](https://feedback.intuita.io/codemod-requests)
10 |
11 | ## 1. Discover
12 |
13 | - Intuita is **a one-stop shop for discovering & sharing quality-governed codemods.** You don't need to install and run many codemod engines for each dependency. Simply search for your framework codemods and click run. With codemod deep links, you can reach & run your target codemod with just one click.
14 |
15 | 
16 |
17 | ## 2. Run
18 |
19 | - **Safely dry-run the codemods**, preview the changes with a user-friendly experience, adjust the changes as necessary, and apply them to your code only when you feel confident.
20 |
21 | 
22 |
23 | ## 3. Customize & Improve
24 |
25 | - Leverage the **1-click integration with Codemod Studio** and the feedback loop with the **community of Codemod Champions** to continuously improve Codemods and customize them to your needs.
26 |
27 | > 💡 Intuita is in Public Beta and we’re continuously working on improving codemods and solving any compatibility issues.
28 | If you run into an issue while running a codemod, please [let us know →](https://feedback.intuita.io/feature-requests-and-bugs)
29 |
30 | ## Other Features
31 |
32 | - **Out-of-the-box Prettier Integration -** Your favorite code transformation engines such as Meta’s JSCodeshift or TS-morph will mess up the formatting. Intuita will automatically prettify the changes according to your settings, saving you much time and energy for more exciting features.
33 | - **Multi-threading -** Execute codemods faster than you would with vanilla jscodeshift or ts-morph. Intuita's engine uses multi-threading, which is customizable via extension settings, to take full advantage of your machine's computing power and expedite large-scale changes.
34 | - For advanced settings & features, visit the [Intuita docs.](https://docs.intuita.io/docs/vs-code-extension/quickstart)
35 |
36 | # Extension vs. the Platform
37 |
38 | 
39 |
40 | - **To learn more about codemod.studio, registry, and the CLI visit the [Intuita docs here](https://docs.intuita.io/docs/intro).**
41 |
42 |
43 | ## Telemetry 🔭
44 |
45 | - The extension collects telemetry data to help us improve the product for you.
46 | - **We never send PII, OS information, file, or folder names.**
47 | - Telemetry can be disabled in the settings.
48 | - See more details in our [telemetry compliance considerations](https://docs.intuita.io/docs/about-intuita/legal/telemetry-compliance) doc.
49 |
50 | ## Share Feedback 🎁
51 |
52 | - Please share your ideas, questions, and feature requests **[here](https://feedback.intuita.io/)**, or chat with us in [Slack](https://join.slack.com/t/codemod-com/shared_invite/zt-1tvxm6ct0-mLZld_78yguDYOSM7DM7Cw).
53 |
--------------------------------------------------------------------------------
/cspell.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignorePaths": ["**/*.d.ts"],
3 | "dictionaries": [
4 | "en_US",
5 | "typescript",
6 | "html",
7 | "companies",
8 | "softwareTerms"
9 | ],
10 | "language": "en",
11 | "useGitignore": true,
12 | "words": [
13 | "Caartaa",
14 | "campaigns",
15 | "codebases",
16 | "codemod",
17 | "codemods",
18 | "coderepair",
19 | "gppd",
20 | "intellicode",
21 | "intuita",
22 | "kase",
23 | "newtype",
24 | "nextjs",
25 | "quickstart",
26 | "pluggable",
27 | "refactorings",
28 | "routerv",
29 | "ripemd",
30 | "roadmap",
31 | "tabnine",
32 | "taskifies",
33 | "Upvote",
34 | "userdata",
35 | "vsix",
36 | "yarnrc",
37 | "cutcopypaste",
38 | "codicons",
39 | "codicon",
40 | "upsert",
41 | "jscodeshift",
42 | "Codeshift",
43 | "unapply",
44 | "redwoodjs",
45 | "repomod",
46 | "hashless",
47 | "interfase",
48 | "Quotify",
49 | "Descendents",
50 | "overscan",
51 | "reactjs",
52 | "Collapsable",
53 | "bpfrpt",
54 | "proptype",
55 | "svgr",
56 | "preact",
57 | "filemod",
58 | "QKEdp-pofR9UnglrKAGDm1Oj6W0",
59 | "Disactivated",
60 | "immutablejsv",
61 | "reactrouterv",
62 | "reduxjs",
63 | "persistor",
64 | "webviews",
65 | "activeid",
66 | "tippyjs",
67 | "fuzzysort",
68 | "redeclared",
69 | "monacoeditorwork",
70 | "whitespace",
71 | "tiptap",
72 | "lowlight",
73 | "lowlights",
74 | "unsanitize",
75 | "toastify",
76 | "Toastify",
77 | "POSTAMBLE",
78 | "INTC",
79 | "INTJ",
80 | "INTE",
81 | "Crossplatform",
82 | "nodir"
83 | ]
84 | }
85 |
--------------------------------------------------------------------------------
/img/codemod-icon-mask.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/img/codemod-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemod-com/intuita-vscode-extension/cc9b2e9fc70e894b3e92dcd48a980476dca1652d/img/codemod-square.png
--------------------------------------------------------------------------------
/img/codemod-square.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/img/intuita.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/img/intuita_square128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemod-com/intuita-vscode-extension/cc9b2e9fc70e894b3e92dcd48a980476dca1652d/img/intuita_square128.png
--------------------------------------------------------------------------------
/intuita-webview/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers=true
2 |
--------------------------------------------------------------------------------
/intuita-webview/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Intuita
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/intuita-webview/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "intuita-webview",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@monaco-editor/react": "^4.5.0",
7 | "@tippyjs/react": "^4.2.6",
8 | "@tiptap/extension-code-block-lowlight": "^2.1.8",
9 | "@tiptap/pm": "^2.1.8",
10 | "@tiptap/react": "^2.1.8",
11 | "@tiptap/starter-kit": "^2.1.8",
12 | "@vscode/webview-ui-toolkit": "^1.2.2",
13 | "classnames": "^2.3.2",
14 | "fp-ts": "^2.14.0",
15 | "lowlight": "^3.0.0",
16 | "monaco-editor": "^0.37.1",
17 | "preact": "^10.13.2",
18 | "preact-compat": "^3.19.0",
19 | "rc-progress": "^3.4.1",
20 | "react": "^18.2.0",
21 | "react-dom": "^18.2.0",
22 | "react-markdown": "^8.0.7",
23 | "react-resizable-panels": "^0.0.51",
24 | "react-toastify": "^9.1.3",
25 | "tippy.js": "^6.3.7",
26 | "typescript": "^4.9.5"
27 | },
28 | "scripts": {
29 | "start": "NODE_ENV='development' vite -c 'vite.config.dev.ts'",
30 | "build:main": "NODE_ENV='production' TARGET_APP='main' vite build",
31 | "build:jobDiffView": "NODE_ENV='production' TARGET_APP='jobDiffView' vite build",
32 | "build:errors": "NODE_ENV='production' TARGET_APP='errors' vite build",
33 | "build": "pnpm build:main && pnpm build:jobDiffView && pnpm build:errors"
34 | },
35 | "eslintConfig": {
36 | "extends": [
37 | "react-app",
38 | "react-app/jest"
39 | ]
40 | },
41 | "browserslist": {
42 | "production": [
43 | ">0.2%",
44 | "not dead",
45 | "not op_mini all"
46 | ],
47 | "development": [
48 | "last 1 chrome version",
49 | "last 1 firefox version",
50 | "last 1 safari version"
51 | ]
52 | },
53 | "devDependencies": {
54 | "@preact/preset-vite": "^2.5.0",
55 | "@testing-library/jest-dom": "^5.16.5",
56 | "@testing-library/react": "^13.4.0",
57 | "@testing-library/user-event": "^13.5.0",
58 | "@types/jest": "^27.5.2",
59 | "@types/node": "^16.18.21",
60 | "@types/react": "^18.0.30",
61 | "@types/react-dom": "^18.0.11",
62 | "@types/react-treeview": "^0.4.3",
63 | "@types/react-virtualized": "^9.21.21",
64 | "@types/testing-library__jest-dom": "^5.14.5",
65 | "@types/vscode-webview": "^1.57.1",
66 | "@vitejs/plugin-react": "^4.0.0",
67 | "react-scripts": "5.0.1",
68 | "vite": "^4.3.1",
69 | "vite-plugin-monaco-editor": "^1.1.0",
70 | "vite-plugin-svgr": "^2.4.0",
71 | "vite-tsconfig-paths": "^4.2.0"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/intuita-webview/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Intuita
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/intuita-webview/src/CreateIssue/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEditor, EditorContent } from '@tiptap/react';
2 | import StarterKit from '@tiptap/starter-kit';
3 | import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';
4 | import { common, createLowlight } from 'lowlight';
5 | import {
6 | VSCodeButton,
7 | VSCodeProgressRing,
8 | VSCodeTextField,
9 | } from '@vscode/webview-ui-toolkit/react';
10 | import { useEffect, useState } from 'react';
11 | import { vscode } from '../shared/utilities/vscode';
12 | import styles from './style.module.css';
13 | import './tiptap.css';
14 |
15 | const lowlight = createLowlight(common);
16 | const unsanitizeCodeBlock = (codeBlock: string) =>
17 | codeBlock.replace(/</g, '<').replace(/>/g, '>');
18 |
19 | const convertHTMLCodeBlockToMarkdownString = (htmlSnippet: string) =>
20 | htmlSnippet.replace(
21 | /(.*?)<\/code><\/pre>/gs,
22 | (_match, language, content) =>
23 | `\n\n\`\`\`${language ?? 'typescript'}\n${unsanitizeCodeBlock(
24 | content,
25 | )}\n\`\`\`\n\n`,
26 | );
27 |
28 | type Props = Readonly<{
29 | title: string;
30 | body: string;
31 | loading: boolean;
32 | }>;
33 |
34 | const CreateIssue = (props: Props) => {
35 | const [title, setTitle] = useState('');
36 |
37 | const onChangeTitle = (e: Event | React.FormEvent) => {
38 | const value =
39 | 'target' in e && e.target !== null && 'value' in e.target
40 | ? String(e.target.value)
41 | : null;
42 |
43 | if (value === null) {
44 | return;
45 | }
46 |
47 | setTitle(value);
48 | };
49 | const handleSubmit = (e: React.FormEvent) => {
50 | e.preventDefault();
51 |
52 | if (editor === null) {
53 | return;
54 | }
55 |
56 | const htmlSnippet = editor.getHTML();
57 |
58 | vscode.postMessage({
59 | kind: 'webview.sourceControl.createIssue',
60 | data: {
61 | title,
62 | body: convertHTMLCodeBlockToMarkdownString(htmlSnippet),
63 | },
64 | });
65 | };
66 |
67 | const extensions = [
68 | StarterKit.configure({
69 | codeBlock: false,
70 | }),
71 | CodeBlockLowlight.configure({
72 | lowlight,
73 | // in our editor, we provide 1 syntax highlighting for all languages;
74 | // once transmitted to Github, the syntax highlighting will be handled there, and therefore
75 | // different syntax highlighting will be applied to different languages there;
76 | defaultLanguage: 'typescript',
77 | }),
78 | ];
79 |
80 | const editor = useEditor({
81 | extensions,
82 | content: props.body,
83 | editable: true,
84 | });
85 |
86 | useEffect(() => {
87 | setTitle(props.title);
88 | }, [props.title]);
89 |
90 | useEffect(() => {
91 | if (props.loading) {
92 | return;
93 | }
94 | editor?.commands.setContent(props.body, false, {
95 | preserveWhitespace: true,
96 | });
97 | }, [editor, props.body, props.loading]);
98 |
99 | return (
100 |
101 |
Report codemod issue
102 |
137 |
138 | );
139 | };
140 |
141 | export default CreateIssue;
142 |
--------------------------------------------------------------------------------
/intuita-webview/src/CreateIssue/style.module.css:
--------------------------------------------------------------------------------
1 | .root {
2 | width: 100%;
3 | padding: 0 0.5rem;
4 | }
5 |
6 | .form {
7 | display: flex;
8 | flex-direction: column;
9 | row-gap: 8px;
10 | padding: 4px;
11 | }
12 |
13 | .actionButton {
14 | height: 24px;
15 | width: 160px;
16 | }
17 |
18 | .formField {
19 | display: flex;
20 | flex-direction: column;
21 | }
22 |
23 | .actions {
24 | display: flex;
25 | column-gap: 8px;
26 | justify-content: flex-end;
27 | }
28 |
29 | .title::part(label) {
30 | margin-bottom: 0.5rem;
31 | cursor: default;
32 | }
33 |
34 | .body::part(label) {
35 | margin-bottom: 0.5rem;
36 | }
37 |
38 | .label {
39 | font-size: var(--type-ramp-base-font-size);
40 | line-height: var(--type-ramp-base-line-height);
41 | display: block;
42 | color: var(--foreground);
43 | user-select: none;
44 | }
45 |
46 | .loadingContainer {
47 | display: flex;
48 | align-items: center;
49 | }
50 |
51 | .progressRing {
52 | width: 16px;
53 | height: 16px;
54 | margin-right: 12px;
55 | }
56 |
57 | .progressRing::part(indeterminate-indicator-1) {
58 | stroke: var(--vscode-icon-foreground);
59 | }
60 |
--------------------------------------------------------------------------------
/intuita-webview/src/CreateIssue/tiptap.css:
--------------------------------------------------------------------------------
1 | .tiptap {
2 | background: var(--input-background);
3 | outline: none;
4 | height: 70vh;
5 | overflow: auto;
6 | padding: 1px calc(var(--design-unit) * 2px + 1px);
7 | }
8 |
9 | .tiptap ul,
10 | .tiptap ol {
11 | padding: 0 1rem;
12 | }
13 |
14 | .tiptap h1,
15 | .tiptap h2,
16 | .tiptap h3,
17 | .tiptap h4,
18 | .tiptap h5,
19 | .tiptap h6 {
20 | line-height: 1.1;
21 | }
22 |
23 | .tiptap code {
24 | background-color: transparent;
25 | }
26 |
27 | .tiptap pre {
28 | background: #0d0d0d;
29 | color: #fff;
30 | font-family: 'JetBrainsMono', monospace;
31 | padding: 0.75rem 1rem;
32 | border-radius: 0.5rem;
33 | }
34 |
35 | .tiptap pre code {
36 | color: inherit;
37 | padding: 0;
38 | background: none;
39 | font-size: 0.8rem;
40 | }
41 |
42 | .tiptap img {
43 | max-width: 100%;
44 | height: auto;
45 | }
46 |
47 | .tiptap blockquote {
48 | padding-left: 1rem;
49 | border-left: 2px solid white;
50 | margin-inline-start: 0px;
51 | margin-inline-end: 0px;
52 | background: transparent;
53 | }
54 |
55 | .tiptap hr {
56 | border: none;
57 | border-top: 2px solid white;
58 | margin: 2rem 0;
59 | }
60 |
61 | /*
62 | - styling for syntax highlights; we don't support different syntax highlights for different languages
63 | - copied from .scss file of demo in https://tiptap.dev/api/nodes/code-block-lowlight#usage
64 | */
65 |
66 | .tiptap .hljs-comment,
67 | .tiptap .hljs-quote {
68 | color: #616161;
69 | }
70 |
71 | .tiptap .hljs-variable,
72 | .tiptap .hljs-template-variable,
73 | .tiptap .hljs-attribute,
74 | .tiptap .hljs-tag,
75 | .tiptap .hljs-name,
76 | .tiptap .hljs-regexp,
77 | .tiptap .hljs-link,
78 | .tiptap .hljs-name,
79 | .tiptap .hljs-selector-id,
80 | .tiptap .hljs-selector-class {
81 | color: #f98181;
82 | }
83 |
84 | .tiptap .hljs-number,
85 | .tiptap .hljs-meta,
86 | .tiptap .hljs-built_in,
87 | .tiptap .hljs-builtin-name,
88 | .tiptap .hljs-literal,
89 | .tiptap .hljs-type,
90 | .tiptap .hljs-params {
91 | color: #fbbc88;
92 | }
93 |
94 | .tiptap .hljs-string,
95 | .tiptap .hljs-symbol,
96 | .tiptap .hljs-bullet {
97 | color: #b9f18d;
98 | }
99 |
100 | .tiptap .hljs-title,
101 | .tiptap .hljs-section {
102 | color: #faf594;
103 | }
104 |
105 | .tiptap .hljs-keyword,
106 | .tiptap .hljs-selector-tag {
107 | color: #70cff8;
108 | }
109 |
110 | .tiptap .hljs-emphasis {
111 | font-style: italic;
112 | }
113 |
114 | .tiptap .hljs-strong {
115 | font-weight: 700;
116 | }
117 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/case.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/intuita_square128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemod-com/intuita-vscode-extension/cc9b2e9fc70e894b3e92dcd48a980476dca1652d/intuita-webview/src/assets/intuita_square128.png
--------------------------------------------------------------------------------
/intuita-webview/src/assets/material-icons/check_box.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/material-icons/check_box_outline_blank.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/material-icons/indeterminate_check_box.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intuita-webview/src/assets/slack.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/intuita-webview/src/campaignManager/App.tsx:
--------------------------------------------------------------------------------
1 | import { vscode } from '../shared/utilities/vscode';
2 | import styles from './style.module.css';
3 | import '../shared/util.css';
4 | import { IntuitaTreeView } from '../intuitaTreeView';
5 | import { CaseHash } from '../../../src/cases/types';
6 | import { CodemodRunsTree } from '../../../src/selectors/selectCodemodRunsTree';
7 | import { ReactComponent as CaseIcon } from '../assets/case.svg';
8 | import TreeItem from '../shared/TreeItem';
9 | import { MainWebviewViewProps } from '../../../src/selectors/selectMainWebviewViewProps';
10 | import IntuitaPopover from '../shared/IntuitaPopover';
11 | import cn from 'classnames';
12 | import LoadingProgress from '../jobDiffView/Components/LoadingProgress';
13 |
14 | type InfoIconProps = {
15 | createdAt: number;
16 | path: string;
17 | };
18 |
19 | const InfoIcon = ({ createdAt, path }: InfoIconProps) => {
20 | return (
21 |
26 |
27 |
28 | );
29 | };
30 |
31 | export const App = (
32 | props: MainWebviewViewProps & { activeTabId: 'codemodRuns' },
33 | ) => {
34 | if (props.codemodRunsTree === null) {
35 | // no workspace is chosen
36 | return (
37 |
38 | No change to review! Run some codemods via Codemod Discovery or
39 | VS Code Command & check back later!
40 |
41 | );
42 | }
43 |
44 | if (props.codemodRunsTree.nodeData.length === 0) {
45 | return props.codemodExecutionInProgress ? (
46 | // `nodeData.length` can be zero momentarily even if a codemod is actually in progress
47 |
48 | ) : (
49 |
50 | No change to review! Run some codemods via Codemod Discovery or
51 | VS Code Command & check back later!
52 |
53 | );
54 | }
55 |
56 | return (
57 |
58 | focusedNodeHashDigest={props.codemodRunsTree.selectedNodeHashDigest}
59 | collapsedNodeHashDigests={[]}
60 | nodeData={props.codemodRunsTree.nodeData}
61 | nodeRenderer={(props) => {
62 | return (
63 | }
70 | depth={props.nodeDatum.depth}
71 | indent={props.nodeDatum.depth * 18}
72 | open={false}
73 | focused={props.nodeDatum.focused}
74 | onClick={(event) => {
75 | event.stopPropagation();
76 |
77 | props.onFocus(props.nodeDatum.node.hashDigest);
78 | }}
79 | endDecorator={
80 |
84 | }
85 | inlineStyles={{
86 | root: {
87 | paddingRight: '3px',
88 | },
89 | }}
90 | />
91 | );
92 | }}
93 | onFlip={() => {}}
94 | onFocus={function (hashDigest: CaseHash): void {
95 | vscode.postMessage({
96 | kind: 'webview.campaignManager.setSelectedCaseHash',
97 | caseHash: hashDigest,
98 | });
99 | }}
100 | />
101 | );
102 | };
103 |
--------------------------------------------------------------------------------
/intuita-webview/src/campaignManager/style.module.css:
--------------------------------------------------------------------------------
1 | .welcomeMessage {
2 | padding: 0 20px 1em;
3 | margin-top: 13px;
4 | }
5 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodArguments/FormField/index.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | VSCodeCheckbox,
3 | VSCodeDropdown,
4 | VSCodeOption,
5 | VSCodeTextField,
6 | } from '@vscode/webview-ui-toolkit/react';
7 | import styles from './style.module.css';
8 | import { CodemodArgumentWithValue } from '../../../../../src/selectors/selectCodemodTree';
9 |
10 | type Props = CodemodArgumentWithValue & {
11 | onChange(value: string): void;
12 | };
13 |
14 | const FormField = (props: Props) => {
15 | const { name, kind, value, description, required, onChange } = props;
16 | if (kind === 'string' || kind === 'number') {
17 | return (
18 |
23 | onChange(
24 | (e as React.ChangeEvent).target.value,
25 | )
26 | }
27 | className={styles.field}
28 | title={description}
29 | >
30 | {name} {required && '(required)'}
31 |
32 | );
33 | }
34 |
35 | if (kind === 'options') {
36 | return (
37 |
39 | onChange(
40 | (e as React.ChangeEvent).target.value,
41 | )
42 | }
43 | value={value}
44 | >
45 | {props.options.map((o) => (
46 | {o}
47 | ))}
48 |
49 | );
50 | }
51 |
52 | return (
53 |
54 |
57 | {
61 | onChange(
62 | String(
63 | (e as React.ChangeEvent).target
64 | .checked,
65 | ),
66 | );
67 | }}
68 | />
69 |
70 | );
71 | };
72 |
73 | export default FormField;
74 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodArguments/FormField/style.module.css:
--------------------------------------------------------------------------------
1 | .field {
2 | width: 100%;
3 | }
4 |
5 | .fieldLayout {
6 | display: flex;
7 | flex-direction: column;
8 | gap: 8px;
9 | }
10 |
11 | .label {
12 | font-size: var(--type-ramp-base-font-size);
13 | line-height: var(--type-ramp-base-line-height);
14 | display: block;
15 | color: var(--foreground);
16 | user-select: none;
17 | }
18 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodArguments/index.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | CodemodArgumentWithValue,
3 | CodemodNodeHashDigest,
4 | } from '../../../../src/selectors/selectCodemodTree';
5 | import { CodemodHash } from '../../shared/types';
6 | import { vscode } from '../../shared/utilities/vscode';
7 |
8 | import FormField from './FormField';
9 | import styles from './styles.module.css';
10 |
11 | import { DirectorySelector } from '../components/DirectorySelector';
12 |
13 | import { pipe } from 'fp-ts/lib/function';
14 | import * as T from 'fp-ts/These';
15 | import * as O from 'fp-ts/Option';
16 |
17 | type Props = Readonly<{
18 | hashDigest: CodemodNodeHashDigest;
19 | arguments: ReadonlyArray;
20 | autocompleteItems: ReadonlyArray;
21 | executionPath: T.These<{ message: string }, string>;
22 | }>;
23 |
24 | const updatePath = (value: string, codemodHash: CodemodHash) => {
25 | vscode.postMessage({
26 | kind: 'webview.codemodList.updatePathToExecute',
27 | value: {
28 | newPath: value,
29 | codemodHash,
30 | errorMessage: '',
31 | warningMessage: '',
32 | revertToPrevExecutionIfInvalid: false,
33 | },
34 | });
35 | };
36 |
37 | const CodemodArguments = ({
38 | hashDigest,
39 | arguments: args,
40 | autocompleteItems,
41 | executionPath,
42 | }: Props) => {
43 | const onChangeFormField = (fieldName: string) => (value: string) => {
44 | vscode.postMessage({
45 | kind: 'webview.global.setCodemodArgument',
46 | hashDigest,
47 | name: fieldName,
48 | value,
49 | });
50 | };
51 |
52 | const path: string = pipe(
53 | O.fromNullable(executionPath),
54 | O.fold(
55 | () => '',
56 | T.fold(
57 | () => '',
58 | (p) => p,
59 | (_, p) => p,
60 | ),
61 | ),
62 | );
63 |
64 | return (
65 |
66 |
81 |
82 | );
83 | };
84 |
85 | export default CodemodArguments;
86 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodArguments/styles.module.css:
--------------------------------------------------------------------------------
1 | .root {
2 | z-index: 1;
3 | width: 100%;
4 | padding: 1em;
5 | box-sizing: border-box;
6 | }
7 |
8 | .form {
9 | display: flex;
10 | flex-direction: column;
11 | row-gap: 8px;
12 | padding: 4px;
13 | }
14 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodNodeRenderer/Directory.tsx:
--------------------------------------------------------------------------------
1 | import cn from 'classnames';
2 | import s from './style.module.css';
3 | import { memo } from 'react';
4 |
5 | const Directory = (
6 | props: Readonly<{
7 | expanded: boolean;
8 | label: string;
9 | }>,
10 | ) => {
11 | return (
12 | <>
13 |
19 |
20 |
21 | {props.label}
22 |
23 |
24 | >
25 | );
26 | };
27 |
28 | export default memo(Directory);
29 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/CodemodNodeRenderer/style.module.css:
--------------------------------------------------------------------------------
1 | .root {
2 | display: flex;
3 | align-items: center;
4 | flex: 1;
5 | text-overflow: ellipsis;
6 | overflow: hidden;
7 | flex-wrap: nowrap;
8 | align-items: center;
9 | min-height: 28px;
10 | }
11 |
12 | .root:not(.focused):hover {
13 | background-color: var(--vscode-list-hoverBackground);
14 | }
15 |
16 | .focused {
17 | background-color: var(--vscode-list-activeSelectionBackground);
18 | }
19 |
20 | .root:focus-visible {
21 | outline: none;
22 | }
23 |
24 | .root .actionGroup {
25 | opacity: 0;
26 | }
27 |
28 | .root:hover .actionGroup,
29 | .focused .actionGroup {
30 | opacity: 1;
31 | }
32 |
33 | .root:hover .description {
34 | display: inline;
35 | }
36 |
37 | .labelContainer {
38 | line-height: 22px;
39 | font-size: 13px;
40 | cursor: pointer;
41 | color: var(--vscode-foreground);
42 | width: 100%;
43 | display: flex;
44 | align-items: center;
45 | }
46 |
47 | .labelContainer.focused {
48 | color: var(--vscode-list-activeSelectionForeground);
49 | }
50 |
51 | .directorySelector {
52 | display: flex;
53 | }
54 |
55 | .description {
56 | color: var(--vscode-descriptionForeground);
57 | font-size: 12px;
58 | line-height: normal;
59 | margin-left: 5px;
60 | display: none;
61 | }
62 |
63 | .actionGroup {
64 | display: flex;
65 | margin-left: auto;
66 | height: 100%;
67 | align-items: center;
68 | min-width: fit-content;
69 | }
70 |
71 | .label {
72 | user-select: none;
73 | text-overflow: ellipsis;
74 | overflow: hidden;
75 | white-space: nowrap;
76 | color: inherit;
77 | }
78 |
79 | .codemodRoot {
80 | display: flex;
81 | gap: 4px;
82 | align-items: center;
83 | width: 100%;
84 | padding: 0 3px;
85 | min-height: 28px;
86 | box-sizing: border-box;
87 | }
88 |
89 | .expandableContent {
90 | background-color: var(--vscode-panel-background);
91 | }
92 |
93 | .progressContainer {
94 | width: 100%;
95 | padding: 0.5em;
96 | padding-top: 0.1em;
97 | box-sizing: border-box;
98 | }
99 |
100 | .progressStatusLabel {
101 | font-size: var(--type-ramp-base-font-size);
102 | line-height: var(--type-ramp-base-line-height);
103 | color: var(--foreground);
104 | user-select: none;
105 | text-overflow: ellipsis;
106 | overflow: hidden;
107 | white-space: nowrap;
108 | }
109 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/ActionButton.tsx:
--------------------------------------------------------------------------------
1 | import { VSCodeButton } from '@vscode/webview-ui-toolkit/react';
2 | import IntuitaPopover from '../../shared/IntuitaPopover';
3 | import cn from 'classnames';
4 | import s from './style.module.css';
5 | import { CSSProperties } from 'react';
6 |
7 | type Props = {
8 | id?: string;
9 | content?: string;
10 | iconName?: string;
11 | children?: React.ReactNode;
12 | onClick(e: React.MouseEvent): void;
13 | disabled?: boolean;
14 | style?: CSSProperties;
15 | active?: boolean;
16 | };
17 |
18 | const ActionButton = ({
19 | content,
20 | disabled,
21 | iconName,
22 | children,
23 | style,
24 | id,
25 | active,
26 | onClick,
27 | }: Props) => {
28 | return (
29 |
30 | {
35 | e.stopPropagation();
36 | onClick(e);
37 | }}
38 | disabled={disabled}
39 | style={style}
40 | >
41 | {iconName ? (
42 |
43 | ) : null}
44 | {children}
45 |
46 |
47 | );
48 | };
49 |
50 | export default ActionButton;
51 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/InfiniteProgress.module.css:
--------------------------------------------------------------------------------
1 | /* inspired by https://dev.to/themodernweb/quick-css-make-infinity-loading-animation-for-your-next-website-187k */
2 |
3 | .progressContainer {
4 | position: relative;
5 | width: 100%;
6 | height: 2.5px;
7 | overflow: hidden;
8 | border-radius: 10px;
9 | }
10 |
11 | .progress {
12 | position: absolute;
13 | width: 100%;
14 | height: 100%;
15 | background: var(--vscode-progressBar-background);
16 | border-radius: 10px;
17 | left: -100%;
18 | animation: loading 1s linear infinite;
19 | }
20 |
21 | @keyframes loading {
22 | 0% {
23 | left: -100%;
24 | }
25 | 100% {
26 | left: 100%;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/InfiniteProgress.tsx:
--------------------------------------------------------------------------------
1 | import styles from './InfiniteProgress.module.css';
2 |
3 | export const InfiniteProgress = () => (
4 |
7 | );
8 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/ProgressBar.tsx:
--------------------------------------------------------------------------------
1 | import { Line } from 'rc-progress';
2 |
3 | const ProgressBar = (
4 | props: Readonly<{
5 | percent: number;
6 | }>,
7 | ) => (
8 |
9 |
17 |
18 | );
19 |
20 | export default ProgressBar;
21 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/index.tsx:
--------------------------------------------------------------------------------
1 | import { vscode } from '../../shared/utilities/vscode';
2 |
3 | import { useProgressBar } from '../useProgressBar';
4 |
5 | import {
6 | CodemodNode,
7 | CodemodNodeHashDigest,
8 | CodemodTree,
9 | NodeDatum,
10 | } from '../../../../src/selectors/selectCodemodTree';
11 |
12 | import { IntuitaTreeView } from '../../intuitaTreeView';
13 | import { getCodemodNodeRenderer } from '../CodemodNodeRenderer';
14 |
15 | type Props = Readonly<{
16 | tree: CodemodTree;
17 | screenWidth: number | null;
18 | autocompleteItems: ReadonlyArray;
19 | rootPath: string | null;
20 | }>;
21 |
22 | const onFocus = (hashDigest: CodemodNodeHashDigest) => {
23 | vscode.postMessage({
24 | kind: 'webview.global.selectCodemodNodeHashDigest',
25 | selectedCodemodNodeHashDigest: hashDigest,
26 | });
27 | };
28 |
29 | const onFlip = (hashDigest: CodemodNodeHashDigest) => {
30 | vscode.postMessage({
31 | kind: 'webview.global.flipCodemodHashDigest',
32 | codemodNodeHashDigest: hashDigest,
33 | });
34 |
35 | onFocus(hashDigest);
36 | };
37 |
38 | const TreeView = ({
39 | tree,
40 | autocompleteItems,
41 | rootPath,
42 | screenWidth,
43 | }: Props) => {
44 | const progress = useProgressBar();
45 |
46 | return (
47 |
48 | {...tree}
49 | nodeRenderer={getCodemodNodeRenderer({
50 | progress,
51 | screenWidth,
52 | autocompleteItems,
53 | rootPath,
54 | })}
55 | onFlip={onFlip}
56 | onFocus={onFocus}
57 | />
58 | );
59 | };
60 |
61 | export default TreeView;
62 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/TreeView/style.module.css:
--------------------------------------------------------------------------------
1 | .action {
2 | margin-left: 3px;
3 | display: flex;
4 | align-items: center;
5 | color: inherit;
6 | }
7 |
8 | .active {
9 | background: var(--button-icon-hover-background);
10 | outline: 1px dotted var(--contrast-active-border);
11 | outline-offset: -1px;
12 | }
13 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/components/DirectorySelector.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useLayoutEffect, useState } from 'react';
2 | import {
3 | VSCodeOption,
4 | VSCodeTextField,
5 | } from '@vscode/webview-ui-toolkit/react';
6 | import styles from './style.module.css';
7 | import cn from 'classnames';
8 |
9 | type Props = {
10 | initialValue: string;
11 | autocompleteItems: ReadonlyArray;
12 | onChange: (value: string) => void;
13 | };
14 |
15 | const AUTOCOMPLETE_OPTIONS_LENGTH = 20;
16 |
17 | const getFilteredOptions = (
18 | allOptions: ReadonlyArray,
19 | value: string,
20 | ) => {
21 | // ignores slashes at the beginning, ignores whitespace
22 | const trimmedLowerCaseValue = value
23 | .replace(/^[/\\]+/, '')
24 | .trim()
25 | .toLocaleLowerCase();
26 |
27 | return allOptions
28 | .filter((i) => i.toLocaleLowerCase().startsWith(trimmedLowerCaseValue))
29 | .slice(0, AUTOCOMPLETE_OPTIONS_LENGTH);
30 | };
31 | export const DirectorySelector = ({
32 | initialValue,
33 | onChange,
34 | autocompleteItems,
35 | }: Props) => {
36 | const [value, setValue] = useState(initialValue);
37 | const [focusedOptionIdx, setFocusedOptionIdx] = useState(
38 | null,
39 | );
40 | const [showOptions, setShowOptions] = useState(false);
41 |
42 | useEffect(() => {
43 | setValue(initialValue);
44 | }, [initialValue]);
45 |
46 | const autocompleteOptions = getFilteredOptions(autocompleteItems, value);
47 |
48 | const handleChange = (e: Event | React.FormEvent) => {
49 | setValue((e.target as HTMLInputElement)?.value);
50 | };
51 |
52 | const handleFocus = () => {
53 | setFocusedOptionIdx(-1);
54 | setShowOptions(true);
55 | };
56 |
57 | const handleKeyDown = (e: React.KeyboardEvent) => {
58 | const maxLength = autocompleteOptions.length;
59 |
60 | if (e.key === 'Esc') {
61 | setFocusedOptionIdx(0);
62 | setShowOptions(false);
63 | }
64 |
65 | if (e.key === 'Enter') {
66 | setShowOptions(false);
67 |
68 | if (focusedOptionIdx === null) {
69 | return;
70 | }
71 |
72 | const nextValue = autocompleteOptions[focusedOptionIdx] ?? '';
73 |
74 | onChange(nextValue);
75 | setValue(nextValue);
76 | }
77 |
78 | if (e.key === 'ArrowUp') {
79 | const nextValue =
80 | focusedOptionIdx === null
81 | ? maxLength
82 | : (focusedOptionIdx - 1 + maxLength) % maxLength;
83 | setFocusedOptionIdx(nextValue);
84 | e.stopPropagation();
85 | e.preventDefault();
86 | }
87 |
88 | if (e.key === 'ArrowDown') {
89 | const nextValue =
90 | focusedOptionIdx === null
91 | ? 0
92 | : (focusedOptionIdx + 1) % maxLength;
93 |
94 | setFocusedOptionIdx(nextValue);
95 | e.stopPropagation();
96 | e.preventDefault();
97 | }
98 |
99 | if (e.key === 'Tab') {
100 | const nextValue =
101 | focusedOptionIdx === null
102 | ? 0
103 | : (focusedOptionIdx + 1) % maxLength;
104 | setFocusedOptionIdx(nextValue);
105 | e.stopPropagation();
106 | e.preventDefault();
107 | }
108 | };
109 |
110 | useLayoutEffect(() => {
111 | document.getElementById(`option_${focusedOptionIdx}`)?.focus();
112 | }, [focusedOptionIdx]);
113 |
114 | return (
115 |
123 |
127 |
134 | Target path
135 |
136 |
137 | {showOptions &&
138 | autocompleteOptions.map((item, i) => (
139 | {
144 | setShowOptions(false);
145 | setValue(item);
146 | onChange(item);
147 | }}
148 | >
149 | {item}
150 |
151 | ))}
152 |
153 |
154 |
155 | );
156 | };
157 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/components/style.module.css:
--------------------------------------------------------------------------------
1 | .textField {
2 | flex-grow: 1;
3 | }
4 |
5 | .textField::part(control) {
6 | font-size: 12px;
7 | opacity: 0.75;
8 | }
9 |
10 | .option {
11 | min-height: 20px;
12 | width: 100%;
13 | display: inline-block;
14 | line-height: 20px;
15 | }
16 |
17 | .autocompleteItems {
18 | background-color: var(--vscode-editor-background);
19 | padding: 4px;
20 | max-height: 250px;
21 | overflow-y: auto;
22 | }
23 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/style.module.css:
--------------------------------------------------------------------------------
1 | .privateCodemodWelcomeMessage {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | padding: 0 20px 1em;
6 | margin-top: 13px;
7 | }
8 |
9 | .privateCodemodWelcomeMessage p {
10 | line-height: 22px;
11 | text-align: center;
12 | }
13 |
14 | .privateCodemodWelcomeMessage p a {
15 | text-decoration: none;
16 | }
17 |
--------------------------------------------------------------------------------
/intuita-webview/src/codemodList/useProgressBar.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { CodemodHash, WebviewMessage } from '../shared/types';
3 |
4 | export type Progress = Readonly<{
5 | codemodHash: CodemodHash;
6 | progressKind: 'finite' | 'infinite';
7 | totalFileNumber: number;
8 | processedFileNumber: number;
9 | }>;
10 |
11 | export const useProgressBar = (): Progress | null => {
12 | const [codemodExecutionProgress, setCodemodExecutionProgress] =
13 | useState