outline-parser.test.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { expect } from 'chai'
  2. import {
  3. matchOutline,
  4. nestOutline
  5. } from '../../../../frontend/js/features/outline/outline-parser'
  6. describe('OutlineParser', function() {
  7. describe('matchOutline', function() {
  8. it('matches all levels', function() {
  9. const content = `
  10. \\book{Book}
  11. \\part{Part}
  12. \\chapter{Chapter}
  13. \\section{Section 1}
  14. \\subsection{Subsection}
  15. \\subsubsection{Subsubsection}
  16. \\section{Section 2}
  17. \\subsubsection{Subsubsection without subsection}
  18. \\paragraph{a paragraph} Here is some text.
  19. \\subparagraph{a subparagraph} Here is some more text.
  20. `
  21. const outline = matchOutline(content)
  22. expect(outline).to.deep.equal([
  23. { line: 2, title: 'Book', level: 10 },
  24. { line: 3, title: 'Part', level: 20 },
  25. { line: 4, title: 'Chapter', level: 30 },
  26. { line: 5, title: 'Section 1', level: 40 },
  27. { line: 6, title: 'Subsection', level: 50 },
  28. { line: 7, title: 'Subsubsection', level: 60 },
  29. { line: 8, title: 'Section 2', level: 40 },
  30. { line: 9, title: 'Subsubsection without subsection', level: 60 },
  31. { line: 10, title: 'a paragraph', level: 70 },
  32. { line: 11, title: 'a subparagraph', level: 80 }
  33. ])
  34. })
  35. it('matches display titles', function() {
  36. const content = `
  37. \\section{\\label{foo} Label before}
  38. \\section{Label after \\label{foo}}
  39. \\section{Label \\label{foo} between}
  40. \\section{TT \\texttt{Bar}}
  41. `
  42. const outline = matchOutline(content)
  43. expect(outline).to.deep.equal([
  44. { line: 2, title: ' Label before', level: 40 },
  45. { line: 3, title: 'Label after ', level: 40 },
  46. { line: 4, title: 'Label between', level: 40 },
  47. { line: 5, title: 'TT Bar', level: 40 }
  48. ])
  49. })
  50. it('matches empty sections', function() {
  51. const outline = matchOutline('\\section{}')
  52. expect(outline).to.deep.equal([{ line: 1, title: '', level: 40 }])
  53. })
  54. it('matches indented sections', function() {
  55. const outline = matchOutline('\t\\section{Indented}')
  56. expect(outline).to.deep.equal([{ line: 1, title: 'Indented', level: 40 }])
  57. })
  58. it('matches unnumbered sections', function() {
  59. const outline = matchOutline('\\section*{Unnumbered}')
  60. expect(outline).to.deep.equal([
  61. { line: 1, title: 'Unnumbered', level: 40 }
  62. ])
  63. })
  64. it('matches short titles', function() {
  65. const outline = matchOutline(
  66. '\\chapter[Short Title For TOC]{Very Long Title for Text}'
  67. )
  68. expect(outline).to.deep.equal([
  69. { line: 1, title: 'Short Title For TOC', level: 30 }
  70. ])
  71. })
  72. it('handles spacing', function() {
  73. const content = `
  74. \\section {Weird Spacing}
  75. \\section * {Weird Spacing Unnumbered}
  76. \\section [Weird Spacing for TOC] {Weird Spacing}
  77. `
  78. const outline = matchOutline(content)
  79. expect(outline).to.deep.equal([
  80. { line: 2, title: 'Weird Spacing', level: 40 },
  81. { line: 3, title: 'Weird Spacing Unnumbered', level: 40 },
  82. { line: 4, title: 'Weird Spacing for TOC', level: 40 }
  83. ])
  84. })
  85. it("doesn't match commented lines", function() {
  86. const content = `
  87. % \\section{I should not appear in the outline}
  88. `
  89. const outline = matchOutline(content)
  90. expect(outline).to.deep.equal([])
  91. })
  92. it("doesn't match inline sections", function() {
  93. const content = `
  94. I like to write \\section{inline} on one line.
  95. `
  96. const outline = matchOutline(content)
  97. expect(outline).to.deep.equal([])
  98. })
  99. })
  100. describe('nestOutline', function() {
  101. it('matches all levels', function() {
  102. const flatOutline = [
  103. { line: 10, title: 'Book', level: 10 },
  104. { line: 20, title: 'Part A', level: 20 },
  105. { line: 30, title: 'Section A 1', level: 40 },
  106. { line: 40, title: 'Subsection A 1 1', level: 50 },
  107. { line: 50, title: 'Subsection A 1 2', level: 50 },
  108. { line: 60, title: 'Section A 2', level: 40 },
  109. { line: 70, title: 'Section A 3', level: 40 },
  110. { line: 80, title: 'Subsection A 3 1', level: 50 },
  111. { line: 90, title: 'Chapter', level: 30 },
  112. { line: 100, title: 'Part B', level: 20 },
  113. { line: 110, title: 'Section 2', level: 40 },
  114. { line: 120, title: 'Subsubsection without subsection', level: 60 }
  115. ]
  116. const nestedOutline = nestOutline(flatOutline)
  117. expect(nestedOutline).to.deep.equal([
  118. {
  119. line: 10,
  120. title: 'Book',
  121. level: 10,
  122. children: [
  123. {
  124. line: 20,
  125. title: 'Part A',
  126. level: 20,
  127. children: [
  128. {
  129. line: 30,
  130. title: 'Section A 1',
  131. level: 40,
  132. children: [
  133. { line: 40, title: 'Subsection A 1 1', level: 50 },
  134. { line: 50, title: 'Subsection A 1 2', level: 50 }
  135. ]
  136. },
  137. { line: 60, title: 'Section A 2', level: 40 },
  138. {
  139. line: 70,
  140. title: 'Section A 3',
  141. level: 40,
  142. children: [{ line: 80, title: 'Subsection A 3 1', level: 50 }]
  143. },
  144. { line: 90, title: 'Chapter', level: 30 }
  145. ]
  146. },
  147. {
  148. line: 100,
  149. title: 'Part B',
  150. level: 20,
  151. children: [
  152. {
  153. line: 110,
  154. title: 'Section 2',
  155. level: 40,
  156. children: [
  157. {
  158. line: 120,
  159. title: 'Subsubsection without subsection',
  160. level: 60
  161. }
  162. ]
  163. }
  164. ]
  165. }
  166. ]
  167. }
  168. ])
  169. })
  170. })
  171. })