UNPKG

string-kit

Version:

A string manipulation toolbox, featuring a string formatter (inspired by sprintf), a variable inspector (output featuring ANSI colors and HTML) and various escape functions (shell argument, regexp, html, etc).

412 lines (282 loc) 15.2 kB
# String Kit A string manipulation toolbox, featuring a string formatter (inspired by sprintf), a variable inspector (output featuring ANSI colors and HTML) and various escape functions (shell argument, regexp, html, etc). * License: MIT * Current status: beta * Platform: Node.js only (browser support is planned) # Install Use Node Package Manager: npm install string-kit # Reference * [.format()](#ref.format) * [.format.count()](#ref.format.count) * [.inspect()](#ref.inspect) * Escape functions collection * [.escape.shellArg()](#ref.escape.shellArg) * [.escape.regExp()](#ref.escape.regExp) * [.escape.regExpPattern()](#ref.escape.regExp) * [.escape.regExpReplacement()](#ref.escape.regExpReplacement) * [.escape.html()](#ref.escape.html) * [.escape.htmlAttr()](#ref.escape.htmlAttr) * [.escape.htmlSpecialChars()](#ref.escape.htmlSpecialChars) * [.escape.control()](#ref.escape.control) <a name="ref.format"></a> ### .format( formatString , ... ) * formatString `String` a string containing some `sprintf()`-like formating * ... `mixed` a variable list of arguments to insert into the formatString This function is inspired by the `C`'s `sprintf()` function. Basicly, if `formatString` includes *format specifiers* (subsequences beginning with %), the additional arguments following `formatString` are formatted and inserted in the resulting string replacing their respective specifiers. Also it diverges from `C` in quite a few places. **New:** Since *v0.3.x* we can add styles markup (color, bold, italic, and so on...) using the `^` caret. See [the format markup documentation](#ref.format.markup). Basic usage: ```js var format = require( 'string-kit' ).format ; console.log( format( 'Hello %s %s, how are you?' , 'Joe' , 'Doe' ) ) ; // Output: 'Hello Joe Doe, how are you?' ``` Specifiers: * `%%` write a single % * `%s` to string, with sanitizer * `%S` to string, with `^` interpretation * `%r` to raw string, without any sanitizer * `%n` to natural: output the most natural representation for this type * `%N` to even more natural: avoid type hinting marks like bracket for array * `%f` to (float) number * `%k` to number with metric system prefixes (like k, M, G, and so on...) * `%e` to exponential “E notation” (e.g. 13 -> 1.23e+2) * `%K` to scientific notation (e.g. 123 -> 1.23 × 10²) * `%i` to integer * `%d` alias of `%i` (*C*'s `printf()` compatibility) * `%u` to unsigned integer * `%U` to unsigned positive integer (>0) * `%P` to (absolute) percent (e.g.: 1.25 -> 125% ; 0.75 -> 75%) * `%p` to relative percent (e.g.: 1.25 -> +25% ; 0.75 -> -25%) * `%t` to time duration, convert ms into H:min:s * `%m` to degrees/minutes/seconds notation * `%h` to unsigned hexadecimal * `%x` to unsigned hexadecimal, force pairs of symbols (e.g. 'f' -> '0f') * `%o` to unsigned octal * `%b` to unsigned binary * `%X` string/binary/buffer to hexadecimal: convert a string into hex charcodes, force pair of symbols (e.g. 'f' -> '0f' ; 'hello' -> '68656c6c6f') * `%z` string/binary/buffer to base64 * `%Z` string/binary/buffer to base64url * `%O` for objects (call string-kit's inspect() with ultra-minimal options) * `%I` call string-kit's inspect() * `%Y` call string-kit's inspect(), but do not inspect non-enumerable * `%E` call string-kit's inspectError() * `%J` to JSON (call JSON.stringify() * `%D` drop, the argument does not produce anything but is eaten anyway * `%F` filter function existing in the *this* context, e.g. %[filter:%a%a]F * `%a` argument for a filter function Few examples: ```js var format = require( 'string-kit' ).format ; console.log( format( 'This company regains %d%% of market share.' , 36 ) ) ; // Output: 'This company regains 36% of market share.' console.log( format( '11/8=%f' , 11/8 ) ) ; // Output: '11/8=1.375' console.log( format( 'Hexa %h %x' , 11 , 11 ) ) ; // Output: 'Hexa b 0b' ``` We can insert a number between the *%* sign and the letter of the specifier, this way, rather than using the next argument, it uses the *Nth* argument, this is the absolute position: ```js console.log( format( '%2s%1s%3s' , 'A' , 'B' , 'C' ) ) ; // 'BAC' ``` Also, the internal pointer is moved anyway, so the *Nth* format specifier still use the *Nth* argument if it doesn't specify any position: ```js console.log( format( '%2s%s%s' , 'A' , 'B' , 'C' ) ) ; // 'BBC' ``` If the number is preceded by a *plus* or a *minus* sign, the relative position is used rather than the absolute position. ```js console.log( format( '%+1s%-1s%s' , 'A' , 'B' , 'C' ) ) ; // 'BAC' ``` Use case: language. ```js var hello = { en: 'Hello %s %s!' , jp: 'Konnichiwa %2s %1s!' } ; console.log( format( hello[ lang ] , firstName , lastName ) ) ; // Output the appropriate greeting in a language. // In japanese the last name will come before the first name, // but the argument list doesn't need to be changed. ``` **Some specifiers accept parameters:** there are between bracket, inserted before the letter, e.g.: `%[L5]s`. [See the specifier parameters section.](#ref.format.parameters) The mysterious `%[]F` format specifier is used when we want custom formatter. Firstly we need to build an object containing one or many functions. Then, `format()` should be used with `call()`, to pass the functions collection as the *this* context. The `%[` is followed by the function's name, followed by a `:`, followed by a variable list of arguments using `%a`. It is still possible to use relative and absolute positionning. The whole *format specifier* is finished when a `]F` is encountered. Example: ```js var filters = { fxy: function( a , b ) { return '' + ( a * a + b ) ; } } ; console.log( format.call( filters , '%s%[fxy:%a%a]F' , 'f(x,y)=' , 5 , 3 ) ) ; // Output: 'f(x,y)=28' console.log( format.call( filters , '%s%[fxy:%+1a%-1a]F' , 'f(x,y)=' , 5 , 3 ) ) ; // Output: 'f(x,y)=14' ``` <a name="ref.format.parameters"></a> ##### Specifiers parameters A parameter consists in a letter, then one character (letter or not letter), that could be followed by any number of non-letter characters. E.g. `%[L5]s`, the *L* parameter that produce left-padding to force a *5* characters-length. A special parameter (specific for that *specifier*) consists in any number of non-letter characters and must be the first parameter. E.g.: * `%[.2]f`, the special parameter for the *f* specifier (float), it rounds the number to the second decimal place. * `%[.2L5]f`, mixing both the special and normal parameters, the special parameter comes first (round the the second decimal place), then comes the generic and normal parameter *L* (left-padding) When a parameter needs a boolean, `+` denotes true, while `-` denotes false. Generic parameters -- they almost always exists for any specifier and use an upper-case parameter letter: * L *integer*: it produces left-padding (using space) and force the length to the value * R *integer*: same than *L* but produce right-padding instead *Specifier's* specific parameters : * %f %e %K %k %p %P: * *integer*: the number precision in *digits*, e.g. `%[3]f` (12.345 -> 12.3) * *integer* .: rounds to this integer place, e.g. `%[3.]f` (12345 -> 12000) * . *integer*: rounds to this decimal place, e.g. `%[.2]f` (1.2345 -> 1.23) * . *integer* !: rounds to this decimal place and force displaying 0 up to this decimal place, e.g. `%[.2!]f` (12.9 -> 12.90 ; 12 -> 12.00) (useful for prices) * . *integer* ?: rounds to this decimal place and force displaying 0 up to this decimal place **if** there is at least one non-zero in the decimal part, e.g. `%[.2?]f` (12.9 -> 12.90 ; 12 -> 12) * z *integer*: it produces zero padding for the integer part forcing at least *integer* digits, e.g. `%[z5]f` (12 -> 00012) * g *char*: set a group separator character for thousands, e.g. `%[g,]f` (123456 -> 12,345) * g: use the default group separator for thousands, e.g. `%[g]f` (123456 -> 12 345) * %O %I %Y %E: * *integer*: the depth of nested object inspection * c *boolean*: if true, can use ANSI color, if false, it will not use colors. E.g. `%[c+]I`. <a name="ref.format.markup"></a> ##### Style markup reference Since *v0.3.x* we can add styles (color, bold, italic, and so on...) using the `^` caret: ```js var format = require( 'string-kit' ).format ; console.log( format( 'This is ^rred^ and ^bblue^:!' ) ) ; // Output: 'This is red and blue!' with 'red' written in red and 'blue' written in blue. ``` Style markups: * `^^` write a single caret `^` * `^b` switch to blue * `^B` switch to bright blue * `^c` switch to cyan * `^C` switch to bright cyan * `^g` switch to green * `^G` switch to bright green * `^k` switch to black * `^K` switch to bright black * `^m` switch to magenta * `^M` switch to bright magenta * `^r` switch to red * `^R` switch to bright red * `^w` switch to white * `^W` switch to bright white * `^y` switch to yellow (i.e. brown or orange) * `^Y` switch to bright yellow (i.e. yellow) * `^_` switch to underline * `^/` switch to italic * `^!` switch to inverse (inverse background and foreground color) * `^+` switch to bold * `^-` switch to dim * `^:` reset the style * `^ ` (caret followed by a space) reset the style and write a single space * `^#` background modifier: next color will be a background color instead of a foreground color, e.g.: `'Some ^#^r^bred background` text' will write *red background* in blue over red. **Note:** as soon as the format string has **one** style markup, a style reset will be added at the end of the string. ##### **New:** Complex Markup The complex markup syntax starts with `^[` follows with the markup keyword or `key:value`, and ends with a `]`. #### Complex markup in the *key:value* format * `fg` (or aliases: `fgColor`, `color`, `c`) set the foreground color, the value can be one of the ANSI color (*red*, *brightRed*, etc), it can also be any color declared in a *Palette* for methods of object supporting `Palette`, it can be a color-code (e.g.: `#aa5577`) if both the terminal and the method support *true-color*. * `bg` (or alias: `bgColor`) set the background color, the supported values are exactly the same than for *foreground color*. E.g: This output “This is pink!” with the word *pink* written in pink color: `console.log( format( 'This is: ^[fg:#f9b]pink^:!' ) )` #### Complex markup **NOT** in the *key:value* format * Any ANSI color (*red*, *brightRed*, etc) or color code (e.g.: `#aa5577`) will be considered as the value for the *foreground color*. * Named *background color* should be prefixed by `bg` and followed by camel-case (e.g. *red* becomes *bgRed*), for color code you have to use the *key:value* syntax (see above, e.g.: `bg:#aa5577`). * Other styles like *bold*, *italic*, *underline*, *inverse*, *dim* are also supported. E.g: This output “This is pink!” with the word *pink* written in pink color: `console.log( format( 'This is: ^[#f9b]pink^:!' ) )` <a name="ref.format.count"></a> ### .format.count( formatString ) * formatString `String` a string containing some `sprintf()`-like formating It just counts the number of *format specifier* in the `formatString`. <a name="ref.inspect"></a> ### .inspect( [options] , variable ) * options `Object` display options, the following key are possible: * style `string` this is the style to use, the value can be: * 'none': (default) normal output suitable for console.log() or writing into a file * 'inline': like 'none', but without newlines * 'color': colorful output suitable for terminal * 'html': html output * tab: `string` override the default tab string of the *style* * depth: `number` depth limit, default: 3 * maxLength: `number` length limit for strings, default: 250 * outputMaxLength: `number` length limit for the inspect output string, default: 5000 * noFunc: `boolean` do not display functions * noDescriptor: `boolean` do not display descriptor information * noArrayProperty: `boolean` do not display array properties * noType: `boolean` do not display type and constructor * enumOnly: `boolean` only display enumerable properties * funcDetails: `boolean` display function's details * proto: `boolean` display object's prototype * sort: `boolean` sort the keys * minimal: `boolean` imply noFunc: true, noDescriptor: true, noType: true, enumOnly: true, proto: false and funcDetails: false. Display a minimal JSON-like output. * protoBlackList: `Set` of blacklisted object prototype (will not recurse inside it) * propertyBlackList: `Set` of blacklisted property names (will not even display it) * useInspect: `boolean` use .inspect() method when available on an object (default to false) * variable `mixed` anything we want to inspect/debug It inspect a variable, and return a string ready to be displayed with console.log(), or even as HTML output. It produces a slightly better output than node's `util.inspect()`, with more options to control what should be displayed. Since `options` come first, it is possible to use `bind()` to create some custom variable inspector. For example: ```js var colorInspect = require( 'string-kit' ).inspect.bind( undefined , { style: 'color' } ) ; ``` ## Escape functions collection <a name="ref.escape.shellArg"></a> ### .escape.shellArg( str ) * str `String` the string to filter It escapes the string so that it will be suitable as a shell command's argument. <a name="ref.escape.regExp"></a> ### .escape.regExp( str ) , .escape.regExpPattern( str ) * str `String` the string to filter It escapes the string so that it will be suitable to inject it in a regular expression's pattern as a literal string. Example of a search and replace from a user's input: ```js var result = data.replace( new RegExp( stringKit.escape.regExp( userInputSearch ) , 'g' ) , stringKit.escape.regExpReplacement( userInputReplace ) ) ; ``` <a name="ref.escape.regExpReplacement"></a> ### .escape.regExpReplacement( str ) * str `String` the string to filter It escapes the string so that it will be suitable as a literal string for a regular expression's replacement. <a name="ref.escape.html"></a> ### .escape.html( str ) * str `String` the string to filter It escapes the string so that it will be suitable as HTML content. Only `< > &` are replaced by HTML entities. <a name="ref.escape.htmlAttr"></a> ### .escape.htmlAttr( str ) * str `String` the string to filter It escapes the string so that it will be suitable as an HTML tag attribute's value. Only `< > & "` are replaced by HTML entities. It assumes valid HTML: the attribute's value should be into double quote, not in single quote. <a name="ref.escape.htmlSpecialChars"></a> ### .escape.htmlSpecialChars( str ) * str `String` the string to filter It escapes all HTML special characters, `< > & " '` are replaced by HTML entities. <a name="ref.escape.control"></a> ### .escape.control( str ) * str `String` the string to filter It escapes all ASCII control characters (code lesser than or equals to 0x1F, or *backspace*). *Carriage return*, *newline* and *tabulation* are respectively replaced by `\r`, `\n` and `\t`. Other characters are replaced by the unicode notation, e.g. `NUL` is replaced by `\x00`. Full BDD spec generated by Mocha: