From 7efbbefdcf7d525e9671d66360ca41eb8d0965c5 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 10 Mar 2025 22:14:46 +0800 Subject: [PATCH] =?UTF-8?q?HTMLRenderer=20=E5=BA=94=E5=BD=93=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=8F=92=E5=85=A5=E8=BF=87=E5=A4=9A=E6=8D=A2=E8=A1=8C?= =?UTF-8?q?=E7=AC=A6=20(#3733)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/HTMLRenderer.java | 57 ++++++++++++++++++- .../org/jackhuang/hmcl/ui/UpgradeDialog.java | 1 + .../java/org/jackhuang/hmcl/ui/WebPage.java | 1 + 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java index dccedf77f..8f8556113 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java @@ -151,6 +151,12 @@ public final class HTMLRenderer { children.add(textNode); } + private void appendAutoLineBreak(String text) { + AutoLineBreak textNode = new AutoLineBreak(text); + applyStyle(textNode); + children.add(textNode); + } + private void appendImage(Node node) { String src = node.absUrl("src"); URI imageUri = null; @@ -230,7 +236,7 @@ public final class HTMLRenderer { case "h6": case "tr": if (!children.isEmpty()) - appendText("\n\n"); + appendAutoLineBreak("\n\n"); break; } @@ -252,15 +258,62 @@ public final class HTMLRenderer { case "h4": case "h5": case "h6": - appendText("\n"); + appendAutoLineBreak("\n"); break; } } + private static boolean isSpacing(String text) { + if (text == null) + return true; + + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (ch != ' ' && ch != '\t') + return false; + } + return true; + } + + public void mergeLineBreaks() { + for (int i = 0; i < this.children.size(); i++) { + javafx.scene.Node child = this.children.get(i); + if (child instanceof AutoLineBreak) { + int lastAutoLineBreak = -1; + + for (int j = i + 1; j < this.children.size(); j++) { + javafx.scene.Node otherChild = this.children.get(j); + + if (otherChild instanceof AutoLineBreak) { + lastAutoLineBreak = j; + } else if (otherChild instanceof Text && isSpacing(((Text) otherChild).getText())) { + // do nothing + } else { + break; + } + } + + if (lastAutoLineBreak > 0) { + this.children.subList(i + 1, lastAutoLineBreak + 1).clear(); + + if (((Text) child).getText().length() == 1) { + ((Text) child).setText("\n\n"); + } + } + } + } + } + public TextFlow render() { TextFlow textFlow = new TextFlow(); textFlow.getStyleClass().add("html"); textFlow.getChildren().setAll(children); return textFlow; } + + private static final class AutoLineBreak extends Text { + public AutoLineBreak(String text) { + super(text); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java index 61d0f63bc..69e51c595 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java @@ -64,6 +64,7 @@ public final class UpgradeDialog extends JFXDialogLayout { node = node.nextSibling(); } while (node != null); + renderer.mergeLineBreaks(); return renderer.render(); }).whenComplete(Schedulers.javafx(), (result, exception) -> { if (exception == null) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java index 96c23f51a..2542d698f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java @@ -53,6 +53,7 @@ public final class WebPage extends SpinnerPane implements DecoratorPage { }, null); }); renderer.appendNode(document); + renderer.mergeLineBreaks(); return renderer.render(); }).whenComplete(Schedulers.javafx(), ((result, exception) -> { if (exception == null) {