def render_gfm_to_html(self, markdown_text: str) -> str: """Render given Github Flavored Markdown to HTML.""" try: html = cmarkgfm.github_flavored_markdown_to_html(markdown_text) return html except ValueError as e: raise TrestleError(f'Not a valid Github Flavored markdown: {e}.')
def markdownify(content): html = cmarkgfm.github_flavored_markdown_to_html(content) return bleach.clean( text=html, tags=settings.BLEACH_ALLOWED_TAGS, attributes=settings.BLEACH_ALLOWED_ATTRIBUTES, strip_comments=False, )
def template_data(self): d = super().template_data text = emojize(self.text, use_aliases=True) text = cmarkgfm.github_flavored_markdown_to_html( text, options=cmarkgfmOptions.CMARK_OPT_UNSAFE) d["text"] = text d["button_block"] = "btn-block" if self.button_block else "" d["button_style"] = self.button_style return d
def post(self, request, invitation_id=None): ''' - Takes an invitation - generates an email with a link to the registration form that will redeem that invitation - sends the email - sets the sent_time on the invitation ''' invitation = get_object_or_404(models.Invitation, id=invitation_id) to_name = invitation.recipient_name to_email = invitation.recipient_email event = invitation.registration_type.event invitation_body_text = chevron.render( invitation.registration_type.invitation_email_template, { 'recipient_name': to_name or to_email, 'recipient_email': to_email, 'invitation_code': invitation.invitation_code, 'register_link': register_page_url(request, event.id, invitation) }) invitation_body_html = cmarkgfm.github_flavored_markdown_to_html( invitation_body_text) email_error = None sent = False try: if '@dontsend.com' in to_email: email_error = 'invitation email contains @dontsend.com' logger.error(invitation_body_html) else: msg = EmailMultiAlternatives( invitation.registration_type.invitation_email_subject, invitation_body_text, event. confirmation_email_from, # TODO: figure out what this should be [f'"{to_name}" <{to_email}>' if to_name else to_email]) msg.attach_alternative(invitation_body_html, "text/html") sent = msg.send(fail_silently=False) if not sent: email_error = 'mail not sent' except SMTPException as e: email_error = str(e) if email_error: return Response({"detail": email_error}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) invitation.sent_time = timezone.now() invitation.save() return Response({ 'success': True, })
def render_text(self, text: str) -> str: """ Renders the markdown and emoji shortcodes in :attr:`.text` Returns: str: Text rendered to html code """ if self.emojize: text = emojize(text, use_aliases=True) if self.render_markdown: text = cmarkgfm.github_flavored_markdown_to_html( text, options=cmarkgfmOptions.CMARK_OPT_UNSAFE ) return text
def view_writeup(writeup_id: int): user = get_current_user() writeup = db.session.query(Submissions).get(writeup_id) error = {} content = '' editable = False if writeup.challenge.type != 'writeup': return redirect(url_for('writeups.writeups')) challenge = (db.session.query(Challenges).filter( Challenges.type != 'writeup').filter( Challenges.writeup_challenge == writeup.challenge).one_or_none()) if not challenge or not challenge.writeup_challenge: return redirect(url_for('writeups.writeups')) if (user.type == 'admin' or not challenge.writeup_challenge.solve_req or (user.team and (challenge.id in (s.challenge_id for s in user.team.solves))) or (challenge.id in (s.challenge_id for s in user.solves)) or writeup.user.id == user.id): content = cmarkgfm.github_flavored_markdown_to_html( writeup.provided, options=cmarkgfmOptions.CMARK_OPT_SAFE) if writeup.user.id == user.id or user.type == 'admin': editable = True else: error = { 'heading': '403', 'msg': 'Sorry, you must solve this challenge before viewing write-ups for it' } return render_template("view_writeup.html", challenge=challenge, content=content, error=error, user=writeup.user, editable=editable)
def title(self): text = emojize(self._title) return cmarkgfm.github_flavored_markdown_to_html( text, options=cmarkgfmOptions.CMARK_OPT_UNSAFE)
import pygments.formatters from .clean import clean _EXTRA_WARNING = ( "Markdown renderers are not available. " "Install 'readme_renderer[md]' to enable Markdown rendering.") try: import cmarkgfm from cmarkgfm.cmark import Options as cmarkgfmOptions variants: Dict[str, Callable[[str], str]] = { "GFM": lambda raw: cast( str, cmarkgfm.github_flavored_markdown_to_html( raw, options=cmarkgfmOptions.CMARK_OPT_UNSAFE)), "CommonMark": lambda raw: cast( str, cmarkgfm.markdown_to_html( raw, options=cmarkgfmOptions.CMARK_OPT_UNSAFE)), } except ImportError: warnings.warn(_EXTRA_WARNING) variants = {} # Make code fences with `python` as the language default to highlighting as # Python 3. _LANG_ALIASES = { 'python': 'python3', }
#!/usr/bin/env python import cmarkgfm import sys fname = sys.argv[1] f = open(fname, 'r') md_text = f.read() html = cmarkgfm.github_flavored_markdown_to_html(md_text).encode('utf8') print(html)
dest='in_file', required=True, help='Input file') parser.add_argument('-o,--output', dest='out_file', required=True, help='Output file') args = parser.parse_args() # Read the markdown document with open(args.in_file, 'r') as f: markdown = f.read() # Convert to HTML html = cmarkgfm.github_flavored_markdown_to_html(markdown) # TODO: Get lexer name from class name and dynamically import the lexer (probably need a name-to-lexer map) soup = BeautifulSoup(html, features="html.parser") r = re.compile('language-(.+)') for m in soup.find_all('code', class_=r): # [idx for idx, c in enumerate(m.attrs['class']) if r.match(c)][0] lexer_from_class = [ r.match(i)[1] for i in m.attrs['class'] if 'language' in i ][0] # Try to find the lexer try: lexer = get_lexer_by_name(lexer_from_class) except: print('Lexer {0} not found'.format(lexer_from_clas))
def markdown(value): # Renders the string using CommonMark in safe mode, which blocks # raw HTML in the input and also some links using a blacklist, # plus a second pass filtering using a whitelist for allowed # tags and URL schemes. import cmarkgfm from cmarkgfm.cmark import Options as cmarkgfmOptions html = cmarkgfm.github_flavored_markdown_to_html( value, options=cmarkgfmOptions.CMARK_OPT_SAFE) import html5lib, urllib.parse def filter_url(url): try: urlp = urllib.parse.urlparse(url) except Exception as e: # invalid URL return None if urlp.scheme not in ("http", "https"): return None return url valid_tags = set( 'strong em a code p h1 h2 h3 h4 h5 h6 pre br hr img ul ol li span blockquote' .split()) valid_tags = set('{http://www.w3.org/1999/xhtml}' + tag for tag in valid_tags) dom = html5lib.HTMLParser().parseFragment(html) for node in dom.iter(): if node.tag not in valid_tags and node.tag != 'DOCUMENT_FRAGMENT': node.tag = '{http://www.w3.org/1999/xhtml}span' for name, val in list(node.attrib.items()): if name.lower() in ("href", "src"): val = filter_url(val) if val is None: node.attrib.pop(name) else: node.set(name, val) else: # No other attributes are permitted. node.attrib.pop(name) # If there is an h1 in the output, demote all of the headings # so we don't create something that interfere's with the page h1. hash1 = False for node in dom.iter(): if node.tag in ("h1", "{http://www.w3.org/1999/xhtml}h1"): hash1 = True if hash1: for node in dom.iter(): m = re.match("(\{http://www.w3.org/1999/xhtml\})?h(\d)$", node.tag) if m: node.tag = (m.group(1) or "") + "h" + str(int(m.group(2)) + 1) html = html5lib.serialize(dom, quote_attr_values="always", omit_optional_tags=False, alphabetical_attributes=True) return safestring.mark_safe(html)
def post(self, request, event_id=None, format=None): event = get_object_or_404(models.Event, id=event_id) form_data = request.data.get('formData') if form_data is None: raise ValidationError({'formData': 'This field is required.'}) client_reported_pricing = request.data.get('pricingResults') if client_reported_pricing is None: raise ValidationError( {'pricingResults': 'This field is required.'}) self.validate_form_data(event, form_data) registration, campers = self.deserialize_form_data(event, form_data) invitation = None try: invitation = self.find_invitation(request) except InvitationError as e: raise ValidationError(e.user_message) if invitation: registration.registration_type = invitation.registration_type server_pricing_results = pricing.calculate_price(registration, campers) registration.server_pricing_results = server_pricing_results registration.client_reported_pricing = client_reported_pricing registration.save() if invitation: invitation.registration = registration invitation.save() campers_template_value = [] for camper_index, camper in enumerate(campers): campers_template_value.append({ **camper.attributes, 'pricing_result': server_pricing_results['campers'][camper_index], }) camper.save() confirmation_email_body_text = chevron.render( event.confirmation_email_template, { 'registration': registration.attributes, 'campers': campers_template_value, 'pricing_results': server_pricing_results, }) confirmation_email_body_html = cmarkgfm.github_flavored_markdown_to_html( confirmation_email_body_text) email_error = None sent = False try: if '@dontsend.com' in registration.registrant_email: email_error = 'registration email contains @dontsend.com' logger.error(confirmation_email_body_html) else: msg = EmailMultiAlternatives(event.confirmation_email_subject, confirmation_email_body_text, event.confirmation_email_from, [registration.registrant_email]) msg.attach_alternative(confirmation_email_body_html, "text/html") sent = msg.send(fail_silently=False) if not sent: email_error = email_error or 'mail not sent' except SMTPException as e: email_error = str(e) if email_error: logger.error(f'error sending confirmation email: {email_error}') return Response({ 'confirmationPageTemplate': event.confirmation_page_template, 'serverPricingResults': server_pricing_results, 'emailError': bool(email_error), })