Initial commit
commit
2f1d820509
@ -0,0 +1 @@
|
||||
node_modules
|
@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
const blessed = require("blessed");
|
||||
const visualizeAST = require("./lib/ast/visualize");
|
||||
const esprima = require("esprima");
|
||||
const util = require("util");
|
||||
const fs = require("fs");
|
||||
|
||||
const markCode = require("./lib/ast/render/mark-code");
|
||||
|
||||
let code = fs.readFileSync("./test/1.js").toString();
|
||||
let _testdata = esprima.parse(code, {
|
||||
range: true,
|
||||
loc: true
|
||||
});
|
||||
|
||||
let ast = visualizeAST(_testdata);
|
||||
|
||||
let screen = blessed.screen({
|
||||
smartCSR: true,
|
||||
terminal: "xterm-256color",
|
||||
fullUnicode: true
|
||||
});
|
||||
|
||||
let list = blessed.list({
|
||||
parent: screen,
|
||||
selectedBg: "blue",
|
||||
mouse: true,
|
||||
keys: true,
|
||||
width: "50%"
|
||||
});
|
||||
|
||||
list.setItems(ast.getLines());
|
||||
list.select(0);
|
||||
|
||||
list.on("select item", (_, index) => {
|
||||
let [start, end] = ast.getItemAtIndex(index).range;
|
||||
codeBox.setContent(markCode(code, start, end));
|
||||
screen.render();
|
||||
});
|
||||
|
||||
let codeBox = blessed.box({
|
||||
parent: screen,
|
||||
width: "50%",
|
||||
left: "50%",
|
||||
border: {
|
||||
type: "line",
|
||||
fg: "#ffffff"
|
||||
},
|
||||
content: code
|
||||
});
|
||||
|
||||
screen.key("q", function(ch, key) {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
screen.render();
|
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const chalk = require("chalk");
|
||||
const ansiStyles = require("ansi-styles");
|
||||
|
||||
module.exports = function colorizedNodeType(astNode) {
|
||||
let nodeType = astNode.type;
|
||||
|
||||
if (nodeType === "FunctionDeclaration" || nodeType === "ArrowFunctionExpression") {
|
||||
return chalk.cyan(nodeType);
|
||||
} else if (nodeType === "CallExpression") {
|
||||
return chalk.green(nodeType);
|
||||
} else if (nodeType === "ReturnStatement") {
|
||||
return chalk.red(nodeType);
|
||||
} else {
|
||||
return ansiStyles.color.ansi256.rgb(100, 100, 100) + nodeType;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const chalk = require("chalk");
|
||||
|
||||
module.exports = function markCode(code, startPosition, endPosition) {
|
||||
return [
|
||||
code.slice(0, startPosition),
|
||||
chalk.bgBlue(code.slice(startPosition, endPosition)),
|
||||
code.slice(endPosition)
|
||||
].join("");
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const chalk = require("chalk");
|
||||
const ansiStyles = require("ansi-styles");
|
||||
const pad = require("pad");
|
||||
|
||||
function grayBackground(string) {
|
||||
return ansiStyles.bgColor.ansi256.rgb(33, 33, 33) + string + ansiStyles.bgColor.close;
|
||||
}
|
||||
|
||||
module.exports = function sectionTag(sectionName, {isArray} = {isArray: false}) {
|
||||
let arrayPrefix;
|
||||
|
||||
if (isArray) {
|
||||
arrayPrefix = chalk.red.bold("[]");
|
||||
} else {
|
||||
arrayPrefix = " ";
|
||||
}
|
||||
|
||||
return `${arrayPrefix} ${grayBackground(`${pad(10, sectionName)} ->`)}`;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
function shortDescription(astNode) {
|
||||
if (astNode.type === "FunctionDeclaration") {
|
||||
return `function ${shortDescription(astNode.id)}(${renderArguments(astNode.params)}) { ... }`;
|
||||
} else if (astNode.type === "ReturnStatement") {
|
||||
return `return ${shortDescription(astNode.argument)}`;
|
||||
} else if (astNode.type === "CallExpression") {
|
||||
return `${shortDescription(astNode.callee)}(${renderArguments(astNode.arguments)})`;
|
||||
} else if (astNode.type === "MemberExpression") {
|
||||
return `${shortDescription(astNode.object)}.${shortDescription(astNode.property)}`;
|
||||
} else if (astNode.type === "Identifier") {
|
||||
return `${astNode.name}`;
|
||||
} else if (astNode.type === "ArrowFunctionExpression") {
|
||||
return `(${renderArguments(astNode.params)}) => { ... }`;
|
||||
} else if (astNode.type === "Literal") {
|
||||
return astNode.raw;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function renderArguments(args) {
|
||||
return args.map(arg => shortDescription(arg)).join(", ");
|
||||
}
|
||||
|
||||
module.exports = shortDescription;
|
@ -0,0 +1,87 @@
|
||||
'use strict';
|
||||
|
||||
const archy = require("archy");
|
||||
const chalk = require("chalk");
|
||||
const memoizee = require("memoizee");
|
||||
const assureArray = require("assure-array");
|
||||
const util = require("util");
|
||||
|
||||
const colorizedNodeType = require("./render/colorize-type");
|
||||
const shortDescription = require("./render/short-description");
|
||||
const sectionTag = require("./render/section-tag");
|
||||
|
||||
module.exports = function visualizeAST(ast) {
|
||||
let indexedItems = []; // NOTE: Impure, but is necessary to make getItemAtIndex work...
|
||||
|
||||
function sectionLabel(name, items) {
|
||||
return {
|
||||
label: chalk.yellow(`${name}:`),
|
||||
nodes: items
|
||||
}
|
||||
}
|
||||
|
||||
function convertChildNodes(key, childNodes) {
|
||||
let arrayifiedNodes = assureArray(childNodes);
|
||||
|
||||
let treeNodes = arrayifiedNodes.map((node) => {
|
||||
let treeNode = astNodeToTreeNode(node);
|
||||
treeNode.label = sectionTag(key, {isArray: Array.isArray(childNodes)}) + " " + treeNode.label;
|
||||
return treeNode;
|
||||
});
|
||||
|
||||
return treeNodes;
|
||||
}
|
||||
|
||||
function astNodeToTreeNode(astNode) {
|
||||
indexedItems.push(astNode);
|
||||
|
||||
let nodeLabel = `${chalk.bold(colorizedNodeType(astNode))} ${shortDescription(astNode)}`;
|
||||
|
||||
let primitiveProperties = [], singleChildren = [], multipleChildren = [];
|
||||
|
||||
Object.keys(astNode).forEach((key) => {
|
||||
if (key === "loc" || key === "range") {
|
||||
/* These are Esprima annotations. */
|
||||
return;
|
||||
}
|
||||
|
||||
let value = astNode[key];
|
||||
|
||||
if (typeof value === "string" || typeof value === "boolean" || typeof value === "number" || value == null) {
|
||||
primitiveProperties.push(key);
|
||||
} else if (Array.isArray(value)) {
|
||||
if (value.length > 0) {
|
||||
multipleChildren.push(key);
|
||||
}
|
||||
} else if (typeof value === "object" && value.type != null) {
|
||||
singleChildren.push(key);
|
||||
} else {
|
||||
throw new Error(`Encountered unrecognized value type in AST: ${typeof value} -- ${util.inspect(value)}`);
|
||||
}
|
||||
});
|
||||
|
||||
let childNodes = (singleChildren.concat(multipleChildren)).map((key) => {
|
||||
return convertChildNodes(key, astNode[key]);
|
||||
}).reduce((combined, array) => {
|
||||
return combined.concat(array);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
label: nodeLabel,
|
||||
nodes: childNodes
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
getString: memoizee(function getString() {
|
||||
let treeNodes = astNodeToTreeNode(ast);
|
||||
return archy(treeNodes);
|
||||
}),
|
||||
getLines: function getLines() {
|
||||
return this.getString().split("\n");
|
||||
},
|
||||
getItemAtIndex: function getItemAtIndex(index) {
|
||||
return indexedItems[index];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "vulnerability-scanner",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.cryto.net:joepie91/vulnerability-scanner.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Sven Slootweg",
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.0.0",
|
||||
"archy": "^1.0.0",
|
||||
"assure-array": "^1.0.0",
|
||||
"blessed": "^0.1.81",
|
||||
"chalk": "^1.1.3",
|
||||
"esprima": "^3.1.3",
|
||||
"memoizee": "^0.4.1",
|
||||
"pad": "^1.0.2"
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
function getContentWithComments() {
|
||||
return Promise.try(() => {
|
||||
return knex('content');
|
||||
}).map((row) => {
|
||||
return Promise.try(() => {
|
||||
return knex('comments').where('content', row.id);
|
||||
}).then((comments) => {
|
||||
row.comments = comments;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue