definition.js 5.1 KB

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