在 Java 處理 Markdown 文件,可使用 flexmark 套件,而 JavaFX,是使用 openjfx,因為 jfx 並不在 openjdk 裡面。
這邊因為使用舊版的 macos,所以使用很舊版本的openjfx
<!-- markdown -->
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-all</artifactId>
<version>0.64.8</version>
</dependency>
<!-- java FX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>17.0.2</version>
</dependency>
pom.xml下面的 plugin 這樣寫
<build>
<plugins>
<!-- JavaFX Maven Plugin -->
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>MarkdownViewerApp</mainClass>
</configuration>
</plugin>
<!-- Build fat JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.7.1</version>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Java compiler -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
MarkdownTable
在 flexmark,要處理 table 時,需要加入 extension,以下是一個處理 Markdown Table 的 sample
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import java.util.Arrays;
public class MarkdownTableExample {
public static void main(String[] args) {
String markdown =
"| Name | Age |\n" +
"|-------|-----|\n" +
"| John | 30 |\n" +
"| Alice | 25 |";
MutableDataSet options = new MutableDataSet();
options.set(Parser.EXTENSIONS, Arrays.asList(TablesExtension.create()));
Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build();
String html = renderer.render(parser.parse(markdown));
System.out.println(html);
}
}
執行結果
<table>
<thead>
<tr><th>Name</th><th>Age</th></tr>
</thead>
<tbody>
<tr><td>John</td><td>30</td></tr>
<tr><td>Alice</td><td>25</td></tr>
</tbody>
</table>
Process finished with exit code 0
MarkdownViewer
html table 加上 css
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.util.data.MutableDataSet;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Scanner;
public class MarkdownViewerApp extends Application {
private MutableDataSet options;
private Parser parser;
private HtmlRenderer renderer;
@Override
public void start(Stage primaryStage) {
options = new MutableDataSet();
options.set(Parser.EXTENSIONS, Arrays.asList(TablesExtension.create()));
parser = Parser.builder(options).build();
renderer = HtmlRenderer.builder(options).build();
// CSS
String css = """
body {
font-family: sans-serif;
margin: 20px;
line-height: 1.6;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ccc;
padding: 6px 10px;
}
th {
background-color: #f0f0f0;
}
""";
TextArea markdownInput = new TextArea();
WebView htmlView = new WebView();
// Default text
// markdownInput.setText("# Hello Markdown\n\nThis is **bold** and this is _italic_.");
try (InputStream in = getClass().getResourceAsStream("/test.md")) {
if (in != null) {
Scanner scanner = new Scanner(in, StandardCharsets.UTF_8).useDelimiter("\\A");
String htmlContent = scanner.hasNext() ? scanner.next() : "";
markdownInput.setText(htmlContent);
}
} catch (Exception e) {
e.printStackTrace();
}
// Convert and display Markdown as HTML
markdownInput.textProperty().addListener((obs, oldVal, newVal) -> {
Node document = parser.parse(newVal);
String htmlBody = renderer.render(document);
String html = """
<html>
<head>
<style>%s</style>
</head>
<body>
%s
</body>
</html>
""".formatted(css, htmlBody);
htmlView.getEngine().loadContent(html);
});
// Initial render
Node document = parser.parse(markdownInput.getText());
String htmlBody = renderer.render(document);
String html = """
<html>
<head>
<style>%s</style>
</head>
<body>
%s
</body>
</html>
""".formatted(css, htmlBody);
htmlView.getEngine().loadContent(html);
BorderPane root = new BorderPane();
root.setLeft(markdownInput);
root.setCenter(htmlView);
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("JavaFX Markdown Viewer");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
可直接用 mvn 啟動
mvn javafx:run
獨立執行需下載 openjfx sdk,可到 JavaFX - Gluon 下載,openjfx-17.0.2_osx-x64_bin-sdk.zip
執行 mvn package 可產生 jar,然後就能這樣啟動
java --module-path ~/Downloads/javafx-sdk-17.0.2/lib/ --add-modules javafx.controls,javafx.web -jar target/markdownviewer-1.0-SNAPSHOT-jar-with-dependencies.jar MarkdownViewerApp
這是執行結果

沒有留言:
張貼留言