From d8af6b0a14c66aa55561eea9161854a337610c84 Mon Sep 17 00:00:00 2001 From: Zhiming Wang Date: Tue, 5 May 2015 03:59:16 -0700 Subject: 20150505: New blog, new start Also fixed several problems: 1. Rending SVG and making it a clickable link is basically impossible across multiple browsers. I'm now using a pretty good PNG; 2. Implemented new_post in pyblog; 3. Footnotes related updates to the theme. --- pyblog | 86 ++++++++++++++--- source/blog/2015-05-05-new-blog-new-start.md | 42 +++++++++ source/css/theme.css | 8 ++ source/img/README.rst | 2 +- source/img/icon.png | Bin 0 -> 6920 bytes source/img/icon.svg | 134 --------------------------- templates/template.html | 2 +- 7 files changed, 124 insertions(+), 150 deletions(-) create mode 100644 source/blog/2015-05-05-new-blog-new-start.md create mode 100644 source/img/icon.png delete mode 100644 source/img/icon.svg diff --git a/pyblog b/pyblog index 271a4684..687d8400 100755 --- a/pyblog +++ b/pyblog @@ -2,6 +2,8 @@ """A simple blog generator with Pandoc as backend.""" +# TODO: Feed icon next to the CC icon. + import argparse import datetime import io @@ -12,6 +14,7 @@ import subprocess import sys import tempfile import time +import urllib.parse import xml.etree.ElementTree as ET import bs4 @@ -133,11 +136,6 @@ class AtomEntry(object): return ET.tostring(self.entry).decode('utf-8') -# TODO: -def new_post(): - pass - - def generate_index(feed): """Generate index.html from index.md and a TOC.""" @@ -252,7 +250,7 @@ def generate_index_and_feed(): sys.stderr.write("wrote atom.xml\n") -def generate(fresh=False): +def generate_blog(fresh=False): """Generate the blog in BUILDDIR. Parameters @@ -344,6 +342,55 @@ def generate(fresh=False): return failed_builds +def generate(args): + """Wrapper for generate_blog(fresh=False).""" + exit(generate_blog(fresh=False)) + + +def regenerate(args): + """Wrapper for generate_blog(fresh=True).""" + exit(generate_blog(fresh=True)) + + +def sanitize(string): + """Sanitize string (title) for URI consumption.""" + if isinstance(string, bytes): + string = string.decode('utf-8') + # to lowercase + string = string.lower() + # strip all non-word, non-hyphen and non-whitespace characters + string = re.sub(r"[^\w\s-]", "", string) + # replace consecutive whitespaces with a single hyphen + string = re.sub(r"\s+", "-", string) + # percent encode the result + return urllib.parse.quote(string) + + +def new_post(args): + title = args.title + date = datetime.datetime.fromtimestamp(round(time.time()), + dateutil.tz.tzlocal()) + filename_date = date.strftime("%Y-%m-%d") + iso_date = date.isoformat() + display_date = "%s %d, %d" % (date.strftime("%B"), date.day, date.year) + title_sanitized = sanitize(title) + filename = "%s-%s.md" % (filename_date, title_sanitized) + postdir = os.path.join(SOURCEDIR, "blog") + fullpath = os.path.join(postdir, filename) + if not os.path.isdir(postdir): + if os.path.exists(postdir): + os.remove(postdir) + os.mkdir(postdir, mode=0o755) + with open(fullpath, 'w', encoding='utf-8') as fd: + fd.write("---\n") + fd.write('title: "%s"\n' % title) + fd.write("date: %s\n" % iso_date) + fd.write("date-display: %s\n" % display_date) + fd.write("---\n") + sys.stderr.write("New post created in:\n") + print(fullpath) + + # TODO: def deploy(): pass @@ -363,15 +410,26 @@ def main(): """CLI interface.""" description = "Simple blog generator in Python with Pandoc as backend." parser = argparse.ArgumentParser(description=description) - parser.add_argument('action', choices=[ - 'generate', 'regenerate', - ]) - args = parser.parse_args() + subparsers = parser.add_subparsers() + + parser_generate = subparsers.add_parser( + "generate", aliases=["g", "gen"], + description="Generate new or changed objects.") + parser_generate.set_defaults(func=generate) - if args.action == 'generate': - exit(generate(fresh=False)) - elif args.action == 'regenerate': - exit(generate(fresh=True)) + parser_regenerate = subparsers.add_parser( + "regenerate", aliases=["r", "regen"], + description="Regenerate the entire blog afresh.") + parser_regenerate.set_defaults(func=regenerate) + + parser_new_post = subparsers.add_parser( + "new_post", aliases=["n", "new"], + description="Create a new post with metadata pre-filled.") + parser_new_post.add_argument("title", help="title of the new post") + parser_new_post.set_defaults(func=new_post) + + args = parser.parse_args() + exit(args.func(args)) if __name__ == '__main__': diff --git a/source/blog/2015-05-05-new-blog-new-start.md b/source/blog/2015-05-05-new-blog-new-start.md new file mode 100644 index 00000000..4fcdf0cb --- /dev/null +++ b/source/blog/2015-05-05-new-blog-new-start.md @@ -0,0 +1,42 @@ +--- +title: "New blog, new start" +date: 2015-05-05T02:42:44-07:00 +date-display: May 5, 2015 +--- +Octopress has been serving me for the past six months, during which even Octopress itself underwent major changes — in fact, [Octopress 3.0.0](https://github.com/octopress/octopress/releases/tag/v3.0.0) was only released 3 days ago, which I never got to try. Anyway, Octopress's heavily colored interface grew old on me fairly quickly. I'm especially unhappy with the inline `` tag, which is always wrapped in a white box and stands out too much (worse still, there's no visual difference when such a `` tag is placed inside an `` tag). Since I use inline code/verbatim a lot, many of my articles were littered with arbitrary boxes everywhere. + +![Farewell, Octopress.](http://i.imgur.com/hxfSnOk.png) + +Apparently I need something simpler. Because + +> Simplicity is the ultimate sophistication. + +But how? Simiplicity 101: get rid of the "platform". There's no reason why I need a blogging platform like Jekyll (let alone the WordPress monster). When I initially switched to Octopress, I thought code highlighting was something fancy that I need heavy machinery to achieve, but it turned out that Pandoc is battery-included when it comes to syntax highting,[^pandoc] so all I need is to specify a highlight style, e.g., Pygments: + +[^pandoc]: Well, Pandoc is heavy-machinery, but it's both generic and self-contained, unlike a specialized blogging platform. + +``` +pandoc input.md --highlight-style=pygments --template template.html --output output.html +``` + +That's it. Write the Markdown, compile with Pandoc, instantly awesome. So the HTML posts are there (assuming the HTML template is written, which is not hard to kick off). + +The rest of the job is to design the stylesheets and compile the posts into a coherent blog — basically, generate an index. I was able to realize both in several hours. For the former task, I borrowed a lot from [mort.ninja](http://mort.ninja/) by [Mort Yao](https://github.com/soimort). Interestingly, we were born in the same city (Nanjing, China), and I benefit from at least two of his open source projects: [you-get](https://github.com/soimort/you-get) and [translate-shell](https://github.com/soimort/translate-shell). The latter task is more interesting but also not hard. I'm rolling my own toolchain in Python, which you can find in [`pyblog`](https://github.com/zmwangx/zmwangx.github.io/blob/source/pyblog). In fact, the complete source of this blog (down to how image assets are generated) are in the [`source` branch](https://github.com/zmwangx/zmwangx.github.io/tree/source) of my GitHub Pages repo, so you may take a look if you're interested. `pyblog` is highly specialized[^pyblog] and is still a work in progress at the time of writing, but it's already well capable of generating the blog — currently missing are auto gen-deploy and preview (with auto-update), which will also come soon. + +[^pyblog]: Which is fine since I don't expect anyone else to use it, anyway. + +By the way, the most annoying thing in the development process was working with XML and generating [the Atom feed](/atom.xml). Standard library `xml.etree.ElementTree` doesn't support the `![CDATA[` tag, and in the end I had to hack [library internals](https://github.com/zmwangx/zmwangx.github.io/blob/source/pyblog#L34-L54), which is likely to break in future versions. Remember the quotes? + +> XML is a classic political compromise: it balances the needs of man and machine by being equally unreadable to both. + +> XML combines the efficiency of text files with the readability of binary files. + +Sigh. + +Anyway, here is my new shiny blog. + +![Welcome to the completely revamped dl? cmplnts?](http://i.imgur.com/VS5f9eJ.png) + +It looks ten times better than Octopress, and ever builds much faster than Octopress[^speed]. As a bonus, the codebase is so small that it's super trivial to hack (no, not *that* hack). + +[^speed]: I have the impression that a complete build of all posts (about fifty of them) with `pyblog` is faster than regenerating for a single modified post in Octopress. That's in the context of absolutely no categories; when you have a dozen or more categories, Octopress slows down to a halt. diff --git a/source/css/theme.css b/source/css/theme.css index f125cc03..4fe7a1ff 100644 --- a/source/css/theme.css +++ b/source/css/theme.css @@ -64,6 +64,14 @@ blockquote { font-style: italic; } +div.footnotes { + font-size: 10pt; +} + +div.footnotes code { + font-size: 9.5pt; +} + img { display: block; max-width: 100%; diff --git a/source/img/README.rst b/source/img/README.rst index cb7a633c..be3eabf7 100644 --- a/source/img/README.rst +++ b/source/img/README.rst @@ -2,7 +2,7 @@ The icon and favicon files are generated via the following commands: :: cd source/img xelatex icon.tex - convert icon.pdf icon.svg + convert icon.pdf -quality 400 -resize 100x100 icon.png for size in 16 32 48 144 152; do convert icon.pdf -density 400 -resize ${size}x${size} favicon-${size}.png; done optipng favicon-16.png favicon-32.png favicon-48.png favicon-144.png favicon-152.png convert favicon-16.png favicon-32.png favicon-48.png ../favicon.ico diff --git a/source/img/icon.png b/source/img/icon.png new file mode 100644 index 00000000..5f1f894b Binary files /dev/null and b/source/img/icon.png differ diff --git a/source/img/icon.svg b/source/img/icon.svg deleted file mode 100644 index e74fd042..00000000 --- a/source/img/icon.svg +++ /dev/null @@ -1,134 +0,0 @@ - - - - diff --git a/templates/template.html b/templates/template.html index ba826be1..de507642 100644 --- a/templates/template.html +++ b/templates/template.html @@ -36,7 +36,7 @@ $endfor$