4.3 KiB
4.3 KiB
Title | Summary | Tags |
---|---|---|
Jouons un peu avec Jinja2 et YAML | Toi aussi, crée ton site statique en buvant un cocktail avec une main dans le dos et les pieds sur le bureau. | yaml, jinja, ssg |
Bon, et si je voulais développer mon propre générateur de sites statiques? Pas que ce soit nécessaire, car il y en a des dizaines de centaines de milliers (+une petite dizaine chaque jour), juste que j'en ai envie.
Les quelques idées sont les suivantes:
- Utiliser
markdown
et ses extensions officielles pour la génération de code HTML. - Passer le tout dans Pygments pour la coloration de code
- Ajouter une couche de Typogrify pour gérer quelques cas particuliers de mises en forme.
# coding: utf-8
from models import Site
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
loader=PackageLoader('grnx', 'templates'),
autoescape=select_autoescape(['html'])
)
if __name__ == "__main__":
root = Site('content')
root.serialize()
template = env.get_template('single.html')
for article in root.articles:
print(template.render(article.__dict__))
# coding: utf-8
import datetime
import json
import re
import os
import yaml
RE_HEADER = re.compile('---((.)?(\n)?)*---')
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, datetime.datetime)
or isinstance(obj, datetime.date)
else None
)
def json_handler(obj):
"""Handles the JSON object serializer.
Returns:
The iso format if the object is a date.
The __dict__ attribute for any other JSON serializable object.
Excepts:
TypeError when object is not JSON serialisable.
"""
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif obj.__dict__:
return obj.__dict__
else:
raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj)))
class Content(object):
def __init__(self, filepath):
with open(filepath, 'r') as f:
try:
file_content = f.read()
print(file_content)
regex_result = RE_HEADER.search(file_content)
if regex_result:
header = file_content[regex_result.start():regex_result.end()-3]
self.properties = yaml.load(header)
headers = self.properties
print('headers: ' + str(headers))
self.published_date = headers.pop('Date', None)
self.last_modified_date = headers.pop('LastModified', self.published_date)
self.title = headers.pop('Title', None)
self.slug = headers.pop('Slug', None)
self.path = filepath
except yaml.YAMLError as error:
print(error)
class Site(object):
"""Represents a Site object.
Args:
articles: containt all articles.
metadata: hum. I don't remember what I would store in this property.
taxonomies: the taxonomies we find for this site. Tags, categories, ...
"""
def __init__(self, current_path):
self.articles = []
self.metadata = {}
self.taxonomies = {}
for directory, dirnames, files in os.walk(current_path):
for file in files:
if file.endswith(".md"):
self.manage_article(directory, file)
def manage_article(self, directory, file):
article = Content(os.path.join(directory, file))
self.articles.append(article)
for taxonomy in article.properties:
if taxonomy not in self.taxonomies:
self.taxonomies[taxonomy] = []
# TODO: we have to get the VALUE _and_ the article slug instead of just the slug.
self.taxonomies[taxonomy].append(article.slug)
def to_json(self):
"""Serialize the content of the current structure to JSON format."""
return json.dumps(self, default=json_handler, sort_keys=True, indent=4)
def serialize(self):
"""Serialize the current files structure to index.json"""
with open('index.json', 'w') as json_serialized_file:
json_serialized_file.write(self.to_json())