You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
7.8 KiB
274 lines
7.8 KiB
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; |
|
});
|
|
|