server and more
This commit is contained in:
parent
b6031b93e6
commit
dd28fde073
5 changed files with 94 additions and 26 deletions
5
pom.xml
5
pom.xml
|
@ -41,6 +41,11 @@
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>2.16.1</version>
|
<version>2.16.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>in.wilsonl.minifyhtml</groupId>
|
||||||
|
<artifactId>minify-html</artifactId>
|
||||||
|
<version>0.15.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -11,6 +11,8 @@ import java.io.IOException;
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
@ -49,6 +51,8 @@ public class Main {
|
||||||
|
|
||||||
Files.createDirectory(outputDirectory.resolve("post"));
|
Files.createDirectory(outputDirectory.resolve("post"));
|
||||||
var postDirectory = workingDirectory.resolve("posts");
|
var postDirectory = workingDirectory.resolve("posts");
|
||||||
|
var posts = new ArrayList<Post>();
|
||||||
|
|
||||||
try (var stream = Files.walk(postDirectory)) {
|
try (var stream = Files.walk(postDirectory)) {
|
||||||
for (var path : stream.collect(Collectors.toSet())) {
|
for (var path : stream.collect(Collectors.toSet())) {
|
||||||
if (!Files.isRegularFile(path)) continue;
|
if (!Files.isRegularFile(path)) continue;
|
||||||
|
@ -66,13 +70,17 @@ public class Main {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.createDirectory(outFile.getParent());
|
Files.createDirectory(outFile.getParent());
|
||||||
} catch (FileAlreadyExistsException e) {
|
} catch (FileAlreadyExistsException ignored) { }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.writeString(outFile, render);
|
Files.writeString(outFile, render);
|
||||||
|
posts.add(post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
posts.sort(Comparator.comparing(Post::createdAt).reversed());
|
||||||
|
Files.writeString(outputDirectory.resolve("index.html"), template.renderIndex(site, posts));
|
||||||
|
|
||||||
|
new Server(outputDirectory).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
50
src/main/java/eu/m724/blog/Server.java
Normal file
50
src/main/java/eu/m724/blog/Server.java
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package eu.m724.blog;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
|
import com.sun.net.httpserver.HttpServer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class Server implements HttpHandler {
|
||||||
|
private final InetSocketAddress listenAddress = new InetSocketAddress("localhost",8010);
|
||||||
|
private final Path directory;
|
||||||
|
|
||||||
|
public Server(Path directory) {
|
||||||
|
this.directory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() throws IOException {
|
||||||
|
var server = HttpServer.create(listenAddress, 0);
|
||||||
|
server.createContext("/", this);
|
||||||
|
server.start();
|
||||||
|
System.out.println("Server started on " + listenAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpExchange exchange) throws IOException {
|
||||||
|
var path = directory.resolve(exchange.getRequestURI().getPath().substring(1));
|
||||||
|
|
||||||
|
if (Files.isDirectory(path)) {
|
||||||
|
path = path.resolve("index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = 404;
|
||||||
|
var content = "Not found".getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
if (Files.isRegularFile(path)) {
|
||||||
|
code = 200;
|
||||||
|
content = Files.readAllBytes(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
exchange.sendResponseHeaders(code, content.length);
|
||||||
|
|
||||||
|
var body = exchange.getResponseBody();
|
||||||
|
body.write(content);
|
||||||
|
body.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,8 @@ public record Post(
|
||||||
Map<String, String> custom,
|
Map<String, String> custom,
|
||||||
String rawContent
|
String rawContent
|
||||||
) {
|
) {
|
||||||
public String getHtmlContent() {
|
// this is because we'll be not only supporting html
|
||||||
|
public String htmlContent() {
|
||||||
return rawContent;
|
return rawContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +34,8 @@ public record Post(
|
||||||
/* read properties before filtering */
|
/* read properties before filtering */
|
||||||
|
|
||||||
var slug = path.getFileName().toString().split("\\.")[0];
|
var slug = path.getFileName().toString().split("\\.")[0];
|
||||||
var lines = Files.readAllLines(git.getRepository().getDirectory().toPath().resolve("posts").resolve(path));
|
path = Path.of("posts").resolve(path);
|
||||||
|
var lines = Files.readAllLines(git.getRepository().getDirectory().toPath().resolve(path));
|
||||||
|
|
||||||
var properties = new HashMap<String, String>();
|
var properties = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@ -55,9 +57,9 @@ public record Post(
|
||||||
|
|
||||||
/* filter properties from read file */
|
/* filter properties from read file */
|
||||||
|
|
||||||
String title = null;
|
String title = "NO TITLE SET";
|
||||||
String summary = null;
|
String summary = "NO SUMMARY SET";
|
||||||
boolean draft = false;
|
boolean draft = true;
|
||||||
|
|
||||||
var custom = new HashMap<String, String>();
|
var custom = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@ -71,8 +73,8 @@ public record Post(
|
||||||
case "summary":
|
case "summary":
|
||||||
summary = value;
|
summary = value;
|
||||||
break;
|
break;
|
||||||
case "draft": // a post is a draft if the key is there
|
case "live": // a post is live (not draft) if the key is there
|
||||||
draft = true;
|
draft = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
custom.put(property.getKey(), value);
|
custom.put(property.getKey(), value);
|
||||||
|
@ -82,16 +84,13 @@ public record Post(
|
||||||
/* get revisions */
|
/* get revisions */
|
||||||
|
|
||||||
int revisions = 0;
|
int revisions = 0;
|
||||||
String createdBy = null;
|
String createdBy = "UNKNOWN AUTHOR";
|
||||||
ZonedDateTime createdAt = null;
|
ZonedDateTime createdAt = Instant.ofEpochMilli(0).atZone(ZoneOffset.UTC);
|
||||||
String modifiedBy = null;
|
String modifiedBy = "UNKNOWN AUTHOR";
|
||||||
ZonedDateTime modifiedAt = null;
|
ZonedDateTime modifiedAt = Instant.ofEpochMilli(0).atZone(ZoneOffset.UTC);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var commits = git.log().addPath("posts/" + slug + ".html").call().iterator();
|
for (var commit : git.log().addPath(path.toString()).call()) {
|
||||||
|
|
||||||
while (commits.hasNext()) {
|
|
||||||
var commit = commits.next();
|
|
||||||
createdBy = commit.getAuthorIdent().getName();
|
createdBy = commit.getAuthorIdent().getName();
|
||||||
createdAt = Instant.ofEpochSecond(commit.getCommitTime()).atZone(ZoneOffset.UTC);
|
createdAt = Instant.ofEpochSecond(commit.getCommitTime()).atZone(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ public record Post(
|
||||||
}
|
}
|
||||||
} catch (GitAPIException e) {
|
} catch (GitAPIException e) {
|
||||||
draft = true;
|
draft = true;
|
||||||
System.out.printf("%s: Git exception, assuming draft: %s\n", slug, e.getMessage());
|
System.out.printf("%s: Git exception, making draft: %s\n", slug, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package eu.m724.blog.data;
|
package eu.m724.blog.data;
|
||||||
|
|
||||||
|
import in.wilsonl.minifyhtml.Configuration;
|
||||||
|
import in.wilsonl.minifyhtml.MinifyHtml;
|
||||||
import io.pebbletemplates.pebble.PebbleEngine;
|
import io.pebbletemplates.pebble.PebbleEngine;
|
||||||
import io.pebbletemplates.pebble.loader.FileLoader;
|
import io.pebbletemplates.pebble.loader.FileLoader;
|
||||||
import io.pebbletemplates.pebble.template.PebbleTemplate;
|
import io.pebbletemplates.pebble.template.PebbleTemplate;
|
||||||
|
@ -7,19 +9,23 @@ import io.pebbletemplates.pebble.template.PebbleTemplate;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
|
||||||
public class Template {
|
public class Template {
|
||||||
private final PebbleEngine pebbleEngine;
|
private final Configuration configuration;
|
||||||
|
|
||||||
private final PebbleTemplate indexTemplate, articleTemplate;
|
private final PebbleTemplate indexTemplate, articleTemplate;
|
||||||
|
|
||||||
public Template(Path directory) {
|
public Template(Path directory) {
|
||||||
|
this.configuration = new Configuration.Builder()
|
||||||
|
.setMinifyCss(true)
|
||||||
|
.setMinifyJs(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
var loader = new FileLoader();
|
var loader = new FileLoader();
|
||||||
loader.setPrefix(directory.toString());
|
loader.setPrefix(directory.toString());
|
||||||
loader.setSuffix(".html");
|
loader.setSuffix(".html");
|
||||||
|
|
||||||
this.pebbleEngine = new PebbleEngine.Builder()
|
var pebbleEngine = new PebbleEngine.Builder()
|
||||||
.loader(loader)
|
.loader(loader)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -27,7 +33,7 @@ public class Template {
|
||||||
this.articleTemplate = pebbleEngine.getTemplate("article_template");
|
this.articleTemplate = pebbleEngine.getTemplate("article_template");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String renderIndex(Site site, 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,
|
||||||
"articles", posts
|
"articles", posts
|
||||||
|
@ -36,7 +42,7 @@ public class Template {
|
||||||
var writer = new StringWriter();
|
var writer = new StringWriter();
|
||||||
indexTemplate.evaluate(writer, context);
|
indexTemplate.evaluate(writer, context);
|
||||||
|
|
||||||
return writer.toString();
|
return MinifyHtml.minify(writer.toString(), configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String renderPost(Site site, Post post) throws IOException {
|
public String renderPost(Site site, Post post) throws IOException {
|
||||||
|
@ -48,6 +54,6 @@ public class Template {
|
||||||
var writer = new StringWriter();
|
var writer = new StringWriter();
|
||||||
articleTemplate.evaluate(writer, context);
|
articleTemplate.evaluate(writer, context);
|
||||||
|
|
||||||
return writer.toString();
|
return MinifyHtml.minify(writer.toString(), configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue