index.js 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import {decodeNamedCharacterReference} from 'decode-named-character-reference'
  2. import {decodeNumericCharacterReference} from 'micromark-util-decode-numeric-character-reference'
  3. import {codes, constants} from 'micromark-util-symbol'
  4. const characterEscapeOrReference =
  5. /\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi
  6. /**
  7. * Decode markdown strings (which occur in places such as fenced code info
  8. * strings, destinations, labels, and titles).
  9. *
  10. * The “string” content type allows character escapes and -references.
  11. * This decodes those.
  12. *
  13. * @param {string} value
  14. * Value to decode.
  15. * @returns {string}
  16. * Decoded value.
  17. */
  18. export function decodeString(value) {
  19. return value.replace(characterEscapeOrReference, decode)
  20. }
  21. /**
  22. * @param {string} $0
  23. * Match.
  24. * @param {string} $1
  25. * Character escape.
  26. * @param {string} $2
  27. * Character reference.
  28. * @returns {string}
  29. * Decoded value
  30. */
  31. function decode($0, $1, $2) {
  32. if ($1) {
  33. // Escape.
  34. return $1
  35. }
  36. // Reference.
  37. const head = $2.charCodeAt(0)
  38. if (head === codes.numberSign) {
  39. const head = $2.charCodeAt(1)
  40. const hex = head === codes.lowercaseX || head === codes.uppercaseX
  41. return decodeNumericCharacterReference(
  42. $2.slice(hex ? 2 : 1),
  43. hex ? constants.numericBaseHexadecimal : constants.numericBaseDecimal
  44. )
  45. }
  46. return decodeNamedCharacterReference($2) || $0
  47. }