| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- import { expect } from 'chai'
- import {
- matchOutline,
- nestOutline,
- } from '../../../../frontend/js/features/outline/outline-parser'
- describe('OutlineParser', function () {
- describe('matchOutline', function () {
- it('matches all levels', function () {
- const content = `
- \\book{Book}
- \\part{Part}
- \\addpart{Part 2}
- \\chapter{Chapter}
- \\addchap{Chapter 2}
- \\section{Section 1}
- \\addsec{Section 1b}
- \\subsection{Subsection}
- \\subsubsection{Subsubsection}
- \\section{Section 2}
- \\subsubsection{Subsubsection without subsection}
- \\paragraph{a paragraph} Here is some text.
- \\subparagraph{a subparagraph} Here is some more text.
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([
- { line: 2, title: 'Book', level: 10 },
- { line: 3, title: 'Part', level: 20 },
- { line: 4, title: 'Part 2', level: 20 },
- { line: 5, title: 'Chapter', level: 30 },
- { line: 6, title: 'Chapter 2', level: 30 },
- { line: 7, title: 'Section 1', level: 40 },
- { line: 8, title: 'Section 1b', level: 40 },
- { line: 9, title: 'Subsection', level: 50 },
- { line: 10, title: 'Subsubsection', level: 60 },
- { line: 11, title: 'Section 2', level: 40 },
- { line: 12, title: 'Subsubsection without subsection', level: 60 },
- { line: 13, title: 'a paragraph', level: 70 },
- { line: 14, title: 'a subparagraph', level: 80 },
- ])
- })
- it('matches display titles', function () {
- const content = `
- \\section{\\label{foo} Label before}
- \\section{Label after \\label{foo}}
- \\section{Label \\label{foo} between}
- \\section{TT \\texttt{Bar}}
- \\section{plain title}
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([
- { line: 2, title: ' Label before', level: 40 },
- { line: 3, title: 'Label after ', level: 40 },
- { line: 4, title: 'Label between', level: 40 },
- { line: 5, title: 'TT Bar', level: 40 },
- { line: 6, title: 'plain title', level: 40 },
- ])
- })
- it('removes spurious commands after title definition', function () {
- const content = `
- \\section{Plain title} more text \\href{link}{link}
- \\section{\\label{foo} Label before} more text \\href{link}{link}
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([
- { line: 2, title: 'Plain title', level: 40 },
- { line: 3, title: ' Label before', level: 40 },
- ])
- })
- it('matches empty sections', function () {
- const outline = matchOutline('\\section{}')
- expect(outline).to.deep.equal([{ line: 1, title: '', level: 40 }])
- })
- it('matches indented sections', function () {
- const outline = matchOutline('\t\\section{Indented}')
- expect(outline).to.deep.equal([{ line: 1, title: 'Indented', level: 40 }])
- })
- it('matches unnumbered sections', function () {
- const outline = matchOutline('\\section*{Unnumbered}')
- expect(outline).to.deep.equal([
- { line: 1, title: 'Unnumbered', level: 40 },
- ])
- })
- it('matches short titles', function () {
- const outline = matchOutline(
- '\\chapter[Short Title For TOC]{Very Long Title for Text}'
- )
- expect(outline).to.deep.equal([
- { line: 1, title: 'Short Title For TOC', level: 30 },
- ])
- })
- it('handles spacing', function () {
- const content = `
- \\section {Weird Spacing}
- \\section * {Weird Spacing Unnumbered}
- \\section [Weird Spacing for TOC] {Weird Spacing}
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([
- { line: 2, title: 'Weird Spacing', level: 40 },
- { line: 3, title: 'Weird Spacing Unnumbered', level: 40 },
- { line: 4, title: 'Weird Spacing for TOC', level: 40 },
- ])
- })
- it("doesn't match commented lines", function () {
- const content = `
- % \\section{I should not appear in the outline}
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([])
- })
- it("doesn't match inline sections", function () {
- const content = `
- I like to write \\section{inline} on one line.
- `
- const outline = matchOutline(content)
- expect(outline).to.deep.equal([])
- })
- })
- describe('nestOutline', function () {
- it('matches all levels', function () {
- const flatOutline = [
- { line: 10, title: 'Book', level: 10 },
- { line: 20, title: 'Part A', level: 20 },
- { line: 30, title: 'Section A 1', level: 40 },
- { line: 40, title: 'Subsection A 1 1', level: 50 },
- { line: 50, title: 'Subsection A 1 2', level: 50 },
- { line: 60, title: 'Section A 2', level: 40 },
- { line: 70, title: 'Section A 3', level: 40 },
- { line: 80, title: 'Subsection A 3 1', level: 50 },
- { line: 90, title: 'Chapter', level: 30 },
- { line: 100, title: 'Part B', level: 20 },
- { line: 110, title: 'Section 2', level: 40 },
- { line: 120, title: 'Subsubsection without subsection', level: 60 },
- ]
- const nestedOutline = nestOutline(flatOutline)
- expect(nestedOutline).to.deep.equal([
- {
- line: 10,
- title: 'Book',
- level: 10,
- children: [
- {
- line: 20,
- title: 'Part A',
- level: 20,
- children: [
- {
- line: 30,
- title: 'Section A 1',
- level: 40,
- children: [
- { line: 40, title: 'Subsection A 1 1', level: 50 },
- { line: 50, title: 'Subsection A 1 2', level: 50 },
- ],
- },
- { line: 60, title: 'Section A 2', level: 40 },
- {
- line: 70,
- title: 'Section A 3',
- level: 40,
- children: [
- { line: 80, title: 'Subsection A 3 1', level: 50 },
- ],
- },
- { line: 90, title: 'Chapter', level: 30 },
- ],
- },
- {
- line: 100,
- title: 'Part B',
- level: 20,
- children: [
- {
- line: 110,
- title: 'Section 2',
- level: 40,
- children: [
- {
- line: 120,
- title: 'Subsubsection without subsection',
- level: 60,
- },
- ],
- },
- ],
- },
- ],
- },
- ])
- })
- })
- })
|