diff --git a/.qsgen3_preserve.example b/.qsgen3_preserve.example new file mode 100644 index 0000000..cd5f93a --- /dev/null +++ b/.qsgen3_preserve.example @@ -0,0 +1,40 @@ +# qsgen3 Preserve File +# +# This file specifies patterns for files that should be preserved during +# output directory cleaning. This is useful for keeping shared articles +# or other content that should remain accessible even after title changes. +# +# Format: +# - One pattern per line +# - Supports shell glob patterns (*, ?, []) +# - Lines starting with # are comments +# - Empty lines are ignored +# - Patterns are relative to the output directory +# +# Examples: + +# Preserve specific files by exact name +# posts/my-important-shared-article.html +# about.html + +# Preserve files by pattern +# posts/legacy-*.html +# *.pdf + +# Preserve entire directories +# archive/* +# downloads/* + +# Preserve files with specific extensions in certain directories +# posts/*.html +# docs/*.pdf + +# Example: Preserve a specific shared article +# posts/how-to-setup-qsgen3.html + +# Example: Preserve all files in a legacy directory +# legacy/* + +# Example: Preserve important documents +# important-*.html +# *.pdf diff --git a/bin/qsgen3 b/bin/qsgen3 index 135c804..c3af879 100755 --- a/bin/qsgen3 +++ b/bin/qsgen3 @@ -599,9 +599,102 @@ _minify_output_directory() { # --- Core Functions --- _clean_output_dir() { _log INFO "Cleaning output directory: ${QSG_CONFIG[paths_output_dir]}" - # rm -rf "${QSG_CONFIG[paths_output_dir]}"/* # Be careful with this! - # For now, just ensure it exists - mkdir -p "${QSG_CONFIG[paths_output_dir]}" + + local output_dir="${QSG_CONFIG[paths_output_dir]}" + local preserve_file="$PROJECT_ROOT/.qsgen3_preserve" + + # If output directory doesn't exist, just create it + if [[ ! -d "$output_dir" ]]; then + mkdir -p "$output_dir" + if [[ $? -eq 0 ]]; then + _log DEBUG "Created output directory: $output_dir" + else + _log ERROR "Failed to create output directory: $output_dir" + return 1 + fi + return 0 + fi + + # Check if preserve file exists + if [[ -f "$preserve_file" ]]; then + _log INFO "Found preserve file: $preserve_file" + _log DEBUG "Performing selective cleaning with file preservation" + + # Create temporary directory to store preserved files + local temp_preserve_dir=$(mktemp -d) + local files_preserved=0 + + # Read preserve patterns and backup matching files + while IFS= read -r pattern || [[ -n "$pattern" ]]; do + # Skip empty lines and comments + [[ -z "$pattern" || "$pattern" == \#* ]] && continue + + # Remove leading/trailing whitespace + pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + [[ -z "$pattern" ]] && continue + + _log DEBUG "Processing preserve pattern: $pattern" + + # Find files matching the pattern in output directory + while IFS= read -r -d '' file; do + if [[ -f "$file" ]]; then + # Get relative path from output directory + local rel_path="${file#$output_dir/}" + local preserve_path="$temp_preserve_dir/$rel_path" + + # Create directory structure in temp location + mkdir -p "$(dirname "$preserve_path")" + + # Copy file to preserve location + if cp "$file" "$preserve_path"; then + files_preserved=$((files_preserved + 1)) + _log DEBUG "Preserved file: $rel_path" + else + _log WARNING "Failed to preserve file: $rel_path" + fi + fi + done < <(find "$output_dir" -name "$pattern" -type f -print0 2>/dev/null) + + done < "$preserve_file" + + # Remove the output directory + _log DEBUG "Removing output directory contents (preserving $files_preserved files)" + rm -rf "$output_dir" + + # Recreate output directory + mkdir -p "$output_dir" + if [[ $? -ne 0 ]]; then + _log ERROR "Failed to recreate output directory: $output_dir" + rm -rf "$temp_preserve_dir" + return 1 + fi + + # Restore preserved files + if [[ $files_preserved -gt 0 ]]; then + _log DEBUG "Restoring $files_preserved preserved files" + if [[ -d "$temp_preserve_dir" ]]; then + # Copy preserved files back, maintaining directory structure + (cd "$temp_preserve_dir" && find . -type f -exec cp --parents {} "$output_dir/" \; 2>/dev/null) + _log INFO "Restored $files_preserved preserved files" + fi + fi + + # Clean up temporary directory + rm -rf "$temp_preserve_dir" + + else + # No preserve file - do complete cleaning as before + _log DEBUG "No preserve file found - performing complete cleaning" + rm -rf "$output_dir" + mkdir -p "$output_dir" + if [[ $? -ne 0 ]]; then + _log ERROR "Failed to recreate output directory: $output_dir" + return 1 + fi + fi + + _log DEBUG "Output directory cleaning completed successfully" + return 0 } _copy_static_files() { @@ -1168,9 +1261,9 @@ _generate_rss_feed() { continue fi - local title=$(echo "$frontmatter" | grep -m1 -iE '^title:' | sed -E 's/^title:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/') - local date_iso=$(echo "$frontmatter" | grep -m1 -iE '^date:' | sed -E 's/^date:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/') - local summary=$(echo "$frontmatter" | grep -m1 -iE '^summary:' | sed -E 's/^summary:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/') + local title=$(echo "$frontmatter" | grep -m1 -iE '^title:' | sed -E 's/^title:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/') + local date_iso=$(echo "$frontmatter" | grep -m1 -iE '^date:' | sed -E 's/^date:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/') + local summary=$(echo "$frontmatter" | grep -m1 -iE '^summary:' | sed -E 's/^summary:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/') local draft=$(echo "$frontmatter" | grep -m1 -iE '^draft:' | sed -E 's/^draft:[[:space:]]*//i' | tr '[:upper:]' '[:lower:]') if [[ "$draft" == "true" && "${QSG_CONFIG[build_options_process_drafts]}" != "true" ]]; then diff --git a/how-it-works.md b/how-it-works.md index e20442a..25eead7 100644 --- a/how-it-works.md +++ b/how-it-works.md @@ -42,6 +42,7 @@ project-root/ ├── bin/ │ └── qsgen3 # Main generator script ├── site.conf # Main configuration file +├── .qsgen3_preserve # Optional: File preservation patterns ├── content/ # Markdown content │ ├── posts/ # Blog posts │ │ └── hello-world.md @@ -56,7 +57,6 @@ project-root/ ├── themes/ # Theme directory │ └── theme-name/ # Individual theme │ ├── layouts/ # Theme-specific templates (optional) -│ ├── static/ # Theme static assets (optional) │ └── css/ # Alternative theme asset location └── output/ # Generated site (created by qsgen3) ├── index.html @@ -128,8 +128,7 @@ themes/theme-name/ │ └── rss.xml # RSS template ├── static/ # Preferred: Standard static assets location │ ├── css/ -│ ├── js/ -│ └── images/ +│ └── js/ └── css/ # Alternative: Direct CSS location └── style.css ``` @@ -180,10 +179,7 @@ themes/my-theme/ └── static/ # Static assets ├── css/ │ └── style.css # Main stylesheet - ├── js/ # JavaScript files (optional) - │ └── theme.js - └── images/ # Theme images (optional) - └── logo.png + └── js/ # JavaScript files (optional) ``` **Option B: CSS-Only Structure** @@ -744,8 +740,7 @@ output/ │ └── post-name.html ├── static/ # All static assets │ ├── css/ # Stylesheets -│ ├── js/ # JavaScript (if provided by theme) -│ └── images/ # Images and media +│ └── js/ # JavaScript (if provided by theme) └── css/ # Legacy: Index-specific CSS location └── theme.css # Copy of main theme CSS for index page ``` @@ -870,11 +865,52 @@ Process Theme Configuration ``` Prepare Output Directory -├── Clean existing output directory -├── Create fresh output directory structure -└── Prepare for static file copying +├── Check for .qsgen3_preserve file in project root +├── If preserve file exists: +│ ├── Read file patterns (shell glob patterns) +│ ├── Create temporary backup directory +│ ├── Find and backup matching files from output directory +│ ├── Remove entire output directory +│ ├── Recreate clean output directory +│ ├── Restore preserved files maintaining directory structure +│ └── Clean up temporary backup directory +│ └── Remove entire output directory +│ └── Create fresh output directory +└── Log preservation and cleaning operations ``` +#### File Preservation System + +qsgen3 supports preserving specific files during the cleaning process to handle cases where content has been shared or bookmarked and should remain accessible even after title changes. + +**Preserve File Format (`.qsgen3_preserve`):** +- Located in project root directory +- One pattern per line using shell glob patterns (`*`, `?`, `[]`) +- Lines starting with `#` are comments +- Empty lines are ignored +- Patterns are relative to the output directory + +**Example preserve patterns:** +```bash +# Preserve specific shared articles +posts/my-important-shared-article.html +posts/viral-blog-post.html + +# Preserve files by pattern +posts/legacy-*.html +archive/* + +# Preserve all PDFs and downloads +*.pdf +downloads/* +``` + +**Benefits:** +- Maintains stable URLs for shared content +- Prevents broken links when content is renamed +- Flexible pattern matching for various preservation needs +- Backward compatible (no preserve file = complete cleaning) + ### 6. Static File Processing ``` @@ -999,6 +1035,31 @@ Complete Generation - Verify available disk space - Review path configurations for absolute vs. relative paths +#### 5. File Preservation Issues +**Symptoms**: Expected files not preserved during cleaning, or preservation not working +**Causes**: +- Incorrect patterns in `.qsgen3_preserve` file +- File paths don't match patterns +- Permission issues with temporary backup directory +- Malformed preserve file format + +**Solutions**: +- Verify patterns use shell glob syntax (`*`, `?`, `[]`) +- Check that patterns are relative to output directory +- Ensure `.qsgen3_preserve` file is in project root +- Test patterns with `find output/ -name "pattern"` before adding to preserve file +- Enable debug logging to see preservation process details +- Verify file permissions allow temporary directory creation + +**Example debugging:** +```bash +# Test if your pattern matches files +find output/ -name "posts/legacy-*.html" + +# Enable debug logging to see preservation process +QSG_DEBUG=1 ./bin/qsgen3 +``` + ### Debug Logging Enable detailed logging by modifying the `_log` function or adding debug statements: diff --git a/images/README.md b/images/README.md deleted file mode 100644 index e5120c2..0000000 --- a/images/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy this directory to your **www_root** - -**$www_root/images/** \ No newline at end of file diff --git a/images/ext-black-top.svg b/images/ext-black-top.svg deleted file mode 100644 index e5348c8..0000000 --- a/images/ext-black-top.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file