javascript 将纯文本链接转换为可单击链接

xsuvu9jc  于 2022-12-25  发布在  Java
关注(0)|答案(7)|浏览(128)

Long story short, I have a website made under Wix.com editor, and coding was made possible a few months ago. I have set up a custom comment box, so users can post their comments, and read others'.
现在的问题是,"评论输入"采取纯文本,每当一个链接被张贴,它显示为纯文本,没有颜色,没有点击。
我想要一个代码,"阅读"的评论列表,并转换每一个文本,开始与"https"或"http"或"www"...橙色和可点击(打开在一个新的标签页)
有什么办法吗?
谢谢!
我已经尝试了许多事情,如:

$w('#text95').html = 
       (/((http:|https:)[^\s]+[\w])/g, '<a href="$1" target="_blank">$1</a>').replace;

text95 =显示的注解(它是一个文本,重复显示所有注解)

icnyk63a

icnyk63a1#

看起来您的替换语法有错误。请尝试类似的操作。我很肯定这会起作用。

function linkify(inputText) {
    var replacedText, replacePattern1, replacePattern2, replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}

调用它:

$w('#text95').innerHTML = linkify($w('#text95').html);
mo49yndu

mo49yndu2#

这里是我的答案(包括视频链接的改进版本).
另请参见此Codepen here

const convertLinks = ( input ) => {

  let text = input;
  const linksFound = text.match( /(?:www|https?)[^\s]+/g );
  const aLink = [];

  if ( linksFound != null ) {

    for ( let i=0; i<linksFound.length; i++ ) {
      let replace = linksFound[i];
      if ( !( linksFound[i].match( /(http(s?)):\/\// ) ) ) { replace = 'http://' + linksFound[i] }
      let linkText = replace.split( '/' )[2];
      if ( linkText.substring( 0, 3 ) == 'www' ) { linkText = linkText.replace( 'www.', '' ) }
      if ( linkText.match( /youtu/ ) ) {

        let youtubeID = replace.split( '/' ).slice(-1)[0];
        aLink.push( '<div class="video-wrapper"><iframe src="https://www.youtube.com/embed/' + youtubeID + '" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>' )
      }
      else if ( linkText.match( /vimeo/ ) ) {
        let vimeoID = replace.split( '/' ).slice(-1)[0];
        aLink.push( '<div class="video-wrapper"><iframe src="https://player.vimeo.com/video/' + vimeoID + '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>' )
      }
      else {
        aLink.push( '<a href="' + replace + '" target="_blank">' + linkText + '</a>' );
      }
      text = text.split( linksFound[i] ).map(item => { return aLink[i].includes('iframe') ? item.trim() : item } ).join( aLink[i] );
    }
    return text;

  }
  else {
    return input;
  }
}

这将把纯文本中冗长笨拙的链接替换为文本中可点击的短链接。(同时还将视频 Package 在响应性iframe中)
示例:

This clumsy link https://stackoverflow.com/questions/49634850/javascript-convert-plain-text-links-to-clickable-links/52544985#52544985 is very clumsy and this http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split is not much better. This one www.apple.com is nice but www can be removed.

变成:

This clumsy link <a href="https://stackoverflow.com/questions/49634850/javascript-convert-plain-text-links-to-clickable-links/52544985#52544985" target="_blank">stackoverflow.com</a> is very clumsy and this <a href="http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split" target="_blank">developer.mozilla.org</a> is not much better. This one <a href="http://www.apple.com" target="_blank">apple.com</a> is nice but www can be removed.

链接的文本显示如下:
This clumsy link stackoverflow.com is very clumsy and this developer.mozilla.org is not much better. This one apple.com is nice but www can be removed.

neskvpey

neskvpey3#

我不确定$w是什么,或者你是否真的可以像那样分配html,但我猜这是jquery,因为$最常引用jquery对象。
你差点就成功了,那就...
$('#text95').html($('#text95').html().replace(/((http:|https:)[^\s]+[\w])/g, '<a href="$1" target="_blank">$1</a>'));
试试看。

$('#text95').html($('#text95').html().replace(/((http:|https:)[^\s]+[\w])/g, '<a href="$1" target="_blank">$1</a>'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id=text95>
stuff and stuff and http://ww.stuff.com stuff
</div>
0h4hbjxa

0h4hbjxa4#

我真的很喜欢@philipeachille的解决方案。它很轻量级,而且做了很多基本的事情。但是,它有几个问题需要解决:

  • 如果链接后面紧跟标点符号,则该标点符号包含在链接中
  • 如果同一链接包含多次,逻辑就会混乱
  • 某些链接不以wwwhttp开始,例如microsoft.com

我从他的代码中派生出了以下代码,修复了这些问题,并省略了我不想要的视频嵌入内容:

const linkify = t => {
  const m = t.match(/(?<=\s|^)[a-zA-Z0-9-:/]+\.[a-zA-Z0-9-].+?(?=[.,;:?!-]?(?:\s|$))/g)
  if (!m) return t
  const a = []
  m.forEach(x => {
    const [t1, ...t2] = t.split(x)
    a.push(t1)
    t = t2.join(x)
    const y = (!(x.match(/(http(s?)):\/\//)) ? 'https://' : '') + x
    a.push('<a href="' + y + '" target="_blank">' + y.split('/')[2] + '</a>')
  })
  a.push(t)
  return a.join('')
}

要解释主正则表达式:

  • (?<=\s|^)查看链接的后面(前面)以确定链接的起始位置,可以是任何空白字符或字符串的开头
  • [a-zA-Z-:/]+\.[a-zA-Z]匹配链接的开头-类似于xxx. x甚至xxx://xxx. x的模式
  • [a-zA-Z-:/]+一个或多个字母、连字符、冒号或斜线的组合
  • \.后面紧跟一个点
  • [a-zA-Z]后跟另一个字母
  • .+?与链路的其余部分匹配。
  • (?=[.,;:?!-]?(?:\s|$))向前(向后)查看链路以确定链路的结束位置
  • ?=正前瞻
  • (?:\s|$)链接以任何空格或字符串结尾结束
  • [.,;:?!-]?,除非空格或字符串结尾前面紧跟这七个标点符号之一,在这种情况下,此标点符号将结束链接。

如果你想尝试一些不同的文本块,看看它们是如何被链接的,这里有一个片段:
x一个一个一个一个x一个一个二个x

    • 更新**

根据@newbie.user88关于XSS漏洞的评论,我认为通过尝试用每个潜在的URL构造一个URL对象来验证它是明智的。

72qzrwbm

72qzrwbm5#

我纠正错误philipeachille的代码,因为youtubeID参数是不正确的。我也纠正直接youtube链接。

convertLinks = input => {
    let text = input;
    const aLink = [];
    const linksFound = text.match(/(?:www|https?)[^\s]+/g);

    if (linksFound != null) {
        for (let i = 0; i < linksFound.length; i++) {
            let replace = linksFound[i];

            if (!(linksFound[i].match(/(http(s?)):\/\//))) {
                replace = 'http://' + linksFound[i]
            }

            let linkText = replace.split('/')[2];

            if (linkText.substring(0, 3) == 'www') {
                linkText = linkText.replace('www.', '')
            }

            if (linkText.match(/youtu/)) {
                const youtubeID = replace.split('/').slice(-1)[0].split('=')[1];

                if (youtubeID === undefined || youtubeID === '') {
                    aLink.push('<a href="' + replace + '" target="_blank">' + linkText + '</a>');
                } else {
                    aLink.push('<span class="video-wrapper"><iframe src="https://www.youtube.com/embed/' + youtubeID + '" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></span>');
                }
            } else {
                aLink.push('<a href="' + replace + '" target="_blank">' + linkText + '</a>');
            }

            text = text.split(linksFound[i]).map(item => {
                return aLink[i].includes('iframe') ? item.trim() : item
            }).join(aLink[i]);
        }
        return text;
    }
    else {
        return input;
    }
};

用法:

const text = 'Hello. This is a link https://www.google.com and this is youtube video https://www.youtube.com/watch?v=O-hnSlicxV4';

convertLinks(text);
wgmfuz8q

wgmfuz8q6#

如果字符串包含URL的任何地方,转换该字符串为链接。我尝试以上代码,但这对我来说是不正常的工作。添加了一些条件后,它的工作。谢谢你帮我@user9590073

function convertLink(inputText) {
        var replacedText, replacePattern1, replacePattern2, replacePattern3;
    
    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&#\/%?=~_|!:,.;]*[-A-Z0-9+&#\/%=~_|])/gim;
    if (replacePattern1.test(inputText))
        inputText = inputText.replace(replacePattern1, '<a href="$1" target="_blank" style="color:blue">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    if (replacePattern2.test(inputText))
        inputText = inputText.replace(replacePattern2, '$1<a href="http://$2" target="_blank" style="color:blue">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    if (replacePattern3.test(inputText))
        replacedText = inputText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return inputText;
}

然后我把我的文本传递到ConverLink Func中,打开带有可点击URL的模态。

$modalBody.find('div.news-content').html('<p>' + convertLink(response.NewsContent) + '</p>');
7tofc5zh

7tofc5zh7#

这里有一个版本(只适用于http/s和ftp链接),如果它看起来已经在一个链接中(或者更确切地说,前面有一个“或”),它不会用链接替换url

function linkifyBareHttp(inputText){
    //URLs starting with http://, https://, or ftp://
    const replacePattern1 = /\b(?<!(\'|\"))(((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]))/gim;
    return inputText.replace(replacePattern1, '<a href="$2"></a>');
}

这里有一个小测试器,显示它处理什么样的事情:

function testLinkify(){
   console.log('starting test'); 
     test(`https://example.com`, `<a href="https://example.com"></a>`);
   test(`\nhttps://example.com`,`\n<a href="https://example.com"></a>`);
   test(`<a href="https://example.com"></a>`,`<a href="https://example.com"></a>`);
   test(`<a href="https://example.com"></a> https://example.com`,`<a href="https://example.com"></a> <a href="https://example.com"></a>`);
    test(`https://example.com\nhttps://example.net <a href="https://example.org">BAZ</a>`,`<a href="https://example.com"></a>\n<a href="https://example.net"></a> <a href="https://example.org">BAZ</a>`);
}
function test(input,expect){
  const testFunction = linkifyBareHttp;
  const output = testFunction(input);
  console.log (output === expect ? 'PASS':'FAIL');
      console.log(` INPUT: ${input}`);
  if(output !== expect) {
    console.log(`EXPECT: ${expect}`);
    console.log(`OUTPUT: ${output}`)
  }
}

相关问题