splitAtDelimiters.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* eslint no-constant-condition:0 */
  2. const findEndOfMath = function(delimiter, text, startIndex) {
  3. // Adapted from
  4. // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
  5. let index = startIndex;
  6. let braceLevel = 0;
  7. const delimLength = delimiter.length;
  8. while (index < text.length) {
  9. const character = text[index];
  10. if (braceLevel <= 0 &&
  11. text.slice(index, index + delimLength) === delimiter) {
  12. return index;
  13. } else if (character === "\\") {
  14. index++;
  15. } else if (character === "{") {
  16. braceLevel++;
  17. } else if (character === "}") {
  18. braceLevel--;
  19. }
  20. index++;
  21. }
  22. return -1;
  23. };
  24. const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
  25. const finalData = [];
  26. for (let i = 0; i < startData.length; i++) {
  27. if (startData[i].type === "text") {
  28. const text = startData[i].data;
  29. let lookingForLeft = true;
  30. let currIndex = 0;
  31. let nextIndex;
  32. nextIndex = text.indexOf(leftDelim);
  33. if (nextIndex !== -1) {
  34. currIndex = nextIndex;
  35. finalData.push({
  36. type: "text",
  37. data: text.slice(0, currIndex),
  38. });
  39. lookingForLeft = false;
  40. }
  41. while (true) {
  42. if (lookingForLeft) {
  43. nextIndex = text.indexOf(leftDelim, currIndex);
  44. if (nextIndex === -1) {
  45. break;
  46. }
  47. finalData.push({
  48. type: "text",
  49. data: text.slice(currIndex, nextIndex),
  50. });
  51. currIndex = nextIndex;
  52. } else {
  53. nextIndex = findEndOfMath(
  54. rightDelim,
  55. text,
  56. currIndex + leftDelim.length);
  57. if (nextIndex === -1) {
  58. break;
  59. }
  60. finalData.push({
  61. type: "math",
  62. data: text.slice(
  63. currIndex + leftDelim.length,
  64. nextIndex),
  65. rawData: text.slice(
  66. currIndex,
  67. nextIndex + rightDelim.length),
  68. display: display,
  69. });
  70. currIndex = nextIndex + rightDelim.length;
  71. }
  72. lookingForLeft = !lookingForLeft;
  73. }
  74. finalData.push({
  75. type: "text",
  76. data: text.slice(currIndex),
  77. });
  78. } else {
  79. finalData.push(startData[i]);
  80. }
  81. }
  82. return finalData;
  83. };
  84. export default splitAtDelimiters;