UNPKG

@ivujs/i-utils

Version:

前端模块化 JavaScript 工具库

369 lines (366 loc) 11.5 kB
import { isNull, isNaN } from '../validate/index.mjs'; /** * @module 字符串 */ /* 字符串处理 */ /** * 字符串中是否包含指定的元素 * @param {string} value 包含的元素 * @param {string} str 查找的字符串 * @returns {boolean} 返回true和false */ function inString(value, str) { return str.includes(value); } /** * 去除字符串前后位置空格 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function trim(value) { return value.replace(/(^\s*)|(\s*$)/g, ""); } /** * 去除字符串开始位置的空格 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function trimStart(value) { return value.replace(/(^\s*)/g, ""); } /** * 去除字符串结束位置的空格 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function trimEnd(value) { return value.replace(/(\s*$)/g, ""); } /** * 去除字符串中全部的空格 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function trimAll(value) { return value.replace(/\s+/g, ""); } /** * 替换所有指定字符串为新的字符串 * @param {string} value 参数 * @param {string} oldSubstr 需要替换的字符串 * @param {string} newSubstr 替换后的字符串 * @returns {string} 返回处理后的字符串 */ function replaceAll(value, oldSubstr, newSubstr) { return value.replace(new RegExp(oldSubstr, "gm"), newSubstr); } /* 字符串转换 */ /** * 字符串转大写 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toUpperCase(value) { return String(value).toLocaleUpperCase(); } /** * 字符串转小写 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toLowerCase(value) { return String(value).toLocaleLowerCase(); } /** * 转为 snake_case 下划线命名 * @description 支持 驼峰命名,短横命名,帕斯卡命名 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toSnakeCase(value) { // 驼峰 if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { return value.replace(/([A-Z])/g, "_$1").toLowerCase(); } // 短横 else if (value.indexOf("-") > 0) { return value.replace(/-/g, "_").toLowerCase(); } // 帕斯卡 else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { value = value.charAt(0).toLowerCase() + value.slice(1); return value.replace(/([A-Z])/g, "_$1").toLowerCase(); } // 不符合格式 else { throw new TypeError(`toSnakeCase: value should be a string`); } } /** * 转为 kebab-case 短横命名 * @description 支持 下划线,驼峰命名,帕斯卡命名 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toKebabCase(value) { // 下划线 if (value.indexOf("_") > 0) { return value.replace(/_/g, "-").toLowerCase(); } // 驼峰 else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { return value.replace(/([A-Z])/g, "-$1").toLowerCase(); } // 帕斯卡 else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { const newStr = value.charAt(0).toLowerCase() + value.slice(1); return newStr.replace(/([A-Z])/g, "-$1").toLowerCase(); } // 不符合格式 else { throw new TypeError("toKebabCase: value should be a string"); } } /** * 转为 camelCase 驼峰命名 * @description 支持 下划线命名,短横命名,帕斯卡命名 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toCamelCase(value) { // 下划线 if (value.indexOf("_") > 0) { return value.replace(/\_(\w)/g, function (all, letter) { return letter.toUpperCase(); }); } // 短横 else if (value.indexOf("-") > 0) { return value.replace(/\-(\w)/g, function (all, letter) { return letter.toUpperCase(); }); } // 帕斯卡 else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { return value.charAt(0).toLowerCase() + value.slice(1); } // 不符合格式 else { throw new TypeError("toCamelCase: value should be a string"); } } /** * 转为 PascalCase 帕斯卡命名 * @description 支持 下划线命名,短横命名,驼峰命名 * @param {string} value 参数 * @returns {string} 返回处理后的字符串 */ function toPascalCase(value) { // 下划线 if (value.indexOf("_") > 0) { const newStr = value.replace(/\_(\w)/g, function (all, letter) { return letter.toUpperCase(); }); return newStr.charAt(0).toUpperCase() + newStr.slice(1); } // 短横 else if (value.indexOf("-") > 0) { const newStr = value.replace(/\-(\w)/g, function (all, letter) { return letter.toUpperCase(); }); return newStr.charAt(0).toUpperCase() + newStr.slice(1); } // 驼峰 else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf("-") > 0 || value.indexOf("_") > 0)) { return value.charAt(0).toUpperCase() + value.slice(1); } // 不符合格式 else { throw new TypeError("toPascalCase: value should be a string"); } } /* 字符串格式化 */ /** * 数字前补齐0达到指定位数 * @description 相当于原生的 padStart(2,'0') * @param {number|string} value 补零的数字 * @param {number} maxLength 补齐0后的最大长度,默认2位 * @returns {string} 返回补0后指定位数的字符串 */ function padZeroStart(value, maxLength = 2) { value = String(value).trim(); if (maxLength < 0) { throw new TypeError("padZeroStart: maxLength should be greater than 0"); } if (isNull(value) || isNaN(value)) { throw new TypeError("padZeroStart: value must be a valid number or numeric string"); } // 前面补0 let len = value.toString().length; while (len < maxLength) { value = "0" + value; len++; } return value; } /** * 数字后补齐0达到指定位数 * @description 相当于原生的 padEnd(2,'0') * @param {number|string} value 补零的数字 * @param {number} maxLength 补齐0后的最大长度,默认2位 * @returns {string} 返回补0后指定位数的字符串 */ function padZeroEnd(value, maxLength = 2) { value = String(value).trim(); if (maxLength < 0) { throw new TypeError("padZeroEnd: maxLength should be greater than 0"); } if (isNull(value) || isNaN(value)) { throw new TypeError("padZeroEnd: value must be a valid number or numeric string"); } // 后面补0 let len = value.toString().length; while (len < maxLength) { value = value + "0"; len++; } return value; } /** * 格式化为标题样式 * @param {string} value 字符串值 * @returns {string} 返回格式化后的标题样式 */ function formatTitle(value) { if (!value) return ""; return value .split(/(?=[A-Z])|[\.\-\s_]/) .map((s) => s.trim()) .filter((s) => !!s) .map((s) => toPascalCase(s.toLowerCase())) .join(" "); } /** * 格式化字符串模版 * @param {string} value 字符串值 * @param {Object} data 模版数据 * @returns {string} 返回格式化后的模版字符串 */ function formatTemplate(value, data) { if (!value) return ""; return Array.from(value.matchAll(/\{\{(.+?)\}\}/g)).reduce((acc, match) => { return acc.replace(match[0], data[match[1]]); }, value); } /** * 格式化千分位数字 * @description 支持任意数据传参,如果非数字则不会格式化,并返回原数据 * @param {number|string} num 数字 * @returns {string} 返回格式化后的千分位数字 */ function formatThousand(num) { if (!parseFloat(String(num))) return String(num); num = String(num); const regex = num.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g; return num.replace(regex, "$1,"); } /** * 格式化人民币金额大写 * @param {number|string} money 金额 * @returns {string} 返回金额大写 */ function formatRmbChinese(money) { // 汉字的数字 const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]; // 基本单位 const cnIntRadiance = ["", "拾", "佰", "仟"]; // 对应整数部分扩展单位 const cnIntUnits = ["", "万", "亿", "兆"]; // 对应小数部分单位 const cnDecUnits = ["角", "分", "毫", "厘"]; // 整数金额时后面跟的字符 const cnInteger = "整"; // 整型完以后的单位 const cnIntLast = "元"; // 最大处理的数字 const maxNum = Number("999999999999999.9999"); // 金额整数部分 let integerNum; // 金额小数部分 let decimalNum; // 输出的中文金额字符串 let chineseStr = ""; // 分离金额后用的数组,预定义 let parts; if (money === "") { // 不能用== return ""; } money = parseFloat(String(money)); if (money >= maxNum) { // 超出最大处理数字,抛出异常 throw new TypeError("formatRmbChinese: calculated number overflow"); } if (money === 0) { chineseStr = cnNums[0] + cnIntLast + cnInteger; return chineseStr; } // 转换为字符串 money = money.toString(); if (money.indexOf(".") === -1) { integerNum = money; decimalNum = ""; } else { parts = money.split("."); integerNum = parts[0]; decimalNum = parts[1].substr(0, 4); } // 获取整型部分转换 if (parseInt(integerNum, 10) > 0) { let zeroCount = 0; const IntLen = integerNum.length; for (let i = 0; i < IntLen; i++) { const n = integerNum.substr(i, 1); const p = IntLen - i - 1; const q = p / 4; const m = p % 4; if (n === "0") { zeroCount++; } else { if (zeroCount > 0) { chineseStr += cnNums[0]; } // 归零 zeroCount = 0; chineseStr += cnNums[parseInt(n)] + cnIntRadiance[m]; } if (m === 0 && zeroCount < 4) { chineseStr += cnIntUnits[q]; } } chineseStr += cnIntLast; } // 小数部分 if (decimalNum !== "") { const decLen = decimalNum.length; for (let i = 0; i < decLen; i++) { const n = decimalNum.substr(i, 1); if (n !== "0") { chineseStr += cnNums[Number(n)] + cnDecUnits[i]; } } } if (chineseStr === "") { chineseStr += cnNums[0] + cnIntLast + cnInteger; } else if (decimalNum === "") { chineseStr += cnInteger; } return chineseStr; } export { formatRmbChinese, formatTemplate, formatThousand, formatTitle, inString, padZeroEnd, padZeroStart, replaceAll, toCamelCase, toKebabCase, toLowerCase, toPascalCase, toSnakeCase, toUpperCase, trim, trimAll, trimEnd, trimStart };