escapeHtml.ts 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. const escapeRE = /["'&<>]/
  2. export function escapeHtml(string: unknown): string {
  3. const str = '' + string
  4. const match = escapeRE.exec(str)
  5. if (!match) {
  6. return str
  7. }
  8. let html = ''
  9. let escaped: string
  10. let index: number
  11. let lastIndex = 0
  12. for (index = match.index; index < str.length; index++) {
  13. switch (str.charCodeAt(index)) {
  14. case 34: // "
  15. escaped = '&quot;'
  16. break
  17. case 38: // &
  18. escaped = '&amp;'
  19. break
  20. case 39: // '
  21. escaped = '&#39;'
  22. break
  23. case 60: // <
  24. escaped = '&lt;'
  25. break
  26. case 62: // >
  27. escaped = '&gt;'
  28. break
  29. default:
  30. continue
  31. }
  32. if (lastIndex !== index) {
  33. html += str.slice(lastIndex, index)
  34. }
  35. lastIndex = index + 1
  36. html += escaped
  37. }
  38. return lastIndex !== index ? html + str.slice(lastIndex, index) : html
  39. }
  40. // https://www.w3.org/TR/html52/syntax.html#comments
  41. const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g
  42. export function escapeHtmlComment(src: string): string {
  43. return src.replace(commentStripRE, '')
  44. }
  45. export const cssVarNameEscapeSymbolsRE: RegExp =
  46. /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
  47. export function getEscapedCssVarName(
  48. key: string,
  49. doubleEscape: boolean,
  50. ): string {
  51. return key.replace(cssVarNameEscapeSymbolsRE, s =>
  52. doubleEscape ? (s === '"' ? '\\\\\\"' : `\\\\${s}`) : `\\${s}`,
  53. )
  54. }