def apply(self): source, boundary, end = self.source, self.boundary, self.end if self.start is not None: res_list = [] start = self.start if boundary != start: res_list.append(source[boundary : start]) url = source[start : end] if not self.has_text: # strip pieces that may not belong to URL while True: last_of_url = url[-1] if last_of_url == ")" and "(" not in url or last_of_url in ".,;:?!\"'": # last ")" is not a part of URL unless there's an "(" earlier in it; # common punctuation is usually not a part of URL end -= 1 url = source[start : end] else: break if self.has_text: after_end = end + 1 # including the space # cut out the link text maybe_quote = source[after_end : after_end+1] if maybe_quote == '"': text_frags, start = QuoteWrapper(source, after_end).apply() else: # skip to next space hit = self.SPACE_RE.search(source, after_end+1) if hit: start = hit.start() else: start = len(source) # had no space till EOL text_frags = applyQueue(source[after_end : start]) else: text_frags = [url] start = end proto_pos = url.find("://") if proto_pos > 0: proto = self.PROTO_CLASS_MAP.get(url[:proto_pos], self.PROTO_CLASS_MAP.get("*", None)) else: proto = None if any(bad_char in url for bad_char in '<>"'): # being defensive url = html_escape(url, True) res_list.extend(('<a href="', url, '"')) if proto: res_list.extend((' class="', proto, '"')) res_list.append('>') res_list.extend(text_frags) res_list.append("</a>") else: # no start start = boundary res_list = [] return (res_list, start)
def apply(self): "Apply formatter; returns a tuple (list of fragments, next position)." source, boundary = self.source, self.boundary start = self.start if start is not None: res_list = [] if boundary != start: res_list.append(source[boundary:start]) left_limit = self.end look_for_closing = True while look_for_closing: look_for_closing = False # usually we need only 1 iteration hit = self.END_RE.search(source, left_limit) if hit and hit.start() != self.end: is_escape = False escape_mark = hit.group(1) if escape_mark: i = j = hit.start(1) while i >= 0 and source[i] == "\\": i -= 1 is_escape = (j - i) % 2 == 1 # odd number of \'s ends in a real escape print is_escape if is_escape: # ignore and repeat left_limit = hit.end(1) + 1 look_for_closing = True continue else: if escape_mark: # ...but not our ending sequence not escaped hit_index = 1 else: # just an end marker matched hit_index = 2 # wrap in tag res_list.extend(self.getOpening()) # recursively format the inside of match res_list.extend(applyQueue(source[self.end:hit.start(hit_index)])) res_list.extend(self.getClosing()) start = hit.end(hit_index) else: # start but no end res_list.append(source[self.start:self.end]) # the unmatched marker start = self.end else: # no start start = boundary res_list = [] return (res_list, start)
def testEOL(self): s = ur'abc http://d.e.f' frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u'abc <a href="http://d.e.f">http://d.e.f</a>')
def testNameWithInMarkup(self): s = ur'abc http://d.e.f|"D _E_ F" ghi' frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u'abc <a href="http://d.e.f">D <i>E</i> F</a> ghi')
def testWrappedInMarkup(self): s = ur'abc *http://d.e.f|"DEF"* ghi' frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u'abc <b><a href="http://d.e.f">DEF</a></b> ghi')
def testPWrappedInMarkup(self): s = u"remember: *{{i += 1}}* and only so!" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), ur"remember: <b><code>i += 1</code></b> and only so!")
def testContainingMarkup(self): s = u"code {{int *char*}} done" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), ur"code <code>int *char*</code> done")
def testLiteralBackslashThenEscapeInside(self): s = ur"*a\\\\\*b*" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), ur"<b>a\\*b</b>")
def testLiteralBackslashThenEscapeBegin(self): s = ur"a\\\*b" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), ur"a\*b")
def testLiteralBackslash(self): s = ur"a\\b" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), ur"a\b")
def testMarkedEscapeCombinedInside(self): s = ur"a *b _c\*d_ ef* ghi" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u"a <b>b <i>c*d</i> ef</b> ghi")
def testEscapeCombinedBegin(self): s = ur"a\*bc *def* ghi" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u"a*bc <b>def</b> ghi")
def testNested(self): s = u"abc _*def*_ _-ghi-_ jkl" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u"abc <i><b>def</b></i> <i><s>ghi</s></i> jkl")
def testSimple(self): s = u"abc *def* _ghi_ -jkl- mno" frags = combinator.applyQueue(s) self.assertEqual(u"".join(frags), u"abc <b>def</b> <i>ghi</i> <s>jkl</s> mno")