1616from pygments .formatters import HtmlFormatter
1717from pygments .util import ClassNotFound
1818from datetime import datetime
19+ import re
1920
2021
2122def parse_frontmatter (content ):
@@ -37,6 +38,20 @@ def parse_frontmatter(content):
3738 return {}, content
3839
3940
41+ def convert_plain_urls_to_links (text ):
42+ """Convert plain text URLs to markdown links"""
43+ # URL regex pattern that matches http/https URLs
44+ url_pattern = r'(?<![\[\(])(https?://[^\s\)]+)(?![\]\)])'
45+
46+ def replace_url (match ):
47+ url = match .group (1 )
48+ # Remove trailing punctuation that's not part of the URL
49+ url = url .rstrip ('.,;:!?' )
50+ return f'[{ url } ]({ url } )'
51+
52+ return re .sub (url_pattern , replace_url , text )
53+
54+
4055# Configure mistune with plugins for syntax highlighting and tables
4156class HighlightRenderer (mistune .HTMLRenderer ):
4257 # Language aliases for better compatibility
@@ -114,6 +129,9 @@ def process_markdown(content, images=None):
114129 image_markdown = f'![{ image ["description" ]} ]({ image ["path" ]} )'
115130 content = content .replace (f'<{{IMAGE:{ image ["id" ]} }}>' , image_markdown )
116131
132+ # Convert plain text URLs to clickable markdown links
133+ content = convert_plain_urls_to_links (content )
134+
117135 return markdown_processor (content )
118136
119137
@@ -433,9 +451,9 @@ def main():
433451 print ("\n 2. Generating static site..." )
434452 site_dir = generate_site (courses )
435453
436- print ("\n ✅ Site generation complete!" )
437- print (f"📁 Output directory: { site_dir .absolute ()} " )
438- print (f"🌐 Open { site_dir .absolute () / 'index.html' } in your browser" )
454+ print ("\n Site generation complete!" )
455+ print (f"Output directory: { site_dir .absolute ()} " )
456+ print (f"Open { site_dir .absolute () / 'index.html' } in your browser" )
439457
440458
441459if __name__ == '__main__' :
0 commit comments