Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import re
- class Tag:
- def __init__(self, name, parent=None, attribs=None):
- self.name = name
- self.attr = attribs
- self.chld = []
- self.printer = lambda k,v: ' ' + k + '="' + v + '"'
- if parent is not None:
- parent.add_child(self)
- def add_child(self, child):
- if not hasattr(child, 'to_html'):
- raise TypeError('"to_html" not support by child %s' % child)
- self.chld.append(child)
- def get_name(self):
- return self.name
- def get_children(self):
- return self.chld
- def set_printer(self, printer):
- self.printer = printer
- def children_to_html(self, indent, pad):
- return '\n'.join([c.to_html(indent, pad) for c in self.chld])
- def head_to_html(self):
- head = '<' + self.name
- if self.attr is not None:
- head += ''.join([self.printer(k, v) for (k, v) in self.attr])
- head += '>'
- return head
- def tail_to_html(self):
- tail = '</' + self.name + '>'
- return tail
- def to_html(self, indent='', pad=' '):
- head = indent + self.head_to_html() + '\n'
- body = self.children_to_html(indent + pad, pad)
- if body is not '':
- body += '\n'
- tail = indent + self.tail_to_html()
- return head + body + tail
- class EmptyTag(Tag):
- def __init__(self, parent=None):
- self.chld = []
- if parent is not None:
- parent.add_child(self)
- def to_html(self, indent='', pad=' '):
- return Tag.children_to_html(self, indent, pad)
- class Content:
- def __init__(self, content, parent=None):
- if isinstance(content, str):
- self.cont = content.split('\n')
- else:
- self.cont = content
- if parent is not None:
- parent.add_child(self)
- def to_html(self, indent='', pad=' '):
- return '\n'.join([indent + c for c in self.cont])
- class VoidTag(Tag):
- def __init__(self, name, parent, attribs=None):
- Tag.__init__(self, name, parent, attribs)
- def to_html(self, indent='', pad=None):
- return indent + Tag.head_to_html(self)
- class DoctypeTag(VoidTag):
- def __init__(self, parent, fpi='"-//W3C//DTD HTML 4.01//EN"', uri='"http://www.w3.org/TR/html4/strict.dtd"'):
- VoidTag.__init__(self, '!DOCTYPE', parent, (('list', ('html', 'PUBLIC', fpi, uri)),))
- self.set_printer(lambda k, v: ''.join([' ' + t for t in v]))
- class Bindable:
- def __init__(self):
- self.bound = False
- def set_bound(self):
- if self.bound:
- raise TypeError('Template already bound')
- self.bound = True
- class DocHeader(Bindable):
- def __init__(self, title, url, description):
- Bindable.__init__(self)
- self.titl = title
- self.url = url
- self.desc = description
- def bind(self, page):
- self.set_bound()
- h = page.get_head()
- Content('%s' % self.titl, Tag('title', h))
- VoidTag('meta', h, (('name', 'description'), ('content', '%s' % self.desc)))
- def get_title(self):
- return self.titl
- def get_url(self):
- return self.url
- class StoryDoc(DocHeader):
- CODES = {
- 'b': 'b',
- 'i': 'i'
- }
- def __init__(self, input_str):
- (title, url, description, self.date, cont) = StoryDoc.parse(input_str)
- DocHeader.__init__(self, title, url, description)
- self.cont = Content(StoryDoc.format_content(cont), None)
- @staticmethod
- def parse(inp):
- tag = lambda o,e: r"<%s>\s*(.*?)\s*</%s>" % (o, e)
- def search_or_die(t, i):
- res = re.search(tag(t, t), i, re.DOTALL)
- if res is None:
- raise TypeError('Input string did not contain required tag "%s"' % t)
- return res.group(1)
- titl = search_or_die('title', inp)
- url = search_or_die('url', inp)
- desc = search_or_die('description', inp)
- dates = search_or_die('date', inp)
- date = []
- for m in re.finditer(tag(r'(\d{4})-(\d{2})-(\d{2})', r'\1-\2-\3'), dates):
- date.append(m.group(1, 2, 3, 4))
- cont = search_or_die('content', inp)
- return (titl, url, desc, date, cont)
- @staticmethod
- def format_content(inp, newline='<br>\n', codes=None):
- mtch = lambda n: r"\[%s\](.*?)\[/%s\]" % (n, n)
- repl = lambda n: r"<%s>\1</%s>" % (n, n)
- if codes is None:
- codes = StoryDoc.CODES
- res = inp
- for (k, v) in codes.items():
- res = re.sub(mtch(k), repl(k), res, 0, re.DOTALL)
- if newline is not None:
- res = re.sub(r"\n", newline, res)
- return res
- def to_html(self, indent='', pad=' '):
- return self.cont.to_html(indent, pad)
- class MenuItem(Bindable):
- def __init__(self, title, url, parent):
- Bindable.__init__(self)
- self.titl = title
- self.url = url
- self.root = parent.new_child()
- parent.add_child(self)
- def bind(self, header):
- self.set_bound()
- if header.get_title() == self.titl:
- Content(self.titl, self.root)
- else:
- Content(self.titl, Tag('a', self.root, (('href', self.url),)))
- class Menu(Bindable):
- def __init__(self, root):
- Bindable.__init__(self)
- self.root = root
- self.chld = []
- def new_child(self):
- return EmptyTag(self.root)
- def add_child(self, child):
- self.chld.append(child)
- def bind(self, header):
- for c in self.chld:
- c.bind(header)
- class Template(Bindable):
- def __init__(self, root, content_container, menu=None, style=None):
- Bindable.__init__(self)
- self.styl = style
- self.root = root
- self.menu = menu
- self.cont = content_container
- def bind(self, page, header, content):
- self.set_bound()
- if self.styl is not None:
- page.get_head().add_child(self.style)
- if self.menu is not None:
- self.menu.bind(header)
- self.cont.add_child(content)
- page.get_body().add_child(self.root)
- header.bind(page)
- class Page(EmptyTag):
- def __init__(self, baseurl=None):
- Tag.__init__(self, 'Root')
- DoctypeTag(self)
- html = Tag('html', self)
- self.head = Tag('head', html)
- self.body = Tag('body', html)
- VoidTag('meta', self.head, (('http-equiv', 'Content-type'), ('content', 'text/html;charset=UTF-8')))
- if baseurl is not None:
- VoidTag('base', self.head, (('href', baseurl),))
- def get_head(self):
- return self.head
- def get_body(self):
- return self.body
- r = Tag('div')
- m = Menu(Tag('div', r, (('name', 'menu'),)))
- MenuItem('test', 'url', m)
- MenuItem('A Little Testing', 'url2', m)
- t = Template(r, Tag('div', r, (('name', 'content'),)), m)
- p = Page()
- f = open('test-story')
- s = StoryDoc(f.read())
- t.bind(p, s, s)
- print(p.to_html())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement