Skip to content

Instantly share code, notes, and snippets.

@thisnameissoclever
Created October 9, 2018 20:02
Show Gist options
  • Save thisnameissoclever/1314ae7137276f24d3924dc9ac0452d6 to your computer and use it in GitHub Desktop.
Save thisnameissoclever/1314ae7137276f24d3924dc9ac0452d6 to your computer and use it in GitHub Desktop.
/***CLASSES***/
class APIClass {
/**
* An APIClass object
* @param name {string} The name of the API class
*/
constructor(name, classDesc = '') {
this._className = name;
this._classDescription = classDesc;
/**
* @type {{name: string, description: string, parmz: Array, returns: {}, exampleCode: ExampleCode}}
* @private
*/
this._methods = {};
}
addMethod(method) {
//if method already exists, warn and return false.
if (this._methods.hasOwnProperty(method.name)) {
let currentArgsLen = this._methods[method.name].methodParams.length;
let newArgsLen = method.methodParams.length;
if (newArgsLen > currentArgsLen) {
console.warn('Method ' + method.name + ' already exists, but the new method has more arguments. Overwriting.');
} else {
console.warn('Method ' + method.name + ' already exists, and the new method has fewer arguments. Ignoring.');
return false; //Halt execution, do not add the new method.
}
}
this._methods[method.name] = method;
return true;
}
/***GETTERS***/
get name() {
return this._className;
}
get description() {
return this._classDescription;
}
/**
* An array of the names of the elMethods included with this API class
* @returns {string[]}
*/
get methodNames() {
return Object.keys(this._methods);
}
/**
* An object where each key is an API method name, and the value is an object with method details.
* @returns {{name: string, description: string, parmz: Array, returns: {}, exampleCode: ExampleCode}}
*/
get methods() {
return this._methods;
}
/***SETTERS***/
set name(newName) {
if (this._className) {
console.log(
'You can\'t change that now! It\'s already set to ' + this._className + '!');
} else {
this._className = newName;
}
}
set description(newDesc) {
this._classDescription = newDesc;
}
}
class APIMethod {
/**
* todo: description
* @param name {string}
* @param desc [string='']
* @param parmz {Array}
* @param returns {*}
* @param exampleCode {ExampleCode}
*/
constructor(name, desc = '', parmz = [], returns = new Returns(), exampleCode = new ExampleCode()) {
this._name = name;
this._description = desc;
this._parmz = parmz;
this._returns = returns;
this._exampleCode = exampleCode;
}
addParam(pName, pType, pDesc) {
this._parmz.push(
new MethodParam(pName, pType, pDesc)
);
}
/***GETTERS***/
get name() {
return this._name
}
get description() {
return this._description;
}
get methodParams() {
return this._parmz;
}
get returns() {
return this._returns;
}
get exampleCode() {
return this._exampleCode.code + '\n\nOutput: ' + this._exampleCode.output;
}
/***SETTERS***/
set name(newName) {
if (this._name) {
console.error(
'You can\'t change that now! It\'s already set to ' + this._name + '!');
} else {
this._name = newName;
}
}
set methodParams(newParams) {
this._parmz = newParams;
}
set returns(newReturns) {
this._returns = newReturns;
}
set exampleCode(newExampleCode) {
if (newExampleCode && newExampleCode.constructor == ExampleCode) {
this._exampleCode = newExampleCode;
} else {
console.error(
'Example code must be created using the constructor new ExampleCode()');
return false;
}
}
}
class MethodParam {
constructor(name, type = '*', description = '') {
this._name = name;
this._type = type;
this._description = description;
}
/***GETTERS***/
get name() {
return this._name;
}
get type() {
return this._type;
}
get description() {
return this._description;
}
/***SETTERS***/
set name(newName) {
if (this._name) {
console.error(
'You can\'t change that now! It\'s already set to ' + this._name + '!');
} else {
this._name = newName;
}
}
set type(newType) {
this._type = newType;
}
set description(newDesc) {
this._description = newDesc;
}
}
class Returns {
constructor(type = '', descr = '') {
this._type = type;
this._description = descr;
}
/***GETTERS***/
get type() {
return this._type;
}
get description() {
return this._description
}
/***SETTERS***/
set type(newType) {
this._type = newType;
}
set description(newDesc) {
this._description = newDesc;
}
}
class ExampleCode {
/**
* Example code with two props: code and output.
* @param code [string]
* @param output [string]
*/
constructor(code = '', output = '') {
this._code = code;
this._output = output;
}
/***GETTERS***/
get output() {
return this._output;
}
get code() {
return this._code;
}
/***SETTERS***/
set code(code) {
this._code = code;
}
set output(output) {
this._output = output;
}
}
function getAPIDocs() {
/***INIT***/
let apiClass;
/***WORK***/
let elClass = document.getElementsByClassName('dp-api-content row')[0];
let className = elClass.getElementsByClassName('api-class-name')[0].innerText;
let elMethods = document.getElementsByClassName('dp-api-content-method-wrap');
let classDesc = getDesc(document.getElementsByClassName('class-desc'));
apiClass = new APIClass(className, classDesc); //Create a new API class
//Iterate over each of the elMethods on the page
for (let i = 0, elMethodBlock; elMethodBlock = elMethods[i]; i++) {
let methodDesc, elMethodBlock, methodName, elMethodParams, methodObj, exampleObj, returnsObj;
//Get each HTML node that contains a method for the current API class
elMethodBlock = elMethods[i];
//Get the method name (including the parentheses and property names)
methodName = elMethodBlock.getElementsByClassName('method_anchor func-name')[0].innerText;
//Get rid of the parens and property names
methodName = methodName.substring(0, methodName.indexOf('('));
methodDesc = getDesc(elMethodBlock.getElementsByClassName('func-desc'));
methodObj = new APIMethod(methodName, methodDesc);
//Get params
elMethodParams = elMethodBlock.querySelector('#paramRow');
if (elMethodParams) {
elMethodParams = elMethodParams.getElementsByTagName('table')[0];
methodObj.methodParams = getParams(elMethodParams);
}
//Get example and output
exampleObj = getExample(elMethodBlock);
if (exampleObj) {
methodObj.exampleCode = exampleObj;
}
//Get returns
returnsObj = getReturn(elMethodBlock);
if (returnsObj) {
methodObj.returns = returnsObj;
}
//last step: add the method
apiClass.addMethod(methodObj);
}
console.log(JSON.stringify(apiClass));
}
function getReturn(elMethod) {
let returnObj = new Returns();
let elReturns = elMethod.querySelector('#rtnRow2');
if (elReturns) {
let returnRow = elReturns.getElementsByTagName('table')[0].rows[1];
return new Returns(
returnRow.cells[0], //Type
returnRow.cells[1] //Description
);
} else {
return false;
}
}
/**
* @param elMethod {Element}
* @returns {ExampleCode}
*/
function getExample(elMethod) {
let exampleObj = new ExampleCode();
let elTableTitles = elMethod.getElementsByClassName('table-title');
for (let i = 0; i < elTableTitles.length; i++) {
let elTableTitle = elTableTitles[i];
if (elTableTitle.innerText == 'Example') {
exampleObj.code = elTableTitle.parentElement.innerText;
} else if (elTableTitle.innerText == 'Output') {
exampleObj.output = elTableTitle.parentElement.innerText;
}
}
if (exampleObj.code) {
return exampleObj;
} else {
return false;
}
}
function getParams(elParams) {
let params = [];
for (let i = 1; i < elParams.rows.length; i++) {
//iterate through rows
let row = elParams.rows[i];
if (row.cells.length == 3) {
params.push(
new MethodParam(
row.cells[0].innerText,
row.cells[1].innerText,
row.cells[2].innerText
)
);
}
}
return params;
}
function getDesc(elDescriptionLines) {
let desc = '';
for (let i = 0; i < elDescriptionLines.length; i++) {
if (i > 0) {
desc += '\n';
}
desc += elDescriptionLines[i].innerText.trim();
}
desc = desc.replace(/(?:\r\n|\r|\n)/g, '<br />\n');
return desc;
}
getAPIDocs();
//todo: need to add a way to handle multiple API definitions with different numbers of params.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment