diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts
index 19918de0c4..e55ae8d6fd 100644
--- a/apps/remix-ide-e2e/src/tests/debugger.test.ts
+++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts
@@ -205,6 +205,7 @@ module.exports = {
.clickLaunchIcon('debugger')
.waitForElementVisible('*[data-id="slider"]')
.goToVMTraceStep(154)
+ .scrollInto('*[data-id="stepdetail"]')
.waitForElementContainsText('*[data-id="stepdetail"]', 'vm trace step:\n154', 60000)
},
diff --git a/apps/remix-ide-e2e/src/tests/gist.test.ts b/apps/remix-ide-e2e/src/tests/gist.test.ts
index 5bf3b34d5d..21832de532 100644
--- a/apps/remix-ide-e2e/src/tests/gist.test.ts
+++ b/apps/remix-ide-e2e/src/tests/gist.test.ts
@@ -9,10 +9,11 @@ const testData = {
// 99266d6da54cc12f37f11586e8171546c7700d67
module.exports = {
+ '@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
- UploadToGists: function (browser: NightwatchBrowser) {
+ 'UploadToGists #group1': function (browser: NightwatchBrowser) {
/*
- set the access token
- publish to gist
@@ -68,7 +69,7 @@ module.exports = {
*/
},
- 'Load Gist Modal': function (browser: NightwatchBrowser) {
+ 'Load Gist Modal #group1': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('home')
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('filePanel')
@@ -84,7 +85,7 @@ module.exports = {
.modalFooterCancelClick('gisthandler')
},
- 'Display Error Message For Invalid Gist ID': function (browser: NightwatchBrowser) {
+ 'Display Error Message For Invalid Gist ID #group1': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
@@ -101,7 +102,7 @@ module.exports = {
.modalFooterOKClick('gisthandler')
},
- 'Display Error Message For Missing Gist Token When Publishing': function (browser: NightwatchBrowser) {
+ 'Display Error Message For Missing Gist Token When Publishing #group1': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
@@ -125,7 +126,7 @@ module.exports = {
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
},
- 'Import From Gist For Valid Gist ID': function (browser: NightwatchBrowser) {
+ 'Import From Gist For Valid Gist ID #group2': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('settings')
@@ -140,6 +141,7 @@ module.exports = {
})
.setValue('*[data-id="gisthandlerModalDialogModalBody-react"] input[data-id="modalDialogCustomPromp"]', testData.validGistId)
.modalFooterOKClick('gisthandler')
+ .pause(10000)
.openFile(`gist-${testData.validGistId}/README.txt`)
.waitForElementVisible(`div[title='default_workspace/gist-${testData.validGistId}/README.txt']`)
.assert.containsText(`div[title='default_workspace/gist-${testData.validGistId}/README.txt'] > span`, 'README.txt')
diff --git a/apps/remix-ide-e2e/src/tests/vyper_api.ts b/apps/remix-ide-e2e/src/tests/vyper_api.ts
index f168372963..bb0afc3859 100644
--- a/apps/remix-ide-e2e/src/tests/vyper_api.ts
+++ b/apps/remix-ide-e2e/src/tests/vyper_api.ts
@@ -21,25 +21,30 @@ module.exports = {
.frame(0)
},
- 'Should add the Ballot.vy #group1': function (browser: NightwatchBrowser) {
- browser.click('button[data-id="add-ballot"]')
+ 'Should clone the Vyper repo #group1': function (browser: NightwatchBrowser) {
+ browser.click('button[data-id="add-repository"]')
.frameParent()
- .openFile('ballot.vy')
+ .waitForElementContainsText('*[data-shared="tooltipPopup"]', 'Vyper repository cloned', 30000)
+ .openFile('examples')
+ .openFile('examples/auctions')
+ .openFile('examples/auctions/blind_auction.vy')
},
- 'Compile ballot.vy should error #group1': function (browser: NightwatchBrowser) {
+ 'Compile blind_auction should success #group1': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('vyper')
// @ts-ignore
.frame(0)
.click('[data-id="remote-compiler"]')
.click('[data-id="compile"]')
- .assert.containsText('[data-id="error-message"]', 'unexpected indent')
+ .waitForElementVisible('[data-id="copy-abi"]')
},
- 'Compile test contract should success #group1': function (browser: NightwatchBrowser) {
+ 'Compile test contract and deploy to remix VM #group1': function (browser: NightwatchBrowser) {
let contractAddress
browser
.frameParent()
+ .clickLaunchIcon('filePanel')
+ .switchWorkspace('default_workspace')
.addFile('test.vy', { content: testContract })
.clickLaunchIcon('vyper')
// @ts-ignore
diff --git a/apps/remix-ide/src/app/tabs/debugger-tab.js b/apps/remix-ide/src/app/tabs/debugger-tab.js
index a06db0c508..5e62bd93d4 100644
--- a/apps/remix-ide/src/app/tabs/debugger-tab.js
+++ b/apps/remix-ide/src/app/tabs/debugger-tab.js
@@ -3,7 +3,7 @@ import { DebuggerApiMixin } from '@remixproject/debugger-plugin' // eslint-disab
import { ViewPlugin } from '@remixproject/engine-web'
import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
-import * as remixBleach from '../../lib/remixBleach'
+import { bleach } from '@remix-ui/helper'
import { compilationFinishedToastMsg, compilingToastMsg, localCompilationToastMsg, notFoundToastMsg, sourceVerificationNotAvailableToastMsg } from '@remix-ui/helper'
const css = require('./styles/debugger-tab-styles')
@@ -51,7 +51,7 @@ export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
this.on('fetchAndCompile', 'sourceVerificationNotAvailable', () => {
this.call('notification', 'toast', sourceVerificationNotAvailableToastMsg())
})
- return
+ return
}
showMessage (title, message) {
@@ -59,7 +59,7 @@ export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
this.call('notification', 'alert', {
id: 'debuggerTabShowMessage',
title,
- message: remixBleach.sanitize(message)
+ message: bleach.sanitize(message)
})
} catch (e) {
console.log(e)
diff --git a/apps/remix-ide/src/app/tabs/styles/debugger-tab-styles.js b/apps/remix-ide/src/app/tabs/styles/debugger-tab-styles.js
index 6a15d2cf56..3fb7add424 100644
--- a/apps/remix-ide/src/app/tabs/styles/debugger-tab-styles.js
+++ b/apps/remix-ide/src/app/tabs/styles/debugger-tab-styles.js
@@ -1,9 +1,6 @@
var csjs = require('csjs-inject')
const css = csjs`
- .debuggerTabView {
- padding: 2%;
- }
.debugger {
margin-bottom: 1%;
}
diff --git a/apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css b/apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css
index f95afd68ec..98d4b409c3 100644
--- a/apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css
+++ b/apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css
@@ -34,6 +34,7 @@
--dark:#343a40;
--body-bg: #fff;
--text-bg-mark: #fcf8e3;
+ --custom-select: #fff;
--breakpoint-xs:0;
--breakpoint-sm:576px;
--breakpoint-md:768px;
@@ -435,25 +436,25 @@ pre code {
.container,.container-sm {
max-width:540px
}
-
+
}
@media (min-width:768px) {
.container,.container-md,.container-sm {
max-width:720px
}
-
+
}
@media (min-width:992px) {
.container,.container-lg,.container-md,.container-sm {
max-width:960px
}
-
+
}
@media (min-width:1200px) {
.container,.container-lg,.container-md,.container-sm,.container-xl {
max-width:1140px
}
-
+
}
.row {
display:-ms-flexbox;
@@ -873,7 +874,7 @@ pre code {
.offset-sm-11 {
margin-left:91.666667%
}
-
+
}
@media (min-width:768px) {
.col-md {
@@ -1075,7 +1076,7 @@ pre code {
.offset-md-11 {
margin-left:91.666667%
}
-
+
}
@media (min-width:992px) {
.col-lg {
@@ -1277,7 +1278,7 @@ pre code {
.offset-lg-11 {
margin-left:91.666667%
}
-
+
}
@media (min-width:1200px) {
.col-xl {
@@ -1479,7 +1480,7 @@ pre code {
.offset-xl-11 {
margin-left:91.666667%
}
-
+
}
.table {
width:100%;
@@ -1662,7 +1663,7 @@ pre code {
.table-responsive-sm>.table-bordered {
border:0
}
-
+
}
@media (max-width:767.98px) {
.table-responsive-md {
@@ -1674,7 +1675,7 @@ pre code {
.table-responsive-md>.table-bordered {
border:0
}
-
+
}
@media (max-width:991.98px) {
.table-responsive-lg {
@@ -1686,7 +1687,7 @@ pre code {
.table-responsive-lg>.table-bordered {
border:0
}
-
+
}
@media (max-width:1199.98px) {
.table-responsive-xl {
@@ -1698,7 +1699,7 @@ pre code {
.table-responsive-xl>.table-bordered {
border:0
}
-
+
}
.table-responsive {
display:block;
@@ -1728,7 +1729,7 @@ pre code {
.form-control {
transition:none
}
-
+
}
.form-control::-ms-expand {
background-color:transparent;
@@ -2114,7 +2115,7 @@ textarea.form-control {
.form-inline .custom-control-label {
margin-bottom:0
}
-
+
}
.btn {
display:inline-block;
@@ -2138,7 +2139,7 @@ textarea.form-control {
.btn {
transition:none
}
-
+
}
.btn:hover {
color:#495057;
@@ -2626,7 +2627,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.fade {
transition:none
}
-
+
}
.fade:not(.show) {
opacity:0
@@ -2644,7 +2645,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.collapsing {
transition:none
}
-
+
}
.dropdown,.dropleft,.dropright,.dropup {
position:relative
@@ -2701,7 +2702,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
right:0;
left:auto
}
-
+
}
@media (min-width:768px) {
.dropdown-menu-md-left {
@@ -2712,7 +2713,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
right:0;
left:auto
}
-
+
}
@media (min-width:992px) {
.dropdown-menu-lg-left {
@@ -2723,7 +2724,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
right:0;
left:auto
}
-
+
}
@media (min-width:1200px) {
.dropdown-menu-xl-left {
@@ -2734,7 +2735,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
right:0;
left:auto
}
-
+
}
.dropup .dropdown-menu {
top:auto;
@@ -3190,7 +3191,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.custom-switch .custom-control-label::after {
transition:none
}
-
+
}
.custom-switch .custom-control-input:checked~.custom-control-label::after {
background-color:#fff;
@@ -3356,7 +3357,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
-webkit-transition:none;
transition:none
}
-
+
}
.custom-range::-webkit-slider-thumb:active {
background-color:#cfeaf9
@@ -3386,7 +3387,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
-moz-transition:none;
transition:none
}
-
+
}
.custom-range::-moz-range-thumb:active {
background-color:#cfeaf9
@@ -3418,7 +3419,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
-ms-transition:none;
transition:none
}
-
+
}
.custom-range::-ms-thumb:active {
background-color:#cfeaf9
@@ -3463,7 +3464,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.custom-control-label::before,.custom-file-label,.custom-select {
transition:none
}
-
+
}
.nav {
display:-ms-flexbox;
@@ -3629,7 +3630,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
padding-right:0;
padding-left:0
}
-
+
}
@media (min-width:576px) {
.navbar-expand-sm {
@@ -3662,14 +3663,14 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.navbar-expand-sm .navbar-toggler {
display:none
}
-
+
}
@media (max-width:767.98px) {
.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl {
padding-right:0;
padding-left:0
}
-
+
}
@media (min-width:768px) {
.navbar-expand-md {
@@ -3702,14 +3703,14 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.navbar-expand-md .navbar-toggler {
display:none
}
-
+
}
@media (max-width:991.98px) {
.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl {
padding-right:0;
padding-left:0
}
-
+
}
@media (min-width:992px) {
.navbar-expand-lg {
@@ -3742,14 +3743,14 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.navbar-expand-lg .navbar-toggler {
display:none
}
-
+
}
@media (max-width:1199.98px) {
.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl {
padding-right:0;
padding-left:0
}
-
+
}
@media (min-width:1200px) {
.navbar-expand-xl {
@@ -3782,7 +3783,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.navbar-expand-xl .navbar-toggler {
display:none
}
-
+
}
.navbar-expand {
-ms-flex-flow:row nowrap;
@@ -4010,7 +4011,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
margin-bottom:0;
margin-left:15px
}
-
+
}
.card-group>.card {
margin-bottom:15px
@@ -4051,7 +4052,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom {
border-bottom-left-radius:0
}
-
+
}
.card-columns .card {
margin-bottom:.75rem
@@ -4071,7 +4072,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
display:inline-block;
width:100%
}
-
+
}
.accordion {
overflow-anchor:none
@@ -4218,7 +4219,7 @@ input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-
.badge {
transition:none
}
-
+
}
a.badge:focus,a.badge:hover {
text-decoration:none
@@ -4341,7 +4342,7 @@ a.badge-dark.focus,a.badge-dark:focus {
.jumbotron {
padding:4rem 2rem
}
-
+
}
.jumbotron-fluid {
padding-right:0;
@@ -4467,7 +4468,7 @@ a.badge-dark.focus,a.badge-dark:focus {
to {
background-position:0 0
}
-
+
}
@keyframes progress-bar-stripes {
from {
@@ -4476,7 +4477,7 @@ a.badge-dark.focus,a.badge-dark:focus {
to {
background-position:0 0
}
-
+
}
.progress {
display:-ms-flexbox;
@@ -4506,7 +4507,7 @@ a.badge-dark.focus,a.badge-dark:focus {
.progress-bar {
transition:none
}
-
+
}
.progress-bar-striped {
background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);
@@ -4521,7 +4522,7 @@ a.badge-dark.focus,a.badge-dark:focus {
-webkit-animation:none;
animation:none
}
-
+
}
.media {
display:-ms-flexbox;
@@ -4637,7 +4638,7 @@ a.badge-dark.focus,a.badge-dark:focus {
margin-left:-1px;
border-left-width:1px
}
-
+
}
@media (min-width:768px) {
.list-group-horizontal-md {
@@ -4663,7 +4664,7 @@ a.badge-dark.focus,a.badge-dark:focus {
margin-left:-1px;
border-left-width:1px
}
-
+
}
@media (min-width:992px) {
.list-group-horizontal-lg {
@@ -4689,7 +4690,7 @@ a.badge-dark.focus,a.badge-dark:focus {
margin-left:-1px;
border-left-width:1px
}
-
+
}
@media (min-width:1200px) {
.list-group-horizontal-xl {
@@ -4715,7 +4716,7 @@ a.badge-dark.focus,a.badge-dark:focus {
margin-left:-1px;
border-left-width:1px
}
-
+
}
.list-group-flush {
border-radius:0
@@ -4930,7 +4931,7 @@ a.close.disabled {
.modal.fade .modal-dialog {
transition:none
}
-
+
}
.modal.show .modal-dialog {
-webkit-transform:none;
@@ -5086,19 +5087,19 @@ a.close.disabled {
.modal-sm {
max-width:300px
}
-
+
}
@media (min-width:992px) {
.modal-lg,.modal-xl {
max-width:800px
}
-
+
}
@media (min-width:1200px) {
.modal-xl {
max-width:1140px
}
-
+
}
.tooltip {
position:absolute;
@@ -5365,7 +5366,7 @@ a.close.disabled {
.carousel-item {
transition:none
}
-
+
}
.carousel-item-next,.carousel-item-prev,.carousel-item.active {
display:block
@@ -5397,7 +5398,7 @@ a.close.disabled {
.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right {
transition:none
}
-
+
}
.carousel-control-next,.carousel-control-prev {
position:absolute;
@@ -5420,7 +5421,7 @@ a.close.disabled {
.carousel-control-next,.carousel-control-prev {
transition:none
}
-
+
}
.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover {
color:#fff;
@@ -5482,7 +5483,7 @@ a.close.disabled {
.carousel-indicators li {
transition:none
}
-
+
}
.carousel-indicators .active {
opacity:1
@@ -5503,14 +5504,14 @@ a.close.disabled {
-webkit-transform:rotate(360deg);
transform:rotate(360deg)
}
-
+
}
@keyframes spinner-border {
to {
-webkit-transform:rotate(360deg);
transform:rotate(360deg)
}
-
+
}
.spinner-border {
display:inline-block;
@@ -5538,7 +5539,7 @@ a.close.disabled {
-webkit-transform:none;
transform:none
}
-
+
}
@keyframes spinner-grow {
0% {
@@ -5550,7 +5551,7 @@ a.close.disabled {
-webkit-transform:none;
transform:none
}
-
+
}
.spinner-grow {
display:inline-block;
@@ -5794,7 +5795,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
display:-ms-inline-flexbox!important;
display:inline-flex!important
}
-
+
}
@media (min-width:768px) {
.d-md-none {
@@ -5826,7 +5827,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
display:-ms-inline-flexbox!important;
display:inline-flex!important
}
-
+
}
@media (min-width:992px) {
.d-lg-none {
@@ -5858,7 +5859,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
display:-ms-inline-flexbox!important;
display:inline-flex!important
}
-
+
}
@media (min-width:1200px) {
.d-xl-none {
@@ -5890,7 +5891,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
display:-ms-inline-flexbox!important;
display:inline-flex!important
}
-
+
}
@media print {
.d-print-none {
@@ -5922,7 +5923,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
display:-ms-inline-flexbox!important;
display:inline-flex!important
}
-
+
}
.embed-responsive {
position:relative;
@@ -6229,7 +6230,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
-ms-flex-item-align:stretch!important;
align-self:stretch!important
}
-
+
}
@media (min-width:768px) {
.flex-md-row {
@@ -6368,7 +6369,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
-ms-flex-item-align:stretch!important;
align-self:stretch!important
}
-
+
}
@media (min-width:992px) {
.flex-lg-row {
@@ -6507,7 +6508,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
-ms-flex-item-align:stretch!important;
align-self:stretch!important
}
-
+
}
@media (min-width:1200px) {
.flex-xl-row {
@@ -6646,7 +6647,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
-ms-flex-item-align:stretch!important;
align-self:stretch!important
}
-
+
}
.float-left {
float:left!important
@@ -6667,7 +6668,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.float-sm-none {
float:none!important
}
-
+
}
@media (min-width:768px) {
.float-md-left {
@@ -6679,7 +6680,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.float-md-none {
float:none!important
}
-
+
}
@media (min-width:992px) {
.float-lg-left {
@@ -6691,7 +6692,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.float-lg-none {
float:none!important
}
-
+
}
@media (min-width:1200px) {
.float-xl-left {
@@ -6703,7 +6704,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.float-xl-none {
float:none!important
}
-
+
}
.user-select-all {
-webkit-user-select:all!important;
@@ -6766,7 +6767,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
top:0;
z-index:1020
}
-
+
}
.sr-only {
position:absolute;
@@ -7388,7 +7389,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.ml-sm-auto,.mx-sm-auto {
margin-left:auto!important
}
-
+
}
@media (min-width:768px) {
.m-md-0 {
@@ -7661,7 +7662,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.ml-md-auto,.mx-md-auto {
margin-left:auto!important
}
-
+
}
@media (min-width:992px) {
.m-lg-0 {
@@ -7934,7 +7935,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.ml-lg-auto,.mx-lg-auto {
margin-left:auto!important
}
-
+
}
@media (min-width:1200px) {
.m-xl-0 {
@@ -8207,7 +8208,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.ml-xl-auto,.mx-xl-auto {
margin-left:auto!important
}
-
+
}
.stretched-link::after {
position:absolute;
@@ -8256,7 +8257,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.text-sm-center {
text-align:center!important
}
-
+
}
@media (min-width:768px) {
.text-md-left {
@@ -8268,7 +8269,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.text-md-center {
text-align:center!important
}
-
+
}
@media (min-width:992px) {
.text-lg-left {
@@ -8280,7 +8281,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.text-lg-center {
text-align:center!important
}
-
+
}
@media (min-width:1200px) {
.text-xl-left {
@@ -8292,7 +8293,7 @@ a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover {
.text-xl-center {
text-align:center!important
}
-
+
}
.text-lowercase {
text-transform:lowercase!important
@@ -8472,7 +8473,7 @@ a.text-dark:focus,a.text-dark:hover {
color:inherit;
border-color:#dee2e6
}
-
+
}
.bg-primary {
background-image:linear-gradient(#54b4eb,#2fa4e7 60%,#1d9ce5);
diff --git a/apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css b/apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css
index 1ed6d7b4b6..30026bb48b 100644
--- a/apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css
+++ b/apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css
@@ -9,8 +9,7 @@
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
-*/@import url(https://fonts.googleapis.com/css2?family=Roboto:wght@400;
-700&display=swap);
+*/@import url(https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap);
:root {
--blue:#2a9fd6;
--indigo:#6610f2;
@@ -36,6 +35,7 @@
--dark:#adafae;
--body-bg: #060606;
--text-bg-mark: #fcf8e3;
+ --custom-select: #fff;
--breakpoint-xs:0;
--breakpoint-sm:576px;
--breakpoint-md:768px;
diff --git a/apps/solidity-compiler/src/app/compiler-api.ts b/apps/solidity-compiler/src/app/compiler-api.ts
index 21a2283ef3..12307bffc5 100644
--- a/apps/solidity-compiler/src/app/compiler-api.ts
+++ b/apps/solidity-compiler/src/app/compiler-api.ts
@@ -223,10 +223,10 @@ export const CompilerApiMixin = (Base) => class extends Base {
}
this.compiler.event.register('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)
- this.data.eventHandlers.onCompilerLoaded = (version) => {
+ this.data.eventHandlers.onCompilerLoaded = (version, license) => {
this.data.loading = false
this.statusChanged({ key: 'none' })
- this.emit('compilerLoaded', version)
+ this.emit('compilerLoaded', version, license)
}
this.compiler.event.register('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)
diff --git a/apps/vyper/src/app/app.tsx b/apps/vyper/src/app/app.tsx
index a6ce7c9db9..18b0fd0a80 100644
--- a/apps/vyper/src/app/app.tsx
+++ b/apps/vyper/src/app/app.tsx
@@ -38,12 +38,15 @@ const App: React.FC = () => {
async function start() {
try {
await remixClient.loaded()
- remixClient.onFileChange(name => setContract(name))
- const name = await remixClient.getContractName()
- setContract(name)
+ remixClient.onFileChange(name => setContract(name))
+ remixClient.onNoFileSelected(() => setContract(''))
} catch (err) {
console.log(err)
}
+ try {
+ const name = await remixClient.getContractName() // throw if no file are selected
+ setContract(name)
+ } catch (e) {}
}
start()
}, [])
diff --git a/apps/vyper/src/app/components/CompilerButton.tsx b/apps/vyper/src/app/components/CompilerButton.tsx
index fb0fb6ff05..c7fe318f0d 100644
--- a/apps/vyper/src/app/components/CompilerButton.tsx
+++ b/apps/vyper/src/app/components/CompilerButton.tsx
@@ -28,22 +28,60 @@ function CompilerButton({ contract, setOutput, compilerUrl }: Props) {
/** Compile a Contract */
async function compileContract() {
try {
- const _contract = await remixClient.getContract()
+ await remixClient.discardHighlight()
+ let _contract: any
+ try {
+ _contract = await remixClient.getContract()
+ } catch (e: any) {
+ setOutput('', { status: 'failed', message: e.message})
+ return
+ }
remixClient.changeStatus({
key: 'loading',
type: 'info',
title: 'Compiling'
})
- const output = await compile(compilerUrl, _contract)
+ let output
+ try {
+ output = await compile(compilerUrl, _contract)
+ } catch (e: any) {
+ setOutput(_contract.name, { status: 'failed', message: e.message})
+ return
+ }
setOutput(_contract.name, output)
// ERROR
if (isCompilationError(output)) {
const line = output.line
- const lineColumnPos = {
- start: { line: line - 1 },
- end: { line: line - 1 }
+ if (line) {
+ const lineColumnPos = {
+ start: { line: line - 1, column: 10 },
+ end: { line: line - 1, column: 10 }
+ }
+ remixClient.highlight(lineColumnPos as any, _contract.name, '#e0b4b4')
+ } else {
+ const regex = output.message.match(/line ((\d+):(\d+))+/g)
+ const errors = output.message.split(/line ((\d+):(\d+))+/g) // extract error message
+ if (regex) {
+ let errorIndex = 0
+ regex.map((errorLocation) => {
+ const location = errorLocation.replace('line ', '').split(':')
+ let message = errors[errorIndex]
+ errorIndex = errorIndex + 4
+ if (message && message.split('\n\n').length > 0) {
+ try {
+ message = message.split('\n\n')[1]
+ } catch (e) {}
+ }
+ if (location.length > 0) {
+ const lineColumnPos = {
+ start: { line: parseInt(location[0]) - 1, column: 10 },
+ end: { line: parseInt(location[0]) - 1, column: 10 }
+ }
+ remixClient.highlight(lineColumnPos as any, _contract.name, message)
+ }
+ })
+ }
}
- remixClient.highlight(lineColumnPos as any, _contract.name, '#e0b4b4')
throw new Error(output.message)
}
// SUCCESS
@@ -61,7 +99,6 @@ function CompilerButton({ contract, setOutput, compilerUrl }: Props) {
type: 'error',
title: err.message
})
- console.error(err)
}
}
diff --git a/apps/vyper/src/app/components/LocalUrl.tsx b/apps/vyper/src/app/components/LocalUrl.tsx
index 3659b4094e..5e2dcbacf1 100644
--- a/apps/vyper/src/app/components/LocalUrl.tsx
+++ b/apps/vyper/src/app/components/LocalUrl.tsx
@@ -26,11 +26,10 @@ function LocalUrlInput({ url, setUrl, environment }: Props) {
type="email"
placeholder="eg http://localhost:8000/compile" />
- The url to your local compiler
)
}
-export default LocalUrlInput;
\ No newline at end of file
+export default LocalUrlInput;
diff --git a/apps/vyper/src/app/components/VyperResult.tsx b/apps/vyper/src/app/components/VyperResult.tsx
index f550d17370..e58f901fea 100644
--- a/apps/vyper/src/app/components/VyperResult.tsx
+++ b/apps/vyper/src/app/components/VyperResult.tsx
@@ -7,7 +7,6 @@ import {
} from '../utils';
import Tabs from 'react-bootstrap/Tabs'
import Tab from 'react-bootstrap/Tab'
-import { Ballot } from '../examples/ballot';
import Button from 'react-bootstrap/Button';
import JSONTree from 'react-json-view'
import { CopyToClipboard } from '@remix-ui/clipboard'
@@ -17,14 +16,20 @@ interface VyperResultProps {
output?: VyperCompilationOutput;
}
+export type ExampleContract = {
+ name: string,
+ address: string
+}
+
function VyperResult({ output }: VyperResultProps) {
- const [ active, setActive ] = useState('abi');
-
+ const [ active, setActive ] = useState('abi')
+
if (!output) return (
+
No contract compiled yet.
-
)
@@ -33,7 +38,7 @@ function VyperResult({ output }: VyperResultProps) {
return (
-
{output.message}
+
{output.message}
)
}
@@ -41,7 +46,7 @@ function VyperResult({ output }: VyperResultProps) {
setActive(key)}>
JSON.stringify(output.abi)}>
- Copy ABI
+ Copy ABI
diff --git a/apps/vyper/src/app/examples/ballot.tsx b/apps/vyper/src/app/examples/ballot.tsx
deleted file mode 100644
index 4b368c6fda..0000000000
--- a/apps/vyper/src/app/examples/ballot.tsx
+++ /dev/null
@@ -1,161 +0,0 @@
-export const Ballot = {
- name: 'browser/ballot.vy',
- content: `# Voting with delegation.
-
- # Information about voters
- struct Voter:
- # weight is accumulated by delegation
- weight: int128
- # if true, that person already voted (which includes voting by delegating)
- voted: bool
- # person delegated to
- delegate: address
- # index of the voted proposal, which is not meaningful unless 'voted' is True.
- vote: int128
-
- # Users can create proposals
- struct Proposal:
- # short name (up to 32 bytes)
- name: bytes32
- # number of accumulated votes
- voteCount: int128
-
- voters: public(map(address, Voter))
- proposals: public(map(int128, Proposal))
- voterCount: public(int128)
- chairperson: public(address)
- int128Proposals: public(int128)
-
-
- @public
- @constant
- def delegated(addr: address) -> bool:
- return self.voters[addr].delegate != ZERO_ADDRESS
-
-
- @public
- @constant
- def directlyVoted(addr: address) -> bool:
- return self.voters[addr].voted and (self.voters[addr].delegate == ZERO_ADDRESS)
-
-
- # Setup global variables
- @public
- def __init__(_proposalNames: bytes32[2]):
- self.chairperson = msg.sender
- self.voterCount = 0
- for i in range(2):
- self.proposals[i] = Proposal({
- name: _proposalNames[i],
- voteCount: 0
- })
- self.int128Proposals += 1
-
- # Give a 'voter' the right to vote on this ballot.
- # This may only be called by the 'chairperson'.
- @public
- def giveRightToVote(voter: address):
- # Throws if the sender is not the chairperson.
- assert msg.sender == self.chairperson
- # Throws if the voter has already voted.
- assert not self.voters[voter].voted
- # Throws if the voter's voting weight isn't 0.
- assert self.voters[voter].weight == 0
- self.voters[voter].weight = 1
- self.voterCount += 1
-
- # Used by 'delegate' below, and can be called by anyone.
- @public
- def forwardWeight(delegate_with_weight_to_forward: address):
- assert self.delegated(delegate_with_weight_to_forward)
- # Throw if there is nothing to do:
- assert self.voters[delegate_with_weight_to_forward].weight > 0
-
- target: address = self.voters[delegate_with_weight_to_forward].delegate
- for i in range(4):
- if self.delegated(target):
- target = self.voters[target].delegate
- # The following effectively detects cycles of length <= 5,
- # in which the delegation is given back to the delegator.
- # This could be done for any int128ber of loops,
- # or even infinitely with a while loop.
- # However, cycles aren't actually problematic for correctness;
- # they just result in spoiled votes.
- # So, in the production version, this should instead be
- # the responsibility of the contract's client, and this
- # check should be removed.
- assert target != delegate_with_weight_to_forward
- else:
- # Weight will be moved to someone who directly voted or
- # hasn't voted.
- break
-
- weight_to_forward: int128 = self.voters[delegate_with_weight_to_forward].weight
- self.voters[delegate_with_weight_to_forward].weight = 0
- self.voters[target].weight += weight_to_forward
-
- if self.directlyVoted(target):
- self.proposals[self.voters[target].vote].voteCount += weight_to_forward
- self.voters[target].weight = 0
-
- # To reiterate: if target is also a delegate, this function will need
- # to be called again, similarly to as above.
-
- # Delegate your vote to the voter 'to'.
- @public
- def delegate(to: address):
- # Throws if the sender has already voted
- assert not self.voters[msg.sender].voted
- # Throws if the sender tries to delegate their vote to themselves or to
- # the default address value of 0x0000000000000000000000000000000000000000
- # (the latter might not be problematic, but I don't want to think about it).
- assert to != msg.sender
- assert to != ZERO_ADDRESS
-
- self.voters[msg.sender].voted = True
- self.voters[msg.sender].delegate = to
-
- # This call will throw if and only if this delegation would cause a loop
- # of length <= 5 that ends up delegating back to the delegator.
- self.forwardWeight(msg.sender)
-
- # Give your vote (including votes delegated to you)
- # to proposal 'proposals[proposal].name'.
- @public
- def vote(proposal: int128):
- # can't vote twice
- assert not self.voters[msg.sender].voted
- # can only vote on legitimate proposals
- assert proposal < self.int128Proposals
-
- self.voters[msg.sender].vote = proposal
- self.voters[msg.sender].voted = True
-
- # transfer msg.sender's weight to proposal
- self.proposals[proposal].voteCount += self.voters[msg.sender].weight
- self.voters[msg.sender].weight = 0
-
- # Computes the winning proposal taking all
- # previous votes into account.
- @public
- @constant
- def winningProposal() -> int128:
- winning_vote_count: int128 = 0
- winning_proposal: int128 = 0
- for i in range(2):
- if self.proposals[i].voteCount > winning_vote_count:
- winning_vote_count = self.proposals[i].voteCount
- winning_proposal = i
- return winning_proposal
-
- # Calls winningProposal() function to get the index
- # of the winner contained in the proposals array and then
- # returns the name of the winner
- @public
- @constant
- def winnerName() -> bytes32:
- return self.proposals[self.winningProposal()].name
-
- `
- }
-
\ No newline at end of file
diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx
index ebc117dba1..0b65c65a1a 100644
--- a/apps/vyper/src/app/utils/compiler.tsx
+++ b/apps/vyper/src/app/utils/compiler.tsx
@@ -18,8 +18,8 @@ export interface VyperCompilationResult {
export interface VyperCompilationError {
status: 'failed'
- column: number
- line: number
+ column?: number
+ line?: number
message: string
}
diff --git a/apps/vyper/src/app/utils/remix-client.tsx b/apps/vyper/src/app/utils/remix-client.tsx
index 080ba64a75..913131e594 100644
--- a/apps/vyper/src/app/utils/remix-client.tsx
+++ b/apps/vyper/src/app/utils/remix-client.tsx
@@ -3,6 +3,7 @@ import { Api, Status } from '@remixproject/plugin-utils';
import { createClient } from '@remixproject/plugin-webview'
import { PluginClient } from '@remixproject/plugin';
import { Contract } from './compiler';
+import { ExampleContract } from '../components/VyperResult';
export class RemixClient extends PluginClient {
private client = createClient>(this);
@@ -14,34 +15,70 @@ export class RemixClient extends PluginClient {
/** Emit an event when file changed */
async onFileChange(cb: (contract: string) => any) {
this.client.on('fileManager', 'currentFileChanged', async (name: string) => {
- if (!name) return
cb(name)
})
}
+ /** Emit an event when file changed */
+ async onNoFileSelected(cb: () => any) {
+ this.client.on('fileManager', 'noFileSelected', async () => {
+ cb()
+ })
+ }
+
/** Load Ballot contract example into the file manager */
- async loadContract({name, content}: Contract) {
+ async loadContract({name, address}: ExampleContract) {
try {
- await this.client.call('fileManager', 'setFile', name, content)
- await this.client.call('fileManager', 'switchFile', name)
+ const content = await this.client.call('contentImport', 'resolve', address)
+ await this.client.call('fileManager', 'setFile', content.cleanUrl, content.content)
+ await this.client.call('fileManager', 'switchFile', content.cleanUrl)
} catch (err) {
console.log(err)
}
}
+ async cloneVyperRepo() {
+ try {
+ // @ts-ignore
+ this.call('notification', 'toast', 'cloning Vyper repository...')
+ await this.call('manager', 'activatePlugin', 'dGitProvider')
+ // @ts-ignore
+ await this.call('dGitProvider', 'clone', { url: 'https://github.com/vyperlang/vyper', token: null }, 'vyper-lang')
+ // @ts-ignore
+ this.call('notification', 'toast', 'Vyper repository cloned, the workspace Vyper has been created.')
+ } catch (e) {
+ // @ts-ignore
+ this.call('notification', 'toast', e.message)
+ }
+ }
+
/** Update the status of the plugin in remix */
changeStatus(status: Status) {
this.client.emit('statusChanged', status);
}
/** Highlight a part of the editor */
- highlight(lineColumnPos: HighlightPosition, name: string, color: string) {
- return this.client.call('editor', 'highlight', lineColumnPos, name, color)
+ async highlight(lineColumnPos: HighlightPosition, name: string, message: string) {
+ await this.client.call('editor', 'highlight', lineColumnPos, name)
+ /*
+ column: -1
+ row: -1
+ text: "browser/Untitled1.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.↵"
+ type: "warning"
+ */
+ const annotation = {
+ column: 0,
+ row: lineColumnPos.start.line,
+ type: 'error',
+ text: message
+ }
+ await this.client.call('editor', 'addAnnotation', annotation, name)
}
/** Remove current Hightlight */
- discardHighlight() {
- return this.client.call('editor', 'discardHighlight')
+ async discardHighlight() {
+ await this.client.call('editor', 'discardHighlight')
+ await this.client.call('editor', 'clearAnnotations')
}
/** Get the name of the current contract */
diff --git a/libs/remix-solidity/src/compiler/compiler-worker.ts b/libs/remix-solidity/src/compiler/compiler-worker.ts
index 7fdeef2791..56c20875e1 100644
--- a/libs/remix-solidity/src/compiler/compiler-worker.ts
+++ b/libs/remix-solidity/src/compiler/compiler-worker.ts
@@ -33,7 +33,8 @@ export default function (self) { // eslint-disable-line @typescript-eslint/expli
}
self.postMessage({
cmd: 'versionLoaded',
- data: compiler.version()
+ data: compiler.version(),
+ license: compiler.license()
})
break
}
diff --git a/libs/remix-solidity/src/compiler/compiler.ts b/libs/remix-solidity/src/compiler/compiler.ts
index 70dd550eae..f1302f88b9 100644
--- a/libs/remix-solidity/src/compiler/compiler.ts
+++ b/libs/remix-solidity/src/compiler/compiler.ts
@@ -25,6 +25,7 @@ export class Compiler {
compileJSON: null,
worker: null,
currentVersion: null,
+ compilerLicense: null,
optimize: false,
runs: 200,
evmVersion: null,
@@ -95,9 +96,10 @@ export class Compiler {
* @param version compiler version
*/
- onCompilerLoaded(version: string): void {
+ onCompilerLoaded (version: string, license: string): void {
this.state.currentVersion = version
- this.event.trigger('compilerLoaded', [version])
+ this.state.compilerLicense = license
+ this.event.trigger('compilerLoaded', [version, license])
}
/**
@@ -132,7 +134,7 @@ export class Compiler {
}
this.onCompilationFinished(result, missingInputs, source, input, this.state.currentVersion)
}
- this.onCompilerLoaded(compiler.version())
+ this.onCompilerLoaded(compiler.version(), compiler.license())
}
}
@@ -185,6 +187,7 @@ export class Compiler {
if (err) {
console.error('Error in loading remote solc compiler: ', err)
} else {
+ let license
this.state.compileJSON = (source: SourceWithTarget) => {
const missingInputs: string[] = []
const missingInputsCallback = (path: string) => {
@@ -204,13 +207,14 @@ export class Compiler {
}
result = JSON.parse(remoteCompiler.compile(input, { import: missingInputsCallback }))
+ license = remoteCompiler.license()
}
} catch (exception) {
result = { error: { formattedMessage: 'Uncaught JavaScript exception:\n' + exception, severity: 'error', mode: 'panic' } }
}
this.onCompilationFinished(result, missingInputs, source, input, version)
}
- this.onCompilerLoaded(version)
+ this.onCompilerLoaded(version, license)
}
})
}
@@ -277,7 +281,7 @@ export class Compiler {
}
switch (data.cmd) {
case 'versionLoaded':
- if (data.data) this.onCompilerLoaded(data.data)
+ if (data.data && data.license) this.onCompilerLoaded(data.data, data.license)
break
case 'compiled':
{
diff --git a/libs/remix-solidity/src/compiler/types.ts b/libs/remix-solidity/src/compiler/types.ts
index ea9906c130..6b9af76845 100644
--- a/libs/remix-solidity/src/compiler/types.ts
+++ b/libs/remix-solidity/src/compiler/types.ts
@@ -163,6 +163,7 @@ export interface CompilerState {
compileJSON: ((input: SourceWithTarget) => void) | null,
worker: any,
currentVersion: string| null| undefined,
+ compilerLicense: string| null
optimize: boolean,
runs: number
evmVersion: EVMVersion| null,
@@ -193,6 +194,7 @@ export interface MessageToWorker {
export interface MessageFromWorker {
cmd: string,
+ license?: string,
job?: number,
missingInputs?: string[],
input?: any,
diff --git a/libs/remix-tests/src/compiler.ts b/libs/remix-tests/src/compiler.ts
index b399f7376e..7fedf9c830 100644
--- a/libs/remix-tests/src/compiler.ts
+++ b/libs/remix-tests/src/compiler.ts
@@ -134,7 +134,7 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts
if (runs) compiler.set('runs', runs)
if (currentCompilerUrl) {
compiler.loadRemoteVersion(currentCompilerUrl)
- compiler.event.register('compilerLoaded', this, function (version) {
+ compiler.event.register('compilerLoaded', this, function (version, license) {
next()
})
} else {
@@ -198,7 +198,7 @@ export function compileContractSources (sources: SrcIfc, newCompConfig: any, imp
compiler.set('runs', runs)
compiler.loadVersion(usingWorker, currentCompilerUrl)
// @ts-ignore
- compiler.event.register('compilerLoaded', this, (version) => {
+ compiler.event.register('compilerLoaded', this, (version, license) => {
next()
})
} else {
diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
index 7bb10333dc..636cfa4eea 100644
--- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
+++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
@@ -16,4 +16,8 @@
}
.validationError {
overflow-wrap: break-word;
+}
+.debuggerPanels {
+ overflow-y: scroll;
+ height: fit-content;
}
\ No newline at end of file
diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
index bd8008d0e3..74660fdabe 100644
--- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
+++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react' // eslint-disable-line
+import React, { useState, useEffect, useRef } from 'react' // eslint-disable-line
import TxBrowser from './tx-browser/tx-browser' // eslint-disable-line
import StepManager from './step-manager/step-manager' // eslint-disable-line
import VmDebugger from './vm-debugger/vm-debugger' // eslint-disable-line
@@ -36,6 +36,28 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
sourceLocationStatus: ''
})
+ const panelsRef = useRef(null)
+ const debuggerTopRef = useRef(null)
+
+ const handleResize = () => {
+ if (panelsRef.current && debuggerTopRef.current) {
+ panelsRef.current.style.height = (window.innerHeight - debuggerTopRef.current.clientHeight) - debuggerTopRef.current.offsetTop - 7 +'px'
+ }
+ }
+
+ useEffect(() => {
+ handleResize()
+ }, [])
+
+ useEffect(() => {
+ window.addEventListener('resize', handleResize)
+ // TODO: not a good way to wait on the ref doms element to be rendered of course
+ setTimeout(() =>
+ handleResize(), 2000)
+ return () => window.removeEventListener('resize', handleResize)
+ }, [state.debugging, state.isActive])
+
+
useEffect(() => {
return unLoad()
}, [])
@@ -260,34 +282,35 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
})
setTimeout(async() => {
- try {
- await debuggerInstance.debug(blockNumber, txNumber, tx, () => {
- listenToEvents(debuggerInstance, currentReceipt)
+ try {
+ await debuggerInstance.debug(blockNumber, txNumber, tx, () => {
+ listenToEvents(debuggerInstance, currentReceipt)
+ setState(prevState => {
+ return {
+ ...prevState,
+ blockNumber,
+ txNumber,
+ debugging: true,
+ currentReceipt,
+ currentBlock,
+ currentTransaction,
+ debugger: debuggerInstance,
+ toastMessage: `debugging ${txNumber}`,
+ validationError: ''
+ }
+ })
+ })
+ } catch (error) {
+ unLoad()
setState(prevState => {
return {
...prevState,
- blockNumber,
- txNumber,
- debugging: true,
- currentReceipt,
- currentBlock,
- currentTransaction,
- debugger: debuggerInstance,
- toastMessage: `debugging ${txNumber}`,
- validationError: ''
+ validationError: error.message || error
}
})
- })
- } catch (error) {
- unLoad()
- setState(prevState => {
- return {
- ...prevState,
- validationError: error.message || error
- }
- })
- }
- }, 300)
+ }
+ }, 300)
+ handleResize()
}
const debug = (txHash, web3?) => {
@@ -315,17 +338,18 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
traceLength: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.traceLength : null,
registerEvent: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.event.register.bind(state.debugger.step_manager.event) : null
}
+
const vmDebugger = {
registerEvent: state.debugger && state.debugger.vmDebuggerLogic ? state.debugger.vmDebuggerLogic.event.register.bind(state.debugger.vmDebuggerLogic.event) : null,
triggerEvent: state.debugger && state.debugger.vmDebuggerLogic ? state.debugger.vmDebuggerLogic.event.trigger.bind(state.debugger.vmDebuggerLogic.event) : null
}
+
return (
-
+
-
Debugger Configuration
-
+
{
setState(prevState => {
return { ...prevState, opt: { ...prevState.opt, debugWithGeneratedSources: checked } }
@@ -333,7 +357,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}} type="checkbox" title="Debug with generated sources" />
- { state.isLocalNodeUsed &&
+ { state.isLocalNodeUsed &&
{
setState(prevState => {
return { ...prevState, opt: { ...prevState.opt, debugWithLocalNode: checked } }
@@ -356,9 +380,11 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}
{ state.debugging &&
}
+
+
{ state.debugging && }
+ { state.debugging && }
- { state.debugging &&
}
)
}
diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
index 3a58c1d2f4..612757fe36 100644
--- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
+++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
@@ -98,7 +98,7 @@ export const VmDebuggerHead = ({ vmDebugger: { registerEvent, triggerEvent } })
}, [registerEvent])
return (
-
+
diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
index 07a1d0238b..47f6b4ff67 100644
--- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
+++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
@@ -75,6 +75,7 @@ type errorMarker = {
},
file: string
}
+
loader.config({ paths: { vs: 'assets/js/monaco-editor/dev/vs' } })
export type DecorationsReturn = {
@@ -442,7 +443,6 @@ export const EditorUI = (props: EditorUIProps) => {
allMarkersPerfile[filePath].push(markerData)
}
}
- console.log(allMarkersPerfile)
for (const filePath in allMarkersPerfile) {
const model = editorModelsState[filePath]?.model
if (model) {
@@ -587,8 +587,7 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
- function handleEditorWillMount(monaco: Monaco) {
-
+ function handleEditorWillMount(monaco) {
monacoRef.current = monaco
// Register a new language
monacoRef.current.languages.register({ id: 'remix-solidity' })
diff --git a/libs/remix-ui/helper/src/index.ts b/libs/remix-ui/helper/src/index.ts
index 9f050ea8b8..19e7721ac3 100644
--- a/libs/remix-ui/helper/src/index.ts
+++ b/libs/remix-ui/helper/src/index.ts
@@ -1,4 +1,5 @@
export * from './lib/remix-ui-helper'
+export * from './lib/bleach'
export * from './lib/helper-components'
export * from './lib/components/PluginViewWrapper'
export * from './lib/components/custom-dropdown'
\ No newline at end of file
diff --git a/apps/remix-ide/src/lib/remixBleach.js b/libs/remix-ui/helper/src/lib/bleach.ts
similarity index 87%
rename from apps/remix-ide/src/lib/remixBleach.js
rename to libs/remix-ui/helper/src/lib/bleach.ts
index e159c8a6df..44aa129042 100644
--- a/apps/remix-ide/src/lib/remixBleach.js
+++ b/libs/remix-ui/helper/src/lib/bleach.ts
@@ -5,7 +5,7 @@
*/
import * as he from 'he'
-const remixBleach = {
+export const bleach = {
matcher: /<\/?([a-zA-Z0-9]+)*(.*?)\/?>/igm,
@@ -24,7 +24,7 @@ const remixBleach = {
let match
// extract all tags
- while ((match = remixBleach.matcher.exec(html)) != null) {
+ while ((match = bleach.matcher.exec(html)) != null) {
const attrr = match[2].split(' ')
const attrs = []
@@ -45,7 +45,7 @@ const remixBleach = {
if (attr.name) attrs.push(attr)
})
- var tag = {
+ const tag = {
full: match[0],
name: match[1],
attr: attrs
@@ -57,14 +57,13 @@ const remixBleach = {
return matches
},
- sanitize: function (html, options) {
+ sanitize: function (html, options = { mode: 'white', list: bleach.whitelist, encode_entities: false}) {
html = String(html) || ''
- options = options || {}
-
+
const mode = options.mode || 'white'
- const list = options.list || remixBleach.whitelist
+ const list = options.list || bleach.whitelist
- var matches = remixBleach.analyze(html)
+ const matches = bleach.analyze(html)
if ((mode === 'white' && list.indexOf('script') === -1) ||
(mode === 'black' && list.indexOf('script') !== -1)) {
@@ -95,5 +94,3 @@ const remixBleach = {
return html
}
}
-
-module.exports = remixBleach
diff --git a/libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.css b/libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.css
index 6f6cd9b221..62a0dd5987 100644
--- a/libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.css
+++ b/libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.css
@@ -8,6 +8,7 @@
.remixModalBody {
overflow-y: auto;
max-height: 600px;
+ white-space: pre-line;
}
@-webkit-keyframes animatetop {
from {top: -300px; opacity: 0}
diff --git a/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx b/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
index 4bffb2565f..b6e8c9948a 100644
--- a/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
+++ b/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
@@ -27,8 +27,8 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
return (
-
{plugin?.profile.displayName || plugin?.profile.name}
-
+
{plugin?.profile.displayName || plugin?.profile.name}
+
{plugin?.profile?.maintainedBy?.toLowerCase() === "remix" && ()}
diff --git a/libs/remix-ui/solidity-compiler/src/lib/actions/compiler.ts b/libs/remix-ui/solidity-compiler/src/lib/actions/compiler.ts
index c67aee6ddb..b1c0b686de 100644
--- a/libs/remix-ui/solidity-compiler/src/lib/actions/compiler.ts
+++ b/libs/remix-ui/solidity-compiler/src/lib/actions/compiler.ts
@@ -46,8 +46,8 @@ export const listenToEvents = (compileTabLogic: CompileTabLogic, api) => (dispat
dispatch(setCompilerMode('loadingCompiler'))
})
- compileTabLogic.compiler.event.register('compilerLoaded', () => {
- dispatch(setCompilerMode('compilerLoaded'))
+ compileTabLogic.compiler.event.register('compilerLoaded', (version, license) => {
+ dispatch(setCompilerMode('compilerLoaded', version, license))
})
compileTabLogic.compiler.event.register('compilationFinished', (success, data, source, input, version) => {
diff --git a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
index 069377d045..857a86e73c 100644
--- a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
+++ b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
@@ -48,6 +48,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
timeout: 300,
allversions: [],
customVersions: [],
+ compilerLicense: null,
selectedVersion: null,
defaultVersion: 'soljson-v0.8.7+commit.e28d00a7.js', // this default version is defined: in makeMockCompiler (for browser test)
runs: '',
@@ -185,7 +186,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
loadingCompiler()
break
case 'compilerLoaded':
- compilerLoaded()
+ compilerLoaded(compilerContainer.compiler.args[1])
break
case 'compilationFinished':
compilationFinished()
@@ -432,14 +433,20 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
if (!compileIcon.current) return
compileIcon.current.setAttribute('title', 'compiler is loading, please wait a few moments.')
compileIcon.current.classList.add('remixui_spinningIcon')
+ setState(prevState => {
+ return { ...prevState, compilerLicense: 'Compiler is loading. License will be displayed once compiler is loaded'}
+ })
_updateLanguageSelector()
setDisableCompileButton(true)
}
- const compilerLoaded = () => {
+ const compilerLoaded = (license) => {
if (!compileIcon.current) return
compileIcon.current.setAttribute('title', '')
compileIcon.current.classList.remove('remixui_spinningIcon')
+ setState(prevState => {
+ return { ...prevState, compilerLicense: license ? license : 'Could not retreive license for selected compiler version' }
+ })
if (state.autoCompile) compile()
const isDisabled = !compiledFileName || (compiledFileName && !isSolFileSelected(compiledFileName))
@@ -554,6 +561,10 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
modal('Add a custom compiler', promptMessage('URL'), 'OK', addCustomCompiler, 'Cancel', () => {})
}
+ const showCompilerLicense = () => {
+ modal('Compiler License', state.compilerLicense ? state.compilerLicense : 'License not available', 'OK', () => {})
+ }
+
const promptMessage = (message) => {
return (
<>
@@ -701,10 +712,9 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
-
+
+ promptCompiler()} title="Add a custom compiler with URL">
+ showCompilerLicense()} title="See compiler license">