1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.devacfr.maven.skins.reflow.snippet;
17
18 import static java.util.Objects.requireNonNull;
19
20 import javax.annotation.Nonnull;
21 import org.apache.commons.lang3.builder.ToStringBuilder;
22 import org.apache.velocity.context.Context;
23 import org.devacfr.maven.skins.reflow.JsoupUtils;
24 import org.jsoup.nodes.Document;
25 import org.jsoup.nodes.Element;
26 import org.jsoup.select.Elements;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30
31
32
33
34
35
36 public class SnippetComponent<T extends SnippetComponent<T>> extends Component<T> {
37
38
39
40
41
42
43
44 public enum Type {
45
46 webComponent,
47
48 shortcode
49 }
50
51 private static Logger LOGGER = LoggerFactory.getLogger(SnippetComponent.class);
52
53
54 private final Type type;
55
56 @Nonnull
57 public static SnippetComponent<?> createSnippet(@Nonnull final Element element,
58 final Component<?> parent,
59 final Type type) {
60 requireNonNull(element);
61 return new SnippetComponent<>(element, type).withParent(parent);
62 }
63
64
65
66
67
68
69
70 protected SnippetComponent(@Nonnull final Element element, @Nonnull final Type type) {
71 super(element);
72 this.type = requireNonNull(type);
73 this.addAttributes(element.attributes());
74 }
75
76
77
78
79 @Nonnull
80 public Type getType() {
81 return type;
82 }
83
84
85
86
87 @Override
88 protected @Nonnull SnippetComponent<?> getRootParent() {
89 return this;
90 }
91
92
93
94
95
96
97
98 public void render(final SnippetContext context) {
99 final Context renderContext = context.getConfig().getVelocityContext();
100 final Element element = getElement();
101 if (element == null) {
102 LOGGER.warn("Element is null for snippet component: {}, file:{}", this, context.getConfig().getFileId());
103 return;
104 }
105 try {
106 final String html = context.renderComponent(this, renderContext);
107
108 final Document doc = JsoupUtils.createHtmlDocument(html);
109 final Elements root = doc.body().children();
110 if (root.isEmpty()) {
111 element.remove();
112 return;
113 }
114
115 if (root.size() > 1 && root.first().tagName().equals("pre")) {
116 final Element div = new Element("div");
117 root.forEach((e) -> div.appendChild(e));
118 element.replaceWith(div);
119 } else {
120 for (final Element el : root) {
121
122 if (context.getParser().hasIncludedSnippetComponent(el)) {
123 final SnippetParser parser = context.createChildParser();
124 final Element childDoc = parser.parse(context.getConfig(), el.outerHtml()).document();
125 childDoc.children().forEach((e) -> element.before(e));
126 } else {
127 element.before(el);
128 }
129 }
130 element.remove();
131 }
132 } catch (final Exception e) {
133 LOGGER.error("Rendering Snippet component failed:{}, file:{}", this, context.getConfig().getFileId());
134 throw new RuntimeException(e.getMessage(), e);
135 }
136 }
137
138 @Override
139 public String toString() {
140 return ToStringBuilder.reflectionToString(this);
141 }
142
143 }