2

我正在尝试限制 Markdown 编辑器的 HTML 中的锚标记可以使用的一些属性。这就是我现在所拥有的:

/^(<a\shref="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i

这允许一个带有titlehref属性的锚标记,但没有别的。我也想添加target,但无论我尝试什么都没有用。

  1. 链接必须包含一个href属性。
  2. 它可以包含title属性,但不是必须的。
  3. 它可以包含target属性,但也不必如此。

如何修改满足上述所有条件的正则表达式。

4

3 回答 3

4

通常正则表达式不是解析某些语言的最佳工具。另一方面,如果你只想匹配一个孤立的锚标记,那么解析器可能有点太多了,而正则表达式可以做得很好。

要将锚标记与您的要求相匹配,您可以使用下面的正则表达式。它使用反向引用来跟踪最多一个title和一个target(重复的属性),也至少/最多一个href

^(<a(?=[^>]*?(\s+href="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+")[^>]*>)(?=([^>]*?(\s+title="[^"<>]+"))?[^>]*>)(?=([^>]*?(\s+target="[^"<>]+"))?[^>]*>)(\2(\6\8?)?|\2\8\6?|\6\2\8?|\8\2\6?|\6\8\2|\8\6\2)\s*>[^<]*</a>)$

在此处查看演示,以及数十个测试用例,您可以对解决方案进行验证测试。

观察这个正则表达式并没有那么复杂(“丑陋”的部分是 URL,真的),但它非常全面并且照顾到:

  • 强制href属性
  • 可选title属性
  • 可选target属性
  • 不允许使用其他类型的属性(尽管很容易自定义和添加支持)
  • 它们之间的任意数量的空格
  • 他们可以按任何顺序出现
  • 最多可以有一个href,一个title和一个target
于 2013-08-16T21:44:28.450 回答
1

RegEx-en本身并不擅长这种事情。

我会做类似的事情:

function validateAnchor(anchor){

    var match,
        name,
        value,
        test,
        attrRE=/\s([a-z]+)(?:\s*=\s*"([^"]+))?"/gi, // matches one tag attribute
        allowedAttrs={ // attributes must appear here to be considered legal
          href:{
            isValid:function(val){
               return isValidURL(val);
            }
          },
          title:{
            isValid:function(val){
                return true;
            }
          },
          target:{
            isValid:function(val){
              return true;
            }
          }
        },
        result=true;

    while(match=attrRE.exec(anchor)){

        name=match[1].toLowerCase(); // lowerCase to match our allowedAttrs keys
        value=match[2]||'';          // optional

        // must have a name
        if(!name){
            console.log('no name for this attr - should not happen!');
            result=false;
            break;
        }

        // and must exist in allowedAttrs
        if(test=allowedAttrs[name]) {
            console.log('unknown attr');
            result=false;
            break;
        }

        // if it has a value and there is am isValid function.
        if(value && 'function'==typeof(attr.isValid)){
            if(!attr.isValid(value)){ // which fails!
                result=false;
                break;
            }
        }
    }
    return result;
}

因此,鉴于:

var anchor='<a href=\"...\" target = \"...\" foo >';

validateAnchor(anchor) 将失败,因为 'foo' 是一个不允许的属性(未在 allowedAttrs 中定义)。

这种方法的好处是你

  • 每次需要接受新属性时都不需要修改 RE,
  • 可以有无价值的属性

我将 isValidURL() 留给您定义。

于 2013-08-16T23:07:54.163 回答
1

让我们更容易:

/<a(?=.*href="((ht|f)tps?:\/)?\/.*")\s*((href|title|target)="[^"]*"\s*)*>[^<]*</a>/
于 2013-08-17T01:47:35.383 回答