parent
09406f35a3
commit
fdf4dcb616
@ -0,0 +1 @@ |
|||||||
|
## Remix resolve engine |
@ -0,0 +1,38 @@ |
|||||||
|
{ |
||||||
|
"name": "remix-resolve", |
||||||
|
"version": "0.0.1", |
||||||
|
"description": "Solidity import resolver engine", |
||||||
|
"main": "./src/index.js", |
||||||
|
"bin": { |
||||||
|
"remix-tests": "./bin/remix-resolve" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "standard", |
||||||
|
"test": "standard && mocha tests/ -t 300000" |
||||||
|
}, |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git+https://github.com/ethereum/remix-tests.git" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"solidity", |
||||||
|
"remix", |
||||||
|
"resolve", |
||||||
|
"import" |
||||||
|
], |
||||||
|
"author": "Remix Team", |
||||||
|
"license": "MIT", |
||||||
|
"standard": { |
||||||
|
"ignore": [ |
||||||
|
"tests/" |
||||||
|
] |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"mocha": "^5.1.0", |
||||||
|
"standard": "^12.0.1" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"url": "^0.11.0", |
||||||
|
"valid-url": "^1.0.9" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
const url = require('url') |
||||||
|
const validUrl = require('valid-url') |
||||||
|
const resolve = require('./resolve.js') |
||||||
|
/* |
||||||
|
combineSource(//basepath, //sources object)
|
||||||
|
*/ |
||||||
|
const combineSource = async function (rootpath, sources) { |
||||||
|
let fn, importLine, ir |
||||||
|
var matches = [] |
||||||
|
ir = /^(?:import){1}(.+){0,1}\s['"](.+)['"];/gm |
||||||
|
let match = null |
||||||
|
for (const fileName of Object.keys(sources)) { |
||||||
|
const source = sources[fileName].content |
||||||
|
while ((match = ir.exec(source))) { |
||||||
|
matches.push(match) |
||||||
|
} |
||||||
|
for (let match of matches) { |
||||||
|
importLine = match[0] |
||||||
|
const extra = match[1] ? match[1] : '' |
||||||
|
if (validUrl.isUri(rootpath)) { |
||||||
|
fn = url.resolve(rootpath, match[2]) |
||||||
|
} else { |
||||||
|
fn = match[2] |
||||||
|
} |
||||||
|
try { |
||||||
|
// resolve anything other than remix_tests.sol & tests.sol
|
||||||
|
if (fn.localeCompare('remix_tests.sol') !== 0 && fn.localeCompare('tests.sol') !== 0) { |
||||||
|
let subSorce = {} |
||||||
|
const response = await resolve(rootpath, fn) |
||||||
|
sources[fileName].content = sources[fileName].content.replace(importLine, 'import' + extra + ' \'' + response.filename + '\';') |
||||||
|
subSorce[response.filename] = { content: response.content } |
||||||
|
sources = Object.assign(await combineSource(response.rootpath, subSorce), sources) |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
throw e |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return sources |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = { combineSource } |
@ -0,0 +1,12 @@ |
|||||||
|
/* |
||||||
|
const rr = require('remix-resolve') |
||||||
|
const fileContent = rr.resolve('https://github.com/ethereum/greeter.sol') |
||||||
|
const input = rr.combineSource({ 'greeter.sol': content }) |
||||||
|
*/ |
||||||
|
const resolve = require('./resolve.js') |
||||||
|
const combineSource = require('./combineSource.js') |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
resolve: resolve, |
||||||
|
combineSource: combineSource |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
const axios = require('axios') |
||||||
|
const path = require('path') |
||||||
|
const fs = require('fs') |
||||||
|
|
||||||
|
const handleGithubCall = async function (fullpath, repoPath, path, filename, fileRoot) { |
||||||
|
const data = await axios({ |
||||||
|
method: 'get', |
||||||
|
url: 'https://api.github.com/repos/' + repoPath + '/contents/' + path, |
||||||
|
responseType: 'json' |
||||||
|
}).then(function (response) { |
||||||
|
if ('content' in response.data) { |
||||||
|
const buf = Buffer.from(response.data.content, 'base64') |
||||||
|
fileRoot = fullpath.substring(0, fullpath.lastIndexOf('/')) |
||||||
|
fileRoot = fileRoot + '/' |
||||||
|
const resp = { filename, content: buf.toString('UTF-8'), fileRoot } |
||||||
|
return resp |
||||||
|
} else { |
||||||
|
throw Error('Content not received!') |
||||||
|
} |
||||||
|
}) |
||||||
|
return data |
||||||
|
} |
||||||
|
const handleNodeModulesImport = async function (pathString, filename, fileRoot) { |
||||||
|
const o = { encoding: 'UTF-8' } |
||||||
|
var modulesDir = fileRoot |
||||||
|
|
||||||
|
while (true) { |
||||||
|
var p = path.join(modulesDir, 'node_modules', pathString, filename) |
||||||
|
try { |
||||||
|
const content = fs.readFileSync(p, o) |
||||||
|
fileRoot = path.join(modulesDir, 'node_modules', pathString) |
||||||
|
const response = { filename, content, fileRoot } |
||||||
|
return response |
||||||
|
} catch (err) { |
||||||
|
console.log(err) |
||||||
|
} |
||||||
|
|
||||||
|
// Recurse outwards until impossible
|
||||||
|
var oldModulesDir = modulesDir |
||||||
|
modulesDir = path.join(modulesDir, '..') |
||||||
|
if (modulesDir === oldModulesDir) { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
const handleLocalImport = async function (pathString, filename, fileRoot) { |
||||||
|
// if no relative/absolute path given then search in node_modules folder
|
||||||
|
if (pathString && pathString.indexOf('.') !== 0 && pathString.indexOf('/') !== 0) { |
||||||
|
return handleNodeModulesImport(pathString, filename, fileRoot) |
||||||
|
} else { |
||||||
|
const o = { encoding: 'UTF-8' } |
||||||
|
const p = pathString ? path.resolve(fileRoot, pathString, filename) : path.resolve(fileRoot, filename) |
||||||
|
const content = fs.readFileSync(p, o) |
||||||
|
fileRoot = pathString ? path.resolve(fileRoot, pathString) : fileRoot |
||||||
|
const response = { filename, content, fileRoot } |
||||||
|
return response |
||||||
|
} |
||||||
|
} |
||||||
|
const getHandlers = async function () { |
||||||
|
return [ |
||||||
|
{ |
||||||
|
type: 'local', |
||||||
|
match: /(^(?!(?:http:\/\/)|(?:https:\/\/)?(?:www.)?(?:github.com)))(^\/*[\w+-_/]*\/)*?(\w+\.sol)/g, |
||||||
|
handle: async (match, fileRoot) => { const data = await handleLocalImport(match[2], match[3], fileRoot); return data } |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'github', |
||||||
|
match: /^(https?:\/\/)?(www.)?github.com\/([^/]*\/[^/]*)(.*\/(\w+\.sol))/g, |
||||||
|
handle: async (match, fileRoot) => { |
||||||
|
const data = await handleGithubCall(match[0], match[3], match[4], match[5], fileRoot) |
||||||
|
return data |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
const resolve = async function (fileRoot, sourcePath) { |
||||||
|
const handlers = await getHandlers() |
||||||
|
let response = {} |
||||||
|
for (const handler of handlers) { |
||||||
|
try { |
||||||
|
// here we are trying to find type of import path github/swarm/ipfs/local
|
||||||
|
const match = handler.match.exec(sourcePath) |
||||||
|
if (match) { |
||||||
|
response = await handler.handle(match, fileRoot) |
||||||
|
break |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
throw e |
||||||
|
} |
||||||
|
} |
||||||
|
return response |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = { resolve } |
@ -0,0 +1,94 @@ |
|||||||
|
const axios = require('axios') |
||||||
|
const path = require('path') |
||||||
|
const fs = require('fs') |
||||||
|
|
||||||
|
const handleGithubCall = async function (fullpath, repoPath, path, filename, fileRoot) { |
||||||
|
const data = await axios({ |
||||||
|
method: 'get', |
||||||
|
url: 'https://api.github.com/repos/' + repoPath + '/contents/' + path, |
||||||
|
responseType: 'json' |
||||||
|
}).then(function (response) { |
||||||
|
if ('content' in response.data) { |
||||||
|
const buf = Buffer.from(response.data.content, 'base64') |
||||||
|
fileRoot = fullpath.substring(0, fullpath.lastIndexOf('/')) |
||||||
|
fileRoot = fileRoot + '/' |
||||||
|
const resp = { filename, content: buf.toString('UTF-8'), fileRoot } |
||||||
|
return resp |
||||||
|
} else { |
||||||
|
throw Error('Content not received!') |
||||||
|
} |
||||||
|
}) |
||||||
|
return data |
||||||
|
} |
||||||
|
const handleNodeModulesImport = async function (pathString, filename, fileRoot) { |
||||||
|
const o = { encoding: 'UTF-8' } |
||||||
|
var modulesDir = fileRoot |
||||||
|
|
||||||
|
while (true) { |
||||||
|
var p = path.join(modulesDir, 'node_modules', pathString, filename) |
||||||
|
try { |
||||||
|
const content = fs.readFileSync(p, o) |
||||||
|
fileRoot = path.join(modulesDir, 'node_modules', pathString) |
||||||
|
const response = { filename, content, fileRoot } |
||||||
|
return response |
||||||
|
} catch (err) { |
||||||
|
console.log(err) |
||||||
|
} |
||||||
|
|
||||||
|
// Recurse outwards until impossible
|
||||||
|
var oldModulesDir = modulesDir |
||||||
|
modulesDir = path.join(modulesDir, '..') |
||||||
|
if (modulesDir === oldModulesDir) { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
const handleLocalImport = async function (pathString, filename, fileRoot) { |
||||||
|
// if no relative/absolute path given then search in node_modules folder
|
||||||
|
if (pathString && pathString.indexOf('.') !== 0 && pathString.indexOf('/') !== 0) { |
||||||
|
return handleNodeModulesImport(pathString, filename, fileRoot) |
||||||
|
} else { |
||||||
|
const o = { encoding: 'UTF-8' } |
||||||
|
const p = pathString ? path.resolve(fileRoot, pathString, filename) : path.resolve(fileRoot, filename) |
||||||
|
const content = fs.readFileSync(p, o) |
||||||
|
fileRoot = pathString ? path.resolve(fileRoot, pathString) : fileRoot |
||||||
|
const response = { filename, content, fileRoot } |
||||||
|
return response |
||||||
|
} |
||||||
|
} |
||||||
|
const getHandlers = async function () { |
||||||
|
return [ |
||||||
|
{ |
||||||
|
type: 'local', |
||||||
|
match: /(^(?!(?:http:\/\/)|(?:https:\/\/)?(?:www.)?(?:github.com)))(^\/*[\w+-_/]*\/)*?(\w+\.sol)/g, |
||||||
|
handle: async (match, fileRoot) => { const data = await handleLocalImport(match[2], match[3], fileRoot); return data } |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'github', |
||||||
|
match: /^(https?:\/\/)?(www.)?github.com\/([^/]*\/[^/]*)(.*\/(\w+\.sol))/g, |
||||||
|
handle: async (match, fileRoot) => { |
||||||
|
const data = await handleGithubCall(match[0], match[3], match[4], match[5], fileRoot) |
||||||
|
return data |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
const resolveImports = async function (fileRoot, sourcePath) { |
||||||
|
const handlers = await getHandlers() |
||||||
|
let response = {} |
||||||
|
for (const handler of handlers) { |
||||||
|
try { |
||||||
|
// here we are trying to find type of import path github/swarm/ipfs/local
|
||||||
|
const match = handler.match.exec(sourcePath) |
||||||
|
if (match) { |
||||||
|
response = await handler.handle(match, fileRoot) |
||||||
|
break |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
throw e |
||||||
|
} |
||||||
|
} |
||||||
|
return response |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = { resolveImports } |
Loading…
Reference in new issue