September 5th, 2026
First off, I apologize if this is being read from a phone. I can't find a way to make the text wrap to work, so you'll have to scroll in the code segments.
This site being entirely written in Skribilo, this means that every time I make a change anywhere I need to recompile the file I updated for the changes to be visible in the HTML. This can definitely become tedious, and hard to keep track of (if you have a lot of files with changes), real quick. This is specially true when you realize the command to compile is
skribilo --target=html <skb-file-name>.skb -o <html-file-name>.html
To solve this issue I wrote the following simple program, broken into parts:
1: import argparse, os, glob 2: from pathlib import path 3: 4: parser = argparse.ArgumentParser() 5: parser.add_argument("-path", "--filepath", help="The path to the file you wish to compile from Skribilo to HTML (without .skb)") 6: parser.add_argument("-out", "--outfile", help="Name of the HTML file (if different from the Skribilo file). Ensure same path.") 7: args = parser.parse_args()
In order to run the program, I need 2 optional arguments. Could I have done this without argparse? Yes, of course, but I wanted to add the --help flag (as if anyone else is using this), so it was needed.
I decided to give it two optional arguments:
8: if args.filepath: 9: if not os.path.exists(f"{args.filepath}.skb"): 10: print(f"File {args.filepath}.skb does not exist.") 11: exit(1) 12: if args.outfile: 13: os.system(f"skribilo --target=html {args.filepath}.skb -o {args.outfile}.html") 14: else: 15: os.system(f"skribilo --target=html {args.filepath}.skb -o {args.filepath}.html")
If the user provides the -path then we know we'll compile a specific file only.
First we need to validate that this .skb file actually exists in the specified relative path, otherwise we exit, as we don't want to compile non-existent files.
Once we validate that the file exists, then we can check whether the compiled HTML file will have the same name ( 14) as the Skribilo file or not ( 12). In either case, we need to run Skribilo's compiling command, hence the use of formatted strings, that way we can include the corresponding argument in the command.
16: else: 17: files = [f.resolve() for f in Path(".").rglob("*.skb")] 18: root = os.getcwd() 19: for file in files: 20: try: 21: os.chdir(file.parent) 22: os.system(f"skribilo --target=html {file.name} -o {file.with_suffix('.html').name}") 23: except Exception as e: 24: print(f"Error occured: {e}, in {file}") 25: finally: 26: os.chdir(root)
Now let's get into the fun part, compiling all Skribilo files at once!
For starters, we need to find all the paths to the .skb files, so that we can compile them one by one later ( 17). When we iterate, we must do two main things:
The other main thing we need to do before we iterate is saving the CWD ( 18). We will be changing directories in each iteration, so we will need to always change back to our CWD, to ensure we access the correct path for each individual file. I.e., compile a file that actually exists, and adding the compiled result to the correct place.
Now that we have the paths, and the CWD, we can begin iterating through each .skb file that exists. In making this program, I realized Skribilo has strange behavior with files that contain images (or rather, files that are referenced from a different directory). Let me explain, some of my posts have images in them, giving me a file structure like this:
It seems like if I have such cases, in which I need to reference a file in a different directory, I must run the Skribilo compiling command from where the main file is (that is, posts/). If I try to run it, it will throw an error once it attempts to link the image, indicating that it can't find it, despite being correctly linked with its relative path (i.e. "../ref-img.png").
Due to this quirk, I had to find a way around it, which is where os.chdir ( 21) comes into play. Every time we encounter a file, we will update our CWD to the .skb file's parent directory (i.e. posts/). That way, the posts that may contain images always are compiled and rendered correctly. ( 22).
Once the current iteration is done, we must reset CWD to our original one, which we saved previously. This will allow us to begin the next iteration from where the script is, ( 26), ensuring every file is accessed from the same relative starting point.