2022-08-30 21:10:45 +02:00
""" ================================= |
| This file is part of |
| staticoso |
| Just a simple Static Site Generator |
| |
| Licensed under the AGPLv3 license |
| Copyright ( C ) 2022 , OctoSpacc |
| == == == == == == == == == == == == == == == == = """
2022-11-17 13:03:17 +01:00
from base64 import b64encode
2022-08-30 21:10:45 +02:00
from Modules . HTML import *
from Modules . Utils import *
2022-11-16 13:07:27 +01:00
JournalHeadings = ( ' h2 ' , ' h3 ' , ' h4 ' , ' h5 ' )
JournalTitleDecorators = { ' ( ' : ' ) ' , ' [ ' : ' ] ' , ' { ' : ' } ' }
2022-11-17 13:03:17 +01:00
#JournalStyles = {
# "Default": {},
# "details": {}
#}
2022-11-04 11:03:43 +01:00
HTMLSectionTitleLine = ' <h {Index} class= " SectionHeading staticoso-SectionHeading " ><span class= " SectionLink staticoso-SectionLink " ><a href= " # {DashTitle} " ><span>»</span></a> </span><span class= " SectionTitle staticoso-SectionTitle " id= " {DashTitle} " > {Title} </span></h {Index} > '
PugSectionTitleLine = " {Start} {Heading} .SectionHeading.staticoso-SectionHeading #[span.SectionLink.staticoso-SectionLink #[a(href= ' # {DashTitle} ' ) #[span »]] ]#[span# {DashTitle} .SectionTitle.staticoso-SectionTitle {Rest} ] "
2022-08-30 21:10:45 +02:00
CategoryPageTemplate = """ \
/ / Title : { Name }
/ / Type : Page
/ / Index : True
# {Name}
2022-10-17 15:53:07 +02:00
< div > < staticoso : Category : { Name } > < / div >
2022-08-30 21:10:45 +02:00
"""
2022-10-17 15:53:07 +02:00
RedirectPageTemplate = """ \
< ! DOCTYPE html >
< html >
< head >
2022-11-02 00:17:36 +01:00
< title > { TitlePrefix } Redirect < / title >
< link rel = " canonical " href = " {SiteDomain} / {DestURL} " >
< meta http - equiv = " refresh " content = " 0; url= ' {DestURL} ' " >
2022-10-17 15:53:07 +02:00
< / head >
< body >
2022-11-02 00:17:36 +01:00
< p > < a href = " {DestURL} " > { StrClick } < / a > { StrRedirect } . < / p >
2022-10-17 15:53:07 +02:00
< / body >
< / html >
"""
2022-11-18 20:51:54 +01:00
HTMLCommentsBlock = ' <br><h3> {StrComments} </h3><a href= " {URL} " rel= " noopener " target= " _blank " > {StrOpen} <span class= " twa twa-↗️ " ><span>↗️</span></span></a> '
2022-08-30 21:10:45 +02:00
def DashifyTitle ( Title , Done = [ ] ) :
return UndupeStr ( DashifyStr ( Title . lstrip ( ' ' ) . rstrip ( ' ' ) ) , Done , ' - ' )
def MakeLinkableTitle ( Line , Title , DashTitle , Type ) :
if Type == ' md ' :
Index = Title . split ( ' ' ) [ 0 ] . count ( ' # ' )
return HTMLSectionTitleLine . format (
Index = Index ,
DashTitle = DashTitle ,
Title = Title [ Index + 1 : ] )
elif Type == ' pug ' :
Index = Line . find ( ' h ' )
2022-11-04 11:03:43 +01:00
return PugSectionTitleLine . format (
Start = Line [ : Index ] ,
Heading = Line [ Index : Index + 2 ] ,
Rest = Line [ Index + 2 : ] ,
DashTitle = DashTitle )
2022-08-30 21:10:45 +02:00
def GetTitle ( FileName , Meta , Titles , Prefer = ' MetaTitle ' , BlogName = None ) :
if Prefer == ' BodyTitle ' :
Title = Titles [ 0 ] . lstrip ( ' # ' ) if Titles else Meta [ ' Title ' ] if Meta [ ' Title ' ] else FileName
elif Prefer == ' MetaTitle ' :
Title = Meta [ ' Title ' ] if Meta [ ' Title ' ] else Titles [ 0 ] . lstrip ( ' # ' ) if Titles else FileName
elif Prefer == ' HTMLTitle ' :
Title = Meta [ ' HTMLTitle ' ] if Meta [ ' HTMLTitle ' ] else Meta [ ' Title ' ] if Meta [ ' Title ' ] else Titles [ 0 ] . lstrip ( ' # ' ) if Titles else FileName
if BlogName and ' Blog ' in Meta [ ' Categories ' ] :
Title + = ' - ' + BlogName
return Title
def GetDescription ( Meta , BodyDescription , Prefer = ' MetaDescription ' ) :
if Prefer == ' BodyDescription ' :
Description = BodyDescription if BodyDescription else Meta [ ' Description ' ] if Meta [ ' Description ' ] else ' '
elif Prefer == ' MetaDescription ' :
Description = Meta [ ' Description ' ] if Meta [ ' Description ' ] else BodyDescription if BodyDescription else ' '
return Description
def GetImage ( Meta , BodyImage , Prefer = ' MetaImage ' ) :
if Prefer == ' BodyImage ' :
Image = BodyImage if BodyImage else Meta [ ' Image ' ] if Meta [ ' Image ' ] else ' '
elif Prefer == ' MetaImage ' :
Image = Meta [ ' Image ' ] if Meta [ ' Image ' ] else BodyImage if BodyImage else ' '
return Image
def MakeContentHeader ( Meta , Locale , Categories = ' ' ) :
Header = ' '
2022-10-19 11:27:51 +02:00
for e in [ ' CreatedOn ' , ' EditedOn ' ] :
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> '
2022-08-30 21:10:45 +02:00
if Categories :
2022-10-19 11:27:51 +02:00
Header + = f ' <span class= " staticoso-ContentHeader-Categories " ><span class= " staticoso-Label " > { Locale [ " Categories " ] } </span>:<span class= " staticoso-Value " > { Categories . removesuffix ( " " ) } </span></span><br> '
2022-08-30 21:10:45 +02:00
return f ' <p> { Header } </p> '
def MakeCategoryLine ( File , Meta ) :
Categories = ' '
2022-11-04 11:03:43 +01:00
for Cat in Meta [ ' Categories ' ] :
Categories + = f ' <a href= " { GetPathLevels ( File ) } Categories/ { Cat } .html " > { html . escape ( Cat ) } </a> '
2022-08-30 21:10:45 +02:00
return Categories
def MakeListTitle ( File , Meta , Titles , Prefer , SiteRoot , BlogName , PathPrefix = ' ' ) :
2022-10-26 11:01:17 +02:00
Title = GetTitle ( File . split ( ' / ' ) [ - 1 ] , Meta , Titles , Prefer , BlogName ) . lstrip ( ) . rstrip ( )
2022-08-30 21:10:45 +02:00
Link = False if Meta [ ' Index ' ] == ' Unlinked ' else True
if Link :
2022-11-04 11:03:43 +01:00
Href = f ' { PathPrefix } { StripExt ( File ) } .html '
Title = f ' <a href= " { Href } " > { Title } </a> '
2022-08-30 21:10:45 +02:00
if Meta [ ' Type ' ] == ' Post ' :
CreatedOn = Meta [ ' CreatedOn ' ] if Meta [ ' CreatedOn ' ] else ' ? '
2022-11-16 13:07:27 +01:00
Title = f " [<time> { CreatedOn } </time>] { Title } "
2022-08-30 21:10:45 +02:00
return Title
def FormatTitles ( Titles , Flatten = False ) :
# TODO: Somehow titles written in Pug can end up here and don't work, they should be handled
HTMLTitles , DashyTitles = ' ' , [ ]
for t in Titles :
n = 0 if Flatten else t . split ( ' ' ) [ 0 ] . count ( ' # ' )
Title = MkSoup ( t . lstrip ( ' # ' ) ) . get_text ( )
DashyTitle = DashifyTitle ( Title , DashyTitles )
DashyTitles + = [ DashyTitle ]
Start = ' <ul><li> ' * ( n - 1 )
End = ' </li></ul> ' * ( n - 1 )
HTMLTitles + = f ' <li> { Start } <a href= " # { DashyTitle } " > { html . escape ( Title ) } </a> { End } </li> '
return f ' <ul> { HTMLTitles } </ul> '
2022-11-16 13:07:27 +01:00
# Clean up a generic HTML tree such that it's compliant with the HTML Journal standard
# (https://m15o.ichi.city/site/subscribing-to-a-journal-page.html);
# basis is: find an element with the JournalBody attr., and group its direct children as <article>s
2022-11-17 13:03:17 +01:00
def MakeHTMLJournal ( Flags , Locale , FilePath , HTML ) :
2022-11-16 13:07:27 +01:00
Soup , Journal , Entries = MkSoup ( HTML ) , ' ' , [ ]
for t in Soup . find_all ( attrs = { " htmljournal " : True } ) :
2022-11-17 13:03:17 +01:00
#JournalStyle = JournalStyles[t.attrs["journalstyle"]] if 'journalstyle' in t.attrs and t.attrs["journalstyle"] in JournalStyles else JournalStyles['Default']
2022-11-16 13:07:27 +01:00
for c in t . children : # Entries, some might be entirely grouped in their own element but others could not, use headings as separators
for ct in MkSoup ( str ( c ) ) . find_all ( ) :
# Transform (almost, for now I reserve some) any heading into h2 and remove any attributes
if ct . name in JournalHeadings :
Title = ct . text . strip ( ) . removeprefix ( ' » ' ) . strip ( )
Chr0 = Title [ 0 ]
2022-11-17 13:03:17 +01:00
# Remove leading symbols before date
2022-11-16 13:07:27 +01:00
if Chr0 in JournalTitleDecorators . keys ( ) :
Idx = Title . find ( JournalTitleDecorators [ Chr0 ] )
Title = Title [ 1 : Idx ] + ' - ' + Title [ Idx + 2 : ]
if Journal :
2022-11-17 13:03:17 +01:00
Journal + = ' \n </article><br> \n '
2022-11-16 13:07:27 +01:00
Journal + = f ' \n <article> \n <h2> { Title } </h2> \n '
elif ct . name == ' p ' : # We should handle any type to preserve <details> and things
Journal + = str ( ct )
2022-11-17 13:03:17 +01:00
FileName = FilePath . split ( ' / ' ) [ - 1 ]
URL = f ' { Flags [ " SiteDomain " ] } / { StripExt ( FilePath ) } .Journal.html '
2022-11-18 20:51:54 +01:00
Redirect = f """ <meta http-equiv= " refresh " content= " 0; url= ' ./ { FileName } ' " > """ if Flags [ " JournalRedirect " ] else ' '
2022-11-17 13:03:17 +01:00
# Instead of copying stuff from the full page, for now we use dedicated title, header, footer, and pagination
Title = t . attrs [ " journaltitle " ] if ' journaltitle ' in t . attrs else f ' " { StripExt ( FileName ) } " Journal - { Flags [ " SiteName " ] } ' if Flags [ " SiteName " ] else f ' " { StripExt ( FileName ) } " Journal '
FeedLink = f """ <a title= " Journal Atom Feed " href= " https://journal.miso.town/atom?url= { URL } " target= " _blank " rel= " noopener " ><img width= " 88 " height= " 31 " alt= " Journal Atom Feed " title= " Journal Atom Feed " src= " data:image/png;base64, { b64encode ( ReadFile ( staticosoBaseDir ( ) + ' Assets/Feed-88x31.png ' , ' rb ' ) ) . decode ( ) } " ></a> """ if Flags [ " SiteDomain " ] else ' '
Header = t . attrs [ " journalheader " ] if ' journalheader ' in t . attrs else f """ \
< p >
< i > { Locale [ " StrippedDownNotice " ] . format ( Link = " ./ " + FileName ) } < / i >
< a title = " Valid HTML Journal " href = " https://journal.miso.town " target = " _blank " rel = " noopener " > < img alt = " Valid HTML Journal " title = " Valid HTML Journal " width = " 88 " height = " 31 " src = " data:image/png;base64, { b64encode(ReadFile(staticosoBaseDir()+ ' Assets/Valid-HTML-Journal-88x31.png ' , ' rb ' )).decode()} " > < / a >
{ FeedLink }
< / p >
"""
Journal = f """ \
2022-11-18 20:51:54 +01:00
< ! - -
2022-11-17 13:03:17 +01:00
< ! DOCTYPE html >
< html >
< head >
< title > { Title } < / title >
< link rel = " canonical " href = " {URL} " >
2022-11-18 20:51:54 +01:00
{ Redirect }
2022-11-17 13:03:17 +01:00
< / head >
< body >
2022-11-18 20:51:54 +01:00
- - - >
2022-11-17 13:03:17 +01:00
< h1 > { Title } < / h1 >
2022-11-18 20:51:54 +01:00
< header id = " Header " >
{ Header }
< div id = " staticoso-LinkToFooter " > < b > [ < big > < a href = " #Footer " > < span class = " twa twa-⬇️ " > < span > ⬇ ️ < / span > < / span > Footer < / a > < / big > ] < / b > < / div >
< / header > < br >
2022-11-17 13:03:17 +01:00
{ Journal }
< / article > < br >
2022-11-18 20:51:54 +01:00
< footer id = " Footer " >
< div id = " staticoso-LinkToHeader " > < b > [ < big > < a href = " #Header " > < span class = " twa twa-⬆️ " > < span > ⬆ ️ < / span > < / span > Header < / a > < / big > ] < / b > < / div >
{ t . attrs [ " journalfooter " ] if " journalfooter " in t . attrs else " " }
< / footer >
< ! - -
2022-11-17 13:03:17 +01:00
< / body >
< / html >
2022-11-18 20:51:54 +01:00
- - - >
2022-11-17 13:03:17 +01:00
"""
2022-11-16 13:07:27 +01:00
return Journal