【问题标题】:Put http:// on hrefs missing a protocol in Angular将 http:// 放在缺少 Angular 协议的 hrefs 上
【发布时间】:2019-10-11 20:05:08
【问题描述】:

我一直在尝试找出一种解决方案,将链接前面没有 http://https:// 的所有 href 替换为附有 http:// 的链接版本。

目前我有这样的事情:

static correctUrls(input: string): string {

  // get all hrefs from the input
  let urls = input.match('<a[^>]* href="([^"]*)"/g');

  // if no urls return original input
  if (!urls) {
    return input;
  }

  // remove duplicate urls
  urls = urls.filter((item, pos) => {
    return urls.indexOf(item) === pos;
  });

  // if no urls in input
  if (!urls) {
    return input;
  }

  for (const url of urls) {

    // if url does not have https
    // tslint:disable-next-line: max-line-length
    if (!url.match('^ (http: \/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$')) {
      input = input.replace(url, 'https://' + url);
    }
  }
  return input;
}

任何帮助将不胜感激。请说明您的答案的正则表达式如何工作。我发现了很多与此类似的问题,但是对于我找到的所有解决方案,当我尝试执行 input.match 时,它会返回匹配的 href 两次(如果有的话),但如果有两个 @ 987654325@s 然后它返回垃圾。

这是输入:

<p> We love
  <a href="https://google.com"
     rel="noopener noreferrer"
     target="_blank">Google</a>
  and
  <a href="Facebook.com"
     rel="noopener noreferrer"
     target="_blank">Facebook</a>.
</p>

以及预期的输出:

<p> We love
  <a href="https://google.com"
     rel="noopener noreferrer"
     target="_blank">Google</a>
  and
  <a href="https://Facebook.com"
     rel="noopener noreferrer"
     target="_blank">Facebook</a>.
</p>

【问题讨论】:

  • 不要使用正则表达式解析出 HTML。使用 DOM 查找锚标记及其 href 属性和 URL 类来解析它们。
  • 我正在使用 Angular,将尝试创建一个新的 HtmlElement() 并将 .innerHtml 设置为输入并以这种方式导航 DOM。
  • 如果您将 HTML 作为字符串,您可以使用 DOM 对其进行解析,而无需实际将其添加到页面中。 developer.mozilla.org/en-US/docs/Web/API/DOMParser 代替。
  • @Amy 谢谢你对我的帮助。

标签: javascript regex angular typescript


【解决方案1】:

在 Angular 中执行此操作的正确方法是使用 DOMParser。然后你可以选择所有带有 标签的元素。然后你可以应用正则表达式来查看它前面是否有http或https。

export class UrlCorrector {
  static correctUrls(input: string): string {

    const parser = new DOMParser();
    const document = parser.parseFromString(input, 'text/html');

    // get all anchor tags from the input
    const anchorTags = document.getElementsByTagName('a');

    // if no anchor tags return original input
    if (anchorTags.length === 0) {
      return input;
    }

    const urls: string[] = [];

    // iterate through all the anchor tags to find their urls
    // tslint:disable-next-line: prefer-for-of
    for (let i = 0; i < anchorTags.length; i++) {

      const href = anchorTags[i].href;
      let url = href;

      // if url has hostname in it, it's a href without http protocol
      if (href.includes(location.hostname)) {

        // get just the ending part e.g., `localhost:4200/submissions/facebook.com` will return `facebook.com`
        url = href.substr(href.lastIndexOf('/') + 1);
      }
      urls.push(url);
    }

    for (const url of urls) {

      // if url does not have a protocol append https:// to front
      // tslint:disable-next-line: max-line-length
      if (!url.match('^ (http: \/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$')) {
        input = input.replace(url, 'https://' + url);
      }
    }
    return input;
  }
}

【讨论】:

    【解决方案2】:

    正则表达式也不适合这项工作。您已经在使用 javascript - 它有大量用于 DOM 管理的工具,其中许多都可以使用 exactly what you want。请尝试改用这些,它们更适用于您的任务!

    如果你真的想用正则表达式来做这件事,href="(?!https?:\/\/)()[^"]+" 应该做这个工作。

    • href=" 寻找 href=" 字符串开始匹配
    • (?!https?:\/\/) 断言 URL 开头没有 http://https://
    • ()在您要编辑的 URL 开头的空白捕获 - 在此处插入您的字符串
    • [^"]+" 匹配内容到下一个引号;这是网址的其余部分

    Demo

    使用此方法的示例 Javascript 程序:

    var x = '<p> We love <a href="https://google.com" rel="noopener noreferrer" target="_blank">Google</a> and <a href="Facebook.com" rel="noopener noreferrer" target="_blank">Facebook</a>. <a href="www.example.com" rel="noopener noreferrer" target="_blank">Facebook</a>. <a href="http://www.example.com" rel="noopener noreferrer" target="_blank">Facebook</a>. </p>'
    var urls = x.match('href="(?!https?:\/\/)()([^"]+)"')
    
    console.log("https://" + urls[2])
    

    'https://Facebook.com'

    【讨论】:

    • 使用预期输入和 .match 结果是 ["href="Facebook.com"", ""]
    • 我不确定我是否理解该评论。你能澄清一下吗?
    • 但是我将使用 DOM。
    • 听起来不错。如果它解决了您的问题,请务必接受答案,或者标记版主关闭问题(不删除),以便将来的用户可以参考。
    • 第一个正则表达式是否有可能返回 ['google.com', 'Facebook.com'],只是获取 href?然后我打算使用第二个正则表达式来确定它前面是否有协议。
    猜你喜欢
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-11
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多