Advertisement
mixster

SASSPy

Nov 9th, 2013
394
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.18 KB | None | 0 0
  1. import re
  2.  
  3. class Tag:
  4.  
  5.     def __init__(self, name, parent=None, attribs=None):
  6.         self.name = name
  7.         self.attr = attribs
  8.         self.chld = []
  9.         self.printer = lambda k,v: ' ' + k + '="' + v + '"'
  10.  
  11.         if parent is not None:
  12.             parent.add_child(self)
  13.  
  14.  
  15.     def add_child(self, child):
  16.         if not hasattr(child, 'to_html'):
  17.             raise TypeError('"to_html" not support by child %s' % child)
  18.         self.chld.append(child)
  19.  
  20.  
  21.     def get_name(self):
  22.         return self.name
  23.  
  24.  
  25.     def get_children(self):
  26.         return self.chld
  27.  
  28.  
  29.     def set_printer(self, printer):
  30.         self.printer = printer
  31.  
  32.  
  33.     def children_to_html(self, indent, pad):
  34.         return '\n'.join([c.to_html(indent, pad) for c in self.chld])
  35.  
  36.  
  37.     def head_to_html(self):
  38.         head = '<' + self.name
  39.         if self.attr is not None:
  40.             head += ''.join([self.printer(k, v) for (k, v) in self.attr])
  41.         head += '>'
  42.  
  43.         return head
  44.  
  45.     def tail_to_html(self):
  46.         tail = '</' + self.name + '>'
  47.  
  48.         return tail
  49.  
  50.     def to_html(self, indent='', pad='  '):
  51.         head = indent + self.head_to_html() + '\n'
  52.  
  53.         body = self.children_to_html(indent + pad, pad)
  54.         if body is not '':
  55.             body += '\n'
  56.  
  57.         tail = indent + self.tail_to_html()
  58.  
  59.         return head + body + tail
  60.  
  61.  
  62.  
  63. class EmptyTag(Tag):
  64.  
  65.     def __init__(self, parent=None):
  66.         self.chld = []
  67.         if parent is not None:
  68.             parent.add_child(self)
  69.  
  70.  
  71.     def to_html(self, indent='', pad='  '):
  72.         return Tag.children_to_html(self, indent, pad)
  73.  
  74.  
  75.  
  76. class Content:
  77.  
  78.     def __init__(self, content, parent=None):
  79.         if isinstance(content, str):
  80.             self.cont = content.split('\n')
  81.         else:
  82.             self.cont = content
  83.         if parent is not None:
  84.             parent.add_child(self)
  85.  
  86.  
  87.     def to_html(self, indent='', pad='  '):
  88.         return '\n'.join([indent + c for c in self.cont])
  89.  
  90.  
  91.  
  92. class VoidTag(Tag):
  93.  
  94.     def __init__(self, name, parent, attribs=None):
  95.         Tag.__init__(self, name, parent, attribs)
  96.  
  97.  
  98.     def to_html(self, indent='', pad=None):
  99.         return indent + Tag.head_to_html(self)
  100.  
  101.  
  102.  
  103. class DoctypeTag(VoidTag):
  104.  
  105.     def __init__(self, parent, fpi='"-//W3C//DTD HTML 4.01//EN"', uri='"http://www.w3.org/TR/html4/strict.dtd"'):
  106.         VoidTag.__init__(self, '!DOCTYPE', parent, (('list', ('html', 'PUBLIC', fpi, uri)),))
  107.         self.set_printer(lambda k, v: ''.join([' ' + t for t in v]))
  108.  
  109.  
  110.  
  111. class Bindable:
  112.  
  113.     def __init__(self):
  114.         self.bound = False
  115.  
  116.  
  117.     def set_bound(self):
  118.         if self.bound:
  119.             raise TypeError('Template already bound')
  120.         self.bound = True
  121.  
  122.  
  123.  
  124. class DocHeader(Bindable):
  125.  
  126.     def __init__(self, title, url, description):
  127.         Bindable.__init__(self)
  128.         self.titl = title
  129.         self.url = url
  130.         self.desc = description
  131.  
  132.  
  133.     def bind(self, page):
  134.         self.set_bound()
  135.  
  136.         h = page.get_head()
  137.         Content('%s' % self.titl, Tag('title', h))
  138.         VoidTag('meta', h, (('name', 'description'), ('content', '%s' % self.desc)))
  139.  
  140.  
  141.     def get_title(self):
  142.         return self.titl
  143.  
  144.    
  145.     def get_url(self):
  146.         return self.url
  147.    
  148.  
  149.  
  150. class StoryDoc(DocHeader):
  151.  
  152.     CODES = {
  153.         'b': 'b',
  154.         'i': 'i'
  155.     }
  156.  
  157.     def __init__(self, input_str):
  158.         (title, url, description, self.date, cont) = StoryDoc.parse(input_str)
  159.         DocHeader.__init__(self, title, url, description)
  160.  
  161.         self.cont = Content(StoryDoc.format_content(cont), None)
  162.  
  163.  
  164.     @staticmethod
  165.     def parse(inp):
  166.         tag = lambda o,e: r"<%s>\s*(.*?)\s*</%s>" % (o, e)
  167.  
  168.         def search_or_die(t, i):
  169.             res = re.search(tag(t, t), i, re.DOTALL)
  170.             if res is None:
  171.                 raise TypeError('Input string did not contain required tag "%s"' % t)
  172.             return res.group(1)
  173.  
  174.         titl = search_or_die('title', inp)
  175.         url = search_or_die('url', inp)
  176.         desc = search_or_die('description', inp)
  177.         dates = search_or_die('date', inp)
  178.  
  179.         date = []
  180.         for m in re.finditer(tag(r'(\d{4})-(\d{2})-(\d{2})', r'\1-\2-\3'), dates):
  181.             date.append(m.group(1, 2, 3, 4))
  182.  
  183.         cont = search_or_die('content', inp)
  184.  
  185.         return (titl, url, desc, date, cont)
  186.  
  187.  
  188.     @staticmethod
  189.     def format_content(inp, newline='<br>\n', codes=None):
  190.         mtch = lambda n: r"\[%s\](.*?)\[/%s\]" % (n, n)
  191.         repl = lambda n: r"<%s>\1</%s>" % (n, n)
  192.         if codes is None:
  193.             codes = StoryDoc.CODES
  194.         res = inp
  195.  
  196.         for (k, v) in codes.items():
  197.             res = re.sub(mtch(k), repl(k), res, 0, re.DOTALL)
  198.         if newline is not None:
  199.             res = re.sub(r"\n", newline, res)
  200.  
  201.         return res
  202.  
  203.  
  204.     def to_html(self, indent='', pad='  '):
  205.         return self.cont.to_html(indent, pad)
  206.  
  207.  
  208.  
  209. class MenuItem(Bindable):
  210.  
  211.     def __init__(self, title, url, parent):
  212.         Bindable.__init__(self)
  213.         self.titl = title
  214.         self.url = url
  215.         self.root = parent.new_child()
  216.         parent.add_child(self)
  217.  
  218.  
  219.     def bind(self, header):
  220.         self.set_bound()
  221.  
  222.         if header.get_title() == self.titl:
  223.             Content(self.titl, self.root)
  224.         else:
  225.             Content(self.titl, Tag('a', self.root, (('href', self.url),)))
  226.  
  227.  
  228.  
  229. class Menu(Bindable):
  230.  
  231.     def __init__(self, root):
  232.         Bindable.__init__(self)
  233.         self.root = root
  234.         self.chld = []
  235.  
  236.  
  237.     def new_child(self):
  238.         return EmptyTag(self.root)
  239.  
  240.  
  241.     def add_child(self, child):
  242.         self.chld.append(child)
  243.  
  244.  
  245.     def bind(self, header):
  246.         for c in self.chld:
  247.             c.bind(header)
  248.  
  249.  
  250.  
  251. class Template(Bindable):
  252.  
  253.     def __init__(self, root, content_container, menu=None, style=None):
  254.         Bindable.__init__(self)
  255.         self.styl = style
  256.         self.root = root
  257.         self.menu = menu
  258.         self.cont = content_container
  259.  
  260.  
  261.     def bind(self, page, header, content):
  262.         self.set_bound()
  263.  
  264.         if self.styl is not None:
  265.             page.get_head().add_child(self.style)
  266.         if self.menu is not None:
  267.             self.menu.bind(header)
  268.         self.cont.add_child(content)
  269.         page.get_body().add_child(self.root)
  270.         header.bind(page)
  271.  
  272.  
  273.  
  274. class Page(EmptyTag):
  275.  
  276.     def __init__(self, baseurl=None):
  277.         Tag.__init__(self, 'Root')
  278.         DoctypeTag(self)
  279.         html = Tag('html', self)
  280.         self.head = Tag('head', html)
  281.         self.body = Tag('body', html)
  282.         VoidTag('meta', self.head, (('http-equiv', 'Content-type'), ('content', 'text/html;charset=UTF-8')))
  283.         if baseurl is not None:
  284.             VoidTag('base', self.head, (('href', baseurl),))
  285.  
  286.  
  287.     def get_head(self):
  288.         return self.head
  289.  
  290.  
  291.     def get_body(self):
  292.         return self.body
  293.  
  294.  
  295.    
  296.  
  297.  
  298.  
  299. r = Tag('div')
  300. m = Menu(Tag('div', r, (('name', 'menu'),)))
  301. MenuItem('test', 'url', m)
  302. MenuItem('A Little Testing', 'url2', m)
  303. t = Template(r, Tag('div', r, (('name', 'content'),)), m)
  304.  
  305. p = Page()
  306.  
  307. f = open('test-story')
  308. s = StoryDoc(f.read())
  309.  
  310. t.bind(p, s, s)
  311.  
  312. print(p.to_html())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement