1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.devacfr.maven.skins.reflow.context;
20
21 import javax.annotation.Nonnull;
22
23 import java.io.IOException;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27
28 import com.google.common.collect.ImmutableMap;
29 import com.google.common.collect.Lists;
30 import org.apache.commons.lang3.builder.ToStringBuilder;
31 import org.codehaus.plexus.util.xml.Xpp3Dom;
32 import org.devacfr.maven.skins.reflow.HtmlTool;
33 import org.devacfr.maven.skins.reflow.ISkinConfig;
34 import org.devacfr.maven.skins.reflow.model.Component;
35 import org.devacfr.maven.skins.reflow.model.Footer;
36 import org.devacfr.maven.skins.reflow.model.NavSideMenu;
37 import org.devacfr.maven.skins.reflow.model.Navbar;
38 import org.devacfr.maven.skins.reflow.model.ScrollTop;
39 import org.devacfr.maven.skins.reflow.model.SideNavMenuItem;
40 import org.devacfr.maven.skins.reflow.snippet.SnippetContext;
41 import org.devacfr.maven.skins.reflow.snippet.SnippetParser;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import static java.util.Objects.requireNonNull;
46
47
48
49
50
51
52
53
54
55 public abstract class Context<T extends Context<?>> extends Component {
56
57
58
59
60 private static final Map<String, String> ICON_REPLACEMENTS = ImmutableMap.<String, String> builder()
61 .put("img[src$=images/add.gif]", "<i class=\"fas fa-plus\"></i>")
62 .put("img[src$=images/remove.gif]", "<i class=\"fas fa-minus\"></i>")
63 .put("img[src$=images/fix.gif]", "<i class=\"fas fa-wrench\"></i>")
64 .put("img[src$=images/update.gif]", "<i class=\"fas fa-redo\"></i>")
65 .put("img[src$=images/icon_help_sml.gif]", "<i class=\"fas fa-question\"></i>")
66 .put("img[src$=images/icon_success_sml.gif]", "<i class=\"fas fa-check-circle\"></i>")
67 .put("img[src$=images/icon_warning_sml.gif]", "<i class=\"fas fa-exclamation-triangle\"></i>")
68 .put("img[src$=images/icon_error_sml.gif]", "<i class=\"fas fa-exclamation-circle\"></i>")
69 .put("img[src$=images/icon_info_sml.gif]", "<i class=\"fas fa-info\"></i>")
70 .build();
71
72
73 private static final Logger LOGGER = LoggerFactory.getLogger(Context.class);
74
75
76 private ContextType type;
77
78
79 private final Navbar navbar;
80
81
82 private final Footer footer;
83
84
85 private final ScrollTop scrollTop;
86
87
88
89
90
91
92
93
94 @Nonnull
95 public static Context<?> buildContext(@Nonnull final ISkinConfig config) {
96 requireNonNull(config);
97
98 ContextType type = ContextType.page;
99 final List<SideNavMenuItem> allSideNaveMenuItems = NavSideMenu.findAllSideNavMenuItems(config);
100 if (LOGGER.isTraceEnabled()) {
101 LOGGER.trace("findAllSideNavMenuItems: " + allSideNaveMenuItems);
102 }
103 final Xpp3Dom pageProperties = config.getPageProperties();
104 final String fileId = config.getFileId();
105
106 if (pageProperties != null) {
107 if (pageProperties.getAttribute("type") != null) {
108 type = ContextType.valueOf(pageProperties.getAttribute("type"));
109 }
110
111
112 if (allSideNaveMenuItems.stream().filter(item -> fileId.equals(item.getSlugName())).count() > 0) {
113 type = ContextType.frame;
114 }
115 }
116
117
118
119 Context<?> context = null;
120 switch (type) {
121 case doc:
122 context = new DocumentContext(config);
123 break;
124
125 case frame:
126
127 final Optional<SideNavMenuItem> menuItem = allSideNaveMenuItems.stream()
128 .filter(item -> fileId.equals(item.getSlugName()))
129 .findFirst();
130 final SideNavMenuItem item = menuItem.get();
131 final String documentParent = item.getParent();
132 context = new FrameContext(config, documentParent);
133 break;
134 case body:
135 context = new BodyContext(config);
136 break;
137 case page:
138 default:
139 context = new PageContext(config);
140 break;
141 }
142 return context;
143 }
144
145
146
147
148
149
150
151
152
153 public Context(@Nonnull final ISkinConfig config, @Nonnull final ContextType type) {
154 requireNonNull(config);
155 this.withType(requireNonNull(type));
156 this.navbar = new Navbar(config);
157 this.scrollTop = new ScrollTop(config);
158 this.footer = new Footer(config);
159
160 this.initialize(config);
161
162
163 this.addChildren(this.navbar, this.scrollTop, this.footer);
164 }
165
166
167
168
169
170
171
172 protected void initialize(@Nonnull final ISkinConfig config) {
173
174 if (!config.not("anchorJS")) {
175 this.addCssOptions("anchorjs-enabled");
176 }
177 }
178
179
180
181
182
183
184
185
186
187 public String preRender(@Nonnull final ISkinConfig skinConfig) {
188 return onPreRender(skinConfig, getBodyContent(skinConfig));
189 }
190
191 @Override
192 protected String onPreRender(final @Nonnull ISkinConfig skinConfig, final @Nonnull String bodyContent) {
193 final HtmlTool htmlTool = getHtmlTool(skinConfig);
194 String content = bodyContent;
195 if (!skinConfig.not("imgLightbox")) {
196
197 content = htmlTool.setAttr(content,
198 "a[href$=jpg], a[href$=JPG], a[href$=jpeg], a[href$=JPEG], "
199 + "a[href$=png], a[href$=gif],a[href$=bmp]:has(img)",
200 "data-lightbox",
201 "page");
202 }
203
204 if (!skinConfig.not("html5Anchor")) {
205
206 content = htmlTool.headingAnchorToId(content);
207 }
208
209 if (!skinConfig.not("bootstrapCss")) {
210
211
212 content = htmlTool
213 .addClass(content, "table.bodyTable", Lists.newArrayList("table", "table-striped", "table-hover"));
214
215 content = htmlTool.addClass(content, "img", Lists.newArrayList("img-fluid"));
216 content = htmlTool.fixTableHeads(content);
217 }
218
219 if (!skinConfig.not("bootstrapIcons")) {
220
221 content = htmlTool.replaceAll(content, ICON_REPLACEMENTS);
222 }
223
224
225
226 content = htmlTool.replaceWith(content, "tt", "<code class=\"literal\">");
227 return super.onPreRender(skinConfig, content);
228 }
229
230 public String renderSnippets(final ISkinConfig skinConfig, final String bodyContent) throws IOException {
231 final SnippetContext snippetContext = new SnippetParser().parse(skinConfig, bodyContent);
232 return snippetContext.html();
233 }
234
235
236
237
238 public Navbar getNavbar() {
239 return navbar;
240 }
241
242
243
244
245 public ScrollTop getScrollTop() {
246 return scrollTop;
247 }
248
249
250
251
252 public Footer getFooter() {
253 return footer;
254 }
255
256
257
258
259
260
261
262
263 protected T withType(final ContextType type) {
264 this.type = type;
265 return self();
266 }
267
268
269
270
271 public String getType() {
272 return type.name();
273 }
274
275
276
277
278 @SuppressWarnings("unchecked")
279 protected T self() {
280 return (T) this;
281 }
282
283
284
285
286 @Override
287 public String toString() {
288 return ToStringBuilder.reflectionToString(this);
289 }
290 }