Last active 1751784195

Converts Ghost export to Markdown

Revision de01baf8813587d064cf78a67f7d4641fd3dd4c2

ghost2md.java Raw
1///usr/bin/env jbang "$0" "$@" ; exit $?
2//
3// This is a JBang script. You need JBang to run this script.
4//
5// To learn more go to https://www.jbang.dev and install JBang.
6//
7// Run this script:
8// ./ghost2md.java -f <input file> -d <output directory>
9//
10//DEPS info.picocli:picocli:4.7.7
11//DEPS com.jayway.jsonpath:json-path:2.8.0
12//DEPS com.fasterxml.jackson.core:jackson-databind:2.19.0
13//DEPS io.github.furstenheim:copy_down:1.1
14//JAVA 21+
15
16import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
17import com.jayway.jsonpath.Configuration;
18import com.jayway.jsonpath.JsonPath;
19import com.jayway.jsonpath.ParseContext;
20import com.jayway.jsonpath.TypeRef;
21import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
22
23import io.github.furstenheim.CopyDown;
24import picocli.CommandLine;
25import picocli.CommandLine.Command;
26import picocli.CommandLine.Option;
27import java.io.File;
28import java.io.FileWriter;
29import java.util.List;
30import java.util.concurrent.Callable;
31
32@Command(name = "ghost2md", mixinStandardHelpOptions = true, version = "0.1", description = "Converts a Ghost export file to markdown files")
33public class ghost2md implements Callable<Integer> {
34
35 private static final ParseContext JSON = JsonPath.using(Configuration.builder().mappingProvider(new JacksonMappingProvider()).build());
36 private static final CopyDown HTML_TO_MD = new CopyDown();
37
38 @Option(names = { "--file", "-f" }, required = true, description = "The exported Ghost JSON file")
39 private File exportFile;
40
41 @Option(names = { "--dir", "-d" }, defaultValue = "exported", description = "The destination directory")
42 private File destinationDir;
43
44 @Override
45 public Integer call() throws Exception {
46 if (!exportFile.exists()) {
47 System.err.printf("%s does not exist%n", exportFile.getAbsolutePath());
48 return 404;
49 }
50
51 destinationDir.mkdirs();
52
53 var json = JSON.parse(exportFile);
54 var posts = json.read("$.db[*].data.posts[*]", new TypeRef<List<Post>>(){});
55 for (var post : posts) {
56 var filename = post.slug() + ".md";
57 var markdown = HTML_TO_MD.convert(post.html());
58 var file = new File(destinationDir, filename);
59 var title = "# " + post.title();
60 System.out.printf("Writing %s\n", file);
61 try (var writer = new FileWriter(file)) {
62 writer.write(title);
63 writer.write("\n\n");
64 writer.write(markdown);
65 }
66 }
67 return 0;
68 }
69
70 @JsonIgnoreProperties(ignoreUnknown = true)
71 record Post(String slug, String title, String html){}
72
73 public static void main(String[] args) {
74 final int exitCode = new CommandLine(new ghost2md()).execute(args);
75 System.exit(exitCode);
76 }
77
78}