Closes #3 Signed-off-by: Minecon724 <git@m724.eu>
This commit is contained in:
parent
0aadf69a42
commit
121a2c6915
7 changed files with 57 additions and 33 deletions
|
@ -1,5 +1,5 @@
|
||||||
name: my blog
|
name: my blog
|
||||||
baseUrl: https://example.com
|
baseUrl: https://example.com/blog
|
||||||
|
|
||||||
coolProperty: 1231
|
coolProperty: 1231
|
||||||
coolerProperty:
|
coolerProperty:
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class BlogBuilder {
|
||||||
this.renderOptions = RenderOptions.fromConfig(workingDirectory.resolve("render.yml"));
|
this.renderOptions = RenderOptions.fromConfig(workingDirectory.resolve("render.yml"));
|
||||||
|
|
||||||
if (template == null)
|
if (template == null)
|
||||||
this.template = new TemplateRenderer(templateDirectory);
|
this.template = new TemplateRenderer(site, templateDirectory);
|
||||||
|
|
||||||
LOGGER.debug("Copying assets...");
|
LOGGER.debug("Copying assets...");
|
||||||
copyTree(workingDirectory.resolve("assets"), outputDirectory.resolve("assets"));
|
copyTree(workingDirectory.resolve("assets"), outputDirectory.resolve("assets"));
|
||||||
|
@ -144,7 +144,7 @@ public class BlogBuilder {
|
||||||
|
|
||||||
LOGGER.debug("Rendering meta...");
|
LOGGER.debug("Rendering meta...");
|
||||||
posts.sort(Comparator.comparing(Post::createdAt).reversed());
|
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));
|
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<Post> renderPosts() throws IOException {
|
private List<Post> renderPosts() throws IOException {
|
||||||
Files.createDirectory(outputDirectory.resolve("post"));
|
Files.createDirectory(outputDirectory.resolve("post"));
|
||||||
var postDirectory = workingDirectory.resolve("posts");
|
var postDirectory = workingDirectory.resolve("posts");
|
||||||
|
@ -178,7 +188,7 @@ public class BlogBuilder {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var render = template.renderPost(site, post);
|
var render = template.renderPost(post);
|
||||||
var outFile = outputDirectory.resolve("post").resolve(path);
|
var outFile = outputDirectory.resolve("post").resolve(path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -46,16 +46,7 @@ public class Main {
|
||||||
// BAD
|
// BAD
|
||||||
LOGGER.info("Exported to {} in {} ms", outputDirectory.toAbsolutePath(), "%.2f".formatted((end - start) / 1000000.0));
|
LOGGER.info("Exported to {} in {} ms", outputDirectory.toAbsolutePath(), "%.2f".formatted((end - start) / 1000000.0));
|
||||||
|
|
||||||
/* Server process */
|
builder.startServer(openBrowser);
|
||||||
|
|
||||||
if (startServer) {
|
|
||||||
var server = new Server(outputDirectory);
|
|
||||||
server.start();
|
|
||||||
|
|
||||||
if (openBrowser) {
|
|
||||||
server.openBrowser();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CommandLine getCommandLine(String[] args) {
|
private static CommandLine getCommandLine(String[] args) {
|
||||||
|
|
|
@ -17,18 +17,21 @@ import java.nio.file.Path;
|
||||||
public class Server {
|
public class Server {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
|
||||||
|
|
||||||
private final Path webroot;
|
private final Path sitePath;
|
||||||
|
private final String contextPath;
|
||||||
private InetSocketAddress listenAddress;
|
private InetSocketAddress listenAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@link Server} instance with the specified webroot directory
|
* Constructs a {@link Server} instance with the specified webroot directory
|
||||||
* and the specified listening address.
|
* 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
|
* @param listenAddress the address and port the server will listen on
|
||||||
*/
|
*/
|
||||||
public Server(Path webroot, InetSocketAddress listenAddress) {
|
public Server(Path sitePath, String contextPath, InetSocketAddress listenAddress) {
|
||||||
this.webroot = webroot;
|
this.sitePath = sitePath;
|
||||||
|
this.contextPath = contextPath;
|
||||||
this.listenAddress = listenAddress;
|
this.listenAddress = listenAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +39,11 @@ public class Server {
|
||||||
* Constructs a {@link Server} instance with the specified webroot directory.
|
* Constructs a {@link Server} instance with the specified webroot directory.
|
||||||
* The server will bind to the localhost address with a dynamically chosen port.
|
* 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) {
|
public Server(Path sitePath, String contextPath) {
|
||||||
this(webroot, new InetSocketAddress("localhost", 0));
|
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
|
* @throws IOException if an I/O error occurs during server initialization
|
||||||
*/
|
*/
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
|
System.out.println(contextPath);
|
||||||
var server = HttpServer.create(listenAddress, 0);
|
var server = HttpServer.create(listenAddress, 0);
|
||||||
server.createContext("/", SimpleFileServer.createFileHandler(webroot.toAbsolutePath()));
|
server.createContext(contextPath, SimpleFileServer.createFileHandler(sitePath.toAbsolutePath()));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LOGGER.info("Server started on http:/{}", server.getAddress());
|
LOGGER.info("Server started on http:/{}", server.getAddress());
|
||||||
|
@ -62,7 +67,7 @@ public class Server {
|
||||||
*/
|
*/
|
||||||
public void openBrowser() {
|
public void openBrowser() {
|
||||||
try {
|
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();
|
var code = process.waitFor();
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
throw new Exception("Exit code " + code);
|
throw new Exception("Exit code " + code);
|
||||||
|
|
|
@ -14,12 +14,15 @@ import java.util.Map;
|
||||||
*
|
*
|
||||||
* @param name the name of the site
|
* @param name the name of the site
|
||||||
* @param baseUrl the base URL 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
|
* @param custom a map of additional custom properties
|
||||||
*/
|
*/
|
||||||
public record Site(
|
public record Site(
|
||||||
String name,
|
String name,
|
||||||
String baseUrl,
|
String baseUrl,
|
||||||
|
|
||||||
|
String directory,
|
||||||
|
|
||||||
Map<String, Object> custom
|
Map<String, Object> 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(
|
return new Site(
|
||||||
name, baseUrl, custom
|
name, baseUrl, directory, custom
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.m724.blog.template;
|
package eu.m724.blog.template;
|
||||||
|
|
||||||
|
import eu.m724.blog.data.Site;
|
||||||
import io.pebbletemplates.pebble.extension.AbstractExtension;
|
import io.pebbletemplates.pebble.extension.AbstractExtension;
|
||||||
import io.pebbletemplates.pebble.extension.Function;
|
import io.pebbletemplates.pebble.extension.Function;
|
||||||
import io.pebbletemplates.pebble.template.EvaluationContext;
|
import io.pebbletemplates.pebble.template.EvaluationContext;
|
||||||
|
@ -9,6 +10,12 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class TemplateExtension extends AbstractExtension {
|
public class TemplateExtension extends AbstractExtension {
|
||||||
|
private final Site site;
|
||||||
|
|
||||||
|
public TemplateExtension(Site site) {
|
||||||
|
this.site = site;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Function> getFunctions() {
|
public Map<String, Function> getFunctions() {
|
||||||
return Map.of(
|
return Map.of(
|
||||||
|
@ -20,7 +27,7 @@ public class TemplateExtension extends AbstractExtension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
|
public Object execute(Map<String, Object> 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() {
|
"asset", new Function() {
|
||||||
|
@ -31,9 +38,10 @@ public class TemplateExtension extends AbstractExtension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
|
public Object execute(Map<String, Object> 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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,26 @@ import java.util.Map;
|
||||||
* using the Pebble templating engine.
|
* using the Pebble templating engine.
|
||||||
*/
|
*/
|
||||||
public class TemplateRenderer {
|
public class TemplateRenderer {
|
||||||
|
private final Site site;
|
||||||
private final PebbleTemplate indexTemplate, articleTemplate;
|
private final PebbleTemplate indexTemplate, articleTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a TemplateRenderer instance for rendering templates from the specified directory.
|
* 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
|
* @param templateDirectory the root directory containing the template files
|
||||||
*/
|
*/
|
||||||
public TemplateRenderer(Path templateDirectory) {
|
public TemplateRenderer(Site site, Path templateDirectory) {
|
||||||
var loader = new FileLoader();
|
var loader = new FileLoader();
|
||||||
loader.setPrefix(templateDirectory.toString());
|
loader.setPrefix(templateDirectory.toString());
|
||||||
loader.setSuffix(".html");
|
loader.setSuffix(".html");
|
||||||
|
|
||||||
var pebbleEngine = new PebbleEngine.Builder()
|
var pebbleEngine = new PebbleEngine.Builder()
|
||||||
.loader(loader)
|
.loader(loader)
|
||||||
.extension(new TemplateExtension())
|
.extension(new TemplateExtension(site))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
this.site = site;
|
||||||
this.indexTemplate = pebbleEngine.getTemplate("index_template");
|
this.indexTemplate = pebbleEngine.getTemplate("index_template");
|
||||||
this.articleTemplate = pebbleEngine.getTemplate("article_template");
|
this.articleTemplate = pebbleEngine.getTemplate("article_template");
|
||||||
}
|
}
|
||||||
|
@ -41,12 +44,11 @@ public class TemplateRenderer {
|
||||||
/**
|
/**
|
||||||
* Renders the index page using this template.
|
* 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
|
* @param posts the {@link Post}s to be included in the index page
|
||||||
* @return the rendered index HTML page as a string
|
* @return the rendered index HTML page as a string
|
||||||
* @throws IOException if an error occurs during the template evaluation
|
* @throws IOException if an error occurs during the template evaluation
|
||||||
*/
|
*/
|
||||||
public String renderIndex(Site site, List<Post> posts) throws IOException {
|
public String renderIndex(List<Post> posts) throws IOException {
|
||||||
Map<String, Object> context = Map.of(
|
Map<String, Object> context = Map.of(
|
||||||
"site", site,
|
"site", site,
|
||||||
"articles", posts
|
"articles", posts
|
||||||
|
@ -61,12 +63,11 @@ public class TemplateRenderer {
|
||||||
/**
|
/**
|
||||||
* Renders the content of a post using this template.
|
* 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
|
* @param post the {@link Post} to be rendered
|
||||||
* @return the rendered post HTML page as a string
|
* @return the rendered post HTML page as a string
|
||||||
* @throws IOException if an error occurs during template evaluation
|
* @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<String, Object> context = Map.of(
|
Map<String, Object> context = Map.of(
|
||||||
"site", site,
|
"site", site,
|
||||||
"article", post
|
"article", post
|
||||||
|
|
Loading…
Add table
Reference in a new issue