579 lines
14 KiB
Bash
Executable file
579 lines
14 KiB
Bash
Executable file
#!/bin/bash
|
||
|
||
# Content generation script for localized blog and recipe content
|
||
# Generates new content files from templates with proper localization
|
||
|
||
set -e
|
||
|
||
# Configuration
|
||
CONTENT_DIR="content"
|
||
TEMPLATES_DIR="scripts/content/templates"
|
||
SUPPORTED_LANGUAGES=("en" "es")
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Helper functions
|
||
log_error() {
|
||
echo -e "${RED}❌ ERROR: $1${NC}"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}⚠️ WARNING: $1${NC}"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
log_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
log_step() {
|
||
echo -e "${CYAN}🔧 $1${NC}"
|
||
}
|
||
|
||
# Display usage information
|
||
show_usage() {
|
||
echo -e "${BLUE}📝 Content Generation Tool${NC}"
|
||
echo "================================"
|
||
echo ""
|
||
echo "Usage: $0 [COMMAND] [OPTIONS]"
|
||
echo ""
|
||
echo "Commands:"
|
||
echo " blog-post Generate a new blog post"
|
||
echo " recipe Generate a new recipe"
|
||
echo " templates Initialize template files"
|
||
echo " index Update content indices"
|
||
echo " help Show this help message"
|
||
echo ""
|
||
echo "Blog Post Options:"
|
||
echo " --title Post title (required)"
|
||
echo " --author Author name (default: 'Jesús Pérez')"
|
||
echo " --category Post category"
|
||
echo " --tags Comma-separated tags"
|
||
echo " --featured Mark as featured (true/false)"
|
||
echo " --language Target language (en/es/all)"
|
||
echo ""
|
||
echo "Recipe Options:"
|
||
echo " --title Recipe title (required)"
|
||
echo " --category Recipe category (required)"
|
||
echo " --difficulty Difficulty level (Beginner/Intermediate/Advanced/Expert)"
|
||
echo " --prep-time Preparation time (e.g., '30 min', '2 hours')"
|
||
echo " --tags Comma-separated tags"
|
||
echo " --featured Mark as featured (true/false)"
|
||
echo " --language Target language (en/es/all)"
|
||
echo ""
|
||
echo "Examples:"
|
||
echo " $0 blog-post --title 'Advanced Rust Patterns' --category 'Programming' --tags 'rust,patterns'"
|
||
echo " $0 recipe --title 'Docker Security Setup' --category 'Security' --difficulty 'Advanced'"
|
||
echo " $0 templates"
|
||
echo ""
|
||
}
|
||
|
||
# Generate unique ID from title
|
||
generate_id() {
|
||
local title="$1"
|
||
echo "$title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g'
|
||
}
|
||
|
||
# Generate current date
|
||
get_current_date() {
|
||
date +"%Y-%m-%d"
|
||
}
|
||
|
||
# Create templates directory and files
|
||
create_templates() {
|
||
log_step "Creating template files..."
|
||
|
||
mkdir -p "$TEMPLATES_DIR"
|
||
|
||
# Blog post template
|
||
cat > "$TEMPLATES_DIR/blog-post.md" << 'EOF'
|
||
---
|
||
id: "{{ID}}"
|
||
title: "{{TITLE}}"
|
||
subtitle: "{{SUBTITLE}}"
|
||
excerpt: "{{EXCERPT}}"
|
||
author: "{{AUTHOR}}"
|
||
date: "{{DATE}}"
|
||
read_time: "{{READ_TIME}}"
|
||
tags: [{{TAGS}}]
|
||
featured: {{FEATURED}}
|
||
published: true
|
||
language: "{{LANGUAGE}}"
|
||
translations: [{{TRANSLATIONS}}]
|
||
---
|
||
|
||
# {{TITLE}}
|
||
|
||
{{SUBTITLE}}
|
||
|
||
## Introduction
|
||
|
||
{{EXCERPT}}
|
||
|
||
## Content
|
||
|
||
Write your blog post content here...
|
||
|
||
## Conclusion
|
||
|
||
Summarize your key points here...
|
||
|
||
---
|
||
|
||
*Published on {{DATE}} by {{AUTHOR}}*
|
||
EOF
|
||
|
||
# Recipe template
|
||
cat > "$TEMPLATES_DIR/recipe.md" << 'EOF'
|
||
---
|
||
id: "{{ID}}"
|
||
title: "{{TITLE}}"
|
||
subtitle: "{{SUBTITLE}}"
|
||
excerpt: "{{EXCERPT}}"
|
||
category: "{{CATEGORY}}"
|
||
difficulty: "{{DIFFICULTY}}"
|
||
prep_time: "{{PREP_TIME}}"
|
||
tags: [{{TAGS}}]
|
||
featured: {{FEATURED}}
|
||
language: "{{LANGUAGE}}"
|
||
translations: [{{TRANSLATIONS}}]
|
||
---
|
||
|
||
# {{TITLE}}
|
||
|
||
{{SUBTITLE}}
|
||
|
||
## Overview
|
||
|
||
{{EXCERPT}}
|
||
|
||
## Prerequisites
|
||
|
||
- List prerequisites here
|
||
- Required tools and knowledge
|
||
- System requirements
|
||
|
||
## Difficulty Level: {{DIFFICULTY}}
|
||
**Estimated Time:** {{PREP_TIME}}
|
||
|
||
## Steps
|
||
|
||
### Step 1: Initial Setup
|
||
|
||
Describe the first step...
|
||
|
||
### Step 2: Configuration
|
||
|
||
Describe configuration steps...
|
||
|
||
### Step 3: Implementation
|
||
|
||
Describe implementation details...
|
||
|
||
## Testing
|
||
|
||
How to test the implementation...
|
||
|
||
## Troubleshooting
|
||
|
||
Common issues and solutions...
|
||
|
||
## Additional Resources
|
||
|
||
- Link to relevant documentation
|
||
- Related recipes or articles
|
||
- Community resources
|
||
|
||
---
|
||
|
||
*Category: {{CATEGORY}} | Difficulty: {{DIFFICULTY}} | Time: {{PREP_TIME}}*
|
||
EOF
|
||
|
||
# JSON templates
|
||
cat > "$TEMPLATES_DIR/blog-post.json" << 'EOF'
|
||
{
|
||
"id": "{{ID}}",
|
||
"title": "{{TITLE}}",
|
||
"subtitle": "{{SUBTITLE}}",
|
||
"excerpt": "{{EXCERPT}}",
|
||
"author": "{{AUTHOR}}",
|
||
"date": "{{DATE}}",
|
||
"read_time": "{{READ_TIME}}",
|
||
"tags": [{{TAGS_JSON}}],
|
||
"featured": {{FEATURED}},
|
||
"published": true,
|
||
"language": "{{LANGUAGE}}",
|
||
"source_file": "content/blog/{{LANGUAGE}}/{{ID}}.md",
|
||
"html_file": "/blog/{{LANGUAGE}}/{{ID}}.html",
|
||
"translations": [{{TRANSLATIONS_JSON}}]
|
||
}
|
||
EOF
|
||
|
||
cat > "$TEMPLATES_DIR/recipe.json" << 'EOF'
|
||
{
|
||
"id": "{{ID}}",
|
||
"title": "{{TITLE}}",
|
||
"subtitle": "{{SUBTITLE}}",
|
||
"excerpt": "{{EXCERPT}}",
|
||
"category": "{{CATEGORY}}",
|
||
"difficulty": "{{DIFFICULTY}}",
|
||
"prep_time": "{{PREP_TIME}}",
|
||
"tags": [{{TAGS_JSON}}],
|
||
"featured": {{FEATURED}},
|
||
"language": "{{LANGUAGE}}",
|
||
"source_file": "content/recipes/{{LANGUAGE}}/{{ID}}.md",
|
||
"html_file": "/recipes/{{LANGUAGE}}/{{ID}}.html",
|
||
"translations": [{{TRANSLATIONS_JSON}}]
|
||
}
|
||
EOF
|
||
|
||
log_success "Template files created in $TEMPLATES_DIR"
|
||
}
|
||
|
||
# Parse command line arguments
|
||
parse_args() {
|
||
TITLE=""
|
||
AUTHOR="Jesús Pérez"
|
||
CATEGORY=""
|
||
DIFFICULTY=""
|
||
PREP_TIME=""
|
||
TAGS=""
|
||
FEATURED="false"
|
||
LANGUAGE="all"
|
||
SUBTITLE=""
|
||
EXCERPT=""
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--title)
|
||
TITLE="$2"
|
||
shift 2
|
||
;;
|
||
--author)
|
||
AUTHOR="$2"
|
||
shift 2
|
||
;;
|
||
--category)
|
||
CATEGORY="$2"
|
||
shift 2
|
||
;;
|
||
--difficulty)
|
||
DIFFICULTY="$2"
|
||
shift 2
|
||
;;
|
||
--prep-time)
|
||
PREP_TIME="$2"
|
||
shift 2
|
||
;;
|
||
--tags)
|
||
TAGS="$2"
|
||
shift 2
|
||
;;
|
||
--featured)
|
||
FEATURED="$2"
|
||
shift 2
|
||
;;
|
||
--language)
|
||
LANGUAGE="$2"
|
||
shift 2
|
||
;;
|
||
--subtitle)
|
||
SUBTITLE="$2"
|
||
shift 2
|
||
;;
|
||
--excerpt)
|
||
EXCERPT="$2"
|
||
shift 2
|
||
;;
|
||
*)
|
||
log_error "Unknown option: $1"
|
||
show_usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Convert tags to JSON array format
|
||
tags_to_json() {
|
||
local tags="$1"
|
||
if [[ -z "$tags" ]]; then
|
||
echo ""
|
||
return
|
||
fi
|
||
|
||
echo "$tags" | sed 's/,/", "/g' | sed 's/^/"/' | sed 's/$/"/'
|
||
}
|
||
|
||
# Get translation languages
|
||
get_translations() {
|
||
local current_lang="$1"
|
||
local translations=""
|
||
|
||
for lang in "${SUPPORTED_LANGUAGES[@]}"; do
|
||
if [[ "$lang" != "$current_lang" ]]; then
|
||
if [[ -z "$translations" ]]; then
|
||
translations="\"$lang\""
|
||
else
|
||
translations="$translations, \"$lang\""
|
||
fi
|
||
fi
|
||
done
|
||
|
||
echo "$translations"
|
||
}
|
||
|
||
# Replace template variables
|
||
replace_template_vars() {
|
||
local template_file="$1"
|
||
local output_file="$2"
|
||
local lang="$3"
|
||
|
||
local id=$(generate_id "$TITLE")
|
||
local date=$(get_current_date)
|
||
local tags_json=$(tags_to_json "$TAGS")
|
||
local translations_json=$(get_translations "$lang")
|
||
|
||
# Set defaults if not provided
|
||
if [[ -z "$SUBTITLE" ]]; then
|
||
SUBTITLE="A comprehensive guide"
|
||
fi
|
||
|
||
if [[ -z "$EXCERPT" ]]; then
|
||
EXCERPT="This content provides detailed information and practical examples."
|
||
fi
|
||
|
||
# Calculate read time (rough estimate: 200 words per minute)
|
||
local read_time="5 min read"
|
||
|
||
cp "$template_file" "$output_file"
|
||
|
||
# Replace all template variables
|
||
sed -i "s|{{ID}}|$id|g" "$output_file"
|
||
sed -i "s|{{TITLE}}|$TITLE|g" "$output_file"
|
||
sed -i "s|{{SUBTITLE}}|$SUBTITLE|g" "$output_file"
|
||
sed -i "s|{{EXCERPT}}|$EXCERPT|g" "$output_file"
|
||
sed -i "s|{{AUTHOR}}|$AUTHOR|g" "$output_file"
|
||
sed -i "s|{{DATE}}|$date|g" "$output_file"
|
||
sed -i "s|{{READ_TIME}}|$read_time|g" "$output_file"
|
||
sed -i "s|{{CATEGORY}}|$CATEGORY|g" "$output_file"
|
||
sed -i "s|{{DIFFICULTY}}|$DIFFICULTY|g" "$output_file"
|
||
sed -i "s|{{PREP_TIME}}|$PREP_TIME|g" "$output_file"
|
||
sed -i "s|{{TAGS}}|$TAGS|g" "$output_file"
|
||
sed -i "s|{{TAGS_JSON}}|$tags_json|g" "$output_file"
|
||
sed -i "s|{{FEATURED}}|$FEATURED|g" "$output_file"
|
||
sed -i "s|{{LANGUAGE}}|$lang|g" "$output_file"
|
||
sed -i "s|{{TRANSLATIONS}}|$(get_translations "$lang" | sed 's/"//g')|g" "$output_file"
|
||
sed -i "s|{{TRANSLATIONS_JSON}}|$translations_json|g" "$output_file"
|
||
}
|
||
|
||
# Generate blog post
|
||
generate_blog_post() {
|
||
if [[ -z "$TITLE" ]]; then
|
||
log_error "Title is required for blog posts"
|
||
show_usage
|
||
exit 1
|
||
fi
|
||
|
||
local id=$(generate_id "$TITLE")
|
||
local languages=("${SUPPORTED_LANGUAGES[@]}")
|
||
|
||
if [[ "$LANGUAGE" != "all" ]]; then
|
||
languages=("$LANGUAGE")
|
||
fi
|
||
|
||
log_step "Generating blog post: $TITLE"
|
||
|
||
for lang in "${languages[@]}"; do
|
||
local blog_dir="${CONTENT_DIR}/blog/${lang}"
|
||
mkdir -p "$blog_dir"
|
||
|
||
local md_file="${blog_dir}/${id}.md"
|
||
local json_file="/tmp/${id}.json"
|
||
|
||
# Generate markdown file
|
||
replace_template_vars "$TEMPLATES_DIR/blog-post.md" "$md_file" "$lang"
|
||
log_success "Created markdown file: $md_file"
|
||
|
||
# Generate JSON entry
|
||
replace_template_vars "$TEMPLATES_DIR/blog-post.json" "$json_file" "$lang"
|
||
|
||
# Update index file
|
||
local index_file="${blog_dir}/index.json"
|
||
if [[ -f "$index_file" ]]; then
|
||
# Add to existing index
|
||
local temp_file="/tmp/blog_index_temp.json"
|
||
jq --argjson new_post "$(cat "$json_file")" '.blog += [$new_post]' "$index_file" > "$temp_file"
|
||
mv "$temp_file" "$index_file"
|
||
else
|
||
# Create new index
|
||
cat > "$index_file" << EOF
|
||
{
|
||
"blog": [$(cat "$json_file")],
|
||
"language": "$lang"
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
log_success "Updated blog index for language: $lang"
|
||
rm "$json_file"
|
||
done
|
||
|
||
log_success "Blog post '$TITLE' generated successfully!"
|
||
}
|
||
|
||
# Generate recipe
|
||
generate_recipe() {
|
||
if [[ -z "$TITLE" ]]; then
|
||
log_error "Title is required for recipes"
|
||
show_usage
|
||
exit 1
|
||
fi
|
||
|
||
if [[ -z "$CATEGORY" ]]; then
|
||
log_error "Category is required for recipes"
|
||
show_usage
|
||
exit 1
|
||
fi
|
||
|
||
# Set defaults
|
||
if [[ -z "$DIFFICULTY" ]]; then
|
||
DIFFICULTY="Intermediate"
|
||
fi
|
||
|
||
if [[ -z "$PREP_TIME" ]]; then
|
||
PREP_TIME="30 min"
|
||
fi
|
||
|
||
local id=$(generate_id "$TITLE")
|
||
local languages=("${SUPPORTED_LANGUAGES[@]}")
|
||
|
||
if [[ "$LANGUAGE" != "all" ]]; then
|
||
languages=("$LANGUAGE")
|
||
fi
|
||
|
||
log_step "Generating recipe: $TITLE"
|
||
|
||
for lang in "${languages[@]}"; do
|
||
local recipe_dir="${CONTENT_DIR}/recipes/${lang}"
|
||
mkdir -p "$recipe_dir"
|
||
|
||
local md_file="${recipe_dir}/${id}.md"
|
||
local json_file="/tmp/${id}.json"
|
||
|
||
# Generate markdown file
|
||
replace_template_vars "$TEMPLATES_DIR/recipe.md" "$md_file" "$lang"
|
||
log_success "Created markdown file: $md_file"
|
||
|
||
# Generate JSON entry
|
||
replace_template_vars "$TEMPLATES_DIR/recipe.json" "$json_file" "$lang"
|
||
|
||
# Update index file
|
||
local index_file="${recipe_dir}/index.json"
|
||
if [[ -f "$index_file" ]]; then
|
||
# Add to existing index
|
||
local temp_file="/tmp/recipe_index_temp.json"
|
||
jq --argjson new_recipe "$(cat "$json_file")" '.recipes += [$new_recipe]' "$index_file" > "$temp_file"
|
||
mv "$temp_file" "$index_file"
|
||
else
|
||
# Create new index
|
||
cat > "$index_file" << EOF
|
||
{
|
||
"recipes": [$(cat "$json_file")],
|
||
"language": "$lang"
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
log_success "Updated recipe index for language: $lang"
|
||
rm "$json_file"
|
||
done
|
||
|
||
log_success "Recipe '$TITLE' generated successfully!"
|
||
}
|
||
|
||
# Update all indices
|
||
update_indices() {
|
||
log_step "Updating all content indices..."
|
||
|
||
for lang in "${SUPPORTED_LANGUAGES[@]}"; do
|
||
# Update blog index
|
||
local blog_dir="${CONTENT_DIR}/blog/${lang}"
|
||
local blog_index="${blog_dir}/index.json"
|
||
|
||
if [[ -d "$blog_dir" ]] && [[ ! -f "$blog_index" ]]; then
|
||
log_info "Creating missing blog index for language: $lang"
|
||
cat > "$blog_index" << EOF
|
||
{
|
||
"blog": [],
|
||
"language": "$lang"
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
# Update recipe index
|
||
local recipe_dir="${CONTENT_DIR}/recipes/${lang}"
|
||
local recipe_index="${recipe_dir}/index.json"
|
||
|
||
if [[ -d "$recipe_dir" ]] && [[ ! -f "$recipe_index" ]]; then
|
||
log_info "Creating missing recipe index for language: $lang"
|
||
cat > "$recipe_index" << EOF
|
||
{
|
||
"recipes": [],
|
||
"language": "$lang"
|
||
}
|
||
EOF
|
||
fi
|
||
done
|
||
|
||
log_success "Indices updated successfully!"
|
||
}
|
||
|
||
# Main function
|
||
main() {
|
||
local command="$1"
|
||
shift
|
||
|
||
case "$command" in
|
||
"blog-post")
|
||
parse_args "$@"
|
||
generate_blog_post
|
||
;;
|
||
"recipe")
|
||
parse_args "$@"
|
||
generate_recipe
|
||
;;
|
||
"templates")
|
||
create_templates
|
||
;;
|
||
"index")
|
||
update_indices
|
||
;;
|
||
"help"|"")
|
||
show_usage
|
||
;;
|
||
*)
|
||
log_error "Unknown command: $command"
|
||
show_usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Check if templates exist, create if not
|
||
if [[ ! -d "$TEMPLATES_DIR" ]] && [[ "$1" != "templates" ]] && [[ "$1" != "help" ]] && [[ "$1" != "" ]]; then
|
||
log_info "Templates not found, creating them first..."
|
||
create_templates
|
||
fi
|
||
|
||
# Run main function
|
||
main "$@"
|