useful-scripts/syncBlog.sh
2024-09-13 11:32:41 +01:00

204 lines
5.7 KiB
Bash
Executable file

#!/bin/bash
set -Eeuo pipefail
### USAGE ###
#./syncBlog.sh --obsidian-dir "/path/to/obsidian" --blog-dir "/path/to/blog"
###
# Get the directory of the script
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Default values
DEFAULT_OBSIDIAN_DIR="/Users/alex/Notes"
DEFAULT_BLOG_DIR="/Users/alex/Projects/alexhyett-blog"
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--obsidian-dir)
OBSIDIAN_DIR="$2"
shift 2
;;
--blog-dir)
BLOG_DIR="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# Set directory paths, using defaults if not provided
OBSIDIAN_DIR="${OBSIDIAN_DIR:-$DEFAULT_OBSIDIAN_DIR}"
BLOG_DIR="${BLOG_DIR:-$DEFAULT_BLOG_DIR}"
WEBSITE_DIR="$OBSIDIAN_DIR/6. WEBSITE/"
NOTES_DIR="$OBSIDIAN_DIR/5. GARDEN/"
LAST_RUN_FILE="$SCRIPT_DIR/.last_run"
# Print the directories being used
echo "Using Obsidian directory: $OBSIDIAN_DIR"
echo "Using Blog directory: $BLOG_DIR"
# Function to log messages with timestamps
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1"
}
# Function to get the last run date
get_last_run_date() {
if [[ -f "$LAST_RUN_FILE" ]]; then
cat "$LAST_RUN_FILE"
else
echo "1970-01-01T00:00:00"
fi
}
# Function to update the last run date
update_last_run_date() {
date +"%Y-%m-%dT%H:%M:%S" > "$LAST_RUN_FILE"
}
# Function to check if a file has been updated since last run
is_file_updated() {
local file=$1
local last_run=$(get_last_run_date)
local updated=$(sed -n 's/^updated: //p' "$file")
if [[ -z "$updated" ]]; then
return 0 # If no updated date, assume it needs processing
fi
if [[ "$updated" > "$last_run" ]]; then
return 0 # File is newer
else
return 1 # File is older
fi
}
# Function to copy updated files
copy_updated_files() {
local source_dir=$1
local dest_dir=$2
local file_count=0
while IFS= read -r -d '' file; do
if is_file_updated "$file"; then
mkdir -p "$(dirname "$dest_dir/${file#$source_dir}")"
cp "$file" "$dest_dir/${file#$source_dir}"
((file_count++))
fi
done < <(find "$source_dir" -type f -name "*.md" -print0)
echo "$file_count"
}
##### SCRIPT START #####
mkdir -p $BLOG_DIR/_staging
# Copy updated website files to staging
files=$(copy_updated_files "$WEBSITE_DIR" "$BLOG_DIR/_staging")
if [[ "$files" != "0" ]]; then
log "Transferred $files updated website files to staging"
fi
# Copy updated notes files to staging
files=$(copy_updated_files "$NOTES_DIR" "$BLOG_DIR/_staging/notes")
if [[ "$files" != "0" ]]; then
log "Transferred $files updated notes files to staging"
fi
# Function to extract the permalink from YAML frontmatter
extract_permalink() {
local note_file=$1
grep "^permalink:" "$note_file" | sed 's/^permalink: //'
}
# Function to process each note file
process_notes() {
local note_file=$1
local debug_file=${note_file/$BLOG_DIR\/_staging/""}
local reference_notes_dir=$2
local temp_file=$(mktemp)
local modified=false
# Read through each line in the note file
while IFS= read -r line || [[ -n "$line" ]]; do
# Use a simpler regex pattern to find wiki links in the line
link_regex='\[\[([^|[]+)(\|([^[]+))?\]\]'
# Replace links in the line
new_line=""
rest_of_line="$line"
while [[ $rest_of_line =~ $link_regex ]]; do
full_match="${BASH_REMATCH[0]}"
file_name="${BASH_REMATCH[1]}"
display_name="${BASH_REMATCH[3]:-$file_name}"
before="${rest_of_line%%"$full_match"*}"
after="${rest_of_line#*"$full_match"}"
# Find the reference note file
note_full_path=$(find "$reference_notes_dir" -type f -iname "$file_name.md" | head -n 1)
echo $note_full_path
replacement="$full_match" # Default replacement is the original link
# Extract the permalink if the reference note file exists
if [[ -n $note_full_path ]]; then
permalink=$(extract_permalink "$note_full_path")
if [[ -n $permalink ]]; then
log "$debug_file: Found permalink: $permalink"
replacement="[$display_name]($permalink)"
modified=true
else
log "$debug_file: No permalink found for: $note_full_path"
fi
else
log "$debug_file: No matching file found for: $file_name"
fi
new_line+="$before$replacement"
rest_of_line="$after"
done
new_line+="$rest_of_line"
# Write the processed line to the temp_file
echo "$new_line" >> "$temp_file"
done < "$note_file"
# If modifications were made, overwrite the original file; otherwise, delete the temp_file
if $modified; then
mv "$temp_file" "$note_file"
else
rm "$temp_file"
fi
}
log "Starting note processing"
# Recursively find and process each Markdown note in the directory
find "$BLOG_DIR/_staging" -type f -name "*.md" | while IFS= read -r note_file; do
process_notes "$note_file" "$BLOG_DIR/content"
done
log "Finished note processing"
# Sync converted files to the blog directory
output=$(rsync -zarvh --stats "$BLOG_DIR/_staging/" "$BLOG_DIR/content/" | grep -A 1 'files transferred')
files=$(echo "$output" | awk '/files transferred/{print $NF}')
if [[ "$files" != "0" ]]; then
log "Transferred $files files to blog"
fi
# Delete _staging dir
rm -rf $BLOG_DIR/_staging
# Update the last run date
update_last_run_date
log "Script completed successfully"