πŸ‘΄ jdcard

A Blog For Spartan

Spartan is much simpler than markdown so it doesn't make sense to edit posts in markdown and then convert them to gemtext (like bashblog does to create HTML). We'll just write blog posts directly as new gemtext files in ~/public_spartan/blog/ and create a cgi executable called sblog in ~/public_spartan to build an index page for the blog on the fly.

Requirements

Here's what it might look like:

-------------------------------------------------------------------------------

# Blog Title

## This Is My New Post

I'm thrilled to have a new, simpler way to produce a blog.

tags: #new #blog #simple-is-better

## All posts:

=> are-we-done-yet.gmi 2022-07-10 17:04 - Are We Done Yet?
> tags: #older #blog #simple-is-better

=> have-you-seen-this-before.gmi 2022-07-11 11:04 - Have you seen this before?
> tags: #improved #blog #simple-is-better

=> this-is-my-new-post.gmi 2022-07-12 17:04 - This Is My New Post
> tags: #older #blog #simple-is-better

=> youll-never-guess.gmi 2022-07-13 11:01 - You'll Never Guess!
> tags: #old #blog #simple-is-better
    

-------------------------------------------------------------------------------

Implementation limitations

Now that I have some working code I realize that some of the "requirements" above may be unrealistic.

The date processing doesn't work as I hoped it would. It can only read the mtime from the files, rather than the crtime, so we can only show the time the post was last modified, rather than when it was created. In most cases there will be little or no difference between the two timestamps.

A more significant issue is that the server reports the time using UTC rather than the local time zone specified in the user's LOCALE. It becomes obvious when running the script from the command line and comparing the timestamps to what the server sends back to a remote client. This issue may become annoying enough for me to figure out how to fix it.

I'm using the same code (with the appropriate one-line modification to the protocol-specific header) for both the Spartan server and the Gemini server.

My Spartan blog The Gemini mirror of the blog (last update 2022-07-20)

I've decided that, at least for my blog, I want to include a date line that specifies when the post was created and when it was last edited. The creation date is easy because the helper script inserts it automatically. However, I don't know how to automatically insert a datesamp using my usual editing tools, so it remains to be seen how effective the last-edit field will be as I actually use the blog. I still consider the date-line an optional feature. I tried placing it just under the title line, but decided that I like it better just above the tags line at the bottom.

Sample code

Here's the initial blog index script:

#!/usr/bin/env sh

# sblog - display the most recent blog post plus links to all older ones
# Each post will have its title   as the first line in the file: # This Is My New Post
# Each post will have a tags line as the final line of the file: tags: #this-is-a-tag, #anotherTag
# All blog posts are in a single (sub)directory and are the only .gmi files in that directory

###############################################################################
##                          W A R N I N G !                                  ##
## The method used to sort and list the blog posts will only work reliably   ##
## if their file names DO NOT include spaces or punctuation (except "-"      ##
## or "."). Letters and numbers are OK. Do not use this script in cases      ##
## where users are permitted to create non-conforming file names.            ##
###############################################################################

# where are the blog files (absolute path, from root)
fpath="/home/_USER_/public_spartan/blog"

# send the Spartan header
printf "2 text/gemini\r\n"

# Transmit the blog's title.
printf "# This Blog Needs A Title\n\n"

# find the newest file in the blog directory (mtime)
newpost="$(find $fpath -type f -name "*.gmi" -print0 | xargs -r -0 ls -1 -t | head -1)"

# display the newest post
cat "$newpost" # ToDo: test if variable is set and if file exists
printf "\n========================================\n"
printf "=> blog/%s Direct link to this post\n" "${newpost##*/}" # print permalink line; strip off the path, leaving just the file name
printf "========================================\n" 
printf "\n## All posts:\n\n"

# build links to all the posts
for fname in $(ls -t $fpath/*.gmi); do  # using ls here is suboptimal, but we're controlling the file names via the "bp" helper script
  fdate="$(stat -c '%x' "$fname")"   # %x is modified-date; %w is creation date, but that does not work on the tilde.team server.
  fdate="${fdate%:*}"                # truncate everything following the final ":" to trim the seconds off the end of the string
  title="$(head -n 1 "$fname")"      # grab the title line at the top of the file
  title="${title##*#}"               # trim the leading "#" character(s) from the line
  tags="$(tail -n 1 "$fname")"       # get the tags list from the bottom of the file
  printf "=> blog/%s %s - %s\n" "${fname##*/}" "$fdate" "$title"   # print the link line; strip off the path, leaving just the file name
  printf "> %s\n\n" "$tags"          # print the tags line and add an extra newline to separate each record
done
    

I've also written a helper script that creates a new file in the ~/public_spartan/blog directory and populates it with a template for a new post, then it opens the file using $EDITOR for editing. Once the editor is closed, the script displays the content of the post for a final review. Here is what it currently looks like:

#!/usr/bin/bash
# bp - a Spartan blog helper to create a new blog post

# CONFIGURATION
# Where is the blog directory?
blogdir="$HOME/public_spartan/blog"
# What e-mail address should blog comments go to?
email="james@jdcard.com"

fname=$(date -Iminutes)  # get current date and time
cdate="${fname/T/ }"     # capture file creation date for use in the post text
mail="mailto:$email?subject=Your%20Blog%20Post%20-%20${fname/:/-}"  # Remove ":" character from URL
fname="${fname%-*}.gmi"  # create a name for the file; 

# Create the new file.
printf "## .\n\n.\n\n=> %s  πŸ“§Comment on this post (via e-mail)\nπŸ“… c: %s  ✏️ e: \ntags: #new\n" "${mail%-*}" "${cdate%-*}" >> "$blogdir/$fname"
# Verify that the file was created? No, if the editor opens an empty file it will be obvious something is wrong.

echo "New post is at: $blogdir/$fname"  # This makes it easy to re-edit the file if you need to.

# Edit the new post
"$EDITOR" "$blogdir/$fname" # ToDo: check whether $EDITOR is set?

# Display the result so you can review it for errors.
cat "$blogdir/$fname"
    

Finally, a blog post edit script that helps record the time the file was edited, and very importantly, adjusts file's mtime datestamp in the filesystem so that our blog indexer keeps things sorted by creation date.

#!/usr/bin/bash
# be - a Spartan blog helper to edit an existing blog post

# EXPECTS these command arguments
#   fname - filename of the post to be edited

fname="$1"

edtime=$(date -Iminutes)  # get current date and time
edtime="${edtime%-*}"     # trim off the timezone offset
edtime="${edtime/T/ }"    # remove the "T" field separator

if [ -e "$fname" ]; then
  echo "Editing $fname at $edtime"
else
  echo "Error: file \"$1\" does not exist. Check the path and filename."
  exit
fi

# Find the file creation date recorded in the file itself (this will break easily if the date line has been edited improperly)
fdate="$(grep "πŸ“… c: " "$fname")"  # retrieve the date line from the post
fdate="${fdate:5:16}"              # slice out the file creation date

# Append the current edit time to the end of the file. Make it ugly and obvious to make sure it gets incorporated during the editing process..
printf "\n## TIME LASTED EDITED: %s MOVE THIS VALUE TO THE DATE LINE ABOVE\n" "$edtime" >> "$fname"

# Edit the post
"$EDITOR" "$fname" # ToDo: check whether $EDITOR is set?

# Display the result so you can review it for errors.
cat "$fname"

# Restore the file date so that our date indexing (in sblog/gblog) will still work.
printf "===================\nFixing file date...\n===================\n"
touch -d "$fdate" "$fname"
echo "Verify that the file date shown below matches \"$fdate\"."
ls -l "$fname"
    

The scripts need a bunch of error-proofing, but they are functional at this stage.

⁂

Β©2022 πŸ…­πŸ…―πŸ„πŸ„Ž Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)

β‹―

πŸ—‘οΈ spartan://jdcard.com:3300/ πŸ›°οΈ gemini://jdcard.com/ 🌐 http://jdcard.com/