diff --git a/Source/Build.py b/Source/Build.py index d0dfd7f..702e81a 100755 --- a/Source/Build.py +++ b/Source/Build.py @@ -76,20 +76,24 @@ def Main(Args, FeedEntries): BlogName = Args.BlogName if Args.BlogName else ReadConf(SiteConf, 'Site', 'BlogName') if ReadConf(SiteConf, 'Site', 'BlogName') else '' SiteTagline = Args.SiteTagline if Args.SiteTagline else ReadConf(SiteConf, 'Site', 'Tagline') if ReadConf(SiteConf, 'Site', 'Tagline') else '' SiteTemplate = Args.SiteTemplate if Args.SiteTemplate else ReadConf(SiteConf, 'Site', 'Template') if ReadConf(SiteConf, 'Site', 'Template') else 'Default.html' - SiteDomain = Args.SiteDomain.rstrip('/') if Args.SiteDomain else ReadConf(SiteConf, 'Site', 'Domain') if ReadConf(SiteConf, 'Site', 'Domain') else '' + SiteDomain = Args.SiteDomain.rstrip('/') if Args.SiteDomain else ReadConf(SiteConf, 'Site', 'Domain').rstrip('/') if ReadConf(SiteConf, 'Site', 'Domain') else '' + SiteRoot = Args.SiteRoot if Args.SiteRoot else ReadConf(SiteConf, 'Site', 'Root') if ReadConf(SiteConf, 'Site', 'Root') else '/' SiteLang = Args.SiteLang if Args.SiteLang else ReadConf(SiteConf, 'Site', 'Lang') if ReadConf(SiteConf, 'Site', 'Lang') else 'en' Locale = LoadLocale(SiteLang) - MastodonURL = Args.MastodonURL if Args.MastodonURL else '' - MastodonToken = Args.MastodonToken if Args.MastodonToken else '' - MarkdownExts = literal_eval(Args.MarkdownExts) if Args.MarkdownExts else EvalOpt(ReadConf(SiteConf, 'Site', 'MarkdownExts')) if ReadConf(SiteConf, 'Site', 'MarkdownExts') else MarkdownExtsDefault - ActivityPubTypeFilter = Args.ActivityPubTypeFilter if Args.ActivityPubTypeFilter else 'Post' + MastodonURL = Args.MastodonURL if Args.MastodonURL else ReadConf(SiteConf, 'Mastodon', 'URL') if ReadConf(SiteConf, 'Mastodon', 'URL') else '' + MastodonToken = Args.MastodonToken if Args.MastodonToken else ReadConf(SiteConf, 'Mastodon', 'Token') if ReadConf(SiteConf, 'Mastodon', 'Token') else '' + DynamicParts = literal_eval(Args.DynamicParts) if Args.DynamicParts else EvalOpt(ReadConf(SiteConf, 'Site', 'DynamicParts')) if ReadConf(SiteConf, 'Site', 'DynamicParts') else {} + MarkdownExts = literal_eval(Args.MarkdownExts) if Args.MarkdownExts else EvalOpt(ReadConf(SiteConf, 'Markdown', 'Exts')) if ReadConf(SiteConf, 'Markdown', 'Exts') else MarkdownExtsDefault + ActivityPubTypeFilter = Args.ActivityPubTypeFilter if Args.ActivityPubTypeFilter else ReadConf(SiteConf, 'ActivityPub', 'TypeFilter') if ReadConf(SiteConf, 'ActivityPub', 'TypeFilter') else 'Post' FeedCategoryFilter = Args.FeedCategoryFilter if Args.FeedCategoryFilter else 'Blog' Minify = StringBoolChoose(False, Args.Minify, ReadConf(SiteConf, 'Site', 'Minify')) - AutoCategories = StringBoolChoose(False, Args.AutoCategories, ReadConf(SiteConf, 'Site', 'AutoCategories')) NoScripts = StringBoolChoose(False, Args.NoScripts, ReadConf(SiteConf, 'Site', 'NoScripts')) + ImgAltAndTitle = StringBoolChoose(True, Args.ImgAltAndTitle, ReadConf(SiteConf, 'Site', 'ImgAltAndTitle')) + AutoCategories = StringBoolChoose(False, Args.AutoCategories, ReadConf(SiteConf, 'Site', 'AutoCategories')) GemtextOut = StringBoolChoose(False, Args.GemtextOut, ReadConf(SiteConf, 'Site', 'GemtextOut')) SitemapOut = StringBoolChoose(True, Args.SitemapOut, ReadConf(SiteConf, 'Site', 'SitemapOut')) - FeedEntries = int(FeedEntries) if FeedEntries and FeedEntries != 'Default' else int(ReadConf(SiteConf, 'Site', 'FeedEntries')) if ReadConf(SiteConf, 'Site', 'FeedEntries') else 10 + FeedEntries = int(FeedEntries) if (FeedEntries or FeedEntries == 0) and FeedEntries != 'Default' else int(ReadConf(SiteConf, 'Site', 'FeedEntries')) if ReadConf(SiteConf, 'Site', 'FeedEntries') else 10 + Sorting = literal_eval(Args.Sorting) if Args.Sorting else EvalOpt(ReadConf(SiteConf, 'Site', 'Sorting')) if ReadConf(SiteConf, 'Site', 'Sorting') else {} MenuEntries = ReadConf(SiteConf, 'Menu') if MenuEntries: @@ -118,7 +122,7 @@ def Main(Args, FeedEntries): Pages = MakeSite( TemplatesText=LoadFromDir('Templates', ['*.htm', '*.html']), StaticPartsText=LoadFromDir('StaticParts', ['*.htm', '*.html']), - DynamicParts=literal_eval(Args.DynamicParts) if Args.DynamicParts else {}, + DynamicParts=DynamicParts, DynamicPartsText=LoadFromDir('DynamicParts', ['*.htm', '*.html']), ConfMenu=ConfMenu, GlobalMacros=ReadConf(SiteConf, 'Macros'), @@ -127,13 +131,14 @@ def Main(Args, FeedEntries): SiteTagline=SiteTagline, SiteTemplate=SiteTemplate, SiteDomain=SiteDomain, - SiteRoot=Args.SiteRoot if Args.SiteRoot else '/', + SiteRoot=SiteRoot, FolderRoots=literal_eval(Args.FolderRoots) if Args.FolderRoots else {}, SiteLang=SiteLang, Locale=Locale, Minify=Minify, NoScripts=NoScripts, - Sorting=SetSorting(literal_eval(Args.Sorting) if Args.Sorting else {}), + ImgAltAndTitle=ImgAltAndTitle, + Sorting=SetSorting(Sorting), MarkdownExts=MarkdownExts, AutoCategories=AutoCategories) @@ -200,7 +205,6 @@ def Main(Args, FeedEntries): if __name__ == '__main__': Parser = argparse.ArgumentParser() - Parser.add_argument('--Minify', type=str) Parser.add_argument('--Sorting', type=str) Parser.add_argument('--SiteLang', type=str) Parser.add_argument('--SiteRoot', type=str) @@ -208,7 +212,9 @@ if __name__ == '__main__': Parser.add_argument('--BlogName', type=str) Parser.add_argument('--SiteTemplate', type=str) Parser.add_argument('--SiteDomain', type=str) + Parser.add_argument('--Minify', type=str) Parser.add_argument('--NoScripts', type=str) + Parser.add_argument('--ImgAltAndTitle', type=str) Parser.add_argument('--GemtextOut', type=str) Parser.add_argument('--GemtextHeader', type=str) Parser.add_argument('--SiteTagline', type=str) diff --git a/Source/Modules/Feed.py b/Source/Modules/Feed.py index d73580f..fa85dcd 100644 --- a/Source/Modules/Feed.py +++ b/Source/Modules/Feed.py @@ -16,7 +16,7 @@ def MakeFeed(CategoryFilter, Pages, SiteName, SiteTagline, SiteDomain, MaxEntrie Feed = FeedGenerator() Link = SiteDomain if SiteDomain else ' ' Feed.id(Link) - Feed.title(SiteName if SiteName else ' ') + Feed.title(SiteName if SiteName else 'Untitled Site') Feed.link(href=Link, rel='alternate') Feed.description(SiteTagline if SiteTagline else ' ') if SiteDomain: @@ -33,13 +33,15 @@ def MakeFeed(CategoryFilter, Pages, SiteName, SiteTagline, SiteDomain, MaxEntrie for File, Content, Titles, Meta, ContentHTML, SlimHTML, Description, Image in DoPages: if FullSite or (not FullSite and Meta['Type'] == 'Post' and (not CategoryFilter or (CategoryFilter and (CategoryFilter in Meta['Categories'] or CategoryFilter == '*')))): Entry = Feed.add_entry() + FileName = File.split('/')[-1] File = '{}.html'.format(StripExt(File)) Content = ReadFile('public/'+File) Link = SiteDomain + '/' + File if SiteDomain else ' ' CreatedOn = GetFullDate(Meta['CreatedOn']) EditedOn = GetFullDate(Meta['EditedOn']) Entry.id(Link) - Entry.title(Meta['Title'] if Meta['Title'] else Titles[0].lstrip('#') if Titles else 'Untitled') + Title = Meta['Title'] if Meta['Title'] else Titles[0].lstrip('#') if Titles else FileName + Entry.title(Title.lstrip().rstrip()) Entry.description(Description) Entry.link(href=Link, rel='alternate') if not FullSite: # Avoid making an enormous site feed file... diff --git a/Source/Modules/HTML.py b/Source/Modules/HTML.py index 9814fd0..32ee7c5 100644 --- a/Source/Modules/HTML.py +++ b/Source/Modules/HTML.py @@ -7,6 +7,7 @@ | Copyright (C) 2022, OctoSpacc | | ================================= """ +import html from Libs.bs4 import BeautifulSoup from Modules.Utils import * @@ -40,12 +41,14 @@ def StripTags(HTML, ToStrip): # Remove desired tags from the HTML t.replace_with('') return str(Soup) -def ImgAltToTitle(HTML): # Adds title attr. to which don't have it, but have alt text +def WriteImgAltAndTitle(HTML): # Adds alt or title attr. to which only have one of them Soup = MkSoup(HTML) Tags = Soup.find_all('img') for t in Tags: if 'alt' in t.attrs and 'title' not in t.attrs: t.attrs.update({'title': t.attrs['alt']}) + elif 'title' in t.attrs and 'alt' not in t.attrs: + t.attrs.update({'alt': t.attrs['title']}) return str(Soup) def AddToTagStartEnd(HTML, MatchStart, MatchEnd, AddStart, AddEnd): # This doesn't handle nested tags diff --git a/Source/Modules/Site.py b/Source/Modules/Site.py index 3e57b4b..648851d 100644 --- a/Source/Modules/Site.py +++ b/Source/Modules/Site.py @@ -16,7 +16,7 @@ from Modules.Pug import * from Modules.Utils import * def DashifyTitle(Title, Done=[]): - return UndupeStr(DashifyStr(Title), Done, '-') + return UndupeStr(DashifyStr(Title.lstrip(' ').rstrip(' ')), Done, '-') def MakeLinkableTitle(Line, Title, DashTitle, Type): if Type == 'md': @@ -365,7 +365,7 @@ def DoMinifyHTML(HTML): convert_charrefs=True, keep_pre=True) -def MakeSite(TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, ConfMenu, GlobalMacros, SiteName, BlogName, SiteTagline, SiteTemplate, SiteDomain, SiteRoot, FolderRoots, SiteLang, Locale, Minify, NoScripts, Sorting, MarkdownExts, AutoCategories): +def MakeSite(TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, ConfMenu, GlobalMacros, SiteName, BlogName, SiteTagline, SiteTemplate, SiteDomain, SiteRoot, FolderRoots, SiteLang, Locale, Minify, NoScripts, ImgAltAndTitle, Sorting, MarkdownExts, AutoCategories): PagesPaths, PostsPaths, Pages, MadePages, Categories = [], [], [], [], {} for Ext in FileExtensions['Pages']: for File in Path('Pages').rglob(f"*.{Ext}"): @@ -448,7 +448,7 @@ def MakeSite(TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, Con elif File.lower().endswith(('.pug')): Content = PagePostprocessor('pug', ReadFile(PagePath), Meta) elif File.lower().endswith(('.txt')): - Content = '
' + Content + '
' + Content = '
' + html.escape(Content) + '
' elif File.lower().endswith(FileExtensions['HTML']): Content = ReadFile(PagePath) @@ -483,11 +483,13 @@ def MakeSite(TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, Con SiteLang=SiteLang, Locale=Locale) - HTML = ImgAltToTitle(HTML) - if NoScripts: - HTML = StripTags(HTML, ['script']) if Minify: HTML = DoMinifyHTML(HTML) + if NoScripts: + HTML = StripTags(HTML, ['script']) + if ImgAltAndTitle: + HTML = WriteImgAltAndTitle(HTML) + WriteFile(PagePath, HTML) MadePages += [[File, Content, Titles, Meta, ContentHTML, SlimHTML, Description, Image]] diff --git a/TODO b/TODO index ceadbb1..c1f3e2a 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ - Handle file extensions with any case sensitivity, not just lowercase; currently the bulk of the issue is finding the files on disk - Test sorting by date for files not starting with date, and dated folders -- Fix arguments - some are only callable from CLI and not Site.ini +- Fix arguments - some are only callable from CLI and not Site.ini - make them coherent with INI categories +- Deprecate FolderRoots (Macros make it redundant) - Fix ordering menu in Site.ini (not working for inner pages) - Fix Python-Markdown is installed problem (to load our modules) - Feed generation without native libraries @@ -9,9 +10,10 @@ - SCSS support - Images in post listings - Fix .HTM input pages -- Fix feed titles and page title ids - Hybrid global+page menu (like on documentation generators) - Highlight of currently selected menu item - Exporting the entire site text as JSON for full-text search tools - Automatic guessing of .htm/.html extension for declarations of templates and stuff - Exporting sites to different formats (?) (single-page HTML, PDF, EPUB, ...) +- Disable only ActivityPub feed for a page +- Override ActivityPub URL