Add show unlisted status for pages, clean code, fix misc issues

This commit is contained in:
octospacc 2022-12-20 13:05:41 +01:00
parent 09eb85be6c
commit 9551342b74
10 changed files with 197 additions and 104 deletions

View File

@ -1,6 +1,7 @@
{ {
"CreatedOn": "Created on", "CreatedOn": "Created on",
"EditedOn": "Edited on", "EditedOn": "Edited on",
"Unlisted": "Unlisted",
"Categories": "Categories", "Categories": "Categories",
"ReadFullPost": "Read the full post", "ReadFullPost": "Read the full post",
"Comments": "Comments", "Comments": "Comments",

View File

@ -1,6 +1,7 @@
{ {
"CreatedOn": "Creato in data", "CreatedOn": "Creato in data",
"EditedOn": "Modificato in data", "EditedOn": "Modificato in data",
"Unlisted": "Non in elenco",
"Categories": "Categorie", "Categories": "Categorie",
"ReadFullPost": "Leggi il post intero", "ReadFullPost": "Leggi il post intero",
"Comments": "Commenti", "Comments": "Commenti",

View File

@ -17,6 +17,7 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from Modules.Config import * from Modules.Config import *
from Modules.Gemini import * from Modules.Gemini import *
from Modules.Globals import *
from Modules.Logging import * from Modules.Logging import *
from Modules.Markdown import * from Modules.Markdown import *
from Modules.Site import * from Modules.Site import *

View File

@ -4,7 +4,7 @@ https://github.com/tootsuite/mastodon/blob/master/docs/Using-the-API/Streaming-A
""" """
import json import json
import six from .. import six
from . import Mastodon from . import Mastodon
from .Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout from .Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout
from requests.exceptions import ChunkedEncodingError, ReadTimeout from requests.exceptions import ChunkedEncodingError, ReadTimeout

View File

@ -8,6 +8,7 @@
| ================================= """ | ================================= """
from base64 import b64encode from base64 import b64encode
from Modules.Globals import *
from Modules.HTML import * from Modules.HTML import *
from Modules.Utils import * from Modules.Utils import *
@ -32,6 +33,8 @@ RedirectPageTemplate = """\
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{TitlePrefix}Redirect</title> <title>{TitlePrefix}Redirect</title>
<link rel="canonical" href="{SiteDomain}/{DestURL}"> <link rel="canonical" href="{SiteDomain}/{DestURL}">
<meta http-equiv="refresh" content="0; url='{DestURL}'"> <meta http-equiv="refresh" content="0; url='{DestURL}'">
@ -68,7 +71,7 @@ def GenHTMLTreeList(MetaList:str, Type:str='ul'):
PrevDepth = CurDepth PrevDepth = CurDepth
return f'<{Type}>{HTML}\n</{Type}>' return f'<{Type}>{HTML}\n</{Type}>'
def MakeLinkableTitle(Line, Title, DashTitle, Type): def MakeLinkableTitle(Line:str, Title:str, DashTitle:str, Type:str):
if Type == 'md': if Type == 'md':
Index = Title.split(' ')[0].count('#') Index = Title.split(' ')[0].count('#')
return HTMLSectionTitleLine.format( return HTMLSectionTitleLine.format(
@ -83,7 +86,7 @@ def MakeLinkableTitle(Line, Title, DashTitle, Type):
Rest=Line[Index+2:], Rest=Line[Index+2:],
DashTitle=DashTitle) DashTitle=DashTitle)
def GetTitle(FileName, Meta, Titles, Prefer='MetaTitle', BlogName=None): def GetTitle(FileName:str, Meta:dict, Titles:list, Prefer='MetaTitle', BlogName=None):
if Prefer == 'BodyTitle': if Prefer == 'BodyTitle':
Title = Titles[0].lstrip('#') if Titles else Meta['Title'] if Meta['Title'] else FileName Title = Titles[0].lstrip('#') if Titles else Meta['Title'] if Meta['Title'] else FileName
elif Prefer == 'MetaTitle': elif Prefer == 'MetaTitle':
@ -94,27 +97,29 @@ def GetTitle(FileName, Meta, Titles, Prefer='MetaTitle', BlogName=None):
Title += ' - ' + BlogName Title += ' - ' + BlogName
return Title return Title
def GetDescription(Meta, BodyDescription, Prefer='MetaDescription'): def GetDescription(Meta:dict, BodyDescription, Prefer='MetaDescription'):
if Prefer == 'BodyDescription': if Prefer == 'BodyDescription':
Description = BodyDescription if BodyDescription else Meta['Description'] if Meta['Description'] else '' Description = BodyDescription if BodyDescription else Meta['Description'] if Meta['Description'] else ''
elif Prefer == 'MetaDescription': elif Prefer == 'MetaDescription':
Description = Meta['Description'] if Meta['Description'] else BodyDescription if BodyDescription else '' Description = Meta['Description'] if Meta['Description'] else BodyDescription if BodyDescription else ''
return Description return Description
def GetImage(Meta, BodyImage, Prefer='MetaImage'): def GetImage(Meta:dict, BodyImage, Prefer='MetaImage'):
if Prefer == 'BodyImage': if Prefer == 'BodyImage':
Image = BodyImage if BodyImage else Meta['Image'] if Meta['Image'] else '' Image = BodyImage if BodyImage else Meta['Image'] if Meta['Image'] else ''
elif Prefer == 'MetaImage': elif Prefer == 'MetaImage':
Image = Meta['Image'] if Meta['Image'] else BodyImage if BodyImage else '' Image = Meta['Image'] if Meta['Image'] else BodyImage if BodyImage else ''
return Image return Image
def MakeContentHeader(Meta, Locale, Categories=''): def MakeContentHeader(Meta:dict, Locale:dict, Categories=''):
Header = '' Header = ''
for e in ['CreatedOn', 'EditedOn']: for e in ['CreatedOn', 'EditedOn']:
if Meta[e]: if Meta[e]:
Header += f'<span class="staticoso-ContentHeader-{e}"><span class="staticoso-Label">{Locale[e]}</span>: <span class="staticoso-Value">{Meta[e]}</span></span><br>' Header += f'<span class="staticoso-ContentHeader-{e}" id="staticoso-ContentHeader-{e}"><span class="staticoso-Label">{Locale[e]}</span>: <span class="staticoso-Value">{Meta[e]}</span></span><br>'
if Categories: if Categories:
Header += f'<span class="staticoso-ContentHeader-Categories"><span class="staticoso-Label">{Locale["Categories"]}</span>:<span class="staticoso-Value">{Categories.removesuffix(" ")}</span></span><br>' Header += f'<span class="staticoso-ContentHeader-Categories" id="staticoso-ContentHeader-Categories"><span class="staticoso-Label">{Locale["Categories"]}</span>:<span class="staticoso-Value">{Categories.removesuffix(" ")}</span></span><br>'
if Meta['Index'].lower() in PageIndexStrNeg:
Header += f'<span class="staticoso-ContentHeader-Index" id="staticoso-ContentHeader-Index"><span class="staticoso-Value">{Locale["Unlisted"]}</span></span><br>'
return f'<p>{Header}</p>' return f'<p>{Header}</p>'
def MakeCategoryLine(File, Meta): def MakeCategoryLine(File, Meta):

23
Source/Modules/Globals.py Normal file
View File

@ -0,0 +1,23 @@
""" ================================= |
| This file is part of |
| staticoso |
| Just a simple Static Site Generator |
| |
| Licensed under the AGPLv3 license |
| Copyright (C) 2022, OctoSpacc |
| ================================= """
ReservedPaths = ('Site.ini', 'Assets', 'Pages', 'Posts', 'Templates', 'StaticParts', 'DynamicParts')
FileExtensions = {
'Pages': ('htm', 'html', 'markdown', 'md', 'pug', 'txt'),
'HTML': ('.htm', '.html'),
'Markdown': ('.markdown', '.md'),
'Tmp': ('htm', 'markdown', 'md', 'pug', 'txt')}
PosStrBools = ('true', 'yes', 'on', '1', 'enabled')
NegStrBools = ('false', 'no', 'off', '0', 'disabled')
PageIndexStrPos = tuple(list(PosStrBools) + ['all', 'listed', 'indexed', 'unlinked'])
PageIndexStrNeg = tuple(list(NegStrBools) + ['none', 'unlisted', 'unindexed', 'hidden'])
InternalMacrosWraps = [['[', ']'], ['<', '>']]

View File

@ -58,21 +58,24 @@ def WriteImgAltAndTitle(HTML, AltToTitle, TitleToAlt): # Adds alt or title attr.
return str(Soup) return str(Soup)
def AddToTagStartEnd(HTML, MatchStart, MatchEnd, AddStart, AddEnd): # This doesn't handle nested tags def AddToTagStartEnd(HTML, MatchStart, MatchEnd, AddStart, AddEnd): # This doesn't handle nested tags
StartPos = None StartPos, DidStart, DidEnd = None, 0, 0
for i,e in enumerate(HTML): for i,e in enumerate(HTML):
FilterStart = HTML[i:i+len(MatchStart)] FilterStart = HTML[i:i+len(MatchStart)]
FilterEnd = HTML[i:i+len(MatchEnd)] FilterEnd = HTML[i:i+len(MatchEnd)]
if not AddStart and not AddEnd: if DidStart == 0 and FilterStart == MatchStart:
break
if FilterStart == MatchStart:
StartPos = i StartPos = i
if AddStart: if AddStart:
HTML = HTML[:i] + AddStart + HTML[i:] HTML = HTML[:i] + AddStart + HTML[i:]
AddStart = None DidStart = 2
if FilterEnd == MatchEnd and StartPos and i > StartPos: if DidEnd == 0 and FilterEnd == MatchEnd and StartPos and i > StartPos:
StartPos = None
if AddEnd: if AddEnd:
HTML = HTML[:i+len(MatchEnd)] + AddEnd + HTML[i+len(MatchEnd):] HTML = HTML[:i+len(MatchEnd)] + AddEnd + HTML[i+len(MatchEnd):]
AddEnd = None DidEnd = 2
if DidStart > 0:
DidStart -= 1
if DidEnd > 0:
DidEnd -= 1
return HTML return HTML
def SquareFnrefs(HTML): # Different combinations of formatting for Soup .prettify, .encode, .decode break different page elements, don't use this for now def SquareFnrefs(HTML): # Different combinations of formatting for Soup .prettify, .encode, .decode break different page elements, don't use this for now

View File

@ -13,6 +13,7 @@ from multiprocessing import Pool, cpu_count
from Libs.bs4 import BeautifulSoup from Libs.bs4 import BeautifulSoup
from Modules.Config import * from Modules.Config import *
from Modules.Elements import * from Modules.Elements import *
from Modules.Globals import *
from Modules.HTML import * from Modules.HTML import *
from Modules.Logging import * from Modules.Logging import *
from Modules.Markdown import * from Modules.Markdown import *
@ -31,7 +32,7 @@ def GetHTMLPagesList(Pages, BlogName, SiteRoot, PathPrefix, CallbackFile=None, U
List, ToPop, LastParent = '', [], [] List, ToPop, LastParent = '', [], []
IndexPages = Pages.copy() IndexPages = Pages.copy()
for e in IndexPages: for e in IndexPages:
if e[3]['Index'] == 'False' or e[3]['Index'] == 'None': if e[3]['Index'].lower() in PageIndexStrNeg:
IndexPages.remove(e) IndexPages.remove(e)
for i,e in enumerate(IndexPages): for i,e in enumerate(IndexPages):
if Type and e[3]['Type'] != Type: if Type and e[3]['Type'] != Type:
@ -43,7 +44,7 @@ def GetHTMLPagesList(Pages, BlogName, SiteRoot, PathPrefix, CallbackFile=None, U
IndexPages = OrderPages(IndexPages) IndexPages = OrderPages(IndexPages)
for i,e in enumerate(Unite): for i,e in enumerate(Unite):
if e: if e:
IndexPages.insert(i,[e,None,None,{'Type':Type,'Index':'True','Order':'Unite'}]) IndexPages.insert(i, [e, None, None, {'Type':Type, 'Index':'True', 'Order':'Unite'}])
for File, Content, Titles, Meta in IndexPages: for File, Content, Titles, Meta in IndexPages:
# Allow for the virtual "Pages/" prefix to be used in path filtering # Allow for the virtual "Pages/" prefix to be used in path filtering
TmpPathFilter = PathFilter TmpPathFilter = PathFilter
@ -128,11 +129,12 @@ def FindPreprocLine(Line, Meta, Macros):
# IgnoreBlocksStart += [l] # IgnoreBlocksStart += [l]
return (Meta, Macros, Changed) return (Meta, Macros, Changed)
def PagePreprocessor(Path, TempPath, Type, SiteTemplate, SiteRoot, GlobalMacros, CategoryUncategorized, LightRun=False): def PagePreprocessor(Path:str, TempPath:str, Type, SiteTemplate, SiteRoot, GlobalMacros, CategoryUncategorized, LightRun=False):
File = ReadFile(Path) File = ReadFile(Path)
Path = Path.lower() Path = Path.lower()
Content, Titles, DashyTitles, HTMLTitlesFound, Macros, Meta, MetaDefault = '', [], [], False, '', '', { Content, Titles, DashyTitles, HTMLTitlesFound, Macros, Meta, MetaDefault = '', [], [], False, '', '', {
'Template': SiteTemplate, 'Template': SiteTemplate,
'Head': '',
'Style': '', 'Style': '',
'Type': Type, 'Type': Type,
'Index': 'Unspecified', 'Index': 'Unspecified',
@ -250,24 +252,24 @@ def PagePreprocessor(Path, TempPath, Type, SiteTemplate, SiteRoot, GlobalMacros,
Meta.update({i:MetaDefault[i]}) Meta.update({i:MetaDefault[i]})
if Meta['UpdatedOn']: if Meta['UpdatedOn']:
Meta['EditedOn'] = Meta['UpdatedOn'] Meta['EditedOn'] = Meta['UpdatedOn']
if Meta['Index'] in ('Default', 'Unspecified', 'Categories'): if Meta['Index'].lower() in ('default', 'unspecified', 'categories'):
if not Meta['Categories']: if not Meta['Categories']:
Meta['Categories'] = [CategoryUncategorized] Meta['Categories'] = [CategoryUncategorized]
if Meta['Type'] == 'Page': if Meta['Type'].lower() == 'page':
Meta['Index'] = 'Categories' Meta['Index'] = 'Categories'
elif Meta['Type'] == 'Post': elif Meta['Type'].lower() == 'post':
Meta['Index'] = 'True' Meta['Index'] = 'True'
if GlobalMacros: if GlobalMacros:
Meta['Macros'].update(GlobalMacros) Meta['Macros'].update(GlobalMacros)
Meta['Macros'].update(ReadConf(LoadConfStr('[Macros]\n' + Macros), 'Macros')) Meta['Macros'].update(ReadConf(LoadConfStr('[Macros]\n' + Macros), 'Macros'))
return [TempPath, Content, Titles, Meta] return [TempPath, Content, Titles, Meta]
def PagePostprocessor(FileType, Text, Meta): def PagePostprocessor(FileType, Text:str, Meta:dict):
for e in Meta['Macros']: for e in Meta['Macros']:
Text = ReplWithEsc(Text, f"[: {e} :]", f"[:{e}:]") Text = ReplWithEsc(Text, f"[: {e} :]", f"[:{e}:]")
return Text return Text
def OrderPages(Old): def OrderPages(Old:list):
New, NoOrder, Max = [], [], 0 New, NoOrder, Max = [], [], 0
for i,e in enumerate(Old): for i,e in enumerate(Old):
Curr = e[3]['Order'] Curr = e[3]['Order']
@ -285,10 +287,10 @@ def OrderPages(Old):
New.remove(None) New.remove(None)
return New + NoOrder return New + NoOrder
def CanIndex(Index, For): def CanIndex(Index:str, For:str):
if Index in ('False', 'None'): if Index.lower() in PageIndexStrNeg:
return False return False
elif Index in ('True', 'All', 'Unlinked'): elif Index.lower() in PageIndexStrPos:
return True return True
else: else:
return True if Index == For else False return True if Index == For else False
@ -297,20 +299,26 @@ def PatchHTML(File, HTML, StaticPartsText, DynamicParts, DynamicPartsText, HTMLP
HTMLTitles = FormatTitles(Titles) HTMLTitles = FormatTitles(Titles)
BodyDescription, BodyImage = '', '' BodyDescription, BodyImage = '', ''
if not File.lower().endswith('.txt'): if not File.lower().endswith('.txt'):
Soup = BeautifulSoup(Content, 'html.parser') Soup = MkSoup(Content)
if not BodyDescription:# and Soup.p:
if not BodyDescription and Soup.p: #BodyDescription = Soup.p.get_text()[:150].replace('\n', ' ').replace('"', "'") + '...'
BodyDescription = Soup.p.get_text()[:150].replace('\n', ' ').replace('"', "'") + '...' for t in Soup.find_all('p'):
if t.get_text():
BodyDescription = t.get_text()[:150].replace('\n', ' ').replace('"', "'") + '...'
break
if not BodyImage and Soup.img and Soup.img['src']: if not BodyImage and Soup.img and Soup.img['src']:
BodyImage = Soup.img['src'] BodyImage = Soup.img['src']
#Content = SquareFnrefs(Content) #Content = SquareFnrefs(Content)
if '<a class="footnote-ref"' in Content: if '<a class="footnote-ref" ' in Content:
Content = AddToTagStartEnd(Content, '<a class="footnote-ref"', '</a>', '[', ']') Content = AddToTagStartEnd(Content, '<a class="footnote-ref" ', '</a>', '[', ']')
if any(_ in Content for _ in ('<!-- noprocess />', '<!--noprocess/>', '</ noprocess -->', '</ noprocess --->', '</noprocess-->', '</noprocess--->')): if any(_ in Content for _ in ('<!-- noprocess />', '<!--noprocess/>', '</ noprocess -->', '</ noprocess --->', '</noprocess-->', '</noprocess--->')):
Content = DictReplWithEsc( Content = DictReplWithEsc(
Content, { Content, {
'<!--<%noprocess>': '',
'<noprocess%>-->': '',
'<noprocess%>--->': '',
'<!-- noprocess />': '', '<!-- noprocess />': '',
'<!--noprocess/>': '', '<!--noprocess/>': '',
'</ noprocess -->': '', '</ noprocess -->': '',
@ -352,85 +360,130 @@ def PatchHTML(File, HTML, StaticPartsText, DynamicParts, DynamicPartsText, HTMLP
if LightRun: if LightRun:
HTML = None HTML = None
else: else:
HTML = DictReplWithEsc(HTML, { HTML = WrapDictReplWithEsc(HTML, {
'[staticoso:Site:Menu]': HTMLPagesList, #'[staticoso:Site:Menu]': HTMLPagesList,
'<staticoso:SiteMenu>': HTMLPagesList, #'<staticoso:SiteMenu>': HTMLPagesList,
'[staticoso:Page:Lang]': Meta['Language'] if Meta['Language'] else SiteLang, #'[staticoso:Page:Lang]': Meta['Language'] if Meta['Language'] else SiteLang,
'<staticoso:PageLang>': Meta['Language'] if Meta['Language'] else SiteLang, #'<staticoso:PageLang>': Meta['Language'] if Meta['Language'] else SiteLang,
'<staticoso:PageLanguage>': Meta['Language'] if Meta['Language'] else SiteLang, #'<staticoso:PageLanguage>': Meta['Language'] if Meta['Language'] else SiteLang,
'[staticoso:Page:Chapters]': HTMLTitles, #'[staticoso:Page:Chapters]': HTMLTitles,
'<staticoso:PageSections>': HTMLTitles, #'<staticoso:PageSections>': HTMLTitles,
'[staticoso:Page:Title]': Title, #'[staticoso:Page:Title]': Title,
'<staticoso:PageTitle>': Title, #'<staticoso:PageTitle>': Title,
'[staticoso:Page:Description]': Description, #'[staticoso:Page:Description]': Description,
'<staticoso:PageDescription>': Description, #'<staticoso:PageDescription>': Description,
'[staticoso:Page:Image]': Image, #'[staticoso:Page:Image]': Image,
'<staticoso:PageImage>': Image, #'<staticoso:PageImage>': Image,
'[staticoso:Page:Path]': PagePath, #'[staticoso:Page:Path]': PagePath,
'<staticoso:PagePath>': PagePath, #'<staticoso:PagePath>': PagePath,
'[staticoso:Page:Style]': Meta['Style'], #'[staticoso:PageHead]': Meta['Head'],
'<staticoso:PageStyle>': Meta['Style'], #'<staticoso:PageHead>': Meta['Head'],
#'[staticoso:Page:Style]': Meta['Style'],
#'<staticoso:PageStyle>': Meta['Style'],
# #DEPRECATION #
'staticoso:Site:Menu': HTMLPagesList,
'staticoso:Page:Lang': Meta['Language'] if Meta['Language'] else SiteLang,
'staticoso:Page:Chapters': HTMLTitles,
'staticoso:Page:Title': Title,
'staticoso:Page:Description': Description,
'staticoso:Page:Image': Image,
'staticoso:Page:Path': PagePath,
'staticoso:Page:Style': Meta['Style'],
################
'staticoso:SiteMenu': HTMLPagesList,
'staticoso:PageLang': Meta['Language'] if Meta['Language'] else SiteLang,
'staticoso:PageLanguage': Meta['Language'] if Meta['Language'] else SiteLang,
'staticoso:PageSections': HTMLTitles,
'staticoso:PageTitle': Title,
'staticoso:PageDescription': Description,
'staticoso:PageImage': Image,
'staticoso:PagePath': PagePath,
'staticoso:PageHead': Meta['Head'],
'staticoso:PageStyle': Meta['Style'],
# NOTE: Content is injected in page only at this point! Keep in mind for other substitutions # NOTE: Content is injected in page only at this point! Keep in mind for other substitutions
'[staticoso:Page:Content]': Content, #'[staticoso:Page:Content]': Content,
'<staticoso:PageContent>': Content, #'<staticoso:PageContent>': Content,
'[staticoso:Page:ContentInfo]': ContentHeader, #'[staticoso:Page:ContentInfo]': ContentHeader,
'<staticoso:PageContentInfo>': ContentHeader, #'<staticoso:PageContentInfo>': ContentHeader,
'[staticoso:BuildTime]': TimeNow, #'[staticoso:BuildTime]': TimeNow,
'<staticoso:BuildTime>': TimeNow, #'<staticoso:BuildTime>': TimeNow,
'<staticoso:SiteDomain>': SiteDomain, #'<staticoso:SiteDomain>': SiteDomain,
'[staticoso:Site:Name]': SiteName, #'[staticoso:Site:Name]': SiteName,
'<staticoso:SiteName>': SiteName, #'<staticoso:SiteName>': SiteName,
'[staticoso:Site:AbsoluteRoot]': SiteRoot, #'[staticoso:Site:AbsoluteRoot]': SiteRoot,
'<staticoso:SiteAbsoluteRoot>': SiteRoot, #'<staticoso:SiteAbsoluteRoot>': SiteRoot,
'[staticoso:Site:RelativeRoot]': RelativeRoot, #'[staticoso:Site:RelativeRoot]': RelativeRoot,
'<staticoso:SiteRelativeRoot>': RelativeRoot}) #'<staticoso:SiteRelativeRoot>': RelativeRoot,
# #DEPRECATION #
'staticoso:Page:Content': Content,
'staticoso:Page:ContentInfo': ContentHeader,
'staticoso:Site:Name': SiteName,
'staticoso:Site:AbsoluteRoot': SiteRoot,
'staticoso:Site:RelativeRoot': RelativeRoot,
################
'staticoso:PageContent': Content,
'staticoso:PageContentInfo': ContentHeader,
'staticoso:BuildTime': TimeNow,
'staticoso:SiteDomain': SiteDomain,
'staticoso:SiteName': SiteName,
'staticoso:SiteAbsoluteRoot': SiteRoot,
'staticoso:SiteRelativeRoot': RelativeRoot,
}, InternalMacrosWraps)
for e in Meta['Macros']: for e in Meta['Macros']:
HTML = ReplWithEsc(HTML, f"[:{e}:]", Meta['Macros'][e]) HTML = ReplWithEsc(HTML, f"[:{e}:]", Meta['Macros'][e])
for e in FolderRoots: for e in FolderRoots:
HTML = DictReplWithEsc(HTML, { HTML = WrapDictReplWithEsc(HTML, {
f"[staticoso:CustomPath:{e}]": FolderRoots[e], f'staticoso:CustomPath:{e}': FolderRoots[e],
f"<staticoso:CustomPath:{e}>": FolderRoots[e], f'staticoso:Folder:{e}:AbsoluteRoot': FolderRoots[e], #DEPRECATED
#DEPRECATED }, InternalMacrosWraps)
f"[staticoso:Folder:{e}:AbsoluteRoot]": FolderRoots[e],
f"<staticoso:Folder:{e}:AbsoluteRoot>": FolderRoots[e]})
for e in Categories: for e in Categories:
HTML = DictReplWithEsc(HTML, { HTML = WrapDictReplWithEsc(HTML, {
f"[staticoso:Category:{e}]": Categories[e], f'staticoso:Category:{e}': Categories[e],
f"<staticoso:Category:{e}>": Categories[e], f'staticoso:CategoryList:{e}': Categories[e],
f"<staticoso:CategoryList:{e}>": Categories[e], }, InternalMacrosWraps)
#DEPRECATED HTML = ReplWithEsc(HTML, f'<span>[staticoso:Category:{e}]</span>', Categories[e]) #DEPRECATED
f"<span>[staticoso:Category:{e}]</span>": Categories[e]})
# TODO: Clean this doubling? # TODO: Clean this doubling?
ContentHTML = Content ContentHTML = Content
ContentHTML = DictReplWithEsc(ContentHTML, { ContentHTML = WrapDictReplWithEsc(ContentHTML, {
#'[staticoso:Page:Title]': Title,
#'<staticoso:PageTitle>': Title,
#'[staticoso:Page:Description]': Description,
#'<staticoso:PageDescription>': Description,
#'<staticoso:SiteDomain>': SiteDomain,
#'[staticoso:Site:Name]': SiteName,
#'<staticoso:SiteName>': SiteName,
#'[staticoso:Site:AbsoluteRoot]': SiteRoot,
#'<staticoso:SiteAbsoluteRoot>': SiteRoot,
#'[staticoso:Site:RelativeRoot]': RelativeRoot,
#'<staticoso:SiteRelativeRoot>': RelativeRoot,
# #DEPRECATION #
'[staticoso:Page:Title]': Title, '[staticoso:Page:Title]': Title,
'<staticoso:PageTitle>': Title,
'[staticoso:Page:Description]': Description, '[staticoso:Page:Description]': Description,
'[staticoso:Site:Name]': SiteName,
'[staticoso:Site:AbsoluteRoot]': SiteRoot,
'[staticoso:Site:RelativeRoot]': RelativeRoot,
################
'<staticoso:PageTitle>': Title,
'<staticoso:PageDescription>': Description, '<staticoso:PageDescription>': Description,
'<staticoso:SiteDomain>': SiteDomain, '<staticoso:SiteDomain>': SiteDomain,
'[staticoso:Site:Name]': SiteName,
'<staticoso:SiteName>': SiteName, '<staticoso:SiteName>': SiteName,
'[staticoso:Site:AbsoluteRoot]': SiteRoot,
'<staticoso:SiteAbsoluteRoot>': SiteRoot, '<staticoso:SiteAbsoluteRoot>': SiteRoot,
'[staticoso:Site:RelativeRoot]': RelativeRoot, '<staticoso:SiteRelativeRoot>': RelativeRoot,
'<staticoso:SiteRelativeRoot>': RelativeRoot}) }, InternalMacrosWraps)
for e in Meta['Macros']: for e in Meta['Macros']:
ContentHTML = ReplWithEsc(ContentHTML, f"[:{e}:]", Meta['Macros'][e]) ContentHTML = ReplWithEsc(ContentHTML, f"[:{e}:]", Meta['Macros'][e])
for e in FolderRoots: for e in FolderRoots:
ContentHTML = DictReplWithEsc(ContentHTML, { ContentHTML = WrapDictReplWithEsc(ContentHTML, {
f"[staticoso:CustomPath:{e}]": FolderRoots[e], f'staticoso:CustomPath:{e}': FolderRoots[e],
f"<staticoso:CustomPath:{e}>": FolderRoots[e], f'staticoso:Folder:{e}:AbsoluteRoot': FolderRoots[e], #DEPRECATED
#DEPRECATED }, InternalMacrosWraps)
f"[staticoso:Folder:{e}:AbsoluteRoot]": FolderRoots[e],
f"<staticoso:Folder:{e}:AbsoluteRoot>": FolderRoots[e]})
for e in Categories: for e in Categories:
ContentHTML = DictReplWithEsc(ContentHTML, { ContentHTML = WrapDictReplWithEsc(ContentHTML, {
f"[staticoso:Category:{e}]": Categories[e], f'staticoso:Category:{e}': Categories[e],
f"<staticoso:Category:{e}>": Categories[e], f'staticoso:CategoryList:{e}': Categories[e],
f"<staticoso:CategoryList:{e}>": Categories[e], }, InternalMacrosWraps)
#DEPRECATED ContentHTML = ReplWithEsc(ContentHTML, f'<span>[staticoso:Category:{e}]</span>', Categories[e]) #DEPRECATED
f"<span>[staticoso:Category:{e}]</span>": Categories[e]})
return HTML, ContentHTML, Description, Image return HTML, ContentHTML, Description, Image

View File

@ -12,13 +12,7 @@ import json
import os import os
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from Modules.Globals import *
ReservedPaths = ('Site.ini', 'Assets', 'Pages', 'Posts', 'Templates', 'StaticParts', 'DynamicParts')
FileExtensions = {
'Pages': ('htm', 'html', 'markdown', 'md', 'pug', 'txt'),
'HTML': ('.htm', '.html'),
'Markdown': ('.markdown', '.md'),
'Tmp': ('htm', 'markdown', 'md', 'pug', 'txt')}
def SureList(e): def SureList(e):
return e if type(e) == list else [e] return e if type(e) == list else [e]
@ -111,11 +105,18 @@ def ReplWithEsc(Str, Find, Repl, Esc='\\'):
New += Repl + e New += Repl + e
return New return New
def DictReplWithEsc(Str, Dict, Esc='\\'): def DictReplWithEsc(Str:str, Dict:dict, Esc:str='\\'):
for Item in Dict: for Item in Dict:
Str = ReplWithEsc(Str, Item, Dict[Item], Esc='\\') Str = ReplWithEsc(Str, Item, Dict[Item], Esc='\\')
return Str return Str
def WrapDictReplWithEsc(Str:str, Dict:dict, Wraps:list=[], Esc:str='\\'):
NewDict = {}
for Item in Dict:
for Wrap in Wraps:
NewDict.update({f'{Wrap[0]}{Item}{Wrap[1]}': Dict[Item]})
return DictReplWithEsc(Str, NewDict, Esc)
def NumsFromFileName(Path): def NumsFromFileName(Path):
Name = Path.split('/')[-1] Name = Path.split('/')[-1]
Split = len(Name) Split = len(Name)

11
TODO
View File

@ -1,5 +1,10 @@
- .html input pages bug: // metadata lines not being removed from final file after parsing
- Multi-line metadata flags
- Category-based feeds
- Meta tag generator showing software version (git commit hash)
- Customize date format
- Misskey for ActivityPub - Misskey for ActivityPub
- Section marking in pages (for use with external translators) - Section marking in pages? (for use with external translators)
- Choosing to use HTML or CSS styling for default internal snippets - Choosing to use HTML or CSS styling for default internal snippets
- Pages transclusion + probably drop StaticParts (would be redundant) - Pages transclusion + probably drop StaticParts (would be redundant)
- User macros with arguments - User macros with arguments
@ -17,8 +22,8 @@
- Custom path for Posts and Categories - Custom path for Posts and Categories
- Support for YAML header in Markdown - Support for YAML header in Markdown
- Support for HTML comment lines (<!-- -->) in any format - Support for HTML comment lines (<!-- -->) in any format
- Support for rST and AsciiDoc (?) - Support for Wikitext, rST, AsciiDoc (?)
- Posts in draft state (will not be compiled) / show unlisted status for posts with Index = False - Posts in draft state (will not be compiled) (?)
- Check if external tools (pug-cli, html2gmi) are installed - Check if external tools (pug-cli, html2gmi) are installed
- Static code syntax highlighing - Static code syntax highlighing
- Override internal HTML snippets (meta lines, page lists, redirects, ...) with config file in Templates/NAME.ini - Override internal HTML snippets (meta lines, page lists, redirects, ...) with config file in Templates/NAME.ini