如何检查字符串是否是有效的 Figma link?
How to check if string is a valid Figma link?
我正在使用 Figma API 在 NodeJS 上构建一个应用程序,我需要检查用户传递的字符串是否是有效的 Figma link。我目前正在使用这个简单的正则表达式来检查字符串:
/^https\:\/\/www.figma.com\/.*/i
但是,它匹配 figma.com
中的所有 link,甚至是主页,而不仅仅是文件和原型的 link。这是一个 Figma link 应该匹配的例子:
https://www.figma.com/file/OoYmkiTlusAzIjYwAgSbv8wy/Test-File?node-id=0%3A1
如果这是原型 link,则匹配也应该是肯定的,路径中使用 proto
而不是 file
。
此外,由于我使用的是 Figma API,因此同时提取 URL 的必要部分(例如文件 ID 和节点 ID)会很有用。
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(例如 wwwww.
)——可以通过将字母匹配替换为更简单的表达。另外这是一个无用的捕获组,我将其设为非捕获。
如果 link 匹配,即使它不以 https://
开头也很好,因为某些引擎(例如 Twitter)为了简洁而删除了这部分,如果有人正在从那里复制一个 link,它应该仍然有效。
应用所有改进后,我们得到以下表达式:
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?$/
还有一个专门的 NPM package 可以根据类似模式简单地检查 URL。但是,它包含上面列出的一些缺陷,所以我不建议使用它,尤其是对于只有一行代码的情况。
正在提取 URL
的部分内容
这个表达式与 Figma API 一起使用非常有用,因为它甚至可以从 URL 中提取必要的部分,例如 link (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 file/prototype URLs 而不会破坏任何东西。这是适用于不同情况的三个相似版本。
✅ 此版本将 URL 参数和文件名分开捕获,以便于处理。你可以check it here。我把它添加在答案的开头,因为我认为它是最干净和最有用的解决方案。
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?(.*))?$/
其中的分组如下:
- 第 1 组:file/proto
- 第 2 组:文件 key/id
- 第 3 组:文件名(可选)
- 第 4 组:url 参数(可选)
✅ 接下来,我想做同样的事情,但将可以添加到任何 Figma URL 末尾的 /duplicate
部分分开,以便在打开时创建文件的副本。
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?([^\/]*)(\/duplicate)?)?$/
✅ 回到 node-id
参数。以下正则表达式成功地在 多行字符串 中查找并捕获多个 URL。我最后发现的唯一缺点是它(以及之前的所有缺点)不检查此 URL 是否包含未编码的 special characters meaning that it can potentially break things, but it can be avoided by manually encoding all parameters using encodeURI()
function.
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/([^\?\n\r\/]+)?((?:\?[^\/]*?node-id=([^&\n\r\/]+))?[^\/]*?)(\/duplicate)?)?$/gm
这个表达式可以捕获六个组:
- 第 1 组:file/proto
- 第 2 组:文件 key/id
- 第 3 组:文件名(可选)
- 第 4 组:url 参数(可选)
- 第 5 组:节点 ID(可选;仅当存在第 4 组时出现)
- 第 6 组:/重复
最后,这里是匹配及其组(或 try it yourself)的示例:
我正在使用 Figma API 在 NodeJS 上构建一个应用程序,我需要检查用户传递的字符串是否是有效的 Figma link。我目前正在使用这个简单的正则表达式来检查字符串:
/^https\:\/\/www.figma.com\/.*/i
但是,它匹配 figma.com
中的所有 link,甚至是主页,而不仅仅是文件和原型的 link。这是一个 Figma link 应该匹配的例子:
https://www.figma.com/file/OoYmkiTlusAzIjYwAgSbv8wy/Test-File?node-id=0%3A1
如果这是原型 link,则匹配也应该是肯定的,路径中使用 proto
而不是 file
。
此外,由于我使用的是 Figma API,因此同时提取 URL 的必要部分(例如文件 ID 和节点 ID)会很有用。
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(例如wwwww.
)——可以通过将字母匹配替换为更简单的表达。另外这是一个无用的捕获组,我将其设为非捕获。如果 link 匹配,即使它不以
https://
开头也很好,因为某些引擎(例如 Twitter)为了简洁而删除了这部分,如果有人正在从那里复制一个 link,它应该仍然有效。
应用所有改进后,我们得到以下表达式:
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?$/
还有一个专门的 NPM package 可以根据类似模式简单地检查 URL。但是,它包含上面列出的一些缺陷,所以我不建议使用它,尤其是对于只有一行代码的情况。
正在提取 URL
的部分内容这个表达式与 Figma API 一起使用非常有用,因为它甚至可以从 URL 中提取必要的部分,例如 link (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 file/prototype URLs 而不会破坏任何东西。这是适用于不同情况的三个相似版本。
✅ 此版本将 URL 参数和文件名分开捕获,以便于处理。你可以check it here。我把它添加在答案的开头,因为我认为它是最干净和最有用的解决方案。
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?(.*))?$/
其中的分组如下:
- 第 1 组:file/proto
- 第 2 组:文件 key/id
- 第 3 组:文件名(可选)
- 第 4 组:url 参数(可选)
✅ 接下来,我想做同样的事情,但将可以添加到任何 Figma URL 末尾的 /duplicate
部分分开,以便在打开时创建文件的副本。
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/?([^\?]+)?([^\/]*)(\/duplicate)?)?$/
✅ 回到 node-id
参数。以下正则表达式成功地在 多行字符串 中查找并捕获多个 URL。我最后发现的唯一缺点是它(以及之前的所有缺点)不检查此 URL 是否包含未编码的 special characters meaning that it can potentially break things, but it can be avoided by manually encoding all parameters using encodeURI()
function.
/^(?:https:\/\/)?(?:www\.)?figma\.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/([^\?\n\r\/]+)?((?:\?[^\/]*?node-id=([^&\n\r\/]+))?[^\/]*?)(\/duplicate)?)?$/gm
这个表达式可以捕获六个组:
- 第 1 组:file/proto
- 第 2 组:文件 key/id
- 第 3 组:文件名(可选)
- 第 4 组:url 参数(可选)
- 第 5 组:节点 ID(可选;仅当存在第 4 组时出现)
- 第 6 组:/重复
最后,这里是匹配及其组(或 try it yourself)的示例: