From 90058697439ee3f048f0f42b61ca5ea677e9b5cc Mon Sep 17 00:00:00 2001 From: Starfall Date: Tue, 5 Dec 2023 09:59:19 -0600 Subject: strike: merge as subdir --- CONTRIBUTING | 10 ----- README | 56 ------------------------- README.md | 9 ++-- sample/blog/also-exclude.html | 1 - sample/blog/empty.html | 0 sample/blog/exclude.html | 1 - sample/blog/happy.html | 1 - sample/blog/subdir/index.html | 1 - sample/blog/with-frontmatter.html | 6 --- sample/html/empty.html | 14 ------- sample/html/happy.html | 15 ------- sample/html/subdir/index.html | 15 ------- sample/html/with-frontmatter.html | 17 -------- sample/strike.ini | 19 --------- sample/template.html | 14 ------- strike.py | 70 -------------------------------- strike/CONTRIBUTING | 10 +++++ strike/README | 56 +++++++++++++++++++++++++ strike/sample/blog/also-exclude.html | 1 + strike/sample/blog/empty.html | 0 strike/sample/blog/exclude.html | 1 + strike/sample/blog/happy.html | 1 + strike/sample/blog/subdir/index.html | 1 + strike/sample/blog/with-frontmatter.html | 6 +++ strike/sample/html/empty.html | 14 +++++++ strike/sample/html/happy.html | 15 +++++++ strike/sample/html/subdir/index.html | 15 +++++++ strike/sample/html/with-frontmatter.html | 17 ++++++++ strike/sample/strike.ini | 19 +++++++++ strike/sample/template.html | 14 +++++++ strike/strike.py | 70 ++++++++++++++++++++++++++++++++ 31 files changed, 245 insertions(+), 244 deletions(-) delete mode 100644 CONTRIBUTING delete mode 100644 README delete mode 100644 sample/blog/also-exclude.html delete mode 100644 sample/blog/empty.html delete mode 100644 sample/blog/exclude.html delete mode 100644 sample/blog/happy.html delete mode 100644 sample/blog/subdir/index.html delete mode 100644 sample/blog/with-frontmatter.html delete mode 100644 sample/html/empty.html delete mode 100644 sample/html/happy.html delete mode 100644 sample/html/subdir/index.html delete mode 100644 sample/html/with-frontmatter.html delete mode 100644 sample/strike.ini delete mode 100644 sample/template.html delete mode 100644 strike.py create mode 100644 strike/CONTRIBUTING create mode 100644 strike/README create mode 100644 strike/sample/blog/also-exclude.html create mode 100644 strike/sample/blog/empty.html create mode 100644 strike/sample/blog/exclude.html create mode 100644 strike/sample/blog/happy.html create mode 100644 strike/sample/blog/subdir/index.html create mode 100644 strike/sample/blog/with-frontmatter.html create mode 100644 strike/sample/html/empty.html create mode 100644 strike/sample/html/happy.html create mode 100644 strike/sample/html/subdir/index.html create mode 100644 strike/sample/html/with-frontmatter.html create mode 100644 strike/sample/strike.ini create mode 100644 strike/sample/template.html create mode 100644 strike/strike.py diff --git a/CONTRIBUTING b/CONTRIBUTING deleted file mode 100644 index 2f2508f..0000000 --- a/CONTRIBUTING +++ /dev/null @@ -1,10 +0,0 @@ -Patches are accepted via email or Matrix DM (check https://starfall.systems/contact for the latest information). - -If anyone actually contributes, feel free to suggest a license change with the first patch. Check https://git.starfall.systems/www-starfall-systems/tree/COPYING.md for our thoughts - AGPL or MPL is probably fine. - -PATCH CHECKLIST ---------------- -* Code style matches everything else (PEP8 compliance is suggested but not required as I've already decided to indent with tabs, feel free to go to 90-110 character lines as appropriate) -* Documentation updated to describe new behavior -* Example case(s) written in sample/blog -* `./strike.py sample` run and output in sample/html looks as expected (you can use `git diff` to verify nothing except last-modified lines are changed) diff --git a/README b/README deleted file mode 100644 index dd6448e..0000000 --- a/README +++ /dev/null @@ -1,56 +0,0 @@ - _____ __ _ __ - / ___// /______(_) /_____ - \__ \/ __/ ___/ / //_/ _ \ - ___/ / /_/ / / / ,< / __/ -/____/\__/_/ /_/_/|_|\___/ -============================ - -A static site generator that does exactly what we need it to and no more. - -(c) 2021 Starfall , all rights reserved until I decide it's in a good enough state for others to use. - -Strike has simple goals: -1. Read HTML page contents from files in the source folder -2. Add boilerplate (head, header, footer, etc) -3. Save to output folder - -And some stretch goals: - * Create an extra page listing all generated pages in order of creation date (newest first) - * As above, but as an RSS feed - * Add links to next & previous generated pages - * Turn the extra page into a flexible component that can be added into any other page - * Use different templates on different files - * Markup parsing (see below) - * More robust created/modified date handling - needs more specification (markup changes vs. template changes, caching original creation date because posix systems don't actually provide that, etc.) - -strike.ini file ---------------- - -Strike should be passed the location of a .ini file or a directory containing a file named strike.ini. This is a text file in Python's configparser format (for now). You can see an example config file with all supported options at sample/strike.ini. - -Markup ------- - -TBD. No markup is used at the moment. - -reStructuredText fulfills most of our desires: https://docutils.sourceforge.io/rst.html -It generates
s and has specific markup for page titles. - -Templating ----------- - -TBD. - -Right now, templates are just passed to Python's str.format(). You can use these variables by default: - -{content} : Complete file contents. -{meta[title]} : Filename, with extension dropped. -{meta[date]} : File modification date, in HTTP header format (e.g. "Sat, 23 Oct 2021 18:28:37 GMT") - -Front matter ------------- - -* Front matter is indicated by starting a file with a line that contains exactly three dashes and nothing else ("---\n"). -* Front matter is closed by another line that containts exactly three dashes and nothing else. -* Every line between the opening and closing line should be key=value pairs. -* Front matter is stored into the 'meta' dict, so you can overwrite meta[title] or meta[date] if you want to. diff --git a/README.md b/README.md index af3bb78..7025dd8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ -Starfall's Old Projects -======================= +Starfall's Trinkets +=================== -Old and abandoned projects that no longer justify being their own repository, but might be worth -coming back to some day so are archived here. Each branch is its own former repo: +Abandoned projects that no longer justify being their own repository, but might be worth +coming back to some day so are archived here. - ev-nova: Archive of two of the plugins we wrote for Escape Velocity: Nova. - ophiculus: Half-started and definitely untested Gemini client. +- strike: Basic static site generator using key=value frontmatter and Python fstrings for formatting. diff --git a/sample/blog/also-exclude.html b/sample/blog/also-exclude.html deleted file mode 100644 index 6ce0fb1..0000000 --- a/sample/blog/also-exclude.html +++ /dev/null @@ -1 +0,0 @@ -This file shouldn't be processed by Strike either. diff --git a/sample/blog/empty.html b/sample/blog/empty.html deleted file mode 100644 index e69de29..0000000 diff --git a/sample/blog/exclude.html b/sample/blog/exclude.html deleted file mode 100644 index d881dce..0000000 --- a/sample/blog/exclude.html +++ /dev/null @@ -1 +0,0 @@ -This file should be excluded from processing when Strike is processed using strike.ini diff --git a/sample/blog/happy.html b/sample/blog/happy.html deleted file mode 100644 index af5626b..0000000 --- a/sample/blog/happy.html +++ /dev/null @@ -1 +0,0 @@ -Hello, world! diff --git a/sample/blog/subdir/index.html b/sample/blog/subdir/index.html deleted file mode 100644 index b66efd5..0000000 --- a/sample/blog/subdir/index.html +++ /dev/null @@ -1 +0,0 @@ -This file in a subdirectory of the input directory should also be processed. diff --git a/sample/blog/with-frontmatter.html b/sample/blog/with-frontmatter.html deleted file mode 100644 index 5195292..0000000 --- a/sample/blog/with-frontmatter.html +++ /dev/null @@ -1,6 +0,0 @@ ---- -title=Custom Title ---- -Things before this line should not appear in the output. ---- -Including the delimiter in body content shouldn't be an issue. diff --git a/sample/html/empty.html b/sample/html/empty.html deleted file mode 100644 index b1a01ea..0000000 --- a/sample/html/empty.html +++ /dev/null @@ -1,14 +0,0 @@ - - -empty - - - - - -
- -
-
-

This page was generated by Strike. -

diff --git a/sample/html/happy.html b/sample/html/happy.html deleted file mode 100644 index 9f4b32f..0000000 --- a/sample/html/happy.html +++ /dev/null @@ -1,15 +0,0 @@ - - -happy - - - - - -
- Hello, world! - -
-
-

This page was generated by Strike. -

diff --git a/sample/html/subdir/index.html b/sample/html/subdir/index.html deleted file mode 100644 index bdeaad0..0000000 --- a/sample/html/subdir/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - -index - - - - - -
- This file in a subdirectory of the input directory should also be processed. - -
-
-

This page was generated by Strike. -

diff --git a/sample/html/with-frontmatter.html b/sample/html/with-frontmatter.html deleted file mode 100644 index 99627a1..0000000 --- a/sample/html/with-frontmatter.html +++ /dev/null @@ -1,17 +0,0 @@ - - -Custom Title - - - - - -
- Things before this line should not appear in the output. ---- -Including the delimiter in body content shouldn't be an issue. - -
-
-

This page was generated by Strike. -

diff --git a/sample/strike.ini b/sample/strike.ini deleted file mode 100644 index 86bc8c3..0000000 --- a/sample/strike.ini +++ /dev/null @@ -1,19 +0,0 @@ -[Input] -# Directory with all of the markup files that you want Strike to process. -# Location should be relative to this config file. -directory = blog -# Files in the input directory to exclude. -# Location should be relative to the default input directory. -excludes = exclude.html - also-exclude.html - -[Templates] -# For now, Strike only supports using a single template, named default. -default = template.html - -[Output] -# Directory to put the output into. -directory = html - -# That's all for now. In the future, we hope to allow the use of multiple templates, -# letting you choose individual directories and files for each template. diff --git a/sample/template.html b/sample/template.html deleted file mode 100644 index 2552906..0000000 --- a/sample/template.html +++ /dev/null @@ -1,14 +0,0 @@ - - -{meta[title]} - - - - - -
- {content} -
-
-

This page was generated by Strike. -

diff --git a/strike.py b/strike.py deleted file mode 100644 index 03d991e..0000000 --- a/strike.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 -import os -from time import gmtime, strftime -from argparse import ArgumentParser -from configparser import ConfigParser -from pathlib import Path - -def handle_args(): - parser = ArgumentParser() - parser.add_argument('config', help='location of strike.ini file (or a directory containing it)') - return parser.parse_args() - -def read_config(location): - location = Path(location) - config = ConfigParser() - if location.is_dir(): - location = location/'strike.ini' - if not location.exists(): - raise FileNotFoundError(f'Config file not found at {location}.') - config.read(location) - return location.resolve().parent, config - -def handle_file(file): - meta = dict( - title = file.stem, - date = strftime('%a, %d %b %Y %H:%M:%S GMT', gmtime(file.stat().st_mtime)) - ) - contents = file.read_text() - delim = '---\n' - if contents.startswith(delim): - parts = contents.split(delim, maxsplit=2) - meta.update(dict((key.strip(), value.strip()) - for key, value in (line.split('=') for line in parts[1].splitlines()) - )) - contents = parts[2] - return contents, meta - -def apply_template(content, meta, template="{content}"): - return template.format( - content = content, - meta = meta - ) - -def main(): - args = handle_args() - basedir, config = read_config(args.config) - - input_dir = basedir/config['Input']['directory'] - - try: exclusions = config['Input']['excludes'].splitlines() - except KeyError: exclusions = {} - - default_template = basedir/config['Templates']['default'] - template = default_template.read_text() - - output_dir = basedir/config['Output']['directory'] - - for path, _, files in os.walk(input_dir): - loc = os.path.relpath(path, input_dir) - (output_dir/loc).mkdir(parents=True, exist_ok=True) - for file in files: - if file in exclusions: - continue - contents, meta = handle_file(input_dir/loc/file) - output = apply_template(contents, meta, template) - (output_dir/loc/file).write_text(output) - -if __name__ == '__main__': - import sys - sys.exit(main()) diff --git a/strike/CONTRIBUTING b/strike/CONTRIBUTING new file mode 100644 index 0000000..2f2508f --- /dev/null +++ b/strike/CONTRIBUTING @@ -0,0 +1,10 @@ +Patches are accepted via email or Matrix DM (check https://starfall.systems/contact for the latest information). + +If anyone actually contributes, feel free to suggest a license change with the first patch. Check https://git.starfall.systems/www-starfall-systems/tree/COPYING.md for our thoughts - AGPL or MPL is probably fine. + +PATCH CHECKLIST +--------------- +* Code style matches everything else (PEP8 compliance is suggested but not required as I've already decided to indent with tabs, feel free to go to 90-110 character lines as appropriate) +* Documentation updated to describe new behavior +* Example case(s) written in sample/blog +* `./strike.py sample` run and output in sample/html looks as expected (you can use `git diff` to verify nothing except last-modified lines are changed) diff --git a/strike/README b/strike/README new file mode 100644 index 0000000..dd6448e --- /dev/null +++ b/strike/README @@ -0,0 +1,56 @@ + _____ __ _ __ + / ___// /______(_) /_____ + \__ \/ __/ ___/ / //_/ _ \ + ___/ / /_/ / / / ,< / __/ +/____/\__/_/ /_/_/|_|\___/ +============================ + +A static site generator that does exactly what we need it to and no more. + +(c) 2021 Starfall , all rights reserved until I decide it's in a good enough state for others to use. + +Strike has simple goals: +1. Read HTML page contents from files in the source folder +2. Add boilerplate (head, header, footer, etc) +3. Save to output folder + +And some stretch goals: + * Create an extra page listing all generated pages in order of creation date (newest first) + * As above, but as an RSS feed + * Add links to next & previous generated pages + * Turn the extra page into a flexible component that can be added into any other page + * Use different templates on different files + * Markup parsing (see below) + * More robust created/modified date handling - needs more specification (markup changes vs. template changes, caching original creation date because posix systems don't actually provide that, etc.) + +strike.ini file +--------------- + +Strike should be passed the location of a .ini file or a directory containing a file named strike.ini. This is a text file in Python's configparser format (for now). You can see an example config file with all supported options at sample/strike.ini. + +Markup +------ + +TBD. No markup is used at the moment. + +reStructuredText fulfills most of our desires: https://docutils.sourceforge.io/rst.html +It generates
s and has specific markup for page titles. + +Templating +---------- + +TBD. + +Right now, templates are just passed to Python's str.format(). You can use these variables by default: + +{content} : Complete file contents. +{meta[title]} : Filename, with extension dropped. +{meta[date]} : File modification date, in HTTP header format (e.g. "Sat, 23 Oct 2021 18:28:37 GMT") + +Front matter +------------ + +* Front matter is indicated by starting a file with a line that contains exactly three dashes and nothing else ("---\n"). +* Front matter is closed by another line that containts exactly three dashes and nothing else. +* Every line between the opening and closing line should be key=value pairs. +* Front matter is stored into the 'meta' dict, so you can overwrite meta[title] or meta[date] if you want to. diff --git a/strike/sample/blog/also-exclude.html b/strike/sample/blog/also-exclude.html new file mode 100644 index 0000000..6ce0fb1 --- /dev/null +++ b/strike/sample/blog/also-exclude.html @@ -0,0 +1 @@ +This file shouldn't be processed by Strike either. diff --git a/strike/sample/blog/empty.html b/strike/sample/blog/empty.html new file mode 100644 index 0000000..e69de29 diff --git a/strike/sample/blog/exclude.html b/strike/sample/blog/exclude.html new file mode 100644 index 0000000..d881dce --- /dev/null +++ b/strike/sample/blog/exclude.html @@ -0,0 +1 @@ +This file should be excluded from processing when Strike is processed using strike.ini diff --git a/strike/sample/blog/happy.html b/strike/sample/blog/happy.html new file mode 100644 index 0000000..af5626b --- /dev/null +++ b/strike/sample/blog/happy.html @@ -0,0 +1 @@ +Hello, world! diff --git a/strike/sample/blog/subdir/index.html b/strike/sample/blog/subdir/index.html new file mode 100644 index 0000000..b66efd5 --- /dev/null +++ b/strike/sample/blog/subdir/index.html @@ -0,0 +1 @@ +This file in a subdirectory of the input directory should also be processed. diff --git a/strike/sample/blog/with-frontmatter.html b/strike/sample/blog/with-frontmatter.html new file mode 100644 index 0000000..5195292 --- /dev/null +++ b/strike/sample/blog/with-frontmatter.html @@ -0,0 +1,6 @@ +--- +title=Custom Title +--- +Things before this line should not appear in the output. +--- +Including the delimiter in body content shouldn't be an issue. diff --git a/strike/sample/html/empty.html b/strike/sample/html/empty.html new file mode 100644 index 0000000..b1a01ea --- /dev/null +++ b/strike/sample/html/empty.html @@ -0,0 +1,14 @@ + + +empty + + + + + +
+ +
+
+

This page was generated by Strike. +

diff --git a/strike/sample/html/happy.html b/strike/sample/html/happy.html new file mode 100644 index 0000000..9f4b32f --- /dev/null +++ b/strike/sample/html/happy.html @@ -0,0 +1,15 @@ + + +happy + + + + + +
+ Hello, world! + +
+
+

This page was generated by Strike. +

diff --git a/strike/sample/html/subdir/index.html b/strike/sample/html/subdir/index.html new file mode 100644 index 0000000..bdeaad0 --- /dev/null +++ b/strike/sample/html/subdir/index.html @@ -0,0 +1,15 @@ + + +index + + + + + +
+ This file in a subdirectory of the input directory should also be processed. + +
+
+

This page was generated by Strike. +

diff --git a/strike/sample/html/with-frontmatter.html b/strike/sample/html/with-frontmatter.html new file mode 100644 index 0000000..99627a1 --- /dev/null +++ b/strike/sample/html/with-frontmatter.html @@ -0,0 +1,17 @@ + + +Custom Title + + + + + +
+ Things before this line should not appear in the output. +--- +Including the delimiter in body content shouldn't be an issue. + +
+
+

This page was generated by Strike. +

diff --git a/strike/sample/strike.ini b/strike/sample/strike.ini new file mode 100644 index 0000000..86bc8c3 --- /dev/null +++ b/strike/sample/strike.ini @@ -0,0 +1,19 @@ +[Input] +# Directory with all of the markup files that you want Strike to process. +# Location should be relative to this config file. +directory = blog +# Files in the input directory to exclude. +# Location should be relative to the default input directory. +excludes = exclude.html + also-exclude.html + +[Templates] +# For now, Strike only supports using a single template, named default. +default = template.html + +[Output] +# Directory to put the output into. +directory = html + +# That's all for now. In the future, we hope to allow the use of multiple templates, +# letting you choose individual directories and files for each template. diff --git a/strike/sample/template.html b/strike/sample/template.html new file mode 100644 index 0000000..2552906 --- /dev/null +++ b/strike/sample/template.html @@ -0,0 +1,14 @@ + + +{meta[title]} + + + + + +
+ {content} +
+ diff --git a/strike/strike.py b/strike/strike.py new file mode 100644 index 0000000..03d991e --- /dev/null +++ b/strike/strike.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +import os +from time import gmtime, strftime +from argparse import ArgumentParser +from configparser import ConfigParser +from pathlib import Path + +def handle_args(): + parser = ArgumentParser() + parser.add_argument('config', help='location of strike.ini file (or a directory containing it)') + return parser.parse_args() + +def read_config(location): + location = Path(location) + config = ConfigParser() + if location.is_dir(): + location = location/'strike.ini' + if not location.exists(): + raise FileNotFoundError(f'Config file not found at {location}.') + config.read(location) + return location.resolve().parent, config + +def handle_file(file): + meta = dict( + title = file.stem, + date = strftime('%a, %d %b %Y %H:%M:%S GMT', gmtime(file.stat().st_mtime)) + ) + contents = file.read_text() + delim = '---\n' + if contents.startswith(delim): + parts = contents.split(delim, maxsplit=2) + meta.update(dict((key.strip(), value.strip()) + for key, value in (line.split('=') for line in parts[1].splitlines()) + )) + contents = parts[2] + return contents, meta + +def apply_template(content, meta, template="{content}"): + return template.format( + content = content, + meta = meta + ) + +def main(): + args = handle_args() + basedir, config = read_config(args.config) + + input_dir = basedir/config['Input']['directory'] + + try: exclusions = config['Input']['excludes'].splitlines() + except KeyError: exclusions = {} + + default_template = basedir/config['Templates']['default'] + template = default_template.read_text() + + output_dir = basedir/config['Output']['directory'] + + for path, _, files in os.walk(input_dir): + loc = os.path.relpath(path, input_dir) + (output_dir/loc).mkdir(parents=True, exist_ok=True) + for file in files: + if file in exclusions: + continue + contents, meta = handle_file(input_dir/loc/file) + output = apply_template(contents, meta, template) + (output_dir/loc/file).write_text(output) + +if __name__ == '__main__': + import sys + sys.exit(main()) -- cgit