# CURRENT: # TODO: Shared # TODO: generate TARGET_EBOOK # TODO: Send HTML & CSS to ebook format converter: # TODO: pdf generation # - Both mobi and pdf generation are done via Qt. Calibre is linked against glibc 3.13, # and the shared hosting has an older version. So Calibre can't find parts of Qt. # TODO: generate TARGET_WEBSITE # TODO: Script invocation needs to be more flexible. # - It should be possible to regenerate one file. # - the home page, with discuss comments. # TODO: The update script should poll disqus and get the relevant data. # - the home page, with featured article changing periodically (random selection from valid candidates with right data). # TODO: Go through articles and add featured status elements. # TODO: Have some sort of database with last update status, which an update script hits. # - any article page, with linked resources being updated as needed. # TODO: Reddit posts and comments. # TODO: Disqus comments are now added to all issue articles in the website. # Could add comment counts to page titles or to links to issue articles: # https://help.disqus.com/customer/portal/articles/565624-tightening-your-disqus-integration # Where else to add disqus comments? # - Other issue pages than articles? # - Home page? # - Contribute page? Other pages? # TODO: RSS feed may need to include announcements. # - add from text file. # - edit in text file. # import calendar import codecs import distutils import distutils.dir_util # Not needed on windows. import distutils.file_util # Not needed on windows. import email.utils import json import os import shutil import subprocess import sys import time import jinja2 import feedformatter FLAG_ONLINE = 1 << 31 TARGET_EBOOK = 1 TARGET_WEBSITE = 2 # This defines where to look for the base template for a given target. templates_by_target = { TARGET_EBOOK: os.path.join("templates", "ebook"), TARGET_WEBSITE | FLAG_ONLINE: os.path.join("templates", "website"), TARGET_WEBSITE: os.path.join("templates", "website"), } """ Variable to configure for generation of final result with side-effects. """ setting_finalise = True setting_domain_name = "journal.imaginary-realities.com" PAGE_OTHER = 1 PAGE_ARTICLE = 2 issue_data = { # (volume_number, issue_number, (year, month)) (5,1,(2013,12)): [ (PAGE_OTHER, "introduction"), (PAGE_OTHER, "copyright"), (PAGE_ARTICLE, "modern-interface-modern-mud"), (PAGE_ARTICLE, "well-built-zone-work-art"), (PAGE_ARTICLE, "journey-through-paradice"), (PAGE_ARTICLE, "blind-accessibility-challenges-opportunities"), (PAGE_ARTICLE, "evennia-introduction"), (PAGE_ARTICLE, "getting-roleplaying-scene-going"), (PAGE_ARTICLE, "introducing-new-players-redesigning-mud-school"), (PAGE_ARTICLE, "hunger-game-learned-break-ship-bottle"), (PAGE_ARTICLE, "help-save-old-mudding-resources"), (PAGE_OTHER, "request-for-content"), (PAGE_OTHER, "staff"), ], (6,1,(2014,4)): [ (PAGE_OTHER, "introduction"), (PAGE_OTHER, "copyright"), (PAGE_ARTICLE, "a-journey-through-paradice-ii"), (PAGE_ARTICLE, "building-a-mech-in-evennia"), (PAGE_ARTICLE, "describing-a-virtual-world"), (PAGE_ARTICLE, "dynamic-room-descriptions"), (PAGE_ARTICLE, "saddle-up"), (PAGE_ARTICLE, "the-successful-quest-builder"), (PAGE_ARTICLE, "your-mud-should-have-an-account-system"), (PAGE_ARTICLE, "help-save-old-mudding-resources"), (PAGE_OTHER, "request-for-content"), (PAGE_OTHER, "staff"), ], (7,1,(2015,1)): [ (PAGE_OTHER, "introduction"), (PAGE_OTHER, "copyright"), (PAGE_ARTICLE, "choosing-an-emoting-system"), (PAGE_ARTICLE, "dungeon-keeper"), (PAGE_ARTICLE, "what-i-do-now"), (PAGE_ARTICLE, "worlds-in-which-we-wander"), (PAGE_OTHER, "request-for-content"), (PAGE_OTHER, "staff"), ], (7,2,(2015,4)): [ (PAGE_OTHER, "introduction"), (PAGE_OTHER, "copyright"), (PAGE_ARTICLE, "bartering"), (PAGE_ARTICLE, "is-structuralism-a-viable-critical-lens-for-roguelike-games"), (PAGE_OTHER, "request-for-content"), (PAGE_OTHER, "staff"), ], (7,3,(2015,7)): [ (PAGE_OTHER, "introduction"), (PAGE_OTHER, "copyright"), (PAGE_ARTICLE, "a-text-mud-with-a-working-ecology-system"), (PAGE_ARTICLE, "dispelling-the-gloom"), (PAGE_ARTICLE, "how-integral-are-letters-and-text-to-ascii-gaming"), (PAGE_ARTICLE, "legend-and-the-lore"), (PAGE_ARTICLE, "the-bonds-of-mudding"), (PAGE_ARTICLE, "the-mercurial-temperament-at-the-end-of-the-world"), (PAGE_ARTICLE, "where-do-i-begin"), (PAGE_OTHER, "request-for-content"), (PAGE_OTHER, "staff"), ] } class TemplateParameters(object): pass def init_template_data(tp): tp.key = None tp.full_url = tp.page_permanent_id.replace("website/", "http://"+ setting_domain_name +"/") tp.target_is_online = (setting_generation_target & FLAG_ONLINE) == FLAG_ONLINE tp.target_is_website = (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE tp.sections = TemplateParameters() if not hasattr(tp, "link_prefix"): tp.link_prefix = "" if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: tp.homepage_link = tp.link_prefix +"index.html" tp.contact_link = tp.link_prefix +"contact.html" tp.copyright_link = tp.link_prefix +"copyright.html" tp.contribute_link = tp.link_prefix +"contribute.html" tp.links_link = tp.link_prefix +"links.html" else: tp.contribute_link = tp.link_prefix +"request-for-content/index.html" tp.rss_link = "http://"+ setting_domain_name +"/feed_rss2.xml" tp.twitter_link = "https://twitter.com/irjrnl" tp.reddit_link = "http://www.reddit.com/r/imaginaryrealities/" if (setting_generation_target & FLAG_ONLINE) == FLAG_ONLINE: tp.js_jquery_link = "http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" else: if setting_use_minimised_files: tp.js_jquery_link = tp.link_prefix +"js/jquery-1.11.3.min.js" else: tp.js_jquery_link = tp.link_prefix +"js/jquery-1.11.3.js" tp.license_text = "CC BY SA NC" tp.license_link = "http://creativecommons.org/licenses/by-nc-sa/3.0/nz/" tp.website_title_text = "Imaginary Realities" tp.menu = TemplateParameters() tp.menu.back_issues_title = "Back Issues" tp.menu.latest_issue_title = "Current Issue" get_latest_issue_data(tp) get_back_issues_data(tp) def get_latest_issue_data(tp): tp.sections.latest_issue = TemplateParameters() tp.sections.latest_issue.title = "Latest Issue" tp.sections.latest_issue.issue_articles = [] issue_keys = issue_data.keys() issue_keys.sort(lambda a, b: cmp(b, a)) issue_key = issue_keys[0] volume_number, issue_number, (year_number, month_number) = issue_key issue_link = "volume-%02d/issue-%02d/" % (volume_number, issue_number) tp.sections.latest_issue.issue_title = "Volume %d, Issue %d (%s %d)" % (volume_number, issue_number, calendar.month_name[month_number], year_number) for article_type, page_dirname in issue_data[issue_key]: if page_dirname in setting_website_hidden_issue_pages: continue article = TemplateParameters() article.title = get_article_block_content(volume_number, issue_number, page_dirname, "page_title") article.link = issue_link + page_dirname +"/index.html" tp.sections.latest_issue.issue_articles.append(article) tp.sections.latest_issue.read_text = "Read this issue" tp.sections.latest_issue.read_link = issue_link +"index.html" def get_back_issues_data(tp): tp.sections.back_issues = TemplateParameters() tp.sections.back_issues.title = "Back Issues" tp.sections.back_issues.issues = [] issue_keys = issue_data.keys() issue_keys.sort(lambda a, b: cmp(b, a)) for issue_key in issue_keys[1:]: volume_number, issue_number, (year_number, month_number) = issue_key issue = TemplateParameters() issue.link = "volume-%02d/issue-%02d/index.html" % (volume_number, issue_number) issue.volume_text = "Volume %d, Issue %d" % (volume_number, issue_number) issue.publication_year_text = "%s %d" % (calendar.month_name[month_number], year_number) tp.sections.back_issues.issues.append(issue) def generate_website_index_page(): global data_disqus t = jinja2_env.get_template("homepage.html") output_path = os.path.join(setting_target_dirname, "index.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") init_template_data(tp) tp.key = "website_index" tp.sections.introduction = TemplateParameters() tp.sections.featured_article = TemplateParameters() tp.sections.recent_comments = TemplateParameters() # SECTION: Introduction tp.sections.introduction.logo_text = "An old logo for Imaginary Realities, with a lower-case i beside a upper-case R" tp.sections.introduction.logo_link = "images/logo.png" # SECTION: Featured article tp.sections.featured_article.title = "Featured Article" featured_article_key = (7,1,"what-i-do-now") volume_number, issue_number, page_dirname = featured_article_key article_title = get_article_block_content(volume_number, issue_number, page_dirname, "page_title") article_link = "volume-%02d/issue-%02d/%s/index.html" % (volume_number, issue_number, page_dirname) article_authors = get_article_block_content(volume_number, issue_number, page_dirname, "article_authors") feature_excerpt = get_article_block_content(volume_number, issue_number, page_dirname, "feature_excerpt") feature_hype = get_article_block_content(volume_number, issue_number, page_dirname, "feature_hype") tp.sections.featured_article.article_title = article_title tp.sections.featured_article.article_hype_text = feature_hype tp.sections.featured_article.article_quote_text = feature_excerpt tp.sections.featured_article.article_authorname_text = article_authors tp.sections.featured_article.read_text = "Read this article" tp.sections.featured_article.read_link = article_link # SECTION: Recent comments tp.sections.recent_comments.title = "Recent Comments" tp.sections.recent_comments.entries = [] tp.sections.recent_comments.is_enabled = True if data_disqus is None: tp.sections.recent_comments.is_enabled = False tp.sections.recent_comments.content = """
Failed to generate content.
""" else: # comment.comment_id/user_name/timestamp/thread_id/text for comment in data_disqus.get_recent_comments(): # thread.url/feed/title thread = data_disqus.get_thread(comment.thread_id) text = comment.text while " " in text: text = text.replace(" ", " ") text = text[:80]+"..." entry = TemplateParameters() entry.age_string = data_disqus.get_time_string(comment.timestamp) entry.user_name = comment.user_name entry.thread_title = thread.title entry.thread_url = thread.url entry.text = text tp.sections.recent_comments.entries.append(entry) html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_website_contact_page(): t = jinja2_env.get_template("contact.html") output_path = os.path.join(setting_target_dirname, "contact.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") init_template_data(tp) tp.key = "website_contact" html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_website_links_page(): t = jinja2_env.get_template("links.html") output_path = os.path.join(setting_target_dirname, "links.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") init_template_data(tp) html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_website_copyright_page(): t = jinja2_env.get_template("copyright.html") output_path = os.path.join(setting_target_dirname, "copyright.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") init_template_data(tp) html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_website_contribute_page(): t = jinja2_env.get_template("contribute.html") output_path = os.path.join(setting_target_dirname, "contribute.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") init_template_data(tp) tp.key = "website_contribute" html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_website_rss(): feed = feedformatter.Feed() feed.feed["title"] = "Imaginary Realities" feed.feed["link"] = "http://"+ setting_domain_name +"/" feed.feed["author"] = "Richard Tew" feed.feed["description"] = "Announcements related to the Imaginary Realities publication" # Load in existing items, in order of oldest to newest. feed_items = json.load(open("feed.json", "rb")) changes_made = False existing_links = [] for feed_item in feed_items: if type(feed_item["pubDate"]) in (str, unicode): # RFC2822 d = email.utils.parsedate_tz(feed_item["pubDate"]) feed_item["pubDate"] = email.utils.mktime_tz(d) # Seconds since epoch. changes_made = True feed.items.append(feed_item) link = feed_item["link"] if link.endswith("/"): link += "index.html" existing_links.append(link) # Add missing issues in order of publication (which is how the feed goes). issue_keys = issue_data.keys() issue_keys.sort() for issue_key in issue_keys: volume_number, issue_number, (year_number, month_number) = issue_key missing_link = feed.feed["link"] + "volume-%02d/issue-%02d/index.html" % (volume_number, issue_number) download_link = feed.feed["link"] + "files/" if missing_link not in existing_links: print "RSS: Adding issue to feed, volume %d, issue %d" % (volume_number, issue_number) item = {} item["title"] = "Imaginary Realities - Volume %d, Issue %d" % (volume_number, issue_number) item["description"] = "

Our latest issue as of %s %d. Long delayed, but finally here. Read it online, or download it as an epub e-book or PDF document. Follow our twitter, if that's your thing. Imaginary Realities contains articles related to mudding, and other text-based forms of gaming include interactive fiction and roguelikes.

" % (calendar.month_name[month_number], year_number, missing_link, download_link) item["link"] = missing_link item["pubDate"] = time.time() item["guid"] = "%d" % (time.time() * 100) feed_items.append(item) feed.items.append(item) changes_made = True if setting_finalise: if changes_made: # Update the json record of what has already been published (to try and avoid sending all entries out again, everytime we add a new RSS entry. json.dump(feed_items, open("feed.json", "wb")) print "RSS feed store modified, changes made." else: print "RSS feed store not modified, no changes to make." else: print "WARNING: Results are not finalised, published result should be finalised." # Generate the RSS2 feed. feed.format_rss2_file(os.path.join(setting_target_dirname, "feed_rss2.xml")) ### ISSUE GENERATION def generate_website(): print "Generating website" generate_website_index_page() generate_website_contact_page() generate_website_copyright_page() generate_website_contribute_page() # generate_website_links_page() generate_website_rss() if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: for dirname in ("css", "js", "fonts", "images"): distutils.dir_util.copy_tree(os.path.join("templates", "website", dirname), os.path.join(setting_target_dirname, dirname)) def generate_issue_page(issue_nav, volume_number, issue_number, year_number, month_number, page_type, page_dirname): outputdir_path = os.path.join(setting_target_dirname, "volume-%02d" % volume_number, "issue-%02d" % issue_number, page_dirname) inputdir_path = os.path.join("templates", "volume%02d_issue%02d" % (volume_number, issue_number), page_dirname) inputtemplate_name = "index.html" shutil.copytree(inputdir_path, outputdir_path, ignore=shutil.ignore_patterns(inputtemplate_name)) jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader([ "templates", setting_base_template, inputdir_path ])) t = jinja2_env.get_template(inputtemplate_name) output_path = os.path.join(outputdir_path, "index.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") # TODO: Path should be set more intelligently. Perhaps absolute in some cases. if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: # Full scope is [TOP/VOLUME/ISSUE/PAGE.html], so 3 levels moves from PAGE to TOP. tp.link_prefix = "../../../" else: # Full scope is [ISSUE/PAGE.html], so 1 levels moves from PAGE to ISSUE. tp.link_prefix = "../" init_template_data(tp) tp.volume_number = volume_number tp.issue_number = issue_number tp.issue_link = "../index.html" tp.issue_nav = issue_nav html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_issue_toc(issue_nav, issue_metadata, issue_pagedata): volume_number, issue_number, (year_number, month_number) = issue_metadata inputdir_path = os.path.join("templates", "issue") outputdir_path = os.path.join(setting_target_dirname, "volume-%02d" % volume_number, "issue-%02d" % issue_number) jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader([ "templates", setting_base_template, inputdir_path ])) t = jinja2_env.get_template("toc.html") output_path = os.path.join(outputdir_path, "index.html") tp = TemplateParameters() tp.page_permanent_id = output_path.replace("\\", "/") # TODO: Path should be set more intelligently. Perhaps absolute in some cases. if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: # Full scope is [TOP/VOLUME/ISSUE//PAGE], so 2 levels moves from PAGE to TOP. tp.link_prefix = "../../" else: # Full scope is [/PAGE], so 0 levels moves to ISSUE. tp.link_prefix = "" init_template_data(tp) tp.volume_number = volume_number tp.issue_number = issue_number tp.issue_link = "index.html" tp.logo_text = "An old logo for Imaginary Realities, with a lower-case i beside a upper-case R" tp.logo_link = "images/logo.png" tp.page_title = "Table of Contents" tp.issue = TemplateParameters() tp.issue.articles = [] for page_type, page_dirname in issue_pagedata: if page_dirname in setting_website_hidden_issue_pages: continue article = TemplateParameters() article.title = get_article_block_content(volume_number, issue_number, page_dirname, "page_title") article.author_names = get_article_block_content(volume_number, issue_number, page_dirname, "article_authors").replace(" and ", "
") article.link = page_dirname +"/index.html" tp.issue.articles.append(article) tp.issue.read_link = issue_pagedata[0][1] +"/index.html" tp.issue.read_text = "Read on.." tp.issue_nav = issue_nav html = t.render(tp=tp) with codecs.open(output_path, "wb", "utf-8") as f: f.write(html) def generate_issues(issue_data): issue_metadatas = issue_data.keys() issue_metadatas.sort() last_issue_index = len(issue_metadatas)-1 for issue_index, issue_metadata in enumerate(issue_metadatas): issue_pagedata = issue_data[issue_metadata] volume_number, issue_number, (year_number, month_number) = issue_metadata print "Generating issue volume %d, issue %d" % (volume_number, issue_number) volume_path = os.path.join(setting_target_dirname, "volume-%02d" % volume_number) issue_path = os.path.join(volume_path, "issue-%02d" % issue_number) distutils.dir_util.mkpath(issue_path) images_input_path = os.path.join("templates", "volume%02d_issue%02d" % (volume_number, issue_number), "images") if os.path.exists(images_input_path): images_output_path = os.path.join(issue_path, "images") distutils.dir_util.copy_tree(images_input_path, images_output_path) # Copy a set of the dependent files to each issue, for local use. if (setting_generation_target & TARGET_EBOOK) == TARGET_EBOOK: for parent_template_name in [ "website", "ebook" ]: parent_template_path = os.path.join("templates", parent_template_name) for entry_name in os.listdir(parent_template_path): entry_path = os.path.join(parent_template_path, entry_name) if os.path.isdir(entry_path): if parent_template_name == "website" and entry_name == "images": # There are a lot of images we do not need. for file_name in [ "logo.png" ]: dest_path = os.path.join(issue_path, entry_name) distutils.dir_util.mkpath(dest_path) distutils.file_util.copy_file(os.path.join(entry_path, file_name), os.path.join(dest_path, file_name)) else: distutils.dir_util.copy_tree(entry_path, os.path.join(issue_path, entry_name)) # TODO: The whole issue_nav debacle should be skipped for non-website builds. # TODO: Non-website builds should not have issue_nav if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: issue_nav = TemplateParameters() else: issue_nav = None if issue_nav: # Inter-article navigation button priming (setup done on per-article basis below). default_prev_article_html = issue_nav.prev_article_html = "« article" issue_nav.prev_article_class = "" default_next_article_html = issue_nav.next_article_html = "article »" issue_nav.next_article_class = "" # Inter-issue navigation button setup. default_prev_issue_html = issue_nav.prev_issue_html = "« issue" if issue_index == 0: issue_nav.prev_issue_class = "unlinked-button" prev_issue_link = "" else: prev_volume_number, prev_issue_number, discarded = issue_metadatas[issue_index-1] prev_issue_link = "volume-%02d/issue-%02d/index.html" % (prev_volume_number, prev_issue_number) issue_nav.prev_issue_html = "%s" % (prev_issue_link, default_prev_issue_html) issue_nav.prev_issue_class = "" default_next_issue_html = issue_nav.next_issue_html = "issue »" if issue_index == last_issue_index: issue_nav.next_issue_class = "unlinked-button" next_issue_link = "" else: next_volume_number, next_issue_number, discarded = issue_metadatas[issue_index+1] next_issue_link = "volume-%02d/issue-%02d/index.html" % (next_volume_number, next_issue_number) issue_nav.next_issue_html = "%s" % (next_issue_link, default_next_issue_html) issue_nav.next_issue_class = "" last_page_link = "../index.html" last_page_index = len(issue_pagedata)-1 for page_index, (page_type, page_dirname) in enumerate(issue_pagedata): if issue_nav: issue_nav.prev_article_class = "unlinked-button" issue_nav.next_article_class = "unlinked-button" issue_nav.prev_article_html = default_prev_article_html issue_nav.next_article_html = default_next_article_html set_prev = False set_next = False next_link = "" # The article hotbar skips over the copyright page. if page_dirname not in setting_website_hidden_issue_pages: if page_index == last_page_index: set_prev = True else: set_next = set_prev = True if set_prev: issue_nav.prev_article_html = "%s" % (last_page_link, default_prev_article_html) issue_nav.prev_article_class = "" if set_next: # The article hotbar skips over the copyright page. j = page_index+1 while j < len(issue_pagedata) and issue_pagedata[j][1] in setting_website_hidden_issue_pages: j += 1 if j < len(issue_pagedata): next_link = "../"+ issue_pagedata[j][1] +"/index.html" issue_nav.next_article_html = "%s" % (next_link, default_next_article_html) issue_nav.next_article_class = "" generate_issue_page(issue_nav, volume_number, issue_number, year_number, month_number, page_type, page_dirname) if issue_nav: # The article hotbar skips over the copyright page. if page_dirname not in setting_website_hidden_issue_pages: last_page_link = "../"+ page_dirname +"/index.html" if issue_nav: if prev_issue_link: issue_nav.prev_issue_html = "%s" % (prev_issue_link, default_prev_issue_html) issue_nav.prev_issue_class = "" else: issue_nav.prev_issue_html = default_prev_issue_html issue_nav.prev_issue_class = "unlinked-button" if next_issue_link: issue_nav.next_issue_html = "%s" % (next_issue_link, default_next_issue_html) issue_nav.next_issue_class = "" else: issue_nav.next_issue_html = default_next_issue_html issue_nav.next_issue_class = "unlinked-button" issue_nav.prev_article_class = "unlinked-button" issue_nav.next_article_class = "" issue_nav.prev_article_html = default_prev_article_html issue_nav.next_article_html = "%s" % (issue_pagedata[0][1] +"/index.html", default_next_article_html) generate_issue_toc(issue_nav, issue_metadata, issue_pagedata) def generate_ebooks(issue_data): """ "" ebooks\volume-06\issue-01\index.html issue.pdf --verbose """ command_path = "" command_path_guess = "" if os.name == "nt": command_path_guess = "c:\\Program Files (x86)\\Calibre2\\ebook-convert.exe" if os.path.exists(command_path_guess): command_path = command_path_guess elif os.name == "posix": command_path_guess = "/home1/disinter/opt/calibre/ebook-convert" if os.path.exists(command_path_guess): command_path = command_path_guess if command_path == "": print "Error: Unable to locate 'ebook-convert.exe', failed to generate ebooks." print "... %s" % command_path_guess return standard_arguments = "" standard_arguments += " --disable-font-rescaling" standard_arguments += " --margin-bottom=72" standard_arguments += " --margin-top=72" standard_arguments += " --margin-left=72" standard_arguments += " --margin-right=72" standard_arguments += " --chapter=/" standard_arguments += " --page-breaks-before=/" standard_arguments += " --chapter-mark=rule" standard_arguments += " --output-profile=default" standard_arguments += " --input-profile=default" standard_arguments += " --pretty-print" standard_arguments += " --replace-scene-breaks=\"\"" standard_arguments += " --toc-filter=.*\[\d+\].*" output_path = os.path.join("website", "files") distutils.dir_util.mkpath(output_path) issue_metadatas = issue_data.keys() issue_metadatas.sort() for issue_index, issue_metadata in enumerate(issue_metadatas): issue_pagedata = issue_data[issue_metadata] volume_number, issue_number, (year_number, month_number) = issue_metadata print "Generating ebook volume %d, issue %d" % (volume_number, issue_number) volume_path = os.path.join(setting_target_dirname, "volume-%02d" % volume_number) issue_path = os.path.join(volume_path, "issue-%02d" % issue_number) html_path = os.path.join(issue_path, "index.html") output_basename = "imaginary-realities-v%02di%02d-%04d%02d" % (volume_number, issue_number, year_number, month_number) for suffix in ("epub", "pdf"): output_filename = output_basename +"."+ suffix ret = subprocess.call([ command_path, html_path, os.path.join(output_path, output_filename) ]) print output_filename, ret def get_article_block_content(volume_number, issue_number, page_dirname, block_name): # Load the template. jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader([ "templates", setting_base_template, os.path.join("templates", "volume%02d_issue%02d" % (volume_number, issue_number), page_dirname) ])) t = jinja2_env.get_template("index.html") if block_name in t.blocks: return next(t.blocks[block_name](None)).strip() return "" default_generation_targets = TARGET_WEBSITE, TARGET_EBOOK def run(targets=None, disqus_data=None, reddit_data=None): # TODO(rmtew): Make these non-global at some point. It's not really a problem, but it's messy. global setting_target_dirname global setting_use_minimised_files global setting_website_hidden_issue_pages global setting_generation_target global setting_base_template global jinja2_env global data_disqus global data_reddit data_disqus = disqus_data data_reddit = reddit_data if targets is None: targets = default_generation_targets for setting_generation_target in targets: if setting_generation_target not in templates_by_target: print >> sys.stderr, "Unknown target:", setting_generation_target sys.exit(1) setting_base_template = templates_by_target[setting_generation_target] setting_use_minimised_files = False setting_target_dirname = None setting_website_hidden_issue_pages = [] if setting_generation_target & TARGET_WEBSITE == TARGET_WEBSITE: setting_target_dirname = "website" setting_website_hidden_issue_pages.extend([ "copyright", "request-for-content" ]) if setting_generation_target & FLAG_ONLINE == FLAG_ONLINE: setting_use_minimised_files = True elif setting_generation_target & TARGET_EBOOK == TARGET_EBOOK: setting_target_dirname = "ebooks" jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader([ 'templates', setting_base_template ])) if os.path.exists(setting_target_dirname): distutils.dir_util.remove_tree(setting_target_dirname) if (setting_generation_target & TARGET_WEBSITE) == TARGET_WEBSITE: generate_issues(issue_data) generate_website() elif (setting_generation_target & TARGET_EBOOK) == TARGET_EBOOK: generate_issues(issue_data) generate_ebooks(issue_data) if __name__ == "__main__": run() # EOF