Make just about all the output formatting customizable.

This commit is contained in:
Jim Miller
2012-10-01 22:23:28 -05:00
parent 4a5e7c9fa1
commit 2ea820936e
5 changed files with 170 additions and 52 deletions
+30 -1
View File
@@ -18,6 +18,7 @@
import re
import os.path
import datetime
import string
import StringIO
import zipfile
from zipfile import ZipFile, ZIP_DEFLATED
@@ -101,6 +102,22 @@ class BaseStoryWriter(Configurable):
names as Story.metadata, but ENTRY should use label and value.
"""
if self.getConfig("include_titlepage"):
if self.hasConfig("titlepage_start"):
START = string.Template(self.getConfig("titlepage_start"))
if self.hasConfig("titlepage_entry"):
ENTRY = string.Template(self.getConfig("titlepage_entry"))
if self.hasConfig("titlepage_end"):
END = string.Template(self.getConfig("titlepage_end"))
if self.hasConfig("titlepage_wide_entry"):
WIDE_ENTRY = string.Template(self.getConfig("titlepage_wide_entry"))
if self.hasConfig("titlepage_no_title_entry"):
NO_TITLE_ENTRY = string.Template(self.getConfig("titlepage_no_title_entry"))
self._write(out,START.substitute(self.story.getAllMetadata()))
if WIDE_ENTRY==None:
@@ -132,6 +149,7 @@ class BaseStoryWriter(Configurable):
TEMPLATE= NO_TITLE_ENTRY
self._write(out,TEMPLATE.substitute({'label':label,
'id':entry,
'value':self.story.getMetadata(entry)}))
else:
self._write(out, entry)
@@ -146,11 +164,22 @@ class BaseStoryWriter(Configurable):
"""
# Only do TOC if there's more than one chapter and it's configured.
if len(self.story.getChapters()) > 1 and self.getConfig("include_tocpage") and not self.metaonly :
if self.hasConfig("tocpage_start"):
START = string.Template(self.getConfig("tocpage_start"))
if self.hasConfig("tocpage_entry"):
ENTRY = string.Template(self.getConfig("tocpage_entry"))
if self.hasConfig("tocpage_end"):
END = string.Template(self.getConfig("tocpage_end"))
self._write(out,START.substitute(self.story.getAllMetadata()))
for index, (title,html) in enumerate(self.story.getChapters(fortoc=True)):
if html:
self._write(out,ENTRY.substitute({'chapter':title, 'index':"%04d"%(index+1)}))
self._write(out,ENTRY.substitute({'chapter':title,
'number':index+1,
'index':"%04d"%(index+1)}))
self._write(out,END.substitute(self.story.getAllMetadata()))
+75 -23
View File
@@ -151,8 +151,16 @@ ${value}<br />
<h3>Update Log</h3>
''')
self.EPUB_LOG_UPDATE_START = string.Template('''
<p class='log_entry'>
''')
self.EPUB_LOG_ENTRY = string.Template('''
<b>${label}:</b> <span id="${id}">${value}</span>
''')
self.EPUB_LOG_UPDATE_END = string.Template('''
</p><hr />
''')
self.EPUB_LOG_PAGE_END = string.Template('''
@@ -160,30 +168,52 @@ ${value}<br />
</html>
''')
self.EPUB_LOG_PAGE_END = string.Template('''
</body>
</html>
''')
self.EPUB_COVER = string.Template('''
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><title>Cover</title><style type="text/css" title="override_css">
@page {padding: 0pt; margin:0pt}
body { text-align: center; padding:0pt; margin: 0pt; }
div { margin: 0pt; padding: 0pt; }
</style></head><body><div>
<img src="${coverimg}" alt="cover"/>
</div></body></html>
''')
def writeLogPage(self, out):
"""
XXX
Write the log page, but only include entries that there's
metadata for. START, ENTRY and END are expected to already by
metadata for. START, ENTRY and END are expected to already be
string.Template(). START and END are expected to use the same
names as Story.metadata, but ENTRY should use id, label and value.
"""
if self.getConfig("include_logpage"):
if self.hasConfig("logpage_start"):
START = string.Template(self.getConfig("logpage_start"))
else:
START = self.EPUB_LOG_PAGE_START
if self.hasConfig("logpage_end"):
END = string.Template(self.getConfig("logpage_end"))
else:
END = self.EPUB_LOG_PAGE_END
# if there's a self.story.logfile, there's an existing log
# to add to.
if self.story.logfile:
print("existing logfile found, appending")
print("existing data:%s"%self._getLastLogData(self.story.logfile))
logging.debug("existing logfile found, appending")
logging.debug("existing data:%s"%self._getLastLogData(self.story.logfile))
replace_string = "</body>" # "</h3>"
self._write(out,self.story.logfile.replace(replace_string,self._makeLogEntry(self._getLastLogData(self.story.logfile))+replace_string))
else:
# otherwise, write a new one.
self._write(out,self.EPUB_LOG_PAGE_START.substitute(self.story.getAllMetadata()))
self._write(out,START.substitute(self.story.getAllMetadata()))
self._write(out,self._makeLogEntry())
self._write(out,self.EPUB_LOG_PAGE_END.substitute(self.story.getAllMetadata()))
self._write(out,END.substitute(self.story.getAllMetadata()))
# self parsing instead of Soup because it should be simple and not
# worth the overhead.
@@ -206,7 +236,22 @@ ${value}<br />
return values
def _makeLogEntry(self, oldvalues={}):
retval = "<p class='log_entry'>"
if self.hasConfig("logpage_update_start"):
START = string.Template(self.getConfig("logpage_update_start"))
else:
START = self.EPUB_LOG_UPDATE_START
if self.hasConfig("logpage_entry"):
ENTRY = string.Template(self.getConfig("logpage_entry"))
else:
ENTRY = self.EPUB_LOG_ENTRY
if self.hasConfig("logpage_update_end"):
END = string.Template(self.getConfig("logpage_update_end"))
else:
END = self.EPUB_LOG_UPDATE_END
retval = START.substitute(self.story.getAllMetadata())
for entry in self.getConfigList("logpage_entries") + self.getConfigList("extra_logpage_entries"):
if self.isValidMetaEntry(entry):
@@ -221,16 +266,16 @@ ${value}<br />
label="%s"%entry.title()
logging.debug("No known label for %s, fallback to '%s'"%(entry,label))
retval = retval + self.EPUB_LOG_ENTRY.substitute({'id':entry,
'label':label,
'value':val})
retval = retval + ENTRY.substitute({'id':entry,
'label':label,
'value':val})
else:
# could be useful for introducing extra text, but
# mostly it makes it easy to tell when you get the
# keyword wrong.
retval = retval + entry
retval = retval + "</p><hr />"
retval = retval + END.substitute(self.story.getAllMetadata())
if self.getConfig('replace_hr'):
retval = retval.replace("<hr />","<div class='center'>* * *</div>")
@@ -429,16 +474,12 @@ ${value}<br />
"title":"Cover",
"href":"OEBPS/cover.xhtml"}))
if self.hasConfig("cover_content"):
COVER = string.Template(self.getConfig("cover_content"))
else:
COVER = self.EPUB_COVER
coverIO = StringIO.StringIO()
coverIO.write('''
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><title>Cover</title><style type="text/css" title="override_css">
@page {padding: 0pt; margin:0pt}
body { text-align: center; padding:0pt; margin: 0pt; }
div { margin: 0pt; padding: 0pt; }
</style></head><body><div>
<img src="%s" alt="cover"/>
</div></body></html>
'''%self.story.cover)
coverIO.write(COVER.substitute(dict(self.story.getAllMetadata().items()+{'coverimg':self.story.cover}.items())))
if self.getConfig("include_titlepage"):
items.append(("title_page","OEBPS/title_page.xhtml","application/xhtml+xml","Title Page"))
@@ -588,11 +629,22 @@ div { margin: 0pt; padding: 0pt; }
if logpageIO.getvalue(): # will be false if no log page.
outputepub.writestr("OEBPS/log_page.xhtml",logpageIO.getvalue())
logpageIO.close()
if self.hasConfig('chapter_start'):
CHAPTER_START = string.Template(self.getConfig("chapter_start"))
else:
CHAPTER_START = self.EPUB_CHAPTER_START
if self.hasConfig('chapter_end'):
CHAPTER_END = string.Template(self.getConfig("chapter_end"))
else:
CHAPTER_END = self.EPUB_CHAPTER_END
for index, (title,html) in enumerate(self.story.getChapters()):
if html:
logging.debug('Writing chapter text for: %s' % title)
fullhtml = self.EPUB_CHAPTER_START.substitute({'chapter':title, 'index':index+1}) + html + self.EPUB_CHAPTER_END.substitute({'chapter':title, 'index':index+1})
vals={'chapter':title, 'index':"%04d"%(index+1), 'number':index+1}
fullhtml = CHAPTER_START.substitute(vals) + html + CHAPTER_END.substitute(vals)
# ffnet(& maybe others) gives the whole chapter text
# as one line. This causes problems for nook(at
# least) when the chapter size starts getting big
+27 -3
View File
@@ -75,6 +75,8 @@ ${output_css}
<a name="section${index}"><h2>${chapter}</h2></a>
''')
self.HTML_CHAPTER_END = string.Template('')
self.HTML_FILE_END = string.Template('''
</body>
</html>''')
@@ -82,7 +84,17 @@ ${output_css}
def writeStoryImpl(self, out):
self._write(out,self.HTML_FILE_START.substitute(self.story.getAllMetadata()))
if self.hasConfig('file_start'):
FILE_START = string.Template(self.getConfig("file_start"))
else:
FILE_START = self.HTML_FILE_START
if self.hasConfig('file_end'):
FILE_END = string.Template(self.getConfig("file_end"))
else:
FILE_END = self.HTML_FILE_END
self._write(out,FILE_START.substitute(self.story.getAllMetadata()))
self.writeTitlePage(out,
self.HTML_TITLE_PAGE_START,
@@ -94,10 +106,22 @@ ${output_css}
self.HTML_TOC_ENTRY,
self.HTML_TOC_PAGE_END)
if self.hasConfig('chapter_start'):
CHAPTER_START = string.Template(self.getConfig("chapter_start"))
else:
CHAPTER_START = self.HTML_CHAPTER_START
if self.hasConfig('chapter_end'):
CHAPTER_END = string.Template(self.getConfig("chapter_end"))
else:
CHAPTER_END = self.HTML_CHAPTER_END
for index, (title,html) in enumerate(self.story.getChapters()):
if html:
logging.debug('Writing chapter text for: %s' % title)
self._write(out,self.HTML_CHAPTER_START.substitute({'chapter':title, 'index':"%04d"%(index+1)}))
vals={'chapter':title, 'index':"%04d"%(index+1), 'number':index+1}
self._write(out,CHAPTER_START.substitute(vals))
self._write(out,html)
self._write(out,CHAPTER_END.substitute(vals))
self._write(out,self.HTML_FILE_END.substitute(self.story.getAllMetadata()))
self._write(out,FILE_END.substitute(self.story.getAllMetadata()))
+12 -22
View File
@@ -88,27 +88,6 @@ ${value}<br />
self.MOBI_TABLE_TITLE_PAGE_END = string.Template('''
</table>
</body>
</html>
''')
self.MOBI_TOC_PAGE_START = string.Template('''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>${title} by ${author}</title>
</head>
<body>
<div>
<h3>Table of Contents</h3>
''')
self.MOBI_TOC_ENTRY = string.Template('''
<a href="file${index}.xhtml">${chapter}</a><br />
''')
self.MOBI_TOC_PAGE_END = string.Template('''
</div>
</body>
</html>
''')
@@ -169,10 +148,21 @@ ${value}<br />
# files.append(tocpageIO.getvalue())
# tocpageIO.close()
if self.hasConfig('chapter_start'):
CHAPTER_START = string.Template(self.getConfig("chapter_start"))
else:
CHAPTER_START = self.MOBI_CHAPTER_START
if self.hasConfig('chapter_end'):
CHAPTER_END = string.Template(self.getConfig("chapter_end"))
else:
CHAPTER_END = self.MOBI_CHAPTER_END
for index, (title,html) in enumerate(self.story.getChapters()):
if html:
logging.debug('Writing chapter text for: %s' % title)
fullhtml = self.MOBI_CHAPTER_START.substitute({'chapter':title, 'index':index+1}) + html + self.MOBI_CHAPTER_END.substitute({'chapter':title, 'index':index+1})
vals={'chapter':title, 'index':"%04d"%(index+1), 'number':index+1}
fullhtml = CHAPTER_START.substitute(vals) + html + CHAPTER_END.substitute(vals)
# ffnet(& maybe others) gives the whole chapter text
# as one line. This causes problems for nook(at
# least) when the chapter size starts getting big
+26 -3
View File
@@ -98,6 +98,7 @@ ${chapter}
\t${chapter}
''')
self.TEXT_CHAPTER_END = string.Template(u'')
self.TEXT_FILE_END = string.Template(u'''
@@ -114,7 +115,17 @@ End file.
wrapout = KludgeStringIO()
wrapout.write(self.TEXT_FILE_START.substitute(self.story.getAllMetadata()))
if self.hasConfig("file_start"):
FILE_START = string.Template(self.getConfig("file_start"))
else:
FILE_START = self.TEXT_FILE_START
if self.hasConfig("file_end"):
FILE_END = string.Template(self.getConfig("file_end"))
else:
FILE_END = self.TEXT_FILE_END
wrapout.write(FILE_START.substitute(self.story.getAllMetadata()))
self.writeTitlePage(wrapout,
self.TEXT_TITLE_PAGE_START,
@@ -133,13 +144,25 @@ End file.
self._write(out,self.lineends(self.wraplines(towrap)))
if self.hasConfig('chapter_start'):
CHAPTER_START = string.Template(self.getConfig("chapter_start"))
else:
CHAPTER_START = self.TEXT_CHAPTER_START
if self.hasConfig('chapter_end'):
CHAPTER_END = string.Template(self.getConfig("chapter_end"))
else:
CHAPTER_END = self.TEXT_CHAPTER_END
for index, (title,html) in enumerate(self.story.getChapters()):
if html:
logging.debug('Writing chapter text for: %s' % title)
self._write(out,self.lineends(self.wraplines(removeAllEntities(self.TEXT_CHAPTER_START.substitute({'chapter':title, 'index':index+1})))))
vals={'chapter':title, 'index':"%04d"%(index+1), 'number':index+1}
self._write(out,self.lineends(self.wraplines(removeAllEntities(CHAPTER_START.substitute(vals)))))
self._write(out,self.lineends(html2text(html,wrap_width=self.wrap_width)))
self._write(out,self.lineends(self.wraplines(removeAllEntities(CHAPTER_END.substitute(vals)))))
self._write(out,self.lineends(self.wraplines(self.TEXT_FILE_END.substitute(self.story.getAllMetadata()))))
self._write(out,self.lineends(self.wraplines(FILE_END.substitute(self.story.getAllMetadata()))))
def wraplines(self, text):