鍍金池/ 問答/Java  HTML/ 各位大佬,幫我看一下js正則反向引用的問題(微信小程序內(nèi))

各位大佬,幫我看一下js正則反向引用的問題(微信小程序內(nèi))

描述:后臺給出一長串字符串,里面包括文本和鏈接,目前我需要做的就是將串解析成下面預(yù)期結(jié)果那樣的一個(gè)數(shù)組,但是在正則引用那里出現(xiàn)了問題,假設(shè)原串中有三個(gè)鏈接,當(dāng)前我自己的解析方法會造成最后一個(gè)覆蓋前面兩個(gè)鏈接的問題,不是預(yù)期的結(jié)果,麻煩各位大神有好的辦法可以交流或者指導(dǎo)一下,謝謝

微信小程序內(nèi)不支持直接操作dom

//原串
var desc = '出于HTTPS的安全策略,瀏覽器會阻斷HTTPS上的非安全請求(HTTP)請求,但是我們可以使用被動(dòng)混合內(nèi)容的方式來跨越這個(gè)安全策略' +
    '<a href="web://http://api.520.com:8891/clientpage/money.php">去看看怎么請求</a>' +
    '這時(shí)候,瀏覽器只會在控制臺報(bào)warning,而不會block我們的請求。<a href="web://http://api.520.com:8891/activity/convention.php">查看規(guī)則</a>。' +
    '因?yàn)楣粽呖梢酝ㄟ^不安全的HTTP內(nèi)容來攻擊安全的HTTPS頁面<a href="in://goplay">去交互</a>';
    
    


//目標(biāo)串,類似這樣,需要將原串里面的多個(gè)a鏈接處理成規(guī)定形式,并保持原串的各位置不變
/*
* '出于HTTPS的安全策略,瀏覽器會阻斷HTTPS上的非安全請求(HTTP)請求,但是我們可以使用被動(dòng)混合內(nèi)容的方式來跨越這個(gè)安全策略' +
    '<a  +
    '這時(shí)候,瀏覽器只會在控制臺報(bào)warning,而不會block我們的請求。<a  +
    '因?yàn)楣粽呖梢酝ㄟ^不安全的HTTP內(nèi)容來攻擊安全的HTTPS頁面<a href="/pages/goplay/goplay">去綁定</a>'
*
* */


//預(yù)期結(jié)果
[
    {
        'MsgType'   : 'text',
        'MsgContent': '出于HTTPS的安全策略,瀏覽器會阻斷HTTPS上的非安全請求(HTTP)請求,但是我們可以使用被動(dòng)混合內(nèi)容的方式來跨越這個(gè)安全策略'
    },
    {
        'MsgType'   : 'navigator',
        'MsgContent': 'https://api.520.com/clientpage/money.php?url=xxx&title=xxx',
        'MsgParam':'去看看怎么請求',
    },
    {
        'MsgType'   : 'text',
        'MsgContent': '這時(shí)候,瀏覽器只會在控制臺報(bào)warning,而不會block我們的請求。'
    },
    {
        'MsgType'   : 'navigator',
        'MsgContent': 'https://api.520.com/activity/convention.php?url=xxx&title=xxx',
        'MsgParam':'查看規(guī)則',
    },
    {
        'MsgType'   : 'text',
        'MsgContent': '因?yàn)楣粽呖梢酝ㄟ^不安全的HTTP內(nèi)容來攻擊安全的HTTPS頁面'
    },
    {
        'MsgType'   : 'navigator',
        'MsgContent': '/pages/goplay/goplay',
        'MsgParam':'去交互',
    },
]


var MsgBody = [];

var MsgContent = null,MsgType = null;

var tmsg = '', amsg, restMsgIndex = null
var expr = /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/mg
amsg = desc.match(expr); //匹配是否存在a鏈接

console.log(amsg)
if (!amsg || amsg.length < 1) {
    MsgType = 'text';
    MsgContent = desc;
    MsgBody.push({
        'MsgType'   : MsgType,
        'MsgContent': MsgContent
    })
}
else  //存在a鏈接的情況
{

    var len = amsg.length; //a鏈接的個(gè)數(shù)
    console.log(len)
    for (var i = 0; i < len; i++) {
        tmsg = desc.substring(0, desc.indexOf(amsg[i])); //最前面的文字

        if (tmsg) {  //以文本開頭
            MsgType = 'text';
            MsgContent = tmsg;
            MsgBody.push({
                'MsgType'   : MsgType,
                'MsgContent': MsgContent
            })
        }

        var pattern1 = new RegExp("in://", "ig");//以,分割   in://mytrends

        var pattern2 = new RegExp("web://", "ig");//以,分割  web://http://api.yuepao520.cn:8009/clientpage/friend_raiders.php

        var url = amsg[i];

        var param = '' ,src='';

        MsgType = 'navigator';

        /*
            <a\b               #匹配a標(biāo)簽的開始
            [^>]+              #匹配a標(biāo)簽中href之前的內(nèi)容
           \bhref="([^"]*)"    #匹配href的值,并將匹配內(nèi)容捕獲到分組1當(dāng)中
             [^>]*>            #匹配a標(biāo)簽中href之后的內(nèi)容
            ([\s\S]*?)         #匹配a標(biāo)簽的value,并捕獲到分組2當(dāng)中,?表示懶惰匹配
            </a>               #匹配a標(biāo)簽的結(jié)束
        */

        new RegExp('<a\b[^>]+\bhref="([^"]*)"[^>]*>([\s\S]*?)</a>', "ig");  //這里reg有緩存,導(dǎo)致了后面覆蓋前面的

        var link = RegExp.$1; //這里是a鏈接href的內(nèi)容

        var alt = RegExp.$2;//這里是a鏈接可點(diǎn)擊文字的內(nèi)容

        console.log(url,link,alt)
        
        
        //解析兩種預(yù)定義的a鏈接,解析成可識別鏈接
        if(pattern1.test(url)) //in開頭類型的  <a href="in://goplay">
        {
            switch (true) {
                case new RegExp("goplay", "ig").test(link):
                    src = app.globalData.navigateTo.goPlay;
                    break;
                case new RegExp("userinfo", "ig").test(link):
                    var temp = (link).split('?');
                    src = app.globalData.navigateTo.getUserInfo+'?'+temp[1];
                    break;
                case new RegExp("setmyinfo", "ig").test(link):
                    src = app.globalData.navigateTo.setUserInfo;
                    break;
                case new RegExp("setting", "ig").test(url):

                    break;
                case new RegExp("mytrends", "ig").test(url):

                    break;
                case new RegExp("myphoto", "ig").test(url):

                    break;
                case new RegExp("visitorrecord", "ig").test(url):

                    break;
                case new RegExp("feedback", "ig").test(url):
                    src = app.globalData.navigateTo.feedBack;
                    break;
                case new RegExp("vip_pay", "ig").test(url):
                    src = app.globalData.navigateTo.vipRecharge;
                    break;
                case new RegExp("money_pay", "ig").test(url):
                    src = app.globalData.navigateTo.goldRecharge;
                    break;
                case new RegExp("payment", "ig").test(url):
                    src = app.globalData.navigateTo.goldRecharge;
                    break;
            }


        }
        else if(pattern2.test(url))//web開頭類型的  <a href="web://http://api.520.com:8891/activity/convention.php">
        {
            src = (link).split('//');  //替換成https,替換掉端口
            if(src[1].indexOf("https") == -1){
                param = src[1].replace(/http/,'https')+'//'+src[2];
                param = param.replace(/:8891/,'')
            } else {
                param = src[1]+'//'+src[2]
            }
            //這種直接使用H5頁面
            //src = app.globalData.navigateTo.clientPage+'?url='+param+'&title='+alt
            src = '測試'+'?url='+param+'&title='+alt
        }


        MsgContent = amsg[i];

        MsgBody.push({
            'MsgType'   : MsgType,
            'MsgContent': src,
            'MsgParam':alt,
        })


        restMsgIndex = desc.indexOf(amsg[i]) + amsg[i].length;

        desc = desc.substring(restMsgIndex);

    }

    if(desc){  //最后還存在文本
        MsgType = 'text';
        MsgBody.push({
            'MsgType'   : MsgType,
            'MsgContent': desc
        })
    }
}
回答
編輯回答
法克魷

參見MDN,DOMParser
https://developer.mozilla.org...

2017年3月20日 16:15
編輯回答
尤禮

題主改了問題。純解決請看luckness的回答。


?有特別的需求一定要自己造DOMParser的輪子嗎?讓原生代碼去做這件事不是又快又沒bug?

const raw = '出于HTTPS的安全策略,瀏覽器會阻斷HTTPS上的非安全請求(HTTP)請求,但是我們可以使用被動(dòng)混合內(nèi)容的方式來跨越這個(gè)安全策略<a href="web://http://api.520.com:8891/clientpage/money.php">去看看怎么請求</a>這時(shí)候,瀏覽器只會在控制臺報(bào)warning,而不會block我們的請求。<a href="web://http://api.520.com:8891/activity/convention.php">查看規(guī)則</a>。因?yàn)楣粽呖梢酝ㄟ^不安全的HTTP內(nèi)容來攻擊安全的HTTPS頁面<a href="in://goplay">去交互</a>';

const tree = (new DOMParser()).parseFromString(raw, 'text/html').body;

const ret = Array.prototype.map.call(tree.childNodes, ({nodeName, textContent, href}) => {
  switch(nodeName) {
    case '#text':
      return { MsgType: 'text', MsgContent: textContent };
    case 'A':
      // whatever you want
      return { MsgType: 'navigator', MsgContent: null, MsgParam: textContent };
  }
});
2018年1月6日 01:19
編輯回答
笨小蛋
//原串
var desc = '出于HTTPS的安全策略,瀏覽器會阻斷HTTPS上的非安全請求(HTTP)請求,但是我們可以使用被動(dòng)混合內(nèi)容的方式來跨越這個(gè)安全策略' +
    '<a href="web://http://api.520.com:8891/clientpage/money.php">去看看怎么請求</a>' +
    '這時(shí)候,瀏覽器只會在控制臺報(bào)warning,而不會block我們的請求。<a href="web://http://api.520.com:8891/activity/convention.php">查看規(guī)則</a>。' +
    '因?yàn)楣粽呖梢酝ㄟ^不安全的HTTP內(nèi)容來攻擊安全的HTTPS頁面<a href="in://goplay">去交互</a>';

var MsgBody = [];
var expr = /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/mg // 盡量不使用構(gòu)造器函數(shù)
let result
let lastIndex = 0
while (result = expr.exec(desc)) { // 使用exec方法,match方法在全局模式下不會保存分組的內(nèi)容,求分組內(nèi)容的時(shí)候還需要再次匹配
    let index = result.index
    let src = result[1]
    let alt = result[2]
    if (lastIndex !== index) {
        MsgBody.push({
            'MsgType'   : 'text',
            'MsgContent': desc.slice(lastIndex, index)
        })
    }
    /**
     * src的處理邏輯,這里我就不寫了
     * ...
     */
    MsgBody.push({
        'MsgType'   : 'navigator',
        'MsgContent': src,
        'MsgParam'  : alt
    })
    lastIndex = index + result[0].length
}
if (lastIndex !== desc.length) {
    MsgBody.push({
        'MsgType'   : 'text',
        'MsgContent': desc.slice(lastIndex)
    })
}
2017年7月20日 02:44