184 lines
4.6 KiB
Python
Executable file
184 lines
4.6 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
"""
|
|
CLI command to manage my site
|
|
|
|
Imports posts from Posty, builds YAML files into JSON blobs, etc.
|
|
|
|
This may be the start of Posty 2.0, who knows.
|
|
"""
|
|
|
|
import click
|
|
from dateutil import parser as date_parser
|
|
import json
|
|
import markdown
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import yaml
|
|
|
|
|
|
@click.group()
|
|
def cli():
|
|
pass
|
|
|
|
|
|
@cli.command()
|
|
def init():
|
|
"""
|
|
Initialize a site in the current directory
|
|
"""
|
|
for directory in ('_media', '_pages', '_posts'):
|
|
if not os.path.exists(directory):
|
|
os.mkdir(directory)
|
|
|
|
|
|
@cli.command()
|
|
@click.option(
|
|
'--path',
|
|
help='Path to output JSON file',
|
|
default='site.json',
|
|
show_default=True
|
|
)
|
|
def build(path):
|
|
"""
|
|
Build posts and pages JSON files
|
|
|
|
Takes all of the YAML in _pages and _posts, combines them into JSON blobs
|
|
and writes them out to disk.
|
|
"""
|
|
if not all([os.path.exists('_pages'), os.path.exists('_posts')]):
|
|
raise click.UsageError('You must run `init` first!')
|
|
|
|
tags = set()
|
|
blob = {
|
|
'pages': [],
|
|
'posts': [],
|
|
'tags': [],
|
|
}
|
|
|
|
pages = []
|
|
for filename in os.listdir('_pages'):
|
|
contents = open(os.path.join('_pages', filename)).read()
|
|
_, meta_yaml, body = contents.split("---\n")
|
|
page = yaml.load(meta_yaml)
|
|
|
|
# page['body'] = render(body.strip())
|
|
page['body'] = body.strip()
|
|
page.setdefault('parent')
|
|
|
|
pages.append(page)
|
|
blob['pages'] = sorted(pages, key=lambda x: x['title'].lower())
|
|
|
|
posts = []
|
|
for filename in os.listdir('_posts'):
|
|
contents = open(os.path.join('_posts', filename)).read()
|
|
parts = contents.split("---\n")
|
|
|
|
post = yaml.load(parts[0])
|
|
post['date'] = post['date'].isoformat()
|
|
post.setdefault('tags', [])
|
|
|
|
if len(parts[1:]) == 1:
|
|
post['blurb'] = parts[1]
|
|
post['body'] = parts[1]
|
|
elif len(parts[1:]) == 2:
|
|
post['blurb'] = parts[1]
|
|
post['body'] = "\n".join(parts[1:])
|
|
else:
|
|
raise click.UsageError("Got too many YAML documents in {}".format(filename))
|
|
|
|
# post['blurb'] = render(post['blurb'].strip())
|
|
# post['body'] = render(post['body'].strip())
|
|
post['blurb'] = post['blurb'].strip()
|
|
post['body'] = post['body'].strip()
|
|
|
|
for tag in post['tags']:
|
|
tags.add(tag)
|
|
|
|
posts.append(post)
|
|
blob['posts'] = sorted(posts, key=lambda x: x['date'], reverse=True)
|
|
|
|
blob['tags'] = list(tags)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(json.dumps(blob))
|
|
|
|
|
|
@cli.command()
|
|
@click.option(
|
|
'--path',
|
|
help='path to the Posty site',
|
|
required=True
|
|
)
|
|
def posty_import(path):
|
|
"""
|
|
Import posts and pages from an existing Posty 1.x site
|
|
|
|
All YAML files are read in and in the case of posts, a blurb is generated
|
|
if one doesn't already exist by singling out the first paragraph.
|
|
"""
|
|
if not all(os.path.exists('_pages'), os.path.exists('_posts')):
|
|
raise click.UsageError('You must run `init` first!')
|
|
|
|
click.echo('Importing site at {} ...'.format(path))
|
|
|
|
# Simply copy pages over, nothing special to do
|
|
for page in os.listdir(os.path.join(path, '_pages')):
|
|
orig_path = os.path.join(path, '_pages', page)
|
|
new_path = os.path.join('_pages', page)
|
|
shutil.copy(orig_path, new_path)
|
|
|
|
old_posts_path = os.path.join(path, '_posts')
|
|
for post in os.listdir(old_posts_path):
|
|
old_post = open(os.path.join(old_posts_path, post)).read()
|
|
click.echo(post)
|
|
new_post = convert_from_posty(old_post)
|
|
|
|
with open(os.path.join('_posts', post), 'w') as f:
|
|
f.write(new_post)
|
|
|
|
click.echo('Done!')
|
|
|
|
|
|
# Utility functions
|
|
def convert_from_posty(old_post):
|
|
"""
|
|
Converts an old Posty post (a string) into a new-style post with a blurb
|
|
and everything. Returns a string containing the three YAML documents.
|
|
"""
|
|
old_post = old_post.replace("\r\n", "\n")
|
|
docs = old_post.split("---\n")
|
|
new_post = ''
|
|
|
|
# Convert the metadata
|
|
meta = yaml.load(docs[1])
|
|
meta.setdefault('tags', [])
|
|
new_post += yaml.dump(meta)
|
|
|
|
# Create a blurb out of the first paragraph
|
|
body = docs[2].strip().split("\n\n")
|
|
blurb = body[0]
|
|
rest_of_post = "\n\n".join(body[1:])
|
|
|
|
new_post += "---\n"
|
|
new_post += blurb
|
|
|
|
# Drop in the rest of the post
|
|
new_post += "\n---\n"
|
|
new_post += rest_of_post
|
|
|
|
return new_post
|
|
|
|
|
|
def render(thing):
|
|
"""
|
|
Renders a specific thing using Markdown
|
|
"""
|
|
return markdown.markdown(thing, extensions=[
|
|
'markdown.extensions.fenced_code',
|
|
])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cli()
|