Browse Source

Merge branch 'master' into allow-url-language-selection

pull/1504/head
David Disu 4 months ago
committed by GitHub
parent
commit
2df27fe6b4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      apps/debugger/src/app/debugger-api.ts
  2. 8
      apps/remix-ide-e2e/src/tests/defaultLayout.test.ts
  3. 2
      apps/remix-ide-e2e/src/tests/generalSettings.test.ts
  4. 12
      apps/remix-ide-e2e/src/tests/plugin_api.ts
  5. 107
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  6. 4
      apps/remix-ide/src/app.js
  7. 3
      apps/remix-ide/src/app/components/panel.ts
  8. 37
      apps/remix-ide/src/app/components/side-panel.tsx
  9. 110
      apps/remix-ide/src/app/components/vertical-icons.js
  10. 116
      apps/remix-ide/src/app/components/vertical-icons.tsx
  11. 2
      apps/remix-ide/src/app/editor/examples.js
  12. 3
      apps/remix-ide/src/app/panels/layout.ts
  13. 6
      apps/remix-ide/src/app/plugins/remixd-handle.tsx
  14. 2
      apps/remix-ide/src/app/tabs/runTab/model/recorder.js
  15. 7
      apps/remix-ide/src/app/tabs/theme-module.js
  16. 8543
      apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css
  17. 8671
      apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css
  18. 7213
      apps/remix-ide/src/assets/css/themes/bootstrap-flatly.min.css
  19. 8645
      apps/remix-ide/src/assets/css/themes/bootstrap-spacelab.min.css
  20. 51
      apps/remix-ide/src/assets/css/themes/remix-black_undtds.css
  21. 3
      apps/remix-ide/src/assets/css/themes/remix-candy_ikhg4m.css
  22. 51
      apps/remix-ide/src/assets/css/themes/remix-dark_tvx1s2.css
  23. 20
      apps/remix-ide/src/assets/css/themes/remix-light_powaqg.css
  24. 3
      apps/remix-ide/src/assets/css/themes/remix-midcentury_hrzph3.css
  25. BIN
      apps/remix-ide/src/assets/img/cairoLogo.webp
  26. 2
      apps/remix-ide/src/blockchain/blockchain.js
  27. 14
      apps/remix-ide/src/remixAppManager.js
  28. 2
      apps/remix-ide/src/walkthroughService.js
  29. 5
      libs/remix-core-plugin/src/lib/compiler-artefacts.ts
  30. 3
      libs/remix-core-plugin/src/lib/compiler-content-imports.ts
  31. 2
      libs/remix-lib/src/execution/txRunnerWeb3.ts
  32. 43
      libs/remix-tests/src/compiler.ts
  33. 22
      libs/remix-tests/src/runTestSources.ts
  34. 4
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.css
  35. 5
      libs/remix-ui/editor/src/lib/remix-ui-editor.css
  36. 7
      libs/remix-ui/helper/src/lib/helper-components.tsx
  37. 4
      libs/remix-ui/helper/src/lib/remix-ui-helper.ts
  38. 25
      libs/remix-ui/home-tab/src/lib/components/pluginButton.tsx
  39. 48
      libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css
  40. 71
      libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
  41. 2
      libs/remix-ui/panel/src/lib/dragbar/dragbar.css
  42. 1
      libs/remix-ui/panel/src/lib/dragbar/dragbar.tsx
  43. 12
      libs/remix-ui/panel/src/lib/main/main-panel.tsx
  44. 2
      libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
  45. 2
      libs/remix-ui/panel/src/lib/types/index.ts
  46. 2
      libs/remix-ui/permission-handler/src/lib/permission-dialog.tsx
  47. 46
      libs/remix-ui/run-tab/src/lib/actions/index.ts
  48. 2
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  49. 9
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  50. 6
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  51. 4
      libs/remix-ui/run-tab/src/lib/types/index.ts
  52. 9
      libs/remix-ui/solidity-unit-testing/src/lib/logic/testTabLogic.ts
  53. 52
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  54. 7
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
  55. 10
      libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
  56. 8
      libs/remix-ui/terminal/src/lib/components/ChechTxStatus.tsx
  57. 55
      libs/remix-ui/terminal/src/lib/components/Context.tsx
  58. 19
      libs/remix-ui/terminal/src/lib/components/RenderCall.tsx
  59. 17
      libs/remix-ui/terminal/src/lib/components/RenderKnownTransactions.tsx
  60. 17
      libs/remix-ui/terminal/src/lib/components/RenderUnknownTransactions.tsx
  61. 84
      libs/remix-ui/terminal/src/lib/components/Table.tsx
  62. 20
      libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts
  63. 581
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.css
  64. 136
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  65. 6
      libs/remix-ui/terminal/src/lib/terminalWelcome.tsx
  66. 51
      libs/remix-ui/theme-module/src/lib/remix-ui-theme-module.tsx
  67. 20
      libs/remix-ui/vertical-icons-panel/.eslintrc.json
  68. 3
      libs/remix-ui/vertical-icons-panel/src/index.ts
  69. 11
      libs/remix-ui/vertical-icons-panel/src/lib/components/Badge.tsx
  70. 2
      libs/remix-ui/vertical-icons-panel/src/lib/components/BasicLogo.tsx
  71. 13
      libs/remix-ui/vertical-icons-panel/src/lib/components/Chevron.tsx
  72. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/Debugger.tsx
  73. 59
      libs/remix-ui/vertical-icons-panel/src/lib/components/FilePanel.tsx
  74. 14
      libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx
  75. 66
      libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx
  76. 33
      libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx
  77. 43
      libs/remix-ui/vertical-icons-panel/src/lib/components/OtherIcons.tsx
  78. 36
      libs/remix-ui/vertical-icons-panel/src/lib/components/PluginManager.tsx
  79. 72
      libs/remix-ui/vertical-icons-panel/src/lib/components/RequiredSection.tsx
  80. 60
      libs/remix-ui/vertical-icons-panel/src/lib/components/Settings.tsx
  81. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/Solidity.tsx
  82. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/SolidityStaticAnalysis.tsx
  83. 42
      libs/remix-ui/vertical-icons-panel/src/lib/components/Udapp.tsx
  84. 29
      libs/remix-ui/vertical-icons-panel/src/lib/reducers/iconBadgeReducer.ts
  85. 3
      libs/remix-ui/vertical-icons-panel/src/lib/reducers/verticalScrollReducer.ts
  86. 26
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css
  87. 167
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx
  88. 10
      libs/remix-ui/vertical-icons-panel/src/lib/types/index.ts
  89. 46
      libs/remix-ui/vertical-icons-panel/src/lib/vertical-icons-context-menu.tsx
  90. 12
      libs/remix-ui/vertical-icons-panel/tsconfig.json
  91. 3
      libs/remix-ui/vertical-icons-panel/tsconfig.lib.json
  92. 111
      libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel.d.ts
  93. 2
      libs/remix-url-resolver/src/resolve.ts
  94. 2
      libs/remix-url-resolver/tests/test.ts

2
apps/debugger/src/app/debugger-api.ts

@ -83,7 +83,7 @@ export const DebuggerApiMixin = (Base) => class extends Base {
const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address
const targetAddress = target || receipt.contractAddress || receipt.to
const codeAtAddress = await this._web3.eth.getCode(targetAddress)
const output = await this.call('fetchAndCompile', 'resolve', targetAddress, codeAtAddress, 'browser/.debug')
const output = await this.call('fetchAndCompile', 'resolve', targetAddress, codeAtAddress, '.debug')
if (output) {
return new CompilerAbstract(output.languageversion, output.data, output.source)
}

8
apps/remix-ide-e2e/src/tests/defaultLayout.test.ts

@ -50,11 +50,15 @@ module.exports = {
'Toggles Terminal': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="terminalContainer"]')
.assert.elementPresent('div[data-id="terminalContainerDisplay"]')
.assert.elementPresent('div[data-id="terminalCli"]')
.assert.elementPresent('div[data-id="terminalContainer"]')
.waitForElementVisible('div[data-id="terminalContainer"]')
.waitForElementVisible('div[data-id="terminalCli"]')
.click('i[data-id="terminalToggleIcon"]')
.checkElementStyle('div[data-id="terminalToggleMenu"]', 'height', '35px')
.assert.not.elementPresent('div[data-id="terminalCli"]')
.click('i[data-id="terminalToggleIcon"]')
.assert.elementPresent('div[data-id="terminalContainerDisplay"]')
.waitForElementVisible('div[data-id="terminalCli"]')
},
'Switch Tabs using tabs icon': function (browser: NightwatchBrowser) {

2
apps/remix-ide-e2e/src/tests/generalSettings.test.ts

@ -19,7 +19,7 @@ module.exports = {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.waitForElementVisible('*[data-id="settingsTabGenerateContractMetadataLabel"]', 5000)
.verify.elementPresent('[data-id="settingsTabGenerateContractMetadata"]:checked')
.click('*[data-id="verticalIconsFileExplorerIcons"]')
.click('*[data-id="verticalIconsKindfilePanel"]')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.click('*[data-id="verticalIconsKindsolidity"]')

12
apps/remix-ide-e2e/src/tests/plugin_api.ts

@ -149,6 +149,18 @@ module.exports = {
await clickAndCheckLog(browser, 'udapp:getAccounts', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', null, null)
},
'Should select another provider #group1': async function (browser: NightwatchBrowser) {
await clickAndCheckLog(browser, 'udapp:setEnvironmentMode', null, null, { context: 'vm', fork: 'berlin' })
await browser
.frameParent()
.useCss()
.clickLaunchIcon('udapp')
.waitForElementContainsText('#selectExEnvOptions option:checked', 'JavaScript VM (Berlin)')
.clickLaunchIcon('localPlugin')
.useXpath()
// @ts-ignore
.frame(0)
},
// context menu item
'Should create context menu item #group1': async function (browser: NightwatchBrowser) {

107
apps/remix-ide-e2e/src/tests/transactionExecution.test.ts

@ -195,6 +195,26 @@ module.exports = {
.journalLastChildIncludes('"documentation": "param2 from library"')
.journalLastChildIncludes('"documentation": "param3 from library"')
.journalLastChildIncludes('Debug the transaction to get more information.')
},
'Should compile and deploy 2 simple contracts, the contract creation component state should be correctly reset for the deployment of the second contract #group4': function (browser: NightwatchBrowser) {
browser
.addFile('Storage.sol', sources[6]['Storage.sol'])
.addFile('Owner.sol', sources[6]['Owner.sol'])
.clickLaunchIcon('udapp')
.createContract('42')
.openFile('Storage.sol')
.clickLaunchIcon('udapp')
.createContract('') // this creation will fail if the component hasn't been properly reset.
.clickInstance(1)
.clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '24' })
.testFunction('last', // we check if the contract is actually reachable.
{
status: 'true Transaction mined and execution succeed',
'decoded input': {
'uint256 num': '24'
}
})
.end()
}
}
@ -322,5 +342,92 @@ contract C {
}
}`
}
},
{
'Owner.sol': {
content: `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Owner
* @dev Set & change owner
*/
contract Owner {
address private owner;
// event for EVM logging
event OwnerSet(address indexed oldOwner, address indexed newOwner);
// modifier to check if caller is owner
modifier isOwner() {
// If the first argument of 'require' evaluates to 'false', execution terminates and all
// changes to the state and to Ether balances are reverted.
// This used to consume all gas in old EVM versions, but not anymore.
// It is often a good idea to use 'require' to check if functions are called correctly.
// As a second argument, you can also provide an explanation about what went wrong.
require(msg.sender == owner, "Caller is not owner");
_;
}
/**
* @dev Set contract deployer as owner
*/
constructor(uint p) {
owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor
emit OwnerSet(address(0), owner);
}
/**
* @dev Change owner
* @param newOwner address of new owner
*/
function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}
/**
* @dev Return owner address
* @return address of owner
*/
function getOwner() external view returns (address) {
return owner;
}
}`
},
'Storage.sol': {
content: `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}`
}
}
]

4
apps/remix-ide/src/app.js

@ -225,8 +225,8 @@ class AppComponent {
self.engine.register([appPanel, tabProxy])
// those views depend on app_manager
self.menuicons = new VerticalIcons(appManager)
self.sidePanel = new SidePanel(appManager, self.menuicons)
self.menuicons = new VerticalIcons()
self.sidePanel = new SidePanel()
self.hiddenPanel = new HiddenPanel()
const pluginManagerComponent = new PluginManagerComponent(

3
apps/remix-ide/src/app/components/panel.ts

@ -49,8 +49,7 @@ export class AbstractPanel extends HostPlugin {
* @param {String} name The name of the plugin to display the content
*/
showContent (name) {
if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
Object.values(this.plugins).forEach(plugin => {
plugin.active = false
})

37
apps/remix-ide/src/app/components/side-panel.tsx

@ -4,8 +4,6 @@ import ReactDOM from 'react-dom'
import { AbstractPanel } from './panel'
import { RemixPluginPanel } from '@remix-ui/panel'
import packageJson from '../../../../../package.json'
import { RemixAppManager } from '../../remixAppManager'
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import RemixUIPanelHeader from 'libs/remix-ui/panel/src/lib/plugins/panel-header'
// const csjs = require('csjs-inject')
@ -17,20 +15,18 @@ const sidePanel = {
methods: ['addView', 'removeView']
}
// TODO merge with vertical-icons.js
export class SidePanel extends AbstractPanel {
appManager: RemixAppManager
sideelement: any
verticalIcons: VerticalIcons;
constructor (appManager: RemixAppManager, verticalIcons: VerticalIcons) {
constructor() {
super(sidePanel)
this.appManager = appManager
this.sideelement = document.createElement('section')
this.sideelement.setAttribute('class', 'panel plugin-manager')
this.verticalIcons = verticalIcons
}
onActivation() {
this.renderComponent()
// Toggle content
verticalIcons.events.on('toggleContent', (name) => {
this.on('menuicons', 'toggleContent', (name) => {
if (!this.plugins[name]) return
if (this.plugins[name].active) {
// TODO: Only keep `this.emit` (issue#2210)
@ -44,7 +40,7 @@ export class SidePanel extends AbstractPanel {
this.events.emit('showing', name)
})
// Force opening
verticalIcons.events.on('showContent', (name) => {
this.on('menuicons', 'showContent', (name) => {
if (!this.plugins[name]) return
this.showContent(name)
// TODO: Only keep `this.emit` (issue#2210)
@ -53,25 +49,22 @@ export class SidePanel extends AbstractPanel {
})
}
onActivation () {
this.renderComponent()
}
focus (name) {
focus(name) {
this.emit('focusChanged', name)
super.focus(name)
}
removeView (profile) {
removeView(profile) {
if (this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
super.removeView(profile)
this.emit('pluginDisabled', profile.name)
this.call('menuicons', 'unlinkContent', profile)
this.renderComponent()
}
addView (profile, view) {
addView(profile, view) {
super.addView(profile, view)
this.verticalIcons.linkContent(profile)
this.call('menuicons', 'linkContent', profile)
this.renderComponent()
}
@ -79,17 +72,17 @@ export class SidePanel extends AbstractPanel {
* Display content and update the header
* @param {String} name The name of the plugin to display
*/
async showContent (name) {
async showContent(name) {
super.showContent(name)
this.emit('focusChanged', name)
this.renderComponent()
}
render () {
render() {
return this.sideelement
}
renderComponent () {
ReactDOM.render(<RemixPluginPanel header={<RemixUIPanelHeader plugins={this.plugins}></RemixUIPanelHeader>} plugins={this.plugins}/>, this.sideelement)
renderComponent() {
ReactDOM.render(<RemixPluginPanel header={<RemixUIPanelHeader plugins={this.plugins}></RemixUIPanelHeader>} plugins={this.plugins} />, this.sideelement)
}
}

110
apps/remix-ide/src/app/components/vertical-icons.js

@ -1,110 +0,0 @@
import * as packageJson from '../../../../../package.json'
import ReactDOM from 'react-dom'
import React from 'react' // eslint-disable-line
// eslint-disable-next-line no-unused-vars
import { RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
import Registry from '../state/registry'
const { Plugin } = require('@remixproject/engine')
const EventEmitter = require('events')
const profile = {
name: 'menuicons',
displayName: 'Vertical Icons',
description: '',
version: packageJson.version,
methods: ['select', 'unlinkContent']
}
// TODO merge with side-panel.js. VerticalIcons should not be a plugin
export class VerticalIcons extends Plugin {
constructor (appManager) {
super(profile)
this.events = new EventEmitter()
this.appManager = appManager
this.htmlElement = document.createElement('div')
this.htmlElement.setAttribute('id', 'icon-panel')
this.icons = {}
this.iconKind = {}
this.iconStatus = {}
this.defaultProfile = profile
this.targetProfileForChange = {}
this.targetProfileForRemoval = {}
this.registry = Registry.getInstance()
this.keys = ['succeed', 'edited', 'none', 'loading', 'failed']
this.types = ['error', 'warning', 'success', 'info', '']
}
renderComponent () {
ReactDOM.render(
<RemixUiVerticalIconsPanel
verticalIconsPlugin={this}
/>,
this.htmlElement)
}
onActivation () {
this.renderComponent()
}
linkContent (profile) {
if (!profile.icon) return
if (!profile.kind) profile.kind = 'none'
this.targetProfileForChange[profile.name] = profile
this.listenOnStatus(profile)
this.renderComponent()
}
unlinkContent (profile) {
this.targetProfileForRemoval = profile
this.removeIcon(profile)
this.renderComponent()
}
listenOnStatus (profile) {
}
/**
* Remove an icon from the map
* @param {ModuleProfile} profile The profile of the module
*/
removeIcon ({ name }) {
if (this.targetProfileForChange[name]) delete this.targetProfileForChange[name]
setTimeout(() => {
this.renderComponent()
}, 150)
}
/**
* Set an icon as active
* @param {string} name Name of profile of the module to activate
*/
select (name) {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('showContent', name)
this.events.emit('showContent', name)
}
onThemeChanged (themeType) {
const invert = themeType === 'dark' ? 1 : 0
const active = this.view.querySelector('.active')
if (active) {
const image = active.querySelector('.image')
image.style.setProperty('filter', `invert(${invert})`)
}
}
/**
* Toggles the side panel for plugin
* @param {string} name Name of profile of the module to activate
*/
toggle (name) {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('toggleContent', name)
this.events.emit('toggleContent', name)
}
render () {
return this.htmlElement
}
}

116
apps/remix-ide/src/app/components/vertical-icons.tsx

@ -0,0 +1,116 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import ReactDOM from 'react-dom'
import Registry from '../state/registry'
import packageJson from '../../../../../package.json'
import { Plugin } from '@remixproject/engine'
import { EventEmitter } from 'events'
import { IconRecord, RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
import { Profile } from '@remixproject/plugin-utils'
import { timeStamp } from 'console'
const profile = {
name: 'menuicons',
displayName: 'Vertical Icons',
description: '',
version: packageJson.version,
methods: ['select', 'unlinkContent', 'linkContent'],
events: ['toggleContent', 'showContent']
}
export class VerticalIcons extends Plugin {
events: EventEmitter
htmlElement: HTMLDivElement
icons: Record<string, IconRecord> = {}
constructor () {
super(profile)
this.events = new EventEmitter()
this.htmlElement = document.createElement('div')
this.htmlElement.setAttribute('id', 'icon-panel')
}
renderComponent () {
const fixedOrder = ['filePanel', 'solidity','udapp', 'debugger', 'solidityStaticAnalysis', 'solidityUnitTesting', 'pluginManager']
const divived = Object.values(this.icons).map((value) => { return {
...value,
isRequired: fixedOrder.indexOf(value.profile.name) > -1
}}).sort((a,b) => {
return a.timestamp - b.timestamp
})
const required = divived.filter((value) => value.isRequired).sort((a,b) => {
return fixedOrder.indexOf(a.profile.name) - fixedOrder.indexOf(b.profile.name)
})
const sorted: IconRecord[] = [
...required,
...divived.filter((value) => { return !value.isRequired })
]
ReactDOM.render(
<RemixUiVerticalIconsPanel
verticalIconsPlugin={this}
icons={sorted}
/>,
this.htmlElement)
}
onActivation () {
this.renderComponent()
this.on('sidePanel', 'focusChanged', (name: string) => {
Object.keys(this.icons).map((o) => {
this.icons[o].active = false
})
this.icons[name].active = true
this.renderComponent()
})
}
async linkContent (profile: Profile) {
if (!profile.icon) return
if (!profile.kind) profile.kind = 'none'
this.icons[profile.name] = {
profile: profile,
active: false,
canbeDeactivated: await this.call('manager', 'canDeactivate', this.profile, profile),
timestamp: Date.now()
}
this.renderComponent()
}
unlinkContent (profile: Profile) {
delete this.icons[profile.name]
this.renderComponent()
}
async activateHome() {
await this.call('manager', 'activatePlugin', 'home')
await this.call('tabs', 'focus', 'home')
}
/**
* Set an icon as active
* @param {string} name Name of profile of the module to activate
*/
select (name: string) {
// TODO: Only keep `this.emit` (issue#2210)
console.log(name, this)
this.emit('showContent', name)
this.events.emit('showContent', name)
}
/**
* Toggles the side panel for plugin
* @param {string} name Name of profile of the module to activate
*/
toggle (name: string) {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('toggleContent', name)
this.events.emit('toggleContent', name)
}
render () {
return this.htmlElement
}
}

2
apps/remix-ide/src/app/editor/examples.js

@ -313,7 +313,7 @@ const deployWithEthers = `// Right click on the script name and hit "Run" to exe
const readme = `REMIX EXAMPLE PROJECT
Remix example project is present when Remix loads very first time or there are no files existing in the File Explorer.
Remix example project is present when Remix loads for the very first time or there are no files existing in the File Explorer.
It contains 3 directories:
1. 'contracts': Holds three contracts with different complexity level, denoted with number prefix in file name.

3
apps/remix-ide/src/app/panels/layout.ts

@ -80,7 +80,8 @@ export class Layout extends Plugin {
const params = queryParams.get()
if (params.minimizeterminal || params.embed) {
this.panels.terminal.minimized = true
this.event.emit('change', null)
this.event.emit('change', this.panels)
this.emit('change', this.panels)
}
if (params.minimizesidepanel || params.embed) {
this.event.emit('minimizesidepanel')

6
apps/remix-ide/src/app/plugins/remixd-handle.tsx

@ -142,11 +142,11 @@ function remixdDialog () {
</div>
<div className='mb-2 text-break'>
If you are just looking for the remixd command, here it is:
<br></br><br></br><b>${commandText}</b>
<br></br><br></br><b>{commandText}</b>
<CopyToClipboard data-id='remixdCopyCommand' content={commandText}></CopyToClipboard>
</div>
<div className='mb-2 text-break'>
When connected, a session will be started between <em>${window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>.
When connected, a session will be started between <em>{window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>.
The shared folder will be in the "File Explorers" workspace named "localhost".
<br/>Read more about other <a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#ports-usage">Remixd ports usage</a>
</div>
@ -155,7 +155,7 @@ function remixdDialog () {
</div>
<div className='mb-2 text-break'>
<h6 className="text-danger">
Before using, make sure remixd version is latest i.e. <b>${remixdVersion}</b>
Before using, make sure remixd version is latest i.e. <b>v{remixdVersion}</b>
<br></br><a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#update-to-the-latest-remixd">Read here how to update it</a>
</h6>
</div>

2
apps/remix-ide/src/app/tabs/runTab/model/recorder.js

@ -259,7 +259,7 @@ class Recorder {
cb(err)
}
)
}, () => { self.setListen(true); self.clearAll() })
}, () => { self.setListen(true) })
}
runScenario (json, continueCb, promptCb, alertCb, confirmationCb, logCallBack, cb) {

7
apps/remix-ide/src/app/tabs/theme-module.js

@ -35,15 +35,17 @@ export class ThemeModule extends Plugin {
}
this.themes = themes.reduce((acc, theme) => {
theme.url = window.location.origin + window.location.pathname + theme.url
return { ...acc, [theme.name]: theme }
return { ...acc, [theme.name.toLocaleLowerCase()]: theme }
}, {})
this._paq = _paq
let queryTheme = (new QueryParams()).get().theme
queryTheme = queryTheme && queryTheme.toLocaleLowerCase()
queryTheme = this.themes[queryTheme] ? queryTheme : null
let currentTheme = this._deps.config.get('settings/theme')
currentTheme = currentTheme && currentTheme.toLocaleLowerCase()
currentTheme = this.themes[currentTheme] ? currentTheme : null
this.currentThemeState = { queryTheme, currentTheme }
this.active = queryTheme || currentTheme || 'Dark'
this.active = queryTheme || currentTheme || 'dark'
this.forced = !!queryTheme
}
@ -82,6 +84,7 @@ export class ThemeModule extends Plugin {
* @param {string} [themeName] - The name of the theme
*/
switchTheme (themeName) {
themeName = themeName && themeName.toLocaleLowerCase()
if (themeName && !Object.keys(this.themes).includes(themeName)) {
throw new Error(`Theme ${themeName} doesn't exist`)
}

8543
apps/remix-ide/src/assets/css/themes/bootstrap-cerulean.min.css

File diff suppressed because one or more lines are too long

8671
apps/remix-ide/src/assets/css/themes/bootstrap-cyborg.min.css

File diff suppressed because one or more lines are too long

7213
apps/remix-ide/src/assets/css/themes/bootstrap-flatly.min.css

File diff suppressed because one or more lines are too long

8645
apps/remix-ide/src/assets/css/themes/bootstrap-spacelab.min.css

File diff suppressed because one or more lines are too long

51
apps/remix-ide/src/assets/css/themes/remix-black_undtds.css

@ -22,6 +22,7 @@
--light: #1f2020;
--dark: #1a1a1a;
--text: #babbcc;
--body-bg: #1a1a1a;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
@ -66,7 +67,7 @@ body {
line-height: 1.5;
color: #b3b3b3;
text-align: left;
background-color: #1a1a1a;
background-color: var(--body-bg);
}
*::-webkit-scrollbar {
width: 8px;
@ -1638,7 +1639,7 @@ pre code {
}
.form-control:focus {
color: #aaaaaa;
background-color: #1a1a1a;
background-color: var(--body-bg);
border-color: #6d7172;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
@ -1655,7 +1656,7 @@ pre code {
}
select.form-control:focus::-ms-value {
color: #aaaaaa;
background-color: #1a1a1a;
background-color: var(--body-bg);
}
.form-control-file,
.form-control-range {
@ -2361,8 +2362,8 @@ fieldset:disabled a.btn {
}
.btn-dark {
color: #d5d5d5;
background-color: #1a1a1a;
border-color: #1a1a1a;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-dark:hover {
color: #d5d5d5;
@ -2376,8 +2377,8 @@ fieldset:disabled a.btn {
.btn-dark.disabled,
.btn-dark:disabled {
color: #d5d5d5;
background-color: #1a1a1a;
border-color: #1a1a1a;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-dark:not(:disabled):not(.disabled).active,
.btn-dark:not(:disabled):not(.disabled):active,
@ -2602,13 +2603,13 @@ fieldset:disabled a.btn {
box-shadow: 0 0 0 0.2rem rgba(42, 44, 63, 0.5);
}
.btn-outline-dark {
color: #1a1a1a;
border-color: #1a1a1a;
color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark:hover {
color: #d5d5d5;
background-color: #1a1a1a;
border-color: #1a1a1a;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark.focus,
.btn-outline-dark:focus {
@ -2616,15 +2617,15 @@ fieldset:disabled a.btn {
}
.btn-outline-dark.disabled,
.btn-outline-dark:disabled {
color: #1a1a1a;
color: var(--body-bg);
background-color: transparent;
}
.btn-outline-dark:not(:disabled):not(.disabled).active,
.btn-outline-dark:not(:disabled):not(.disabled):active,
.show > .btn-outline-dark.dropdown-toggle {
color: #d5d5d5;
background-color: #1a1a1a;
border-color: #1a1a1a;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark:not(:disabled):not(.disabled).active:focus,
.btn-outline-dark:not(:disabled):not(.disabled):active:focus,
@ -3359,7 +3360,7 @@ input[type="submit"].btn-block {
}
.custom-select:focus::-ms-value {
color: #aaaaaa;
background-color: #1a1a1a;
background-color: var(--body-bg);
}
.custom-select[multiple],
.custom-select[size]:not([size="1"]) {
@ -3427,7 +3428,7 @@ input[type="submit"].btn-block {
font-weight: 400;
line-height: 1.25;
color: #aaaaaa;
background-color: #1a1a1a;
background-color: var(--body-bg);
border: 1px solid transparent;
border-radius: 2px;
}
@ -3458,15 +3459,15 @@ input[type="submit"].btn-block {
outline: 0;
}
.custom-range:focus::-webkit-slider-thumb {
box-shadow: 0 0 0 1px #1a1a1a, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range:focus::-moz-range-thumb {
box-shadow: 0 0 0 1px #1a1a1a, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range:focus::-ms-thumb {
box-shadow: 0 0 0 1px #1a1a1a, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range::-moz-focus-outer {
@ -4423,7 +4424,7 @@ a.badge-light:focus {
}
.badge-dark {
color: #d5d5d5;
background-color: #1a1a1a;
background-color: var(--body-bg);
}
a.badge-dark:focus,
a.badge-dark:hover {
@ -5040,7 +5041,7 @@ a.close.disabled {
width: 100%;
color: #d5d5d5;
pointer-events: auto;
background-color: #1a1a1a;
background-color: var(--body-bg);
background-clip: padding-box;
border: 1px solid #000000;
border-radius: 2px;
@ -5691,7 +5692,7 @@ button.bg-light:hover {
background-color: #161720 !important;
}
.bg-dark {
background-color: #1a1a1a !important;
background-color: var(--body-bg) !important;
}
a.bg-dark:focus,
a.bg-dark:hover,
@ -8711,16 +8712,16 @@ a.text-dark:hover {
/* Plugins manager */
.plugin-manager {
background: #1a1a1a;
background: var(--body-bg);
}
.plugins-header {
background-color: #1a1a1a !important;
background-color: var(--body-bg) !important;
border-bottom: 1px solid #000000 !important;
}
.plugins-list-header {
justify-content: flex-start !important;
padding: 1rem 1.5rem;
background-color: #1a1a1a !important
background-color: var(--body-bg) !important
}
.plugins-list-title {
margin: 0 0.5rem 0 0 !important;

3
apps/remix-ide/src/assets/css/themes/remix-candy_ikhg4m.css

@ -21,6 +21,7 @@
--light: #fff;
--dark: #645fb5;
--text: #11556c;
--body-bg: #d5efff;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
@ -69,7 +70,7 @@ body {
line-height: 1.5;
color: #0f7292;
text-align: left;
background-color: #d5efff;
background-color: var(--body-bg);
}
[tabindex="-1"]:focus {

51
apps/remix-ide/src/assets/css/themes/remix-dark_tvx1s2.css

@ -23,6 +23,7 @@
--dark: #222336;
--text: #babbcc;
--text-background: #222336;
--body-bg: #222336;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
@ -67,7 +68,7 @@ body {
line-height: 1.5;
color: #A2A3BD;
text-align: left;
background-color: #222336;
background-color: var(--body-bg);
}
*::-webkit-scrollbar {
width: 8px;
@ -448,7 +449,7 @@ mark {
}
.img-thumbnail {
padding: 0.25rem;
background-color: #222336;
background-color: var(--body-bg);
border: 1px solid #ddd;
border-radius: 2px;
max-width: 100%;
@ -1364,7 +1365,7 @@ pre code {
border: 0;
}
.table-striped tbody tr:nth-of-type(odd) {
background-color: #222336;
background-color: var(--body-bg);
}
.table-hover tbody tr:hover {
color: #fff;
@ -1533,7 +1534,7 @@ pre code {
}
.table .thead-light th {
color: #fff;
background-color: #222336;
background-color: var(--body-bg);
border-color: #51536b;
}
.table-dark {
@ -2353,8 +2354,8 @@ fieldset:disabled a.btn {
}
.btn-dark {
color: #fff;
background-color: #222336;
border-color: #222336;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-dark:hover {
color: #fff;
@ -2368,8 +2369,8 @@ fieldset:disabled a.btn {
.btn-dark.disabled,
.btn-dark:disabled {
color: #fff;
background-color: #222336;
border-color: #222336;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-dark:not(:disabled):not(.disabled).active,
.btn-dark:not(:disabled):not(.disabled):active,
@ -2594,13 +2595,13 @@ fieldset:disabled a.btn {
box-shadow: 0 0 0 0.2rem rgba(42, 44, 63, 0.5);
}
.btn-outline-dark {
color: #222336;
border-color: #222336;
color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark:hover {
color: #fff;
background-color: #222336;
border-color: #222336;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark.focus,
.btn-outline-dark:focus {
@ -2608,15 +2609,15 @@ fieldset:disabled a.btn {
}
.btn-outline-dark.disabled,
.btn-outline-dark:disabled {
color: #222336;
color: var(--body-bg);
background-color: transparent;
}
.btn-outline-dark:not(:disabled):not(.disabled).active,
.btn-outline-dark:not(:disabled):not(.disabled):active,
.show > .btn-outline-dark.dropdown-toggle {
color: #fff;
background-color: #222336;
border-color: #222336;
background-color: var(--body-bg);
border-color: var(--body-bg);
}
.btn-outline-dark:not(:disabled):not(.disabled).active:focus,
.btn-outline-dark:not(:disabled):not(.disabled):active:focus,
@ -3454,15 +3455,15 @@ input[type="submit"].btn-block {
outline: 0;
}
.custom-range:focus::-webkit-slider-thumb {
box-shadow: 0 0 0 1px #222336, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range:focus::-moz-range-thumb {
box-shadow: 0 0 0 1px #222336, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range:focus::-ms-thumb {
box-shadow: 0 0 0 1px #222336, inset 0 1px 1px rgba(0, 0, 0, 0.075),
box-shadow: 0 0 0 1px var(--body-bg), inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 0 3px rgba(0, 122, 166, 0.25);
}
.custom-range::-moz-focus-outer {
@ -3633,7 +3634,7 @@ input[type="submit"].btn-block {
.nav-tabs .nav-item.show .nav-link,
.nav-tabs .nav-link.active {
color: #fff;
background-color: #222336;
background-color: var(--body-bg);
border-color: #3f4455;
}
.nav-tabs .dropdown-menu {
@ -4419,7 +4420,7 @@ a.badge-light:focus {
}
.badge-dark {
color: #fff;
background-color: #222336;
background-color: var(--body-bg);
}
a.badge-dark:focus,
a.badge-dark:hover {
@ -5036,7 +5037,7 @@ a.close.disabled {
width: 100%;
color: #fff;
pointer-events: auto;
background-color: #222336;
background-color: var(--body-bg);
background-clip: padding-box;
border: 1px solid #2c3244;
border-radius: 2px;
@ -5687,7 +5688,7 @@ button.bg-light:hover {
background-color: #161720 !important;
}
.bg-dark {
background-color: #222336 !important;
background-color: var(--body-bg) !important;
}
a.bg-dark:focus,
a.bg-dark:hover,
@ -8707,16 +8708,16 @@ a.text-dark:hover {
/* Plugins manager */
.plugin-manager {
background: #222336;
background: var(--body-bg);
}
.plugins-header {
background-color: #222336 !important;
background-color: var(--body-bg) !important;
border-bottom: 1px solid #2C3244 !important;
}
.plugins-list-header {
justify-content: flex-start !important;
padding: 1rem 1.5rem;
background-color: #222336 !important
background-color: var(--body-bg) !important
}
.plugins-list-title {
margin: 0 0.5rem 0 0 !important;

20
apps/remix-ide/src/assets/css/themes/remix-light_powaqg.css

@ -21,6 +21,7 @@
--light: #fff;
--dark: #f8fafe;
--text: #3b445e;
--body-bg: #eef1f6;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
@ -69,7 +70,7 @@ body {
line-height: 1.5;
color: #2e3145;
text-align: left;
background-color: #eef1f6;
background-color: var(--body-bg);
}
[tabindex="-1"]:focus {
@ -517,7 +518,7 @@ mark,
.img-thumbnail {
padding: 0.25rem;
background-color: #eef1f6;
background-color: var(--body-bg);
border: 1px solid #dee2e6;
border-radius: 0.25rem;
max-width: 100%;
@ -1673,7 +1674,7 @@ pre code {
.table-active,
.table-active > th,
.table-active > td {
background-color: #eef1f6;
background-color: var(--body-bg);
}
.table-hover .table-active:hover {
@ -3767,13 +3768,13 @@ input[type="button"].btn-block {
outline: none;
}
.custom-range:focus::-webkit-slider-thumb {
box-shadow: 0 0 0 1px #eef1f6, 0px 0px 5px #00bbff;
box-shadow: 0 0 0 1px var(--body-bg), 0px 0px 5px #00bbff;
}
.custom-range:focus::-moz-range-thumb {
box-shadow: 0 0 0 1px #eef1f6, 0px 0px 5px #00bbff;
box-shadow: 0 0 0 1px var(--body-bg), 0px 0px 5px #00bbff;
}
.custom-range:focus::-ms-thumb {
box-shadow: 0 0 0 1px #eef1f6, 0px 0px 5px #00bbff;
box-shadow: 0 0 0 1px var(--body-bg), 0px 0px 5px #00bbff;
}
.custom-range::-moz-focus-outer {
border: 0;
@ -5482,7 +5483,7 @@ a.close.disabled {
flex-direction: column;
width: 100%;
pointer-events: auto;
background-color: #eef1f6;
background-color: var(--body-bg);
background-clip: padding-box;
border: 1px solid #dfe1ea;
border-radius: 0.3rem;
@ -5496,7 +5497,7 @@ a.close.disabled {
z-index: 1040;
width: 100vw;
height: 100vh;
background-color: #eef1f6;
background-color: var(--body-bg);
}
.modal-backdrop.fade {
opacity: 0;
@ -9494,8 +9495,9 @@ a.text-dark:focus {
border: none !important;
}
.remix-bg-opacity {
background: rgba(248, 250, 254, 0.80) !important;
background: rgba(248, 250, 254, 0.80) !important;
}
.plugins-list-header {
background: transparent !important;
}

3
apps/remix-ide/src/assets/css/themes/remix-midcentury_hrzph3.css

@ -21,6 +21,7 @@
--light: #eeede9;
--dark: #01414E;
--text: #11556c;
--body-bg: #DBE2E0;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
@ -69,7 +70,7 @@ body {
line-height: 1.5;
color: #062809;
text-align: left;
background-color: #DBE2E0;
background-color: var(--body-bg);
}
[tabindex="-1"]:focus {

BIN
apps/remix-ide/src/assets/img/cairoLogo.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

2
apps/remix-ide/src/blockchain/blockchain.js

@ -353,7 +353,7 @@ export class Blockchain extends Plugin {
if (network.name === 'VM') return
this.call('terminal', 'logHtml',
(<a href={etherScanLink(network.name, txhash)} target="_blank">
open in etherscan
view on etherscan
</a>))
})
})

14
apps/remix-ide/src/remixAppManager.js

@ -50,6 +50,10 @@ export class RemixAppManager extends PluginManager {
return isNative(from.name)
}
async canDeactivate(from,to) {
return this.canDeactivatePlugin(from, to)
}
async deactivatePlugin (name) {
const [to, from] = [
await this.getProfile(name),
@ -145,16 +149,6 @@ export class RemixAppManager extends PluginManager {
pattern: [],
sticky: true
})
await this.call('filePanel', 'registerContextMenuItem', {
id: 'optimism-compiler',
name: 'compileCustomAction',
label: 'Compile with Optimism',
type: [],
extension: ['.sol'],
path: [],
pattern: [],
sticky: true
})
}
}

2
apps/remix-ide/src/walkthroughService.js

@ -31,7 +31,7 @@ export class WalkthroughService extends Plugin {
position: 'right'
},
{
element: document.querySelector('#compileIcons'),
element: document.querySelector('#verticalIconsKindsolidity'),
title: 'Solidity Compiler',
intro: 'Having selected a .sol file in the File Explorers (the icon above), compile it with the Solidity Compiler.',
tooltipClass: 'bg-light text-dark',

5
libs/remix-core-plugin/src/lib/compiler-artefacts.ts

@ -48,11 +48,6 @@ export class CompilerArtefacts extends Plugin {
saveCompilationPerFileResult(file, source, languageVersion, data)
})
this.on('optimism-compiler', 'compilationFinished', (file, source, languageVersion, data) => {
this.compilersArtefacts.__last = new CompilerAbstract(languageVersion, data, source)
saveCompilationPerFileResult(file, source, languageVersion, data)
})
this.on('solidityUnitTesting', 'compilationFinished', (file, source, languageVersion, data) => {
this.compilersArtefacts.__last = new CompilerAbstract(languageVersion, data, source)
saveCompilationPerFileResult(file, source, languageVersion, data)

3
libs/remix-core-plugin/src/lib/compiler-content-imports.ts

@ -35,7 +35,8 @@ export class CompilerImports extends Plugin {
isExternalUrl (url) {
const handlers = this.urlResolver.getHandlers()
return handlers.some(handler => handler.match(url))
// we filter out "npm" because this will be recognized as internal url although it's not the case.
return handlers.filter((handler) => handler.type !== 'npm').some(handler => handler.match(url))
}
/**

2
libs/remix-lib/src/execution/txRunnerWeb3.ts

@ -153,7 +153,7 @@ async function tryTillReceiptAvailable (txhash, web3) {
async function tryTillTxAvailable (txhash, web3) {
try {
const tx = await web3.eth.getTransaction(txhash)
if (tx) return tx
if (tx && tx.blockHash) return tx
} catch (e) {}
return await tryTillTxAvailable(txhash, web3)
}

43
libs/remix-tests/src/compiler.ts

@ -1,6 +1,7 @@
import fs from './fileSystem'
import async from 'async'
import path from 'path'
import deepequal from 'deep-equal'
import Log from './logger'
import { Compiler as RemixCompiler } from '@remix-project/remix-solidity'
import { SrcIfc, CompilerConfiguration, CompilationErrors } from './types'
@ -46,7 +47,6 @@ function isRemixTestFile (path: string) {
function processFile (filePath: string, sources: SrcIfc, isRoot = false) {
const importRegEx = /import ['"](.+?)['"];/g
let group: RegExpExecArray| null = null
const isFileAlreadyInSources: boolean = Object.keys(sources).includes(filePath)
// Return if file is a remix test file or already processed
@ -61,14 +61,6 @@ function processFile (filePath: string, sources: SrcIfc, isRoot = false) {
content = includeTestLibs.concat(content)
}
sources[filePath] = { content }
importRegEx.exec('') // Resetting state of RegEx
// Process each 'import' in file content
while ((group = importRegEx.exec(content))) {
const importedFile: string = group[1]
const importedFilePath: string = path.join(path.dirname(filePath), importedFile)
processFile(importedFilePath, sources)
}
}
const userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
@ -122,7 +114,13 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts
} finally {