diff --git a/src/app.js b/src/app.js index 221f0b5be8..f970ddb079 100644 --- a/src/app.js +++ b/src/app.js @@ -36,7 +36,7 @@ var modalDialogCustom = require('./app/ui/modal-dialog-custom') var TxLogger = require('./app/execution/txLogger') var Txlistener = remixLib.execution.txListener var EventsDecoder = remixLib.execution.EventsDecoder -var handleImports = require('./app/compiler/compiler-imports') +var CompilerImport = require('./app/compiler/compiler-imports') var FileManager = require('./app/files/fileManager') var ContextualListener = require('./app/editor/contextualListener') var ContextView = require('./app/editor/contextView') @@ -135,6 +135,7 @@ class App { self._api.filesProviders['ipfs'] = new BasicReadOnlyExplorer('ipfs') self._view = {} self._components = {} + self._components.compilerImport = new CompilerImport() self.data = { _layout: { right: { @@ -235,7 +236,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } function importExternal (url, cb) { - handleImports.import(url, + self._components.compilerImport.import(url, (loadingMsg) => { toolTip(loadingMsg) }, @@ -249,22 +250,34 @@ Please make a backup of your contracts and start using http://remix.ethereum.org }) } - // ----------------- Compiler ----------------- - var compiler = new Compiler((url, cb) => { + function importFileCb (url, filecb) { var provider = fileManager.fileProviderOf(url) if (provider) { provider.exists(url, (error, exist) => { - if (error) return cb(error) + if (error) return filecb(error) if (exist) { - return provider.get(url, cb) + return provider.get(url, filecb) } else { - importExternal(url, cb) + importExternal(url, filecb) } }) + } else if (self._components.compilerImport.isRelativeImport(url)) { + // try to resolve localhost modules (aka truffle imports) + var splitted = /([^/]+)\/(.*)$/g.exec(url) + async.tryEach([ + (cb) => { importFileCb('localhost/installed_contracts/' + url, cb) }, + (cb) => { if (!splitted) { cb('url not parseable' + url) } else { importFileCb('localhost/installed_contracts/' + splitted[1] + '/contracts/' + splitted[2], cb) } }, + (cb) => { importFileCb('localhost/node_modules/' + url, cb) }, + (cb) => { if (!splitted) { cb('url not parseable' + url) } else { importFileCb('localhost/node_modules/' + splitted[1] + '/contracts/' + splitted[2], cb) } }], + (error, result) => { filecb(error, result) } + ) } else { - importExternal(url, cb) + importExternal(url, filecb) } - }) + } + + // ----------------- Compiler ----------------- + var compiler = new Compiler(importFileCb) var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) // ----------------- UniversalDApp ----------------- @@ -553,7 +566,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org var fileManager = new FileManager({ config: config, editor: editor, - filesProviders: filesProviders + filesProviders: filesProviders, + compilerImport: self._components.compilerImport }) // Add files received from remote instance (i.e. another remix-ide) diff --git a/src/app/compiler/compiler-imports.js b/src/app/compiler/compiler-imports.js index 8860beb161..6a0e559c47 100644 --- a/src/app/compiler/compiler-imports.js +++ b/src/app/compiler/compiler-imports.js @@ -3,9 +3,12 @@ var base64 = require('js-base64').Base64 var swarmgw = require('swarmgw') var request = require('request') -module.exports = { - previouslyHandled: {}, // cache import so we don't make the request at each compilation. - handleGithubCall: function (root, path, cb) { +module.exports = class CompilerImports { + constructor () { + this.previouslyHandled = {} // cache import so we don't make the request at each compilation. + } + + handleGithubCal (root, path, cb) { return request.get( { url: 'https://api.github.com/repos/' + root + '/contents/' + path, @@ -26,15 +29,15 @@ module.exports = { cb('Content not received') } }) - }, + } - handleSwarmImport: function (url, cleanUrl, cb) { + handleSwarmImport (url, cleanUrl, cb) { swarmgw.get(url, function (err, content) { cb(err, content, cleanUrl) }) - }, + } - handleIPFS: function (url, cb) { + handleIPFS (url, cb) { // replace ipfs:// with /ipfs/ url = url.replace(/^ipfs:\/\/?/, 'ipfs/') @@ -51,17 +54,21 @@ module.exports = { } cb(null, data, url) }) - }, + } - handlers: function () { + handlers () { return [ { type: 'github', match: /^(https?:\/\/)?(www.)?github.com\/([^/]*\/[^/]*)\/(.*)/, handler: (match, cb) => { this.handleGithubCall(match[3], match[4], cb) } }, { type: 'swarm', match: /^(bzz[ri]?:\/\/?(.*))$/, handler: (match, cb) => { this.handleSwarmImport(match[1], match[2], cb) } }, { type: 'ipfs', match: /^(ipfs:\/\/?.+)/, handler: (match, cb) => { this.handleIPFS(match[1], cb) } } ] - }, + } + + isRelativeImport (url) { + return /^([A-Za-z0-9]+)/.exec(url) + } - import: function (url, loadingCb, cb) { + import (url, loadingCb, cb) { var self = this var imported = this.previouslyHandled[url] if (imported) { diff --git a/src/app/files/fileManager.js b/src/app/files/fileManager.js index 8bbdee20ba..0d974200fb 100644 --- a/src/app/files/fileManager.js +++ b/src/app/files/fileManager.js @@ -4,7 +4,6 @@ var $ = require('jquery') var remixLib = require('remix-lib') var yo = require('yo-yo') var EventManager = remixLib.EventManager -var imports = require('../compiler/compiler-imports') /* attach to files event (removed renamed) @@ -161,7 +160,7 @@ class FileManager { if (provider !== null && this.opt.filesProviders[provider[0]]) { return this.opt.filesProviders[provider[0]] } else { - for (var handler of imports.handlers()) { + for (var handler of this.opt.compilerImport.handlers()) { if (handler.match.exec(file)) { return this.opt.filesProviders[handler.type] }