91 lines
2.4 KiB
Python
91 lines
2.4 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
|
|
|
|
|
|
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
|