docs: add Javadoc for core classes
- Added Javadoc comments to `Site`, `Server`, `Feed`, `BlogBuilder`, `TemplateRenderer`, and `Post` classes. - Documented constructors, methods, and class-level descriptions. - Enhanced clarity around parameters, return values, and exceptions. Signed-off-by: Minecon724 <git@m724.eu>
This commit is contained in:
parent
d5f6eaf487
commit
b339d6d239
6 changed files with 148 additions and 37 deletions
|
@ -15,6 +15,11 @@ import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code BlogBuilder} class facilitates building a static blog by managing templates,
|
||||||
|
* assets, posts, and rendering output files. It uses a Git repository as the
|
||||||
|
* source for the blog's content and configuration.
|
||||||
|
*/
|
||||||
public class BlogBuilder {
|
public class BlogBuilder {
|
||||||
private final Git git;
|
private final Git git;
|
||||||
private final Path workingDirectory;
|
private final Path workingDirectory;
|
||||||
|
@ -26,6 +31,11 @@ public class BlogBuilder {
|
||||||
private Path outputDirectory;
|
private Path outputDirectory;
|
||||||
private boolean renderDrafts = false;
|
private boolean renderDrafts = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link BlogBuilder} instance using the provided Git repository.
|
||||||
|
*
|
||||||
|
* @param git the Git repository to be used for the blog.
|
||||||
|
*/
|
||||||
public BlogBuilder(Git git) {
|
public BlogBuilder(Git git) {
|
||||||
this.git = git;
|
this.git = git;
|
||||||
|
|
||||||
|
@ -34,6 +44,14 @@ public class BlogBuilder {
|
||||||
this.outputDirectory = workingDirectory.resolve("generated_out");
|
this.outputDirectory = workingDirectory.resolve("generated_out");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link BlogBuilder} instance for the specified working directory.
|
||||||
|
* The directory is expected to be a Git repository.
|
||||||
|
*
|
||||||
|
* @param workingDirectory the root path of the blog, which must contain a Git repository.
|
||||||
|
* @return a {@link BlogBuilder} instance
|
||||||
|
* @throws IOException if there is an error accessing the Git repository
|
||||||
|
*/
|
||||||
public static BlogBuilder fromPath(Path workingDirectory) throws IOException {
|
public static BlogBuilder fromPath(Path workingDirectory) throws IOException {
|
||||||
var repository = new RepositoryBuilder()
|
var repository = new RepositoryBuilder()
|
||||||
.setGitDir(workingDirectory.resolve(".git").toFile())
|
.setGitDir(workingDirectory.resolve(".git").toFile())
|
||||||
|
@ -45,16 +63,34 @@ public class BlogBuilder {
|
||||||
return new BlogBuilder(git);
|
return new BlogBuilder(git);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the directory to be used for templates in the blog build process.
|
||||||
|
*
|
||||||
|
* @param templateDirectory the path to the template directory
|
||||||
|
* @return the current instance of {@link BlogBuilder}
|
||||||
|
*/
|
||||||
public BlogBuilder templateDirectory(Path templateDirectory) {
|
public BlogBuilder templateDirectory(Path templateDirectory) {
|
||||||
this.templateDirectory = templateDirectory;
|
this.templateDirectory = templateDirectory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the directory where the output files will be saved during the blog build process.
|
||||||
|
*
|
||||||
|
* @param outputDirectory the path representing the directory for output files
|
||||||
|
* @return the current instance of {@link BlogBuilder}
|
||||||
|
*/
|
||||||
public BlogBuilder outputDirectory(Path outputDirectory) {
|
public BlogBuilder outputDirectory(Path outputDirectory) {
|
||||||
this.outputDirectory = outputDirectory;
|
this.outputDirectory = outputDirectory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures whether drafts should be rendered in the blog build process.
|
||||||
|
*
|
||||||
|
* @param renderDrafts a boolean flag indicating whether to include drafts in the rendering process.
|
||||||
|
* @return the current instance of {@link BlogBuilder}
|
||||||
|
*/
|
||||||
public BlogBuilder renderDrafts(boolean renderDrafts) {
|
public BlogBuilder renderDrafts(boolean renderDrafts) {
|
||||||
this.renderDrafts = renderDrafts;
|
this.renderDrafts = renderDrafts;
|
||||||
return this;
|
return this;
|
||||||
|
@ -72,6 +108,11 @@ public class BlogBuilder {
|
||||||
Files.createDirectory(outputDirectory);
|
Files.createDirectory(outputDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the blog by generating templates, copying assets, and rendering posts.
|
||||||
|
*
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
public void build() throws IOException {
|
public void build() throws IOException {
|
||||||
if (site == null)
|
if (site == null)
|
||||||
this.site = Site.fromConfig(workingDirectory.resolve("site-config.json"));
|
this.site = Site.fromConfig(workingDirectory.resolve("site-config.json"));
|
||||||
|
|
|
@ -10,19 +10,41 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code Server} class represents a basic HTTP server designed to serve files
|
||||||
|
* from a specified webroot directory.
|
||||||
|
*/
|
||||||
public class Server implements HttpHandler {
|
public class Server implements HttpHandler {
|
||||||
private final Path webroot;
|
private final Path webroot;
|
||||||
private InetSocketAddress listenAddress;
|
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 listenAddress the address and port the server will listen on
|
||||||
|
*/
|
||||||
public Server(Path webroot, InetSocketAddress listenAddress) {
|
public Server(Path webroot, InetSocketAddress listenAddress) {
|
||||||
this.webroot = webroot;
|
this.webroot = webroot;
|
||||||
this.listenAddress = listenAddress;
|
this.listenAddress = listenAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
public Server(Path webroot) {
|
public Server(Path webroot) {
|
||||||
this(webroot, new InetSocketAddress("localhost", 0));
|
this(webroot, new InetSocketAddress("localhost", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an HTTP server on the specified listen address.
|
||||||
|
*
|
||||||
|
* @throws IOException if an I/O error occurs during server initialization
|
||||||
|
*/
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
var server = HttpServer.create(listenAddress, 0);
|
var server = HttpServer.create(listenAddress, 0);
|
||||||
server.createContext("/", this);
|
server.createContext("/", this);
|
||||||
|
@ -33,6 +55,9 @@ public class Server implements HttpHandler {
|
||||||
this.listenAddress = server.getAddress();
|
this.listenAddress = server.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to open the default web browser and navigate to the server's URL.
|
||||||
|
*/
|
||||||
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() });
|
||||||
|
|
|
@ -16,9 +16,18 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code TemplateRenderer} class is responsible for rendering dynamic HTML templates
|
||||||
|
* using the Pebble templating engine.
|
||||||
|
*/
|
||||||
public class TemplateRenderer {
|
public class TemplateRenderer {
|
||||||
private final PebbleTemplate indexTemplate, articleTemplate;
|
private final PebbleTemplate indexTemplate, articleTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a TemplateRenderer instance for rendering templates from the specified directory.
|
||||||
|
*
|
||||||
|
* @param templateDirectory the root directory containing the template files
|
||||||
|
*/
|
||||||
public TemplateRenderer(Path templateDirectory) {
|
public TemplateRenderer(Path templateDirectory) {
|
||||||
var loader = new FileLoader();
|
var loader = new FileLoader();
|
||||||
loader.setPrefix(templateDirectory.toString());
|
loader.setPrefix(templateDirectory.toString());
|
||||||
|
@ -61,6 +70,14 @@ public class TemplateRenderer {
|
||||||
this.articleTemplate = pebbleEngine.getTemplate("article_template");
|
this.articleTemplate = pebbleEngine.getTemplate("article_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
|
||||||
|
* @return the rendered index HTML page as a string
|
||||||
|
* @throws IOException if an error occurs during the template evaluation
|
||||||
|
*/
|
||||||
public String renderIndex(Site site, ArrayList<Post> posts) throws IOException {
|
public String renderIndex(Site site, ArrayList<Post> posts) throws IOException {
|
||||||
Map<String, Object> context = Map.of(
|
Map<String, Object> context = Map.of(
|
||||||
"site", site,
|
"site", site,
|
||||||
|
@ -73,6 +90,14 @@ public class TemplateRenderer {
|
||||||
return writer.toString();
|
return writer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(Site site, Post post) throws IOException {
|
||||||
Map<String, Object> context = Map.of(
|
Map<String, Object> context = Map.of(
|
||||||
"site", site,
|
"site", site,
|
||||||
|
|
|
@ -4,6 +4,13 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Feed {
|
public class Feed {
|
||||||
|
/**
|
||||||
|
* Generates an RSS feed XML string for a given website and its list of blog posts.
|
||||||
|
*
|
||||||
|
* @param site the {@code Site} object representing the website for which the RSS feed is generated
|
||||||
|
* @param posts the list of {@code Post} objects representing the blog posts to include in the RSS feed
|
||||||
|
* @return a {@code String} containing the formatted RSS feed in XML
|
||||||
|
*/
|
||||||
public static String generateRss(Site site, List<Post> posts) {
|
public static String generateRss(Site site, List<Post> posts) {
|
||||||
var content = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><rss version=\"2.0\">";
|
var content = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><rss version=\"2.0\">";
|
||||||
content += "<channel><title>%s</title><link>%s</link>".formatted(site.name(), site.baseUrl());
|
content += "<channel><title>%s</title><link>%s</link>".formatted(site.name(), site.baseUrl());
|
||||||
|
|
|
@ -10,6 +10,21 @@ import java.time.*;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code Post} class represents a blog post with various attributes including metadata and content.
|
||||||
|
*
|
||||||
|
* @param slug A unique identifier for the post derived from the file name.
|
||||||
|
* @param title The title of the post.
|
||||||
|
* @param summary A brief summary of the post content.
|
||||||
|
* @param draft Indicates whether the post is marked as a draft or published.
|
||||||
|
* @param revisions The number of revisions the post has undergone in version control.
|
||||||
|
* @param createdBy The name of the author who created the post.
|
||||||
|
* @param createdAt The timestamp of when the post was first created.
|
||||||
|
* @param modifiedBy The name of the author who last modified the post.
|
||||||
|
* @param modifiedAt The timestamp of the last modification to the post.
|
||||||
|
* @param custom A map of custom properties or metadata associated with the post.
|
||||||
|
* @param rawContent The raw content of the post, which <em>currently</em> is usually HTML.
|
||||||
|
*/
|
||||||
public record Post(
|
public record Post(
|
||||||
String slug,
|
String slug,
|
||||||
String title,
|
String title,
|
||||||
|
@ -25,11 +40,17 @@ public record Post(
|
||||||
Map<String, String> custom,
|
Map<String, String> custom,
|
||||||
String rawContent
|
String rawContent
|
||||||
) {
|
) {
|
||||||
// this is because we'll be not only supporting html
|
/**
|
||||||
public String htmlContent() {
|
* Creates a {@link Post} instance by reading and parsing the content of a post file.
|
||||||
return rawContent;
|
* <p>
|
||||||
}
|
* The method extracts metadata properties, content, and versioning information
|
||||||
|
* based on the Git history of the file.
|
||||||
|
*
|
||||||
|
* @param git the Git repository used to retrieve versioning and commit information
|
||||||
|
* @param path the relative path to the file within the "posts" directory
|
||||||
|
* @return a {@link Post} object populated with data extracted from the specified file
|
||||||
|
* @throws IOException if an error occurs during file reading
|
||||||
|
*/
|
||||||
public static Post fromFile(Git git, Path path) throws IOException {
|
public static Post fromFile(Git git, Path path) throws IOException {
|
||||||
/* read properties before filtering */
|
/* read properties before filtering */
|
||||||
|
|
||||||
|
@ -106,4 +127,13 @@ public record Post(
|
||||||
|
|
||||||
return new Post(slug, title, summary, draft, revisions, createdBy, createdAt, modifiedBy, modifiedAt, custom, content);
|
return new Post(slug, title, summary, draft, revisions, createdBy, createdAt, modifiedBy, modifiedAt, custom, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the raw HTML content associated with the post.
|
||||||
|
*
|
||||||
|
* @return the raw HTML content as a string
|
||||||
|
*/
|
||||||
|
public String htmlContent() {
|
||||||
|
return rawContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,27 @@ import java.nio.file.Path;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code Site} class represents a website and its configuration.
|
||||||
|
*
|
||||||
|
* @param name the name of the site
|
||||||
|
* @param baseUrl the base URL of the site
|
||||||
|
* @param custom a map of additional custom properties
|
||||||
|
*/
|
||||||
public record Site(
|
public record Site(
|
||||||
String name,
|
String name,
|
||||||
String baseUrl,
|
String baseUrl,
|
||||||
|
|
||||||
Map<String, Object> custom
|
Map<String, Object> custom
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* Creates a {@link Site} object by reading and parsing the configuration file at the specified path.<br>
|
||||||
|
* The configuration file must be a JSON file.
|
||||||
|
*
|
||||||
|
* @param path the path to the configuration file
|
||||||
|
* @return a {@link Site} object initialized with the data from the configuration file
|
||||||
|
* @throws IOException if an error occurs during file reading
|
||||||
|
*/
|
||||||
public static Site fromConfig(Path path) throws IOException {
|
public static Site fromConfig(Path path) throws IOException {
|
||||||
var content = Files.readString(path);
|
var content = Files.readString(path);
|
||||||
var json = new JSONObject(content);
|
var json = new JSONObject(content);
|
||||||
|
@ -41,36 +56,4 @@ public record Site(
|
||||||
name, baseUrl, custom
|
name, baseUrl, custom
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remained from gson
|
|
||||||
|
|
||||||
private static Map<String, Object> deep(JsonObject jsonObject) {
|
|
||||||
return jsonObject.entrySet().stream()
|
|
||||||
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), eToO(e.getValue())))
|
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object eToO(JsonElement element) {
|
|
||||||
if (element.isJsonArray()) {
|
|
||||||
return element.getAsJsonArray().asList().stream().map(Site::eToO).toList();
|
|
||||||
} else if (element.isJsonObject()) {
|
|
||||||
return deep(element.getAsJsonObject());
|
|
||||||
} else if (element.isJsonPrimitive()) {
|
|
||||||
try {
|
|
||||||
return element.getAsBoolean();
|
|
||||||
} catch (IllegalStateException e) { }
|
|
||||||
|
|
||||||
try {
|
|
||||||
return element.getAsLong();
|
|
||||||
} catch (NumberFormatException e) { }
|
|
||||||
|
|
||||||
try {
|
|
||||||
return element.getAsDouble();
|
|
||||||
} catch (NumberFormatException e) { }
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue