Files
bin/css_json_convert.sh

348 lines
9.2 KiB
Bash
Raw Permalink Normal View History

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
#!/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 "$@"