Files
bin/css_json_convert.sh
Sebastian Krüger a71eef9006 Add utility scripts collection with auto-generated documentation
This commit introduces a comprehensive collection of utility scripts for shell
automation, color manipulation, and documentation generation:

Core Scripts:
- artifact_github_download.sh: Download GitHub Action artifacts via CLI
- css_color_filter.sh: Generate CSS filter values using SPSA algorithm
- css_color_palette.sh: Generate comprehensive color palettes (monochromatic, triadic, etc.)
- css_json_convert.sh: Convert CSS variables to JSON/YAML formats
- doc_bash_generate.sh: Auto-generate README.md with animated GIF demos
- doc_rust_generate.sh: Generate Rust project documentation
- jinja_template_render.sh: Render Jinja2 templates from CLI
- mime_mp4_gif.sh: Convert MP4 videos to GIF format

Documentation Features:
- Comprehensive README.md with table of contents
- 8 animated GIF demos showing real command examples
- Sandboxed demo execution in temporary directories
- 15-second timeout protection for intensive computations
- Automatic example extraction from --help output

Technical Implementation:
- Pure bash color utilities using only bc for arithmetic
- tput-based color codes for portability
- IFS-safe string parsing using parameter expansion
- Stdout/stderr isolation to prevent contamination
- Base64 encoding for multi-line text preservation

All scripts include detailed --help documentation with usage examples.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 03:10:19 +01:00

348 lines
9.2 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#############################################
# CSS Variable to JSON/YAML Converter
# Extracts CSS custom properties (--var: value;)
# and converts them to JSON or YAML format
#############################################
set -euo pipefail
# Terminal colors using tput
RED="" GREEN="" YELLOW="" BLUE="" MAGENTA="" CYAN="" BOLD="" DIM="" RESET=""
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
COLORS=$(tput colors 2>/dev/null || echo 0)
if [[ ${COLORS:-0} -ge 8 ]]; then
RED=$(tput setaf 1 2>/dev/null || echo "")
GREEN=$(tput setaf 2 2>/dev/null || echo "")
YELLOW=$(tput setaf 3 2>/dev/null || echo "")
BLUE=$(tput setaf 4 2>/dev/null || echo "")
MAGENTA=$(tput setaf 5 2>/dev/null || echo "")
CYAN=$(tput setaf 6 2>/dev/null || echo "")
BOLD=$(tput bold 2>/dev/null || echo "")
DIM=$(tput dim 2>/dev/null || echo "")
RESET=$(tput sgr0 2>/dev/null || echo "")
fi
fi
# Icons for output (simple ASCII)
readonly ICON_SUCCESS="[OK]"
readonly ICON_ERROR="[ERROR]"
readonly ICON_INFO="[INFO]"
readonly ICON_CONVERT="==>"
# Default values
OUTPUT_FILE="${PWD}/output.yaml"
INPUT_FILE=""
CAMEL_CASE=false
VERBOSE=false
#############################################
# Functions
#############################################
print_banner() {
echo ""
echo "${CYAN}${BOLD}================================================================${RESET}"
echo "${CYAN}${BOLD} CSS Variable to JSON/YAML Converter${RESET}"
echo "${CYAN}${BOLD} Extract CSS custom properties with ease${RESET}"
echo "${CYAN}${BOLD}================================================================${RESET}"
echo ""
}
print_success() {
echo "${GREEN}${ICON_SUCCESS}${RESET} $*"
}
print_error() {
echo "${RED}${ICON_ERROR}${RESET} $*" >&2
}
print_info() {
echo "${BLUE}${ICON_INFO}${RESET} $*"
}
print_verbose() {
if [[ "$VERBOSE" == true ]]; then
echo "${DIM} ==> $*${RESET}"
fi
return 0
}
show_help() {
cat << EOF
${BOLD}USAGE:${RESET}
$(basename "$0") [OPTIONS] <input.css>
${BOLD}DESCRIPTION:${RESET}
Extracts CSS custom properties (variables) from a CSS file and converts
them to JSON or YAML format. Automatically detects output format from
file extension.
${BOLD}ARGUMENTS:${RESET}
<input.css> Input CSS file containing CSS variables
${BOLD}OPTIONS:${RESET}
-o, --output FILE Output file path (default: ./output.yaml)
Format auto-detected from extension (.json/.yaml/.yml)
-c, --camel-case Convert variable names to camelCase
(e.g., --main-color -> mainColor)
-v, --verbose Enable verbose output
-h, --help Show this help message
${BOLD}EXAMPLES:${RESET}
# Extract CSS vars to YAML (default)
$(basename "$0") styles.css
# Extract to JSON with custom output
$(basename "$0") styles.css -o theme.json
# Convert variable names to camelCase
$(basename "$0") styles.css -o vars.json --camel-case
${BOLD}CSS VARIABLE FORMAT:${RESET}
The script extracts CSS custom properties in the format:
--variable-name: value;
Example input:
:root {
--main-color: #e8eaed;
--font-size: 16px;
}
Example JSON output:
{
"main-color": "#e8eaed",
"font-size": "16px"
}
EOF
}
# Convert kebab-case to camelCase
to_camel_case() {
local input="$1"
# Remove leading dashes and convert to camelCase
echo "$input" | sed -E 's/^--//; s/-(.)/\U\1/g'
}
# Extract CSS variables using advanced sed
extract_css_variables() {
local input_file="$1"
print_verbose "Extracting CSS variables from: $input_file" >&2
# Advanced sed expression to extract CSS custom properties
# Matches: --variable-name: value; (with flexible whitespace)
sed -n 's/^[[:space:]]*\(--[a-zA-Z0-9_-]\+\)[[:space:]]*:[[:space:]]*\([^;]\+\);.*$/\1|\2/p' "$input_file" \
| sed 's/[[:space:]]*$//' \
| sed 's/^[[:space:]]*//'
}
# Convert to JSON format
convert_to_json() {
local -a variables=("$@")
local json="{"
local first=true
for var in "${variables[@]}"; do
IFS='|' read -r name value <<< "$var"
# Remove leading dashes
name="${name#--}"
# Convert to camelCase if requested
if [[ "$CAMEL_CASE" == true ]]; then
name=$(to_camel_case "--$name")
fi
# Trim whitespace from value
value=$(echo "$value" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
# Escape quotes in value
value="${value//\"/\\\"}"
if [[ "$first" == true ]]; then
first=false
json+=$'\n'
else
json+=","$'\n'
fi
json+=" \"$name\": \"$value\""
done
json+=$'\n'"}"
echo "$json"
}
# Convert to YAML format
convert_to_yaml() {
local -a variables=("$@")
local yaml=""
for var in "${variables[@]}"; do
IFS='|' read -r name value <<< "$var"
# Remove leading dashes
name="${name#--}"
# Convert to camelCase if requested
if [[ "$CAMEL_CASE" == true ]]; then
name=$(to_camel_case "--$name")
fi
# Trim whitespace from value
value=$(echo "$value" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
# Quote value if it contains special characters or starts with special chars
if [[ "$value" =~ ^[#\&\*\!\|\>\'\"] ]] || [[ "$value" =~ [:\{\}\[\],] ]]; then
value="\"$value\""
fi
yaml+="$name: $value"$'\n'
done
echo "$yaml"
}
# Determine output format from file extension
get_output_format() {
local file="$1"
local ext="${file##*.}"
case "$ext" in
json)
echo "json"
;;
yaml|yml)
echo "yaml"
;;
*)
print_error "Unsupported output format: .$ext"
print_info "Supported formats: .json, .yaml, .yml"
exit 1
;;
esac
}
#############################################
# Main Script
#############################################
main() {
print_banner
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-o|--output)
OUTPUT_FILE="$2"
shift 2
;;
-c|--camel-case)
CAMEL_CASE=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
print_error "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
*)
INPUT_FILE="$1"
shift
;;
esac
done
# Validate input file
if [[ -z "$INPUT_FILE" ]]; then
print_error "No input file specified"
echo "Use -h or --help for usage information"
exit 1
fi
if [[ ! -f "$INPUT_FILE" ]]; then
print_error "Input file not found: $INPUT_FILE"
exit 1
fi
# Show processing info
print_info "${ICON_FILE} Input: ${CYAN}$INPUT_FILE${RESET}"
print_info "${ICON_FILE} Output: ${CYAN}$OUTPUT_FILE${RESET}"
if [[ "$CAMEL_CASE" == true ]]; then
print_info "${ICON_CONVERT} Mode: ${YELLOW}camelCase conversion enabled${RESET}"
fi
echo ""
# Extract CSS variables
print_info "${ICON_CONVERT} Extracting CSS variables..."
mapfile -t variables < <(extract_css_variables "$INPUT_FILE")
if [[ ${#variables[@]} -eq 0 ]]; then
print_error "No CSS variables found in $INPUT_FILE"
print_info "Expected format: --variable-name: value;"
exit 1
fi
print_success "Found ${BOLD}${#variables[@]}${RESET} CSS variable(s)"
# Show extracted variables in verbose mode
if [[ "$VERBOSE" == true ]]; then
echo ""
for var in "${variables[@]}"; do
IFS='|' read -r name value <<< "$var"
print_verbose "${MAGENTA}$name${RESET} = ${GREEN}$value${RESET}"
done
echo ""
fi
# Determine output format
OUTPUT_FORMAT=$(get_output_format "$OUTPUT_FILE")
print_verbose "Output format: $OUTPUT_FORMAT"
# Convert and write output
print_info "${ICON_CONVERT} Converting to ${BOLD}${OUTPUT_FORMAT^^}${RESET}..."
case "$OUTPUT_FORMAT" in
json)
convert_to_json "${variables[@]}" > "$OUTPUT_FILE"
;;
yaml)
convert_to_yaml "${variables[@]}" > "$OUTPUT_FILE"
;;
esac
# Success message
echo ""
print_success "${ICON_ROCKET} Conversion complete!"
print_info "Output saved to: ${BOLD}${GREEN}$OUTPUT_FILE${RESET}"
# Show preview if verbose
if [[ "$VERBOSE" == true ]]; then
echo ""
echo -e "${DIM} Preview ${RESET}"
head -n 20 "$OUTPUT_FILE" | sed 's/^/ /'
if [[ $(wc -l < "$OUTPUT_FILE") -gt 20 ]]; then
echo -e "${DIM} ... (truncated)${RESET}"
fi
echo -e "${DIM}${RESET}"
fi
}
# Run main function
main "$@"