From 121a2c69152973ec815f3e52e1f9fc3dd15bb060 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 27 Feb 2025 14:34:36 +0100 Subject: [PATCH] Support folders Closes #3 Signed-off-by: Minecon724 --- example_workdir/site.yml | 2 +- src/main/java/eu/m724/blog/BlogBuilder.java | 16 ++++++++++--- src/main/java/eu/m724/blog/Main.java | 11 +-------- src/main/java/eu/m724/blog/Server.java | 23 +++++++++++-------- src/main/java/eu/m724/blog/data/Site.java | 11 ++++++++- .../m724/blog/template/TemplateExtension.java | 12 ++++++++-- .../m724/blog/template/TemplateRenderer.java | 15 ++++++------ 7 files changed, 57 insertions(+), 33 deletions(-) diff --git a/example_workdir/site.yml b/example_workdir/site.yml index 6ba34c1..8e8c264 100644 --- a/example_workdir/site.yml +++ b/example_workdir/site.yml @@ -1,5 +1,5 @@ name: my blog -baseUrl: https://example.com +baseUrl: https://example.com/blog coolProperty: 1231 coolerProperty: diff --git a/src/main/java/eu/m724/blog/BlogBuilder.java b/src/main/java/eu/m724/blog/BlogBuilder.java index 797a029..a523d4e 100644 --- a/src/main/java/eu/m724/blog/BlogBuilder.java +++ b/src/main/java/eu/m724/blog/BlogBuilder.java @@ -133,7 +133,7 @@ public class BlogBuilder { this.renderOptions = RenderOptions.fromConfig(workingDirectory.resolve("render.yml")); if (template == null) - this.template = new TemplateRenderer(templateDirectory); + this.template = new TemplateRenderer(site, templateDirectory); LOGGER.debug("Copying assets..."); copyTree(workingDirectory.resolve("assets"), outputDirectory.resolve("assets")); @@ -144,7 +144,7 @@ public class BlogBuilder { LOGGER.debug("Rendering meta..."); posts.sort(Comparator.comparing(Post::createdAt).reversed()); - Files.writeString(outputDirectory.resolve("index.html"), template.renderIndex(site, posts)); + Files.writeString(outputDirectory.resolve("index.html"), template.renderIndex(posts)); Files.writeString(outputDirectory.resolve("posts.rss"), Feed.generateRss(site, posts)); @@ -154,6 +154,16 @@ public class BlogBuilder { } } + // TODO should server be here in builder really + public void startServer(boolean openBrowser) throws IOException { + var server = new Server(outputDirectory, site.directory()); + server.start(); + + if (openBrowser) { + server.openBrowser(); + } + } + private List renderPosts() throws IOException { Files.createDirectory(outputDirectory.resolve("post")); var postDirectory = workingDirectory.resolve("posts"); @@ -178,7 +188,7 @@ public class BlogBuilder { continue; } - var render = template.renderPost(site, post); + var render = template.renderPost(post); var outFile = outputDirectory.resolve("post").resolve(path); try { diff --git a/src/main/java/eu/m724/blog/Main.java b/src/main/java/eu/m724/blog/Main.java index 49335aa..ac3989a 100644 --- a/src/main/java/eu/m724/blog/Main.java +++ b/src/main/java/eu/m724/blog/Main.java @@ -46,16 +46,7 @@ public class Main { // BAD LOGGER.info("Exported to {} in {} ms", outputDirectory.toAbsolutePath(), "%.2f".formatted((end - start) / 1000000.0)); - /* Server process */ - - if (startServer) { - var server = new Server(outputDirectory); - server.start(); - - if (openBrowser) { - server.openBrowser(); - } - } + builder.startServer(openBrowser); } private static CommandLine getCommandLine(String[] args) { diff --git a/src/main/java/eu/m724/blog/Server.java b/src/main/java/eu/m724/blog/Server.java index b6a53eb..4a4b17f 100644 --- a/src/main/java/eu/m724/blog/Server.java +++ b/src/main/java/eu/m724/blog/Server.java @@ -17,18 +17,21 @@ import java.nio.file.Path; public class Server { private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); - private final Path webroot; + private final Path sitePath; + private final String contextPath; private InetSocketAddress listenAddress; /** * Constructs a {@link Server} instance with the specified webroot directory * and the specified listening address. * - * @param webroot the path to the webroot directory from which files will be served + * @param sitePath the directory from which files will be served + * @param contextPath TODO explain * @param listenAddress the address and port the server will listen on */ - public Server(Path webroot, InetSocketAddress listenAddress) { - this.webroot = webroot; + public Server(Path sitePath, String contextPath, InetSocketAddress listenAddress) { + this.sitePath = sitePath; + this.contextPath = contextPath; this.listenAddress = listenAddress; } @@ -36,10 +39,11 @@ public class Server { * Constructs a {@link Server} instance with the specified webroot directory. * The server will bind to the localhost address with a dynamically chosen port. * - * @param webroot the path to the webroot directory from which files will be served + * @param sitePath the directory from which files will be served + * @param contextPath TODO explain */ - public Server(Path webroot) { - this(webroot, new InetSocketAddress("localhost", 0)); + public Server(Path sitePath, String contextPath) { + this(sitePath, contextPath, new InetSocketAddress("localhost", 0)); } /** @@ -48,8 +52,9 @@ public class Server { * @throws IOException if an I/O error occurs during server initialization */ public void start() throws IOException { + System.out.println(contextPath); var server = HttpServer.create(listenAddress, 0); - server.createContext("/", SimpleFileServer.createFileHandler(webroot.toAbsolutePath())); + server.createContext(contextPath, SimpleFileServer.createFileHandler(sitePath.toAbsolutePath())); server.start(); LOGGER.info("Server started on http:/{}", server.getAddress()); @@ -62,7 +67,7 @@ public class Server { */ public void openBrowser() { try { - var process = Runtime.getRuntime().exec(new String[] { "xdg-open", "http://" + listenAddress.getHostString() + ":" + listenAddress.getPort() }); + var process = Runtime.getRuntime().exec(new String[] { "xdg-open", "http://" + listenAddress.getHostString() + ":" + listenAddress.getPort() + contextPath }); var code = process.waitFor(); if (code != 0) { throw new Exception("Exit code " + code); diff --git a/src/main/java/eu/m724/blog/data/Site.java b/src/main/java/eu/m724/blog/data/Site.java index 037b227..4f176fe 100644 --- a/src/main/java/eu/m724/blog/data/Site.java +++ b/src/main/java/eu/m724/blog/data/Site.java @@ -14,12 +14,15 @@ import java.util.Map; * * @param name the name of the site * @param baseUrl the base URL of the site + * @param directory The directory that the site is installed into. Like "https://example.com/blog" turns to "/blog" * @param custom a map of additional custom properties */ public record Site( String name, String baseUrl, + String directory, + Map custom ) { /** @@ -53,8 +56,14 @@ public record Site( } } + String directory = null; + if (baseUrl != null) { + var temp = baseUrl.substring(baseUrl.indexOf(':') + 3); + directory = temp.substring(temp.indexOf('/')); + } + return new Site( - name, baseUrl, custom + name, baseUrl, directory, custom ); } } diff --git a/src/main/java/eu/m724/blog/template/TemplateExtension.java b/src/main/java/eu/m724/blog/template/TemplateExtension.java index 54eb917..d5e3923 100644 --- a/src/main/java/eu/m724/blog/template/TemplateExtension.java +++ b/src/main/java/eu/m724/blog/template/TemplateExtension.java @@ -1,5 +1,6 @@ package eu.m724.blog.template; +import eu.m724.blog.data.Site; import io.pebbletemplates.pebble.extension.AbstractExtension; import io.pebbletemplates.pebble.extension.Function; import io.pebbletemplates.pebble.template.EvaluationContext; @@ -9,6 +10,12 @@ import java.util.List; import java.util.Map; public class TemplateExtension extends AbstractExtension { + private final Site site; + + public TemplateExtension(Site site) { + this.site = site; + } + @Override public Map getFunctions() { return Map.of( @@ -20,7 +27,7 @@ public class TemplateExtension extends AbstractExtension { @Override public Object execute(Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { - return "/static/" + args.get("path"); // TODO for more advanced stuff + return site.directory() + "/static/" + args.get("path"); } }, "asset", new Function() { @@ -31,9 +38,10 @@ public class TemplateExtension extends AbstractExtension { @Override public Object execute(Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { - return "/assets/" + args.get("path"); // TODO for more advanced stuff + return site.directory() + "/assets/" + args.get("path"); } } + // TODO make url_for that supports relative and absolute paths ); } } diff --git a/src/main/java/eu/m724/blog/template/TemplateRenderer.java b/src/main/java/eu/m724/blog/template/TemplateRenderer.java index cf9fe15..72e8066 100644 --- a/src/main/java/eu/m724/blog/template/TemplateRenderer.java +++ b/src/main/java/eu/m724/blog/template/TemplateRenderer.java @@ -17,23 +17,26 @@ import java.util.Map; * using the Pebble templating engine. */ public class TemplateRenderer { + private final Site site; private final PebbleTemplate indexTemplate, articleTemplate; /** * Constructs a TemplateRenderer instance for rendering templates from the specified directory. - * + + * @param site the {@link Site} this renderer renders * @param templateDirectory the root directory containing the template files */ - public TemplateRenderer(Path templateDirectory) { + public TemplateRenderer(Site site, Path templateDirectory) { var loader = new FileLoader(); loader.setPrefix(templateDirectory.toString()); loader.setSuffix(".html"); var pebbleEngine = new PebbleEngine.Builder() .loader(loader) - .extension(new TemplateExtension()) + .extension(new TemplateExtension(site)) .build(); + this.site = site; this.indexTemplate = pebbleEngine.getTemplate("index_template"); this.articleTemplate = pebbleEngine.getTemplate("article_template"); } @@ -41,12 +44,11 @@ public class TemplateRenderer { /** * Renders the index page using this template. * - * @param site the {@link Site} this index is for * @param posts the {@link Post}s to be included in the index page * @return the rendered index HTML page as a string * @throws IOException if an error occurs during the template evaluation */ - public String renderIndex(Site site, List posts) throws IOException { + public String renderIndex(List posts) throws IOException { Map context = Map.of( "site", site, "articles", posts @@ -61,12 +63,11 @@ public class TemplateRenderer { /** * Renders the content of a post using this template. * - * @param site the {@link Site} containing the post * @param post the {@link Post} to be rendered * @return the rendered post HTML page as a string * @throws IOException if an error occurs during template evaluation */ - public String renderPost(Site site, Post post) throws IOException { + public String renderPost(Post post) throws IOException { Map context = Map.of( "site", site, "article", post