Refactor site articles
This commit is contained in:
parent
d991c17cac
commit
e577d67b16
|
@ -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
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue