mirror of
https://gitlab.com/octtspacc/staticoso
synced 2025-06-05 22:09:23 +02:00
More coherent conf. flags, Updated README, minor code improv.
This commit is contained in:
parent
c546458073
commit
a1e77b8f91
19
README.md
19
README.md
@ -17,11 +17,13 @@ Obviously, it's built with staticoso itself 😁️. Its source repo can be foun
|
|||||||
Keep in mind that, currently, it's still very incomplete. **Any help**, from writing the documentation to creating a decent HTML+CSS template for its site, **is more than welcome**.
|
Keep in mind that, currently, it's still very incomplete. **Any help**, from writing the documentation to creating a decent HTML+CSS template for its site, **is more than welcome**.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- [Python == 3.10.4](https://python.org)
|
|
||||||
|
- [Python >= 3.10](https://python.org)
|
||||||
- (Included) [Python Markdown == 3.3.7](https://pypi.org/project/Markdown)
|
- (Included) [Python Markdown == 3.3.7](https://pypi.org/project/Markdown)
|
||||||
- (Included) Third-Party Extensions for Python Markdown: [markdown_del_ins](https://github.com/honzajavorek/markdown-del-ins), [mdx_subscript](https://github.com/jambonrose/markdown_subscript_extension), [mdx_superscript](https://github.com/jambonrose/markdown_superscript_extension)
|
- (Included) Third-Party Extensions for Python Markdown: [markdown_del_ins](https://github.com/honzajavorek/markdown-del-ins), [mdx_subscript](https://github.com/jambonrose/markdown_subscript_extension), [mdx_superscript](https://github.com/jambonrose/markdown_superscript_extension)
|
||||||
- (Included) [Beautiful Soup == 4.11.1](https://pypi.org/project/beautifulsoup4)
|
- (Included) [Beautiful Soup == 4.11.1](https://pypi.org/project/beautifulsoup4)
|
||||||
- (Included) [feedgen == 0.9.0](https://pypi.org/project/feedgen)
|
- (Included) [feedgen == 0.9.0](https://pypi.org/project/feedgen)
|
||||||
|
- [lxml == 4.9.1](https://pypi.org/project/lxml)
|
||||||
- (Included) [htmlmin == 0.1.12](https://pypi.org/project/htmlmin)
|
- (Included) [htmlmin == 0.1.12](https://pypi.org/project/htmlmin)
|
||||||
|
|
||||||
### Optional dependencies
|
### Optional dependencies
|
||||||
@ -29,7 +31,7 @@ Keep in mind that, currently, it's still very incomplete. **Any help**, from wri
|
|||||||
Needed for Pug input support:
|
Needed for Pug input support:
|
||||||
|
|
||||||
- [node == 12.22.5](https://nodejs.org) - [npm == 7.5.2](https://www.npmjs.com)
|
- [node == 12.22.5](https://nodejs.org) - [npm == 7.5.2](https://www.npmjs.com)
|
||||||
- (Included) [pug-cli == 1.0.0-alpha6](https://npmjs.com/package/pug-cli)
|
- (Included, must be manually installed in system $PATH) [pug-cli == 1.0.0-alpha6](https://npmjs.com/package/pug-cli)
|
||||||
|
|
||||||
Needed for Gemtext output support:
|
Needed for Gemtext output support:
|
||||||
|
|
||||||
@ -37,14 +39,17 @@ Needed for Gemtext output support:
|
|||||||
- [html2gmi](https://github.com/LukeEmmet/html2gmi)
|
- [html2gmi](https://github.com/LukeEmmet/html2gmi)
|
||||||
|
|
||||||
## Features roadmap
|
## Features roadmap
|
||||||
|
|
||||||
|
- [ ] Overriding internal HTML snippets for template-specific ones
|
||||||
|
- [ ] Static syntax highlighing for code blocks in any page
|
||||||
- [x] File name used as a title for pages without one
|
- [x] File name used as a title for pages without one
|
||||||
- [ ] Custom category names in header links
|
- [ ] Custom category names in header links
|
||||||
- [ ] Choosing custom name for Blog and Uncategorized categories
|
- [ ] Choosing custom name for Blog and Uncategorized categories
|
||||||
- [ ] Choosing to use a template for all pages in a folder
|
- [ ] Choosing to use a template for all pages in a folder
|
||||||
- [ ] Configuration with both INI files and CLI arguments
|
- [x] Configuration with both INI files and CLI arguments
|
||||||
- [ ] Category-based feeds
|
- [ ] Category-based feeds
|
||||||
- [ ] Support for multi-language sites
|
- [ ] Support for multi-language sites
|
||||||
- [x] The `title` attribute is added to images which only have `alt` (for desktop accessibility)
|
- [x] The `title` attribute is added to images which only have `alt` (for desktop accessibility), or viceversa
|
||||||
- [x] Local (per-page) and global (per-site) macros
|
- [x] Local (per-page) and global (per-site) macros
|
||||||
- [x] ActivityPub (Mastodon) support (Feed + embedded comments)
|
- [x] ActivityPub (Mastodon) support (Feed + embedded comments)
|
||||||
- [ ] Polished Gemtext generation
|
- [ ] Polished Gemtext generation
|
||||||
@ -68,3 +73,9 @@ Needed for Gemtext output support:
|
|||||||
- [x] Auto-detection of titles in a page
|
- [x] Auto-detection of titles in a page
|
||||||
- [x] _HTML_, TXT, _Extended Markdown_, and _Pug_ supported for input page files
|
- [x] _HTML_, TXT, _Extended Markdown_, and _Pug_ supported for input page files
|
||||||
- [ ] Out of heavy-WIP state
|
- [ ] Out of heavy-WIP state
|
||||||
|
|
||||||
|
## Known issues (might need further investigation)
|
||||||
|
|
||||||
|
- Bad HTML included in Markdown files can cause a build to fail entirely.
|
||||||
|
- The program currently takes about 2 seconds to build a smallish site. While by itself that's not a long time, problems could arise for bigger sites.
|
||||||
|
- Ordering pages in the global menu with external configuration flags (outside the pages' source) yields broken and unpredictable results.
|
@ -135,14 +135,16 @@ def Main(Args, FeedEntries):
|
|||||||
ActivityPubTypeFilter = OptionChoose('Post', Args.ActivityPubTypeFilter, ReadConf(SiteConf, 'ActivityPub', 'TypeFilter'))
|
ActivityPubTypeFilter = OptionChoose('Post', Args.ActivityPubTypeFilter, ReadConf(SiteConf, 'ActivityPub', 'TypeFilter'))
|
||||||
ActivityPubHoursLimit = OptionChoose(168, Args.ActivityPubHoursLimit, ReadConf(SiteConf, 'ActivityPub', 'HoursLimit'))
|
ActivityPubHoursLimit = OptionChoose(168, Args.ActivityPubHoursLimit, ReadConf(SiteConf, 'ActivityPub', 'HoursLimit'))
|
||||||
FeedCategoryFilter = OptionChoose('Blog', Args.FeedCategoryFilter, ReadConf(SiteConf, 'Feed', 'CategoryFilter'))
|
FeedCategoryFilter = OptionChoose('Blog', Args.FeedCategoryFilter, ReadConf(SiteConf, 'Feed', 'CategoryFilter'))
|
||||||
Minify = StringBoolChoose(False, Args.Minify, ReadConf(SiteConf, 'Site', 'Minify'))
|
Minify = StringBoolChoose(False, Args.Minify, ReadConf(SiteConf, 'Minify', 'Minify'))
|
||||||
|
MinifyKeepComments = StringBoolChoose(False, Args.MinifyKeepComments, ReadConf(SiteConf, 'Minify', 'KeepComments'))
|
||||||
NoScripts = StringBoolChoose(False, Args.NoScripts, ReadConf(SiteConf, 'Site', 'NoScripts'))
|
NoScripts = StringBoolChoose(False, Args.NoScripts, ReadConf(SiteConf, 'Site', 'NoScripts'))
|
||||||
ImgAltToTitle = StringBoolChoose(True, Args.ImgAltToTitle, ReadConf(SiteConf, 'Site', 'ImgAltToTitle'))
|
ImgAltToTitle = StringBoolChoose(True, Args.ImgAltToTitle, ReadConf(SiteConf, 'Site', 'ImgAltToTitle'))
|
||||||
ImgTitleToAlt = StringBoolChoose(False, Args.ImgTitleToAlt, ReadConf(SiteConf, 'Site', 'ImgTitleToAlt'))
|
ImgTitleToAlt = StringBoolChoose(False, Args.ImgTitleToAlt, ReadConf(SiteConf, 'Site', 'ImgTitleToAlt'))
|
||||||
AutoCategories = StringBoolChoose(False, Args.AutoCategories, ReadConf(SiteConf, 'Site', 'AutoCategories'))
|
CategoriesAutomatic = StringBoolChoose(False, Args.CategoriesAutomatic, ReadConf(SiteConf, 'Categories', 'Automatic'))
|
||||||
GemtextOut = StringBoolChoose(False, Args.GemtextOut, ReadConf(SiteConf, 'Site', 'GemtextOut'))
|
CategoriesUncategorized = OptionChoose('Uncategorized', Args.CategoriesUncategorized, ReadConf(SiteConf, 'Categories', 'Uncategorized'))
|
||||||
|
GemtextOutput = StringBoolChoose(False, Args.GemtextOutput, ReadConf(SiteConf, 'Gemtext', 'Output'))
|
||||||
GemtextHeader = Args.GemtextHeader if Args.GemtextHeader else ReadConf(SiteConf, 'Gemtext', 'Header') if ReadConf(SiteConf, 'Gemtext', 'Header') else f"# {SiteName}\n\n" if SiteName else ''
|
GemtextHeader = Args.GemtextHeader if Args.GemtextHeader else ReadConf(SiteConf, 'Gemtext', 'Header') if ReadConf(SiteConf, 'Gemtext', 'Header') else f"# {SiteName}\n\n" if SiteName else ''
|
||||||
SitemapOut = StringBoolChoose(True, Args.SitemapOut, ReadConf(SiteConf, 'Site', 'SitemapOut'))
|
SitemapOutput = StringBoolChoose(True, Args.SitemapOutput, ReadConf(SiteConf, 'Sitemap', 'Output'))
|
||||||
FeedEntries = int(FeedEntries) if (FeedEntries or FeedEntries == 0) 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(OptionChoose('{}', Args.Sorting, ReadConf(SiteConf, 'Site', 'Sorting')))
|
Sorting = literal_eval(OptionChoose('{}', Args.Sorting, ReadConf(SiteConf, 'Site', 'Sorting')))
|
||||||
|
|
||||||
@ -163,12 +165,12 @@ def Main(Args, FeedEntries):
|
|||||||
if os.path.isdir('Pages'):
|
if os.path.isdir('Pages'):
|
||||||
HavePages = True
|
HavePages = True
|
||||||
shutil.copytree('Pages', OutputDir, dirs_exist_ok=True)
|
shutil.copytree('Pages', OutputDir, dirs_exist_ok=True)
|
||||||
if GemtextOut:
|
if GemtextOutput:
|
||||||
shutil.copytree('Pages', f"{OutputDir}.gmi", ignore=IgnoreFiles, dirs_exist_ok=True)
|
shutil.copytree('Pages', f"{OutputDir}.gmi", ignore=IgnoreFiles, dirs_exist_ok=True)
|
||||||
if os.path.isdir('Posts'):
|
if os.path.isdir('Posts'):
|
||||||
HavePosts = True
|
HavePosts = True
|
||||||
shutil.copytree('Posts', f"{OutputDir}/Posts", dirs_exist_ok=True)
|
shutil.copytree('Posts', f"{OutputDir}/Posts", dirs_exist_ok=True)
|
||||||
if GemtextOut:
|
if GemtextOutput:
|
||||||
shutil.copytree('Posts', f"{OutputDir}.gmi/Posts", ignore=IgnoreFiles, dirs_exist_ok=True)
|
shutil.copytree('Posts', f"{OutputDir}.gmi/Posts", ignore=IgnoreFiles, dirs_exist_ok=True)
|
||||||
|
|
||||||
if not (HavePages or HavePosts):
|
if not (HavePages or HavePosts):
|
||||||
@ -195,11 +197,12 @@ def Main(Args, FeedEntries):
|
|||||||
SiteLang=SiteLang,
|
SiteLang=SiteLang,
|
||||||
Locale=Locale,
|
Locale=Locale,
|
||||||
Minify=Minify,
|
Minify=Minify,
|
||||||
|
MinifyKeepComments=MinifyKeepComments,
|
||||||
NoScripts=NoScripts,
|
NoScripts=NoScripts,
|
||||||
ImgAltToTitle=ImgAltToTitle, ImgTitleToAlt=ImgTitleToAlt,
|
ImgAltToTitle=ImgAltToTitle, ImgTitleToAlt=ImgTitleToAlt,
|
||||||
Sorting=SetSorting(Sorting),
|
Sorting=SetSorting(Sorting),
|
||||||
MarkdownExts=MarkdownExts,
|
MarkdownExts=MarkdownExts,
|
||||||
AutoCategories=AutoCategories)
|
AutoCategories=CategoriesAutomatic)
|
||||||
|
|
||||||
if FeedEntries != 0:
|
if FeedEntries != 0:
|
||||||
print("[I] Generating Feeds")
|
print("[I] Generating Feeds")
|
||||||
@ -245,14 +248,14 @@ def Main(Args, FeedEntries):
|
|||||||
Content = ReplWithEsc(Content, '[staticoso:Comments]', Post)
|
Content = ReplWithEsc(Content, '[staticoso:Comments]', Post)
|
||||||
WriteFile(File, Content)
|
WriteFile(File, Content)
|
||||||
|
|
||||||
if GemtextOut:
|
if GemtextOutput:
|
||||||
print("[I] Generating Gemtext")
|
print("[I] Generating Gemtext")
|
||||||
GemtextCompileList(OutputDir, Pages, GemtextHeader)
|
GemtextCompileList(OutputDir, Pages, GemtextHeader)
|
||||||
|
|
||||||
print("[I] Cleaning Temporary Files")
|
print("[I] Cleaning Temporary Files")
|
||||||
DelTmp(OutputDir)
|
DelTmp(OutputDir)
|
||||||
|
|
||||||
if SitemapOut:
|
if SitemapOutput:
|
||||||
print("[I] Generating Sitemap")
|
print("[I] Generating Sitemap")
|
||||||
MakeSitemap(OutputDir, Pages, SiteDomain)
|
MakeSitemap(OutputDir, Pages, SiteDomain)
|
||||||
|
|
||||||
@ -261,7 +264,7 @@ def Main(Args, FeedEntries):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
Parser = argparse.ArgumentParser()
|
Parser = argparse.ArgumentParser()
|
||||||
Parser.add_argument('--DiffBuild', action='store_true')
|
Parser.add_argument('--DiffBuild', type=str)
|
||||||
Parser.add_argument('--OutputDir', type=str)
|
Parser.add_argument('--OutputDir', type=str)
|
||||||
#Parser.add_argument('--InputDir', type=str)
|
#Parser.add_argument('--InputDir', type=str)
|
||||||
Parser.add_argument('--Sorting', type=str)
|
Parser.add_argument('--Sorting', type=str)
|
||||||
@ -272,13 +275,14 @@ if __name__ == '__main__':
|
|||||||
Parser.add_argument('--SiteTemplate', type=str)
|
Parser.add_argument('--SiteTemplate', type=str)
|
||||||
Parser.add_argument('--SiteDomain', type=str)
|
Parser.add_argument('--SiteDomain', type=str)
|
||||||
Parser.add_argument('--Minify', type=str)
|
Parser.add_argument('--Minify', type=str)
|
||||||
|
Parser.add_argument('--MinifyKeepComments', type=str)
|
||||||
Parser.add_argument('--NoScripts', type=str)
|
Parser.add_argument('--NoScripts', type=str)
|
||||||
Parser.add_argument('--ImgAltToTitle', type=str)
|
Parser.add_argument('--ImgAltToTitle', type=str)
|
||||||
Parser.add_argument('--ImgTitleToAlt', type=str)
|
Parser.add_argument('--ImgTitleToAlt', type=str)
|
||||||
Parser.add_argument('--GemtextOut', type=str)
|
Parser.add_argument('--GemtextOutput', type=str)
|
||||||
Parser.add_argument('--GemtextHeader', type=str)
|
Parser.add_argument('--GemtextHeader', type=str)
|
||||||
Parser.add_argument('--SiteTagline', type=str)
|
Parser.add_argument('--SiteTagline', type=str)
|
||||||
Parser.add_argument('--SitemapOut', type=str)
|
Parser.add_argument('--SitemapOutput', type=str)
|
||||||
Parser.add_argument('--FeedEntries', type=str)
|
Parser.add_argument('--FeedEntries', type=str)
|
||||||
Parser.add_argument('--FolderRoots', type=str)
|
Parser.add_argument('--FolderRoots', type=str)
|
||||||
Parser.add_argument('--DynamicParts', type=str)
|
Parser.add_argument('--DynamicParts', type=str)
|
||||||
@ -288,7 +292,8 @@ if __name__ == '__main__':
|
|||||||
Parser.add_argument('--FeedCategoryFilter', type=str)
|
Parser.add_argument('--FeedCategoryFilter', type=str)
|
||||||
Parser.add_argument('--ActivityPubTypeFilter', type=str, help=argparse.SUPPRESS)
|
Parser.add_argument('--ActivityPubTypeFilter', type=str, help=argparse.SUPPRESS)
|
||||||
Parser.add_argument('--ActivityPubHoursLimit', type=int)
|
Parser.add_argument('--ActivityPubHoursLimit', type=int)
|
||||||
Parser.add_argument('--AutoCategories', type=str)
|
Parser.add_argument('--CategoriesUncategorized', type=str)
|
||||||
|
Parser.add_argument('--CategoriesAutomatic', type=str)
|
||||||
Args = Parser.parse_args()
|
Args = Parser.parse_args()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -37,8 +37,8 @@ def EvalOpt(Opt):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def OptionChoose(Default, Primary, Secondary):
|
def OptionChoose(Default, Primary, Secondary, Tertiary=None):
|
||||||
return Primary if Primary != None else Secondary if Secondary != None else Default
|
return Primary if Primary != None else Secondary if Secondary != None else Tertiary if Tertiary != None else Default
|
||||||
|
|
||||||
def StringBoolChoose(Default, Primary, Secondary):
|
def StringBoolChoose(Default, Primary, Secondary):
|
||||||
Var = Default
|
Var = Default
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import html
|
import html
|
||||||
import warnings
|
import warnings
|
||||||
|
from Libs import htmlmin
|
||||||
from Libs.bs4 import BeautifulSoup
|
from Libs.bs4 import BeautifulSoup
|
||||||
from Modules.Utils import *
|
from Modules.Utils import *
|
||||||
|
|
||||||
@ -70,3 +71,15 @@ def SquareFnrefs(HTML): # Different combinations of formatting for Soup .prettif
|
|||||||
s = t.find('a')
|
s = t.find('a')
|
||||||
s.replace_with(f'[{t}]')
|
s.replace_with(f'[{t}]')
|
||||||
return str(Soup.prettify(formatter=None))
|
return str(Soup.prettify(formatter=None))
|
||||||
|
|
||||||
|
def DoMinifyHTML(HTML, KeepComments):
|
||||||
|
return htmlmin.minify(
|
||||||
|
input=HTML,
|
||||||
|
remove_comments=not KeepComments,
|
||||||
|
remove_empty_space=True,
|
||||||
|
remove_all_empty_space=False,
|
||||||
|
reduce_empty_attributes=True,
|
||||||
|
reduce_boolean_attributes=True,
|
||||||
|
remove_optional_attribute_quotes=True,
|
||||||
|
convert_charrefs=True,
|
||||||
|
keep_pre=True)
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
| ================================= """
|
| ================================= """
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from Libs import htmlmin
|
|
||||||
from Libs.bs4 import BeautifulSoup
|
from Libs.bs4 import BeautifulSoup
|
||||||
from Modules.Config import *
|
from Modules.Config import *
|
||||||
from Modules.HTML import *
|
from Modules.HTML import *
|
||||||
@ -18,6 +17,15 @@ from Modules.Utils import *
|
|||||||
|
|
||||||
HTMLSectionTitleLine = '<h{Index} class="SectionHeading"><span class="SectionLink"><a href="#{DashTitle}"><span>»</span></a> </span><span class="SectionTitle" id="{DashTitle}">{Title}</span></h{Index}>'
|
HTMLSectionTitleLine = '<h{Index} class="SectionHeading"><span class="SectionLink"><a href="#{DashTitle}"><span>»</span></a> </span><span class="SectionTitle" id="{DashTitle}">{Title}</span></h{Index}>'
|
||||||
#PugSectionTitleLine = "{Line[:Index]}{Line[Index:Index+2]}.SectionHeading #[span.SectionLink #[a(href='#{DashTitle}') #[span »]] ]#[span#{DashTitle}.SectionTitle {Line[Index+2:]}]"
|
#PugSectionTitleLine = "{Line[:Index]}{Line[Index:Index+2]}.SectionHeading #[span.SectionLink #[a(href='#{DashTitle}') #[span »]] ]#[span#{DashTitle}.SectionTitle {Line[Index+2:]}]"
|
||||||
|
CategoryPageTemplate = """\
|
||||||
|
// Title: {Name}
|
||||||
|
// Type: Page
|
||||||
|
// Index: True
|
||||||
|
|
||||||
|
# {Name}
|
||||||
|
|
||||||
|
<div>[staticoso:Category:{Name}]</div>
|
||||||
|
"""
|
||||||
|
|
||||||
def DashifyTitle(Title, Done=[]):
|
def DashifyTitle(Title, Done=[]):
|
||||||
return UndupeStr(DashifyStr(Title.lstrip(' ').rstrip(' ')), Done, '-')
|
return UndupeStr(DashifyStr(Title.lstrip(' ').rstrip(' ')), Done, '-')
|
||||||
@ -331,54 +339,50 @@ def PatchHTML(File, HTML, StaticPartsText, DynamicParts, DynamicPartsText, HTMLP
|
|||||||
|
|
||||||
for e in StaticPartsText:
|
for e in StaticPartsText:
|
||||||
HTML = ReplWithEsc(HTML, f"[staticoso:StaticPart:{e}]", StaticPartsText[e])
|
HTML = ReplWithEsc(HTML, f"[staticoso:StaticPart:{e}]", StaticPartsText[e])
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Site:Menu]', HTMLPagesList)
|
HTML = DictReplWithEsc(
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Lang]', SiteLang)
|
HTML, {
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Chapters]', HTMLTitles)
|
'[staticoso:Site:Menu]': HTMLPagesList,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Title]', Title)
|
'[staticoso:Page:Lang]': SiteLang,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Description]', Description)
|
'[staticoso:Page:Chapters]': HTMLTitles,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Image]', Image)
|
'[staticoso:Page:Title]': Title,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Path]', PagePath)
|
'[staticoso:Page:Description]': Description,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Style]', Meta['Style'])
|
'[staticoso:Page:Image]': Image,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:Content]', Content)
|
'[staticoso:Page:Path]': PagePath,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Page:ContentInfo]', MakeContentHeader(Meta, Locale, MakeCategoryLine(File, Meta)))
|
'[staticoso:Page:Style]': Meta['Style'],
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:BuildTime]', datetime.now().strftime('%Y-%m-%d %H:%M'))
|
'[staticoso:Page:Content]': Content,
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Site:Name]', SiteName)
|
'[staticoso:Page:ContentInfo]': MakeContentHeader(Meta, Locale, MakeCategoryLine(File, Meta)),
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Site:AbsoluteRoot]', SiteRoot)
|
'[staticoso:BuildTime]': datetime.now().strftime('%Y-%m-%d %H:%M'),
|
||||||
HTML = ReplWithEsc(HTML, '[staticoso:Site:RelativeRoot]', GetPathLevels(PagePath))
|
'[staticoso:Site:Name]': SiteName,
|
||||||
|
'[staticoso:Site:AbsoluteRoot]': SiteRoot,
|
||||||
|
'[staticoso:Site:RelativeRoot]': GetPathLevels(PagePath)
|
||||||
|
})
|
||||||
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 = ReplWithEsc(HTML, f"[staticoso:Folder:{e}:AbsoluteRoot]", FolderRoots[e])
|
HTML = ReplWithEsc(HTML, f"[staticoso:Folder:{e}:AbsoluteRoot]", FolderRoots[e])
|
||||||
for e in Categories:
|
for e in Categories:
|
||||||
HTML = ReplWithEsc(HTML, f"<span>[staticoso:Category:{e}]</span>", Categories[e])
|
HTML = ReplWithEsc(HTML, f"<span>[staticoso:Category:{e}]</span>", Categories[e])
|
||||||
|
HTML = ReplWithEsc(HTML, f"[staticoso:Category:{e}]", Categories[e])
|
||||||
|
|
||||||
# TODO: Clean this doubling?
|
# TODO: Clean this doubling?
|
||||||
ContentHTML = Content
|
ContentHTML = Content
|
||||||
ContentHTML = ReplWithEsc(ContentHTML, '[staticoso:Site:AbsoluteRoot]', SiteRoot)
|
ContentHTML = DictReplWithEsc(
|
||||||
ContentHTML = ReplWithEsc(ContentHTML, '[staticoso:Site:RelativeRoot]', GetPathLevels(PagePath))
|
ContentHTML, {
|
||||||
|
'[staticoso:Site:AbsoluteRoot]': SiteRoot,
|
||||||
|
'[staticoso:Site:RelativeRoot]': GetPathLevels(PagePath)
|
||||||
|
})
|
||||||
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 = ReplWithEsc(ContentHTML, f"[staticoso:Folder:{e}:AbsoluteRoot]", FolderRoots[e])
|
ContentHTML = ReplWithEsc(ContentHTML, f"[staticoso:Folder:{e}:AbsoluteRoot]", FolderRoots[e])
|
||||||
for e in Categories:
|
for e in Categories:
|
||||||
ContentHTML = ReplWithEsc(ContentHTML, f"<span>[staticoso:Category:{e}]</span>", Categories[e])
|
ContentHTML = ReplWithEsc(ContentHTML, f"<span>[staticoso:Category:{e}]</span>", Categories[e])
|
||||||
|
ContentHTML = ReplWithEsc(ContentHTML, f"[staticoso:Category:{e}]", Categories[e])
|
||||||
SlimHTML = HTMLPagesList + ContentHTML
|
SlimHTML = HTMLPagesList + ContentHTML
|
||||||
|
|
||||||
return HTML, ContentHTML, SlimHTML, Description, Image
|
return HTML, ContentHTML, SlimHTML, Description, Image
|
||||||
|
|
||||||
def DoMinifyHTML(HTML):
|
def MakeSite(OutputDir, LimitFiles, TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, ConfMenu, GlobalMacros, SiteName, BlogName, SiteTagline, SiteTemplate, SiteDomain, SiteRoot, FolderRoots, SiteLang, Locale, Minify, MinifyKeepComments, NoScripts, ImgAltToTitle, ImgTitleToAlt, Sorting, MarkdownExts, AutoCategories):
|
||||||
return htmlmin.minify(
|
|
||||||
input=HTML,
|
|
||||||
remove_comments=True,
|
|
||||||
remove_empty_space=True,
|
|
||||||
remove_all_empty_space=False,
|
|
||||||
reduce_empty_attributes=True,
|
|
||||||
reduce_boolean_attributes=True,
|
|
||||||
remove_optional_attribute_quotes=True,
|
|
||||||
convert_charrefs=True,
|
|
||||||
keep_pre=True)
|
|
||||||
|
|
||||||
def MakeSite(OutputDir, LimitFiles, TemplatesText, StaticPartsText, DynamicParts, DynamicPartsText, ConfMenu, GlobalMacros, SiteName, BlogName, SiteTagline, SiteTemplate, SiteDomain, SiteRoot, FolderRoots, SiteLang, Locale, Minify, NoScripts, ImgAltToTitle, ImgTitleToAlt, Sorting, MarkdownExts, AutoCategories):
|
|
||||||
PagesPaths, PostsPaths, Pages, MadePages, Categories = [], [], [], [], {}
|
PagesPaths, PostsPaths, Pages, MadePages, Categories = [], [], [], [], {}
|
||||||
for Ext in FileExtensions['Pages']:
|
for Ext in FileExtensions['Pages']:
|
||||||
for File in Path('Pages').rglob(f"*.{Ext}"):
|
for File in Path('Pages').rglob(f"*.{Ext}"):
|
||||||
@ -435,15 +439,7 @@ def MakeSite(OutputDir, LimitFiles, TemplatesText, StaticPartsText, DynamicParts
|
|||||||
if not Exists:
|
if not Exists:
|
||||||
File = f"Categories/{Cat}.md"
|
File = f"Categories/{Cat}.md"
|
||||||
FilePath = f"{OutputDir}/{File}"
|
FilePath = f"{OutputDir}/{File}"
|
||||||
WriteFile(FilePath, f"""\
|
WriteFile(FilePath, CategoryPageTemplate.format(Title=Cat))
|
||||||
// Title: {Cat}
|
|
||||||
// Type: Page
|
|
||||||
// Index: True
|
|
||||||
|
|
||||||
# {Cat}
|
|
||||||
|
|
||||||
<div><span>[staticoso:Category:{Cat}]</span></div>
|
|
||||||
""")
|
|
||||||
Content, Titles, Meta = PagePreprocessor(FilePath, SiteRoot)
|
Content, Titles, Meta = PagePreprocessor(FilePath, SiteRoot)
|
||||||
Pages += [[File, Content, Titles, Meta]]
|
Pages += [[File, Content, Titles, Meta]]
|
||||||
|
|
||||||
@ -497,7 +493,7 @@ def MakeSite(OutputDir, LimitFiles, TemplatesText, StaticPartsText, DynamicParts
|
|||||||
Locale=Locale)
|
Locale=Locale)
|
||||||
|
|
||||||
if Minify:
|
if Minify:
|
||||||
HTML = DoMinifyHTML(HTML)
|
HTML = DoMinifyHTML(HTML, MinifyKeepComments)
|
||||||
if NoScripts:
|
if NoScripts:
|
||||||
HTML = StripTags(HTML, ['script'])
|
HTML = StripTags(HTML, ['script'])
|
||||||
if ImgAltToTitle or ImgTitleToAlt:
|
if ImgAltToTitle or ImgTitleToAlt:
|
||||||
|
@ -84,6 +84,7 @@ def FindAllIndex(Str, Sub):
|
|||||||
yield i
|
yield i
|
||||||
i = Str.find(Sub, i+1)
|
i = Str.find(Sub, i+1)
|
||||||
|
|
||||||
|
# Replace substrings in a string, except when an escape char is prepended
|
||||||
def ReplWithEsc(Str, Find, Repl, Esc='\\'):
|
def ReplWithEsc(Str, Find, Repl, Esc='\\'):
|
||||||
New = ''
|
New = ''
|
||||||
Sects = Str.split(Find)
|
Sects = Str.split(Find)
|
||||||
@ -101,6 +102,11 @@ def ReplWithEsc(Str, Find, Repl, Esc='\\'):
|
|||||||
New += Repl + e
|
New += Repl + e
|
||||||
return New
|
return New
|
||||||
|
|
||||||
|
def DictReplWithEsc(Str, Dict, Esc='\\'):
|
||||||
|
for Item in Dict:
|
||||||
|
Str = ReplWithEsc(Str, Item, Dict[Item], Esc='\\')
|
||||||
|
return Str
|
||||||
|
|
||||||
def NumsFromFileName(Path):
|
def NumsFromFileName(Path):
|
||||||
Name = Path.split('/')[-1]
|
Name = Path.split('/')[-1]
|
||||||
Split = len(Name)
|
Split = len(Name)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user