如何检查字符串是否为有效的Figma链接?

时间:2019-03-30 06:58:48

标签: javascript regex figma-api

我正在使用Figma API的NodeJS上构建一个应用程序,我需要检查用户传递的字符串是否是有效的Figma链接。我目前正在使用此简单的正则表达式表达式来检查字符串:

/^https\:\/\/www.figma.com\/.*/i

但是,它匹配figma.com中的所有链接,甚至是主页,不仅链接到文件和原型。这是一个应该匹配的示例Figma链接:

https://www.figma.com/file/OoYmkiTlusAzIjYwAgSbv8wy/Test-File?node-id=0%3A1

如果这是一个原型链接,且路径中使用proto而不是file,则匹配也应为正。

此外,由于我使用的是Figma API,因此同时提取URL的必要部分(例如文件ID和节点ID)会很有用。

1 个答案:

答案 0 :(得分:1)

TL; DR

✅使用此表达式捕获四个最重要的组(类型,文件ID,文件名和URL属性)并从那里开始工作。

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?(.*))?$/

来自文档

这是Figma在其developer documentation page about embeds上提供的正则表达式代码:

/https://([w.-]+.)?figma.com/(file|proto)/([0-9a-zA-Z]{22,128})(?:/.*)?$/

但是,它不能在JS中使用,因为 文档当前是错误的,并且此表达式存在多个问题:

  • 斜杠和点不能用反斜杠转义。

  • 从字符串开头不匹配。在VLAZ在评论中指出之后,我添加了start of string anchor ^。这样,我们将避免匹配不以https开头的字符串,例如malicious.site/?link=https://figma.com/...

  • 它不仅会匹配www.子域,而且还会匹配W数量不大的任何其他W(例如wwwww.)-可以通过用更简单的表达式替换字母match来解决。这也是一个无用的捕获组,我将使其变为非捕获。

  • 即使链接不是以https://开头,如果链接匹配也很好,因为某些引擎(例如Twitter)为简洁起见将其剥离,并且如果有人从那里复制链接,应该仍然有效。

应用所有改进后,我们将得到以下表达式:

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?$/

还有一个专用的NPM package,可以根据相似的模式简单地检查URL。但是,它包含上面列出的一些缺陷,因此我不建议您使用它,尤其是仅针对一行代码。


提取部分网址

该表达式与Figma API一起使用非常有用,因为它甚至可以从URL中提取必要的部分,例如链接类型(原型/文件)和file key。您可以按索引访问它们。

您还可以添加piece of regex来匹配查询中的特定键,例如node-id

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?node-id=([^&]*)$/

现在您可以在代码中使用它,并分别获取URL的所有部分:

var pattern = /^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?node-id=([^&]*)$/

var matched = 'https://www.figma.com/file/OoYmkiTlusAzIjYwAgSbv8wy/Test-File?node-id=0%3A1'.match(pattern)

console.log('url:', matched[0]) // whole matched string
console.log('type:', matched[1]) // group 1
console.log('file key:', matched[2]) // group 2
console.log('node id:', matched[3]) // group 3


深入挖掘

我花了一些时间几乎从头开始重新创建该表达式,以便它可以匹配尽可能多的Figma文件/原型URL,而不会造成任何麻烦。这是适用于不同情况的三个类似版本。

✅此版本分别捕获URL参数和文件名,以便于处理。您可以check it here。我将其添加到答案的开头,因为我认为这是最干净,最有用的解决方案。

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?(.*))?$/

其中的组如下:

  • 第1组:文件/协议
  • 第2组:文件密钥/ ID
  • 第3组:文件名(可选)
  • 第4组:网址参数(可选)

✅接下来,我想做同样的事情,但是将/duplicate部分分开,该部分可以添加到任何Figma URL的末尾,以在打开时创建文件的副本。

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?([^\/]*)(\/duplicate)?)?$/

✅返回node-id参数。以下正则表达式可以成功找到并捕获多行字符串中的多个URL。我最后发现的唯一缺点是,它(以及之前的所有URL)都不会检查此URL是否包含未编码的special characters,这意味着它可能会破坏某些内容,但是可以通过手动避免使用encodeURI() function对所有参数进行编码。

/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/([^\?\n\r\/]+)?((?:\?[^\/]*?node-id=([^&\n\r\/]+))?[^\/]*?)(\/duplicate)?)?$/gm

此表达式可以捕获六个组:

  • 第1组:文件/协议
  • 第2组:文件密钥/ ID
  • 第3组:文件名(可选)
  • 第4组:URL参数(可选)
    • 第5组:node-id(可选;仅在存在第4组时出现)
  • 第6组:/重复

最后,这是比赛及其分组(或try it yourself)的示例:

groups examples