Merge remote-tracking branch 'upstream/master' into spacesailor24/web3js-v4-upgrade

pull/5370/head
Oleksii Kosynskyi 1 year ago
commit 85ec60d27a
  1. 4
      .husky/pre-commit
  2. 3
      .lintstagedrc.json
  3. 13
      .prettierignore
  4. 14
      .prettierrc.json
  5. 17
      README.md
  6. 2
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  7. 6
      apps/remix-ide-e2e/src/tests/solidityImport.test.ts
  8. 2
      apps/remix-ide-e2e/src/tests/staticAnalysis.test.ts
  9. 3
      apps/remix-ide/src/app/editor/editor.js
  10. 63
      apps/remix-ide/src/app/plugins/solidity-umlgen.tsx
  11. 8
      apps/remix-ide/src/app/tabs/locales/en/home.json
  12. 8
      apps/remix-ide/src/app/tabs/locales/es/home.json
  13. 8
      apps/remix-ide/src/app/tabs/locales/fr/home.json
  14. 6
      apps/remix-ide/src/app/tabs/locales/zh/home.json
  15. 2
      apps/remix-ide/src/app/tabs/search.tsx
  16. 41
      apps/remix-ide/src/app/tabs/theme-module.js
  17. 4
      apps/remix-ide/src/app/udapp/run-tab.js
  18. BIN
      apps/remix-ide/src/assets/img/cookbook.webp
  19. 4
      libs/remix-debug/src/trace/traceCache.ts
  20. 4
      libs/remix-lib/src/execution/txRunnerWeb3.ts
  21. 8
      libs/remix-lib/src/util.ts
  22. 7
      libs/remix-lib/test/util.ts
  23. 162
      libs/remix-ui/editor/src/lib/providers/codeActionProvider.ts
  24. 52
      libs/remix-ui/editor/src/lib/providers/quickfixes.ts
  25. 7
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  26. 186
      libs/remix-ui/editor/src/lib/syntaxes/circom.ts
  27. 3
      libs/remix-ui/helper/src/lib/remix-ui-helper.ts
  28. 2
      libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx
  29. 4
      libs/remix-ui/run-tab/src/lib/actions/deploy.ts
  30. 5
      libs/remix-ui/solidity-uml-gen/src/types/index.ts
  31. 19
      libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
  32. 2
      libs/remix-ui/terminal/src/lib/components/RenderCall.tsx
  33. 2
      libs/remix-ui/terminal/src/lib/components/RenderKnownTransactions.tsx
  34. 2
      libs/remix-ui/terminal/src/lib/components/RenderUnknownTransactions.tsx
  35. 2
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  36. 517
      libs/remix-ui/workspace/src/lib/reducers/workspace.ts
  37. 4
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  38. 10
      package.json
  39. 260
      yarn.lock

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn lint-staged

@ -0,0 +1,3 @@
{
"*.{tsx,ts,js,jsx,mjs,cjs}": ["prettier --write","eslint --fix"]
}

@ -0,0 +1,13 @@
**/.yarn/*
# Ignore node_modules
./node_modules
# Ignore e2e files
./apps/remix-ide-e2e/*
# Ignore build artefacts
./dist
# Ignore all json files
**/*.json

@ -0,0 +1,14 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"quoteProps": "consistent",
"jsxSingleQuote": false,
"bracketSpacing": false,
"trailingComma": "none",
"jsxBracketSameLine": false,
"arrowParens": "always",
"singleAttributePerLine": false,
"ignorePath": ".prettierignore"
}

@ -63,14 +63,13 @@ yarn global add nx
```bash
git clone https://github.com/ethereum/remix-project.git
```
* Build `remix-project`:
```bash
cd remix-project
yarn install
yarn run build:libs // Build remix libs
nx build
nx serve
```
* Build and Run `remix-project`:
1. Move to project directory: `cd remix-project`
2. Install dependencies: `yarn install` or simply run `yarn`
3. Build Remix libraries: `yarn run build:libs`
4. Build Remix project: `yarn build`
5. Build and run project server: `yarn serve`. Optionally, run `yarn serve:hot` to enable hot module reload for frontend updates.
Open `http://127.0.0.1:8080` in your browser to load Remix IDE locally.
@ -151,7 +150,7 @@ To run the Selenium tests via Nightwatch:
- Install Selenium for the first time: `yarn run selenium-install`
- Run a selenium server: `yarn run selenium`
- Build & Serve Remix: `nx serve`
- Build & Serve Remix: `yarn serve`
- Run all the end-to-end tests:
for Firefox: `yarn run nightwatch_local_firefox`, or

@ -104,7 +104,7 @@ module.exports = {
})
.addFile('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'])
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.0
.setSolidityCompilerVersion('soljson-v0.8.20+commit.a1b79de6.js') // open-zeppelin moved to pragma ^0.8.20
.testContracts('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'], ['ERC20', 'test11'])
},
'Static Analysis run with remixd #group3': '' + function (browser) {

@ -38,7 +38,7 @@ module.exports = {
'Test GitHub Import - from master branch #group1': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.19 (master branch)
.setSolidityCompilerVersion('soljson-v0.8.20+commit.a1b79de6.js') // open-zeppelin moved to pragma ^0.8.20 (master branch)
.addFile('Untitled4.sol', sources[3]['Untitled4.sol'])
.clickLaunchIcon('filePanel')
.verifyContracts(['test7', 'ERC20'], { wait: 10000 })
@ -54,7 +54,7 @@ module.exports = {
'Test GitHub Import - no branch specified #group2': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.19 (master branch)
.setSolidityCompilerVersion('soljson-v0.8.20+commit.a1b79de6.js') // open-zeppelin moved to pragma ^0.8.20 (master branch)
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled6.sol', sources[5]['Untitled6.sol'])
@ -64,7 +64,7 @@ module.exports = {
'Test GitHub Import - raw URL #group4': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.setSolidityCompilerVersion('soljson-v0.8.20+commit.a1b79de6.js') // open-zeppelin moved to pragma ^0.8.20 (master branch)
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled7.sol', sources[6]['Untitled7.sol'])

@ -54,7 +54,7 @@ module.exports = {
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.click('*[data-rb-event-key="remix"]')
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount', '382')
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount', '386')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.assert.containsText('span#ssaRemixtab > *[data-id="RemixStaticAnalysisErrorCount', '1')

@ -51,7 +51,8 @@ class Editor extends Plugin {
rs: 'rust',
cairo: 'cairo',
ts: 'typescript',
move: 'move'
move: 'move',
circom: 'circom'
}
this.activated = false

@ -24,33 +24,6 @@ const profile = {
events: [],
}
const themeCollection = [
{ themeName: 'HackerOwl', backgroundColor: '#011628', textColor: '#babbcc',
shapeColor: '#8694a1',fillColor: '#011C32'},
{ themeName: 'Cerulean', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8f9fa'},
{ themeName: 'Cyborg', backgroundColor: '#060606', textColor: '#adafae',
shapeColor: '#adafae', fillColor: '#222222'},
{ themeName: 'Dark', backgroundColor: '#222336', textColor: '#babbcc',
shapeColor: '#babbcc',fillColor: '#2a2c3f'},
{ themeName: 'Flatly', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#7b8a8b',fillColor: '#ffffff'},
{ themeName: 'Black', backgroundColor: '#1a1a1a', textColor: '#babbcc',
shapeColor: '#b5b4bc',fillColor: '#1f2020'},
{ themeName: 'Light', backgroundColor: '#eef1f6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#ffffff'},
{ themeName: 'Midcentury', backgroundColor: '#DBE2E0', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#eeede9'},
{ themeName: 'Spacelab', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#333333', fillColor: '#eeeeee'},
{ themeName: 'Candy', backgroundColor: '#d5efff', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#fbe7f8' },
{ themeName: 'Violet', backgroundColor: '#f1eef6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#f8fafe' },
{ themeName: 'Unicorn', backgroundColor: '#f1eef6', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8fafe' },
]
/**
* add context menu which will offer download as pdf and download png.
* add menu under the first download button to download
@ -81,8 +54,8 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
this.currentlySelectedTheme = ''
this.themeName = ''
this.themeCollection = themeCollection
this.activeTheme = themeCollection.find(t => t.themeName === 'Dark')
this.activeTheme = {} as ThemeSummary
this.appManager = appManager
this.element = document.createElement('div')
this.element.setAttribute('id', 'sol-uml-gen')
@ -106,7 +79,7 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
const ast = result.length > 1 ? parser.parse(result) : parser.parse(source.sources[file].content)
this.umlClasses = convertAST2UmlClasses(ast, this.currentFile)
let umlDot = ''
this.activeTheme = themeCollection.find(theme => theme.themeName === currentTheme.name)
this.activeTheme = await this.call('theme', 'currentTheme')
umlDot = convertUmlClasses2Dot(this.umlClasses, false, { backColor: this.activeTheme.backgroundColor, textColor: this.activeTheme.textColor, shapeColor: this.activeTheme.shapeColor, fillColor: this.activeTheme.fillColor })
const payload = vizRenderStringSync(umlDot)
this.updatedSvg = payload
@ -127,35 +100,15 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
private handleThemeChange() {
this.on('theme', 'themeChanged', async (theme) => {
this.currentlySelectedTheme = theme.quality
const themeQuality: ThemeQualityType = await this.call('theme', 'currentTheme')
themeCollection.forEach((theme) => {
if (theme.themeName === themeQuality.name) {
this.themeDark = theme.backgroundColor
this.activeTheme = theme
const umlDot = convertUmlClasses2Dot(this.umlClasses, false, { backColor: this.activeTheme.backgroundColor, textColor: this.activeTheme.textColor, shapeColor: this.activeTheme.shapeColor, fillColor: this.activeTheme.fillColor })
this.updatedSvg = vizRenderStringSync(umlDot)
this.renderComponent()
}
})
this.activeTheme = theme
this.themeDark = theme.backgroundColor
const umlDot = convertUmlClasses2Dot(this.umlClasses, false, { backColor: this.activeTheme.backgroundColor, textColor: this.activeTheme.textColor, shapeColor: this.activeTheme.shapeColor, fillColor: this.activeTheme.fillColor })
this.updatedSvg = vizRenderStringSync(umlDot)
this.renderComponent()
await this.call('tabs', 'focus', 'solidityumlgen')
})
}
async mangleSvgPayload(svgPayload: string) : Promise<string> {
const parser = new DOMParser()
const themeQuality: ThemeQualityType = await this.call('theme', 'currentTheme')
const parsedDocument = parser.parseFromString(svgPayload, 'image/svg+xml')
const element = parsedDocument.getElementsByTagName('svg')
themeCollection.forEach((theme) => {
if (theme.themeName === themeQuality.name) {
parsedDocument.documentElement.setAttribute('style', `background-color: var(${this.getThemeCssVariables('--body-bg')})`)
element[0].setAttribute('fill', theme.backgroundColor)
}
})
const stringifiedSvg = new XMLSerializer().serializeToString(parsedDocument)
return stringifiedSvg
}
onDeactivation(): void {
this.off('solidity', 'compilationFinished')
}

@ -6,9 +6,9 @@
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.jumpIntoWeb3": "WE NEED YOUR HELP",
"home.jumpIntoWeb3More": "Go to survey",
"home.jumpIntoWeb3Text": "Remixers... Have a spare moment? Please help us improve your Remix experience with this one-minute survey.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
@ -18,7 +18,7 @@
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test and analyse smart contract.",
"home.solidityPluginDesc": "Compile, test, and analyze smart contracts.",
"home.cookbookDesc": "Find smart contracts, solidity libraries, and discover protocols.",
"home.codeAnalyizerPluginDesc": "Analyze your code using Remix, Solhint and Slither.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",

@ -6,9 +6,9 @@
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.jumpIntoWeb3": "WE NEED YOUR HELP",
"home.jumpIntoWeb3More": "Go to survey",
"home.jumpIntoWeb3Text": "Remixers... Have a spare moment? Please help us improve your Remix experience with this one-minute survey.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
@ -18,7 +18,7 @@
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test and analyse smart contract.",
"home.solidityPluginDesc": "Compile, test, and analyze smart contracts.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",
"home.solhintPluginDesc": "Solhint is an open source project for linting Solidity code.",
"home.sourcifyPluginDesc": "Solidity contract and metadata verification service.",

@ -6,9 +6,9 @@
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.jumpIntoWeb3": "WE NEED YOUR HELP",
"home.jumpIntoWeb3More": "Go to survey",
"home.jumpIntoWeb3Text": "Remixers... Have a spare moment? Please help us improve your Remix experience with this one-minute survey.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
@ -18,7 +18,7 @@
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test and analyse smart contract.",
"home.solidityPluginDesc": "Compile, test, and analyze smart contracts.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",
"home.solhintPluginDesc": "Solhint is an open source project for linting Solidity code.",
"home.sourcifyPluginDesc": "Solidity contract and metadata verification service.",

@ -6,9 +6,9 @@
"home.learnMore": "了解更多",
"home.here": "这里",
"home.featured": "精选",
"home.jumpIntoWeb3": "迎接 WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix 项目是一个丰富的工具集,任何知识水平的用户都可以在这上面进行全周期的合约开发,并且可作为以太坊教学和实验的学习实验室。",
"home.jumpIntoWeb3": "WE NEED YOUR HELP",
"home.jumpIntoWeb3More": "Go to survey",
"home.jumpIntoWeb3Text": "Remixers... Have a spare moment? Please help us improve your Remix experience with this one-minute survey.",
"home.remixYouTube": "观看学习",
"home.remixYouTubeText1": "来自 Remix 团队的视频小贴士",
"home.remixYouTubeMore": "观看",

@ -11,7 +11,7 @@ const profile = {
description: 'Find and replace in file explorer',
kind: '',
location: 'sidePanel',
documentation: '',
documentation: 'https://remix-ide.readthedocs.io/en/latest/search_in_fe.html',
version: packageJson.version,
maintainedBy: 'Remix'
}

@ -5,20 +5,33 @@ import * as packageJson from '../../../../../package.json'
import Registry from '../state/registry'
const _paq = window._paq = window._paq || []
//sol2uml dot files cannot work with css variables so hex values for colors are used
const themes = [
{ name: 'Dark', quality: 'dark', url: 'assets/css/themes/remix-dark_tvx1s2.css' },
{ name: 'Light', quality: 'light', url: 'assets/css/themes/remix-light_powaqg.css' },
{ name: 'Violet', quality: 'light', url: 'assets/css/themes/remix-violet.css' },
{ name: 'Unicorn', quality: 'light', url: 'assets/css/themes/remix-unicorn.css' },
{ name: 'Midcentury', quality: 'light', url: 'assets/css/themes/remix-midcentury_hrzph3.css' },
{ name: 'Black', quality: 'dark', url: 'assets/css/themes/remix-black_undtds.css' },
{ name: 'Candy', quality: 'light', url: 'assets/css/themes/remix-candy_ikhg4m.css' },
{ name: 'HackerOwl', quality: 'dark', url: 'assets/css/themes/remix-hacker_owl.css' },
{ name: 'Dark', quality: 'dark', url: 'assets/css/themes/remix-dark_tvx1s2.css', backgroundColor: '#222336', textColor: '#babbcc',
shapeColor: '#babbcc',fillColor: '#2a2c3f' },
{ name: 'Light', quality: 'light', url: 'assets/css/themes/remix-light_powaqg.css', backgroundColor: '#eef1f6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#ffffff' },
{ name: 'Violet', quality: 'light', url: 'assets/css/themes/remix-violet.css', backgroundColor: '#f1eef6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#f8fafe' },
{ name: 'Unicorn', quality: 'light', url: 'assets/css/themes/remix-unicorn.css', backgroundColor: '#f1eef6', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8fafe' },
{ name: 'Midcentury', quality: 'light', url: 'assets/css/themes/remix-midcentury_hrzph3.css', backgroundColor: '#DBE2E0', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#eeede9' },
{ name: 'Black', quality: 'dark', url: 'assets/css/themes/remix-black_undtds.css', backgroundColor: '#1a1a1a', textColor: '#babbcc',
shapeColor: '#b5b4bc',fillColor: '#1f2020' },
{ name: 'Candy', quality: 'light', url: 'assets/css/themes/remix-candy_ikhg4m.css', backgroundColor: '#d5efff', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#fbe7f8' },
{ name: 'HackerOwl', quality: 'dark', url: 'assets/css/themes/remix-hacker_owl.css', backgroundColor: '#011628', textColor: '#babbcc',
shapeColor: '#8694a1',fillColor: '#011C32' },
{ name: 'Cerulean', quality: 'light', url: 'assets/css/themes/bootstrap-cerulean.min.css' },
{ name: 'Flatly', quality: 'light', url: 'assets/css/themes/bootstrap-flatly.min.css' },
{ name: 'Spacelab', quality: 'light', url: 'assets/css/themes/bootstrap-spacelab.min.css' },
{ name: 'Cyborg', quality: 'dark', url: 'assets/css/themes/bootstrap-cyborg.min.css' }
{ name: 'Cerulean', quality: 'light', url: 'assets/css/themes/bootstrap-cerulean.min.css', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8f9fa' },
{ name: 'Flatly', quality: 'light', url: 'assets/css/themes/bootstrap-flatly.min.css', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#7b8a8b',fillColor: '#ffffff' },
{ name: 'Spacelab', quality: 'light', url: 'assets/css/themes/bootstrap-spacelab.min.css', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#333333', fillColor: '#eeeeee' },
{ name: 'Cyborg', quality: 'dark', url: 'assets/css/themes/bootstrap-cyborg.min.css', backgroundColor: '#060606', textColor: '#adafae',
shapeColor: '#adafae', fillColor: '#222222' }
]
const profile = {
@ -55,7 +68,7 @@ export class ThemeModule extends Plugin {
this.forced = !!queryTheme
}
/** Return the active theme
/** Return the active theme
* @return {{ name: string, quality: string, url: string }} - The active theme
*/
currentTheme () {
@ -93,7 +106,7 @@ export class ThemeModule extends Plugin {
* @param {string} [themeName] - The name of the theme
*/
switchTheme (themeName) {
themeName = themeName && themeName.toLocaleLowerCase()
themeName = themeName && themeName.toLocaleLowerCase()
if (themeName && !Object.keys(this.themes).includes(themeName)) {
throw new Error(`Theme ${themeName} doesn't exist`)
}

@ -182,8 +182,8 @@ export class RunTab extends ViewPlugin {
return this.call('fileManager', 'readFile', fileName)
}
resolveContractAndAddInstance (contractObject, address) {
const data = this.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
async resolveContractAndAddInstance (contractObject, address) {
const data = await this.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
this.compilersArtefacts.addResolvedContract(addressToString(address), data)
this.addInstance(address, contractObject.abi, contractObject.name)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -102,11 +102,13 @@ export class TraceCache {
}
pushContractCreationFromMemory (index, token, trace, lastMemoryChange) {
const toHexString = arr => Array.from(arr, i => (i as any).toString(16).padStart(2, "0")).join("")
const memory = trace[lastMemoryChange].memory
const stack = trace[index].stack
const offset = 2 * parseInt(toHexPaddedString(stack[stack.length - 2]), 16)
const size = 2 * parseInt(toHexPaddedString(stack[stack.length - 3]), 16)
this.contractCreation[token] = '0x' + memory.join('').substr(offset, size)
const memoryHex = toHexString(memory)
this.contractCreation[token] = '0x' + memoryHex.substr(offset, size)
}
pushContractCreation (token, code) {

@ -106,13 +106,13 @@ export class TxRunnerWeb3 {
console.log(errNetWork)
return
}
const txCopy = { ...tx, type: undefined, maxFeePerGas: undefined, gasPrice: undefined }
const txCopy = { ...tx, type: undefined, maxFeePerGas: undefined, gasPrice: undefined }
if (network && network.lastBlock) {
if (network.lastBlock.baseFeePerGas) {
// the sending stack (web3.js / metamask need to have the type defined)
// this is to avoid the following issue: https://github.com/MetaMask/metamask-extension/issues/11824
txCopy.type = '0x2'
txCopy.maxFeePerGas = Math.ceil(network.lastBlock.baseFeePerGas + network.lastBlock.baseFeePerGas / 2)
txCopy.maxFeePerGas = Math.ceil(network.lastBlock.baseFeePerGas + network.lastBlock.baseFeePerGas / 3)
} else {
txCopy.type = '0x1'
txCopy.gasPrice = network.lastBlock.baseFeePerGas

@ -203,7 +203,9 @@ export function inputParametersExtraction () {
}
export function extractcborMetadata (value) {
return value.replace(cborEncodedValueExtraction(), '')
const cbor = value.match(cborEncodedValueExtraction())
if (cbor && cbor[0]) value = value.replace(cbor[0], '')
return value
}
export function extractSwarmHash (value) {
@ -214,7 +216,9 @@ export function extractSwarmHash (value) {
}
export function extractinputParameters (value) {
return value.replace(inputParametersExtraction(), '')
const inputsParam = getinputParameters(value)
if (inputsParam) value = value.replace(inputsParam, '')
return value
}
export function getinputParameters (value) {

File diff suppressed because one or more lines are too long

@ -1,7 +1,7 @@
import { Monaco } from "@monaco-editor/react"
import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
import { default as fixes } from "./quickfixes"
import { default as fixesList } from "./quickfixes"
export class RemixCodeActionProvider implements monaco.languages.CodeActionProvider {
props: EditorUIProps
@ -12,37 +12,143 @@ export class RemixCodeActionProvider implements monaco.languages.CodeActionProvi
}
async provideCodeActions (
model /**ITextModel*/,
range /**Range*/,
context /**CodeActionContext*/,
token /**CancellationToken*/
) {
const actions = context.markers.map(error => {
const errStrings = Object.keys(fixes)
const errStr = errStrings.find(es => error.message.includes(es))
const fix = fixes[errStr]
return {
title: fix.title,
diagnostics: [error],
kind: "quickfix",
edit: {
edits: [
{
resource: model.uri,
edit: {
range: fix.range || error,
text: fix.message
}
}
]
},
isPreferred: true
model: monaco.editor.ITextModel,
range: monaco.Range,
context: monaco.languages.CodeActionContext,
token: monaco.CancellationToken
): Promise<monaco.languages.CodeActionList> {
const actions: monaco.languages.CodeAction[] = []
for (const error of context.markers) {
let fixes: Record<string, any>[], msg: string
let isOldAST: boolean = false
const errStrings: string[] = Object.keys(fixesList)
const errStr:string = errStrings.find(es => error.message.includes(es))
if (errStr) {
fixes = fixesList[errStr]
const cursorPosition: number = this.props.editorAPI.getHoverPosition({lineNumber: error.startLineNumber, column: error.startColumn})
const nodeAtPosition = await this.props.plugin.call('codeParser', 'definitionAtPosition', cursorPosition)
// Check if a function is hovered
if (nodeAtPosition && nodeAtPosition.nodeType === "FunctionDefinition") {
// Identify type of AST node
if (nodeAtPosition.parameters && !Array.isArray(nodeAtPosition.parameters) && Array.isArray(nodeAtPosition.parameters.parameters))
isOldAST = true
const paramNodes = isOldAST ? nodeAtPosition.parameters.parameters : nodeAtPosition.parameters
for (const fix of fixes) {
msg = paramNodes.length
? await this.fixForMethodWithParams(model, paramNodes, fix, error, isOldAST)
: await this.fixForMethodWithoutParams(model, nodeAtPosition, fix, error, isOldAST)
this.addQuickFix(actions, error, model.uri, {title: fix.title, range: fix.range, text: msg})
}
} else {
for (const fix of fixes) {
if (fix && nodeAtPosition && fix.nodeType !== nodeAtPosition.nodeType) continue
else this.addQuickFix(actions, error, model.uri, {title: fix.title, range: fix.range || error, text: fix.message})
}
}
}
})
}
return {
actions: actions,
dispose: () => {}
}
}
/**
* Add quick fix to code actions
* @param actions code actions array
* @param error editor error object
* @param uri model URI
* @param fix details of quick fix to apply
*/
addQuickFix(actions: monaco.languages.CodeAction[], error: monaco.editor.IMarkerData, uri: monaco.Uri, fix: Record<string, any>) {
const {title, range, text} = fix
actions.push({
title,
diagnostics: [error],
kind: "quickfix",
edit: {
edits: [
{
resource: uri,
edit: { range, text }
}
]
},
isPreferred: true
})
}
/**
* Returns message for various quick fixes related to a method with parameters
* @param model Model
* @param paramNodes function parameters AST nodes
* @param fix details of quick fix to apply
* @param error editor error object
* @param isOldAST true, if AST node contains legacy fields
* @returns message to be placed as quick fix
*/
async fixForMethodWithParams(model: monaco.editor.ITextModel, paramNodes: Record<string, any>[], fix: Record<string, any>, error: monaco.editor.IMarkerData, isOldAST: boolean): Promise<string> {
let lastParamEndLoc: Record<string, any>, fixLineNumber: number, msg: string
// Get last function parameter node
const lastParamNode: Record<string, any> = paramNodes[paramNodes.length - 1]
if (isOldAST) {
const location: Record<string, any> = await this.props.plugin.call('codeParser', 'getLineColumnOfNode', lastParamNode)
// Get end location of last function parameter, it returns end column of parameter name
lastParamEndLoc = location.end
fixLineNumber = lastParamEndLoc.line + 1
} else {
// Get end location of last function parameter, it returns start column of parameter name
lastParamEndLoc = lastParamNode.loc.end
fixLineNumber = lastParamEndLoc.line
}
const lineContent: string = model.getLineContent(fixLineNumber)
if (fix.id === 5 && lineContent.includes(' view '))
msg = lineContent.replace('view', 'pure')
else if (isOldAST)
msg = lineContent.substring(0, lastParamEndLoc.column + 2) + fix.message + lineContent.substring(lastParamEndLoc.column + 1, lineContent.length)
else
msg = lineContent.substring(0, lastParamEndLoc.column + lastParamNode.name.length + 2) + fix.message + lineContent.substring(lastParamEndLoc.column + lastParamNode.name.length + 1, lineContent.length)
fix.range = {
startLineNumber: fixLineNumber,
endLineNumber: fixLineNumber,
startColumn: 0,
endColumn: error.startColumn + msg.length
}
return msg
}
/**
* Returns message for various quick fixes related to a method without parameters
* @param model Model
* @param paramNodes function parameters AST nodes
* @param fix details of quick fix to apply
* @param error editor error object
* @param isOldAST true, if AST node contains legacy fields
* @returns message to be placed as quick fix
*/
async fixForMethodWithoutParams(model: monaco.editor.ITextModel, nodeAtPosition: Record<string, any>, fix: Record<string, any>, error: monaco.editor.IMarkerData, isOldAST: boolean): Promise<string> {
let fixLineNumber: number, msg: string
if (isOldAST) {
const location: Record<string, any> = await this.props.plugin.call('codeParser', 'getLineColumnOfNode', nodeAtPosition)
fixLineNumber = location.start.line + 1
} else fixLineNumber = nodeAtPosition.loc.start.line
const lineContent: string = model.getLineContent(fixLineNumber)
const i: number = lineContent.indexOf('()')
if (fix.id === 5 && lineContent.includes(' view ')) {
msg = lineContent.replace('view', 'pure')
} else
msg = lineContent.substring(0, i + 3) + fix.message + lineContent.substring(i + 3, lineContent.length)
fix.range = {
startLineNumber: fixLineNumber,
endLineNumber: fixLineNumber,
startColumn: 0,
endColumn: error.startColumn + msg.length
}
return msg
}
}

@ -1,16 +1,58 @@
export default {
"Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.": {
"Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.": [{
"id": 1.1,
"nodeType": "SourceUnit",
"title": "Add open-source license",
"message": "// SPDX-License-Identifier: GPL-3.0"
},
"Warning: Source file does not specify required compiler version! Consider adding" : {
"title": "Add pragma line",
},{
"id": 1.2,
"nodeType": "SourceUnit",
"title": "Add non-open-source license",
"message": "// SPDX-License-Identifier: UNLICENSED"
}],
"Warning: Source file does not specify required compiler version! Consider adding" : [{
"id": 2,
"title": "Add Solidity pragma",
"message": "pragma solidity ^0.*.*;",
"nodeType": "PragmaDirective",
"range": {
startLineNumber: 2,
endLineNumber: 2,
startColumn: 1,
endColumn: 1
}
}
}],
"SyntaxError: No visibility specified. Did you intend to add \"public\"": [{
"id": 3.1,
"title": "Add visibility 'public'",
"message": "public ",
"nodeType": "FunctionDefinition"
},{
"id": 3.2,
"title": "Add visibility 'private'",
"message": "private ",
"nodeType": "FunctionDefinition"
},{
"id": 3.3,
"title": "Add visibility 'internal'",
"message": "internal ",
"nodeType": "FunctionDefinition"
},{
"id": 3.4,
"title": "Add visibility 'external'",
"message": "external ",
"nodeType": "FunctionDefinition"
}],
"Warning: Function state mutability can be restricted to view": [{
"id": 4,
"title": "Add mutability 'view'",
"message": "view ",
"nodeType": "FunctionDefinition"
}],
"Warning: Function state mutability can be restricted to pure": [{
"id": 5,
"title": "Add mutability 'pure'",
"message": "pure ",
"nodeType": "FunctionDefinition"
}]
}

@ -17,6 +17,7 @@ import { RemixHighLightProvider } from './providers/highlightProvider'
import { RemixDefinitionProvider } from './providers/definitionProvider'
import { RemixCodeActionProvider } from './providers/codeActionProvider'
import './remix-ui-editor.css'
import { circomLanguageConfig, circomTokensProvider } from './syntaxes/circom'
enum MarkerSeverity {
@ -322,6 +323,8 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-zokrates')
} else if (file.language === 'move') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-move')
} else if (file.language === 'circom') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-circom')
}
}, [props.currentFile])
@ -731,6 +734,7 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.register({ id: 'remix-cairo' })
monacoRef.current.languages.register({ id: 'remix-zokrates' })
monacoRef.current.languages.register({ id: 'remix-move' })
monacoRef.current.languages.register({ id: 'remix-circom' })
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', solidityTokensProvider as any)
@ -745,6 +749,9 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.setMonarchTokensProvider('remix-move', moveTokenProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-move', moveLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider('remix-circom', circomTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-circom', circomLanguageConfig(monacoRef.current) as any)
monacoRef.current.languages.registerDefinitionProvider('remix-solidity', new RemixDefinitionProvider(props, monaco))
monacoRef.current.languages.registerDocumentHighlightProvider('remix-solidity', new RemixHighLightProvider(props, monaco))
monacoRef.current.languages.registerReferenceProvider('remix-solidity', new RemixReferenceProvider(props, monaco))

@ -0,0 +1,186 @@
/* eslint-disable */
export const circomLanguageConfig = (monaco) => ({
wordPattern:
/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
comments: {
lineComment: "//",
blockComment: ["/*", "*/"],
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
],
onEnterRules: [
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: {
indentAction: monaco.languages.IndentAction.IndentOutdent,
appendText: " * ",
},
},
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: {
indentAction: monaco.languages.IndentAction.None,
appendText: " * ",
},
},
{
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: {
indentAction: monaco.languages.IndentAction.None,
appendText: "* ",
},
},
{
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: {
indentAction: monaco.languages.IndentAction.None,
removeText: 1,
},
},
],
autoClosingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: '"', close: '"', notIn: ["string"] },
{ open: "'", close: "'", notIn: ["string", "comment"] },
{ open: "`", close: "`", notIn: ["string", "comment"] },
{ open: "/**", close: " */", notIn: ["string"] },
],
folding: {
markers: {
start: new RegExp("^\\s*//\\s*#?region\\b"),
end: new RegExp("^\\s*//\\s*#?endregion\\b"),
},
},
})
export const circomTokensProvider = {
defaultToken: "",
tokenPostfix: ".circom",
keywords: [
"signal",
"input",
"output",
"public",
"template",
"component",
"parallel",
"custom",
"var",
"function",
"return",
"if",
"else",
"for",
"while",
"do",
"log",
"assert",
"include",
"pragma",
],
typeKeywords: ["input", "output", "public"],
operators: [
"!",
"~",
"-",
"||",
"&&",
"==",
"!=",
"<",
">",
"<=",
">=",
"|",
"&",
"<<",
">>",
"+",
"-",
"*",
"/",
"\\",
"%",
"**",
"^",
"=",
"<--",
"<==",
],
escapes:
/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
tokenizer: {
root: [
[
/[a-z_$][\w$]*/,
{
cases: {
"@typeKeywords": "keyword",
"@keywords": "keyword",
"@default": "identifier",
},
},
],
[/[A-Z][\w\$]*/, "type.identifier"],
{ include: "@whitespace" },
[/[{}()\[\]]/, "@brackets"],
[
/@\s*[a-zA-Z_\$][\w\$]*/,
{ token: "annotation", log: "annotation token: $0" },
],
[/\d*\.\d+([eE][\-+]?\d+)?/, "number.float"],
[/0[xX][0-9a-fA-F]+/, "number.hex"],
[/\d+/, "number"],
[/[;,.]/, "delimiter"],
[/"([^"\\]|\\.)*$/, "string.invalid"],
[/"/, { token: "string.quote", bracket: "@open", next: "@string" }],
[/'[^\\']'/, "string"],
[/(')(@escapes)(')/, ["string", "string.escape", "string"]],
[/'/, "string.invalid"],
],
comment: [
[/[^\/*]+/, "comment"],
[/\/\*/, "comment", "@push"],
["\\*/", "comment", "@pop"],
[/[\/*]/, "comment"],
],
string: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
whitespace: [
[/[ \t\r\n]+/, "white"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
],
},
}

@ -80,7 +80,8 @@ export const getPathIcon = (path: string) => {
? 'fak fa-lexon' : path.endsWith('ts')
? 'small fak fa-ts-logo' : path.endsWith('.tsc')
? 'fad fa-brackets-curly' : path.endsWith('.cairo')
? 'small fak fa-cairo' : 'far fa-file'
? 'small fak fa-cairo' : path.endsWith('.circom')
? 'fak fa-circom-plug1' : 'far fa-file'
}
export const isNumeric = (value) => {

@ -47,7 +47,7 @@ function HomeTabFeatured() {
className="remixui_home_text btn-sm btn-secondary mt-2 text-decoration-none mb-3"
onClick={() => _paq.push(['trackEvent', 'hometab', 'featuredSection', 'jumpIntoWeb3'])}
target="__blank"
href="https://remix-project.org"
href="https://us8.list-manage.com/survey?u=5a84beb6d688fe180c0da482a&id=1148d10f8c"
>
<FormattedMessage id='home.jumpIntoWeb3More'/>
</a>

@ -155,14 +155,14 @@ export const createInstance = async (
return terminalLogger(plugin, log)
}
const finalCb = (error, contractObject, address) => {
const finalCb = async (error, contractObject, address) => {
if (error) {
const log = logBuilder(error)
return terminalLogger(plugin, log)
}
addInstance(dispatch, { contractData: contractObject, address, name: contractObject.name })
const data = plugin.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
const data = await plugin.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
plugin.compilersArtefacts.addResolvedContract(addressToString(address), data)
if (plugin.REACT_API.ipfsChecked) {

@ -16,7 +16,6 @@ export interface ISolidityUmlGen extends ViewPlugin {
showUmlDiagram(path: string, svgPayload: string): void
updateComponent(state: any): JSX.Element
setDispatch(dispatch: React.Dispatch<any>): void
mangleSvgPayload(svgPayload: string) : Promise<string>
generateCustomAction(action: customAction): Promise<void>
flattenContract (source: any, filePath: string, data: any): Promise<string>
hideSpinner(): void
@ -27,5 +26,5 @@ export interface ISolidityUmlGen extends ViewPlugin {
export type ThemeQualityType = { name: string, quality: 'light' | 'dark', url: string }
export type ThemeSummary = { themeName: string, backgroundColor: string, textColor?: string,
shapeColor?: string, fillColor?: string }
export type ThemeSummary = { name: string, quality: 'light' | 'dark', url: string, backgroundColor: string, textColor?: string,
shapeColor?: string, fillColor?: string }

@ -134,7 +134,24 @@ export const initListeningOnNetwork = (plugins, dispatch: React.Dispatch<any>) =
if (resolvedTransaction) {
let compiledContracts = null
if (plugins._deps.compilersArtefacts.__last) {
try {
if (tx.to) {
compiledContracts = await plugins._deps.compilersArtefacts.get(tx.to).getContracts()
}
} catch (error) {
console.log(error)
}
try {
const currentFile = plugins._deps.fileManager.getCurrentFile()
if (!compiledContracts && currentFile && currentFile.endsWith('.sol')) {
compiledContracts = await (await plugins._deps.compilersArtefacts.getCompilerAbstract(currentFile)).getContracts()
}
} catch (error) {
console.log(error)
}
if (!compiledContracts && plugins._deps.compilersArtefacts.__last) {
compiledContracts = await plugins._deps.compilersArtefacts.__last.getContracts()
}
await plugins.eventsDecoder.parseLogs(tx, resolvedTransaction.contractName, compiledContracts, async (error, logs) => {

@ -15,7 +15,7 @@ const RenderCall = ({ tx, resolvedData, logs, index, plugin, showTableHash, txDe
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', false, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}

@ -11,7 +11,7 @@ const RenderKnownTransactions = ({ tx, receipt, resolvedData, logs, index, plugi
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', false, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}

@ -8,7 +8,7 @@ const RenderUnKnownTransactions = ({ tx, receipt, index, plugin, showTableHash,
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in Remix VM mode.', 'Ok', false, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}

@ -371,7 +371,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
}
const modal = (title: string, message: string, okLabel: string, hide: boolean, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => {
setModalState(prevState => ({ ...prevState, message, okLabel, okFn, cancelLabel, cancelFn, hide }))
setModalState(prevState => ({ ...prevState, title, message, okLabel, okFn, cancelLabel, cancelFn, hide }))
}
const handleHideModal = () => {

@ -1,71 +1,71 @@
import { extractNameFromKey } from '@remix-ui/helper'
import { action, FileType } from '../types'
import {extractNameFromKey} from '@remix-ui/helper'
import {action, FileType} from '../types'
import * as _ from 'lodash'
import { fileDecoration } from '@remix-ui/file-decorators'
import { ROOT_PATH } from '../utils/constants'
import {fileDecoration} from '@remix-ui/file-decorators'
import {ROOT_PATH} from '../utils/constants'
interface Action {
type: string
payload: any
}
export interface BrowserState {
browser: {
currentWorkspace: string,
currentWorkspace: string
workspaces: {
name: string;
isGitRepo: boolean;
name: string
isGitRepo: boolean
branches?: {
remote: any;
name: string;
}[],
remote: any
name: string
}[]
currentBranch?: string
}[],
files: { [x: string]: Record<string, FileType> },
}[]
files: {[x: string]: Record<string, FileType>}
expandPath: string[]
isRequestingDirectory: boolean,
isSuccessfulDirectory: boolean,
isRequestingWorkspace: boolean,
isSuccessfulWorkspace: boolean,
isRequestingCloning: boolean,
isSuccessfulCloning: boolean,
error: string,
isRequestingDirectory: boolean
isSuccessfulDirectory: boolean
isRequestingWorkspace: boolean
isSuccessfulWorkspace: boolean
isRequestingCloning: boolean
isSuccessfulCloning: boolean
error: string
contextMenu: {
registeredMenuItems: action[],
removedMenuItems: action[],
registeredMenuItems: action[]
removedMenuItems: action[]
error: string
},
}
fileState: fileDecoration[]
},
}
localhost: {
sharedFolder: string,
files: { [x: string]: Record<string, FileType> },
expandPath: string[],
isRequestingDirectory: boolean,
isSuccessfulDirectory: boolean,
isRequestingLocalhost: boolean,
isSuccessfulLocalhost: boolean,
error: string,
sharedFolder: string
files: {[x: string]: Record<string, FileType>}
expandPath: string[]
isRequestingDirectory: boolean
isSuccessfulDirectory: boolean
isRequestingLocalhost: boolean
isSuccessfulLocalhost: boolean
error: string
contextMenu: {
registeredMenuItems: action[],
removedMenuItems: action[],
registeredMenuItems: action[]
removedMenuItems: action[]
error: string
},
}
fileState: []
},
mode: 'browser' | 'localhost',
}
mode: 'browser' | 'localhost'
notification: {
title: string,
message: string,
actionOk: () => void,
actionCancel: (() => void) | null,
labelOk: string,
title: string
message: string
actionOk: () => void
actionCancel: (() => void) | null
labelOk: string
labelCancel: string
},
readonly: boolean,
popup: string,
focusEdit: string,
focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[],
initializingFS: boolean,
gitConfig: { username: string, email: string, token: string },
}
readonly: boolean
popup: string
focusEdit: string
focusElement: {key: string; type: 'file' | 'folder' | 'gist'}[]
initializingFS: boolean
gitConfig: {username: string; email: string; token: string}
}
export const browserInitialState: BrowserState = {
@ -108,8 +108,8 @@ export const browserInitialState: BrowserState = {
notification: {
title: '',
message: '',
actionOk: () => { },
actionCancel: () => { },
actionOk: () => {},
actionCancel: () => {},
labelOk: '',
labelCancel: ''
},
@ -118,33 +118,47 @@ export const browserInitialState: BrowserState = {
focusEdit: '',
focusElement: [],
initializingFS: true,
gitConfig: { username: '', email: '', token: '' }
gitConfig: {username: '', email: '', token: ''}
}
export const browserReducer = (state = browserInitialState, action: Action) => {
switch (action.type) {
case 'SET_CURRENT_WORKSPACE': {
const payload = action.payload as { name: string; isGitRepo: boolean; branches?: { remote: any; name: string; }[], currentBranch?: string }
const workspaces = state.browser.workspaces.find(({ name }) => name === payload.name) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
const payload = action.payload as {
name: string
isGitRepo: boolean
branches?: {remote: any; name: string}[]
currentBranch?: string
}
const workspaces = state.browser.workspaces.find(
({name}) => name === payload.name
)
? state.browser.workspaces
: [...state.browser.workspaces, action.payload]
return {
...state,
browser: {
...state.browser,
currentWorkspace: payload.name,
workspaces: workspaces.filter(workspace => workspace)
workspaces: workspaces.filter((workspace) => workspace)
}
}
}
case 'SET_WORKSPACES': {
const payload = action.payload as { name: string; isGitRepo: boolean; branches?: { remote: any; name: string; }[], currentBranch?: string }[]
const payload = action.payload as {
name: string
isGitRepo: boolean
branches?: {remote: any; name: string}[]
currentBranch?: string
}[]
return {
...state,
browser: {
...state.browser,
workspaces: payload.filter(workspace => workspace)
workspaces: payload.filter((workspace) => workspace)
}
}
}
@ -177,20 +191,26 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'FETCH_DIRECTORY_SUCCESS': {
const payload = action.payload as { path: string, fileTree }
const payload = action.payload as {path: string; fileTree}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fetchDirectoryContent(state, payload) : state.browser.files,
files:
state.mode === 'browser'
? fetchDirectoryContent(state, payload)
: state.browser.files,
isRequestingDirectory: false,
isSuccessfulDirectory: true,
error: null
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fetchDirectoryContent(state, payload) : state.localhost.files,
files:
state.mode === 'localhost'
? fetchDirectoryContent(state, payload)
: state.localhost.files,
isRequestingDirectory: false,
isSuccessfulDirectory: true,
error: null
@ -235,20 +255,26 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'FETCH_WORKSPACE_DIRECTORY_SUCCESS': {
const payload = action.payload as { path: string, fileTree }
const payload = action.payload as {path: string; fileTree}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fetchWorkspaceDirectoryContent(state, payload) : state.browser.files,
files:
state.mode === 'browser'
? fetchWorkspaceDirectoryContent(state, payload)
: state.browser.files,
isRequestingWorkspace: false,
isSuccessfulWorkspace: true,
error: null
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fetchWorkspaceDirectoryContent(state, payload) : state.localhost.files,
files:
state.mode === 'localhost'
? fetchWorkspaceDirectoryContent(state, payload)
: state.localhost.files,
isRequestingWorkspace: false,
isSuccessfulWorkspace: true,
error: null,
@ -276,15 +302,25 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'DISPLAY_NOTIFICATION': {
const payload = action.payload as { title: string, message: string, actionOk: () => void, actionCancel: () => void, labelOk: string, labelCancel: string }
const payload = action.payload as {
title: string
message: string
actionOk: () => void
actionCancel: () => void
labelOk: string
labelCancel: string
}
return {
...state,
notification: {
title: payload.title,
message: payload.message,
actionOk: payload.actionOk || browserInitialState.notification.actionOk,
actionCancel: payload.actionCancel || browserInitialState.notification.actionCancel,
actionOk:
payload.actionOk || browserInitialState.notification.actionOk,
actionCancel:
payload.actionCancel ||
browserInitialState.notification.actionCancel,
labelOk: payload.labelOk,
labelCancel: payload.labelCancel
}
@ -305,31 +341,64 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fileAdded(state, payload) : state.browser.files,
expandPath: state.mode === 'browser' ? [...new Set([...state.browser.expandPath, payload])] : state.browser.expandPath
files:
state.mode === 'browser'
? fileAdded(state, payload)
: state.browser.files,
expandPath:
state.mode === 'browser'
? [...new Set([...state.browser.expandPath, payload])]
: state.browser.expandPath
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fileAdded(state, payload) : state.localhost.files,
expandPath: state.mode === 'localhost' ? [...new Set([...state.localhost.expandPath, payload])] : state.localhost.expandPath
files:
state.mode === 'localhost'
? fileAdded(state, payload)
: state.localhost.files,
expandPath:
state.mode === 'localhost'
? [...new Set([...state.localhost.expandPath, payload])]
: state.localhost.expandPath
}
}
}
case 'FOLDER_ADDED_SUCCESS': {
const payload = action.payload as { path: string, folderPath: string, fileTree }
const payload = action.payload as {
path: string
folderPath: string
fileTree
}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fetchDirectoryContent(state, payload) : state.browser.files,
expandPath: state.mode === 'browser' ? [...new Set([...state.browser.expandPath, payload.folderPath])] : state.browser.expandPath
files:
state.mode === 'browser'
? fetchDirectoryContent(state, payload)
: state.browser.files,
expandPath:
state.mode === 'browser'
? [...new Set([...state.browser.expandPath, payload.folderPath])]
: state.browser.expandPath
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fetchDirectoryContent(state, payload) : state.localhost.files,
expandPath: state.mode === 'localhost' ? [...new Set([...state.localhost.expandPath, payload.folderPath])] : state.localhost.expandPath
files:
state.mode === 'localhost'
? fetchDirectoryContent(state, payload)
: state.localhost.files,
expandPath:
state.mode === 'localhost'
? [
...new Set([
...state.localhost.expandPath,
payload.folderPath
])
]
: state.localhost.expandPath
}
}
}
@ -341,13 +410,25 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fileRemoved(state, payload) : state.browser.files,
expandPath: state.mode === 'browser' ? [...(state.browser.expandPath.filter(path => path !== payload))] : state.browser.expandPath
files:
state.mode === 'browser'
? fileRemoved(state, payload)
: state.browser.files,
expandPath:
state.mode === 'browser'
? [...state.browser.expandPath.filter((path) => path !== payload)]
: state.browser.expandPath
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fileRemoved(state, payload) : state.localhost.files,
expandPath: state.mode === 'localhost' ? [...(state.browser.expandPath.filter(path => path !== payload))] : state.localhost.expandPath
files:
state.mode === 'localhost'
? fileRemoved(state, payload)
: state.localhost.files,
expandPath:
state.mode === 'localhost'
? [...state.browser.expandPath.filter((path) => path !== payload)]
: state.localhost.expandPath
}
}
}
@ -365,34 +446,50 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'ADD_INPUT_FIELD': {
const payload = action.payload as { path: string, fileTree, type: 'file' | 'folder' }
const payload = action.payload as {
path: string
fileTree
type: 'file' | 'folder'
}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fetchDirectoryContent(state, payload) : state.browser.files
files:
state.mode === 'browser'
? fetchDirectoryContent(state, payload)
: state.browser.files
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fetchDirectoryContent(state, payload) : state.localhost.files
files:
state.mode === 'localhost'
? fetchDirectoryContent(state, payload)
: state.localhost.files
},
focusEdit: payload.path + '/' + 'blank'
}
}
case 'REMOVE_INPUT_FIELD': {
const payload = action.payload as { path: string, fileTree }
const payload = action.payload as {path: string; fileTree}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? removeInputField(state, payload.path) : state.browser.files
files:
state.mode === 'browser'
? removeInputField(state, payload.path)
: state.browser.files
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? removeInputField(state, payload.path) : state.localhost.files
files:
state.mode === 'localhost'
? removeInputField(state, payload.path)
: state.localhost.files
},
focusEdit: null
}
@ -408,17 +505,27 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'FILE_RENAMED_SUCCESS': {
const payload = action.payload as { path: string, oldPath: string, fileTree }
const payload = action.payload as {
path: string
oldPath: string
fileTree
}
return {
...state,
browser: {
...state.browser,
files: state.mode === 'browser' ? fetchDirectoryContent(state, payload, payload.oldPath) : state.browser.files
files:
state.mode === 'browser'
? fetchDirectoryContent(state, payload, payload.oldPath)
: state.browser.files
},
localhost: {
...state.localhost,
files: state.mode === 'localhost' ? fetchDirectoryContent(state, payload, payload.oldPath) : state.localhost.files
files:
state.mode === 'localhost'
? fetchDirectoryContent(state, payload, payload.oldPath)
: state.localhost.files
}
}
}
@ -436,15 +543,24 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'CREATE_WORKSPACE_SUCCESS': {
const payload = action.payload as { name: string; isGitRepo: boolean; branches?: { remote: any; name: string; }[], currentBranch?: string }
const workspaces = state.browser.workspaces.find(({ name }) => name === payload.name) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
const payload = action.payload as {
name: string
isGitRepo: boolean
branches?: {remote: any; name: string}[]
currentBranch?: string
}
const workspaces = state.browser.workspaces.find(
({name}) => name === payload.name
)
? state.browser.workspaces
: [...state.browser.workspaces, action.payload]
return {
...state,
browser: {
...state.browser,
currentWorkspace: payload.name,
workspaces: workspaces.filter(workspace => workspace),
workspaces: workspaces.filter((workspace) => workspace),
isRequestingWorkspace: false,
isSuccessfulWorkspace: true,
error: null
@ -465,21 +581,23 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'RENAME_WORKSPACE': {
const payload = action.payload as { oldName: string, workspaceName: string }
const payload = action.payload as {oldName: string; workspaceName: string}
let renamedWorkspace
const workspaces = state.browser.workspaces.filter(({ name, isGitRepo, branches, currentBranch }) => {
if (name && (name !== payload.oldName)) {
return true
} else {
renamedWorkspace = {
name: payload.workspaceName,
isGitRepo,
branches,
currentBranch
const workspaces = state.browser.workspaces.filter(
({name, isGitRepo, branches, currentBranch}) => {
if (name && name !== payload.oldName) {
return true
} else {
renamedWorkspace = {
name: payload.workspaceName,
isGitRepo,
branches,
currentBranch
}
return false
}
return false
}
})
)
return {
...state,
@ -494,7 +612,9 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
case 'DELETE_WORKSPACE': {
const payload = action.payload as string
const workspaces = state.browser.workspaces.filter(({ name }) => name && (name !== payload))
const workspaces = state.browser.workspaces.filter(
({name}) => name && name !== payload
)
return {
...state,
@ -522,7 +642,10 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'SET_FOCUS_ELEMENT': {
const payload = action.payload as { key: string, type: 'file' | 'folder' | 'gist' }[]
const payload = action.payload as {
key: string
type: 'file' | 'folder' | 'gist'
}[]
return {
...state,
@ -535,7 +658,9 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
return {
...state,
focusElement: state.focusElement.filter(element => element.key !== payload)
focusElement: state.focusElement.filter(
(element) => element.key !== payload
)
}
}
@ -676,14 +801,15 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'SET_CURRENT_WORKSPACE_BRANCHES': {
const payload: { remote: any, name: string }[] = action.payload
const payload: {remote: any; name: string}[] = action.payload
return {
...state,
browser: {
...state.browser,
workspaces: state.browser.workspaces.map((workspace) => {
if (workspace.name === state.browser.currentWorkspace) workspace.branches = payload
if (workspace.name === state.browser.currentWorkspace)
workspace.branches = payload
return workspace
})
}
@ -698,7 +824,8 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
browser: {
...state.browser,
workspaces: state.browser.workspaces.map((workspace) => {
if (workspace.name === state.browser.currentWorkspace) workspace.currentBranch = payload
if (workspace.name === state.browser.currentWorkspace)
workspace.currentBranch = payload
return workspace
})
}
@ -713,50 +840,68 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
browser: {
...state.browser,
workspaces: state.browser.workspaces.map((workspace) => {
if (workspace.name === state.browser.currentWorkspace) workspace.isGitRepo = payload
if (workspace.name === state.browser.currentWorkspace)
workspace.isGitRepo = payload
return workspace
})
}
}
}
case 'SET_GIT_CONFIG' : {
const payload: { username: string, token: string, email: string } = action.payload
case 'SET_GIT_CONFIG': {
const payload: {username: string; token: string; email: string} =
action.payload
return {
...state,
gitConfig: payload
}
}
default:
throw new Error()
}
}
const fileAdded = (state: BrowserState, path: string): { [x: string]: Record<string, FileType> } => {
let files = state.mode === 'browser' ? state.browser.files : state.localhost.files
const fileAdded = (
state: BrowserState,
path: string
): {[x: string]: Record<string, FileType>} => {
let files =
state.mode === 'browser' ? state.browser.files : state.localhost.files
const _path = splitPath(state, path)
files = _.setWith(files, _path, {
path: path,
name: extractNameFromKey(path),
isDirectory: false,
type: 'file'
}, Object)
files = _.setWith(
files,
_path,
{
path: path,
name: extractNameFromKey(path),
isDirectory: false,
type: 'file'
},
Object
)
return files
}
const fileRemoved = (state: BrowserState, path: string): { [x: string]: Record<string, FileType> } => {
const files = state.mode === 'browser' ? state.browser.files : state.localhost.files
const fileRemoved = (
state: BrowserState,
path: string
): {[x: string]: Record<string, FileType>} => {
const files =
state.mode === 'browser' ? state.browser.files : state.localhost.files
const _path = splitPath(state, path)
_.unset(files, _path)
return files
}
const removeInputField = (state: BrowserState, path: string): { [x: string]: Record<string, FileType> } => {
let files = state.mode === 'browser' ? state.browser.files : state.localhost.files
const removeInputField = (
state: BrowserState,
path: string
): {[x: string]: Record<string, FileType>} => {
let files =
state.mode === 'browser' ? state.browser.files : state.localhost.files
const root = state.mode === 'browser' ? ROOT_PATH : state.mode
if (path === root) {
@ -767,35 +912,51 @@ const removeInputField = (state: BrowserState, path: string): { [x: string]: Rec
const prevFiles = _.get(files, _path)
if (prevFiles) {
prevFiles.child && prevFiles.child[path + '/' + 'blank'] && delete prevFiles.child[path + '/' + 'blank']
files = _.setWith(files, _path, {
isDirectory: true,
path,
name: extractNameFromKey(path),
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder',
child: prevFiles ? prevFiles.child : {}
}, Object)
prevFiles.child &&
prevFiles.child[path + '/' + 'blank'] &&
delete prevFiles.child[path + '/' + 'blank']
files = _.setWith(
files,
_path,
{
isDirectory: true,
path,
name: extractNameFromKey(path),
type:
extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder',
child: prevFiles ? prevFiles.child : {}
},
Object
)
}
return files
}
// IDEA: Modify function to remove blank input field without fetching content
const fetchDirectoryContent = (state: BrowserState, payload: { fileTree, path: string, type?: 'file' | 'folder' }, deletePath?: string): { [x: string]: Record<string, FileType> } => {
if (!payload.fileTree) return state.mode === 'browser' ? state.browser.files : state[state.mode].files
const fetchDirectoryContent = (
state: BrowserState,
payload: {fileTree; path: string; type?: 'file' | 'folder'},
deletePath?: string
): {[x: string]: Record<string, FileType>} => {
if (!payload.fileTree)
return state.mode === 'browser'
? state.browser.files
: state[state.mode].files
if (state.mode === 'browser') {
if (payload.path === ROOT_PATH) {
let files = normalize(payload.fileTree, ROOT_PATH, payload.type)
files = _.merge(files, state.browser.files[ROOT_PATH])
if (deletePath) delete files[deletePath]
return { [ROOT_PATH]: files }
return {[ROOT_PATH]: files}
} else {
let files = state.browser.files
const _path = splitPath(state, payload.path)
let prevFiles = _.get(files, _path)
if (!prevFiles) {
const object = {}; let o = object
const object = {}
let o = object
for (const pa of _path) {
o = o[pa] = {}
}
@ -804,7 +965,10 @@ const fetchDirectoryContent = (state: BrowserState, payload: { fileTree, path: s
}
if (prevFiles) {
prevFiles.child = _.merge(normalize(payload.fileTree, payload.path, payload.type), prevFiles.child)
prevFiles.child = _.merge(
normalize(payload.fileTree, payload.path, payload.type),
prevFiles.child
)
if (deletePath) {
if (deletePath.endsWith('/blank')) delete prevFiles.child[deletePath]
else {
@ -814,7 +978,13 @@ const fetchDirectoryContent = (state: BrowserState, payload: { fileTree, path: s
}
files = _.setWith(files, _path, prevFiles, Object)
} else if (payload.fileTree && payload.path) {
files = { [payload.path]: normalize(payload.fileTree, payload.path, payload.type) }
files = {
[payload.path]: normalize(
payload.fileTree,
payload.path,
payload.type
)
}
}
return files
}
@ -823,14 +993,17 @@ const fetchDirectoryContent = (state: BrowserState, payload: { fileTree, path: s
let files = normalize(payload.fileTree, ROOT_PATH, payload.type)
files = _.merge(files, state.localhost.files[ROOT_PATH])
if (deletePath) delete files[deletePath]
return { [ROOT_PATH]: files }
return {[ROOT_PATH]: files}
} else {
let files = state.localhost.files
const _path = splitPath(state, payload.path)
const prevFiles = _.get(files, _path)
if (prevFiles) {
prevFiles.child = _.merge(normalize(payload.fileTree, payload.path, payload.type), prevFiles.child)
prevFiles.child = _.merge(
normalize(payload.fileTree, payload.path, payload.type),
prevFiles.child
)
if (deletePath) {
if (deletePath.endsWith('/blank')) delete prevFiles.child[deletePath]
else {
@ -840,24 +1013,37 @@ const fetchDirectoryContent = (state: BrowserState, payload: { fileTree, path: s
}
files = _.setWith(files, _path, prevFiles, Object)
} else {
files = { [payload.path]: normalize(payload.fileTree, payload.path, payload.type) }
files = {
[payload.path]: normalize(
payload.fileTree,
payload.path,
payload.type
)
}
}
return files
}
}
}
const fetchWorkspaceDirectoryContent = (state: BrowserState, payload: { fileTree, path: string }): { [x: string]: Record<string, FileType> } => {
const fetchWorkspaceDirectoryContent = (
state: BrowserState,
payload: {fileTree; path: string}
): {[x: string]: Record<string, FileType>} => {
const files = normalize(payload.fileTree, ROOT_PATH)
return { [ROOT_PATH]: files }
return {[ROOT_PATH]: files}
}
const normalize = (filesList, directory?: string, newInputType?: 'folder' | 'file'): Record<string, FileType> => {
const normalize = (
filesList,
directory?: string,
newInputType?: 'folder' | 'file'
): Record<string, FileType> => {
const folders = {}
const files = {}
Object.keys(filesList || {}).forEach(key => {
Object.keys(filesList || {}).forEach((key) => {
key = key.replace(/^\/|\/$/g, '') // remove first and last slash
let path = key
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
@ -867,7 +1053,8 @@ const normalize = (filesList, directory?: string, newInputType?: 'folder' | 'fil
path,
name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory,
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder'
type:
extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder'
}
} else {
files[extractNameFromKey(key)] = {
@ -904,24 +1091,35 @@ const normalize = (filesList, directory?: string, newInputType?: 'folder' | 'fil
const splitPath = (state: BrowserState, path: string): string[] | string => {
const root = ROOT_PATH
const pathArr: string[] = (path || '').split('/').filter(value => value)
const pathArr: string[] = (path || '').split('/').filter((value) => value)
if (pathArr[0] !== root) pathArr.unshift(root)
const _path = pathArr.map((key, index) => index > 1 ? ['child', key] : key).reduce((acc: string[], cur) => {
return Array.isArray(cur) ? [...acc, ...cur] : [...acc, cur]
}, [])
const _path = pathArr
.map((key, index) => (index > 1 ? ['child', key] : key))
.reduce((acc: string[], cur) => {
return Array.isArray(cur) ? [...acc, ...cur] : [...acc, cur]
}, [])
return _path
}
const addContextMenuItem = (state: BrowserState, item: action): { registeredMenuItems: action[], removedMenuItems: action[], error: string } => {
const addContextMenuItem = (
state: BrowserState,
item: action
): {
registeredMenuItems: action[]
removedMenuItems: action[]
error: string
} => {
let registeredItems = state[state.mode].contextMenu.registeredMenuItems
let removedItems = state[state.mode].contextMenu.removedMenuItems
let error = null
if (registeredItems.filter((o) => {
return o.id === item.id && o.name === item.name
}).length) {
if (
registeredItems.filter((o) => {
return o.id === item.id && o.name === item.name
}).length
) {
error = `Action ${item.name} already exists on ${item.id}`
return {
registeredMenuItems: registeredItems,
@ -930,7 +1128,7 @@ const addContextMenuItem = (state: BrowserState, item: action): { registeredMenu
}
}
registeredItems = [...registeredItems, item]
removedItems = removedItems.filter(menuItem => item.id !== menuItem.id)
removedItems = removedItems.filter((menuItem) => item.id !== menuItem.id)
return {
registeredMenuItems: registeredItems,
removedMenuItems: removedItems,
@ -938,7 +1136,14 @@ const addContextMenuItem = (state: BrowserState, item: action): { registeredMenu
}
}
const removeContextMenuItem = (state: BrowserState, plugin): { registeredMenuItems: action[], removedMenuItems: action[], error: string } => {
const removeContextMenuItem = (
state: BrowserState,
plugin
): {
registeredMenuItems: action[]
removedMenuItems: action[]
error: string
} => {
let registeredItems = state[state.mode].contextMenu.registeredMenuItems
const removedItems = state[state.mode].contextMenu.removedMenuItems
const error = null

@ -680,7 +680,7 @@ export function Workspace () {
handleContextMenu(e.pageX, e.pageY, ROOT_PATH, "workspace", 'workspace')
}
}>
<div className='d-flex flex-column w-100 remixui_fileexplorer' data-id="remixUIWorkspaceExplorer" onClick={resetFocus}>
<div className='d-flex flex-column w-100 pb-4 mb-2 remixui_fileexplorer' data-id="remixUIWorkspaceExplorer" onClick={resetFocus}>
<div>
<header>
<div className="mx-2 my-2 d-flex flex-column">
@ -972,4 +972,4 @@ export function Workspace () {
)
}
export default Workspace
export default Workspace

@ -112,7 +112,8 @@
"watch": "watchify apps/remix-ide/src/index.js -dv -p browserify-reload -o apps/remix-ide/build/app.js --exclude solc",
"reinstall": "rm ./node-modules/ -rf && rm yarn.lock && rm ./build/ -rf && yarn install & yarn run build",
"ganache-cli": "npx ganache-cli",
"build-contracts": "find ./node_modules/@openzeppelin/contracts | grep -i '.sol' > libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt && find ./node_modules/@uniswap/v3-core/contracts | grep -i '.sol' >> libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt"
"build-contracts": "find ./node_modules/@openzeppelin/contracts | grep -i '.sol' > libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt && find ./node_modules/@uniswap/v3-core/contracts | grep -i '.sol' >> libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt",
"prepare": "husky install"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.16.0",
@ -313,6 +314,7 @@
"gulp": "^4.0.2",
"hardhat": "^2.14.0",
"https-browserify": "^1.0.0",
"husky": "^8.0.0",
"ipfs-http-client": "^47.0.1",
"ipfs-mini": "^1.1.5",
"is-electron": "^2.2.0",
@ -320,6 +322,7 @@
"js-base64": "^2.1.9",
"js-beautify": "1.6.14",
"lerna": "^3.22.1",
"lint-staged": "^13.2.3",
"minixhr": "^4.0.0",
"mkdirp": "^0.5.1",
"mocha": "^8.0.1",
@ -363,5 +366,10 @@
},
"resolutions": {
"@types/react": "^17.0.24"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged --pattern \"**/*.{js,jsx,ts,tsx}\""
}
}
}

@ -6960,6 +6960,11 @@ ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-regex@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@ -6984,6 +6989,11 @@ ansi-styles@^5.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
ansi-styles@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
ansi-to-html@^0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.7.2.tgz#a92c149e4184b571eb29a0135ca001a8e2d710cb"
@ -7370,6 +7380,11 @@ ast-types-flow@^0.0.7:
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
async-done@^1.2.0, async-done@^1.2.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2"
@ -8581,7 +8596,7 @@ braces@^2.3.1, braces@^2.3.2:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1, braces@~3.0.2:
braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@ -9317,6 +9332,11 @@ chai@^4.3.7:
pathval "^1.1.1"
type-detect "^4.0.5"
chalk@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3"
integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@ -9639,6 +9659,22 @@ cli-table@^0.3.1:
dependencies:
colors "1.0.3"
cli-truncate@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
dependencies:
slice-ansi "^3.0.0"
string-width "^4.2.0"
cli-truncate@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389"
integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==
dependencies:
slice-ansi "^5.0.0"
string-width "^5.0.0"
cli-usage@^0.1.1:
version "0.1.10"
resolved "https://registry.yarnpkg.com/cli-usage/-/cli-usage-0.1.10.tgz#2c9d30a3824b48d161580a8f8d5dfe53d66b00d2"
@ -9865,6 +9901,11 @@ colorette@^2.0.10, colorette@^2.0.14:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798"
integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==
colorette@^2.0.19:
version "2.0.20"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
colors-browserify@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/colors-browserify/-/colors-browserify-0.1.1.tgz#286cc80fb00d62a1271f99045ee07d031a9acb76"
@ -9942,6 +9983,11 @@ commander@3.0.2:
resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
commander@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
commander@^2.12.1, commander@^2.15.0, commander@^2.20.0, commander@^2.20.3, commander@^2.9.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -11591,6 +11637,11 @@ each-props@^1.3.2:
is-plain-object "^2.0.1"
object.defaults "^1.1.0"
eastasianwidth@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@ -12529,6 +12580,21 @@ execa@^5.0.0:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
execa@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9"
integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.1"
human-signals "^4.3.0"
is-stream "^3.0.0"
merge-stream "^2.0.0"
npm-run-path "^5.1.0"
onetime "^6.0.0"
signal-exit "^3.0.7"
strip-final-newline "^3.0.0"
execr@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/execr/-/execr-1.0.1.tgz#79865e89a940f56f72be2dd6656ffffd7f2b7c8b"
@ -14791,6 +14857,11 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
human-signals@^4.3.0:
version "4.3.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
humanize-ms@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
@ -14798,6 +14869,11 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
husky@^8.0.0:
version "8.0.3"
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==
hyperscript-attribute-to-property@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyperscript-attribute-to-property/-/hyperscript-attribute-to-property-1.0.2.tgz#66ad4164f88beefacf46ec884bd3d1173c1c382a"
@ -15532,6 +15608,17 @@ is-fullwidth-code-point@^3.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-fullwidth-code-point@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
is-function@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
is-generator-fn@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
@ -15802,6 +15889,11 @@ is-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
@ -17192,6 +17284,11 @@ lightercollective@^0.1.0:
resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300"
integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==
lilconfig@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
lilconfig@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082"
@ -17212,6 +17309,39 @@ lines-and-columns@~2.0.3:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b"
integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==
lint-staged@^13.2.3:
version "13.2.3"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.3.tgz#f899aad6c093473467e9c9e316e3c2d8a28f87a7"
integrity sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==
dependencies:
chalk "5.2.0"
cli-truncate "^3.1.0"
commander "^10.0.0"
debug "^4.3.4"
execa "^7.0.0"
lilconfig "2.1.0"
listr2 "^5.0.7"
micromatch "^4.0.5"
normalize-path "^3.0.0"
object-inspect "^1.12.3"
pidtree "^0.6.0"
string-argv "^0.3.1"
yaml "^2.2.2"
listr2@^5.0.7:
version "5.0.8"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23"
integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==
dependencies:
cli-truncate "^2.1.0"
colorette "^2.0.19"
log-update "^4.0.0"
p-map "^4.0.0"
rfdc "^1.3.0"
rxjs "^7.8.0"
through "^2.3.8"
wrap-ansi "^7.0.0"
lit-element@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.2.tgz#9913bf220b85065f0e5f1bb8878cc44f36b50cfa"
@ -17587,6 +17717,16 @@ log-symbols@4.1.0, log-symbols@^4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
log-update@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
dependencies:
ansi-escapes "^4.3.0"
cli-cursor "^3.1.0"
slice-ansi "^4.0.0"
wrap-ansi "^6.2.0"
logform@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.3.0.tgz#a3997a05985de2ebd325ae0d166dffc9c6fe6b57"
@ -18491,6 +18631,14 @@ micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4:
braces "^3.0.1"
picomatch "^2.2.3"
micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
dependencies:
braces "^3.0.2"
picomatch "^2.3.1"
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
@ -18531,6 +18679,11 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-fn@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
mimic-response@^1.0.0, mimic-response@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
@ -19743,6 +19896,13 @@ npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
npm-run-path@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00"
integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==
dependencies:
path-key "^4.0.0"
npm-user-validate@~0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-0.1.5.tgz#52465d50c2d20294a57125b996baedbf56c5004b"
@ -20048,6 +20208,11 @@ object-inspect@^1.12.2, object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
object-inspect@^1.12.3:
version "1.12.3"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
object-is@^1.0.1, object-is@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
@ -20251,6 +20416,13 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
onetime@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
dependencies:
mimic-fn "^4.0.0"
open@^8.0.9, open@^8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
@ -20839,6 +21011,11 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-key@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
path-parse@^1.0.6, path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@ -20928,7 +21105,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
picomatch@^2.2.2:
picomatch@^2.2.2, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@ -20938,6 +21115,11 @@ pidtree@^0.3.0:
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
pidtree@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c"
integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -23080,6 +23262,11 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
rgbcolor@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/rgbcolor/-/rgbcolor-1.0.1.tgz#d6505ecdb304a6595da26fa4b43307306775945d"
@ -23268,6 +23455,13 @@ rxjs@^6.4.0, rxjs@^6.5.4, rxjs@^6.6.3:
dependencies:
tslib "^1.9.0"
rxjs@^7.8.0:
version "7.8.1"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
dependencies:
tslib "^2.1.0"
sade@^1.7.3:
version "1.8.1"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701"
@ -23789,6 +23983,32 @@ slash@^4.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
slice-ansi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
dependencies:
ansi-styles "^4.0.0"
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
slice-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
dependencies:
ansi-styles "^4.0.0"
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
slice-ansi@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
dependencies:
ansi-styles "^6.0.0"
is-fullwidth-code-point "^4.0.0"
slide@^1.1.3, slide@^1.1.5, slide@^1.1.6, slide@~1.1.3, slide@~1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
@ -24340,6 +24560,11 @@ strict-uri-encode@^2.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
string-argv@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
string-hash@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
@ -24393,6 +24618,15 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string-width@^5.0.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
dependencies:
eastasianwidth "^0.2.0"
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
string.prototype.matchall@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d"
@ -24518,6 +24752,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
dependencies:
ansi-regex "^6.0.1"
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
@ -24545,6 +24786,11 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-final-newline@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
strip-hex-prefix@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
@ -25382,6 +25628,11 @@ tslib@^2.0.3, tslib@^2.3.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
tslib@^2.1.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
tslint@~6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.0.0.tgz#1c0148beac4779924216302f192cdaa153618310"
@ -27141,6 +27392,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.2.2:
version "2.3.1"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
yargs-parser@20.2.4, yargs-parser@^20.2.2:
version "20.2.4"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"

Loading…
Cancel
Save