strikethrough.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // ~~strike through~~
  2. //
  3. 'use strict';
  4. // Insert each marker as a separate text token, and add it to delimiter list
  5. //
  6. module.exports.tokenize = function strikethrough(state, silent) {
  7. var i, scanned, token, len, ch,
  8. start = state.pos,
  9. marker = state.src.charCodeAt(start);
  10. if (silent) { return false; }
  11. if (marker !== 0x7E/* ~ */) { return false; }
  12. scanned = state.scanDelims(state.pos, true);
  13. len = scanned.length;
  14. ch = String.fromCharCode(marker);
  15. if (len < 2) { return false; }
  16. if (len % 2) {
  17. token = state.push('text', '', 0);
  18. token.content = ch;
  19. len--;
  20. }
  21. for (i = 0; i < len; i += 2) {
  22. token = state.push('text', '', 0);
  23. token.content = ch + ch;
  24. state.delimiters.push({
  25. marker: marker,
  26. jump: i,
  27. token: state.tokens.length - 1,
  28. level: state.level,
  29. end: -1,
  30. open: scanned.can_open,
  31. close: scanned.can_close
  32. });
  33. }
  34. state.pos += scanned.length;
  35. return true;
  36. };
  37. // Walk through delimiter list and replace text tokens with tags
  38. //
  39. module.exports.postProcess = function strikethrough(state) {
  40. var i, j,
  41. startDelim,
  42. endDelim,
  43. token,
  44. loneMarkers = [],
  45. delimiters = state.delimiters,
  46. max = state.delimiters.length;
  47. for (i = 0; i < max; i++) {
  48. startDelim = delimiters[i];
  49. if (startDelim.marker !== 0x7E/* ~ */) {
  50. continue;
  51. }
  52. if (startDelim.end === -1) {
  53. continue;
  54. }
  55. endDelim = delimiters[startDelim.end];
  56. token = state.tokens[startDelim.token];
  57. token.type = 's_open';
  58. token.tag = 's';
  59. token.nesting = 1;
  60. token.markup = '~~';
  61. token.content = '';
  62. token = state.tokens[endDelim.token];
  63. token.type = 's_close';
  64. token.tag = 's';
  65. token.nesting = -1;
  66. token.markup = '~~';
  67. token.content = '';
  68. if (state.tokens[endDelim.token - 1].type === 'text' &&
  69. state.tokens[endDelim.token - 1].content === '~') {
  70. loneMarkers.push(endDelim.token - 1);
  71. }
  72. }
  73. // If a marker sequence has an odd number of characters, it's splitted
  74. // like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the
  75. // start of the sequence.
  76. //
  77. // So, we have to move all those markers after subsequent s_close tags.
  78. //
  79. while (loneMarkers.length) {
  80. i = loneMarkers.pop();
  81. j = i + 1;
  82. while (j < state.tokens.length && state.tokens[j].type === 's_close') {
  83. j++;
  84. }
  85. j--;
  86. if (i !== j) {
  87. token = state.tokens[j];
  88. state.tokens[j] = state.tokens[i];
  89. state.tokens[i] = token;
  90. }
  91. }
  92. };