【问题标题】:How can I replace all internal urls in a string of html with their relative external url?如何将 html 字符串中的所有内部 url 替换为它们的相对外部 url?
【发布时间】:2021-01-26 15:34:53
【问题描述】:

给定一串 html,如下所示:

<html>
<link rel="stylesheet" href="/thing.css">

<body>
    <script src="/nothing.js"></script>
    <link rel="stylesheet" href="/styles.css">
    <a href='#a_hash'>A link</a>
</body>

</html>

我希望能够得到以下内容:

<html>
<link rel="stylesheet" href="//example.com/thing.css">

<body>
    <script src="//example.com/nothing.js"></script>
    <link rel="stylesheet" href="//example.com/styles.css">
    <a href='//example.com#a_hash'>A link</a>
</body>

</html>

我最好在没有库的情况下使用原生 JavaScript 来执行此操作。 目前我有这个正则表达式来查找网址(我对新网址持开放态度!):

<.+?(?:href|src)=(?:"|')([^"']+)(?:"|').*?>

【问题讨论】:

  • 将字符串转换为实际的 HTML,然后使用 DOM?

标签: javascript html regex replace


【解决方案1】:

使用

.replace(/\b((?:href|src)=)(?!\/\/example\.com)(["']?)([^"']+)\2/gi, 
   (_,x,y,z) => z.charAt(0) == '/' ? 
   `${x}${y}//example.com${z}${y}` : `${x}${y}//example.com/${z}${y}`)

regex proof

说明

--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    (?:                      group, but do not capture:
--------------------------------------------------------------------------------
      href                     'href'
--------------------------------------------------------------------------------
     |                        OR
--------------------------------------------------------------------------------
      src                      'src'
--------------------------------------------------------------------------------
    )                        end of grouping
--------------------------------------------------------------------------------
    =                        '='
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    \/                       '/'
--------------------------------------------------------------------------------
    \/                       '/'
--------------------------------------------------------------------------------
    example                  'example'
--------------------------------------------------------------------------------
    \.                       '.'
--------------------------------------------------------------------------------
    com                      'com'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    ["']?                    any character of: '"', ''' (optional
                             (matching the most amount possible))
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  (                        group and capture to \3:
--------------------------------------------------------------------------------
    [^"']+                   any character except: '"', ''' (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \3
--------------------------------------------------------------------------------
  \2                       what was matched by capture \2

const string = ' href="nowhere"  src="/nothing.js"';
const rx = /\b((?:href|src)=)(?!\/\/example\.com)(["']?)([^"']+)\2/gi;
console.log(string.replace(rx, (_,x,y,z) => z.charAt(0) == '/' ? 
   `${x}${y}//example.com${z}${y}` : `${x}${y}//example.com/${z}${y}`));

【讨论】:

  • 感谢您的回答,但这会忽略以下内容:&lt;a href='nowhere'&gt; 而是返回 &lt;a href='//example.comnowhere&gt; 我该如何解决这个问题?
  • @Explosion 它并没有忽略这一点,它匹配&lt;a href='nowhere'&gt;。如果您不想这样做,则必须检查一段时间,然后您需要\b((?:href|src)=)(?!\/\/example\.com)(["']?)([^"'.]+\.[^"']+)\2。见proof
  • 哦,误会了,我不是说它忽略它,我的意思是它没有替换它。它将&lt;a href='nowhere'&gt;A link&lt;/a&gt; 替换为&lt;a href="//example.comnowhere&gt;A link&lt;/a&gt; 而不是&lt;a href="//example.com/nowhere(注意“/”!)感谢您的回答! =)
  • @Explosion 用普通的正则表达式似乎不可能做到这一点。要么需要第二个正则表达式,要么替换需要是一个函数。
  • 谢谢! :D 我还做了一个版本,它使用 DOM 接口来查找和替换它!
【解决方案2】:

对于您的具体情况,您可能根本不需要 JavaScript。 今天了解了&lt;base&gt;标签:https://developer.mozilla.org/en-us/docs/Web/HTML/Element/base

将此添加到您的标题中,您应该没问题:

<base href="https://www.example.com/">

【讨论】:

  • 我正在使用 fetch 来获取 url 的 html,我需要链接、样式和脚本按预期工作。不过谢谢!
  • 这甚至适用于 JavaScript 文件,只要 URL 是相对。在您的浏览器控制台中尝试此操作:document.head.insertAdjacentHTML("afterbegin", '&lt;base href="https://example.com"&gt;');fetch("foo")。请求将发送至https://example.com/foo
  • 只要将获取的 HTML 插入 DOM,就会应用基本标签(只要链接是相对的)
  • @Explosion 这能回答你的问题吗?
猜你喜欢
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 2016-11-03
相关资源
最近更新 更多