2828
2929static final String BASE_URL = "https://javaevolved.github.io" ;
3030static final String TEMPLATE_FILE = "templates/slug-template.html" ;
31+ static final String WHY_CARD_TEMPLATE = "templates/why-card.html" ;
32+ static final String RELATED_CARD_TEMPLATE = "templates/related-card.html" ;
33+ static final String SOCIAL_SHARE_TEMPLATE = "templates/social-share.html" ;
3134static final String CONTENT_DIR = "content" ;
3235static final String SITE_DIR = "site" ;
3336static final Pattern TOKEN_PATTERN = Pattern .compile ("\\ {\\ {(\\ w+)}}" );
@@ -105,12 +108,16 @@ record Empty() implements NavArrow {}
105108
106109void main () throws IOException {
107110 var template = Files .readString (Path .of (TEMPLATE_FILE ));
111+ var whyCardTemplate = Files .readString (Path .of (WHY_CARD_TEMPLATE ));
112+ var relatedCardTemplate = Files .readString (Path .of (RELATED_CARD_TEMPLATE ));
113+ var socialShareTemplate = Files .readString (Path .of (SOCIAL_SHARE_TEMPLATE ));
108114 var allSnippets = loadAllSnippets ();
109115 IO .println ("Loaded %d snippets" .formatted (allSnippets .size ()));
110116
111117 // Generate HTML files
112118 for (var snippet : allSnippets .values ()) {
113- var html = generateHtml (template , snippet , allSnippets ).strip ();
119+ var html = generateHtml (template , whyCardTemplate , relatedCardTemplate , socialShareTemplate ,
120+ snippet , allSnippets ).strip ();
114121 Files .createDirectories (Path .of (SITE_DIR , snippet .category ()));
115122 Files .writeString (Path .of (SITE_DIR , snippet .category (), snippet .slug () + ".html" ), html );
116123 }
@@ -224,92 +231,56 @@ String renderArrow(NavArrow arrow, String label, String symbol) {
224231 };
225232}
226233
227- String renderWhyCards (JsonNode whyList ) {
234+ String renderWhyCards (String whyCardTemplate , JsonNode whyList ) {
228235 var cards = new ArrayList <String >();
229236 for (var w : whyList ) {
230- cards .add ("""
231- <div class="why-card">
232- <div class="why-icon">%s</div>
233- <h3>%s</h3>
234- <p>%s</p>
235- </div>\
236- """ .formatted (
237- w .get ("icon" ).asText (),
238- escape (w .get ("title" ).asText ()),
239- escape (w .get ("desc" ).asText ())).stripTrailing ());
237+ var replacements = Map .of (
238+ "icon" , w .get ("icon" ).asText (),
239+ "title" , escape (w .get ("title" ).asText ()),
240+ "desc" , escape (w .get ("desc" ).asText ()));
241+ cards .add (replaceTokens (whyCardTemplate , replacements ));
240242 }
241243 return String .join ("\n " , cards );
242244}
243245
244- String renderRelatedCard (Snippet rel ) {
245- return """
246- <a href="/%s/%s.html" class="tip-card">
247- <div class="tip-card-body">
248- <div class="tip-card-header">
249- <div class="tip-badges">
250- <span class="badge %s">%s</span>
251- <span class="badge %s">%s</span>
252- </div>
253- </div>
254- <h3>%s</h3>
255- </div>
256- <div class="card-code">
257- <div class="card-code-layer old-layer">
258- <div class="mini-label">%s</div>
259- <pre class="code-text">%s</pre>
260- </div>
261- <div class="card-code-layer modern-layer">
262- <div class="mini-label">%s</div>
263- <pre class="code-text">%s</pre>
264- </div>
265- <span class="hover-hint">Hover to see modern ➜</span>
266- </div>
267- <div class="tip-card-footer">
268- <span class="browser-support"><span class="dot"></span>JDK %s+</span>
269- <span class="arrow-link">→</span>
270- </div>
271- </a>\
272- """ .formatted (
273- rel .category (), rel .slug (),
274- rel .category (), rel .catDisplay (),
275- rel .difficulty (), rel .difficulty (),
276- escape (rel .title ()),
277- escape (rel .oldLabel ()), escape (rel .oldCode ()),
278- escape (rel .modernLabel ()), escape (rel .modernCode ()),
279- rel .jdkVersion ()).stripTrailing ();
246+ String renderRelatedCard (String relatedCardTemplate , Snippet rel ) {
247+ var replacements = Map .ofEntries (
248+ Map .entry ("category" , rel .category ()),
249+ Map .entry ("slug" , rel .slug ()),
250+ Map .entry ("catDisplay" , rel .catDisplay ()),
251+ Map .entry ("difficulty" , rel .difficulty ()),
252+ Map .entry ("title" , escape (rel .title ())),
253+ Map .entry ("oldLabel" , escape (rel .oldLabel ())),
254+ Map .entry ("oldCode" , escape (rel .oldCode ())),
255+ Map .entry ("modernLabel" , escape (rel .modernLabel ())),
256+ Map .entry ("modernCode" , escape (rel .modernCode ())),
257+ Map .entry ("jdkVersion" , rel .jdkVersion ()));
258+ return replaceTokens (relatedCardTemplate , replacements );
280259}
281260
282- String renderRelatedSection (Snippet snippet , Map <String , Snippet > allSnippets ) {
261+ String renderRelatedSection (String relatedCardTemplate , Snippet snippet , Map <String , Snippet > allSnippets ) {
283262 return snippet .related ().stream ()
284263 .filter (allSnippets ::containsKey )
285- .map (path -> renderRelatedCard (allSnippets .get (path )))
264+ .map (path -> renderRelatedCard (relatedCardTemplate , allSnippets .get (path )))
286265 .collect (Collectors .joining ("\n " ));
287266}
288267
289- String renderSocialShare (String slug , String title ) {
268+ String renderSocialShare (String socialShareTemplate , String slug , String title ) {
290269 var pageUrl = "%s/%s.html" .formatted (BASE_URL , slug );
291270 var shareText = "%s \u2013 java.evolved" .formatted (title );
292271 var encodedUrl = urlEncode (pageUrl );
293272 var encodedText = urlEncode (shareText );
294273
295- return """
296- <div class="social-share">
297- <span class="share-label">Share</span>
298- <a href="https://x.com/intent/tweet?url=%s&text=%s" target="_blank" rel="noopener" class="share-btn share-x" aria-label="Share on X">𝕏</a>
299- <a href="https://bsky.app/intent/compose?text=%s%%20%s" target="_blank" rel="noopener" class="share-btn share-bsky" aria-label="Share on Bluesky">🦋</a>
300- <a href="https://www.linkedin.com/sharing/share-offsite/?url=%s" target="_blank" rel="noopener" class="share-btn share-li" aria-label="Share on LinkedIn">in</a>
301- <a href="https://www.reddit.com/submit?url=%s&title=%s" target="_blank" rel="noopener" class="share-btn share-reddit" aria-label="Share on Reddit">⬡</a>
302- </div>\
303- """ .formatted (
304- encodedUrl , encodedText ,
305- encodedText , encodedUrl ,
306- encodedUrl ,
307- encodedUrl , encodedText ).stripTrailing ();
274+ var replacements = Map .of (
275+ "encodedUrl" , encodedUrl ,
276+ "encodedText" , encodedText );
277+ return replaceTokens (socialShareTemplate , replacements );
308278}
309279
310280// -- Main generation logic -----------------------------------------------
311281
312- String generateHtml (String template , Snippet snippet , Map <String , Snippet > allSnippets ) {
282+ String generateHtml (String template , String whyCardTemplate , String relatedCardTemplate ,
283+ String socialShareTemplate , Snippet snippet , Map <String , Snippet > allSnippets ) {
313284 var replacements = Map .ofEntries (
314285 Map .entry ("title" , escape (snippet .title ())),
315286 Map .entry ("summary" , escape (snippet .summary ())),
@@ -332,11 +303,15 @@ String generateHtml(String template, Snippet snippet, Map<String, Snippet> allSn
332303 Map .entry ("summaryJson" , jsonEscape (snippet .summary ())),
333304 Map .entry ("categoryDisplayJson" , jsonEscape (snippet .catDisplay ())),
334305 Map .entry ("navArrows" , renderNavArrows (snippet )),
335- Map .entry ("whyCards" , renderWhyCards (snippet .whyModernWins ())),
336- Map .entry ("relatedCards" , renderRelatedSection (snippet , allSnippets )),
337- Map .entry ("socialShare" , renderSocialShare (snippet .slug (), snippet .title ()))
306+ Map .entry ("whyCards" , renderWhyCards (whyCardTemplate , snippet .whyModernWins ())),
307+ Map .entry ("relatedCards" , renderRelatedSection (relatedCardTemplate , snippet , allSnippets )),
308+ Map .entry ("socialShare" , renderSocialShare (socialShareTemplate , snippet .slug (), snippet .title ()))
338309 );
339310
311+ return replaceTokens (template , replacements );
312+ }
313+
314+ String replaceTokens (String template , Map <String , String > replacements ) {
340315 var m = TOKEN_PATTERN .matcher (template );
341316 var sb = new StringBuilder ();
342317 while (m .find ()) {
0 commit comments