index.js 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import {codes, values} from 'micromark-util-symbol'
  2. /**
  3. * Turn the number (in string form as either hexa- or plain decimal) coming from
  4. * a numeric character reference into a character.
  5. *
  6. * Sort of like `String.fromCodePoint(Number.parseInt(value, base))`, but makes
  7. * non-characters and control characters safe.
  8. *
  9. * @param {string} value
  10. * Value to decode.
  11. * @param {number} base
  12. * Numeric base.
  13. * @returns {string}
  14. * Character.
  15. */
  16. export function decodeNumericCharacterReference(value, base) {
  17. const code = Number.parseInt(value, base)
  18. if (
  19. // C0 except for HT, LF, FF, CR, space.
  20. code < codes.ht ||
  21. code === codes.vt ||
  22. (code > codes.cr && code < codes.space) ||
  23. // Control character (DEL) of C0, and C1 controls.
  24. (code > codes.tilde && code < 160) ||
  25. // Lone high surrogates and low surrogates.
  26. (code > 55_295 && code < 57_344) ||
  27. // Noncharacters.
  28. (code > 64_975 && code < 65_008) ||
  29. /* eslint-disable no-bitwise */
  30. (code & 65_535) === 65_535 ||
  31. (code & 65_535) === 65_534 ||
  32. /* eslint-enable no-bitwise */
  33. // Out of range
  34. code > 1_114_111
  35. ) {
  36. return values.replacementCharacter
  37. }
  38. return String.fromCodePoint(code)
  39. }