added syntax highlighting config
This commit is contained in:
parent
c792a6bb07
commit
3bd1eddfac
4 changed files with 58 additions and 15 deletions
|
@ -12,7 +12,9 @@ from rich import print
|
||||||
|
|
||||||
class ZonaBuilder:
|
class ZonaBuilder:
|
||||||
def __init__(
|
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.layout: Layout = discover_layout(cli_root, cli_output)
|
||||||
self.config: ZonaConfig = ZonaConfig.from_file(
|
self.config: ZonaConfig = ZonaConfig.from_file(
|
||||||
|
@ -37,7 +39,9 @@ class ZonaBuilder:
|
||||||
destination=destination,
|
destination=destination,
|
||||||
url=str(destination.relative_to(layout.output)),
|
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"
|
layout.root / "content" / "static"
|
||||||
):
|
):
|
||||||
item.metadata, item.content = parse_metadata(path)
|
item.metadata, item.content = parse_metadata(path)
|
||||||
|
@ -52,9 +56,13 @@ class ZonaBuilder:
|
||||||
item.copy = False
|
item.copy = False
|
||||||
name = destination.stem
|
name = destination.stem
|
||||||
if name == "index":
|
if name == "index":
|
||||||
item.destination = item.destination.with_suffix(".html")
|
item.destination = (
|
||||||
|
item.destination.with_suffix(".html")
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
relative = path.relative_to(base).with_suffix("")
|
relative = path.relative_to(base).with_suffix(
|
||||||
|
""
|
||||||
|
)
|
||||||
name = relative.stem
|
name = relative.stem
|
||||||
item.destination = (
|
item.destination = (
|
||||||
layout.output
|
layout.output
|
||||||
|
@ -62,9 +70,13 @@ class ZonaBuilder:
|
||||||
/ name
|
/ name
|
||||||
/ "index.html"
|
/ "index.html"
|
||||||
)
|
)
|
||||||
rel_url = item.destination.parent.relative_to(layout.output)
|
rel_url = item.destination.parent.relative_to(
|
||||||
|
layout.output
|
||||||
|
)
|
||||||
item.url = (
|
item.url = (
|
||||||
"" if rel_url == Path(".") else rel_url.as_posix()
|
""
|
||||||
|
if rel_url == Path(".")
|
||||||
|
else rel_url.as_posix()
|
||||||
)
|
)
|
||||||
items.append(item)
|
items.append(item)
|
||||||
# print(item)
|
# print(item)
|
||||||
|
@ -74,13 +86,17 @@ class ZonaBuilder:
|
||||||
assert self.items
|
assert self.items
|
||||||
post_list: list[Item] = sorted(
|
post_list: list[Item] = sorted(
|
||||||
[item for item in self.items if item.post],
|
[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,
|
reverse=True,
|
||||||
)
|
)
|
||||||
templater = Templater(
|
templater = Templater(
|
||||||
template_dir=self.layout.templates, post_list=post_list
|
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)
|
# print(item_map)
|
||||||
for item in self.item_map.values():
|
for item in self.item_map.values():
|
||||||
dst = item.destination
|
dst = item.destination
|
||||||
|
@ -90,6 +106,7 @@ class ZonaBuilder:
|
||||||
assert item.content is not None
|
assert item.content is not None
|
||||||
# parse markdown and render as html
|
# parse markdown and render as html
|
||||||
raw_html = zmd.md_to_html(
|
raw_html = zmd.md_to_html(
|
||||||
|
config=self.config,
|
||||||
content=item.content,
|
content=item.content,
|
||||||
resolve_links=True,
|
resolve_links=True,
|
||||||
source=item.source,
|
source=item.source,
|
||||||
|
|
|
@ -19,15 +19,24 @@ class BlogConfig:
|
||||||
dir: str = "blog"
|
dir: str = "blog"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class HighlightingConfig:
|
||||||
|
enabled: bool = True
|
||||||
|
theme: str = "ashen"
|
||||||
|
wrap: bool = False
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MarkdownConfig:
|
class MarkdownConfig:
|
||||||
image_labels: bool = True
|
image_labels: bool = True
|
||||||
|
syntax_highlighting: HighlightingConfig = field(
|
||||||
|
default_factory=HighlightingConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ThemeConfig:
|
class ThemeConfig:
|
||||||
name: str = "default"
|
name: str = "default"
|
||||||
syntax_highlighting: bool = True
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -5,6 +5,7 @@ from marko.inline import Link, Image
|
||||||
from marko.block import FencedCode
|
from marko.block import FencedCode
|
||||||
from marko.html_renderer import HTMLRenderer
|
from marko.html_renderer import HTMLRenderer
|
||||||
from marko.parser import Parser
|
from marko.parser import Parser
|
||||||
|
from zona.config import ZonaConfig
|
||||||
from zona.layout import Layout
|
from zona.layout import Layout
|
||||||
|
|
||||||
from pygments import highlight
|
from pygments import highlight
|
||||||
|
@ -18,6 +19,7 @@ from zona.models import Item
|
||||||
class ZonaRenderer(HTMLRenderer):
|
class ZonaRenderer(HTMLRenderer):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
config: ZonaConfig | None,
|
||||||
resolve: bool = False,
|
resolve: bool = False,
|
||||||
source: Path | None = None,
|
source: Path | None = None,
|
||||||
layout: Layout | None = None,
|
layout: Layout | None = None,
|
||||||
|
@ -33,6 +35,7 @@ class ZonaRenderer(HTMLRenderer):
|
||||||
self.source: Path = source.resolve()
|
self.source: Path = source.resolve()
|
||||||
self.layout: Layout = layout
|
self.layout: Layout = layout
|
||||||
self.item_map: dict[Path, Item] = item_map
|
self.item_map: dict[Path, Item] = item_map
|
||||||
|
self.config: ZonaConfig | None = config
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def render_link(self, element: Link):
|
def render_link(self, element: Link):
|
||||||
|
@ -80,16 +83,23 @@ class ZonaRenderer(HTMLRenderer):
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def render_fenced_code(self, element: FencedCode):
|
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
|
code = "".join(child.children for child in element.children) # type: ignore
|
||||||
lang = element.lang or "text"
|
lang = element.lang or "text"
|
||||||
|
if not config.enabled:
|
||||||
|
return f"<pre><code>{code}</code></pre>"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lexer = get_lexer_by_name(lang, stripall=False)
|
lexer = get_lexer_by_name(lang, stripall=False)
|
||||||
except Exception:
|
except Exception:
|
||||||
lexer = TextLexer(stripall=False) # type: ignore
|
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
|
highlighted = highlight(code, lexer, formatter) # type: ignore
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -100,18 +110,25 @@ class ZonaRenderer(HTMLRenderer):
|
||||||
|
|
||||||
def md_to_html(
|
def md_to_html(
|
||||||
content: str,
|
content: str,
|
||||||
|
config: ZonaConfig | None,
|
||||||
resolve_links: bool = False,
|
resolve_links: bool = False,
|
||||||
source: Path | None = None,
|
source: Path | None = None,
|
||||||
layout: Layout | None = None,
|
layout: Layout | None = None,
|
||||||
item_map: dict[Path, Item] | None = None,
|
item_map: dict[Path, Item] | None = None,
|
||||||
) -> str:
|
) -> 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(
|
raise TypeError(
|
||||||
"md_to_html() missing source and ctx when resolve_links is true"
|
"md_to_html() missing source and ctx when resolve_links is true"
|
||||||
)
|
)
|
||||||
parser = Parser()
|
parser = Parser()
|
||||||
ast = parser.parse(content)
|
ast = parser.parse(content)
|
||||||
renderer = ZonaRenderer(
|
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)
|
return renderer.render(ast)
|
||||||
|
|
|
@ -9,7 +9,7 @@ def get_header(template_dir: Path) -> str | None:
|
||||||
md_header = template_dir / "header.md"
|
md_header = template_dir / "header.md"
|
||||||
html_header = template_dir / "header.html"
|
html_header = template_dir / "header.html"
|
||||||
if md_header.exists():
|
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():
|
elif html_header.exists():
|
||||||
return html_header.read_text()
|
return html_header.read_text()
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def get_footer(template_dir: Path) -> str | None:
|
||||||
md_footer = template_dir / "footer.md"
|
md_footer = template_dir / "footer.md"
|
||||||
html_footer = template_dir / "footer.html"
|
html_footer = template_dir / "footer.html"
|
||||||
if md_footer.exists():
|
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():
|
elif html_footer.exists():
|
||||||
return html_footer.read_text()
|
return html_footer.read_text()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue