bib2json.spec.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import { Bib2JsonEntry } from '@/features/ide-react/references/types'
  2. import BibtexParserImport from '../../../../../../frontend/js/features/ide-react/references/bib2json'
  3. import { expect } from 'chai'
  4. const BibtexParser = BibtexParserImport as unknown as (
  5. content: string,
  6. allowedKeys?: string[]
  7. ) => {
  8. entries: Bib2JsonEntry[]
  9. errors: any[]
  10. }
  11. describe('Bib2JsonTests', function () {
  12. describe('Upstream', function () {
  13. // pulled in from the bib2json repository
  14. // https://github.com/mayanklahiri/bib2json/blob/3d7c1f0d738c07d0e1c9a59f4cb9b96c74deb744/test/spec/ParserSpec.js
  15. // Author: Mayank Lahiri <mlahiri@gmail.com>
  16. // License: BSD-2-Clause
  17. it('Parse an empty string without errors or results', function () {
  18. const result = BibtexParser(' \t\t\n \n\n')
  19. expect(result.entries.length).to.equal(0)
  20. expect(result.errors.length).to.equal(0)
  21. })
  22. it('Parse braces within braces', function () {
  23. const result = BibtexParser(
  24. '@book { pollock, title={{{A}} very {Big} Book.} }'
  25. )
  26. expect(result.entries.length).to.equal(1)
  27. expect(result.errors.length).to.equal(0)
  28. expect(result.entries[0].Fields.title).to.equal('A very Big Book.')
  29. })
  30. it('Parse braces within quotes', function () {
  31. const result = BibtexParser(
  32. '@book { pollock, title="{A} very {Big} Book."}'
  33. )
  34. expect(result.entries.length).to.equal(1)
  35. expect(result.errors.length).to.equal(0)
  36. expect(result.entries[0].Fields.title).to.equal('A very Big Book.')
  37. })
  38. it('Parse quotes within braces', function () {
  39. const result = BibtexParser(
  40. '@book { pollock, title="{A} very {"Big"} Book."}'
  41. )
  42. expect(result.entries.length).to.equal(1)
  43. expect(result.errors.length).to.equal(0)
  44. expect(result.entries[0].Fields.title).to.equal('A very "Big" Book.')
  45. })
  46. it('Respect backslashes', function () {
  47. const text = '@book { pollock, title="{A} \\\\very \\{{Big} \\"Book\\"."}'
  48. const result = BibtexParser(text)
  49. expect(result.entries.length).to.equal(1)
  50. expect(result.errors.length).to.equal(0)
  51. expect(result.entries[0].Fields.title).to.equal('A \\very {Big "Book".')
  52. })
  53. it('Convert some Latex characters to UTF-8', function () {
  54. const result = BibtexParser(
  55. '@book { pollock, title="\\"{o}\\AA \\^{I}\\alpha " }'
  56. )
  57. expect(result.entries.length).to.equal(1)
  58. expect(result.errors.length).to.equal(0)
  59. expect(result.entries[0].Fields.title).to.equal(
  60. '\u00f6\u00c5\u00ce\u03b1'
  61. )
  62. })
  63. it('Expand a predefined macro in the middle an entry', function () {
  64. const text = '@book{ pollock, month = jan, title="A title!" }'
  65. const result = BibtexParser(text)
  66. expect(result.entries.length).to.equal(1)
  67. expect(result.errors.length).to.equal(0)
  68. expect(result.entries[0].Fields.month).to.equal('January')
  69. })
  70. return it('Expand a macro at the end of an entry', function () {
  71. const text =
  72. '@string \n{ howdy = "well, hello!" }@book{ pollock, title=howdy }'
  73. const result = BibtexParser(text)
  74. expect(result.entries.length).to.equal(1)
  75. expect(result.errors.length).to.equal(0)
  76. expect(result.entries[0].Fields.title).to.equal('well, hello!')
  77. })
  78. })
  79. describe('normalize keys to lower case', function () {
  80. it('should lower the case of RaNDoM', function () {
  81. const text = '@book{ id, RaNDoM = "VALUE" }'
  82. const result = BibtexParser(text)
  83. expect(result.entries.length).to.equal(1)
  84. expect(result.errors.length).to.equal(0)
  85. expect(result.entries[0].Fields).to.deep.equal({ random: 'VALUE' })
  86. })
  87. return it('should preserve the marco usage of RaNDoM', function () {
  88. const text = '@string{ RaNDoM="MACRO"}@book{ id, Title = RaNDoM }'
  89. const result = BibtexParser(text)
  90. expect(result.entries.length).to.equal(1)
  91. expect(result.errors.length).to.equal(0)
  92. expect(result.entries[0].Fields).to.deep.equal({ title: 'MACRO' })
  93. })
  94. })
  95. // sometimes imported bib files contain {\\}, {\\\}, {\\\\} etc to replace whitespace in values
  96. describe('handles backslash braces from imported bibs', function () {
  97. it('handles one backslash {\\}', function () {
  98. const text =
  99. '@book { pollock, title="{\\}{A} \\\\very \\{{Big} \\"Book\\"."}'
  100. const result = BibtexParser(text)
  101. expect(result.entries.length).to.equal(1)
  102. expect(result.errors.length).to.equal(0)
  103. expect(result.entries[0].Fields.title).to.equal('}A \\very {Big "Book".')
  104. })
  105. it('handles two backslashes {\\\\}', function () {
  106. const text =
  107. '@book { pollock, title="{\\\\}{A} \\\\very \\{{Big} \\"Book\\"."}'
  108. const result = BibtexParser(text)
  109. expect(result.entries.length).to.equal(1)
  110. expect(result.errors.length).to.equal(0)
  111. expect(result.entries[0].Fields.title).to.equal('\\A \\very {Big "Book".')
  112. })
  113. it('handles three backslashes {\\\\\\}', function () {
  114. const text =
  115. '@book { pollock, title="{\\\\\\}{A} \\\\very \\{{Big} \\"Book\\"."}'
  116. const result = BibtexParser(text)
  117. expect(result.entries.length).to.equal(1)
  118. expect(result.errors.length).to.equal(0)
  119. expect(result.entries[0].Fields.title).to.equal(
  120. '\\}A \\very {Big "Book".'
  121. )
  122. })
  123. it('handles four backslashes {\\\\\\\\}', function () {
  124. const text =
  125. '@book { pollock, title="{\\\\\\\\}{A} \\\\very \\{{Big} \\"Book\\"."}'
  126. const result = BibtexParser(text)
  127. expect(result.entries.length).to.equal(1)
  128. expect(result.errors.length).to.equal(0)
  129. expect(result.entries[0].Fields.title).to.equal(
  130. '\\\\A \\very {Big "Book".'
  131. )
  132. })
  133. it('keeps parsing future entries after an even amount of backslashes {\\\\}', function () {
  134. const text =
  135. '@book { pollock, title="{\\\\}{A} \\\\very \\{{Big} \\"Book\\"."}' +
  136. '@book { pollock, title="{\\\\}{A} \\\\very \\{{Big} secondary \\"Book\\".", author="Muräkämi, Häruki"}'
  137. const result = BibtexParser(text)
  138. expect(result.entries.length).to.equal(2)
  139. expect(result.errors.length).to.equal(0)
  140. expect(result.entries[0].Fields.title).to.equal('\\A \\very {Big "Book".')
  141. expect(result.entries[1].Fields.title).to.equal(
  142. '\\A \\very {Big secondary "Book".'
  143. )
  144. expect(result.entries[1].Fields.author).to.equal('Muräkämi, Häruki')
  145. })
  146. return it('keeps parsing future entries after an odd amount of backslashes {\\\\\\}', function () {
  147. const text =
  148. '@book { pollock, title="{\\\\\\}{A} \\\\very \\{{Big} \\"Book\\"."}' +
  149. '@book { pollock, title="{\\\\}{A} \\\\very \\{{Big} secondary \\"Book\\".", author="Muräkämi, Häruki"}'
  150. const result = BibtexParser(text)
  151. expect(result.entries.length).to.equal(2)
  152. expect(result.errors.length).to.equal(0)
  153. expect(result.entries[0].Fields.title).to.equal(
  154. '\\}A \\very {Big "Book".'
  155. )
  156. expect(result.entries[1].Fields.title).to.equal(
  157. '\\A \\very {Big secondary "Book".'
  158. )
  159. expect(result.entries[1].Fields.author).to.equal('Muräkämi, Häruki')
  160. })
  161. })
  162. return describe('with allowedKeys set', function () {
  163. it('should skip the unknown key Random', function () {
  164. const text = '@book{ id, Random = "ABC", title="VALUE" }'
  165. const result = BibtexParser(text, ['title'])
  166. expect(result.entries.length).to.equal(1)
  167. expect(result.errors.length).to.equal(0)
  168. expect(result.entries[0].Fields).to.deep.equal({ title: 'VALUE' })
  169. })
  170. it('should still parse unknown entry types', function () {
  171. const text = '@myCustomType{ id, Random = "ABC", title="VALUE" }'
  172. const result = BibtexParser(text, ['title'])
  173. expect(result.entries.length).to.equal(1)
  174. expect(result.errors.length).to.equal(0)
  175. expect(result.entries[0].Fields).to.deep.equal({ title: 'VALUE' })
  176. })
  177. return it('should preserve the marco usage of RaNDoM', function () {
  178. const text =
  179. '@string{ RaNDoM="MACRO"}@book{ id, Random = "ABC", Title = RaNDoM }'
  180. const result = BibtexParser(text, ['title'])
  181. expect(result.entries.length).to.equal(1)
  182. expect(result.errors.length).to.equal(0)
  183. expect(result.entries[0].Fields).to.deep.equal({ title: 'MACRO' })
  184. })
  185. })
  186. })