32 lines
1.1 KiB
JavaScript
32 lines
1.1 KiB
JavaScript
// Safe rendering of user-authored notes HTML (e.g. Application Notes, which the
|
|
// form advertises as "HTML supported"). DOMPurify strips scripts, event
|
|
// handlers, and any active/unsafe content; we allow only basic formatting +
|
|
// links. Never v-html raw notes without this.
|
|
import DOMPurify from 'dompurify'
|
|
|
|
// Force every surviving link to open safely: new tab + no window.opener handle.
|
|
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
|
|
if (node.tagName === 'A' && node.getAttribute('href')) {
|
|
node.setAttribute('target', '_blank')
|
|
node.setAttribute('rel', 'noopener noreferrer')
|
|
}
|
|
})
|
|
|
|
const ALLOWED_TAGS = [
|
|
'p', 'br', 'hr', 'b', 'strong', 'i', 'em', 'u', 's', 'span', 'div',
|
|
'a', 'ul', 'ol', 'li', 'blockquote', 'code', 'pre',
|
|
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
'table', 'thead', 'tbody', 'tr', 'th', 'td',
|
|
]
|
|
const ALLOWED_ATTR = ['href', 'title', 'target', 'rel']
|
|
|
|
// Return a sanitized HTML string safe to bind with v-html. Empty in -> empty out.
|
|
export function sanitizeNotesHtml(html) {
|
|
if (!html) return ''
|
|
return DOMPurify.sanitize(String(html), {
|
|
ALLOWED_TAGS,
|
|
ALLOWED_ATTR,
|
|
ALLOW_DATA_ATTR: false,
|
|
})
|
|
}
|