pull/5370/head
bunsenstraat 3 years ago
commit 52943b412e
  1. 70
      apps/remix-ide-e2e/src/tests/editor.test.ts
  2. 4
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  3. 5
      apps/remix-ide/src/app.js
  4. 194
      apps/remix-ide/src/app/editor/contextView.js
  5. 5
      apps/remix-ide/src/app/editor/editor.js
  6. 18
      apps/remix-ide/src/app/panels/main-view.js
  7. 1
      libs/remix-core-plugin/src/index.ts
  8. 6
      libs/remix-core-plugin/src/lib/compiler-artefacts.ts
  9. 100
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  10. 4
      libs/remix-ui/editor-context-view/.babelrc
  11. 19
      libs/remix-ui/editor-context-view/.eslintrc
  12. 7
      libs/remix-ui/editor-context-view/README.md
  13. 1
      libs/remix-ui/editor-context-view/src/index.ts
  14. 20
      libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.css
  15. 191
      libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx
  16. 16
      libs/remix-ui/editor-context-view/tsconfig.json
  17. 13
      libs/remix-ui/editor-context-view/tsconfig.lib.json
  18. 5
      libs/remix-ui/editor/src/lib/remix-ui-editor.css
  19. 46
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  20. 3
      nx.json
  21. 3
      tsconfig.base.json
  22. 100
      workspace.json

@ -6,10 +6,10 @@ import init from '../helpers/init'
module.exports = { module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done) init(browser, done, 'http://127.0.0.1:8080', true)
}, },
'Should zoom in editor ': function (browser: NightwatchBrowser) { 'Should zoom in editor #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]') browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]')
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
@ -22,7 +22,7 @@ module.exports = {
.checkElementStyle('.view-lines', 'font-size', '16px') .checkElementStyle('.view-lines', 'font-size', '16px')
}, },
'Should zoom out editor ': function (browser: NightwatchBrowser) { 'Should zoom out editor #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.checkElementStyle('.view-lines', 'font-size', '16px') .checkElementStyle('.view-lines', 'font-size', '16px')
.click('*[data-id="tabProxyZoomOut"]') .click('*[data-id="tabProxyZoomOut"]')
@ -30,7 +30,7 @@ module.exports = {
.checkElementStyle('.view-lines', 'font-size', '14px') .checkElementStyle('.view-lines', 'font-size', '14px')
}, },
'Should display compile error in editor ': function (browser: NightwatchBrowser) { 'Should display compile error in editor #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.setEditorValue(storageContractWithError + 'error') .setEditorValue(storageContractWithError + 'error')
.pause(2000) .pause(2000)
@ -42,7 +42,7 @@ module.exports = {
.checkAnnotations('fa-exclamation-square', 29) // error .checkAnnotations('fa-exclamation-square', 29) // error
}, },
'Should minimize and maximize codeblock in editor ': '' + function (browser: NightwatchBrowser) { 'Should minimize and maximize codeblock in editor #group1': '' + function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.waitForElementVisible('.ace_open') .waitForElementVisible('.ace_open')
.click('.ace_start:nth-of-type(1)') .click('.ace_start:nth-of-type(1)')
@ -51,7 +51,7 @@ module.exports = {
.waitForElementVisible('.ace_open') .waitForElementVisible('.ace_open')
}, },
'Should add breakpoint to editor ': function (browser: NightwatchBrowser) { 'Should add breakpoint to editor #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.waitForElementNotPresent('.margin-view-overlays .fa-circle') .waitForElementNotPresent('.margin-view-overlays .fa-circle')
.execute(() => { .execute(() => {
@ -60,7 +60,7 @@ module.exports = {
.waitForElementVisible('.margin-view-overlays .fa-circle') .waitForElementVisible('.margin-view-overlays .fa-circle')
}, },
'Should load syntax highlighter for ace light theme': '' + function (browser: NightwatchBrowser) { 'Should load syntax highlighter for ace light theme #group1': '' + function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#editorView') browser.waitForElementVisible('#editorView')
.checkElementStyle('.ace_keyword', 'color', aceThemes.light.keyword) .checkElementStyle('.ace_keyword', 'color', aceThemes.light.keyword)
.checkElementStyle('.ace_comment.ace_doc', 'color', aceThemes.light.comment) .checkElementStyle('.ace_comment.ace_doc', 'color', aceThemes.light.comment)
@ -68,7 +68,7 @@ module.exports = {
.checkElementStyle('.ace_variable', 'color', aceThemes.light.variable) .checkElementStyle('.ace_variable', 'color', aceThemes.light.variable)
}, },
'Should load syntax highlighter for ace dark theme': '' + function (browser: NightwatchBrowser) { 'Should load syntax highlighter for ace dark theme #group1': '' + function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="verticalIconsKindsettings"]') browser.waitForElementVisible('*[data-id="verticalIconsKindsettings"]')
.click('*[data-id="verticalIconsKindsettings"]') .click('*[data-id="verticalIconsKindsettings"]')
.waitForElementVisible('*[data-id="settingsTabThemeLabelDark"]') .waitForElementVisible('*[data-id="settingsTabThemeLabelDark"]')
@ -83,7 +83,7 @@ module.exports = {
*/ */
}, },
'Should highlight source code ': function (browser: NightwatchBrowser) { 'Should highlight source code #group1': function (browser: NightwatchBrowser) {
// include all files here because switching between plugins in side-panel removes highlight // include all files here because switching between plugins in side-panel removes highlight
browser browser
.addFile('sourcehighlight.js', sourcehighlightScript) .addFile('sourcehighlight.js', sourcehighlightScript)
@ -101,7 +101,7 @@ module.exports = {
.checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)') .checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)')
}, },
'Should remove 1 highlight from source code': '' + function (browser: NightwatchBrowser) { 'Should remove 1 highlight from source code #group1': '' + function (browser: NightwatchBrowser) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]') browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]') .click('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.pause(2000) .pause(2000)
@ -115,7 +115,7 @@ module.exports = {
.checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)') .checkElementStyle('.highlightLine51', 'background-color', 'rgb(52, 152, 219)')
}, },
'Should remove all highlights from source code ': function (browser: NightwatchBrowser) { 'Should remove all highlights from source code #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]') browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]') .click('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.pause(2000) .pause(2000)
@ -126,6 +126,54 @@ module.exports = {
.waitForElementNotPresent('.highlightLine33', 60000) .waitForElementNotPresent('.highlightLine33', 60000)
.waitForElementNotPresent('.highlightLine41', 60000) .waitForElementNotPresent('.highlightLine41', 60000)
.waitForElementNotPresent('.highlightLine51', 60000) .waitForElementNotPresent('.highlightLine51', 60000)
},
'Should display the context view #group2': function (browser: NightwatchBrowser) {
browser
.openFile('contracts')
.openFile('contracts/1_Storage.sol')
.waitForElementVisible('#editorView')
.setEditorValue(storageContractWithError)
.pause(2000)
.execute(() => {
(document.getElementById('editorView') as any).gotoLine(17, 16)
}, [], () => {})
.waitForElementVisible('.contextview')
.waitForElementContainsText('.contextview .type', 'FunctionDefinition')
.waitForElementContainsText('.contextview .name', 'store')
.execute(() => {
(document.getElementById('editorView') as any).gotoLine(18, 12)
}, [], () => {})
.waitForElementContainsText('.contextview .type', 'uint256')
.waitForElementContainsText('.contextview .name', 'number')
.click('.contextview [data-action="previous"]') // declaration
.execute(() => {
return (document.getElementById('editorView') as any).getCursorPosition()
}, [], (result) => {
console.log('result', result)
browser.assert.equal(result.value, '180')
})
.click('.contextview [data-action="next"]') // back to the initial state
.execute(() => {
return (document.getElementById('editorView') as any).getCursorPosition()
}, [], (result) => {
console.log('result', result)
browser.assert.equal(result.value, '323')
})
.click('.contextview [data-action="next"]') // next reference
.execute(() => {
return (document.getElementById('editorView') as any).getCursorPosition()
}, [], (result) => {
console.log('result', result)
browser.assert.equal(result.value, '489')
})
.click('.contextview [data-action="gotoref"]') // back to the declaration
.execute(() => {
return (document.getElementById('editorView') as any).getCursorPosition()
}, [], (result) => {
console.log('result', result)
browser.assert.equal(result.value, '180')
})
.end() .end()
} }
} }

@ -4,7 +4,7 @@ import init from '../helpers/init'
import * as path from 'path' import * as path from 'path'
const testData = { const testData = {
testFile1: path.resolve(__dirname + '/editor.spec.js'), // eslint-disable-line testFile1: path.resolve(__dirname + '/editor.test.js'), // eslint-disable-line
testFile2: path.resolve(__dirname + '/fileExplorer.test.js'), // eslint-disable-line testFile2: path.resolve(__dirname + '/fileExplorer.test.js'), // eslint-disable-line
testFile3: path.resolve(__dirname + '/generalSettings.test.js') // eslint-disable-line testFile3: path.resolve(__dirname + '/generalSettings.test.js') // eslint-disable-line
} }
@ -105,7 +105,7 @@ module.exports = {
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3)
.waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.spec.js"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemfileExplorer.test.js"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemfileExplorer.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemgeneralSettings.test.js"]') .waitForElementVisible('[data-id="treeViewLitreeViewItemgeneralSettings.test.js"]')
.end() .end()

@ -15,7 +15,7 @@ import { FramingService } from './framingService'
import { WalkthroughService } from './walkthroughService' import { WalkthroughService } from './walkthroughService'
import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports } from '@remix-project/core-plugin' import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, EditorContextListener } from '@remix-project/core-plugin'
import migrateFileSystem from './migrateFileSystem' import migrateFileSystem from './migrateFileSystem'
@ -48,7 +48,6 @@ const TestTab = require('./app/tabs/test-tab')
const FilePanel = require('./app/panels/file-panel') const FilePanel = require('./app/panels/file-panel')
const Editor = require('./app/editor/editor') const Editor = require('./app/editor/editor')
const Terminal = require('./app/panels/terminal') const Terminal = require('./app/panels/terminal')
const ContextualListener = require('./app/editor/contextualListener')
class AppComponent { class AppComponent {
constructor (api = {}, events = {}, opts = {}) { constructor (api = {}, events = {}, opts = {}) {
@ -156,7 +155,7 @@ class AppComponent {
} }
} }
) )
const contextualListener = new ContextualListener({ editor }) const contextualListener = new EditorContextListener()
self.engine.register([ self.engine.register([
blockchain, blockchain,

@ -1,194 +0,0 @@
'use strict'
import { sourceMappingDecoder } from '@remix-project/remix-debug'
const yo = require('yo-yo')
const globalRegistry = require('../../global/registry')
const css = require('./styles/contextView-styles')
/*
Display information about the current focused code:
- if it's a reference, display information about the declaration
- jump to the declaration
- number of references
- rename declaration/references
*/
class ContextView {
constructor (opts, localRegistry) {
this._components = {}
this._components.registry = localRegistry || globalRegistry
this.contextualListener = opts.contextualListener
this.editor = opts.editor
this._deps = {
compilersArtefacts: this._components.registry.get('compilersartefacts').api,
offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api,
config: this._components.registry.get('config').api,
fileManager: this._components.registry.get('filemanager').api
}
this._view = null
this._nodes = null
this._current = null
this.sourceMappingDecoder = sourceMappingDecoder
this.previousElement = null
this.contextualListener.event.register('contextChanged', nodes => {
this.show()
this._nodes = nodes
this.update()
})
this.contextualListener.event.register('stopHighlighting', () => {
})
}
render () {
const view = yo`
<div class="${css.contextview} ${css.contextviewcontainer} bg-light text-dark border-0">
<div class=${css.container}>
${this._renderTarget()}
</div>
</div>`
if (!this._view) {
this._view = view
}
return view
}
hide () {
if (this._view) {
this._view.style.display = 'none'
}
}
show () {
if (this._view) {
this._view.style.display = 'block'
}
}
update () {
if (this._view) {
yo.update(this._view, this.render())
}
}
_renderTarget () {
let last
const previous = this._current
if (this._nodes && this._nodes.length) {
last = this._nodes[this._nodes.length - 1]
if (isDefinition(last)) {
this._current = last
} else {
const target = this.contextualListener.declarationOf(last)
if (target) {
this._current = target
} else {
this._current = null
}
}
}
if (!this._current || !previous || previous.id !== this._current.id || (this.previousElement && !this.previousElement.children.length)) {
this.previousElement = this._render(this._current, last)
}
return this.previousElement
}
_jumpToInternal (position) {
const jumpToLine = (lineColumn) => {
if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) {
this.editor.gotoLine(lineColumn.start.line, lineColumn.end.column + 1)
}
}
const lastCompilationResult = this._deps.compilersArtefacts.__last
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const lineColumn = this._deps.offsetToLineColumnConverter.offsetToLineColumn(
position,
position.file,
lastCompilationResult.getSourceCode().sources,
lastCompilationResult.getAsts())
const filename = lastCompilationResult.getSourceName(position.file)
// TODO: refactor with rendererAPI.errorClick
if (filename !== this._deps.config.get('currentFile')) {
const provider = this._deps.fileManager.fileProviderOf(filename)
if (provider) {
provider.exists(filename).then(exist => {
this._deps.fileManager.open(filename)
jumpToLine(lineColumn)
}).catch(error => {
if (error) return console.log(error)
})
}
} else {
jumpToLine(lineColumn)
}
}
}
_render (node, nodeAtCursorPosition) {
if (!node) return yo`<div></div>`
let references = this.contextualListener.referencesOf(node)
const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType
references = `${references ? references.length : '0'} reference(s)`
let ref = 0
const nodes = this.contextualListener.getActiveHighlights()
for (const k in nodes) {
if (nodeAtCursorPosition.id === nodes[k].nodeId) {
ref = k
break
}
}
// JUMP BETWEEN REFERENCES
const jump = (e) => {
e.target.dataset.action === 'next' ? ref++ : ref--
if (ref < 0) ref = nodes.length - 1
if (ref >= nodes.length) ref = 0
this._jumpToInternal(nodes[ref].position)
}
const jumpTo = () => {
if (node && node.src) {
const position = this.sourceMappingDecoder.decode(node.src)
if (position) {
this._jumpToInternal(position)
}
}
}
const showGasEstimation = () => {
if (node.nodeType === 'FunctionDefinition') {
const result = this.contextualListener.gasEstimation(node)
const executionCost = ' Execution cost: ' + result.executionCost + ' gas'
const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas'
const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}`
return yo`
<div class=${css.gasEstimation}>
<i class="fas fa-gas-pump ${css.gasStationIcon}" title='Gas estimation'></i>
<span>${estimatedGas}</span>
</div>
`
}
}
return yo`
<div class=${css.line}>${showGasEstimation()}
<div title=${type} class=${css.type}>${type}</div>
<div title=${node.name} class=${css.name}>${node.name}</div>
<i class="fas fa-share ${css.jump}" aria-hidden="true" onclick=${jumpTo}></i>
<span class=${css.referencesnb}>${references}</span>
<i data-action='previous' class="fas fa-chevron-up ${css.jump}" aria-hidden="true" onclick=${jump}></i>
<i data-action='next' class="fas fa-chevron-down ${css.jump}" aria-hidden="true" onclick=${jump}></i>
</div>
`
}
}
function isDefinition (node) {
return node.nodeType === 'ContractDefinition' ||
node.nodeType === 'FunctionDefinition' ||
node.nodeType === 'ModifierDefinition' ||
node.nodeType === 'VariableDeclaration' ||
node.nodeType === 'StructDefinition' ||
node.nodeType === 'EventDefinition'
}
module.exports = ContextView

@ -12,7 +12,7 @@ const profile = {
name: 'editor', name: 'editor',
description: 'service - editor', description: 'service - editor',
version: packageJson.version, version: packageJson.version,
methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine'] methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine', 'getCursorPosition']
} }
class Editor extends Plugin { class Editor extends Plugin {
@ -75,7 +75,8 @@ class Editor extends Plugin {
this._onChange(this.currentFile) this._onChange(this.currentFile)
} }
} }
this.el.gotoLine = (line) => this.gotoLine(line, 0) this.el.gotoLine = (line, column) => this.gotoLine(line, column || 0)
this.el.getCursorPosition = () => this.getCursorPosition()
return this.el return this.el
} }

@ -4,8 +4,6 @@ var EventManager = require('../../lib/events')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
var { TabProxy } = require('./tab-proxy.js') var { TabProxy } = require('./tab-proxy.js')
var ContextView = require('../editor/contextView')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var css = csjs` var css = csjs`
@ -14,7 +12,7 @@ var css = csjs`
flex-direction : column; flex-direction : column;
height : 100%; height : 100%;
width : 100%; width : 100%;
} }
` `
// @todo(#650) Extract this into two classes: MainPanel (TabsProxy + Iframe/Editor) & BottomPanel (Terminal) // @todo(#650) Extract this into two classes: MainPanel (TabsProxy + Iframe/Editor) & BottomPanel (Terminal)
@ -25,12 +23,12 @@ export class MainView {
self._view = {} self._view = {}
self._components = {} self._components = {}
self._components.registry = globalRegistry self._components.registry = globalRegistry
self.contextualListener = contextualListener
self.editor = editor self.editor = editor
self.fileManager = fileManager self.fileManager = fileManager
self.mainPanel = mainPanel self.mainPanel = mainPanel
self.txListener = globalRegistry.get('txlistener').api self.txListener = globalRegistry.get('txlistener').api
self._components.terminal = terminal self._components.terminal = terminal
self._components.contextualListener = contextualListener
this.appManager = appManager this.appManager = appManager
this.init() this.init()
} }
@ -39,7 +37,6 @@ export class MainView {
this.fileManager.unselectCurrentFile() this.fileManager.unselectCurrentFile()
this.mainPanel.showContent(name) this.mainPanel.showContent(name)
this._view.editor.style.display = 'none' this._view.editor.style.display = 'none'
this._components.contextView.hide()
this._view.mainPanel.style.display = 'block' this._view.mainPanel.style.display = 'block'
} }
@ -63,19 +60,16 @@ export class MainView {
// we check upstream for "fileChanged" // we check upstream for "fileChanged"
self._view.editor.style.display = 'block' self._view.editor.style.display = 'block'
self._view.mainPanel.style.display = 'none' self._view.mainPanel.style.display = 'none'
self._components.contextView.show()
}) })
self.tabProxy.event.on('openFile', (file) => { self.tabProxy.event.on('openFile', (file) => {
self._view.editor.style.display = 'block' self._view.editor.style.display = 'block'
self._view.mainPanel.style.display = 'none' self._view.mainPanel.style.display = 'none'
self._components.contextView.show()
}) })
self.tabProxy.event.on('closeFile', (file) => { self.tabProxy.event.on('closeFile', (file) => {
}) })
self.tabProxy.event.on('switchApp', self.showApp.bind(self)) self.tabProxy.event.on('switchApp', self.showApp.bind(self))
self.tabProxy.event.on('closeApp', (name) => { self.tabProxy.event.on('closeApp', (name) => {
self._view.editor.style.display = 'block' self._view.editor.style.display = 'block'
self._components.contextView.show()
self._view.mainPanel.style.display = 'none' self._view.mainPanel.style.display = 'none'
}) })
self.tabProxy.event.on('tabCountChanged', (count) => { self.tabProxy.event.on('tabCountChanged', (count) => {
@ -90,10 +84,6 @@ export class MainView {
} }
} }
const contextView = new ContextView({ contextualListener: self._components.contextualListener, editor: self.editor })
self._components.contextView = contextView
self._components.terminal.event.register('resize', delta => self._adjustLayout('top', delta)) self._components.terminal.event.register('resize', delta => self._adjustLayout('top', delta))
if (self.txListener) { if (self.txListener) {
self._components.terminal.event.register('listenOnNetWork', (listenOnNetWork) => { self._components.terminal.event.register('listenOnNetWork', (listenOnNetWork) => {
@ -181,15 +171,17 @@ export class MainView {
self._view.editor.style.display = 'none' self._view.editor.style.display = 'none'
self._view.mainPanel = self.mainPanel.render() self._view.mainPanel = self.mainPanel.render()
self._view.terminal = self._components.terminal.render() self._view.terminal = self._components.terminal.render()
self._view.mainview = yo` self._view.mainview = yo`
<div class=${css.mainview}> <div class=${css.mainview}>
${self.tabProxy.renderTabsbar()} ${self.tabProxy.renderTabsbar()}
${self._view.editor} ${self._view.editor}
${self._view.mainPanel} ${self._view.mainPanel}
${self._components.contextView.render()} <div class="${css.contextview} contextview"></div>
${self._view.terminal} ${self._view.terminal}
</div> </div>
` `
// INIT // INIT
self._adjustLayout('top', self.data._layout.top.offset) self._adjustLayout('top', self.data._layout.top.offset)

@ -3,3 +3,4 @@ export { CompilerMetadata } from './lib/compiler-metadata'
export { FetchAndCompile } from './lib/compiler-fetch-and-compile' export { FetchAndCompile } from './lib/compiler-fetch-and-compile'
export { CompilerImports } from './lib/compiler-content-imports' export { CompilerImports } from './lib/compiler-content-imports'
export { CompilerArtefacts } from './lib/compiler-artefacts' export { CompilerArtefacts } from './lib/compiler-artefacts'
export { EditorContextListener } from './lib/editor-context-listener'

@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity'
const profile = { const profile = {
name: 'compilerArtefacts', name: 'compilerArtefacts',
methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas'], methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas', 'getLastCompilationResult'],
events: [], events: [],
version: '0.0.1' version: '0.0.1'
} }
@ -59,6 +59,10 @@ export class CompilerArtefacts extends Plugin {
}) })
} }
getLastCompilationResult () {
return this.compilersArtefacts.__last
}
getAllContractDatas () { getAllContractDatas () {
const contractsData = {} const contractsData = {}
Object.keys(this.compilersArtefactsPerFile).map((targetFile) => { Object.keys(this.compilersArtefactsPerFile).map((targetFile) => {

@ -1,47 +1,48 @@
'use strict' 'use strict'
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import { sourceMappingDecoder } from '@remix-project/remix-debug' import { sourceMappingDecoder } from '@remix-project/remix-debug'
const { AstWalker } = require('@remix-project/remix-astwalker') const { AstWalker } = require('@remix-project/remix-astwalker')
const EventManager = require('../../lib/events')
const globalRegistry = require('../../global/registry')
const profile = { const profile = {
name: 'contextualListener', name: 'contextualListener',
methods: [], methods: ['referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf'],
events: [], events: [],
version: packageJson.version version: '0.0.1'
} }
/* /*
trigger contextChanged(nodes) trigger contextChanged(nodes)
*/ */
class ContextualListener extends Plugin { export class EditorContextListener extends Plugin {
constructor (opts) { _index: any
_activeHighlights: Array<any>
astWalker: any
currentPosition: any
currentFile: String
nodes: Array<any>
results: any
estimationObj: any
creationCost: any
codeDepositCost: any
contract: any
activated: boolean
constructor () {
super(profile) super(profile)
this.event = new EventManager() this.activated = false
this._components = {}
this._components.registry = globalRegistry
this.editor = opts.editor
this.pluginManager = opts.pluginManager
this._deps = {
compilersArtefacts: this._components.registry.get('compilersartefacts').api,
config: this._components.registry.get('config').api,
offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api
}
this._index = { this._index = {
Declarations: {}, Declarations: {},
FlatReferences: {} FlatReferences: {}
} }
this._activeHighlights = [] this._activeHighlights = []
this.editor.event.register('contentChanged', () => { this._stopHighlighting() })
this.sourceMappingDecoder = sourceMappingDecoder
this.astWalker = new AstWalker() this.astWalker = new AstWalker()
} }
onActivation () { onActivation () {
this.on('editor', 'contentChanged', () => { this._stopHighlighting() })
this.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => { this.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => {
if (languageVersion.indexOf('soljson') !== 0) return if (languageVersion.indexOf('soljson') !== 0) return
this._stopHighlighting() this._stopHighlighting()
@ -52,11 +53,18 @@ class ContextualListener extends Plugin {
this._buildIndex(data, source) this._buildIndex(data, source)
}) })
setInterval(() => { setInterval(async () => {
if (this._deps.compilersArtefacts.__last && this._deps.compilersArtefacts.__last.languageversion.indexOf('soljson') === 0) { const compilationResult = await this.call('compilerArtefacts', 'getLastCompilationResult')
this._highlightItems(this.editor.getCursorPosition(), this._deps.compilersArtefacts.__last, this._deps.config.get('currentFile')) if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
this._highlightItems(
await this.call('editor', 'getCursorPosition'),
compilationResult,
await this.call('fileManager', 'file')
)
} }
}, 1000) }, 1000)
this.activated = true
} }
getActiveHighlights () { getActiveHighlights () {
@ -74,7 +82,7 @@ class ContextualListener extends Plugin {
return this._index.Declarations[node.id] return this._index.Declarations[node.id]
} }
_highlightItems (cursorPosition, compilationResult, file) { async _highlightItems (cursorPosition, compilationResult, file) {
if (this.currentPosition === cursorPosition) return if (this.currentPosition === cursorPosition) return
if (this.currentFile !== file) { if (this.currentFile !== file) {
this.currentFile = file this.currentFile = file
@ -85,12 +93,12 @@ class ContextualListener extends Plugin {
this.currentPosition = cursorPosition this.currentPosition = cursorPosition
this.currentFile = file this.currentFile = file
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) { if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) {
const nodes = this.sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) const nodes = sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file])
this.nodes = nodes this.nodes = nodes
if (nodes && nodes.length && nodes[nodes.length - 1]) { if (nodes && nodes.length && nodes[nodes.length - 1]) {
this._highlightExpressions(nodes[nodes.length - 1], compilationResult) await this._highlightExpressions(nodes[nodes.length - 1], compilationResult)
} }
this.event.trigger('contextChanged', [nodes]) this.emit('contextChanged', nodes)
} }
} }
@ -111,21 +119,19 @@ class ContextualListener extends Plugin {
} }
} }
_highlight (node, compilationResult) { async _highlight (node, compilationResult) {
if (!node) return if (!node) return
const position = this.sourceMappingDecoder.decode(node.src) const position = sourceMappingDecoder.decode(node.src)
const eventId = this._highlightInternal(position, node) await this._highlightInternal(position, node, compilationResult)
const lastCompilationResult = this._deps.compilersArtefacts.__last if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
if (eventId && lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0) { this._activeHighlights.push({ position, fileTarget: compilationResult.getSourceName(position.file), nodeId: node.id })
this._activeHighlights.push({ eventId, position, fileTarget: lastCompilationResult.getSourceName(position.file), nodeId: node.id })
} }
} }
_highlightInternal (position, node) { async _highlightInternal (position, node, compilationResult) {
if (node.nodeType === 'Block') return if (node.nodeType === 'Block') return
const lastCompilationResult = this._deps.compilersArtefacts.__last if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0) { let lineColumn = await this.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, position.file, compilationResult.getSourceCode().sources, compilationResult.getAsts())
let lineColumn = this._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, lastCompilationResult.getSourceCode().sources, lastCompilationResult.getAsts())
if (node.nodes && node.nodes.length) { if (node.nodes && node.nodes.length) {
// If node has children, highlight the entire line. if not, just highlight the current source position of the node. // If node has children, highlight the entire line. if not, just highlight the current source position of the node.
lineColumn = { lineColumn = {
@ -139,38 +145,38 @@ class ContextualListener extends Plugin {
} }
} }
} }
const fileName = lastCompilationResult.getSourceName(position.file) const fileName = compilationResult.getSourceName(position.file)
if (fileName) { if (fileName) {
return this.call('editor', 'highlight', lineColumn, fileName, '', { focus: false }) return await this.call('editor', 'highlight', lineColumn, fileName, '', { focus: false })
} }
} }
return null return null
} }
_highlightExpressions (node, compilationResult) { async _highlightExpressions (node, compilationResult) {
const highlights = (id) => { const highlights = async (id) => {
if (this._index.Declarations && this._index.Declarations[id]) { if (this._index.Declarations && this._index.Declarations[id]) {
const refs = this._index.Declarations[id] const refs = this._index.Declarations[id]
for (const ref in refs) { for (const ref in refs) {
const node = refs[ref] const node = refs[ref]
this._highlight(node, compilationResult) await this._highlight(node, compilationResult)
} }
} }
} }
if (node && node.referencedDeclaration) { if (node && node.referencedDeclaration) {
highlights(node.referencedDeclaration) await highlights(node.referencedDeclaration)
const current = this._index.FlatReferences[node.referencedDeclaration] const current = this._index.FlatReferences[node.referencedDeclaration]
this._highlight(current, compilationResult) await this._highlight(current, compilationResult)
} else { } else {
highlights(node.id) await highlights(node.id)
this._highlight(node, compilationResult) await this._highlight(node, compilationResult)
} }
this.results = compilationResult this.results = compilationResult
} }
_stopHighlighting () { _stopHighlighting () {
this.call('editor', 'discardHighlight') this.call('editor', 'discardHighlight')
this.event.trigger('stopHighlighting', []) this.emit('stopHighlighting')
this._activeHighlights = [] this._activeHighlights = []
} }
@ -229,5 +235,3 @@ class ContextualListener extends Plugin {
return '(' + params.toString() + ')' return '(' + params.toString() + ')'
} }
} }
module.exports = ContextualListener

@ -0,0 +1,4 @@
{
"presets": ["@nrwl/react/babel"],
"plugins": []
}

@ -0,0 +1,19 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": "../../../.eslintrc",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 11,
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error"
}
}

@ -0,0 +1,7 @@
# remix-ui-editor-context-view
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test remix-ui-editor-context-view` to execute the unit tests via [Jest](https://jestjs.io).

@ -0,0 +1 @@
export * from './lib/remix-ui-editor-context-view';

@ -1,17 +1,9 @@
var csjs = require('csjs-inject')
var css = csjs` .container-context-view {
.contextview {
opacity : 1;
position : relative;
height : 25px;
}
.container {
padding : 1px 15px; padding : 1px 15px;
} }
.line { .line {
display : flex; display : flex;
justify-content : flex-end;
align-items : center; align-items : center;
text-overflow : ellipsis; text-overflow : ellipsis;
overflow : hidden; overflow : hidden;
@ -48,12 +40,4 @@ var css = csjs`
z-index : 50; z-index : 50;
border-radius : 1px; border-radius : 1px;
border : 2px solid var(--secondary); border : 2px solid var(--secondary);
} }
.contextviewcontainer{
z-index : 50;
border-radius : 1px;
border : 2px solid var(--secondary);
}
`
module.exports = css

@ -0,0 +1,191 @@
import React, { useEffect, useState, useRef } from 'react' // eslint-disable-line
import { sourceMappingDecoder } from '@remix-project/remix-debug'
import './remix-ui-editor-context-view.css'
/* eslint-disable-next-line */
export type astNode = {
name: string,
id: number,
children: Array<any>,
typeDescriptions: any,
nodeType: String,
src: any,
nodeId: any,
position: any
}
export type onContextListenerChangedListener = (nodes: Array<astNode>) => void
export type gasEstimationType = {
executionCost: string,
codeDepositCost: string
}
export interface RemixUiEditorContextViewProps {
hide: boolean,
gotoLine: (line: number, column: number) => void,
openFile: (fileName: string) => void,
getLastCompilationResult: () => any,
offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any,
getCurrentFileName: () => String
onContextListenerChanged: (listener: onContextListenerChangedListener) => void
referencesOf: (nodes: astNode) => Array<astNode>
getActiveHighlights: () => Array<astNode>
gasEstimation: (node: astNode) => gasEstimationType
declarationOf: (node: astNode) => astNode
}
function isDefinition (node: any) {
return node.nodeType === 'ContractDefinition' ||
node.nodeType === 'FunctionDefinition' ||
node.nodeType === 'ModifierDefinition' ||
node.nodeType === 'VariableDeclaration' ||
node.nodeType === 'StructDefinition' ||
node.nodeType === 'EventDefinition'
}
type nullableAstNode = astNode | null
export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps) {
/*
gotoLineDisableRef is used to temporarily disable the update of the view.
e.g when the user ask the component to "gotoLine" we don't want to rerender the component (but just to put the mouse on the desired line)
*/
const gotoLineDisableRef = useRef(false)
const [state, setState] = useState<{
nodes: Array<astNode>,
references: Array<astNode>,
activeHighlights: Array<any>
currentNode: nullableAstNode,
gasEstimation: gasEstimationType
}>({
nodes: [],
references: [],
activeHighlights: [],
currentNode: null,
gasEstimation: { executionCost: '', codeDepositCost: '' }
})
useEffect(() => {
props.onContextListenerChanged(async (nodes: Array<astNode>) => {
if (gotoLineDisableRef.current) {
gotoLineDisableRef.current = false
return
}
let currentNode
if (!props.hide && nodes && nodes.length) {
currentNode = nodes[nodes.length - 1]
if (!isDefinition(currentNode)) {
currentNode = await props.declarationOf(currentNode)
}
}
let references
let gasEstimation
if (currentNode) {
references = await props.referencesOf(currentNode)
if (currentNode.nodeType === 'FunctionDefinition') {
gasEstimation = await props.gasEstimation(currentNode)
}
}
let activeHighlights = await props.getActiveHighlights()
setState(prevState => {
return { ...prevState, nodes, references, activeHighlights, currentNode, gasEstimation }
})
})
}, [])
/*
* show gas estimation
*/
const gasEstimation = (node) => {
if (node.nodeType === 'FunctionDefinition') {
const result: gasEstimationType = state.gasEstimation
const executionCost = ' Execution cost: ' + result.executionCost + ' gas'
const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas'
const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}`
return (
<div className="gasEstimation">
<i className="fas fa-gas-pump gasStationIcon" title='Gas estimation'></i>
<span>{estimatedGas}</span>
</div>
)
} else {
return (<div></div>)
}
}
/*
* onClick jump to ast node in the editor
*/
const _jumpToInternal = async (position: any) => {
const jumpToLine = async (fileName: string, lineColumn: any) => {
if (fileName !== await props.getCurrentFileName()) {
await props.openFile(fileName)
}
if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) {
gotoLineDisableRef.current = true
props.gotoLine(lineColumn.start.line, lineColumn.end.column + 1)
}
}
const lastCompilationResult = await props.getLastCompilationResult()
if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) {
const lineColumn = await props.offsetToLineColumn(
position,
position.file,
lastCompilationResult.getSourceCode().sources,
lastCompilationResult.getAsts())
const filename = lastCompilationResult.getSourceName(position.file)
// TODO: refactor with rendererAPI.errorClick
jumpToLine(filename, lineColumn)
}
}
const _render = (node: nullableAstNode) => {
if (!node) return (<div></div>)
const references = state.references
const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType
const referencesCount = `${references ? references.length : '0'} reference(s)`
let ref = 0
const nodes: Array<astNode> = state.activeHighlights
const jumpTo = () => {
if (node && node.src) {
const position = sourceMappingDecoder.decode(node.src)
if (position) {
_jumpToInternal(position)
}
}
}
// JUMP BETWEEN REFERENCES
const jump = (e: any) => {
e.target.dataset.action === 'next' ? ref++ : ref--
if (ref < 0) ref = nodes.length - 1
if (ref >= nodes.length) ref = 0
_jumpToInternal(nodes[ref].position)
}
return (
<div className="line">{gasEstimation(node)}
<div title={type} className="type">{type}</div>
<div title={node.name} className="name mr-2">{node.name}</div>
<i className="fas fa-share jump" data-action='gotoref' aria-hidden="true" onClick={jumpTo}></i>
<span className="referencesnb">{referencesCount}</span>
<i data-action='previous' className="fas fa-chevron-up jump" aria-hidden="true" onClick={jump}></i>
<i data-action='next' className="fas fa-chevron-down jump" aria-hidden="true" onClick={jump}></i>
</div>
)
}
return (
!props.hide && <div className="container-context-view contextviewcontainer bg-light text-dark border-0 py-1">
{_render(state.currentNode)}
</div>
)
}
export default RemixUiEditorContextView

@ -0,0 +1,16 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -8,4 +8,9 @@
border-radius : 10px; border-radius : 10px;
height: auto; height: auto;
width: auto; width: auto;
}
.contextview {
opacity: 1;
position: absolute;
} }

@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line
import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view'
import Editor, { loader } from '@monaco-editor/react' import Editor, { loader } from '@monaco-editor/react'
import { reducerActions, reducerListener, initialState } from './actions/editor' import { reducerActions, reducerListener, initialState } from './actions/editor'
import { language, conf } from './syntax' import { language, conf } from './syntax'
@ -49,6 +50,7 @@ loader.config({ paths: { vs: 'assets/js/monaco-editor/dev/vs' } })
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface EditorUIProps { export interface EditorUIProps {
contextualListener: any
activated: boolean activated: boolean
themeType: string themeType: string
currentFile: string currentFile: string
@ -62,6 +64,7 @@ export interface EditorUIProps {
} }
plugin: { plugin: {
on: (plugin: string, event: string, listener: any) => void on: (plugin: string, event: string, listener: any) => void
call: (plugin: string, method: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any) => any
} }
editorAPI: { editorAPI: {
findMatches: (uri: string, value: string) => any findMatches: (uri: string, value: string) => any
@ -207,7 +210,12 @@ export const EditorUI = (props: EditorUIProps) => {
'editor.lineHighlightBorder': secondaryColor, 'editor.lineHighlightBorder': secondaryColor,
'editor.lineHighlightBackground': textbackground === darkColor ? lightColor : secondaryColor, 'editor.lineHighlightBackground': textbackground === darkColor ? lightColor : secondaryColor,
'editorGutter.background': lightColor, 'editorGutter.background': lightColor,
'minimap.background': lightColor 'minimap.background': lightColor,
'menu.foreground': textColor,
'menu.background': textbackground,
'menu.selectionBackground': secondaryColor,
'menu.selectionForeground': textColor,
'menu.selectionBorder': secondaryColor
} }
}) })
monacoRef.current.editor.setTheme(themeName) monacoRef.current.editor.setTheme(themeName)
@ -256,7 +264,7 @@ export const EditorUI = (props: EditorUIProps) => {
range: new monacoRef.current.Range(marker.position.start.line + 1, marker.position.start.column + 1, marker.position.end.line + 1, marker.position.end.column + 1), range: new monacoRef.current.Range(marker.position.start.line + 1, marker.position.start.column + 1, marker.position.end.line + 1, marker.position.end.column + 1),
options: { options: {
isWholeLine, isWholeLine,
inlineClassName: `bg-info highlightLine${marker.position.start.line + 1}` inlineClassName: `alert-info highlightLine${marker.position.start.line + 1}`
} }
}) })
} }
@ -377,15 +385,31 @@ export const EditorUI = (props: EditorUIProps) => {
} }
return ( return (
<Editor <div className="w-100 h-100 d-flex flex-column-reverse">
width="100%" <Editor
height="100%" width="100%"
path={props.currentFile} path={props.currentFile}
language={editorModelsState[props.currentFile] ? editorModelsState[props.currentFile].language : 'text'} language={editorModelsState[props.currentFile] ? editorModelsState[props.currentFile].language : 'text'}
onMount={handleEditorDidMount} onMount={handleEditorDidMount}
beforeMount={handleEditorWillMount} beforeMount={handleEditorWillMount}
options={{ glyphMargin: true }} options={{ glyphMargin: true }}
/> />
<div className="contextview">
<RemixUiEditorContextView
hide={false}
gotoLine={(line, column) => props.plugin.call('editor', 'gotoLine', line, column)}
openFile={(file) => props.plugin.call('editor', 'openFile', file)}
getLastCompilationResult={() => { return props.plugin.call('compilerArtefacts', 'getLastCompilationResult') } }
offsetToLineColumn={(position, file, sources, asts) => { return props.plugin.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } }
getCurrentFileName={() => { return props.plugin.call('fileManager', 'file') } }
onContextListenerChanged={(listener) => { props.plugin.on('contextualListener', 'contextChanged', listener) }}
referencesOf={(node: astNode) => { return props.plugin.call('contextualListener', 'referencesOf', node) }}
getActiveHighlights={() => { return props.plugin.call('contextualListener', 'getActiveHighlights') }}
gasEstimation={(node: astNode) => { return props.plugin.call('contextualListener', 'gasEstimation', node) }}
declarationOf={(node: astNode) => { return props.plugin.call('contextualListener', 'declarationOf', node) }}
/>
</div>
</div>
) )
} }

@ -150,6 +150,9 @@
}, },
"remix-ui-theme-module": { "remix-ui-theme-module": {
"tags": [] "tags": []
},
"remix-ui-editor-context-view": {
"tags": []
} }
}, },
"targetDependencies": { "targetDependencies": {

@ -73,7 +73,8 @@
"libs/remix-ui/vertical-icons-panel/src/index.ts" "libs/remix-ui/vertical-icons-panel/src/index.ts"
], ],
"@remix-ui/theme-module": ["libs/remix-ui/theme-module/src/index.ts"], "@remix-ui/theme-module": ["libs/remix-ui/theme-module/src/index.ts"],
"@remix-ui/panel": ["libs/remix-ui/panel/src/index.ts"] "@remix-ui/panel": ["libs/remix-ui/panel/src/index.ts"],
"@remix-ui/editor-context-view": ["libs/remix-ui/editor-context-view/src/index.ts"]
} }
}, },
"exclude": ["node_modules", "tmp"] "exclude": ["node_modules", "tmp"]

@ -1131,80 +1131,48 @@
} }
} }
} }
},
"remix-ui-editor-context-view": {
"root": "libs/remix-ui/editor-context-view",
"sourceRoot": "libs/remix-ui/editor-context-view/src",
"projectType": "library",
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": ["libs/remix-ui/editor-context-view/tsconfig.lib.json"],
"exclude": ["**/node_modules/**", "!libs/remix-ui/editor-context-view/**/*"]
}
}
}
} }
}, },
"remix-ui-editor": { "cli": {
"root": "libs/remix-ui/editor", "defaultCollection": "@nrwl/react"
"sourceRoot": "libs/remix-ui/editor/src", },
"projectType": "library", "schematics": {
"schematics": {}, "@nrwl/workspace": {
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"babel": true
},
"component": {
"style": "css"
},
"library": {
"style": "css",
"linter": "eslint"
}
},
"library": { "library": {
"linter": "eslint" "linter": "eslint"
} }
}, },
"@nrwl/nx-plugin": { "@nrwl/cypress": {
"plugin": { "cypress-project": {
"linter": "eslint" "linter": "eslint"
} }
}, },
"@nrwl/web": { "@nrwl/react": {
"application": { "application": {
"linter": "eslint" "style": "css",
} "linter": "eslint",
"babel": true
}, },
"@nrwl/node": { "component": {
"application": { "style": "css"
"linter": "eslint"
},
"library": {
"linter": "eslint"
}
}
},
"cli": {
"defaultCollection": "@nrwl/react"
},
"schematics": {
"@nrwl/workspace": {
"library": {
"linter": "eslint"
}
},
"@nrwl/cypress": {
"cypress-project": {
"linter": "eslint"
}
},
"@nrwl/react": {
"application": {
"style": "css",
"linter": "eslint",
"babel": true
},
"component": {
"style": "css"
},
"library": {
"style": "css",
"linter": "eslint"
}
}, },
"library": { "library": {
"style": "css",
"linter": "eslint" "linter": "eslint"
} }
}, },
@ -1212,6 +1180,8 @@
"plugin": { "plugin": {
"linter": "eslint" "linter": "eslint"
} }
}, }
"defaultProject": "remix-ide" },
} "defaultProject": "remix-ide"
}

Loading…
Cancel
Save