package eu.m724.blog; import eu.m724.blog.data.Feed; import eu.m724.blog.data.Post; import eu.m724.blog.data.Site; import org.apache.commons.io.file.PathUtils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.RepositoryBuilder; import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Comparator; import java.util.stream.Collectors; public class BlogBuilder { private final Git git; private final Path workingDirectory; private Site site; private TemplateRenderer template; private Path templateDirectory; private Path outputDirectory; private boolean renderDrafts = false; public BlogBuilder(Git git) { this.git = git; this.workingDirectory = git.getRepository().getDirectory().toPath().getParent(); this.templateDirectory = workingDirectory.resolve("template"); this.outputDirectory = workingDirectory.resolve("generated_out"); } public static BlogBuilder fromPath(Path workingDirectory) throws IOException { var repository = new RepositoryBuilder() .setGitDir(workingDirectory.resolve(".git").toFile()) .build(); var git = new Git(repository); // return new BlogBuilder(git); } public BlogBuilder templateDirectory(Path templateDirectory) { this.templateDirectory = templateDirectory; return this; } public BlogBuilder outputDirectory(Path outputDirectory) { this.outputDirectory = outputDirectory; return this; } public BlogBuilder renderDrafts(boolean renderDrafts) { this.renderDrafts = renderDrafts; return this; } public void mkdirs(boolean force) throws IOException { if (outputDirectory.toFile().exists()) { if (force) { PathUtils.deleteDirectory(outputDirectory); } else { throw new FileAlreadyExistsException(outputDirectory.toString(), null, "Output directory already exists. --force?"); } } Files.createDirectory(outputDirectory); } public void build() throws IOException { if (site == null) this.site = Site.fromConfig(workingDirectory.resolve("site-config.json")); if (template == null) this.template = new TemplateRenderer(templateDirectory); copyIfExists(workingDirectory.resolve("assets"), outputDirectory.resolve("assets")); copyIfExists(templateDirectory.resolve("static"), outputDirectory.resolve("static")); Files.createDirectory(outputDirectory.resolve("post")); var postDirectory = workingDirectory.resolve("posts"); var posts = new ArrayList(); try (var stream = Files.walk(postDirectory)) { for (var path : stream.collect(Collectors.toSet())) { if (!Files.isRegularFile(path)) continue; // directory is created below if (!path.toString().endsWith(".html")) { System.out.println("Post " + path.getFileName() + ": unsupported file type"); continue; } path = postDirectory.relativize(path); var post = Post.fromFile(git, path); if (post.draft() && !renderDrafts) { System.out.println("Post " + path.getFileName() + ": draft, ignoring"); continue; } var render = template.renderPost(site, post); var outFile = outputDirectory.resolve("post").resolve(path); try { Files.createDirectory(outFile.getParent()); } catch (FileAlreadyExistsException ignored) { } Files.writeString(outFile, render); posts.add(post); } } posts.sort(Comparator.comparing(Post::createdAt).reversed()); Files.writeString(outputDirectory.resolve("index.html"), template.renderIndex(site, posts)); Files.writeString(outputDirectory.resolve("posts.rss"), Feed.generateRss(site, posts)); } /* Internal functions */ private boolean copyTree(Path srcDir, Path destDir) throws IOException { if (!Files.isDirectory(srcDir)) { return false; } try (var walk = Files.walk(srcDir)) { for (var src : walk.collect(Collectors.toSet())) { var rel = srcDir.relativize(src); var dest = destDir.resolve(rel); if (Files.isRegularFile(src)) { var parent = dest.getParent(); if (!Files.isDirectory(parent)) { Files.createDirectories(parent); } Files.copy(src, dest); } } } return true; } private void copyIfExists(Path srcDir, Path destDir) throws IOException { System.out.print(srcDir); if (copyTree(srcDir, destDir)) { System.out.println(" copied"); } else { System.out.println(" doesn't exist, not copying"); } } }