"use strict";
/**
* Provides an API for enabling extra string functions.
*
* @module string
*
* @author Henry Brown
*/
/**
* A helper function that's used to get the number of repeats of padValue needed
* to pad string's length to padLength without exceeding padLength while only
* repeating whole portions of padValue.
*
* @example
* //returns 2 because the length of "freddyblabla" is 12, and additional
* // repetitions of bla would cause us to exceed the specified padLength of 13
* padCount("freddy", "bla", 13);
*/
module.exports.padCount = function(string, padValue, padLength) {
return Math.floor(Math.max(0, padLength - string.length) / padValue.length);
};
/**
* Enables all of the string functions including:
* - {@link module:string.padLeft padLeft}
* - {@link module:string.padRight padRight}
* - {@link module:string.prepend prepend}
* - {@link module:string.indent indent}
*
* @throws {Error} If String has already implemented any of the above
* functions
*/
module.exports.enableAll = function() {
let s = require("./string.js");
s.enablePadLeft();
s.enablePadRight();
s.enablePrepend();
s.enableIndent();
};
/**
* Pads the left hand side of this string with copies of padValue until another
* would cause the string's length to exceed padLength.
*
* @param {String} padValue The value to repeat
* @param {String} padLength The max length of the string after padding
*
* @returns {String} A padded string
*
* @example
* //returns "00007"
* "7".padLeft("0", 5)
*/
module.exports.padLeft = function(padValue, padLength) {
if (padLength < 0) {
throw new Error("Invalid pad length");
} else if (typeof this !== "string") {
throw new Error("This function can only be used on a string object after" +
"calling require(\"node-extra-funcs\").string.enablePadLeft();");
}
return String(padValue.repeat(require("./string")
.padCount(this, padValue, padLength)) + this);
};
/**
* Attaches the {@link module:string.padLeft padLeft} function to the String
* prototypes so that it can be used on any String objects in the application.
*
* @throws {Error} If String has already implemented padLeft.
*/
module.exports.enablePadLeft = function() {
if (String.prototype.padLeft === undefined) {
this.enabledPadLeft = true;
String.prototype.padLeft = require("./string").padLeft;
} else {
if (this.enabledPadLeft !== true) {
throw new Error("Attempted to redefine padLeft function");
}
}
};
/**
* Detaches the {@link module:string.padLeft padLeft} function from the String
* prototypes.
*/
module.exports.disablePadLeft = function() {
if (this.enabledPadLeft === true) {
delete String.prototype.padLeft;
}
};
/**
* Pads the right hand side of this string with copies of padValue until another
* would cause the string's length to exceed padLength.
*
* @param {String} padValue The value to repeat
* @param {String} padLength The max length of the string after padding
*
* @returns {String} A padded string
*
* @example
* //returns "Noooo"
* "N".padRight("o", 5)
*/
module.exports.padRight = function(padValue, padLength) {
if (padLength < 0) {
throw new Error("Invalid pad length");
}
return String(this + padValue.repeat(require("./string")
.padCount(this, padValue, padLength)));
};
/**
* Attaches the {@link module:string.padRight padRight} function to the String
* prototypes so that it can be used on any String objects in the application.
*
* @throws {Error} If String has already implemented padRight.
*/
module.exports.enablePadRight = function() {
if (String.prototype.padRight === undefined) {
this.enabledPadRight = true;
String.prototype.padRight = require("./string").padRight;
} else {
if (this.enabledPadRight !== true) {
throw new Error("Attempted to redefine padRight function");
}
}
};
/**
* Detaches the {@link module:string.padRight padRight} function from the String
* prototypes.
*/
module.exports.disablePadRight = function() {
if (this.enabledPadRight === true) {
delete String.prototype.padRight;
}
};
/**
* Concatenates the prefix parameter and this string together.
*
* @param {String} prefix The value to prepend.
*
* @returns {String} The concatenated string.
*
* @example
* //returns "prefix"
* "fix".prepend("pre");
*/
module.exports.prepend = function(prefix) {
return String(prefix + this);
};
/**
* Attaches the {@link module:string.prepend prepend} function to the String
* prototypes so that it can be used on any String objects in the application.
*
* @throws {Error} If String has already implemented prepend.
*/
module.exports.enablePrepend = function() {
if (String.prototype.prepend === undefined) {
this.enabledPrepend = true;
String.prototype.prepend = require("./string").prepend;
} else {
if (this.enabledPrepend !== true) {
throw new Error("Attempted to redefine prepend function");
}
}
};
/**
* Detaches the {@link module:string.prepend prepend} function from the String
* prototypes.
*/
module.exports.disablePrepend = function() {
if (this.enabledPrepend === true) {
delete String.prototype.prepend;
}
};
/**
* Indents this string by a number of spaces characters equal to the
* indentSize parameter.
*
* @param {Number} indentSize The number of spaces to indent each line
*
* @returns {String} The indented string.
*
* @example
* //outputs:
* // {
* // "name": "Fred",
* // "role": "Superhero",
* // "mascot": "Platypus"
* // }
* console.log(JSON.stringify({
* "name": "Fred",
* "role": "Superhero",
* "mascot": "Platypus"
* }, null, 2).indent(4));
*/
module.exports.indent = function(indentSize) {
/* prepend a new line in order to indent the first line as well */
return ("\n" + this)
/* replace all consecutive end of line characters with \n and indentSize
spaces */
.replace(/[\r\n]+/g, "\n" + " ".repeat(indentSize))
/* pulls off the first newline (which we prepended in order to indent the
first line.) */
.slice(1);
};
/**
* Attaches the {@link module:string.indent indent} function to the String
* prototypes so that it can be used on any String objects in the application.
*
* @throws {Error} If String has already implemented indent.
*/
module.exports.enableIndent = function() {
if (String.prototype.indent === undefined) {
this.enabledIndent = true;
String.prototype.indent = require("./string").indent;
} else {
if (this.enabledIndent !== true) {
throw new Error("Attempted to redefine indent function");
}
}
};
/**
* Detaches the {@link module:string.indent indent} function from the String
* prototypes.
*/
module.exports.disableIndent = function() {
if (this.enabledIndent === true) {
delete String.prototype.indent;
}
};