character-reference.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict'
  2. var assert = require('assert')
  3. var decodeEntity = require('parse-entities/decode-entity.js')
  4. var asciiAlphanumeric = require('../character/ascii-alphanumeric.js')
  5. var asciiDigit = require('../character/ascii-digit.js')
  6. var asciiHexDigit = require('../character/ascii-hex-digit.js')
  7. var codes = require('../character/codes.js')
  8. var constants = require('../constant/constants.js')
  9. var types = require('../constant/types.js')
  10. function _interopDefaultLegacy(e) {
  11. return e && typeof e === 'object' && 'default' in e ? e : {default: e}
  12. }
  13. var assert__default = /*#__PURE__*/ _interopDefaultLegacy(assert)
  14. var decodeEntity__default = /*#__PURE__*/ _interopDefaultLegacy(decodeEntity)
  15. var characterReference = {
  16. name: 'characterReference',
  17. tokenize: tokenizeCharacterReference
  18. }
  19. function tokenizeCharacterReference(effects, ok, nok) {
  20. var self = this
  21. var size = 0
  22. var max
  23. var test
  24. return start
  25. function start(code) {
  26. assert__default['default'](code === codes.ampersand, 'expected `&`')
  27. effects.enter(types.characterReference)
  28. effects.enter(types.characterReferenceMarker)
  29. effects.consume(code)
  30. effects.exit(types.characterReferenceMarker)
  31. return open
  32. }
  33. function open(code) {
  34. if (code === codes.numberSign) {
  35. effects.enter(types.characterReferenceMarkerNumeric)
  36. effects.consume(code)
  37. effects.exit(types.characterReferenceMarkerNumeric)
  38. return numeric
  39. }
  40. effects.enter(types.characterReferenceValue)
  41. max = constants.characterReferenceNamedSizeMax
  42. test = asciiAlphanumeric
  43. return value(code)
  44. }
  45. function numeric(code) {
  46. if (code === codes.uppercaseX || code === codes.lowercaseX) {
  47. effects.enter(types.characterReferenceMarkerHexadecimal)
  48. effects.consume(code)
  49. effects.exit(types.characterReferenceMarkerHexadecimal)
  50. effects.enter(types.characterReferenceValue)
  51. max = constants.characterReferenceHexadecimalSizeMax
  52. test = asciiHexDigit
  53. return value
  54. }
  55. effects.enter(types.characterReferenceValue)
  56. max = constants.characterReferenceDecimalSizeMax
  57. test = asciiDigit
  58. return value(code)
  59. }
  60. function value(code) {
  61. var token
  62. if (code === codes.semicolon && size) {
  63. token = effects.exit(types.characterReferenceValue)
  64. if (
  65. test === asciiAlphanumeric &&
  66. !decodeEntity__default['default'](self.sliceSerialize(token))
  67. ) {
  68. return nok(code)
  69. }
  70. effects.enter(types.characterReferenceMarker)
  71. effects.consume(code)
  72. effects.exit(types.characterReferenceMarker)
  73. effects.exit(types.characterReference)
  74. return ok
  75. }
  76. if (test(code) && size++ < max) {
  77. effects.consume(code)
  78. return value
  79. }
  80. return nok(code)
  81. }
  82. }
  83. module.exports = characterReference