Exemple #1
0
def test_parse_suffix_section(app):
    source = """
## Section 1

- [1A](./1A.md)
- [1B](./1B.md)

---

[2A](./2A.md)
[2B](./2B.md)
[2C](./2C.md)
"""
    parser = SummaryParser(app, source)
    actual = parser.parse_sections()

    expected = [
        Section(title='Section 1',
                parts=[
                    Part('1A', source='./1A.md', level=0),
                    Part('1B', source='./1B.md', level=0),
                ]),
        Section(parts=[
            Part('2A', source='./2A.md'),
            Part('2B', source='./2B.md'),
            Part('2C', source='./2C.md'),
        ]),
    ]
    assert actual == expected
Exemple #2
0
def test_create_part_raises_value_error_when_link_is_empty(app):
    src = "[Empty]()\n"
    parser = SummaryParser(app, src)

    element = parser.stream.parse_tree.find('.//a')
    with pytest.raises(ValueError):
        parser.create_part(element)
Exemple #3
0
def test_parse_sections_with_multiple_sections_where_first_section_has_no_heading(
        app):
    source = """
- [1A](./1A.md)
- [1B](./1B.md)
- [1C](./1C.md)

## Section 2

- [2A](./2A.md)

"""
    parser = SummaryParser(app, source)
    actual = parser.parse_sections()

    expected = [
        Section(parts=[
            Part('1A', source='./1A.md', level=0),
            Part('1B', source='./1B.md', level=0),
            Part('1C', source='./1C.md', level=0),
        ]),
        Section(title='Section 2',
                parts=[
                    Part('2A', source='./2A.md', level=0),
                ]),
    ]
    assert actual == expected
Exemple #4
0
def test_parse_sections_with_one_section_and_no_heading(app):
    source = """
- [1A](./1A.md)
- [1B](./1B.md)
- [1C](./1C.md)
"""
    parser = SummaryParser(app, source)
    actual = parser.parse_sections()

    expected = [
        Section(parts=[
            Part('1A', source='./1A.md', level=0),
            Part('1B', source='./1B.md', level=0),
            Part('1C', source='./1C.md', level=0),
        ])
    ]
    assert actual == expected
Exemple #5
0
def test_parse_section_with_one_section_excluding_non_links(app):
    src = """
- [First](./first.md)
- [Second](./second.md)
- Item 1
- Item 2
- [Third](./third.md)"""
    parser = SummaryParser(app, src)
    actual = parser.parse_sections()

    expected = [
        Section(parts=[
            Part('First', source='./first.md', level=0),
            Part('Second', source='./second.md', level=0),
            Part('Third', source='./third.md', level=0),
        ])
    ]
    assert actual == expected
Exemple #6
0
def test_parse_sections_with_multiple_sections(app):
    source = """
## Section 1

- [1A](./1A.md)
- [1B](./1B.md)
- [1C](./1C.md)

---

- [2A](./2A.md)
- [2B](./2B.md)
- [2C](./2C.md)
- [2D](./2D.md)

#### Section 3

- [3A](./3A.md)

"""
    parser = SummaryParser(app, source)
    actual = parser.parse_sections()

    expected = [
        Section(title='Section 1',
                parts=[
                    Part('1A', source='./1A.md', level=0),
                    Part('1B', source='./1B.md', level=0),
                    Part('1C', source='./1C.md', level=0),
                ]),
        Section(parts=[
            Part('2A', source='./2A.md', level=0),
            Part('2B', source='./2B.md', level=0),
            Part('2C', source='./2C.md', level=0),
            Part('2D', source='./2D.md', level=0),
        ]),
        Section(title='Section 3',
                parts=[
                    Part('3A', source='./3A.md', level=0),
                ]),
    ]
    assert actual == expected
Exemple #7
0
def parse_summary(book):
    """Parse the text to create a ``Summary`` object.

    The ``text``, read from a ``SUMMARY.md`` file, is parsed into a ``Summary``
    object, which acts as a sort of "recipe" to be used when loading a book's
    contents from disk. It represents the structure of the book, in-so-far as
    how the chapters will be compiled and in what order.

    Summary Format
    --------------

    The format of the ``SUMMARY.md`` might contain the following elements:

    - **Title:** It's common practice to begin with a title, e.g. ``# Summary``.
      It's not mandatory and the parser (currently) ignores it, so you can too
      if you feel like it.
    - **Prefix Chapters:** Before the main numbered chapters you can add one or
      more chapter elements that will not be numbered.

      This is useful for forewords, introductions, etc. There are however some
      constraints: (1) You can not nest prefix chapters, they should all be on
      the root level, and (2) you can not add prefix chapters once you have
      added numbered chapters.::

        [Title of prefix element](relative/path/to/markdown.md)

    - **Numbered Chapter:** Numbered chapters are the main content of the book,
      they will be numbered and can be nested, resulting in a nice hierarchy
      (chapters, sub-chapters, etc.).::

        - [Title of the Chapter](relative/path/to/markdown.md)

      You can either use - or * to indicate a numbered chapter, the parser
      doesn't care but you'll probably want to stay consistent.

    - **Suffix Chapter:** After the numbered chapters you can add a couple of
      non-numbered chapters. They are the same as prefix chapters but come after
      the numbered chapters instead of before.

    All other elements are unsupported and will be ignored at best, or result in
    an error at worst.

    Summary Example
    ---------------

    ::

      # Table of Contents

      [Introduction](./indtroduction.md)

      [Preface](./preface.md)

      - [Chapter 1](./chapter1.md)
      - [Chapter 2](./chapter2.md)
      - [Chapter 3](./chapter3.md)
      - [Chapter 4](./chapter4.md)

      [Appendix A](./appendix-a.md)

      [Appendix B](./appendix-b.md)
    """
    if not book:
        raise InvalidBookError('Unable to parse summary for unknown book.')

    summary = None

    app = book.app
    summary_file = parse_structure_file(book, 'summary')
    if not summary_file:
        app.logger.warn('no summary file in this book')
        summary = Summary()
    else:
        app.logger.debug('summary file found at: {}'.format(summary_file))
        with open(summary_file) as f:
            summary_content = f.read()
            if not summary_content:
                summary = Summary()
            else:
                parser = SummaryParser(app, summary_content, book=book)
                summary = parser.parse()

    # Insert README as first entry if not in SUMMARY.md
    # var readmeArticle = summary.getByPath(readmeFile.getPath());

    # if (readmeFile.exists() && !readmeArticle) {
    #     summary = SummaryModifier.unshiftArticle(summary, {
    #         title: 'Introduction',
    #         ref: readmeFile.getPath()
    #     });
    # }
    book.summary = summary
    return summary
Exemple #8
0
def test_parse_sections_with_no_sections(app):
    parser = SummaryParser(app, '')
    actual = parser.parse_sections()
    assert actual == []
Exemple #9
0
def test_parse_initial_title(app, source, expected):
    parser = SummaryParser(app, source)
    actual = parser.parse_title()

    assert actual == expected
Exemple #10
0
def test_create_part(app, source, expected):
    parser = SummaryParser(app, source)
    element = parser.stream.parse_tree.find('.//a')

    actual = parser.create_part(element)
    assert actual == expected