Parse content files twice – for gemini and www with different 'mode' variable (see NOTES.md). Fixed bug (in abs2rel) causing lack of link labels. Few other minor fixes.

This commit is contained in:
faildev_mode 2023-07-14 15:05:49 +02:00
parent b52648c5e7
commit 35a7c14c1a
No known key found for this signature in database
GPG Key ID: 70845C70C0F5E205
3 changed files with 92 additions and 52 deletions

View File

@ -2,9 +2,9 @@ build.py
# Configs # Configs
* **\[defaults\]**  default frontmatter fields values (i.e. `author=faildev_mode`) * **\[defaults\]** default frontmatter fields values (i.e. `author=faildev_mode`)
* **\[variables\]** project-wide variables (i.e. `root=rawtext.club/~faildev_mode`) * **\[variables\]** project-wide variables (i.e. `root=rawtext.club/~faildev_mode`)
* **\[variables.gemini\]**  project-wide variables gemini-exclusive * **\[variables.gemini\]** project-wide variables gemini-exclusive
* **\[variables.www\]** project-wide variables www-exclusive * **\[variables.www\]** project-wide variables www-exclusive
* **\[redirections\]** redirection table (i.e. `youtube.com=invidious.citizen4.eu`) * **\[redirections\]** redirection table (i.e. `youtube.com=invidious.citizen4.eu`)
* **\[templates\]** template routing table (i.e. `articles/*.gmi=articles`) * **\[templates\]** template routing table (i.e. `articles/*.gmi=articles`)
@ -32,7 +32,7 @@ for path in content_files:
if item.mode == 'www' or not item.mode: if item.mode == 'www' or not item.mode:
content = evaluate(item.content, {mode='www'}) content = evaluate(item.content, {mode='www'})
content = evaluate(item.template, {mode='www', item=item}) content = evaluate(item.template, {mode='www', item=item})
content = gemini2html(content) content = gemtext2html(content)
content = evaluate(item.html_template, {item=item}) content = evaluate(item.html_template, {item=item})
save_this(f'html/{item.location}.html', content) save_this(f'html/{item.location}.html', content)
``` ```

View File

@ -12,7 +12,7 @@ from functools import partial
import apis # from itself import apis # from itself
import traceback import traceback
from item import Item # from itself from item import Item # from itself
from files import read_this, save_this, link_this, scan_dir # from itself from files import save_this, link_this, scan_dir # from itself
from config import config # from itself from config import config # from itself
def template_for(path: str) -> str: def template_for(path: str) -> str:
@ -28,9 +28,8 @@ def template_for(path: str) -> str:
for pattern in config['templates'].keys(): for pattern in config['templates'].keys():
if fnmatch(path, pattern): if fnmatch(path, pattern):
template = config['templates'][pattern] template = config['templates'][pattern]
template_data = read_this('templates/'+template)
return template_data return template
def namespace_from(*extensions) -> dict: def namespace_from(*extensions) -> dict:
"""Generates global namespace for evaluation derrived from provided """Generates global namespace for evaluation derrived from provided
@ -167,9 +166,9 @@ def gemtext2html(gemtext: str) -> str:
def abs2rel(match: re.Match, path: str) -> str: def abs2rel(match: re.Match, path: str) -> str:
"""Callable for re.sub, converts absolute link to relative to current document (path argument).""" """Callable for re.sub, converts absolute link to relative to current document (path argument)."""
url = os.path.relpath(match.group(1), start=os.path.dirname(path)) url = os.path.relpath(match.group(2), start=os.path.dirname(path))
text = match.group(2).strip() if len(match.groups()) > 2 else url print(' M', url)
return f'=> {url} {text}' return match.group(1) + url
if __name__ == '__main__': if __name__ == '__main__':
os.chdir(sys.path[0]) os.chdir(sys.path[0])
@ -201,51 +200,92 @@ if __name__ == '__main__':
item = Item(path) item = Item(path)
# parse content # parsing in gemini mode
namespace = namespace_from( if not 'mode' in item or item.mode == 'gemini':
{'path': path}, # preparing namespace
apis.Content,
config['variables'],
item.frontmatter_data
)
content = evaluate_this(item.content, namespace)
# load template
if template := template_for(path):
# apply template
namespace = namespace_from( namespace = namespace_from(
{'path': path}, {'path': path},
apis.Content, apis.Content,
config['variables'], config['variables'],
config['variables.gemini'],
item.frontmatter_data, item.frontmatter_data,
{'content': content} {'mode': 'gemini'}
) )
content = evaluate_this(template, namespace) # evaluation
content = evaluate_this(item.content, namespace)
# do redirections # determining and applying template (optional)
if 'redirections' in config: if template := template_for(path):
content = re.sub(r'(https?://)([-\w]+[-\w.]*)(/\S*)?', partial( tpl_item = Item(template, prefix='templates/')
redirect, if not 'mode' in tpl_item or tpl_item.mode == 'gemini':
domains=dict(config['redirections']) namespace = namespace_from(
), content) {'path': path},
apis.Content,
# convert absolute links to relative config['variables'],
if path.endswith('.gmi'): config['variables.gemini'],
content = re.sub(r'=>\s+/(\S+)(\s+.*)?', partial( item.frontmatter_data,
abs2rel, path=path {'mode': 'gemini', 'content': content}
), content) )
content = evaluate_this(tpl_item.content, namespace)
# produce HTML version # do redirections (http/https only!)
html_path = os.path.splitext(path)[0]+'.html' if 'redirections' in config:
html_content = gemtext2html(content) content = re.sub(r'(https?://)([-\w]+[-\w.]*)(/\S*)?', partial(
# determine which template to use redirect,
if template := template_for(html_path): domains=dict(config['redirections'])
... ), content)
save_this('../html/'+html_path, html_content)
# convert absolute links to relative (gemtext only!)
if path.endswith('.gmi'):
content = re.sub(r'(=>[ \t]+)/(\S+)', partial(
abs2rel, path=path
), content)
# save results
save_this('../'+path, content)
else:
print(' ! skipped for gemini')
# TODO: delete from gemini output
# save results # parsing in www mode
save_this('../'+path, content) if not 'mode' in item or item.mode == 'www':
namespace = namespace_from(
if not path.endswith('.gmi'): {'path': path},
link_this('../'+path, '../html/'+path) apis.Content,
config['variables'],
config['variables.www'],
item.frontmatter_data,
{'mode': 'www'}
)
content = evaluate_this(item.content, namespace)
if template := template_for(path):
tpl_item = Item(template, prefix='templates/')
if not 'mode' in tpl_item or tpl_item.mode == 'www':
namespace = namespace_from(
{'path': path},
apis.Content,
config['variables'],
config['variables.www'],
item.frontmatter_data,
{'mode': 'www', 'content': content}
)
content = evaluate_this(tpl_item.content, namespace)
# convert to html
html_path = path
if path.endswith('.gmi'):
content = gemtext2html(content)
html_path = os.path.splitext(path)[0]+'.html'
if html_path.endswith('.html'):
# TODO: html template
if template := template_for(html_path):
...
# TODO: redirections, path conversion
save_this('../html/'+html_path, content)
else:
print(' ! skipped for www')
# TODO: delete from www output

View File

@ -14,13 +14,13 @@ class Item(AttrDict):
source = None source = None
author = None author = None
def __init__(self, path: str): def __init__(self, path: str, prefix: str = 'content/'):
# initialize parent # initialize parent
super().__init__() super().__init__()
self.path = path self.path, self.prefix = path, prefix
frontmatter_data, content = frontmatter.parse(read_this('content/'+path)) frontmatter_data, content = frontmatter.parse(read_this(prefix + path))
self.content = content self.content = content
self.frontmatter_data = frontmatter_data self.frontmatter_data = frontmatter_data