email.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. 'use strict'
  2. var decode = require('parse-entities')
  3. var decimal = require('is-decimal')
  4. var alphabetical = require('is-alphabetical')
  5. var locate = require('../locate/email')
  6. module.exports = email
  7. email.locator = locate
  8. email.notInLink = true
  9. var plusSign = 43 // '+'
  10. var dash = 45 // '-'
  11. var dot = 46 // '.'
  12. var atSign = 64 // '@'
  13. var underscore = 95 // '_'
  14. function email(eat, value, silent) {
  15. var self = this
  16. var gfm = self.options.gfm
  17. var tokenizers = self.inlineTokenizers
  18. var index = 0
  19. var length = value.length
  20. var firstDot = -1
  21. var code
  22. var content
  23. var children
  24. var exit
  25. if (!gfm) {
  26. return
  27. }
  28. code = value.charCodeAt(index)
  29. while (
  30. decimal(code) ||
  31. alphabetical(code) ||
  32. code === plusSign ||
  33. code === dash ||
  34. code === dot ||
  35. code === underscore
  36. ) {
  37. code = value.charCodeAt(++index)
  38. }
  39. if (index === 0) {
  40. return
  41. }
  42. if (code !== atSign) {
  43. return
  44. }
  45. index++
  46. while (index < length) {
  47. code = value.charCodeAt(index)
  48. if (
  49. decimal(code) ||
  50. alphabetical(code) ||
  51. code === dash ||
  52. code === dot ||
  53. code === underscore
  54. ) {
  55. index++
  56. if (firstDot === -1 && code === dot) {
  57. firstDot = index
  58. }
  59. continue
  60. }
  61. break
  62. }
  63. if (
  64. firstDot === -1 ||
  65. firstDot === index ||
  66. code === dash ||
  67. code === underscore
  68. ) {
  69. return
  70. }
  71. if (code === dot) {
  72. index--
  73. }
  74. content = value.slice(0, index)
  75. /* istanbul ignore if - never used (yet) */
  76. if (silent) {
  77. return true
  78. }
  79. exit = self.enterLink()
  80. // Temporarily remove all tokenizers except text in url.
  81. self.inlineTokenizers = {text: tokenizers.text}
  82. children = self.tokenizeInline(content, eat.now())
  83. self.inlineTokenizers = tokenizers
  84. exit()
  85. return eat(content)({
  86. type: 'link',
  87. title: null,
  88. url: 'mailto:' + decode(content, {nonTerminated: false}),
  89. children: children
  90. })
  91. }