jack/jack/models.py

95 lines
2.5 KiB
Python

import logging
import os
import re
from datetime import datetime
from typing import List
import markdown
import yaml
LOGGER = logging.getLogger(__name__)
def extract_metadata_from_content(content):
BLOCK_RE = re.compile(r'^-{3}[ \t]*\n(.*?\n)(?:\.{3}|-{3})[ \t]*\n', re.UNICODE|re.DOTALL)
metadata = {}
if (match := BLOCK_RE.match(content)):
try:
metadata = yaml.safe_load(match.group(1))
content = content[match.end():].lstrip('\n')
except Exception as exc:
LOGGER.warning("Unable to extract metadata: {}".format(exc))
return metadata, content
class Article:
"""An article is composed by a content, associated to facultative tags and a category
"""
def __init__(self, file_content: str, file_name: str, categories: list):
self.meta, self.content = extract_metadata_from_content(file_content)
self.title = self.meta.get("title")
self.description = self.meta.get("description")
self.tags = self.meta.get("tags")
self.file_name = file_name
try:
self.published_date = datetime.strptime(file_name[0:10], "%Y-%m-%d")
except TypeError:
self.published_date = None
self.categories = categories
md = markdown.Markdown(extensions=["fenced_code"])
self.html = md.convert(self.content)
def to_prose(self):
return self.html
def write(self, output_path):
with open(output_path, "w") as output_file:
output_file.write(self.to_prose())
class Section:
def __init__(self, key, path=None):
self.key = key
self.path = path
self.parent = None
self.sections = {}
def add(self, section):
if section.key not in self.sections.keys():
section.parent = self
self.sections[section.key] = section
return self.sections[section.key]
class Site:
"""A site contains articles, categories and all related data.
"""
def __init__(self, root_directory: str):
self.root_directory = root_directory
self.articles = []
self.sections = {}
self.tags = {}
def add(self, file_content: str):
"""Add a new article to the current site
Returns:
The newly created article
"""
article = Article(file_content, None, None)
self.articles.append(article)
for tag in article.tags:
tag_key = self.tags.setdefault(tag, [])
tag_key.append(article)
return article