예제 #1
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)

        lines = []
        underline = None
        try:
            for line in reader:
                lines.append(line.lstrip())
                if self.pattern.match(reader.next_line):
                    underline = reader.readline()
                    break
                elif self.parser.is_interrupted(reader):
                    break
        except IOError:
            pass

        if underline is None:
            # underline of heading not found. backtracking.
            reader.step(-len(lines))
            return False
        else:
            text = ''.join(lines).strip()
            depth = self.section_level[underline.strip()[0]]
            section = nodes.section(depth=depth)
            section += nodes.title(text, text)
            location.set_source_info(section[0])
            get_root_document(document).note_implicit_target(section)

            document += section
            return True
예제 #2
0
    def read_table_header(self,
                          reader: LineReader) -> Tuple[nodes.row, List[str]]:
        try:
            location = reader.get_source_and_line(incr=1)
            header = self.parse_row(reader.readline())
            if self.parser.is_interrupted(reader):
                raise IOError
            elif not self.delimiter_pattern.match(reader.next_line):
                raise IOError

            delimiters = self.parse_row(reader.next_line)
            aligns = [align(d) for d in delimiters]
            if len(header) != len(delimiters):
                raise IOError
        except IOError:
            reader.step(-1)
            return None, None

        reader.step()

        row = nodes.row()
        for i, cell in enumerate(header):
            text = cell.strip()
            entry = nodes.entry()
            location.set_source_info(entry)
            if text:
                entry += nodes.paragraph(text, text)
            if aligns[i]:
                entry['align'] = aligns[i]
            row += entry
        return row, aligns
예제 #3
0
    def read_table_body(self, reader: LineReader,
                        aligns: List[str]) -> List[nodes.row]:
        try:
            rows = []
            while True:
                if self.parser.is_interrupted(reader):
                    break
                else:
                    row = self.parse_row(reader.readline())
                    if len(row) == 1 and row[0] == '':
                        reader.step(-1)
                        break

                    entries = []
                    for i, align in enumerate(aligns):
                        try:
                            text = row[i].strip()
                        except IndexError:
                            text = ''

                        entry = nodes.entry()
                        if text:
                            entry += nodes.paragraph(text, text)
                        entry.source, entry.line = reader.get_source_and_line()
                        if align:
                            entry['align'] = align
                        entries.append(entry)
                    rows.append(nodes.row('', *entries))
        except IOError:
            pass

        return rows
예제 #4
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)

        code = ''.join(IndentedCodeBlockReader(reader))
        code = re.sub('^\n+', '', code)  # strip blank lines
        code = re.sub('\n+$', '\n', code)  # strip blank lines
        document += nodes.literal_block(code, code, classes=['code'])
        location.set_source_info(document[-1])
        return True
예제 #5
0
def test_LineReader():
    reader = LineReader(text.splitlines(), source='dummy.md')
    assert reader.eof() is False
    assert reader.get_source_and_line() == ('dummy.md', 0)

    # read first line
    assert reader.readline() == "Lorem ipsum dolor sit amet, "
    assert reader.current_line == "Lorem ipsum dolor sit amet, "
    assert reader.fetch() == "Lorem ipsum dolor sit amet, "
    assert reader.fetch(1) == "consectetur adipiscing elit, "
    assert reader.next_line == "consectetur adipiscing elit, "
    assert reader.fetch(2) == ""
    assert reader.get_source_and_line() == ('dummy.md', 1)

    # read second line
    assert reader.readline() == "consectetur adipiscing elit, "
    assert reader.current_line == "consectetur adipiscing elit, "
    assert reader.fetch() == "consectetur adipiscing elit, "
    assert reader.fetch(1) == ""
    assert reader.get_source_and_line() == ('dummy.md', 2)

    # rollback a line
    reader.step(-1)
    assert reader.current_line == "Lorem ipsum dolor sit amet, "
    assert reader.get_source_and_line() == ('dummy.md', 1)

    # step a line again
    reader.step()
    assert reader.current_line == "consectetur adipiscing elit, "

    # read until the end
    assert reader.readline() == ""
    assert reader.readline() == "    sed do eiusmod tempor incididunt "
    assert reader.readline() == "    ut labore et dolore magna aliqua."
    assert reader.readline() == ""
    assert reader.readline() == "Ut enim ad minim veniam, quis nostrud"
    assert reader.eof() is True

    try:
        assert reader.readline()
        assert False, "reader does not raise IOError on EOF"
    except IOError:
        pass
예제 #6
0
    def run(self, reader: LineReader, document: Element) -> bool:
        marker, title = self.pattern.match(reader.readline()).groups()
        title = self.trailing_hashes.sub('', title).strip()
        title_node = nodes.title(title, title)
        title_node.source, title_node.line = reader.get_source_and_line()
        section = nodes.section('', title_node, depth=len(marker))
        get_root_document(document).note_implicit_target(section)

        document += section
        return True
예제 #7
0
    def run(self, reader: LineReader, document: Element) -> bool:
        line = reader.readline()
        klass = line.strip().strip('=').strip()
        container = nodes.container(classes=[klass])
        container.source, container.line = reader.get_source_and_line()
        document += container

        walled_block_reader = WalledBlockReader(reader)
        self.parser.parse(walled_block_reader, container)
        walled_block_reader.consume_endmarker()
        return True
예제 #8
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)
        content = ''
        for line in reader:
            content += line
            if self.closing_pattern.search(line):
                break

        content = re.sub('\n+$', '\n', content)  # strip multiple CRs on tail
        document += nodes.raw(content, content, format='html')
        location.set_source_info(document[-1])
        return True
예제 #9
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)
        reader = LazyLineReader(reader)

        text = ''
        for line in reader:
            text += line.lstrip()
            if self.parser.is_interrupted(reader):
                break

        node = nodes.paragraph(text.strip(), text.strip())
        location.set_source_info(node)
        document += node

        return True
예제 #10
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)

        indent, marker, info = self.pattern.match(reader.readline()).groups()
        code = ''.join(FencedCodeBlockReader(reader, len(indent), marker))

        literal_block = nodes.literal_block(code, code, classes=['code'])
        location.set_source_info(literal_block)
        if info.strip():
            language = unescape(entitytrans._unescape(info.split()[0].strip()))
            literal_block['language'] = language
            literal_block['classes'].append('language-%s' %
                                            language.split()[0])
        document += literal_block

        return True
예제 #11
0
    def run(self, reader: LineReader, document: Element) -> bool:
        location = reader.get_source_and_line(incr=1)
        header_row, aligns = self.read_table_header(reader)
        if header_row is None:
            return False
        body_rows = self.read_table_body(reader, aligns)

        colspecs = [
            nodes.colspec('', colwidth=int(100 / len(aligns))) for _ in aligns
        ]
        thead = nodes.thead('', header_row)
        tgroup = nodes.tgroup('', *colspecs, thead, cols=len(aligns))
        if body_rows:
            tgroup += nodes.tbody('', *body_rows)
        table = nodes.table('', tgroup)
        location.set_source_info(table)
        document += table
        return True
예제 #12
0
    def run(self, reader: LineReader, document: Element) -> bool:
        if reader.lineno != 0:
            return False

        reader.readline()
        field_list = nodes.field_list()
        field_list.source, field_list.line = reader.get_source_and_line()
        for line in reader:
            if self.pattern.match(line):
                break
            elif ':' in line:
                key, value = line.split(':')
                field_name = nodes.field_name('', key.strip())
                field_body = nodes.field_body('', nodes.paragraph('', value.strip()))
                field_list += nodes.field('', field_name, field_body)
            else:
                # Not a frontmatter, rollback
                lines = len(field_list) + 2
                reader.step(-lines)
                return False

        document += field_list
        return True
예제 #13
0
 def run(self, reader: LineReader, document: Element) -> bool:
     quote = nodes.block_quote()
     quote.source, quote.line = reader.get_source_and_line(incr=1)
     document += quote
     self.parser.parse(BlockQuoteReader(reader), quote)
     return True