@swipewallet/venus-js
Version:
A JavaScript SDK for Ethereum and the Venus Protocol.
237 lines (181 loc) • 5.89 kB
JavaScript
const fs = require('fs');
const docblockParser = require('docblock-parser');
String.prototype.toSingleLine = function () {
return this.replace(/\n /g, ' ');
}
// Credit https://stackoverflow.com/a/7225450/6193736
String.prototype.toTitleCase = function () {
const result = this.replace(/([A-Z])/g, ' $1');
return result.charAt(0).toUpperCase() + result.slice(1);
}
String.prototype.toKebabCase = function () {
const title = this.toTitleCase();
return title.replace(/\s/g, '-').toLowerCase();
}
// remove trailing slash due to docblock-parser bug
function unSlashBug(parsed) {
const tags = parsed.tags;
if (!tags) {
return parsed;
}
let keys = Object.keys(parsed.tags);
let str = parsed.tags[keys[keys.length-1]];
if (str[str.length-2] === '\n' && str[str.length-1] === '\/') {
str = str.slice(0, str.length-2);
}
parsed.tags[keys[keys.length-1]] = str;
return parsed;
}
function reduceParamString(param) {
param = param.toSingleLine();
const docBlockItems = (/({.+}) ([^\ ])+ /g).exec(param);
const toRemove = docBlockItems[0];
let name = docBlockItems[0].split(' ');
name = name[name.length-2];
let type = docBlockItems[1];
type = '(' + type.slice(1, type.length-1) + ')';
param = `- \`${name}\` ${type} ${param.split(toRemove)[1]}`;
// HTML escape < and >
param = param.replace(/\</g, '<').replace(/\>/g, '>');
return param;
}
function markdownify(block, functionName) {
let result = '';
const tags = block.tags;
// don't render doc blocks marked hidden
if (tags.hidden !== undefined) {
return result;
}
// for the header of a file
if (tags.file && tags.desc) {
const file = `${tags.file} Methods`;
const id = `${tags.file.toLowerCase()}-methods`;
result += `<section id="${id}" name="${file}">\n\n`
result += `## ${file}\n\n`;
result += `${tags.desc.toSingleLine()}\n\n`;
result += `</section>\n\n`;
return result;
}
let id = functionName.toKebabCase();
let title = functionName.toTitleCase();
// handle special cases
if (functionName === 'vToken') {
id = 'vToken';
title = 'vToken';
}
if (functionName === 'function') {
id = 'constructor';
title = 'Venus Constructor';
}
if (title === 'Get Abi') {
title = 'Get ABI';
}
if (title === 'Get Net Name With Chain Id') {
title = 'Get Network Name With Chain ID';
}
// create section header
result += `<section id="${id}" name="${title}">\n\n`;
result += `## ${title}\n\n`;
// description
const description = block.text.toSingleLine();
result += description + '\n\n';
// parameters
if (tags.param) {
tags.param = Array.isArray(tags.param) ? tags.param : [ tags.param ];
tags.param.forEach((param) => {
result += reduceParamString(param) + '\n';
});
}
// return
if (tags.returns) {
let _return = tags.returns.toSingleLine().replace('{', '(').replace('}', ')');
_return = _return.replace(/\</g, '<').replace(/\>/g, '>');
result += '- `RETURN` ' + _return + '\n\n';
}
// example
if (tags.example) {
const example = tags.example
.replace('```', "```js")
.replace(/&/g, '&');
result += example + '\n\n';
}
result += '</section>\n\n';
return result;
}
function getDocBlocks(fileContents) {
const docBlocks = [];
const startVal = '/**';
const endVal = ' */';
const lines = fileContents.toString().split('\n');
let startIndex;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === startVal) {
startIndex = i;
}
if (line === endVal) {
const functionNameLine = lines[i+1];
const rgx = /\ ([^\s]+)\(/g;
const functionNameResult = rgx.exec(functionNameLine);
let functionName;
if (functionNameResult !== null) {
functionName = functionNameResult[1];
}
let contents = '';
for (let j = startIndex; j <= i; j++) {
const _line = lines[j];
contents += _line + '\n';
}
docBlocks.push({
functionName,
contents
});
}
}
return docBlocks;
}
function getAllFilePaths(srcPath, resultPaths) {
dirOrFileNames = fs.readdirSync(srcPath);
resultPaths = resultPaths || [];
dirOrFileNames.forEach((name) => {
if (fs.statSync(srcPath + name).isDirectory()) {
resultPaths = getAllFilePaths(srcPath + name + '/', resultPaths);
} else {
resultPaths.push(srcPath + name);
}
});
return resultPaths;
}
let intro = '';
intro += '<section id="introduction" name="Introduction">\n\n';
intro += '# Venus.js\n\n';
intro += '## Introduction\n\n';
intro += '[Venus.js](https://github.com/venusprotocol/venus-js) is a ';
intro += 'JavaScript SDK for Ethereum and the Venus Protocol. It wraps ';
intro += 'around Ethers.js, which is its only dependency. It is designed for ';
intro += 'both the web browser and Node.js.\n\n';
intro += 'The SDK is currently in open beta. For bugs reports and feature ';
intro += 'requests, either create an issue in the GitHub repository or send a';
intro += ' message in the Development channel of the Venus Discord.\n\n';
intro += '</section>\n\n';
const srcDir = './src/';
const outFilePath = './scripts/out.md';
const srcFilePaths = getAllFilePaths(srcDir);
// Move `index.ts` to the front
const indexTs = './src/index.ts';
const idx = srcFilePaths.findIndex((el) => el === indexTs);
srcFilePaths.splice(idx, 1);
srcFilePaths.unshift(indexTs);
let mdResult = '';
mdResult += intro;
srcFilePaths.forEach((f) => {
const fileContents = fs.readFileSync(f);
const blocks = getDocBlocks(fileContents);
if (blocks.length > 0) {
blocks.forEach((b) => {
const parsed = unSlashBug(docblockParser.parse(b.contents));
mdResult += markdownify(parsed, b.functionName);
});
}
});
fs.writeFileSync(outFilePath, mdResult);