AsciiDocToFx.java

1
package pro.verron.officestamper.asciidoc;
2
3
import javafx.geometry.Insets;
4
import javafx.scene.Scene;
5
import javafx.scene.control.ScrollPane;
6
import javafx.scene.layout.Priority;
7
import javafx.scene.layout.VBox;
8
import javafx.scene.text.*;
9
import javafx.scene.text.Text;
10
11
import java.util.List;
12
13
import static pro.verron.officestamper.asciidoc.AsciiDocModel.*;
14
15
/// Renders [AsciiDocModel] into a JavaFX [Scene].
16
public final class AsciiDocToFx {
17
18
    private static void emitInline(TextFlow flow, Inline inline, Font base, FontWeight weight, FontPosture posture) {
19
        switch (inline) {
20
            case AsciiDocModel.Text(String text) -> {
21
                flow.getChildren()
22
                    .add(styledText(text, base, weight, posture));
23
                return;
24
            }
25
            case Bold(List<Inline> children) -> {
26
                for (Inline child : children) {
27 1 1. emitInline : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                    emitInline(flow, child, base, FontWeight.BOLD, posture);
28
                }
29
                return;
30
            }
31
            case Italic(List<Inline> children) -> {
32
                for (Inline child : children) {
33 1 1. emitInline : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                    emitInline(flow, child, base, weight, FontPosture.ITALIC);
34
                }
35
                return;
36
            }
37
            case Link link -> {
38
                Text t = styledText(link.text(), base, weight, posture);
39 1 1. emitInline : removed call to javafx/scene/text/Text::setUnderline → NO_COVERAGE
                t.setUnderline(true);
40 1 1. emitInline : removed call to javafx/scene/text/Text::setFill → NO_COVERAGE
                t.setFill(javafx.scene.paint.Color.BLUE);
41
                flow.getChildren()
42
                    .add(t);
43
            }
44
            default -> { /* DO NOTHING */ }
45
        }
46 1 1. emitInline : negated conditional → NO_COVERAGE
        if (inline instanceof InlineImage ii) {
47
            flow.getChildren()
48
                .add(new Text("[Image: " + ii.path() + "]"));
49
        }
50
    }
51
52
    private static Font fontForHeading(int level) {
53
        double size = switch (level) {
54
            case 1 -> 24;
55
            case 2 -> 20;
56
            case 3 -> 18;
57
            case 4 -> 16;
58
            case 5 -> 14;
59
            default -> 13;
60
        };
61 1 1. fontForHeading : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::fontForHeading → NO_COVERAGE
        return Font.font(Font.getDefault()
62
                             .getFamily(), FontWeight.BOLD, size);
63
    }
64
65
    private static Text styledText(String value, Font base, FontWeight weight, FontPosture posture) {
66
        Text t = new Text(value);
67 1 1. styledText : removed call to javafx/scene/text/Text::setFont → NO_COVERAGE
        t.setFont(Font.font(base.getFamily(), weight, posture, base.getSize()));
68 1 1. styledText : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::styledText → NO_COVERAGE
        return t;
69
    }
70
71
    /// Compiles the model into a simple scrollable Scene using a VBox of TextFlow nodes.
72
    ///
73
    /// Headings are rendered with larger font sizes; bold/italic are applied per inline fragment.
74
    ///
75
    /// @param model parsed AsciiDoc model
76
    ///
77
    /// @return JavaFX scene containing the rendered content
78
    public Scene apply(AsciiDocModel model) {
79
        var rootBox = new VBox(8.0);
80 1 1. apply : removed call to javafx/scene/layout/VBox::setPadding → NO_COVERAGE
        rootBox.setPadding(new Insets(16));
81
82
        for (Block block : model.getBlocks()) {
83
            TextFlow flow = new TextFlow();
84
            switch (block) {
85 1 1. apply : negated conditional → NO_COVERAGE
                case Heading(_, int level, List<Inline> inlines) -> {
86
                    for (Inline inline : inlines) {
87 1 1. apply : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                        emitInline(flow, inline, fontForHeading(level), FontWeight.NORMAL, FontPosture.REGULAR);
88
                    }
89
                }
90
                case Paragraph(_, List<Inline> inlines) -> {
91
                    for (Inline inline : inlines) {
92 1 1. apply : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                        emitInline(flow, inline, Font.getDefault(), FontWeight.NORMAL, FontPosture.REGULAR);
93
                    }
94
                }
95
                case UnorderedList(List<ListItem> items1) -> {
96
                    for (ListItem item : items1) {
97
                        TextFlow itemFlow = new TextFlow();
98
                        itemFlow.getChildren()
99
                                .add(new Text("• "));
100
                        for (Inline inline : item.inlines()) {
101 1 1. apply : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                            emitInline(itemFlow, inline, Font.getDefault(), FontWeight.NORMAL, FontPosture.REGULAR);
102
                        }
103
                        rootBox.getChildren()
104
                               .add(itemFlow);
105
                    }
106
                    continue;
107
                }
108
                case OrderedList(List<ListItem> items) -> {
109
                    int i = 1;
110
                    for (ListItem item : items) {
111
                        TextFlow itemFlow = new TextFlow();
112 1 1. apply : Changed increment from 1 to -1 → NO_COVERAGE
                        itemFlow.getChildren()
113
                                .add(new Text((i++) + ". "));
114
                        for (Inline inline : item.inlines()) {
115 1 1. apply : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                            emitInline(itemFlow, inline, Font.getDefault(), FontWeight.NORMAL, FontPosture.REGULAR);
116
                        }
117
                        rootBox.getChildren()
118
                               .add(itemFlow);
119
                    }
120
                    continue;
121
                }
122
                case Blockquote(List<Inline> inlines) -> {
123 1 1. apply : removed call to javafx/scene/text/TextFlow::setPadding → NO_COVERAGE
                    flow.setPadding(new Insets(0, 0, 0, 20));
124
                    for (Inline inline : inlines) {
125 1 1. apply : removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE
                        emitInline(flow, inline, Font.getDefault(), FontWeight.NORMAL, FontPosture.ITALIC);
126
                    }
127
                }
128
                case CodeBlock cb -> {
129 1 1. apply : removed call to javafx/scene/text/TextFlow::setStyle → NO_COVERAGE
                    flow.setStyle("-fx-background-color: #f4f4f4; -fx-font-family: 'monospace';");
130
                    flow.getChildren()
131
                        .add(new Text(cb.content()));
132
                }
133
                case ImageBlock(String url, String altText) -> flow.getChildren()
134
                                                                   .add(new Text(
135
                                                                           "[Image: " + url + " - " + altText + "]"));
136
                default -> { /* Do NOTHING */ }
137
            }
138
            rootBox.getChildren()
139
                   .add(flow);
140
        }
141
142
        var scroll = new ScrollPane(rootBox);
143 1 1. apply : removed call to javafx/scene/control/ScrollPane::setFitToWidth → NO_COVERAGE
        scroll.setFitToWidth(true);
144 1 1. apply : removed call to javafx/scene/layout/VBox::setVgrow → NO_COVERAGE
        VBox.setVgrow(scroll, Priority.ALWAYS);
145 1 1. apply : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::apply → NO_COVERAGE
        return new Scene(scroll, 800, 600);
146
    }
147
}

Mutations

27

1.1
Location : emitInline
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

33

1.1
Location : emitInline
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

39

1.1
Location : emitInline
Killed by : none
removed call to javafx/scene/text/Text::setUnderline → NO_COVERAGE

40

1.1
Location : emitInline
Killed by : none
removed call to javafx/scene/text/Text::setFill → NO_COVERAGE

46

1.1
Location : emitInline
Killed by : none
negated conditional → NO_COVERAGE

61

1.1
Location : fontForHeading
Killed by : none
replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::fontForHeading → NO_COVERAGE

67

1.1
Location : styledText
Killed by : none
removed call to javafx/scene/text/Text::setFont → NO_COVERAGE

68

1.1
Location : styledText
Killed by : none
replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::styledText → NO_COVERAGE

80

1.1
Location : apply
Killed by : none
removed call to javafx/scene/layout/VBox::setPadding → NO_COVERAGE

85

1.1
Location : apply
Killed by : none
negated conditional → NO_COVERAGE

87

1.1
Location : apply
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

92

1.1
Location : apply
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

101

1.1
Location : apply
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

112

1.1
Location : apply
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

115

1.1
Location : apply
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

123

1.1
Location : apply
Killed by : none
removed call to javafx/scene/text/TextFlow::setPadding → NO_COVERAGE

125

1.1
Location : apply
Killed by : none
removed call to pro/verron/officestamper/asciidoc/AsciiDocToFx::emitInline → NO_COVERAGE

129

1.1
Location : apply
Killed by : none
removed call to javafx/scene/text/TextFlow::setStyle → NO_COVERAGE

143

1.1
Location : apply
Killed by : none
removed call to javafx/scene/control/ScrollPane::setFitToWidth → NO_COVERAGE

144

1.1
Location : apply
Killed by : none
removed call to javafx/scene/layout/VBox::setVgrow → NO_COVERAGE

145

1.1
Location : apply
Killed by : none
replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocToFx::apply → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.22.1