dojo
Version:
Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.
275 lines (246 loc) • 7.99 kB
JavaScript
define([
"./_base/kernel", // kernel.global
"./_base/lang"
], function(kernel, lang){
// module:
// dojo/string
var ESCAPE_REGEXP = /[&<>'"\/]/g;
var ESCAPE_MAP = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
var string = {
// summary:
// String utilities for Dojo
};
lang.setObject("dojo.string", string);
string.escape = function(/*String*/str){
// summary:
// Efficiently escape a string for insertion into HTML (innerHTML or attributes), replacing &, <, >, ", ', and / characters.
// str:
// the string to escape
if(!str){ return ""; }
return str.replace(ESCAPE_REGEXP, function(c) {
return ESCAPE_MAP[c];
});
};
// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt#Polyfill
string.codePointAt = String.prototype.codePointAt ?
function (str, position) {
return String.prototype.codePointAt.call(str, position);
} :
function(str, position) {
if (str == null) {
throw new TypeError('codePointAt called on null or undefined');
}
var size;
var first;
var second;
var index;
str = String(str);
size = str.length;
// `ToInteger`
index = position ? Number(position) : 0;
if (index != index) { // better `isNaN`
index = 0;
}
// Account for out-of-bounds indices:
if (index < 0 || index >= size) {
return undefined;
}
// Get the first code unit
first = str.charCodeAt(index);
// check if it's the start of a surrogate pair
if (first >= 0xD800 && first <= 0xDBFF && // high surrogate
size > index + 1 // there is a next code unit
) {
second = str.charCodeAt(index + 1);
if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
}
}
return first;
};
// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint#Polyfill
string.fromCodePoint = String.fromCodePoint || function () {
var codeUnits = [];
var codeLen = 0;
var result = "";
var codePoint;
var index;
for (index = 0, len = arguments.length; index !== len; ++index) {
codePoint = +arguments[index];
// correctly handles all cases including `NaN`, `-Infinity`, `+Infinity`
// The surrounding `!(...)` is required to correctly handle `NaN` cases
// The (codePoint>>>0) === codePoint clause handles decimals and negatives
if (!(codePoint < 0x10FFFF && (codePoint>>>0) === codePoint)) {
throw RangeError("Invalid code point: " + codePoint);
}
if (codePoint <= 0xFFFF) { // BMP code point
codeLen = codeUnits.push(codePoint);
} else { // Astral code point; split in surrogate halves
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
codePoint -= 0x10000;
codeLen = codeUnits.push(
(codePoint >> 10) + 0xD800, // highSurrogate
(codePoint % 0x400) + 0xDC00 // lowSurrogate
);
}
if (codeLen >= 0x3fff) {
result += String.fromCharCode.apply(null, codeUnits);
codeUnits.length = 0;
}
}
return result + String.fromCharCode.apply(null, codeUnits);
};
string.rep = function(/*String*/str, /*Integer*/num){
// summary:
// Efficiently replicate a string `n` times.
// str:
// the string to replicate
// num:
// number of times to replicate the string
if(num <= 0 || !str){ return ""; }
var buf = [];
for(;;){
if(num & 1){
buf.push(str);
}
if(!(num >>= 1)){ break; }
str += str;
}
return buf.join(""); // String
};
string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
// summary:
// Pad a string to guarantee that it is at least `size` length by
// filling with the character `ch` at either the start or end of the
// string. Pads at the start, by default.
// text:
// the string to pad
// size:
// length to provide padding
// ch:
// character to pad, defaults to '0'
// end:
// adds padding at the end if true, otherwise pads at start
// example:
// | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++".
// | string.pad("Dojo", 10, "+", true);
if(!ch){
ch = '0';
}
var out = String(text),
pad = string.rep(ch, Math.ceil((size - out.length) / ch.length));
return end ? out + pad : pad + out; // String
};
string.substitute = function( /*String*/ template,
/*Object|Array*/map,
/*Function?*/ transform,
/*Object?*/ thisObject){
// summary:
// Performs parameterized substitutions on a string. Throws an
// exception if any parameter is unmatched.
// template:
// a string with expressions in the form `${key}` to be replaced or
// `${key:format}` which specifies a format function. keys are case-sensitive.
// The special sequence `${}` can be used escape `$`.
// map:
// hash to search for substitutions
// transform:
// a function to process all parameters before substitution takes
// place, e.g. mylib.encodeXML
// thisObject:
// where to look for optional format function; default to the global
// namespace
// example:
// Substitutes two expressions in a string from an Array or Object
// | // returns "File 'foo.html' is not found in directory '/temp'."
// | // by providing substitution data in an Array
// | string.substitute(
// | "File '${0}' is not found in directory '${1}'.",
// | ["foo.html","/temp"]
// | );
// |
// | // also returns "File 'foo.html' is not found in directory '/temp'."
// | // but provides substitution data in an Object structure. Dotted
// | // notation may be used to traverse the structure.
// | string.substitute(
// | "File '${name}' is not found in directory '${info.dir}'.",
// | { name: "foo.html", info: { dir: "/temp" } }
// | );
// example:
// Use a transform function to modify the values:
// | // returns "file 'foo.html' is not found in directory '/temp'."
// | string.substitute(
// | "${0} is not found in ${1}.",
// | ["foo.html","/temp"],
// | function(str){
// | // try to figure out the type
// | var prefix = (str.charAt(0) == "/") ? "directory": "file";
// | return prefix + " '" + str + "'";
// | }
// | );
// example:
// Use a formatter
// | // returns "thinger -- howdy"
// | string.substitute(
// | "${0:postfix}", ["thinger"], null, {
// | postfix: function(value, key){
// | return value + " -- howdy";
// | }
// | }
// | );
thisObject = thisObject || kernel.global;
transform = transform ?
lang.hitch(thisObject, transform) : function(v){ return v; };
return template.replace(/\$\{([^\s\:\}]*)(?:\:([^\s\:\}]+))?\}/g,
function(match, key, format){
if (key == ''){
return '$';
}
var value = lang.getObject(key, false, map);
if(format){
value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
}
var result = transform(value, key);
if (typeof result === 'undefined') {
throw new Error('string.substitute could not find key "' + key + '" in template');
}
return result.toString();
}); // String
};
string.trim = String.prototype.trim ?
lang.trim : // aliasing to the native function
function(str){
str = str.replace(/^\s+/, '');
for(var i = str.length - 1; i >= 0; i--){
if(/\S/.test(str.charAt(i))){
str = str.substring(0, i + 1);
break;
}
}
return str;
};
/*=====
string.trim = function(str){
// summary:
// Trims whitespace from both sides of the string
// str: String
// String to be trimmed
// returns: String
// Returns the trimmed string
// description:
// This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
// The short yet performant version of this function is dojo/_base/lang.trim(),
// which is part of Dojo base. Uses String.prototype.trim instead, if available.
return ""; // String
};
=====*/
return string;
});