前端开发工具类方法、h5优化样式以及富文本解析js

103 阅读6分钟

一、 开发工具类方法

/* eslint-disable no-irregular-whitespace */
// 算法
// 获取数据类型
const getType = (obj) => {
    const class2type = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regexp',
        '[object Object]': 'object',
        '[object Error]': 'error',
        '[object Symbol]': 'symbol'
    }

    if (obj == null) {
        return obj + ''
    }
    // javascript高级程序设计中提供了一种方法,可以通用的来判断原始数据类型和引用数据类型
    const str = Object.prototype.toString.call(obj)
    console.log('str', str)
    console.log('typeof obj', typeof obj)
    return typeof obj === 'object' || typeof obj === 'function' ? class2type[str] || 'object' : typeof obj
}

// 拆解URL参数中queryString
const getUrlQuery = (queryStr) => {
    //const [, query] = queryStr.split('?')
    // 去除hash标识
    const [query,] = queryStr.split('?')[1].split('#')
    if (query) {
        return query.split('&').reduce((pre, cur) => {
            const [key, val] = cur.split('=')
            pre[key] = decodeURIComponent(val)
            return pre
        }, {})
    }
    return {}
}

// 字符串相加
/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
const addStrings = function (num1, num2) {
    if (num1 === num2 && num1 === "0") {
        return num1
    }

    //  切割成数组倒过来,倒过来是因为可能存在长度不一的字符串
    num1 = num1.split("").reverse();
    num2 = num2.split("").reverse();
    const len = Math.max(num1.length, num2.length);
    let flag = 0;
    const result = [];

    for (let i = 0; i < len; i++) {
        const n1 = +num1[i] || 0;
        const n2 = +num2[i] || 0;
        let sum = n1 + n2 + flag;
        flag = 0;

        //  进1
        if (sum > 9) {
            sum -= 10
            flag = 1
        }
        result.push(sum);
    }
    //  仍存在进1标志,手动进1
    if (flag) {
        result.push(flag)
    }

    return result.reverse().join("");
}

// 翻转字符串里的单词
const reverseWords = function (s) {
    return s.trim().split(/\s+/).reverse().join(' ');
};

// 二分查找
const binarySearch = function (nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        const mid = Math.floor((right - left) / 2) + left;
        const num = nums[mid];
        if (num === target) {
            return mid;
        } else if (num > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return -1;
}

// 两个数组的交集
const intersection = function (nums1, nums2) {
    const set_intersection = (set1, set2) => {
        if (set1.size > set2.size) {
            return set_intersection(set2, set1);
        }
        const intersection = new Set();
        for (const num of set1) {
            if (set2.has(num)) {
                intersection.add(num);
            }
        }
        return [...intersection];
    }

    const set1 = new Set(nums1);
    const set2 = new Set(nums2);
    return set_intersection(set1, set2);
};

// 两数之和下标
const twoSumIndex = (nums, target) => {
    const prevNums = {};                    // 存储出现过的数字,和对应的索引               

    for (let i = 0; i < nums.length; i++) {       // 遍历元素   
        const curNum = nums[i];                     // 当前元素   
        const targetNum = target - curNum;          // 满足要求的目标元素   
        const targetNumIndex = prevNums[targetNum]; // 在prevNums中获取目标元素的索引
        if (targetNumIndex !== undefined) {         // 如果存在,直接返回 [目标元素的索引,当前索引]
            return [targetNumIndex, i];
        } else {                                    // 如果不存在,说明之前没出现过目标元素
            prevNums[curNum] = i;                     // 存入当前的元素和对应的索引
        }
    }
}

// 基本计算器(字符串)
const calculate = function (s) {
    const ops = [1];
    let sign = 1;

    let ret = 0;
    const n = s.length;
    let i = 0;
    while (i < n) {
        if (s[i] === ' ') {
            i++;
        } else if (s[i] === '+') {
            sign = ops[ops.length - 1];
            i++;
        } else if (s[i] === '-') {
            sign = -ops[ops.length - 1];
            i++;
        } else if (s[i] === '(') {
            ops.push(sign);
            i++;
        } else if (s[i] === ')') {
            ops.pop();
            i++;
        } else {
            let num = 0;
            while (i < n && !(isNaN(Number(s[i]))) && s[i] !== ' ') {
                num = num * 10 + s[i].charCodeAt() - '0'.charCodeAt();
                i++;
            }
            ret += sign * num;
        }
    }
    return ret;
}

// 验证IP地址
const validIPAddress = (queryIP) => {
    return queryIP.match(/^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)($|(?!\.$)\.)){4}$/) ? "IPv4" :
        queryIP.match(/^(([\da-fA-F]{1,4})($|(?!:$):)){8}$/) ? "IPv6" : "Neither";
}

// 过滤 JSON 中的无效条目
const filterByID = (item) => {
    if (Number.isFinite(item.id) && item.id !== 0) {
        return true;
    }
    return false;
}

// 判断某个字符串长度(要求支持表情)
const unicodeLength = (str) => {
    return Array.from(str).length
}

// 循环递归深拷贝
const deepClone = (obj, hash = new WeakMap()) => {
    if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
    if (typeof obj !== "object") return obj;
    // 是对象的话就要进行深拷贝
    if (hash.get(obj)) return hash.get(obj);
    let cloneObj = new obj.constructor();
    // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
    hash.set(obj, cloneObj);
    for (let key in obj) {
        //   if (obj.hasOwnProperty(key)) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {

            // 实现一个递归拷贝
            cloneObj[key] = deepClone(obj[key], hash);
        }
    }
    return cloneObj;
}

//  判断页面是通过PC端还是移动端访问
const isMobile = () => {
    if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) {
        // 当前设备是移动设备
        return true
    }
    return false
}

// 获取全局对象
const getGlobal = () => {
    if (typeof self !== 'undefined') {
        return self
    }
    if (typeof window !== 'undefined') {
        return window
    }
    if (typeof global !== 'undefined') {
        return global
    }
    throw new Error('无法找到全局对象')
}

// 归并排序
const mergeSort = (arr) => {
    let array = mergeSortRec(arr)
    return array
}
// 若分裂后的两个数组长度不为 1,则继续分裂
// 直到分裂后的数组长度都为 1,
// 然后合并小数组
const mergeSortRec = (arr) => {
    let lenth = arr.length
    if (lenth == 1) {
        return arr
    }
    let mid = Math.floor(lenth / 2)
    let left = arr.slice(0, mid)
    let right = arr.slice(mid, lenth)
    return merge(mergeSortRec(left), mergeSortRec(right))
}

const merge = (left, right) => {
    let result = [],
        ileft = 0,
        iright = 0
    while (ileft < left.length && iright < right.length) {
        if (left[ileft] < right[iright]) {
            // eslint-disable-next-line no-irregular-whitespace
            result.push(left[ileft++])
        } else {
            result.push(right[iright++])
        }
    }
    while (ileft < left.length) {
        result.push(left[ileft++])
    }
    while (iright < right.length) {
        result.push(right[iright++])
    }
    return result
}

// 数组扁平化、去重、排序
const newArray = (arr) => {
    while (arr.some(Array.isArray)) {
        arr = [].concat(...arr)
    }
    arr = [...new Set(arr)].sort((a, b) => a - b)
    return arr
}

// add方法
const add = (...args) => {
    const _add = (...args1) => {
        return add(...args, ...args1)
    }
    _add.value = () => args.reduce((t, e) => t + e)
    return _add
}

// 快速排序算法
const sortArray = (nums) => {
    quickSort(0, nums.length - 1, nums);
    return nums;
}

const quickSort = (start, end, arr) => {
    if (start < end) {
        const mid = sort(start, end, arr);
        quickSort(start, mid - 1, arr);
        quickSort(mid + 1, end, arr);
    }
}

const sort = (start, end, arr) => {
    const base = arr[start];
    let left = start;
    let right = end;
    while (left !== right) {
        while (arr[right] >= base && right > left) {
            right--;
        }
        arr[left] = arr[right];
        while (arr[left] <= base && right > left) {
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = base;
    return left;
}

// 带并发的异步调度器 Scheduler
// 页面引用 const scheduler = new Scheduler();
class Scheduler {
    constructor() {
        this.waitTasks = []; // 待执行的任务队列
        this.excutingTasks = []; // 正在执行的任务队列
        this.maxExcutingNum = 2// 允许同时运行的任务数量
    }

    add(promiseMaker) {
        if (this.excutingTasks.length < this.maxExcutingNum) {
            this.run(promiseMaker);
        } else {
            this.waitTasks.push(promiseMaker);
        }
    }

    run(promiseMaker) {
        const len = this.excutingTasks.push(promiseMaker);
        const index = len - 1;
        promiseMaker().then(() => {
            this.excutingTasks.splice(index, 1);
            if (this.waitTasks.length > 0) {
                this.run(this.waitTasks.shift());
            }
        });
    }
}
// Promise 调度器
class PromiseQueue{
    constructor(tasks,concurrentCount=1){
        this.totals = tasks.length;
        this.todo =tasks;
        this.count = concurrentCount;
        this.running =[];
        this.complete =[];
        
    }

    runNext(){
        return (
            this.running.length < this.count
            && this.todo.length
        )
    }

    run(){
        while(this.runNext()){
            let promise = this.todo.shift();
            promise.then(()=>{
                this.complete.push(this.running.shift());
                this.run();
            })

            this.running.push(promise)
        }
    }
}

// 浮点数保留两位小数

// 将浮点数四舍五入,取小数点后2位
// 注⚠️,数据类型不变。
const toDecimal = (x) => {
    var f = parseFloat(x);
    if (isNaN(f)) {
        return;
    }
    f = Math.round(x * 100) / 100;
    return f;
}

// 强制保留2位小数,如:2,会在2后面补上00.即2.00
// 注意⚠️,数据类型变为字符串类型。
const toDecimal2 = (x) => {
    var f = parseFloat(x);
    if (isNaN(f)) {
        return false;
    }
    var f = Math.round(x * 100) / 100;
    var s = f.toString();
    var rs = s.indexOf('.');
    if (rs < 0) {
        rs = s.length;
        s += '.';
    }
    while (s.length <= rs + 2) {
        s += '0';
    }
    return s;
}

// 保留两位小数 浮点数四舍五入 位数不够 不补0
// 注意⚠️,数据类型不变。
const fomatFloat = (src, pos) => {
    return Math.round(src * Math.pow(10, pos)) / Math.pow(10, pos);
}

//加法函数,用来得到精确的加法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
//调用:accAdd(arg1,arg2)
//返回值:arg1加上arg2的精确结果
const accAdd = (arg1, arg2) => {
    var r1, r2, m;
    try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
    m = Math.pow(10, Math.max(r1, r2))
    return (arg1 * m + arg2 * m) / m
}
//给Number类型增加一个add方法,调用起来更加方便。
Number.prototype.add = function (arg) {
    return accAdd(arg, this);
}

//减法函数,用来得到精确的减法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
//调用:accSub(arg1,arg2)
//返回值:arg1减去arg2的精确结果
const accSub = (arg1, arg2) => {
    var r1, r2, m, n;
    try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
    m = Math.pow(10, Math.max(r1, r2));
    //last modify by deeka
    //动态控制精度长度
    n = (r1 >= r2) ? r1 : r2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}

//除法函数,用来得到精确的除法结果
//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精确结果
const accDiv = (arg1, arg2) => {
    var t1 = 0, t2 = 0, r1, r2;
    try { t1 = arg1.toString().split(".")[1].length } catch (e) { }
    try { t2 = arg2.toString().split(".")[1].length } catch (e) { }
    while (Math) {
        r1 = Number(arg1.toString().replace(".", ""))
        r2 = Number(arg2.toString().replace(".", ""))
        return (r1 / r2) * Math.pow(10, t2 - t1);
    }
}
//给Number类型增加一个div方法,调用起来更加方便。
Number.prototype.div = function (arg) {
    return accDiv(this, arg);
}

//乘法函数,用来得到精确的乘法结果
//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用:accMul(arg1,arg2)
//返回值:arg1乘以arg2的精确结果
const accMul = (arg1, arg2) => {
    var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
    try { m += s1.split(".")[1].length } catch (e) { }
    try { m += s2.split(".")[1].length } catch (e) { }
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
}
//给Number类型增加一个mul方法,调用起来更加方便。
Number.prototype.mul = function (arg) {
    return accMul(arg, this);
}

// obj是获取属性的对象,path是路径,fallback是默认值
const getAttributeObj = (obj, path, fallback) => {
    const parts = path.split(".");
    const key = parts.shift();
    if (typeof obj[key] !== "undefined") {
        return parts.length > 0 ?
        getAttributeObj(obj[key], parts.join("."), fallback) :
        obj[key];
    }
    // 如果没有找到key返回fallback
    return fallback;
}
// 防止XSS攻击:对接口返回的数据进行过滤和转义处理
const escapeHtml = (unsafe) => {
    return unsafe
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
}

// 截断数字
const toFixedNum = (n, fixed) => `${n}`.match(new RegExp(`^-?\d+(?:.\d{0,${fixed}})?`))[0]

//四舍五入
const roundNum = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)

// 数字补零
const replenishZero = (num, len, zero = 0) => num.toString().padStart(len, zero)

// 字符串转对象
const strParse = (str) => JSON.parse(str.replace(/(\w+)\s*:/g, (_, p1) => `"${p1}":`).replace(/\'/g, "\""))

// uuid
const uuid = (a) => (a ? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid))
uuid()

// 强制等待
const sleep = async (t) => new Promise((resolve) => setTimeout(resolve, t));

//发布订阅
class Observer {
    caches = {}; // 事件中心
    
    // eventName事件名-独一无二, fn订阅后执行的自定义行为
    on (eventName, fn){ 
      this.caches[eventName] = this.caches[eventName] || [];
      this.caches[eventName].push(fn);
    }
    
    // 发布 => 将订阅的事件进行统一执行
    emit (eventName, data) { 
      if (this.caches[eventName]) {
        this.caches[eventName]
        .forEach(fn => fn(data));
      }
    }
    // 取消订阅 => 若fn不传, 直接取消该事件所有订阅信息
    off (eventName, fn) { 
      if (this.caches[eventName]) {
        const newCaches = fn 
          ? this.caches[eventName].filter(e => e !== fn) 
          : [];
        this.caches[eventName] = newCaches;
      }
    }
  
}
// 判断数据类型
const dataType = (tgt, type) => {
    const dataType = Object.prototype.toString.call(tgt).replace(/\[object (\w+)\]/, "$1").toLowerCase();
    return type ? dataType === type : dataType;
}
// 是否为空数组
const isNullArray = (arr) => {
 return Array.isArray(arr) && !arr.length;
}

// 是否为空对象
const isNullObject = (obj) => {
 return dataType(obj, "object") && !Object.keys(obj).length;
}

const FilterXss = (content) => {
    let elem = document.createElement("div");
    elem.innerText = content;
    const result = elem.innerHTML;
    elem = null;
    return result;
}

// URL参数反序列化
// 正则表达式需要转义的字符:* . ? + ^ $ | \ / [ ] ( ) { }
const ParseUrlSearch = () => {
    return location.search.replace(/(\^?)|(&\$)/g, "").split("&").reduce((t, v) => {
        const [key, val] = v.split("=");
        t[key] = decodeURIComponent(val);
        return t;
    }, {});
}

const StringifyUrlSearch = (search = {}) => {
    return Object.entries(search).reduce(
        (t, v) => `${t}${v[0]}=${encodeURIComponent(v[1])}&`,
        Object.keys(search).length ? "?" : ""
    ).replace(/&$/, "");
}
/**
 * 16进制颜色值转RGB
 * @param  {String} hex 16进制颜色字符串
 * @return {String}     RGB颜色字符串
 */
 const hexToRGB = (hex) => {
    var hexx = hex.replace('#', '0x')
    var r = hexx >> 16
    var g = hexx >> 8 & 0xff
    var b = hexx & 0xff
    return `rgb(${r}, ${g}, ${b})`
}

/**
 * RGB颜色转16进制颜色
 * @param  {String} rgb RGB进制颜色字符串
 * @return {String}     16进制颜色字符串
 */
 const RGBToHex = (rgb) => {
    var rgbArr = rgb.split(/[^\d]+/)
    var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3]
    return '#'+ color.toString(16)
}

export {
    // 获取数据类型
    getType,
    // 拆解URL参数中queryString
    getUrlQuery,
    // 字符串相加
    addStrings,
    // 翻转字符串里的单词
    reverseWords,
    // 二分查找
    binarySearch,
    // 两个数组的交集
    intersection,
    // 两数之和下标
    twoSumIndex,
    // 基本计算器(字符串)
    calculate,
    // 验证IP地址
    validIPAddress,
    // 过滤 JSON 中的无效条目
    filterByID,
    // 判断某个字符串长度(要求支持表情)
    unicodeLength,
    // 循环递归深拷贝
    deepClone,
    // 判断页面是通过PC端还是移动端访问
    isMobile,
    // 获取全局对象
    getGlobal,
    // 归并排序
    mergeSort,
    // 快速排序算法
    sortArray,
    // 数组扁平化、去重、排序
    newArray,
    // add()()()方法
    add,
    // 带并发的异步调度器 Scheduler
    Scheduler,
    // Promise 调度器
    PromiseQueue,
    // 浮点数保留两位小数
    toDecimal,
    toDecimal2,
    fomatFloat,
    // 浮点数加减乘除
    accAdd,
    accSub,
    accMul,
    accDiv,
    // 递归获取对象属性
    getAttributeObj,
    // 防止XSS攻击:对接口返回的数据进行过滤和转义处理
    escapeHtml,
    // 截断数字
    toFixedNum,
    // 四舍五入
    roundNum,
    // 数字补零
    replenishZero,
    // 字符串转对象
    strParse,
    // uuid
    uuid,
    // 强制等待
    sleep,
    // 发布订阅
    Observer,
    // 是否为空数组
    isNullArray,
    // 是否为空对象
    isNullObject,
    // 判断数据类型
    dataType,
    // 过滤XSS
    FilterXss,
    // URL参数反序列化
    ParseUrlSearch,
    // URL参数序列化
    StringifyUrlSearch,
    // 16进制颜色值转RGB
    hexToRGB,
    // RGB颜色转16进制颜色
    RGBToHex,
}

二、 h5优化样式

// 移动端H5兼容
body {
    // 苹果系统上非<body>元素的滚动操作可能会存在卡顿
    //-webkit-overflow-scrolling: touch;
    //在手机端 iOS 13 系统中,-webkit-overflow-scrolling:touch 也会使 z-index 失效,将 touch 换成 unset
    -webkit-overflow-scrolling: unset;
    // 禁止屏幕抖动
    padding-right: calc(100vw - 100%); 
}
.elem {
    overflow: auto;
}
// 禁止滚动传播
.overscroll-contain {
    overscroll-behavior: contain;
}
// 禁止长按操作
* {
    /* pointer-events: none; */ /* 微信浏览器还需附加该属性才有效 */
    user-select: none; /* 禁止长按选择文字 */
    -webkit-touch-callout: none;
    // 禁止字体调整
    text-size-adjust: 100%;
    // 禁止高亮显示:触摸元素会出现半透明灰色遮罩,不想要!
    -webkit-tap-highlight-color: transparent;
    // 识别文本换行
    white-space: pre-line;
    // 屏幕旋转为横屏时,字体大小会变(禁止)
    -webkit-text-size-adjust: 100%;
}
// 声明user-select:none会让<input>和<textarea>无法输入文本,可对其声明user-select:auto排除在外。
input,
textarea {
    user-select: auto;
}
.transform-3d {
    // 禁止动画闪屏
    perspective: 1000;
    backface-visibility: hidden;
    transform-style: preserve-3d;
    // 开启硬件加速
    transform: translate3d(0, 0, 0); 
    /* transform: translateZ(0); */
}
// 美化滚动占位
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
    background-color: transparent;
}
::-webkit-scrollbar-track {
    background-color: transparent;
}
::-webkit-scrollbar-thumb {
    border-radius: 3px;
    background-image: linear-gradient(135deg, #09f, #3c9);
}
// 美化输入占位:输入框占位文本太丑,::-webkit-input-placeholder来帮你。
input::-webkit-input-placeholder {
    color: #66f;
}
// 对齐输入占位
input {
    line-height: normal;
}

// input密码框password在ie/edge浏览器下默认的icon去除
// ie
input::-ms-reveal {
    display: none;
}
input::-ms-clear {
    display: none;
}
// edge
input::-o-clear {
    display: none;
}

::-ms-clear,
::-ms-reveal {
    display: none;
}

// 对齐下拉选项
// 下拉框选项默认向左对齐,是时候改改向右对齐了。
select option {
    direction: rtl;
}
// 修复点击无效
// 在苹果系统上有些情况下非可点击元素监听click事件可能会无效,针对该情况只需对不触发click事件的元素声明cursor:pointer就能解决。
.cursor {
    cursor: pointer;
}

// 画三角形
.triangle {
    border: 50px solid transparent;
    width: 0;
    height: 0;
    &.left {
        border-right-color: #f66;
    }
    &.right {
        border-left-color: #f66;
    }
    &.top {
        border-bottom-color: #f66;
    }
    &.bottom {
        border-top-color: #f66;
    }
    &.left-top {
        border-left-color: #f66;
        border-top-color: #f66;
    }
    &.left-bottom {
        border-left-color: #f66;
        border-bottom-color: #f66;
    }
    &.right-top {
        border-right-color: #f66;
        border-top-color: #f66;
    }
    &.right-bottom {
        border-right-color: #f66;
        border-bottom-color: #f66;
    }
}

// 禁止长按
.long-press{
    // 禁止长按图片保存
    img {
        -webkit-touch-callout: none;
        pointer-events: none; // 像微信浏览器还是无法禁止,加上这行样式即可
    }
  
    // 禁止长按选择文字
    div {
        -webkit-user-select: none;
    }
  
     // 禁止长按呼出菜单
    div {
        -webkit-touch-callout: none;
    }
  
}

三、富文本解析js

/*
graceUI rich-text 加强工具
link : graceui.hcoder.net
author : 5213606@qq.com 深海

*/

// 正则变量
var graceRichTextReg;

// 批量替换的样式 [ 根据项目需求自行设置 ]
var GRT = [	// div 样式	['div', "line-height:2em;"],
	// h1 样式
	['h1', "font-size:3em; line-height:1.5em;"],
	// h2 样式
	['h2', "font-size:2em; line-height:1.8em;"],
	// h3 样式
	['h3', "font-size:1.6em; line-height:2em;"],
	// h4 样式
	['h4', "font-size:1.2em; line-height:2em;"],
	// h5 样式
	['h5', "font-size:1em; line-height:2em;"],
	// h6 样式
	['h6', "font-size:0.9em; line-height:2em;"],
	// p 样式
	['p', "margin:0;padding:0;overflow:hidden;"],
	// b 样式
	['b', "font-size:1em; line-height:2em;"],
	// strong 样式
	['strong', "font-size:1em; line-height:2em;"],
	// code 样式
	['code', "font-size:1em; line-height:1.2em; background:#F6F7F8; padding:8px 2%; width:96%;"],
	// img 样式
	['img', "width:100%; margin:0px 0;float:left;"],
	// blockquote
	['blockquote', "font-size:1em; border-left:3px solid #D1D1D1; line-height:2em; border-radius:5px; background:#F6F7F8; padding:8px 2%;"],
	// li 样式
	['ul', "padding:5px 0; list-style:none; padding:0; margin:0;"],
	['li', "line-height:1.5em; padding:5px 0; list-style:none; padding:0; margin:0; margin-top:10px;"],
	// table
	['table', "width:100%; border-left:1px solid #F2F3F4; border-top:1px solid #F2F3F4;"],
	['th', "border-right:1px solid #F2F3F4; border-bottom:1px solid #F2F3F4;"],
	['td', "border-right:1px solid #F2F3F4; border-bottom:1px solid #F2F3F4; padding-left:5px;"]
];


module.exports = {
	format : function(html){
// 		html = html.replace(/<pre.*pre>?/gis, function(word){
// 			word =  word.replace(/[\n]/gi,'<br />');
// 			word =  word.replace(/    /gi,'<span style="padding-left:2em;"></span>');
// 			return word.replace(/[\t]/gi, '<span style="padding-left:2em;"></span>');
// 		});
// console.log(html)
		html = html.replace(/<pre/gi, '<p ');
		html = html.replace(/<\/pre/gi,"</p");
		for(let i = 0; i < GRT.length; i++){
			graceRichTextReg = new RegExp('<'+GRT[i][0]+'>|<'+GRT[i][0]+' (.*?)>', 'gi');
			html = html.replace(graceRichTextReg , function(word){
				// 分析 dom 上是否带有 style=""
				if(word.indexOf('style=') != -1){
					var regIn = new RegExp('<' + GRT[i][0] + '(.*?)style="(.*?)"(.*?)(/?)>', 'gi');
					return word.replace(regIn, '<'+ GRT[i][0] +'$1style="$2 ' + GRT[i][1] +'"$3$4>');
				}else{
					var regIn = new RegExp('<' + GRT[i][0] + '(.*?)(/?)>', 'gi');
					return word.replace(regIn, '<'+ GRT[i][0] +'$1 style="' + GRT[i][1] +'$2">');
				}
			});
		}
		return html;
	}
}