import re try: from mistune import Renderer, InlineLexer, Markdown, escape from pygments import highlight from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter except ImportError as err: print("Please install mistune to make use of markdown parsing.") print("\t pip install mistune") ## TODO get lexer elsewhere no_copy = "-webkit-touch-callout: none; \ -webkit-user-select: none; \ -khtml-user- select: none; \ -moz-user-select: none;\ -ms-user-select: none;\ user-select: none;" def box(content, color): return '<div style="background-color: #ffedc9; border: 1px solid {}; \ padding: 10px; font-size: smaller;">{}</div>'.format(color, content) def yellow_box(content): return box(content, '#FFB12E') def blue_box(content): return box(content, '#9999ff') def markdown(value): renderer = HighlightRenderer() markdown = Markdown(renderer=renderer) return markdown(value) class LaTeXRenderer(Renderer): def latex(self, formula): return '<span class="latex">{}</span>'.format(formula) def block_code(self, code, lang): if not lang: return '\n<pre><code>%s</code></pre>\n' % \ escape(code) lexer = get_lexer_by_name(lang, stripall=True) formatter = HtmlFormatter(noclasses=True, cssstyles=no_copy) return highlight(code, lexer, formatter) class LaTeXInlineLexer(InlineLexer): """ Classes are inspired by the lexer example in the mistune readme """ def enable_latex(self): # add latex rules self.rules.latex = re.compile( r'\[\[' # [[ r'([^\]]+)' # formula r'\]\](?!\])' # ]] ) self.default_rules.insert(3, 'latex') def output_latex(self, m): formula = m.group(1).replace('\n', ' ') return self.renderer.latex(formula) def get_custom_markdown(): renderer = LaTeXRenderer() inline = LaTeXInlineLexer(renderer) # enable the feature inline.enable_latex() return Markdown(renderer, inline=inline) markdown = get_custom_markdown() def choice_parser(raw_choices, points): """ Parse the multiple choice answers and form an array that has the following form: (text, isCorrect, points, solution) and store them in an array of arbitrary size TODO : This is too dense. simplyfy! """ if type(raw_choices) is str: lines = raw_choices.strip().split('\n') elif type(raw_choices) is list: lines = raw_choices regex = re.compile('\[(\d|X| )\]\s+([\w\W]+)', re.MULTILINE) parse = [re.match(regex, line).groups() for line in lines] final = [( markdown(text), True if mark != ' ' else False, float(mark) if mark not in ' X' else points) for mark, text in parse] return final def gap_parser(task): r = re.compile('\[select\]([\w\W]+?)\[\/select\]', re.MULTILINE) m = re.findall(r, task) final = [] for s in m: lines = s.strip().split('\n') regex = re.compile('\[(([0-9]*[.])?[0-9]+| )\]\s?([\w\W]+)', re.MULTILINE) parse = [re.search(regex, line).groups() for line in lines] final.append([(text.strip(), float(points) if not points == ' ' else 0) for points, _, text in parse]) sep = ' !"ยง$%&/(XCVBNM; ' no_gaps = re.sub(r, sep, task) text_only = [markdown(text) for text in no_gaps.split(sep)] for i, s in enumerate(final): text_only.insert(2*i+1, (s, -1)) return text_only