Dynastie/generators/post.py

256 lines
9.0 KiB
Python

import datetime
import os
from xml.dom.minidom import parse, parseString
from dynastie.generators.generator import DynastieGenerator, StrictUTF8Writer
from dynastie.generators.index import Index
from django.db import models
from dynastie.tree import TreeNode
class Post(Index):
cur_comment = None
comment_index = {}
def createReplace(self, post, dom, root, replace_elem):
if not replace_elem.hasAttribute('div_name'):
self.addError('No attribute div_name for a replace tag')
return
div_element = replace_elem.cloneNode(True)
div_element.tagName = replace_elem.getAttribute('div_name')
div_element.removeAttribute('div_name')
for key,value in replace_elem.attributes.items():
if key == 'div_name': continue
value = value.replace('dyn:post_id', str(post.id))
if self.cur_comment is None:
value = value.replace('dyn:comment_index', '0')
else:
value = value.replace('dyn:comment_index', str(self.comment_index[self.cur_comment.id]))
if self.cur_comment is None:
value = value.replace('dyn:comment_id', '0')
else:
value = value.replace('dyn:comment_id', str(self.cur_comment.id))
value = value.replace('dyn:blog_id', str(self.blog.id))
div_element.setAttribute(key, value)
root.replaceChild(div_element, replace_elem)
return div_element
def createComment(self, comment, dom, comment_elem, root):
values = {}
values['comment_index'] = str(self.comment_index[comment.id])
values['comment_author'] = comment.author
values['comment_date'] = comment.date.strftime('%d %B %Y %H:%m')
values['comment_content'] = comment.the_comment
self.simpleTransform(values, dom, comment_elem, root)
def _createComments(self, rootNode, post, dom, root_comment, root):
self.cur_comment = rootNode.value
comment_element = self.createElement(dom, 'comment')
self.createComment(self.cur_comment, dom, comment_element, root)
root_comment.appendChild(comment_element)
# Parse inner HTML
self._parse(self.hooks, post, dom, comment_element)
for commentNode in rootNode.childs:
self._createComments(commentNode, post, dom, comment_element, root)
def createComments(self, post, dom, post_elem, root):
from dynastie.models import Post, Blog, Comment
comments = Comment.objects.filter(post=post).order_by('date')
cur_comment = None
comment_index = {}
index = 1
rootNode = TreeNode('', '')
for comment in comments:
self.comment_index[comment.id] = index
index = index + 1
tnode = TreeNode(comment.id, comment)
if comment.parent is None:
rootNode.addChildNode(tnode)
else:
temp = rootNode.find(comment.parent.id)
if temp is None:
self.addWarning('Error with comments chain')
rootNode.addChildNode(tnode)
else:
temp.addChildNode(tnode)
initial_root_comment = root_comment = self.createElement(dom, 'comments')
for tnode in rootNode.childs:
self._createComments(tnode, post, dom, root_comment, root)
# Empty tag seems to crap rendering
if len(rootNode.childs) == 0:
post_elem.removeChild(root)
return None
else:
post_elem.replaceChild(root_comment, root)
return root_comment
def createMetas(self, post, dom, meta_elem, root):
name = root.getAttribute('name')
if name is None:
self.addError('Missing name attribute in dyn:meta')
return
new_elem = None
if name == 'keywords':
new_elem = self.createMeta(dom, name, post.keywords)
elif name == 'title':
new_elem = self.createMeta(dom, name, post.title)
elif name == 'description':
new_elem = self.createMeta(dom, name, post.description)
elif name == 'author':
try:
new_elem = self.createMeta(dom, name, post.author.first_name + ' ' + post.author.last_name)
except:
return None
if not new_elem is None:
root.parentNode.replaceChild(new_elem, root)
return new_elem
else:
self.addError('name attribute \'' + name + '\' unknown for dyn:meta' )
return None
def _createPost(self, post, dom, post_elem, root):
import sys, traceback
self.cur_post_obj = post
posts = [post]
self.createPost(posts, dom, post_elem, root)
# Post are appended by index. Remove template
post_nodes = dom.getElementsByTagNameNS(self.URI, 'post')
post_elem = post_nodes[0]
post_elem.parentNode.removeChild(post_elem)
title_nodes = dom.getElementsByTagName('title')
# Set title to be title's post
for node in title_nodes:
if node.hasChildNodes():
node.removeChild(node.childNodes[0])
node.appendChild(dom.createTextNode(post.title))
return node
def _generate(self, blog, src, output, posts):
import xml
self.hooks['post'] = self._createPost
self.hooks['meta'] = self.createMetas
self.hooks['comments'] = self.createComments
self.hooks['replace'] = self.createReplace
del self.hooks['navigation']
del self.hooks['recents']
del self.hooks['posts']
self.blog = blog
name = 'post'
if not os.path.exists(src + '/_%s.html' % name):
self.addError('No _%s.html found, exiting' % name)
return self.report
try:
dom = parse(src + '/_%s.html' % name)
except xml.dom.DOMException as e:
self.addError('Error parsing _%s.html : ' + e)
return self.report
impl = xml.dom.getDOMImplementation()
for post in posts:
#print 'Generate ' + filename
dom_ = impl.createDocument('', 'xml', None)
dom_.replaceChild(dom.firstChild.cloneNode(0), dom_.firstChild)
nodes = dom.getElementsByTagName("*")
nodes[0] = self.parse(src, self.hooks, post, dom_, nodes[0])
filename = output + '/post/'
filename = filename + post.creation_date.strftime("%Y") + '/' + post.creation_date.strftime("%m") + '/'
if not os.path.exists(filename):
os.makedirs(filename)
filename = filename + post.title_slug + '.html'
self.writeIfNotTheSame(filename, nodes[0])
if not self.somethingWrote:
self.addReport('Nothing changed')
return self.report
def generate(self, blog, src, output):
from dynastie.models import Post, Blog
self.blog = blog
posts = Post.objects.all()
return self._generate(blog, src, output, posts)
def createPreview(self, values, dom, root, node):
now = datetime.datetime.now()
v = {}
v['title'] = self.createLinkElem(dom, '/preview.html', values['title'])
v['author'] = values['author']
v['date'] = now.strftime("%A, %d %B %Y %H:%m")
v['post_content'] = ''
values['content'] = self.pygmentCode(values['content'])
self.simpleTransform(v, dom, root, node)
content_nodes = root.getElementsByTagName("div")
post_transform = ('post_content')
for content_node in content_nodes:
the_class = content_node.getAttribute('class')
if not the_class in post_transform:
continue
if the_class == 'post_content':
new_node = dom.createTextNode(values['content'])
content_node.appendChild(new_node)
post_nodes = dom.getElementsByTagNameNS(self.URI, "post")
post_elem = post_nodes[0]
post_elem.parentNode.removeChild(post_elem)
return post_elem
def preview(self, src, values):
from dynastie.models import Blog
# Override all hooks
self.hooks = {'post' : self.createPreview,
'tags' : self.createTags}
if not os.path.exists(src + '/_post.html'):
self.addError('No _post.html found, exiting')
return self.report
try:
dom = parse(src + '/_post.html')
except xml.dom.DOMException as e:
self.addError('Error parsing _post.html : ' + e)
return self.report
post_nodes = dom.getElementsByTagNameNS(self.URI, "posts")
if post_nodes is None:
self.addError('No tag dyn:posts found')
return self.report
nodes = dom.getElementsByTagName("*")
nodes[0] = self.parse(src, self.hooks, values, dom, nodes[0])
writer = StrictUTF8Writer()
nodes[0].writexml(writer)
return writer.getvalue().encode('utf-8')