Refactor site articles

This commit is contained in:
Fred Pauchet 2023-01-09 20:22:21 +01:00
parent d991c17cac
commit e577d67b16
3 changed files with 76 additions and 37 deletions

View File

@ -4,7 +4,7 @@ import os
import shutil import shutil
import tempfile import tempfile
from .models import Article, Section, Site from jack.models import Article, Section, Site
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
@ -17,24 +17,20 @@ def generate_site(input_path):
LOGGER.info("Processing static content to {}".format(root_directory)) LOGGER.info("Processing static content to {}".format(root_directory))
site = Site(None) site = Site("Site name")
for root, dirs, files in os.walk(root_directory): for root, dirs, files in os.walk(root_directory):
base_name = root.replace(root_directory, "") base_name = root.replace(root_directory, "")
categories = [x for x in base_name.split(os.sep) if x] if "index.md" in files:
if "_index.md" in files:
section = Section(categories[-1])
elif "index.md" in files:
with open(os.path.join(root, "index.md")) as md_file: with open(os.path.join(root, "index.md")) as md_file:
content = md_file.read() content = md_file.read()
article = site.add(content) article = Article(content, base_name)
article.write(os.path.join(root, "index.html")) article.write(root)
else: else:
LOGGER.warning( LOGGER.warning(
"{}: No `index.md` or `_index.md` files found in this directory. You might want to add one.".format( "{}: No `index.md` or `_index.md` files found in this directory.".format(
root root
) )
) )

View File

@ -11,14 +11,16 @@ LOGGER = logging.getLogger(__name__)
def extract_metadata_from_content(content): def extract_metadata_from_content(content):
BLOCK_RE = re.compile(r'^-{3}[ \t]*\n(.*?\n)(?:\.{3}|-{3})[ \t]*\n', re.UNICODE|re.DOTALL) BLOCK_RE = re.compile(
r"^-{3}[ \t]*\n(.*?\n)(?:\.{3}|-{3})[ \t]*\n", re.UNICODE | re.DOTALL
)
metadata = {} metadata = {}
if (match := BLOCK_RE.match(content)): if match := BLOCK_RE.match(content):
try: try:
metadata = yaml.safe_load(match.group(1)) metadata = yaml.safe_load(match.group(1))
content = content[match.end():].lstrip('\n') content = content[match.end() :].lstrip("\n")
except Exception as exc: except Exception as exc:
LOGGER.warning("Unable to extract metadata: {}".format(exc)) LOGGER.warning("Unable to extract metadata: {}".format(exc))
@ -26,20 +28,24 @@ def extract_metadata_from_content(content):
class Article: class Article:
"""An article is composed by a content, associated to facultative tags and a category """An article is composed by a content, associated to facultative tags and a category"""
""" def __init__(self, file_content: str, relative_file_path: str):
def __init__(self, file_content: str, file_name: str, categories: list): self.meta, self.content = extract_metadata_from_content(file_content)
self.meta, self.content = extract_metadata_from_content(file_content)
self.title = self.meta.get("title") self.title = self.meta.get("title")
self.description = self.meta.get("description") self.description = self.meta.get("description")
self.tags = self.meta.get("tags", []) self.tags = self.meta.get("tags", [])
self.file_name = file_name self.relative_file_path = relative_file_path
if self.relative_file_path:
self.sections = categories = [x for x in relative_file_path.split(os.sep) if x]
else:
self.sections = []
try: try:
self.published_date = datetime.strptime(file_name[0:10], "%Y-%m-%d") self.published_date = datetime.strptime(self.sections[-1][0:10], "%Y-%m-%d")
except TypeError: except (IndexError, TypeError, ValueError):
self.published_date = None self.published_date = None
self.categories = categories
md = markdown.Markdown(extensions=["fenced_code"]) md = markdown.Markdown(extensions=["fenced_code"])
self.html = md.convert(self.content) self.html = md.convert(self.content)
@ -47,8 +53,10 @@ class Article:
def to_prose(self): def to_prose(self):
return self.html return self.html
def write(self, output_path): def write(self, root_output_path):
with open(output_path, "w") as output_file: with open(
os.path.join(root_output_path, self.relative_file_path, "index.html"), "w"
) as output_file:
output_file.write(self.to_prose()) output_file.write(self.to_prose())
@ -58,6 +66,7 @@ class Section:
self.path = path self.path = path
self.parent = None self.parent = None
self.sections = {} self.sections = {}
self.articles = []
def add(self, section): def add(self, section):
if section.key not in self.sections.keys(): if section.key not in self.sections.keys():
@ -67,24 +76,40 @@ class Section:
return self.sections[section.key] return self.sections[section.key]
class Tag:
def __init__(self, name):
self.name = name
self.articles = []
def write(self, output_path):
absolute_output_path = os.path.join(output_path, "tags", self.name)
os.mkdir(absolute_output_path)
with open(os.path.join(absolute_output_path, "index.html"), "w") as html_file:
html_file.write("""<html><body><p>Test</p></body></html>""")
def __eq__(self, o):
if isinstance(o, type(Tag)) and o.name == self.name:
return True
return False
class Site: class Site:
"""A site contains articles, categories and all related data. """A site contains articles, categories and all related data."""
"""
def __init__(self, root_directory: str): def __init__(self, root_directory: str):
self.root_directory = root_directory self.root_directory = root_directory
self.articles = [] self.articles = []
self.sections = {} self.sections = {}
self.tags = {} self.tags = {}
def add(self, file_content: str): def add(self, article: Article):
"""Add a new article to the current site """Add a new article to the current site
Returns: Returns:
The newly created article The newly created article
""" """
article = Article(file_content, None, None)
self.articles.append(article) self.articles.append(article)
for tag in article.tags: for tag in article.tags:
@ -93,9 +118,21 @@ class Site:
return article return article
def add_section(self, section: Section):
self.sections.setdefault(section.key, section)
self.sections[section.key].articles.extend(section.articles)
def write(self): def write(self):
LOGGER.info("Writing site tags") LOGGER.info("Writing site articles")
... for article in self.articles:
article.write(self.root_directory)
LOGGER.info("Writing site categories") LOGGER.info("Writing site categories")
... for section in self.sections:
print(len(self.articles)) section.write(self.root_directory)
LOGGER.info("Writing site tags")
for tag in self.tags:
tag.write(self.root_directory)
print(len(self.articles))

View File

@ -9,6 +9,7 @@ tags:
- python - python
- dev - dev
- code - code
writers: ["Ken Follet", "Gilles Legardinier"]
--- ---
This is the content This is the content
@ -21,27 +22,31 @@ def this_is_a_python_function():
""" """
def test_article_metadata(): def test_article_metadata():
article = Article(content, None, None) article = Article(content, None)
assert article.title == "This is a test article" assert article.title == "This is a test article"
assert article.description == "Some fancy description" assert article.description == "Some fancy description"
assert article.tags == ["python", "dev", "code"] assert article.tags == ["python", "dev", "code"]
def test_article_content(): def test_article_content():
article = Article(content, None, None) article = Article(content, None)
assert "title" not in article.content assert "title" not in article.content
def test_article_published_date(): def test_article_published_date():
article = Article(content, None, None) article = Article(content, None)
assert article.published_date is None assert article.published_date is None
def test_article_fenced_code(): def test_article_fenced_code():
article = Article(content, None, None) article = Article(content, None)
assert """<pre><code class="language-python">""" in article.to_prose() assert """<pre><code class="language-python">""" in article.to_prose()
def test_sections():
article = Article(content, "a/b/c")
def test_section_add(): def test_section_add():
parent = Section("dev") parent = Section("dev")
child = Section("code") child = Section("code")
@ -64,7 +69,8 @@ def test_add_existing_section():
def test_site_append_article(): def test_site_append_article():
site = Site(".") site = Site(".")
article = site.add(content) article = Article(content, None)
site.add(article)
assert article in site.articles assert article in site.articles
assert "python" in site.tags assert "python" in site.tags