/**
* Turn plain message text into safe HTML where URLs become clickable links that
* open in a new tab. Used by the ticket history (RequestForm) and the staff chat
* (Drawer.vue / pages/chat.vue) — anywhere user-entered text is shown and may
* contain a link.
*
* Safety: every non-URL segment AND the link href/label are HTML-escaped, so the
* result is safe to bind with `v-html` — the only markup we ever inject is the
* `` tags we build ourselves. Newlines are left intact (callers render inside
* a `white-space: pre-wrap` container).
*/
const escapeHtml = (s: string): string => s
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
// http(s):// or bare www. — stop at whitespace / '<', and don't swallow trailing
// punctuation (.,;:!?) or closing brackets/quotes that usually end a sentence.
const URL_RE = /\b((?:https?:\/\/|www\.)[^\s<]+[^\s<.,;:!?)\]}'"])/gi
export const linkifyHtml = (input: any): string => {
const text = input == null ? '' : String(input)
let out = ''
let last = 0
URL_RE.lastIndex = 0
let m: RegExpExecArray | null
while ((m = URL_RE.exec(text)) !== null) {
out += escapeHtml(text.slice(last, m.index))
const url = m[0]
const href = /^www\./i.test(url) ? `https://${url}` : url
out += `${escapeHtml(url)}`
last = m.index + url.length
}
out += escapeHtml(text.slice(last))
return out
}
export default linkifyHtml