From 2e6232cd65e7f7249c31676691bdbda9f7711a7a Mon Sep 17 00:00:00 2001 From: Ryan McGuire Date: Mon, 9 Mar 2009 15:10:08 -0400 Subject: [PATCH] posts can now be in markdown syntax drafts of posts can be put in _drafts and optionally rendered using the -d flag. --- .gitignore | 1 + blogofile/__init__.py | 13 ++++++++++--- blogofile/post.py | 26 ++++++++++++++++---------- blogofile/util.py | 15 +++++++++++++++ blogofile/writer.py | 8 +++++--- setup.py | 5 +++-- 6 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 blogofile/util.py diff --git a/.gitignore b/.gitignore index 9187d7a..3f4b24f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /Blogofile.egg-info/* /build/* /dist/* +/blogofile/.ropeproject* diff --git a/blogofile/__init__.py b/blogofile/__init__.py index 8e6c0f4..18ff174 100644 --- a/blogofile/__init__.py +++ b/blogofile/__init__.py @@ -21,8 +21,6 @@ """ __author__ = "Ryan McGuire (ryan@enigmacurry.com)" -__date__ = "Tue Feb 3 12:52:52 2009" -__version__ = "0.1" import ConfigParser import os @@ -43,6 +41,9 @@ def main(): parser.add_option("-b","--build",dest="do_build", help="Build the blog again from source", default=False, action="store_true") + parser.add_option("-d","--include-drafts",dest="include_drafts", + default=False, action="store_true", + help="Writes permapages for drafts (but not in feeds or chronlogical blog)") (options, args) = parser.parse_args() #load config @@ -56,8 +57,14 @@ def main(): sys.exit(1) posts = post.parse_posts("_posts", timezone=config.get("blogofile","timezone")) + if options.include_drafts: + drafts = post.parse_posts("_drafts", timezone=config.get("blogofile","timezone")) + for p in drafts: + p.draft = True + else: + drafts = None writer = Writer(output_dir=os.path.join(config_dir,"_site"), config=config) - writer.write_blog(posts) + writer.write_blog(posts, drafts) if __name__ == '__main__': main() diff --git a/blogofile/post.py b/blogofile/post.py index 3efc215..ed2db91 100644 --- a/blogofile/post.py +++ b/blogofile/post.py @@ -17,9 +17,13 @@ import pytz import yaml import textile +import markdown date_format = "%Y/%m/%d %H:%M:%S" +class PostFormatException(Exception): + pass + class Post: """ Class to describe a blog post and associated metadata @@ -57,10 +61,10 @@ def __init__(self, source, timezone): self.tags = set() self.permalink = None self.content = u"" - self.draft = False self.format = "html" self.author = "" self.guid = None #Default guid is permalink + self.draft = False self.__parse() def __repr__(self): @@ -81,9 +85,12 @@ def __parse(self): #Convert post to HTML if self.format == "textile": self.content = textile.textile(post_src).decode("utf-8") - else: - #Assume it's raw html to begin with + elif self.format == "markdown": + self.content = markdown.markdown(post_src).decode("utf-8") + elif self.format == "html": self.content = post_src.decode("utf-8") + else: + raise PostFormatException("Post format '%s' not recognized." % self.format) def __parse_yaml(self, yaml_src): y = yaml.load(yaml_src) @@ -131,17 +138,16 @@ def parse_posts(directory, timezone): Returns a list of the posts sorted in reverse by date.""" posts = [] - textile_files = [f for f in os.listdir(directory) if f.endswith(".textile")] - for texi in textile_files: - src = open(os.path.join(directory,texi)).read() + post_filename_re = re.compile(".*((\.textile$)|(\.markdown$)|(\.html$))") + post_file_names = [f for f in os.listdir(directory) if post_filename_re.match(f)] + for post_fn in post_file_names: + src = open(os.path.join(directory,post_fn)).read() p = Post(src, timezone) #Exclude some posts - if not (p.draft == True or p.permalink == None): + if not (p.permalink == None): posts.append(p) posts.sort(key=operator.attrgetter('date'), reverse=True) - return posts - - + return posts if __name__ == '__main__': import doctest diff --git a/blogofile/util.py b/blogofile/util.py new file mode 100644 index 0000000..e91ec71 --- /dev/null +++ b/blogofile/util.py @@ -0,0 +1,15 @@ +html_escape_table = { + "&": "&", + '"': """, + "'": "'", + ">": ">", + "<": "<", + } + +def html_escape(text): + """Produce entities within text.""" + L=[] + for c in text: + L.append(html_escape_table.get(c,c)) + return "".join(L) + diff --git a/blogofile/writer.py b/blogofile/writer.py index 9d6bce5..7fc88d8 100644 --- a/blogofile/writer.py +++ b/blogofile/writer.py @@ -37,14 +37,16 @@ def __init__(self, output_dir, config): self.files_exclude_regex = re.compile("(^_.*)|(^#.*)|(^.*~$)") self.dirs_exclude_regex = re.compile("(^\.git)|(^\.hg)|(^\.bzr)|(^\.svn)|(^\CVS)") - def write_blog(self, posts): + def write_blog(self, posts, drafts=None): self.archive_links = self.__get_archive_links(posts) self.all_categories = self.__get_all_categories(posts) self.category_link_names = self.__compute_category_link_names(self.all_categories) self.__setup_output_dir() self.__write_files(posts) self.__write_blog_chron(posts) - self.__write_blog_permanent(posts) + self.__write_permapage(posts) + if drafts: + self.__write_permapage(drafts) self.__write_monthly_archives(posts) self.__write_blog_categories(posts) self.__write_feed(posts, "/feed", "rss.mako") @@ -224,7 +226,7 @@ def __write_monthly_archives(self, posts): for link, posts in m.items(): self.__write_blog_chron(posts,root=link) - def __write_blog_permanent(self, posts): + def __write_permapage(self, posts): """Write blog posts to their permalink locations""" perma_template = self.template_lookup.get_template("permapage.mako") perma_template.output_encoding = "utf-8" diff --git a/setup.py b/setup.py index 5d26872..49d1b3d 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup setup(name='Blogofile', - version='0.3', + version='0.3.1', description='A blog engine/compiler, inspired by Jekyll.', author='Ryan McGuire', author_email='ryan@enigmacurry.com', @@ -13,7 +13,8 @@ 'BeautifulSoup', 'pytz', 'pyyaml', - 'textile'], + 'textile', + 'markdown'], entry_points=""" [console_scripts] blogofile = blogofile:main