def render_text(text, autocompletes=None, comment=None, unwrap_p=False): # Render comment text into HTML. import re # Put @-mentions in bold. if autocompletes: text, _ = match_autocompletes(text, autocompletes, lambda text: "**" + text + "**") # Rewrite attachment:### URLs. if comment is not None: def get_attachment_url(attachment_id): try: return Attachment.objects.get( id=attachment_id.group(1)).get_absolute_url() except: return "about:blank" text = re.sub("(?<=\()attachment:(\d+)(?=\))", get_attachment_url, text) # Render to HTML as if CommonMark. import CommonMark parsed = CommonMark.Parser().parse(text) text = CommonMark.HtmlRenderer({"safe": True}).render(parsed) if unwrap_p: # If it's a single paragraph, unwrap it. text = re.sub(r"^<p>(.*)</p>$", r"\1", text) return text
def markdown(text, escape=True): parser = CommonMark.Parser() ast = parser.parse(text) renderer = CommonMark.HtmlRenderer() html = renderer.render(ast) return html
def to_json(self, user=None): parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(self.event.abstract) abstract = renderer.render(ast) data = { 'title': self.event.title, 'event_slug': self.event.slug, 'abstract': abstract, 'from': self.when.lower.isoformat(), 'to': self.when.upper.isoformat(), 'url': str(self.event.get_absolute_url()), 'id': self.id, 'speakers': [ { 'name': speaker.name , 'url': str(speaker.get_absolute_url()) } for speaker in self.event.speakers.all() ], 'bg-color': self.event.event_type.color, 'fg-color': '#fff' if self.event.event_type.light_text else '#000', 'event_type': self.event.event_type.slug, 'location': self.location.slug, 'location_icon': self.location.icon, 'timeslots': self.timeslots, } if user and user.is_authenticated: is_favorited = user.favorites.filter(event_instance=self).exists() data['is_favorited'] = is_favorited return data
def neomarkdown(markdown_content): parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(markdown_content) html = renderer.render(ast) # json = CommonMark.dumpJSON(ast) # CommonMark.dumpAST(ast) return html
def test_smart_dashes(self): md = 'a - b -- c --- d ---- e ----- f' EM = '\u2014' EN = '\u2013' expected_html = ('<p>' + 'a - ' + 'b ' + EN + ' ' + 'c ' + EM + ' ' + 'd ' + EN + EN + ' ' + 'e ' + EM + EN + ' ' + 'f</p>\n') parser = CommonMark.Parser(options=dict(smart=True)) ast = parser.parse(md) renderer = CommonMark.HtmlRenderer() html = renderer.render(ast) self.assertEqual(html, expected_html)
def page(name='teemo'): exodus_dir = os.path.dirname(os.path.realpath(__file__)) page = 'pages/%s.md' % name path = os.path.join(exodus_dir, page) if path.startswith(exodus_dir) and os.path.exists(path): with open(str(path)) as p: c = p.read() parser = CommonMark.Parser() ast = parser.parse(unicode(c, 'utf-8')) renderer = CommonMark.HtmlRenderer() html = renderer.render(ast) return render_template('page.html', page=html) else: return render_template('404.html'), 404
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 CommonMark ast = CommonMark.Parser().parse(force_unicode(value)) html = CommonMark.HtmlRenderer({'safe': True}).render(ast) import html5lib, urlparse def filter_url(url): try: urlp = urlparse.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 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) html = html5lib.serialize(dom, quote_attr_values="always", omit_optional_tags=False, alphabetical_attributes=True) return safestring.mark_safe(html)
def main(): parser = argparse.ArgumentParser( description="Process Markdown according to " "the CommonMark specification.") if sys.version_info < (3, 0): reload(sys) # noqa sys.setdefaultencoding('utf-8') parser.add_argument('infile', nargs="?", type=argparse.FileType('r'), default=sys.stdin, help="Input Markdown file to parse, defaults to STDIN") parser.add_argument('-o', nargs="?", type=argparse.FileType('w'), default=sys.stdout, help="Output HTML/JSON file, defaults to STDOUT") parser.add_argument('-a', action="store_true", help="Print formatted AST") parser.add_argument('-aj', action="store_true", help="Output JSON AST") args = parser.parse_args() parser = CommonMark.Parser() f = args.infile o = args.o lines = [] for line in f: lines.append(line) data = "".join(lines) ast = parser.parse(data) if not args.a and not args.aj: renderer = CommonMark.HtmlRenderer() o.write(renderer.render(ast)) exit() if args.a: # print ast CommonMark.dumpAST(ast) exit() # o.write(ast.to_JSON()) o.write(CommonMark.dumpJSON(ast)) exit()
def render_commonmark_template(template, context): # Render a CommonMark template to HTML. # Replace template tags with Unicode sentinels so that # the template tags do not impact CommonMark rendering. substitutions = [] import re def replace(m): # Record the substitution. index = len(substitutions) substitutions.append(m.group(0)) return "\uE000%d\uE001" % index # use Unicode private use area code points template = re.sub("{%.*?%}|{{.*?}}", replace, template) # Render the CommonMark. # Prevent CommonMark from mucking with our sentinels # in URLs though - it would otherwise add escaping. from CommonMark import inlines def urlencode_special(uri): import urllib.parse return "".join( urllib.parse.quote(c, safe="/@:+?=&()%#*,") # this is what CommonMark does if c not in "\uE000\uE001" else c # but keep our special codes for c in uri) inlines.normalize_uri = urlencode_special # Render. import CommonMark template = CommonMark.HtmlRenderer().render(CommonMark.Parser().parse(template)) # Put the template tags back that we removed prior to running # the CommonMark renderer. def replace(m): return substitutions[int(m.group(1))] template = re.sub("\uE000(\d+)\uE001", replace, template) # And finally render the Django template. return Template(template).render(Context(context))
def create(self, options): self.parser = CommonMark.Parser() self.renderer = CommonMark.HtmlRenderer()
def init_app(app): parser = CommonMark.Parser # Not an instance because not thread-safe(?) renderer = CommonMark.HtmlRenderer({'softbreak': '<br/>'}) app.extensions['markdown'] = UDataMarkdown(app, parser, renderer) app.add_template_filter(mdstrip)
parser.add_argument('-i', action="store_true", help="Interactive Markdown input mode") parser.add_argument('-d', action="store_true", help="Debug, trace calls") parser.add_argument('-np', action="store_true", help="Only print section header, tick, or cross") parser.add_argument('-s', action="store_true", help="Print percent of tests passed by category") args = parser.parse_args() if args.d: sys.settrace(trace_calls) renderer = CommonMark.HtmlRenderer() parser = CommonMark.Parser() f = codecs.open("spec.txt", encoding="utf-8") datalist = [] for line in f: datalist.append(line) data = "".join(datalist) passed = 0 failed = 0 catStats = {} examples = [] example_number = 0 current_section = "" tabChar = '\u2192' spaceChar = '\u2423'
def commonmark(value): parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(force_text(value)) return mark_safe(force_text(renderer.render(ast)))
def show_question(request, task, answered, context, q, EncryptionProvider, set_ephemeral_encryption_cookies): # Always hide the fill-out-your-profile blurb on all question pages - it's # distracting from answering the question at hand. See task_view. request.suppress_prompt_banner = True # If this question cannot currently be answered (i.e. dependencies are unmet), # then redirect away from this page. If the user is allowed to use the authoring # tool, then allow seeing this question so they can edit all questions. authoring_tool_enabled = task.module.is_authoring_tool_enabled(request.user) is_answerable = (((q not in answered.unanswered) or (q in answered.can_answer)) and (q.key not in answered.was_imputed)) if not is_answerable and not authoring_tool_enabled: return HttpResponseRedirect(task.get_absolute_url()) # Is there a TaskAnswer for this yet? taskq = TaskAnswer.objects.filter(task=task, question=q).first() # Display requested question. # Is there an answer already? (If this question isn't answerable, i.e. if we're # only here because the user is using the authoring tool, then there is no # real answer to load.) answer = None if taskq and is_answerable: answer = taskq.get_current_answer() if answer and answer.cleared: # If the answer is cleared, treat as if it had not been answered. answer = None # For "module"-type questions, get the Module instance of the tasks that can # be an answer to this question, and get the existing Tasks that the user can # choose as an answer. answer_module = q.answer_type_module answer_tasks = [] if answer_module: # The user can choose from any Task instances they have read permission on # and that are of the correct Module type. answer_tasks = Task.get_all_tasks_readable_by(request.user, request.organization, recursive=True)\ .filter(module=answer_module) # Annotate the instances with whether the user also has write permission. for t in answer_tasks: t.can_write = t.has_write_priv(request.user) # Sort the instances: # first: the current answer, if any # then: tasks defined in the same project as this task # later: tasks defined in projects in the same folder as this task's project # last: everything else by reverse update date now = timezone.now() current_answer = answer.answered_by_task.first() if answer else None answer_tasks = sorted(answer_tasks, key = lambda t : ( not (t == current_answer), not (t.project == task.project), not (set(t.project.contained_in_folders.all()) & set(task.project.contained_in_folders.all())), now-t.updated, )) # Add instrumentation event. # How many times has this question been shown? i_prev_view = InstrumentationEvent.objects\ .filter(user=request.user, event_type="task-question-show", task=task, question=q)\ .order_by('-event_time')\ .first() # Save. InstrumentationEvent.objects.create( user=request.user, event_type="task-question-show", event_value=(i_prev_view.event_value+1) if i_prev_view else 1, module=task.module, question=q, project=task.project, task=task, answer=taskq, ) # Indicate for the InstrumentQuestionPageLoadTimes middleware that this is # a question page load. request._instrument_page_load = { "event_type": "task-question-request-duration", "module": task.module, "question": q, "project": task.project, "task": task, "answer": taskq, } # Construct the page. def render_markdown_field(field, output_format, **kwargs): template = q.spec.get(field) if not template: return None if not isinstance(template, str): raise ValueError("%s question %s %s is not a string" % (repr(q.module), q.key, field)) return module_logic.render_content({ "template": template, "format": "markdown", }, answered, output_format, "%s question %s %s" % (repr(q.module), q.key, field), **kwargs ) # Get any existing answer for this question. existing_answer = None if answer: existing_answer = answer.get_value(decryption_provider=EncryptionProvider()) # For longtext questions, because the WYSIWYG editor is initialized with HTML, # render the value as HTML. if existing_answer and q.spec["type"] == "longtext": import CommonMark existing_answer = CommonMark.HtmlRenderer().render(CommonMark.Parser().parse(existing_answer)) # What's the title/h1 of the page and the rest of the prompt? Render the # prompt field. If it starts with a paragraph, turn that paragraph into # the title. title = q.spec["title"] prompt = render_markdown_field("prompt", "html") m = re.match(r"^<p>([\w\W]*?)</p>\s*", prompt) if m: title = m.group(1) prompt = prompt[m.end():] # Get a default answer for this question. Render Jinja2 template, but don't turn # Markdown into HTML for plain text fields. For longtext fields, turn it into # HTML because the WYSIWYG editor is initialized with HTML. default_answer = render_markdown_field("default", "text" if q.spec["type"] != "longtext" else "html", demote_headings=False) context.update({ "header_col_active": "start" if (len(answered.as_dict()) == 0 and q.spec["type"] == "interstitial") else "questions", "q": q, "title": title, "prompt": prompt, "placeholder_answer": render_markdown_field("placeholder", "text") or "", # Render Jinja2 template but don't turn Markdown into HTML. "reference_text": render_markdown_field("reference_text", "html"), "history": taskq.get_history() if taskq else None, "answer_obj": answer, "answer": existing_answer, "default_answer": default_answer, "review_choices": [(0, 'Not Reviewed'), (1, 'Reviewed'), (2, 'Approved')], "discussion": Discussion.get_for(request.organization, taskq) if taskq else None, "show_discussion_members_count": True, "answer_module": answer_module, "answer_tasks": answer_tasks, "answer_tasks_show_user": len([ t for t in answer_tasks if t.editor != request.user ]) > 0, "context": module_logic.get_question_context(answered, q), # Helpers for showing date month, day, year dropdowns, with # localized strings and integer values. Default selections # are done in the template & client-side so that we can use # the client browser's timezone to determine the current date. "date_l8n": lambda : { "months": [ (timezone.now().replace(2016,m,1).strftime("%B"), m) for m in range(1, 12+1)], "days": [ d for d in range(1, 31+1)], "years": [ y for y in reversed(range(timezone.now().year-100, timezone.now().year+101))], }, "is_answerable": is_answerable, # only false if authoring tool is enabled, otherwise this page is not renderable "authoring_tool_enabled": authoring_tool_enabled, }) return render(request, "question.html", context)
def __init__(self, *args, **kwargs): super(CompileCommonMark, self).__init__(*args, **kwargs) if CommonMark is not None: self.parser = CommonMark.Parser() self.renderer = CommonMark.HtmlRenderer()
def commonmark(value): """Returns HTML given some CommonMark Markdown. Does not clean HTML, not for use with untrusted input.""" parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(value) return mark_safe(renderer.render(ast))
def unsafecommonmark(value): """Returns HTML given some CommonMark Markdown. Cleans HTML from input using bleach, suitable for use with untrusted input.""" parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(bleach.clean(value)) return mark_safe(renderer.render(ast))
def __init__(self): self.path = os.path.join(settings.BASE_DIR, 'NEWS.md') self.parser = CommonMark.Parser() self.renderer = CommonMark.HtmlRenderer() self.cookie_name = 'news_current'
def trustedcommonmark(value): """Returns HTML given some CommonMark Markdown. Also allows real HTML, so do not use this with untrusted input.""" parser = CommonMark.Parser() renderer = CommonMark.HtmlRenderer() ast = parser.parse(value) return mark_safe(renderer.render(ast))
def __init__(self): self.parser = CommonMark.Parser() self.renderer = CommonMark.HtmlRenderer()