def run(self, parent, blocks): sibling = self.lastChild(parent) block = blocks.pop(0) theRest = '' if (sibling is not None and sibling.tag == "pre" and len(sibling) and sibling[0].tag == "code"): # The previous block was a code block. As blank lines do not start # new code blocks, append this block to the previous, adding back # linebreaks removed from the split into a list. code = sibling[0] block, theRest = self.detab(block) code.text = md_util.AtomicString( '%s\n%s\n' % (code.text, md_util.code_escape(block.rstrip()))) else: # This is a new codeblock. Create the elements and insert text. code_id = 'code-%s' % uuid(block) pre = md_util.etree.SubElement(parent, 'pre') code = md_util.etree.SubElement(pre, 'code') a = md_util.etree.XML(COPY_WRAP % ('#%s' % code_id)) pre.append(a) block, theRest = self.detab(block) code.attrib = {'id': code_id, 'data-lang': 'TEXT'} code.text = md_util.AtomicString( '%s\n' % md_util.code_escape(block.rstrip())) if theRest: # This block contained unindented line(s) after the first indented # line. Insert these lines as the first block of the master blocks # list for future processing. blocks.insert(0, theRest)
def shorten_issue(self, provider, link, class_name, label, user_repo, value, link_type): """Shorten issue/pull link.""" # user/repo#(issue|pull) if link_type == self.ISSUE: issue_type = self.repo_labels.get('issue', 'Issue') icon = '#' if 'magiclink-issue' not in class_name: class_name.append('magiclink-issue') elif link_type == self.PULL: issue_type = self.repo_labels.get('pull', 'Pull Request') icon = '#' if self.normalize else '!' if 'magiclink-pull' not in class_name: class_name.append('magiclink-pull') elif provider == 'github' and link_type == self.DISCUSS: issue_type = self.repo_labels.get('discuss', 'Discussion') icon = '#' if self.normalize else '?' if 'magiclink-discussion' not in class_name: class_name.append('magiclink-discussion') if self.my_repo: link.text = md_util.AtomicString("{}{}".format(icon, value)) elif self.my_user: link.text = md_util.AtomicString("{}{}{}".format( user_repo.split('/')[1], icon, value)) else: link.text = md_util.AtomicString("{}{}{}".format( user_repo, icon, value)) link.set( 'title', '{} {}: {} #{}'.format(label, issue_type, user_repo.rstrip('/'), value))
def handleMatch(self, m, data): """Handle kbd pattern matches.""" if m.group(1): return m.group('escapes').replace(DOUBLE_BSLASH, ESCAPED_BSLASH), m.start(0), m.end(0) content = [self.process_key(key) for key in UNESCAPED_PLUS.split(m.group(2)) if key != '+'] if None in content: return None, None, None el = etree.Element( ('kbd' if self.strict else 'span'), ({'class': ' '.join(self.classes)} if self.classes else {}) ) last = None for item_class, item_name in content: classes = [] if item_class: classes.append('key-' + item_class) if last is not None and self.ksep: span = etree.SubElement(el, 'span') span.text = md_util.AtomicString(self.ksep) attr = {} if classes: attr['class'] = ' '.join(classes) kbd = etree.SubElement(el, 'kbd', attr) kbd.text = md_util.AtomicString(item_name) last = kbd return el, m.start(0), m.end(0)
def mathjax_output(self, parent, math): """Default MathJax output.""" if self.preview: grandparent = parent parent = etree.SubElement(grandparent, 'div') preview = etree.SubElement(parent, 'div', {'class': 'MathJax_Preview'}) preview.text = md_util.AtomicString(math) el = etree.SubElement(parent, 'script', {'type': 'math/tex; mode=display'}) el.text = md_util.AtomicString(math)
def shorten(self, link, provider, my_repo, my_user, link_type, user_repo, value, url, hash_size): """Shorten url.""" label = PROVIDER_INFO[provider]['provider'] prov_class = 'magiclink-%s' % provider class_attr = link.get('class', '') class_name = class_attr.split(' ') if class_attr else [] if 'magiclink' not in class_name: class_name.append('magiclink') if prov_class not in class_name: class_name.append(prov_class) if link_type is self.COMMIT: # user/repo@hash repo_label = self.repo_labels.get('commit', 'Commit') if my_repo: text = value[0:hash_size] elif my_user: text = '%s@%s' % (user_repo.split('/')[1], value[0:hash_size]) else: text = '%s@%s' % (user_repo, value[0:hash_size]) link.text = md_util.AtomicString(text) if 'magiclink-commit' not in class_name: class_name.append('magiclink-commit') link.set( 'title', '%s %s: %s@%s' % (label, repo_label, user_repo.rstrip('/'), value[0:hash_size])) else: # user/repo#(issue|pull) if link_type == self.ISSUE: issue_type = self.repo_labels.get('issue', 'Issue') separator = '#' if 'magiclink-issue' not in class_name: class_name.append('magiclink-issue') else: issue_type = self.repo_labels.get('pull', 'Pull Request') separator = '!' if 'magiclink-pull' not in class_name: class_name.append('magiclink-pull') if my_repo: text = separator + value elif my_user: text = user_repo.split('/')[1] + separator + value else: text = user_repo + separator + value link.text = md_util.AtomicString(text) link.set( 'title', '%s %s: %s%s%s' % (label, issue_type, user_repo.rstrip('/'), separator, value)) link.set('class', ' '.join(class_name))
def handleMatch(self, m): """Return link optionally without protocol.""" shorten = self.config.get('repo_url_shortener', False) el = md_util.etree.Element("a") el.set('href', self.unescape(m.group(2))) el.text = md_util.AtomicString(m.group(2)) if self.config['hide_protocol']: el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:]) if shorten: el.attrib['magiclink'] = '1' return el
def handleMatch(self, m, data): """Return link optionally without protocol.""" el = etree.Element("a") el.set('href', self.unescape(m.group(1))) el.text = md_util.AtomicString(m.group(1)) if self.config['hide_protocol']: el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:]) if self.config.get('repo_url_shortener', False): el.set('magiclink', str(MAGIC_AUTO_LINK)) return el, m.start(0), m.end(0)
def _block_mathjax_format(math, preview=False): """Block math formatter.""" if preview: el = etree.Element('span') pre = etree.SubElement(el, 'span', {'class': 'MathJax_Preview'}) pre.text = md_util.AtomicString(math) script = etree.SubElement(el, 'script', {'type': 'math/tex; mode=display'}) script.text = md_util.AtomicString(math) else: el = etree.Element('script', {'type': 'math/tex; mode=display'}) el.text = md_util.AtomicString(math) return el
def mathjax_output(self, math): """Default MathJax output.""" if self.preview: el = md_util.etree.Element('span') preview = md_util.etree.SubElement(el, 'span', {'class': 'MathJax_Preview'}) preview.text = md_util.AtomicString(math) script = md_util.etree.SubElement(el, 'script', {'type': 'math/tex'}) script.text = md_util.AtomicString(math) else: el = md_util.etree.Element('script', {'type': 'math/tex'}) el.text = md_util.AtomicString(math) return el
def _inline_mathjax_format(math, preview=False): """Inline math formatter.""" if preview: el = ETree.Element('span') pre = ETree.SubElement(el, 'span', {'class': 'MathJax_Preview'}) pre.text = md_util.AtomicString(math) script = ETree.SubElement(el, 'script', {'type': 'math/tex'}) script.text = md_util.AtomicString(math) else: el = ETree.Element('script', {'type': 'math/tex'}) el.text = md_util.AtomicString(math) return el
def run(self, parent, blocks): sibling = self.lastChild(parent) block = blocks.pop(0) theRest = '' if sibling and sibling.tag == 'pre' and len(sibling) and sibling[0].tag == 'code': code = sibling[0] block, theRest = self.detab(block) code.text = util.AtomicString('%s\n%s\n' % (code.text, block.rstrip())) else: pre = util.etree.SubElement(parent, 'pre') code = util.etree.SubElement(pre, 'code') block, theRest = self.detab(block) code.text = util.AtomicString('%s\n' % block.rstrip()) if theRest: blocks.insert(0, theRest)
def _inline_mathjax_format(math, language='math', class_name='arithmatex', md=None, tag='span', preview=False): """Inline math formatter.""" el = etree.Element(tag, {'class': 'arithmatex'}) if preview: pre = etree.SubElement(el, 'span', {'class': 'MathJax_Preview'}) pre.text = md_util.AtomicString(math) script = etree.SubElement(el, 'script', {'type': 'math/tex'}) script.text = md_util.AtomicString(math) return el
def handleMatch(self, m): print(m.groups()) url = m.group(3) if url.startswith('<'): url = url[1:-1] text = url is_url = re.match(MAIL_RE, url) if not is_url: url = sanitize_url(url) parts = urlparse(url) # If no protocol (and not explicit relative link), add one if parts[0] == "": if is_url: url = 'mailto:' + url elif not url.startswith("#") and not url.startswith("/"): url = 'http://' + url el = util.etree.Element("a") el.set('href', url) el.text = util.AtomicString(text) return el
def shorten_issue(self, link, class_name, label, user_repo, value, link_type): """Shorten issue/pull link.""" # user/repo#(issue|pull) if link_type == self.ISSUE: issue_type = self.repo_labels.get('issue', 'Issue') separator = '#' if 'magiclink-issue' not in class_name: class_name.append('magiclink-issue') else: issue_type = self.repo_labels.get('pull', 'Pull Request') separator = '!' if 'magiclink-pull' not in class_name: class_name.append('magiclink-pull') if self.my_repo: text = separator + value elif self.my_user: text = user_repo.split('/')[1] + separator + value else: text = user_repo + separator + value link.text = md_util.AtomicString(text) link.set( 'title', '%s %s: %s%s%s' % (label, issue_type, user_repo.rstrip('/'), separator, value))
def process_compare(self, el, provider, user, repo, commit1, commit2): """Process commit.""" hash_ref1 = commit1[0:PROVIDER_INFO[provider]['hash_size']] hash_ref2 = commit2[0:PROVIDER_INFO[provider]['hash_size']] if self.my_repo: text = '%s...%s' % (hash_ref1, hash_ref2) elif self.my_user: text = '%s@%s...%s' % (repo, hash_ref1, hash_ref2) else: text = '%s/%s@%s...%s' % (user, repo, hash_ref1, hash_ref2) el.set('href', PROVIDER_INFO[provider]['compare'] % (user, repo, commit1, commit2)) el.text = md_util.AtomicString(text) el.set('class', 'magiclink magiclink-%s magiclink-compare' % provider) el.set( 'title', '%s %s: %s/%s@%s...%s' % ( PROVIDER_INFO[provider]['provider'], self.labels.get('compare', 'Compare'), user, repo, hash_ref1, hash_ref2 ) )
def handleMatch(self, m, data): """Handle email link patterns.""" text = m.group('mention')[1:] parts = text.split(':') if len(parts) > 1: provider = parts[0] user = parts[1] else: provider = self.provider user = parts[0] repo = m.group('mention_repo') el = etree.Element("a") el.set('href', '{}/{}/{}'.format(PROVIDER_INFO[provider]['url'], user, repo)) el.set( 'title', "{} {}: {}/{}".format(PROVIDER_INFO[provider]['provider'], self.labels.get('repository', 'Repository'), user, repo)) el.set('class', 'magiclink magiclink-{} magiclink-repository'.format(provider)) el.text = md_util.AtomicString('{}/{}'.format(user, repo)) return el, m.start(0), m.end(0)
def handleMatch(self, m, data): if m.group(3): el = etree.Element(self.tag) el.text = util.AtomicString(util.code_escape(m.group(3).strip())) return el, m.start(0), m.end(0) else: return m.group(1).replace('\\\\', self.ESCAPED_BSLASH), m.start(0), m.end(0)
def process_commit(self, el, provider, user, repo, commit): """Process commit.""" my_repo = not repo my_user = not user if my_repo: repo = self.repo if my_user: user = self.user prov = provider if provider else self.provider if my_repo: text = commit[0:PROVIDER_INFO[prov]['hash_size']] elif my_user: text = '%s@%s' % (repo, commit[0:PROVIDER_INFO[prov]['hash_size']]) else: text = '%s/%s@%s' % (user, repo, commit[0:PROVIDER_INFO[prov]['hash_size']]) el.set('href', PROVIDER_INFO[prov]['commit'] % (user, repo, commit)) el.text = md_util.AtomicString(text) el.set('class', 'magiclink magiclink-%s magiclink-commit' % prov) el.set( 'title', '%s %s: %s/%s@%s' % (PROVIDER_INFO[prov]['provider'], self.labels.get('commit', 'Commit'), user, repo, commit[0:PROVIDER_INFO[prov]['hash_size']]))
def process_issues(self, el, provider, user, repo, issue): """Process issues.""" issue_type = issue[:1] issue_value = issue[1:] if issue_type == '#': issue_link = PROVIDER_INFO[provider]['issue'] issue_label = self.labels.get('issue', 'Issue') class_name = 'magiclink-issue' else: issue_link = PROVIDER_INFO[provider]['pull'] issue_label = self.labels.get('pull', 'Pull Request') class_name = 'magiclink-pull' if self.my_repo: text = '%s%s' % (issue_type, issue_value) elif self.my_user: text = '%s%s%s' % (repo, issue_type, issue_value) else: text = '%s/%s%s%s' % (user, repo, issue_type, issue_value) el.set('href', issue_link % (user, repo, issue_value)) el.text = md_util.AtomicString(text) el.set('class', 'magiclink magiclink-%s %s' % (provider, class_name)) el.set( 'title', '%s %s: %s/%s%s%s' % (PROVIDER_INFO[provider]['provider'], issue_label, user, repo, issue_type, issue_value))
def shorten_diff(self, link, class_name, label, user_repo, value, hash_size): """Shorten diff/compare links.""" repo_label = self.repo_labels.get('compare', 'Compare') if self.my_repo: text = '{}...{}'.format(value[0][0:hash_size], value[1][0:hash_size]) elif self.my_user: text = '{}@{}...{}'.format( user_repo.split('/')[1], value[0][0:hash_size], value[1][0:hash_size]) else: text = '{}@{}...{}'.format(user_repo, value[0][0:hash_size], value[1][0:hash_size]) link.text = md_util.AtomicString(text) if 'magiclink-compare' not in class_name: class_name.append('magiclink-compare') link.set( 'title', '{} {}: {}@{}...{}'.format(label, repo_label, user_repo.rstrip('/'), value[0][0:hash_size], value[1][0:hash_size]))
def handleMatch(self, m, data): """Handle URL matches.""" el = md_util.etree.Element("a") el.text = md_util.AtomicString(m.group('link')) if m.group("www"): href = "http://%s" % m.group('link') else: href = m.group('link') if self.config['hide_protocol']: el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:]) el.set("href", self.unescape(href.strip())) if self.config.get('repo_url_shortener', False): el.set('magiclink', md_util.text_type(MAGIC_LINK)) return el, m.start(0), m.end(0)
def run(self, parent, blocks): block = blocks.pop(0) m = self.RE.match(block) if m: blocks.insert(0, block[m.end():]) sibling = self.lastChild(parent) if sibling and sibling.tag == 'pre' and sibling[0] and sibling[0].tag == 'code': sibling[0].text = util.AtomicString('%s/n/n/n' % sibling[0].text)
def handleMatch(self, m, data): """Handle email link patterns.""" el = md_util.etree.Element("a") email = self.unescape(m.group('mail')) href = "mailto:%s" % email el.text = md_util.AtomicString(''.join([self.email_encode(ord(c)) for c in email])) el.set("href", ''.join([md_util.AMP_SUBSTITUTE + '#%d;' % ord(c) for c in href])) return el, m.start(0), m.end(0)
def handleMatch(self, m): """Handle URL matches.""" shorten = self.config.get('repo_url_shortener', False) el = md_util.etree.Element("a") el.text = md_util.AtomicString(m.group(2)) if m.group("www"): href = "http://%s" % m.group(2) else: href = m.group(2) if self.config['hide_protocol']: el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:]) if shorten: el.set('magiclink', '1') el.set("href", self.sanitize_url(self.unescape(href.strip()))) return el
def run(self, parent, blocks): """Find and handle block content.""" blocks.pop(0) math = self.match.group('math') if not math: math = self.match.group('math2') if not math: math = self.match.group('math3') if self.script: el = md_util.etree.SubElement(parent, 'script', {'type': 'math/tex; mode=display'}) el.text = md_util.AtomicString(math) else: el = md_util.etree.SubElement(parent, 'span') el.text = md_util.AtomicString(self.wrap % math) return True
def inline_generic_format(math, language='math', class_name='arithmatex', md=None, wrap='\\(%s\\)'): """Inline generic formatter.""" el = md_util.etree.Element('span', {'class': class_name}) el.text = md_util.AtomicString(wrap % math) return el
def shorten_user(self, link, class_name, label, user_repo): """Shorten user link.""" link.text = md_util.AtomicString('@' + user_repo) if 'magiclink-mention' not in class_name: class_name.append('magiclink-mention') link.set( 'title', "%s %s: %s" % (label, self.repo_labels.get('metion', 'User'), user_repo))
def _inline_generic_format(math, language='math', class_name='arithmatex', md=None, wrap='\\({}\\)', tag='span'): """Inline generic formatter.""" el = etree.Element(tag, {'class': class_name}) el.text = md_util.AtomicString(wrap.format(math)) return el
def process_issues(self, el, provider, user, repo, issue): """Process issues.""" issue_type = issue[:1] issue_value = issue[1:] if issue_type == '#': issue_link = PROVIDER_INFO[provider]['issue'] issue_label = self.labels.get('issue', 'Issue') class_name = 'magiclink-issue' icon = issue_type elif issue_type == '!': issue_link = PROVIDER_INFO[provider]['pull'] issue_label = self.labels.get('pull', 'Pull Request') class_name = 'magiclink-pull' icon = '#' if self.normalize else issue_type elif provider == "github" and issue_type == '?': issue_link = PROVIDER_INFO[provider]['discuss'] issue_label = self.labels.get('discuss', 'Discussion') class_name = 'magiclink-discussion' icon = '#' if self.normalize else issue_type else: return False if self.my_repo: el.text = md_util.AtomicString('{}{}'.format(icon, issue_value)) elif self.my_user: el.text = md_util.AtomicString('{}{}{}'.format( repo, icon, issue_value)) else: el.text = md_util.AtomicString('{}/{}{}{}'.format( user, repo, icon, issue_value)) el.set('href', issue_link.format(user, repo, issue_value)) el.set('class', 'magiclink magiclink-{} {}'.format(provider, class_name)) el.set( 'title', '{} {}: {}/{} #{}'.format(PROVIDER_INFO[provider]['provider'], issue_label, user, repo, issue_value)) return True
def handleMatch(self, m): """Handle notations and switch them to something that will be more detectable in HTML.""" # Handle escapes escapes = m.group(2) if not escapes: escapes = m.group(5) if escapes: return escapes.replace('\\\\', self.ESCAPED_BSLASH) # Handle Tex math = m.group(4) if not math: math = m.group(7) if self.script: el = md_util.etree.Element('script', {'type': 'math/tex'}) el.text = md_util.AtomicString(math) else: el = md_util.etree.Element('span') el.text = md_util.AtomicString(self.wrap % math) return el