feat(editor): link insertion full UI and flow
This commit is contained in:
1 parent
03b39e64f2
commit
6f9ae6207a
16 files changed
+2865
-14
No files matched your search
@@ -0,0 +1,39 @@
|
||||
const WEB_URL = /^https?:\/\/[^\s\\/?#]+(?:[/?#]\S*)?$/i
|
||||
const MAIL_URL = /^mailto:[^\s@/?#]+@[^\s@]+$/i
|
||||
const SITE_PATH = /^\/(?![/\\])\S*$/
|
||||
const ANCHOR = /^#\S+$/
|
||||
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/g
|
||||
const HAS_CONTROL_CHARACTER = /[\u0000-\u001f\u007f-\u009f]/
|
||||
const SCHEME = /^([a-z][a-z0-9+.-]*):/i
|
||||
const STORED_SCHEMES = ['http', 'https', 'mailto', 'tel', 'ftp']
|
||||
|
||||
export function normalizeLinkUrl(raw: string): string | null {
|
||||
const url = raw.trim()
|
||||
if (HAS_CONTROL_CHARACTER.test(url)) {
|
||||
return null
|
||||
}
|
||||
if (WEB_URL.test(url) || MAIL_URL.test(url) || SITE_PATH.test(url) || ANCHOR.test(url)) {
|
||||
return url
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function isStoredHrefSafe(raw: string): boolean {
|
||||
const visible = raw.replace(CONTROL_CHARACTERS, '').trim().replace(/\s/g, '')
|
||||
const scheme = SCHEME.exec(visible)
|
||||
if (scheme === null) {
|
||||
return visible !== ''
|
||||
}
|
||||
return STORED_SCHEMES.includes(scheme[1]!.toLowerCase())
|
||||
}
|
||||
|
||||
export function neutralizeUnsafeLinks(html: string): string {
|
||||
const document = new DOMParser().parseFromString(html, 'text/html')
|
||||
for (const anchor of document.body.querySelectorAll('a')) {
|
||||
if (isStoredHrefSafe(anchor.getAttribute('href') ?? '')) {
|
||||
continue
|
||||
}
|
||||
anchor.replaceWith(...anchor.childNodes)
|
||||
}
|
||||
return document.body.innerHTML
|
||||
}
|
||||
Reference in new issue
Block a user