您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
String helper functions
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/27278/175156/Str%20Lib.js
(function (global, Str) { "use strict"; // region [ Private Functions ] /** * Test if the specified object is an array. * @param obj {Array|object} * @returns {boolean} * @private */ function _isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; } /** * Convert json string into js object. * @param s * @private */ function _parseJson(s) { var _parser; if (typeof global.JSON !== 'undefined') { _parser = global.JSON.parse; } else if (typeof window.jQuery !== 'undefined') { _parser = window.jQuery.parseJSON; } if (typeof _parser === 'undefined') { throw 'Undefined JSON method'; } return _parser(s); } // endregion /** * Check for undefined, null, zero length, blanks or s is false. * @param s {string|object} - string, array or object to test. * @returns {boolean} * Unit Test: http://jsfiddle.net/wao20/TGP3N/ */ Str.empty = function (s) { // s == undefined <= double equals is deliberate, check for null and undefined return !!(s == undefined || s.length === 0 || Str.trim(s).length === 0 || !s); }; /** * Compare two strings * @param s1 {?string} * @param s2 {?string} * @param caseSensitive {boolean=} * @returns {boolean} */ Str.equals = function (s1, s2, caseSensitive) { if (s1 == undefined || s2 == undefined) { return false; } if (caseSensitive) { return s1 == s2; } return s1.toLowerCase() == s2.toLowerCase(); }; /** * empty(), '0', '0.0', 'false' => false. Otherwise return !!s. * * @param s {?string} * @returns {boolean} */ Str.boolVal = function (s) { if (Str.empty(s)) { return false; } s = Str.trim(s).toLowerCase(); if (s == '0' || s == '0.0' || s == 'false') { return false; } return !!s; }; /** * Escape the string to be use as a literal in regex expression. * * @param s {string|Array} * @returns {string|Array} */ Str.regexEscape = function (s) { if (!s) { return ''; } if (typeof s === 'string') { return s.replace(/([.?*+\^$\[\]\\(){}|\-])/g, '\\$1'); } else if (_isArray(s)) { var result = [], i; for (i = 0; i < s.length; i++) { result.push(Str.regexEscape(s[i])); } return result; } return s; }; /** * Tests whether the beginning of a string matches pattern. * * @param s {string} * @param pattern {string} - to find * @param caseSensitive {boolean=} * @return {boolean} */ Str.startsWith = function (s, pattern, caseSensitive) { if (caseSensitive) { return s.indexOf(pattern) === 0; } return s.toLowerCase().indexOf(pattern.toLowerCase()) === 0; }; /** * Test if string ends with specified pattern * @param s {string} * @param pattern {string} * @param caseSensitive {boolean=} * @returns {boolean} */ Str.endsWith = function (s, pattern, caseSensitive) { var d = s.length - pattern.length; if (caseSensitive) { return d >= 0 && s.lastIndexOf(pattern) === d; } return d >= 0 && s.toLowerCase().lastIndexOf(pattern.toLowerCase()) === d; }; /** * Check if the string contains a substring. * @param s {string} * @param needle {string} * @param caseSensitive {boolean=} * @return {boolean} */ Str.contains = function (s, needle, caseSensitive) { if (Str.empty(s) || Str.empty(needle)) { return false; } if (caseSensitive) { return s.indexOf(needle) > -1; } return s.toLowerCase().indexOf(needle.toLowerCase()) > -1; }; /** * Must contains all the element in the array. * @param s {string} * @param needles {Array|string} * @param caseSensitive {boolean=} * @return {boolean} */ Str.containsAll = function (s, needles, caseSensitive) { var i = 0; if (_isArray(needles)) { for (i = 0; i < needles.length; i++) { if (!Str.contains(s, needles[i], caseSensitive)) { return false; } } return true; } return Str.contains(s, needles, caseSensitive); }; /** * Must contains ANY the element in the array. * @param s {string} * @param needles {Array|string} * @param caseSensitive {boolean=} * @return {boolean} */ Str.containsAny = function (s, needles, caseSensitive) { var i; if (_isArray(needles)) { for (i = 0; i < needles.length; i++) { if (Str.contains(s, needles[i], caseSensitive)) { return true; } } return false; } return Str.contains(s, needles, caseSensitive); }; /** * Determine if the specified variable is a string * @param o * @returns {boolean} */ Str.isString = function (o) { return typeof o === 'string'; }; /** * Trims white space from the beginning and end of a string. * @param s {string} * @param c {string=} * @return {string} */ Str.trim = function (s, c) { if (!Str.isString(s)) { return s; } if (c == undefined || c == ' ') { if (String.prototype.trim) { return String.prototype.trim.call(s); } return s.replace(/^\s+/, '').replace(/\s+$/, ''); } return Str.trimStart(Str.trimEnd(s, c), c); }; /** * Remove chars/Str from the start of the string * @param s * @param c {string|Array=} - supports Str.trimStart(s, ['0x0', '0', 'x']); */ Str.trimStart = function (s, c) { if (c == undefined || c == '') { return s.replace(/^\s+/, ''); } var trims = c, regex, result; if (!_isArray(c)) { trims = [c]; } trims = Str.regexEscape(trims).join('|'); regex = '^(' + trims + '|\s)+'; regex = new RegExp(regex, 'g'); result = s.replace(regex, ''); return result; }; /** * Remove chars/Str(s) from the end of the string * @param s {string} * @param c {string|Array=} - supports Str.trimEnd(s, ['0x0', '0', 'x']); */ Str.trimEnd = function (s, c) { if (c == undefined) { return s.replace(/\s+$/, ''); } var trims = c, regex, result; if (!_isArray(c)) { trims = [c]; } trims = Str.regexEscape(trims).join('|'); regex = '(' + trims + '|\s)+$'; regex = new RegExp(regex, 'g'); result = s.replace(regex, ''); return result; }; /** * Extended substring, support negative index (ordinal js substr(startIndex, endIndex)) * * @param s {string} * @param index {number} - if negative take string from the right similar to php substr() * @param len {number=} - number of char to take starting from the index to the right (even when index is negative) * @return {string} */ Str.subStr = function (s, index, len) { if (s == undefined) { return ''; } len = len || 0; if (Math.abs(index) > s.length) { return s; } // regular substring if (index > -1) { if (len > 0 && (index + len) < s.length) { return s.substring(index, index + len); } return s.substring(index); } // Negative index, take string from the right // Index is negative => subStr ('hello', -3) => 'llo' var start = s.length + index; if (len > 0 && (start + len) < s.length) { return s.substring(start, start + len); } return s.substring(start); }; /** * Count number of occurrences of an substring. * @param s {string} - the big string * @param sub {string} - the little string you want to find. * @param caseSensitive {boolean=} * @returns {number} */ Str.subCount = function (s, sub, caseSensitive) { sub = Str.regexEscape(sub); if (caseSensitive) { return s.split(sub).length - 1; } return s.toLowerCase().split(sub.toLowerCase()).length - 1; }; /** * Concatenate count number of copies of s together and return result. * @param s {string} * @param count {number} - Number of times to repeat s * @return {string} */ Str.repeat = function (s, count) { var result = '', i; for (i = 0; i < count; i++) { result += s; } return result; }; /** * Pad left * * @param s {!string} * @param padStr {!string} - the padding * @param totalLength {!number} - the final length after padding * @return {string} */ Str.padLeft = function (s, padStr, totalLength) { return s.length >= totalLength ? s : Str.repeat(padStr, (totalLength - s.length) / padStr.length) + s; }; /** * Pad right * * @param s {string} * @param padStr {string} - the padding * @param totalLength {number} - the final length after padding * @return {string} */ Str.padRight = function (s, padStr, totalLength) { return s.length >= totalLength ? s : s + Str.repeat(padStr, (totalLength - s.length) / padStr.length); }; /** * Pad string based on the boolean value. * * @param s {string} * @param padStr {string} - the padding * @param totalLength {number} - the final length after padding * @param padRight {boolean} - pad right if true, pad left otherwise * @return {string} */ Str.pad = function (s, padStr, totalLength, padRight) { if (padRight) { return Str.padRight(s, padStr, totalLength); } return Str.padLeft(s, padStr, totalLength); }; /** * Strips any HTML tags from the specified string. * @param s {string} * @return {string} */ Str.stripTags = function (s) { return s.replace(/<\/?[^>]+>/gi, ''); }; /** * escapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko! * Converts HTML special characters to their entity equivalents. * * @param s {string} * @return {string} */ Str.escapeHTML = function (s) { s = s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); return s; }; /** * unescapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko! * Strips tags and converts the entity forms of special HTML characters to their normal form. * * @param s {string} * @return {string} */ Str.unescapeHTML = function (s) { return Str.stripTags(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }; /** * Remove all Viet's accents and replace it with the latin based alphabet * @param s {string} * @return {string} */ Str.stripViet = function (s) { /* data = data.replace(/[àáâãăạảấầẩẫậắằẳẵặ]/g, 'a'); data = data.replace(/[òóôõơọỏốồổỗộớờởỡợ]/g, 'o'); data = data.replace(/[èéêẹẻẽếềểễệ]/g, 'e'); data = data.replace(/[ùúũưụủứừửữự]/g, 'u'); data = data.replace(/[ìíĩỉị]/g, 'i'); data = data.replace(/[ýỳỵỷỹ]/g, 'y'); data = data.replace(/[đðĐ]/g, 'd'); */ if (Str.empty(s)) { return s; } s = s.replace(/[\u00E0\u00E1\u00E2\u00E3\u0103\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7]/g, 'a'); s = s.replace(/[\u00F2\u00F3\u00F4\u00F5\u01A1\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3]/g, 'o'); s = s.replace(/[\u00E8\u00E9\u00EA\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7]/g, 'e'); s = s.replace(/[\u00F9\u00FA\u0169\u01B0\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1]/g, 'u'); s = s.replace(/[\u00EC\u00ED\u0129\u1EC9\u1ECB]/g, 'i'); s = s.replace(/[\u00FD\u1EF3\u1EF5\u1EF7\u1EF9]/g, 'y'); s = s.replace(/[\u0111\u00F0\u0110]/g, 'd'); return s; }; /** * Use this to constructs multi lines string * * eg. Str.multiLines(true, * 'hello', * 'world' * ); * returns: "hello\nworld" * * @param glue {string} - the separator between each line (eg. '\n', ', ' or ' ') * @param args {...string} - each line */ Str.multiLines = function (glue, args) { args = Array.prototype.splice.call(arguments, 1); return args.join(glue); }; /** * Try to parse the json, if valid return the object else return defaultValue * * @param s {string} - json string * @param defaultValue {boolean|object=} - if not specified defaultValue=false * @returns {boolean|object} */ Str.parseJson = function (s, defaultValue) { defaultValue = defaultValue === undefined ? false : defaultValue; if (Str.empty(s)) { return defaultValue; } try { if (typeof s === 'string') { return _parseJson(s); } // it already an object return s; } catch (err) { return defaultValue; } }; /** * Escape the attribute, make sure it doesn't break the attribute select or to be use a an attribute. * @param s {string} - the string */ Str.escapeAttribute = function (s) { return s.replace(/"/g, '\\"'); }; /** * Reverse the string. * * @param s * @returns {*} */ Str.reverse = function (s) { if (s) { return s.split('').reverse().join(''); } return s; }; /** * Get all the matched based on the specified group. * * @param s {string} * @param regex {RegExp} * @param index {Number} - the index of the match. * @returns {Array} */ Str.matchAll = function (s, regex, index) { var m, result = []; index = index || 0; if (!s) { return []; } while (m = regex.exec(s)) { result.push(m[index]); } return result; }; /** * Split the string into multiple smaller chunks. * * @param s * @param chunkSize * @returns {Array} */ Str.chop = function (s, chunkSize) { var regex; if (!s) { return []; } regex = new RegExp('.{1,' + chunkSize + '}', 'g'); return s.match(regex); }; function _getWords(s) { s = s.replace(/(\w)([A-Z][a-z])/, '$1-$2'); s = s.replace(' ', '-'); s = s.replace('_', '-'); s = s.replace(/-+/g, '-'); return s.split('-') } /** * Convert any string to camel case. * * @param s */ Str.toCamelCase = function (s) { var words = _getWords(s), result = '', i, word; for (i = 0; i < words.length; i++) { word = words[i]; if (i == 0) { result += word.toLowerCase(); } else { result += word.charAt(0).toUpperCase() + word.substr(1).toLowerCase(); } } return result; }; /** * Convert any string to title case. * * @param s */ Str.toTitleCase = function (s) { var words = _getWords(s), result = '', i, word; for (i = 0; i < words.length; i++) { word = words[i]; result += word.charAt(0).toUpperCase() + word.substr(1).toLowerCase() + ' '; } return Str.trimEnd(result); }; /** * Convert any string to snake case. * * @param s */ Str.toSnakeCase = function (s) { var words = _getWords(s), result = '', i, word; for (i = 0; i < words.length; i++) { word = words[i]; result += word.toLowerCase() + '_'; } return Str.trimEnd(result, '_'); }; /** * Convert any string to-kebab-case. * * @param s */ Str.toKebabCase = function (s) { var words = _getWords(s), result = '', i, word; for (i = 0; i < words.length; i++) { word = words[i]; result += word.toLowerCase() + '-'; } return Str.trimEnd(result, '-'); }; }(window, window._Str = {}));