rendered paste body#!/usr/bin/env python# coding:utf-8import reexample_content = """!Example ContentWir unterteilen die Welt in diese Kontinente:- Afrika- Antarktika- Asien- Australien- Europa- Nordamerika- Südamerika!!Wie Informatiker die Welt beschreiben```class Welt: winkel = 0 def dreht_sich(self): winkel += 1```"""class NoSuchMarkupError(Exception): def __init__(self, message): self.message = messageclass EmptyFileError(Exception): passclass SomeWeirdError(Exception): def __init__(self, message): self.message = message class Factory: def __init__(self): """ provides sanity checks and wraps objects around identifiers """ pass def makeFile(self, content, in_markup, out_markup): global example_content # sanity check the markup identifiers valid_input_markup = lambda x: x in ['dfm', 'restructuredText', ] valid_output_markup = lambda x: x in ['restructuredText', 'html', ] if not valid_input_markup(in_markup): raise NoSuchMarkupError('Input markup %s is not supported'% in_markup) if not valid_output_markup(out_markup): raise NoSuchMarkupError('Output markup %s is not supported'% out_markup) # empty content? set default. wrong content? error. is_empty = content is None or content == '' is_no_string = type(content) != type('string') if is_empty: content = example_content elif is_no_string: raise TypeError f = File(content, in_markup, out_markup) return f def getInputMarkup(self, name): """ @param linesMap: @param inLinesMap: It took me a long time to understand how to express inline markup with regular expressions. The answer is greedy: http://www.amk.ca/python/howto/regex/regex.html#SECTION000730000000000000000 """ dfm_lines = { 'heading1': re.compile(r'^!([^!].*)$'), 'heading2': re.compile(r'^!!([^!].*)$'), 'heading3': re.compile(r'^!!!([^!].*)$'), 'heading4': re.compile(r'^!!!!([^!].*)$'), 'code-begin': re.compile(r'\{\{\{'), 'code-end': re.compile(r'^}}}$'),# 'paragraph': re.compile(r'^(.+)$'),# 'blank line': re.compile(r'^$'), } dfm_inlines = { 'bold': re.compile('[*](.+?)[*]'), # GREEDY!!! (see greedy_url) 'italic': re.compile('//(.+?)//'), # GREEDY!!! (see greedy_url) 'underline': re.compile('__(.+?)__'), # GREEDY!!! (see greedy_url) } if name == 'dfm': inputMarkup = InputMarkup(dfm_lines, dfm_inlines) return inputMarkup def getParser(self, file): p = Parser(file) return p def getOutputMarkup(self, name): outputMarkup = None html_lines = { 'heading1': 'h2', 'heading2': 'h3', 'heading3': 'h4', 'heading4': 'h5', 'code-begin': 'pre', 'code-end': 'pre', } html_inlines = { 'bold': 'strong', 'italic': 'em', 'underline': 'span class="underline"',} if name == 'html': outputMarkup = OutputMarkup(html_lines, html_inlines)# if not outputMarkup:# raise SomeWeirdError('output markup ist none?') return outputMarkup def getOutFile(self): o = OutFile() return o # GLOBALfactory = Factory()# GLOBALclass File: global factory MarkupLines = [] in_markup = None out_markup = None def __init__(self, string, in_markup, out_markup): self.setContent(string) self.in_markup = factory.getInputMarkup(in_markup) self.out_markup = factory.getOutputMarkup(out_markup) def __str__(self): return '\n'.join(map(str, self.MarkupLines)) def getLines(self): return self.MarkupLines def getIterator(self): return self.MarkupLines.__iter__() def getInputMarkup(self): return self.in_markup def getOutputMarkup(self): return self.out_markup def setContent(self, string): l = [] for line in string.splitlines(): l.append(MarkupLine(line)) self.MarkupLines = l def setInputMarkup(self, string): self.in_markup = factory.getInputMarkup(string) def setOutputMarkup(self, string): self.out_markup = factory.getOutputMarkup(string) class InputMarkup: lines = {} inlines = {} def __init__(self, lines, inlines): self.lines = lines self.inlines = inlines def get(self, id): return self.lines[id] def getIds(self): return self.lines.keys def getLinesMap(self): return self.lines def isLineMarkup(self, string): """ returns true if string is a line markup """ result = False for tag in self.lines: compiled_regex_object = self.lines[tag] m = re.match(compiled_regex_object, string) if m: result = True return result def containsInlineMarkup(self, string): """ returns true if string contains inline markup """ result = False for tag in self.inlines: compiled_regex_object = self.inlines[tag] m = re.search(compiled_regex_object, string) if m: result = True return result def getLineMarkupTag(self, string): """ returns the markup identifier (tag) of string (e.g. 'heading1') """ result = None for tag in self.lines: if re.match(self.lines[tag], string): result = tag return result def getIdAndPattern(self, string): id = self.getLineMarkupTag(string) pattern = self.lines[id] return id, patternclass OutputMarkup: lines = {} inlines = {} def __init__(self, lines, inlines): self.lines = lines self.inlines = inlinesclass MarkupBlock: stack = [] def __init__(self, markupLine): self.string.append(markupLine.strip()) def add(self, markupLine): """ Pushes @param markupLine: """ pass class MarkupLine: string = '' id = '' match = None containsInlineMarkup = False def __init__(self, string, markup=factory.getInputMarkup('dfm')): """ blablabla MarkupLine blabla bla blab blablabla """ self.string = string # wurde ich "verschönert"? if markup.isLineMarkup(self.string): # was bin ich? womit wurde ich verglichen? self.id, pattern = markup.getIdAndPattern(self.string) # was wurde in mir gematcht? self.match = re.match(pattern, self.string) # habe ich inline Markup? #self.containsInlineMarkup = markup.containsInlineMarkup(self.string) def __str__(self): return self.string # jetzt kann ich "line.is_a('code-begin')" ausführen :) def is_a(self, id): return id == self.id def hasInlineMarkup(self): return self.containsInlineMarkup def strip(self): """ returns the "demarkified" string """ return self.match.groups()[0] class OutFile: lines = []# def __init__(self):# self.lines = [] def push(self, line): self.lines.append(line) def __str__(self): return '\n'.join(self.lines) infile = None outfile = Noneclass Parser: """ Usage: txt = '!Hello World\n- a\n- list\nFollowed by a paragraph.' parser = Parser() # loads a default setup parser.setText(txt) # parser.setMarkup('dfm') # this is the default, so we don't need to specify it here newTxt = parser.parse() """ global factory, example_content _inFile_ = None _outfile_ = None def __init__(self, content=example_content, input_markup='dfm', output_markup='html'): self._inFile_ = factory.makeFile(content, input_markup, output_markup) def loadExample(self): self.__init__() def getFile(self): return self._inFile_ def getInputMarkup(self): return self._inFile_.in_markup def getOutputMarkup(self): return self._inFile_.out_markup def getText(self): return str(self._inFile_) def setText(self, string): """ loads string as file that should be parsed """ self._inFile_.setContent(string) def load_file(self, path): f = open(path, 'r') string = f.read() f.close() self.setText(string) def markup(self, string): self._inFile_.setInputMarkup(string) def output(self, string): self._inFile_.setOutputMarkup(string) def parse(self):# lines = self.file.getLines()# i = 0# last_line = len(lines)-1# while i <= last_line:# line = lines[i]# if line.isCodeBegin:# i = parseBlock(lines[i:], 'Code')# for line in self.file.getl i = self.infile o = self.outfile for line in i.getLines(): o.push(line) return str(self.outfile) def encloseInHTMLTags(self, string, tag): return '<' + tag + '>' + string + '</' + tag + '>'