|
2 | 2 |
|
3 | 3 | import javafx.geometry.Insets;
|
4 | 4 | import javafx.scene.control.Button;
|
| 5 | +import javafx.scene.control.Hyperlink; |
5 | 6 | import javafx.scene.control.Label;
|
6 | 7 | import javafx.scene.layout.BorderPane;
|
7 | 8 | import javafx.scene.layout.GridPane;
|
|
11 | 12 | import me.coley.recaf.ui.controls.ActionButton;
|
12 | 13 | import me.coley.recaf.ui.controls.ExceptionAlert;
|
13 | 14 | import me.coley.recaf.util.Log;
|
| 15 | +import me.coley.recaf.util.UiUtil; |
14 | 16 | import me.coley.recaf.util.self.SelfUpdater;
|
15 | 17 | import org.commonmark.node.*;
|
16 | 18 | import org.commonmark.parser.Parser;
|
17 | 19 |
|
18 | 20 | import java.io.IOException;
|
| 21 | +import java.net.URL; |
| 22 | +import java.util.function.Consumer; |
19 | 23 |
|
20 | 24 | import static me.coley.recaf.util.LangUtil.translate;
|
21 | 25 |
|
@@ -60,58 +64,94 @@ private BorderPane getHeader() {
|
60 | 64 | private BorderPane getNotes() {
|
61 | 65 | TextFlow flow = new TextFlow();
|
62 | 66 | Parser parser = Parser.builder().build();
|
63 |
| - Node document = parser.parse(SelfUpdater.getLatestPatchnotes().replaceAll("\\(\\[.+\\)\\)", "")); |
| 67 | + Node document = parser.parse(SelfUpdater.getLatestPatchnotes()); |
64 | 68 | document.accept(new AbstractVisitor() {
|
65 | 69 | @Override
|
66 | 70 | public void visit(Paragraph paragraph) {
|
67 |
| - StringBuilder sb = new StringBuilder(); |
68 |
| - Node node = paragraph.getFirstChild(); |
69 |
| - build(sb, node); |
70 |
| - addLine(sb.toString(), null); |
| 71 | + // Add all content to same line |
| 72 | + parse(paragraph, this::text, this::link); |
| 73 | + newLine(); |
71 | 74 | }
|
72 | 75 |
|
73 | 76 | @Override
|
74 | 77 | public void visit(Heading heading) {
|
75 | 78 | // Skip the version H2 text
|
76 | 79 | if (heading.getLevel() <= 2)
|
77 | 80 | return;
|
78 |
| - addLine(build(heading), "h2"); |
| 81 | + // Extract heading text |
| 82 | + StringBuilder sb = new StringBuilder(); |
| 83 | + parse(heading, text -> sb.append(text.getLiteral()), null); |
| 84 | + // Render |
| 85 | + addText(sb.toString(), "h2"); |
| 86 | + newLine(); |
79 | 87 | }
|
80 | 88 |
|
81 | 89 | @Override
|
82 | 90 | public void visit(BulletList list) {
|
83 | 91 | Node item = list.getFirstChild();
|
84 | 92 | do {
|
85 |
| - String itemText = build(item); |
86 |
| - addLine(" ● " + itemText, null); |
| 93 | + // Prefix with bullet point |
| 94 | + addText(" ● ", null); |
| 95 | + // Add all content to same line |
| 96 | + parse(item, this::text, this::link); |
| 97 | + // New line between items |
| 98 | + newLine(); |
87 | 99 | item = item.getNext();
|
88 | 100 | } while (item != null);
|
89 | 101 | }
|
90 | 102 |
|
91 |
| - private String build(Node node) { |
92 |
| - StringBuilder sb = new StringBuilder(); |
93 |
| - build(sb, node); |
94 |
| - return sb.toString(); |
| 103 | + private void text(Text text) { |
| 104 | + addText(text.getLiteral(), null); |
| 105 | + } |
| 106 | + |
| 107 | + private void link(Link link) { |
| 108 | + String text = link.getTitle(); |
| 109 | + if (text == null) { |
| 110 | + StringBuilder sb = new StringBuilder(); |
| 111 | + parse(link, t -> sb.append(t.getLiteral()), null); |
| 112 | + text = sb.toString(); |
| 113 | + } |
| 114 | + addLink(text, link.getDestination()); |
95 | 115 | }
|
96 | 116 |
|
97 |
| - private void build(StringBuilder sb, Node node) { |
98 |
| - if (node instanceof Text) |
99 |
| - sb.append(((Text) node).getLiteral()); |
100 |
| - else { |
| 117 | + private void parse(Node node, Consumer<Text> textHandler, Consumer<Link> linkHandler) { |
| 118 | + if (node instanceof Text) { |
| 119 | + if (textHandler != null) textHandler.accept((Text) node); |
| 120 | + } else if (linkHandler != null && node instanceof Link) { |
| 121 | + linkHandler.accept((Link) node); |
| 122 | + } else { |
101 | 123 | Node child = node.getFirstChild();
|
102 | 124 | do {
|
103 |
| - build(sb, child); |
| 125 | + parse(child, textHandler, linkHandler); |
104 | 126 | child = child.getNext();
|
105 | 127 | } while (child != null);
|
106 | 128 | }
|
107 | 129 | }
|
108 | 130 |
|
109 |
| - private void addLine(String text, String style) { |
110 |
| - javafx.scene.text.Text t = new javafx.scene.text.Text(text + "\n"); |
| 131 | + private void addLink(String text, String url) { |
| 132 | + Hyperlink link = new Hyperlink(text); |
| 133 | + link.getStyleClass().add("a"); |
| 134 | + link.setOnAction(e -> { |
| 135 | + try { |
| 136 | + UiUtil.showDocument(new URL(url).toURI()); |
| 137 | + } catch (Exception ex) { |
| 138 | + Log.error("Could not open URL: " + url); |
| 139 | + } |
| 140 | + }); |
| 141 | + flow.getChildren().add(link); |
| 142 | + } |
| 143 | + |
| 144 | + private void addText(String text, String style) { |
| 145 | + javafx.scene.text.Text t = new javafx.scene.text.Text(text); |
111 | 146 | if (style != null)
|
112 | 147 | t.getStyleClass().add(style);
|
113 | 148 | flow.getChildren().add(t);
|
114 | 149 | }
|
| 150 | + |
| 151 | + private void newLine() { |
| 152 | + javafx.scene.text.Text t = new javafx.scene.text.Text("\n"); |
| 153 | + flow.getChildren().add(t); |
| 154 | + } |
115 | 155 | });
|
116 | 156 | BorderPane pane = new BorderPane(flow);
|
117 | 157 | pane.getStyleClass().add("content");
|
|
0 commit comments