definition.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. 'use strict'
  2. var whitespace = require('is-whitespace-character')
  3. var normalize = require('../util/normalize')
  4. module.exports = definition
  5. var quotationMark = '"'
  6. var apostrophe = "'"
  7. var backslash = '\\'
  8. var lineFeed = '\n'
  9. var tab = '\t'
  10. var space = ' '
  11. var leftSquareBracket = '['
  12. var rightSquareBracket = ']'
  13. var leftParenthesis = '('
  14. var rightParenthesis = ')'
  15. var colon = ':'
  16. var lessThan = '<'
  17. var greaterThan = '>'
  18. function definition(eat, value, silent) {
  19. var self = this
  20. var commonmark = self.options.commonmark
  21. var index = 0
  22. var length = value.length
  23. var subvalue = ''
  24. var beforeURL
  25. var beforeTitle
  26. var queue
  27. var character
  28. var test
  29. var identifier
  30. var url
  31. var title
  32. while (index < length) {
  33. character = value.charAt(index)
  34. if (character !== space && character !== tab) {
  35. break
  36. }
  37. subvalue += character
  38. index++
  39. }
  40. character = value.charAt(index)
  41. if (character !== leftSquareBracket) {
  42. return
  43. }
  44. index++
  45. subvalue += character
  46. queue = ''
  47. while (index < length) {
  48. character = value.charAt(index)
  49. if (character === rightSquareBracket) {
  50. break
  51. } else if (character === backslash) {
  52. queue += character
  53. index++
  54. character = value.charAt(index)
  55. }
  56. queue += character
  57. index++
  58. }
  59. if (
  60. !queue ||
  61. value.charAt(index) !== rightSquareBracket ||
  62. value.charAt(index + 1) !== colon
  63. ) {
  64. return
  65. }
  66. identifier = queue
  67. subvalue += queue + rightSquareBracket + colon
  68. index = subvalue.length
  69. queue = ''
  70. while (index < length) {
  71. character = value.charAt(index)
  72. if (character !== tab && character !== space && character !== lineFeed) {
  73. break
  74. }
  75. subvalue += character
  76. index++
  77. }
  78. character = value.charAt(index)
  79. queue = ''
  80. beforeURL = subvalue
  81. if (character === lessThan) {
  82. index++
  83. while (index < length) {
  84. character = value.charAt(index)
  85. if (!isEnclosedURLCharacter(character)) {
  86. break
  87. }
  88. queue += character
  89. index++
  90. }
  91. character = value.charAt(index)
  92. if (character === isEnclosedURLCharacter.delimiter) {
  93. subvalue += lessThan + queue + character
  94. index++
  95. } else {
  96. if (commonmark) {
  97. return
  98. }
  99. index -= queue.length + 1
  100. queue = ''
  101. }
  102. }
  103. if (!queue) {
  104. while (index < length) {
  105. character = value.charAt(index)
  106. if (!isUnclosedURLCharacter(character)) {
  107. break
  108. }
  109. queue += character
  110. index++
  111. }
  112. subvalue += queue
  113. }
  114. if (!queue) {
  115. return
  116. }
  117. url = queue
  118. queue = ''
  119. while (index < length) {
  120. character = value.charAt(index)
  121. if (character !== tab && character !== space && character !== lineFeed) {
  122. break
  123. }
  124. queue += character
  125. index++
  126. }
  127. character = value.charAt(index)
  128. test = null
  129. if (character === quotationMark) {
  130. test = quotationMark
  131. } else if (character === apostrophe) {
  132. test = apostrophe
  133. } else if (character === leftParenthesis) {
  134. test = rightParenthesis
  135. }
  136. if (!test) {
  137. queue = ''
  138. index = subvalue.length
  139. } else if (queue) {
  140. subvalue += queue + character
  141. index = subvalue.length
  142. queue = ''
  143. while (index < length) {
  144. character = value.charAt(index)
  145. if (character === test) {
  146. break
  147. }
  148. if (character === lineFeed) {
  149. index++
  150. character = value.charAt(index)
  151. if (character === lineFeed || character === test) {
  152. return
  153. }
  154. queue += lineFeed
  155. }
  156. queue += character
  157. index++
  158. }
  159. character = value.charAt(index)
  160. if (character !== test) {
  161. return
  162. }
  163. beforeTitle = subvalue
  164. subvalue += queue + character
  165. index++
  166. title = queue
  167. queue = ''
  168. } else {
  169. return
  170. }
  171. while (index < length) {
  172. character = value.charAt(index)
  173. if (character !== tab && character !== space) {
  174. break
  175. }
  176. subvalue += character
  177. index++
  178. }
  179. character = value.charAt(index)
  180. if (!character || character === lineFeed) {
  181. if (silent) {
  182. return true
  183. }
  184. beforeURL = eat(beforeURL).test().end
  185. url = self.decode.raw(self.unescape(url), beforeURL, {nonTerminated: false})
  186. if (title) {
  187. beforeTitle = eat(beforeTitle).test().end
  188. title = self.decode.raw(self.unescape(title), beforeTitle)
  189. }
  190. return eat(subvalue)({
  191. type: 'definition',
  192. identifier: normalize(identifier),
  193. label: identifier,
  194. title: title || null,
  195. url: url
  196. })
  197. }
  198. }
  199. // Check if `character` can be inside an enclosed URI.
  200. function isEnclosedURLCharacter(character) {
  201. return (
  202. character !== greaterThan &&
  203. character !== leftSquareBracket &&
  204. character !== rightSquareBracket
  205. )
  206. }
  207. isEnclosedURLCharacter.delimiter = greaterThan
  208. // Check if `character` can be inside an unclosed URI.
  209. function isUnclosedURLCharacter(character) {
  210. return (
  211. character !== leftSquareBracket &&
  212. character !== rightSquareBracket &&
  213. !whitespace(character)
  214. )
  215. }