@@ -73,24 +73,27 @@ Hey friend! Help me out for a couple of :beers:! <span class="badge-patreon"><a
7373
7474You can see in which language an app is written. Currently there are following languages:
7575
76- - ![c_icon] - C language.
77- - ![cpp_icon] - C++ language.
78- - ![c_sharp_icon] - C# language.
79- - ![clojure_icon] - Clojure language.
80- - ![coffee_script_icon] - CoffeeScript language.
81- - ![css_icon] - CSS language.
82- - ![go_icon] - Go language.
83- - ![elm_icon] - Elm language.
84- - ![haskell_icon] - Haskell language.
85- - ![javascript_icon] - JavaScript language.
86- - ![lua_icon] - Lua language.
87- - ![objective_c_icon] - Objective-C language.
88- - ![python_icon] - Python language.
89- - ![ruby_icon] - Ruby language.
90- - ![rust_icon] - Rust language.
91- - ![shell_icon] - Shell language.
92- - ![swift_icon] - Swift language.
93- - ![typescript_icon] - TypeScript language.
76+ | Language | Icon |
77+ |----------|------|
78+ | C | <img src='./icons/c-16.png' alt='C' height='16'/> |
79+ | C++ | <img src='./icons/cpp-16.png' alt='C++' height='16'/> |
80+ | C# | <img src='./icons/csharp-16.png' alt='C#' height='16'/> |
81+ | Clojure | <img src='./icons/clojure-16.png' alt='Clojure' height='16'/> |
82+ | CoffeeScript | <img src='./icons/coffeescript-16.png' alt='CoffeeScript' height='16'/> |
83+ | CSS | <img src='./icons/css-16.png' alt='CSS' height='16'/> |
84+ | Elm | <img src='./icons/elm-16.png' alt='Elm' height='16'/> |
85+ | Go | <img src='./icons/golang-16.png' alt='Go' height='16'/> |
86+ | Haskell | <img src='./icons/haskell-16.png' alt='Haskell' height='16'/> |
87+ | Java | <img src='./icons/java-16.png' alt='Java' height='16'/> |
88+ | JavaScript | <img src='./icons/javascript-16.png' alt='JavaScript' height='16'/> |
89+ | Lua | <img src='./icons/Lua-16.png' alt='Lua' height='16'/> |
90+ | Objective-C | <img src='./icons/objective-c-16.png' alt='Objective-C' height='16'/> |
91+ | Python | <img src='./icons/python-16.png' alt='Python' height='16'/> |
92+ | Ruby | <img src='./icons/ruby-16.png' alt='Ruby' height='16'/> |
93+ | Rust | <img src='./icons/rust-16.png' alt='Rust' height='16'/> |
94+ | Shell | <img src='./icons/shell-16.png' alt='Shell' height='16'/> |
95+ | Swift | <img src='./icons/swift-16.png' alt='Swift' height='16'/> |
96+ | TypeScript | <img src='./icons/typescript-16.png' alt='TypeScript' height='16'/> |
9497
9598
9699## Contents
@@ -334,7 +337,10 @@ class ReadmeGenerator {
334337 let categoryApps = validApplications. filter ( { $0. categories. contains ( category. id) } )
335338 let categoryCount = categoryApps. count
336339 let categoryEmoji = getCategoryEmoji ( category. id)
337- readmeString. append ( String . enter + String. section + String. space + categoryEmoji + String. space + category. title + String. space + " ( \( categoryCount) ) " + String. enter)
340+ // Add explicit anchor for TOC linking
341+ let anchorId = generateAnchorId ( category. title)
342+ readmeString. append ( String . enter + " <a id= \" \( anchorId) \" ></a> " + String. enter)
343+ readmeString. append ( String . section + String. space + categoryEmoji + String. space + category. title + String. space + " ( \( categoryCount) ) " + String. enter)
338344
339345 var categoryApplications = categoryApps
340346 categoryApplications = categoryApplications. sorted ( by: { $0. title. lowercased ( ) < $1. title. lowercased ( ) } )
@@ -355,7 +361,10 @@ class ReadmeGenerator {
355361 let subcategoryApps = validApplications. filter ( { $0. categories. contains ( subcategory. id) } )
356362 let subcategoryCount = subcategoryApps. count
357363 let subcategoryEmoji = getCategoryEmoji ( subcategory. id)
358- readmeString. append ( String . enter + String. subsection + String. space + subcategoryEmoji + String. space + subcategory. title + String. space + " ( \( subcategoryCount) ) " + String. enter)
364+ // Add explicit anchor for TOC linking
365+ let subAnchorId = generateAnchorId ( subcategory. title)
366+ readmeString. append ( String . enter + " <a id= \" \( subAnchorId) \" ></a> " + String. enter)
367+ readmeString. append ( String . subsection + String. space + subcategoryEmoji + String. space + subcategory. title + String. space + " ( \( subcategoryCount) ) " + String. enter)
359368
360369 var categoryApplications = subcategoryApps
361370 categoryApplications = categoryApplications. sorted ( by: { $0. title. lowercased ( ) < $1. title. lowercased ( ) } )
@@ -408,6 +417,16 @@ func normalizeLanguageName(_ lang: String) -> String {
408417 }
409418}
410419
420+ // Helper function to generate GitHub-compatible anchor IDs from titles
421+ func generateAnchorId( _ title: String ) -> String {
422+ return title. lowercased ( )
423+ . replacingOccurrences ( of: " / " , with: " -- " ) // Handle " / " like GitHub does
424+ . replacingOccurrences ( of: " / " , with: " - " )
425+ . replacingOccurrences ( of: " & " , with: " -- " ) // Handle " & " like GitHub does
426+ . replacingOccurrences ( of: " & " , with: " - " )
427+ . replacingOccurrences ( of: " " , with: " - " )
428+ }
429+
411430extension String {
412431 static let empty = " "
413432 static let space = " "
@@ -433,12 +452,12 @@ extension JSONApplication {
433452
434453 // Collapsible extra details (languages, links, screenshots) indented to belong to the list item
435454 let indent = " "
436- markdownDescription. append ( indent + " <details> " )
437- markdownDescription. append ( indent + " <summary>More</summary> " )
438- markdownDescription. append ( indent + " <p> " )
455+ markdownDescription. append ( " \n " + indent + " <details> \n " )
456+ markdownDescription. append ( indent + " <summary>More</summary> \n " )
457+ markdownDescription. append ( indent + " <p> \n \n " )
439458
440459 // Add languages
441- markdownDescription. append ( " <b> Languages:</b> \( languages) <br> " )
460+ markdownDescription. append ( " ** Languages:** \( languages) \n \n " )
442461
443462 // Add download/badge section
444463 let ownerRepo = githubOwnerRepo ( from: self . repoURL)
@@ -470,33 +489,33 @@ extension JSONApplication {
470489 badges. append ( brewBadge)
471490 }
472491 if badges. isEmpty == false {
473- markdownDescription. append ( " <b> Links:</b> \( badges. joined ( separator: " " ) ) <br> " )
492+ markdownDescription. append ( " ** Links:** \( badges. joined ( separator: " " ) ) \n \n " )
474493 }
475494
476495 // Add official site if available
477496 if !self . officialSite. isEmpty {
478- markdownDescription. append ( " <b> Website:</b> <a href= \" \ (self . officialSite) \" > \ (self . officialSite) </a><br> " )
497+ markdownDescription. append ( " ** Website:** [ \ (self . officialSite) ]( \ (self . officialSite) ) \n \n " )
479498 }
480499
481500 // Add screenshots with lazy loading to improve page load performance
482501 if self . screenshots. count > 0 {
483- markdownDescription. append ( " <b> Screenshots:</b><br> " )
502+ markdownDescription. append ( " ** Screenshots:** \n \n " )
484503
485504 // Limit to first 3 screenshots to reduce load time
486505 let limitedScreenshots = self . screenshots. count > 3 ? Array ( self . screenshots. prefix ( 3 ) ) : self . screenshots
487506
488507 limitedScreenshots. forEach ( {
489- markdownDescription. append ( " <img src=' \( $0) ' width='400' loading='lazy'/><br> " )
508+ markdownDescription. append ( " <img src='\( $0) ' width='400' loading='lazy'/> \n \n " )
490509 } )
491510
492511 // Add a note if there are more screenshots
493512 if self . screenshots. count > 3 {
494- markdownDescription. append ( " <em> (\( self . screenshots. count - 3 ) more screenshots available in the repository)</em><br> " )
513+ markdownDescription. append ( " * (\( self . screenshots. count - 3 ) more screenshots available in the repository)* \n \n " )
495514 }
496515 }
497516
498- markdownDescription. append ( indent + " </p> " )
499- markdownDescription. append ( indent + " </details> " )
517+ markdownDescription. append ( indent + " </p> \n " )
518+ markdownDescription. append ( indent + " </details> \n " )
500519
501520 return markdownDescription
502521 }
0 commit comments