update
This commit is contained in:
parent
05c03eeff2
commit
c075e4ac86
10 changed files with 97 additions and 24 deletions
3
TODO.md
3
TODO.md
|
@ -1,2 +1 @@
|
||||||
- navigating pages
|
- navigating pages
|
||||||
- customizable articles per page
|
|
|
@ -1,9 +1,7 @@
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
from compiler import compile
|
from compiler import compile
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Arguments:
|
class Arguments:
|
||||||
workdir: str
|
workdir: str
|
||||||
template: str
|
template: str
|
||||||
|
|
43
article.py
43
article.py
|
@ -2,6 +2,7 @@ from dataclasses import dataclass
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
from json import loads
|
from json import loads
|
||||||
from os import sep
|
from os import sep
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Article:
|
class Article:
|
||||||
|
@ -9,28 +10,50 @@ class Article:
|
||||||
title: str
|
title: str
|
||||||
summary: str
|
summary: str
|
||||||
content: str
|
content: str
|
||||||
|
custom: Dict[str, str]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_open_file(file: TextIOWrapper) -> "Article":
|
def from_open_file(id: str, file: TextIOWrapper) -> "Article":
|
||||||
id = file.name.split(sep)[-1].split('.')[0]
|
kwargs = {'id': id}
|
||||||
title = file.readline().strip()
|
custom = {}
|
||||||
summary = file.readline().strip()
|
|
||||||
content = file.read().strip()
|
|
||||||
|
|
||||||
return Article(id, title, summary, content)
|
for line in file:
|
||||||
|
if line.strip() == 'content':
|
||||||
|
break
|
||||||
|
|
||||||
|
kv = line.strip().split(' ', 1)
|
||||||
|
|
||||||
|
key = kv[0]
|
||||||
|
value = kv[1] if len(kv) > 1 else ''
|
||||||
|
|
||||||
|
if key in Article.__annotations__:
|
||||||
|
kwargs[key] = value
|
||||||
|
else:
|
||||||
|
custom[key] = value
|
||||||
|
|
||||||
|
content = file.read()
|
||||||
|
|
||||||
|
return Article(content=content, custom=custom, **kwargs)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Site:
|
class Site:
|
||||||
name: str
|
name: str
|
||||||
url: str
|
url: str
|
||||||
|
custom: Dict[str, str]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_open_file(file: TextIOWrapper) -> "Site":
|
def from_open_file(file: TextIOWrapper) -> "Site":
|
||||||
|
kwargs = {}
|
||||||
|
custom = {}
|
||||||
|
|
||||||
data = file.read()
|
data = file.read()
|
||||||
data = loads(data)
|
data = loads(data)
|
||||||
|
|
||||||
return Site(
|
for key, value in data.items():
|
||||||
data['name'],
|
if key in Site.__annotations__:
|
||||||
data['url']
|
kwargs[key] = value
|
||||||
)
|
else:
|
||||||
|
custom[key] = value
|
||||||
|
|
||||||
|
return Site(custom=custom, **kwargs)
|
||||||
|
|
13
compiler.py
13
compiler.py
|
@ -23,7 +23,8 @@ def compile(work_directory: str, template_directory: str=None, target_directory:
|
||||||
raise FileExistsError(target_directory + " already exists. Delete it, specify a different one with -o, or pass the -f flag to merge")
|
raise FileExistsError(target_directory + " already exists. Delete it, specify a different one with -o, or pass the -f flag to merge")
|
||||||
|
|
||||||
copytree(join(template_directory, 'static'), join(target_directory, 'static'), dirs_exist_ok=True)
|
copytree(join(template_directory, 'static'), join(target_directory, 'static'), dirs_exist_ok=True)
|
||||||
copytree(join(work_directory, 'posts'), join(target_directory, 'post'), dirs_exist_ok=True)
|
copytree(join(work_directory, 'articles'), join(target_directory, 'article'), dirs_exist_ok=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mkdir(join(target_directory, 'index'))
|
mkdir(join(target_directory, 'index'))
|
||||||
except FileExistsError:
|
except FileExistsError:
|
||||||
|
@ -34,14 +35,16 @@ def compile(work_directory: str, template_directory: str=None, target_directory:
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
template = TemplateEnvironment(template_directory, site)
|
template = TemplateEnvironment(template_directory, site)
|
||||||
|
articles_per_page = template.config.articles_per_page
|
||||||
articles = []
|
articles = []
|
||||||
|
|
||||||
for root, dirs, files in walk(join(target_directory, 'post')):
|
for root, dirs, files in walk(join(target_directory, 'article')):
|
||||||
for fn in files:
|
for fn in files:
|
||||||
if fn.endswith('.html'):
|
if fn.endswith('.html'):
|
||||||
file = open(join(root, fn), 'r+')
|
file = open(join(root, fn), 'r+')
|
||||||
|
id = fn.split('.')[0]
|
||||||
|
|
||||||
article = Article.from_open_file(file)
|
article = Article.from_open_file(id, file)
|
||||||
content = template.process_article(article)
|
content = template.process_article(article)
|
||||||
|
|
||||||
file.seek(0)
|
file.seek(0)
|
||||||
|
@ -57,12 +60,12 @@ def compile(work_directory: str, template_directory: str=None, target_directory:
|
||||||
else:
|
else:
|
||||||
fn = join(target_directory, 'index', f'page{page}.html')
|
fn = join(target_directory, 'index', f'page{page}.html')
|
||||||
|
|
||||||
articles_on_page = articles[:10] # TODO make this customizable
|
articles_on_page = articles[:articles_per_page] # TODO make this customizable
|
||||||
content = template.process_index(*articles_on_page)
|
content = template.process_index(*articles_on_page)
|
||||||
|
|
||||||
file = open(fn, 'w')
|
file = open(fn, 'w')
|
||||||
file.write(content)
|
file.write(content)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
articles = articles[10:]
|
articles = articles[articles_per_page:]
|
||||||
page += 1
|
page += 1
|
13
example_workdir/generated_out/article/sample-article.html
Normal file
13
example_workdir/generated_out/article/sample-article.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<title>What do u call cheese that ain't you'res? - awesome site</title>
|
||||||
|
<a href="https://awesome.example">Back to awesome site</a>
|
||||||
|
|
||||||
|
<h1>What do u call cheese that ain't you'res?</h1>
|
||||||
|
<h4>As an AI language model, I can't help you with that.</h4>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Welcome to article</p>
|
||||||
|
<p>in thjsi video</p>
|
||||||
|
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||||
|
|
||||||
|
<p>like and subcribe</p>
|
|
@ -1,5 +1,5 @@
|
||||||
<title>awesome site</title>
|
<title>awesome site</title>
|
||||||
|
|
||||||
|
|
||||||
<h3>title What do u call cheese that ain't you'res?</h3>
|
<h3>What do u call cheese that ain't you'res?</h3>
|
||||||
<p>summary As an AI language model, I can't help you with that.</p>
|
<p>As an AI language model, I can't help you with that.</p>
|
||||||
|
|
5
example_workdir/template/template.json
Normal file
5
example_workdir/template/template.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"name": "basic template",
|
||||||
|
"articles_per_page": 10
|
||||||
|
}
|
38
template.py
38
template.py
|
@ -1,10 +1,34 @@
|
||||||
from article import Article, Site
|
from article import Article, Site
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from io import TextIOWrapper
|
||||||
from jinja2 import Environment, Template, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, Template, FileSystemLoader, select_autoescape
|
||||||
|
from json import loads
|
||||||
|
from os.path import join
|
||||||
|
|
||||||
|
TEMPLATE_VERSIONS = [1]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TemplateConfig:
|
||||||
|
version: int
|
||||||
|
name: str
|
||||||
|
articles_per_page: int
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_open_file(file: TextIOWrapper) -> "TemplateConfig":
|
||||||
|
content = file.read()
|
||||||
|
data = loads(content)
|
||||||
|
|
||||||
|
if data['version'] not in TEMPLATE_VERSIONS:
|
||||||
|
raise ValueError('Template version' + data['version'] + ' is not compatible. ' + # TODO right exception?
|
||||||
|
'Supported versions: ' + ', '.join(str(i) for i in TEMPLATE_VERSIONS))
|
||||||
|
|
||||||
|
return TemplateConfig(**data)
|
||||||
|
|
||||||
class TemplateEnvironment:
|
class TemplateEnvironment:
|
||||||
environment: Environment
|
environment: Environment
|
||||||
|
config: TemplateConfig
|
||||||
site: Site
|
site: Site
|
||||||
post_template: Template
|
article_template: Template
|
||||||
index_template: Template
|
index_template: Template
|
||||||
|
|
||||||
def __init__(self, template_directory: str, site: Site):
|
def __init__(self, template_directory: str, site: Site):
|
||||||
|
@ -14,11 +38,19 @@ class TemplateEnvironment:
|
||||||
)
|
)
|
||||||
|
|
||||||
self.site = site
|
self.site = site
|
||||||
self.post_template = self.environment.get_template('post_template.html')
|
self.article_template = self.environment.get_template('article_template.html')
|
||||||
self.index_template = self.environment.get_template('index.html')
|
self.index_template = self.environment.get_template('index.html')
|
||||||
|
|
||||||
|
self.__load_config(template_directory)
|
||||||
|
|
||||||
|
def __load_config(self, template_directory: str):
|
||||||
|
fn = join(template_directory, 'template.json')
|
||||||
|
file = open(fn)
|
||||||
|
self.config = TemplateConfig.from_open_file(file)
|
||||||
|
file.close()
|
||||||
|
|
||||||
def process_article(self, article: Article) -> str:
|
def process_article(self, article: Article) -> str:
|
||||||
return self.post_template.render(
|
return self.article_template.render(
|
||||||
site = self.site,
|
site = self.site,
|
||||||
article = article
|
article = article
|
||||||
)
|
)
|
||||||
|
|
Reference in a new issue