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