From 7ce073a853adcd0513e16848c5b2d24896d865ce Mon Sep 17 00:00:00 2001 From: kingwill101 Date: Sat, 13 Apr 2024 03:24:53 -0500 Subject: [PATCH] update content renderer to handle recursive layouts --- lib/renderer.dart | 145 ++++++++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 51 deletions(-) diff --git a/lib/renderer.dart b/lib/renderer.dart index f415f1c..2462337 100644 --- a/lib/renderer.dart +++ b/lib/renderer.dart @@ -1,87 +1,130 @@ import 'package:gengen/liquid/template.dart'; +import 'package:gengen/logging.dart'; +import 'package:gengen/md/md.dart'; import 'package:gengen/models/base.dart'; import 'package:gengen/sass/sass.dart'; -import 'package:markdown/markdown.dart'; +import 'package:gengen/site.dart'; +import 'package:gengen/utilities.dart'; class Renderer { Base base; - late String content; - Renderer(this.base); - - Future render() async { + Renderer(this.base) { content = base.content; - - if (base.isMarkdown) { - _renderMd(); + if (containsMarkdown(content)) { + content = renderMd(content); } + } - if (base.isAsset) { - var result = compileSass( - base.source, - importPaths: [base.site.sassPath, base.site.theme.sassPath], - ); - - return result.css; + Future resolve() async { + if (containsLiquid(content) || containsMarkdown(content)) { + await _renderLiquid(); + renderMd(content); } if (base.config.containsKey("layout")) { - if (base.hasLiquid) { - await _renderLiquid(); - } + content = await _renderWithLayout(content); + } + } - var layouts = base.site.layouts; - - String? tmplKeyIndex; - for (var key in layouts.keys) { - if (key.startsWith( - "${base.site.config.get("layout_dir")}/${base.layout}", - ) || - key.startsWith( - "${base.site.theme.config.get("layout_dir")}/${base.layout}", - )) { - tmplKeyIndex = key; - } + Future render() async { + if (base.isAsset) { + try { + var result = compileSass( + base.source, + importPaths: [Site.instance.sassPath, Site.instance.theme.sassPath], + ); + return result.css; + } catch (e) { + log.severe(e.toString()); } + return ""; + } + await resolve(); - if (tmplKeyIndex == null) return ""; - var tmpl = layouts[tmplKeyIndex]; + return content; + } - tmpl?.data.addAll(base.data); - tmpl?.data.addAll(base.site.data); + Future _renderWithLayout(String content, + [String? initialLayoutName]) async { + var layoutName = initialLayoutName ?? base.config["layout"] as String?; - var template = Template.r( - tmpl!.content, - child: await _renderLiquid(), - data: tmpl.data, - contentRoot: ContentRoot(base.site), - ); + if (layoutName == null) { + return content; // No layout specified, return original content + } - return await template.render(); + var layoutPath = _findLayoutPath(layoutName); + + if (layoutPath == null) { + return content; // Layout not found, return original content } - if (base.hasLiquid) { - content = await _renderLiquid(); + var tmpl = Site.instance.layouts[layoutPath]; + if (tmpl == null) { + return content; // Template is null, return original content } - return content; + // Add page data and site-wide data to the template's data + tmpl.data.addAll({"page": base.to_liquid}); + tmpl.data.addAll(Site.instance.data); + + // Render the current layout with its content + var template = Template.r( + tmpl.content, + child: content, + // Pass the current content as the child content to be included in the layout + data: tmpl.data, + contentRoot: ContentRoot(), + ); + + var renderedContent = await safeRender(template); + + // Check if the current layout specifies another layout + var nestedLayoutName = tmpl.data["layout"] as String?; + if (nestedLayoutName != null) { + // If there's a nested layout, recursively render the content with the nested layout + return _renderWithLayout(renderedContent, nestedLayoutName); + } + + return renderedContent; } - void _renderMd() { - content = markdownToHtml(content); + Future safeRender(Template template) async { + try { + return await template.render(); + } catch (err, st) { + log.severe("Error rendering template: ${base.filePath}"); + log.severe(err); + log.severe(st); + return ''; + } } - Future _renderLiquid() async { + Future _renderLiquid() async { var template = Template.r( content, data: { - ...base.data, - ...base.site.data, + "page": base.to_liquid, + ...Site.instance.data, }, - contentRoot: ContentRoot(base.site), + contentRoot: ContentRoot(), ); - return await template.render(); + content = await safeRender(template); + } + + String? _findLayoutPath(String layoutName) { + var layoutDir = Site.instance.config.get("layout_dir"); + var themeLayoutDir = Site.instance.theme.config.get("layout_dir"); + var possiblePaths = [ + "$layoutDir/$layoutName", + "$themeLayoutDir/$layoutName", + ]; + + return Site.instance.layouts.keys.firstWhere( + (k) => possiblePaths.contains(k), + orElse: () => '', + ); } }