예제 #1
0
    def parseBareLinkDestination(self, reader: TextReader,
                                 document: Element) -> str:
        assert reader.consume(re.compile(r'[ \n]*'))

        if reader.remain == '':  # must be empty line!
            return None

        parens = 0
        start = reader.position
        while reader.remain:
            c = reader.remain[0]
            if c in (' ', '\n'):
                break
            elif c == '(':
                parens += 1
            elif c == ')':
                parens -= 1
                if parens < 0:
                    break
            elif escaped_chars_pattern.match(reader.remain):
                reader.step()  # one more step for escaping

            reader.step()

        end = reader.position
        return self.normalize_link_destination(reader[start:end])
예제 #2
0
 def run(self, reader: TextReader, document: Element) -> bool:
     if not isinstance(document, nodes.paragraph):
         return False
     else:
         reader.consume(self.pattern)
         document += addnodes.linebreak()
         return True
예제 #3
0
 def run(self, reader: TextReader, document: Element) -> bool:
     reader.step(1)
     document += addnodes.bracket(marker="]",
                                  can_open=False,
                                  position=reader.position - 1)
     self.process_link_or_image(reader, document)
     return True
예제 #4
0
 def run(self, reader: TextReader, document: Element) -> bool:
     if not isinstance(document, nodes.paragraph):
         return False
     else:
         reader.consume(self.pattern)  # skip over a space at tail
         document += addnodes.SparseText(reader.subject, reader.position,
                                         reader.position)
         return True
예제 #5
0
    def parse_link_destination(self, reader: TextReader,
                               document: Element) -> Tuple[str, str]:
        reader.step()
        destination = LinkDestinationParser().parse(reader, document)
        title = LinkTitleParser().parse(reader, document)
        assert reader.consume(re.compile(r'\s*\)'))

        return destination, title
예제 #6
0
 def wrapper(self, reader: TextReader, document: Element, **kwargs) -> bool:
     new_reader = TextReader(reader.subject, reader.position)
     try:
         ret = func(self, new_reader, document, **kwargs)
         if ret:
             reader.position = new_reader.position
         return ret
     except UnmatchedTokenError as exc:
         text = exc.args[0]
         document += Text(text)
         reader.step(len(text))
         return True
     except Exception:
         return False
예제 #7
0
 def run(self, reader: TextReader, document: Element) -> bool:
     marker = reader.consume(self.pattern).group(0)
     document += addnodes.bracket(marker=marker,
                                  can_open=True,
                                  active=True,
                                  position=reader.position)
     return True
예제 #8
0
 def parse(self, reader: TextReader, document: Element) -> str:
     if re.match(r'^\s*<', reader.remain):
         matched = reader.consume(self.pattern)
         if not matched:
             return ''
         else:
             return self.normalize_link_destination(matched.group(1))
     else:
         return self.parseBareLinkDestination(reader, document)
예제 #9
0
    def parse_link_label(self,
                         reader: TextReader,
                         document: Element,
                         opener: Element = None,
                         closer: Element = None) -> Tuple[object, str]:  # NOQA
        reader.step()
        refname = LinkLabelParser().parse(reader, document)
        if refname == '':
            # collapsed reference link
            #     [...][]
            refname = reader[opener['position']:closer['position']]

        target = self.lookup_target(document, refname)
        if target:
            destination = target.get('refuri')
            title = target.get('title')
            return destination, title
        else:
            return LABEL_NOT_MATCHED, None
예제 #10
0
def test_TextReader():
    text = "hello world"
    reader = TextReader(text)
    assert reader.remain == 'hello world'

    reader.step()
    assert reader.remain == 'ello world'

    matched = reader.consume(re.compile(r'\w+'))
    assert matched
    assert matched.group(0) == 'ello'
    assert reader.remain == ' world'

    matched = reader.consume(re.compile(r'\w+'))
    assert matched is None

    reader.step(6)
    assert reader.remain == ''

    reader.step(1)
    assert reader.remain == ''
예제 #11
0
    def parse(self, document: TextElement) -> TextElement:
        """Parses a text and build TextElement."""
        if len(document) == 0:
            return document

        reader = TextReader(cast(Text, document.pop()))
        while reader.remain:
            for _, processor in self.processors:
                if processor.match(reader):
                    if processor.run(reader, document) is True:
                        break
            else:
                if len(document) > 0 and isinstance(document[-1], SparseText):
                    tail = document[-1]
                    tail.spread(end=1)
                else:
                    tail = SparseText(reader.subject, reader.position,
                                      reader.position + 1)
                    document += tail

                if reader.remain[0] == '\\':  # escaped
                    tail.spread(end=1)
                    reader.step(2)
                else:
                    reader.step(1)

        return document
예제 #12
0
    def run(self, reader: TextReader, document: Element) -> bool:
        brackets = list(n for n in document.children if isinstance(n, bracket))
        openers = list(d for d in brackets if d['can_open'])
        if openers == []:
            return False

        matched = reader.consume(self.pattern)
        rubytext = unescape(matched.group(0)[2:-1])
        ruby = addnodes.ruby(rubytext=rubytext)
        document += ruby

        # transplant ruby base text to ruby node
        transplant_nodes(document, ruby, start=openers[-1], end=ruby)
        document.remove(openers[-1])
        return True
예제 #13
0
    def run(self, reader: TextReader, document: Element) -> bool:
        if reader.position == 0:
            before_is_whitespace: Any = True
            before_is_punctuation: Any = False
        else:
            before = reader[reader.position - 1]
            before_is_whitespace = self.whitespaces.match(before)
            before_is_punctuation = is_punctuation(before)

        marker = reader.consume(self.pattern).group(0)

        if reader.remain:
            after = reader.remain[0]
            after_is_whitespace: Any = self.whitespaces.match(after)
            after_is_punctuation: Any = is_punctuation(after)
        else:
            after_is_whitespace = True
            after_is_punctuation = False

        left_flanking = (not after_is_whitespace
                         and (not after_is_punctuation or before_is_whitespace
                              or before_is_punctuation))
        right_flanking = (not before_is_whitespace
                          and (not before_is_punctuation or after_is_whitespace
                               or after_is_punctuation))

        if marker[0] == '_':
            can_open = (left_flanking
                        and (not right_flanking or before_is_punctuation))
            can_close = (right_flanking
                         and (not left_flanking or after_is_punctuation))
        else:
            can_open = left_flanking
            can_close = right_flanking

        document += addnodes.emphasis(marker=marker,
                                      can_open=can_open,
                                      can_close=can_close,
                                      orig_length=len(marker),
                                      curr_length=len(marker),
                                      interior=can_open and can_close)
        return True
예제 #14
0
    def run(self, reader: TextReader, document: Element) -> bool:
        marker = reader.consume(self.pattern).group(0)

        pattern = re.compile(marker + r"([^`]|$)")
        text = addnodes.SparseText(reader.remain, 0, 0)
        while reader.remain:
            if pattern.match(reader.remain):
                code = re.sub(r'[\r\n]', ' ', str(text), re.S)
                code = self.trim_single_space(code)
                document += nodes.literal(code, code)
                reader.step(len(marker))
                return True
            elif reader.remain[0] == '`':
                while reader.remain and reader.remain[0] == '`':
                    text.spread(end=1)
                    reader.step()
            else:
                text.spread(end=1)
                reader.step()
        else:
            raise UnmatchedTokenError(marker)
예제 #15
0
 def run(self, reader: TextReader, document: Element) -> bool:
     reader.consume(self.pattern)
     document += addnodes.strikethrough()
     return True
예제 #16
0
 def run(self, reader: TextReader, document: Element) -> bool:
     uri = reader.consume(self.pattern).group(1)
     document += nodes.reference(uri,
                                 uri,
                                 refuri='mailto:' + normalize_uri(uri))
     return True
예제 #17
0
 def run(self, reader: TextReader, document: Element) -> bool:
     html = reader.consume(self.pattern).group(0)
     document += nodes.raw(html, html, format='html')
     return True
예제 #18
0
 def run(self, reader: TextReader, document: Element) -> bool:
     document += addnodes.SparseText(reader.subject, reader.position + 1,
                                     reader.position + 2)
     reader.step(2)
     return True
예제 #19
0
 def parse(self, reader: TextReader, document: Element) -> str:
     matched = reader.consume(self.pattern)
     if matched:
         return matched.group(0)[:-1]
     else:
         return None
예제 #20
0
 def parse(self, reader: TextReader, document: Element) -> str:
     matched = reader.consume(self.pattern)
     if matched:
         return unescape(entitytrans._unescape(matched.group(1)[1:-1]))
     else:
         return None
예제 #21
0
 def run(self, reader: TextReader, document: Element) -> bool:
     text = reader.consume(self.pattern).group(0)
     document += Text(entitytrans._unescape(text))
     return True