【问题标题】:How to check if string is a valid Figma link?如何检查字符串是否是有效的 Figma 链接?
【发布时间】:2019-08-21 01:52:13
【问题描述】:

我正在 NodeJS 上构建一个使用 Figma API 的应用程序,我需要检查用户传递的字符串是否是有效的 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)会很有用。

【问题讨论】:

    标签: javascript regex figma-api


    【解决方案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 在 cmets 中指出之后,我添加了 start of string anchor ^。这样我们就可以避免匹配不以https开头的字符串,例如malicious.site/?link=https://figma.com/...

    • 它不仅会匹配 www. 子域,还会匹配任何其他不太好的 W(例如 wwwww.)——它可以通过用更简单的表达式替换字母匹配来修复。另外这是一个无用的捕获组,我将其设为非捕获。

    • 1234563有效。

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

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

    还有一个专用的NPM package,它只是根据类似的模式检查 URL。但是,它包含上面列出的一些缺陷,所以我不建议使用它,尤其是对于仅一行代码。


    提取部分 URL

    这个表达式与 Figma API 一起使用非常有用,因为它甚至可以从 URL 中提取必要的部分,例如链接类型(proto/file)和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 组:url 参数(可选)

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

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

    ✅ 回到node-id 参数。以下正则表达式成功地找到并捕获了 多行字符串 中的多个 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 组:节点 ID(可选;仅在第 4 组存在时出现)
    • 第 6 组:/重复

    最后,这是一个匹配及其组(或try it yourself)的示例:

    【讨论】:

    • "但是,它在 JS 中作为斜杠不起作用,点应该用反斜杠转义,给我们留下以下表达式:" 但斜杠部分为真对于任何使用/ 作为正则表达式分隔符的东西。至于.,当在字符类之外使用时,所有正则表达式引擎都会将其解释为“任何字符”。这不是 JS 特定的 - 文档完全是错误的。我还注意到它有一个$ 锚但没有^ 锚,这看起来很奇怪。
    • 感谢您告诉我这一点,我不是正则表达式的专家。我会告诉 Figma 团队更正文档!关于^ 主播,你是对的,我没有注意到它不存在。我会改进答案。
    • 我认为[w.-]+ 应该是[\w.-]+
    • @Toto 好点!那么它会匹配任何figma.com 子域吗?目前它只检查www.,因为目前 Figma 不使用任何其他子域来获取文件和原型链接。但是当我对此进行更多试验时,我认为在该捕获组中简单地使用(www.) 会更好,因为目前它将匹配wwwww.,这不是我们想要的。
    • 对不起,我的意思是(www\.)
    猜你喜欢
    • 2020-11-22
    • 2010-09-30
    • 2013-02-13
    • 2011-06-17
    • 1970-01-01
    • 2011-11-26
    • 2018-03-21
    • 1970-01-01
    相关资源
    最近更新 更多