added syntax highlighting config

This commit is contained in:
Daniel Fichtinger 2025-06-29 23:42:35 -04:00
parent c792a6bb07
commit 3bd1eddfac
4 changed files with 58 additions and 15 deletions

View file

@ -12,7 +12,9 @@ from rich import print
class ZonaBuilder:
def __init__(
self, cli_root: Path | None = None, cli_output: Path | None = None
self,
cli_root: Path | None = None,
cli_output: Path | None = None,
):
self.layout: Layout = discover_layout(cli_root, cli_output)
self.config: ZonaConfig = ZonaConfig.from_file(
@ -37,7 +39,9 @@ class ZonaBuilder:
destination=destination,
url=str(destination.relative_to(layout.output)),
)
if path.name.endswith(".md") and not path.is_relative_to(
if path.name.endswith(
".md"
) and not path.is_relative_to(
layout.root / "content" / "static"
):
item.metadata, item.content = parse_metadata(path)
@ -52,9 +56,13 @@ class ZonaBuilder:
item.copy = False
name = destination.stem
if name == "index":
item.destination = item.destination.with_suffix(".html")
item.destination = (
item.destination.with_suffix(".html")
)
else:
relative = path.relative_to(base).with_suffix("")
relative = path.relative_to(base).with_suffix(
""
)
name = relative.stem
item.destination = (
layout.output
@ -62,9 +70,13 @@ class ZonaBuilder:
/ name
/ "index.html"
)
rel_url = item.destination.parent.relative_to(layout.output)
rel_url = item.destination.parent.relative_to(
layout.output
)
item.url = (
"" if rel_url == Path(".") else rel_url.as_posix()
""
if rel_url == Path(".")
else rel_url.as_posix()
)
items.append(item)
# print(item)
@ -74,13 +86,17 @@ class ZonaBuilder:
assert self.items
post_list: list[Item] = sorted(
[item for item in self.items if item.post],
key=lambda item: item.metadata.date if item.metadata else date.min,
key=lambda item: item.metadata.date
if item.metadata
else date.min,
reverse=True,
)
templater = Templater(
template_dir=self.layout.templates, post_list=post_list
)
self.item_map = {item.source.resolve(): item for item in self.items}
self.item_map = {
item.source.resolve(): item for item in self.items
}
# print(item_map)
for item in self.item_map.values():
dst = item.destination
@ -90,6 +106,7 @@ class ZonaBuilder:
assert item.content is not None
# parse markdown and render as html
raw_html = zmd.md_to_html(
config=self.config,
content=item.content,
resolve_links=True,
source=item.source,

View file

@ -19,15 +19,24 @@ class BlogConfig:
dir: str = "blog"
@dataclass
class HighlightingConfig:
enabled: bool = True
theme: str = "ashen"
wrap: bool = False
@dataclass
class MarkdownConfig:
image_labels: bool = True
syntax_highlighting: HighlightingConfig = field(
default_factory=HighlightingConfig
)
@dataclass
class ThemeConfig:
name: str = "default"
syntax_highlighting: bool = True
@dataclass

View file

@ -5,6 +5,7 @@ from marko.inline import Link, Image
from marko.block import FencedCode
from marko.html_renderer import HTMLRenderer
from marko.parser import Parser
from zona.config import ZonaConfig
from zona.layout import Layout
from pygments import highlight
@ -18,6 +19,7 @@ from zona.models import Item
class ZonaRenderer(HTMLRenderer):
def __init__(
self,
config: ZonaConfig | None,
resolve: bool = False,
source: Path | None = None,
layout: Layout | None = None,
@ -33,6 +35,7 @@ class ZonaRenderer(HTMLRenderer):
self.source: Path = source.resolve()
self.layout: Layout = layout
self.item_map: dict[Path, Item] = item_map
self.config: ZonaConfig | None = config
@override
def render_link(self, element: Link):
@ -80,16 +83,23 @@ class ZonaRenderer(HTMLRenderer):
@override
def render_fenced_code(self, element: FencedCode):
# code = element.children
assert self.config
config = self.config.markdown.syntax_highlighting
code = "".join(child.children for child in element.children) # type: ignore
lang = element.lang or "text"
if not config.enabled:
return f"<pre><code>{code}</code></pre>"
try:
lexer = get_lexer_by_name(lang, stripall=False)
except Exception:
lexer = TextLexer(stripall=False) # type: ignore
formatter = HtmlFormatter(style="ashen", nowrap=True, noclasses=True)
formatter = HtmlFormatter(
style=config.theme,
nowrap=not config.wrap,
noclasses=True,
)
highlighted = highlight(code, lexer, formatter) # type: ignore
return (
@ -100,18 +110,25 @@ class ZonaRenderer(HTMLRenderer):
def md_to_html(
content: str,
config: ZonaConfig | None,
resolve_links: bool = False,
source: Path | None = None,
layout: Layout | None = None,
item_map: dict[Path, Item] | None = None,
) -> str:
if resolve_links and (source is None or layout is None or item_map is None):
if resolve_links and (
source is None or layout is None or item_map is None
):
raise TypeError(
"md_to_html() missing source and ctx when resolve_links is true"
)
parser = Parser()
ast = parser.parse(content)
renderer = ZonaRenderer(
resolve_links, source, layout=layout, item_map=item_map
config,
resolve_links,
source,
layout=layout,
item_map=item_map,
)
return renderer.render(ast)

View file

@ -9,7 +9,7 @@ def get_header(template_dir: Path) -> str | None:
md_header = template_dir / "header.md"
html_header = template_dir / "header.html"
if md_header.exists():
return md_to_html(md_header.read_text())
return md_to_html(md_header.read_text(), None)
elif html_header.exists():
return html_header.read_text()
@ -18,7 +18,7 @@ def get_footer(template_dir: Path) -> str | None:
md_footer = template_dir / "footer.md"
html_footer = template_dir / "footer.html"
if md_footer.exists():
return md_to_html(md_footer.read_text())
return md_to_html(md_footer.read_text(), None)
elif html_footer.exists():
return html_footer.read_text()