index.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Process ~subscript~
  2. 'use strict';
  3. // same as UNESCAPE_MD_RE plus a space
  4. var UNESCAPE_RE = /\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;
  5. function subscript(state, silent) {
  6. var found,
  7. content,
  8. token,
  9. max = state.posMax,
  10. start = state.pos;
  11. if (state.src.charCodeAt(start) !== 0x7E/* ~ */) { return false; }
  12. if (silent) { return false; } // don't run any pairs in validation mode
  13. if (start + 2 >= max) { return false; }
  14. state.pos = start + 1;
  15. while (state.pos < max) {
  16. if (state.src.charCodeAt(state.pos) === 0x7E/* ~ */) {
  17. found = true;
  18. break;
  19. }
  20. state.md.inline.skipToken(state);
  21. }
  22. if (!found || start + 1 === state.pos) {
  23. state.pos = start;
  24. return false;
  25. }
  26. content = state.src.slice(start + 1, state.pos);
  27. // don't allow unescaped spaces/newlines inside
  28. if (content.match(/(^|[^\\])(\\\\)*\s/)) {
  29. state.pos = start;
  30. return false;
  31. }
  32. // found!
  33. state.posMax = state.pos;
  34. state.pos = start + 1;
  35. // Earlier we checked !silent, but this implementation does not need it
  36. token = state.push('sub_open', 'sub', 1);
  37. token.markup = '~';
  38. token = state.push('text', '', 0);
  39. token.content = content.replace(UNESCAPE_RE, '$1');
  40. token = state.push('sub_close', 'sub', -1);
  41. token.markup = '~';
  42. state.pos = state.posMax + 1;
  43. state.posMax = max;
  44. return true;
  45. }
  46. module.exports = function sub_plugin(md) {
  47. md.inline.ruler.after('emphasis', 'sub', subscript);
  48. };