summaryrefslogtreecommitdiff
path: root/core/modules/template.sh
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/template.sh')
-rw-r--r--core/modules/template.sh131
1 files changed, 131 insertions, 0 deletions
diff --git a/core/modules/template.sh b/core/modules/template.sh
new file mode 100644
index 0000000..887a47b
--- /dev/null
+++ b/core/modules/template.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+# Module: template
+# Description: Genera archivos a partir de plantillas con variables {{var}}, bucles, includes y delimitadores configurables
+# Author: Luis GuLo
+# Version: 0.4.0
+# Dependencies: bash, sed, tee, grep, cat
+
+# 🧭 Detección de raíz del proyecto
+PROJECT_ROOT="${SHFLOW_HOME:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
+TEMPLATE_DIR="$PROJECT_ROOT/core/templates"
+
+template_task() {
+ local host="$1"; shift
+ declare -A args
+ local start_delim="{{" end_delim="}}" strict="false"
+ declare -A vars
+
+ # 🌐 Cargar traducciones
+ local lang="${shflow_vars[language]:-es}"
+ local trfile="$(dirname "${BASH_SOURCE[0]}")/template.tr.${lang}"
+ declare -A tr
+ if [[ -f "$trfile" ]]; then
+ while IFS='=' read -r k v; do tr["$k"]="$v"; done < "$trfile"
+ fi
+
+ # Parsear argumentos
+ for arg in "$@"; do
+ key="${arg%%=*}"
+ value="${arg#*=}"
+ case "$key" in
+ src) src="$value" ;;
+ dest) dest="$value" ;;
+ become) become="$value" ;;
+ delimiters)
+ start_delim="${value%% *}"
+ end_delim="${value#* }"
+ ;;
+ strict) strict="$value" ;;
+ *) vars["$key"]="$value" ;;
+ esac
+ done
+
+ local prefix=""
+ [ "$become" = "true" ] && prefix="sudo"
+
+ local template_path="$TEMPLATE_DIR/$src"
+ [[ ! -f "$template_path" ]] && echo "$(render_msg "${tr[missing_template]}" "path=$template_path")" && return 1
+
+ local rendered=""
+ local line loop_active="false" loop_key="" loop_buffer=()
+
+ while IFS= read -r line || [[ -n "$line" ]]; do
+ if [[ "$line" =~ ${start_delim}[[:space:]]*include[[:space:]]*\"([^\"]+)\"[[:space:]]*${end_delim} ]]; then
+ include_file="${BASH_REMATCH[1]}"
+ include_path="$TEMPLATE_DIR/$include_file"
+ [[ -f "$include_path" ]] && rendered+=$(cat "$include_path")$'\n'
+ continue
+ fi
+
+ if [[ "$line" =~ ^#LOOP[[:space:]]+([a-zA-Z0-9_]+)$ ]]; then
+ loop_active="true"
+ loop_key="${BASH_REMATCH[1]}"
+ loop_buffer=()
+ continue
+ fi
+
+ if [[ "$line" == "#ENDLOOP" ]]; then
+ loop_active="false"
+ IFS=',' read -r -a items <<< "${vars[$loop_key]}"
+ for item in "${items[@]}"; do
+ for loop_line in "${loop_buffer[@]}"; do
+ rendered+=$(replace_vars "$loop_line" "$item" "$start_delim" "$end_delim")$'\n'
+ done
+ done
+ continue
+ fi
+
+ if [[ "$loop_active" == "true" ]]; then
+ loop_buffer+=("$line")
+ continue
+ fi
+
+ rendered+=$(replace_vars "$line" "" "$start_delim" "$end_delim")$'\n'
+ done < "$template_path"
+
+ if [[ "$strict" == "true" ]]; then
+ missing=$(echo "$rendered" | grep -o "${start_delim}[^${end_delim}]*${end_delim}" | sort -u)
+ if [[ -n "$missing" ]]; then
+ echo "${tr[missing_vars]:-❌ [template] Variables no definidas:}"
+ echo "$missing"
+ return 1
+ fi
+ fi
+
+ echo "$rendered" | $prefix tee "$dest" > /dev/null
+ echo "$(render_msg "${tr[generated]}" "dest=$dest")"
+}
+
+replace_vars() {
+ local line="$1"
+ local item="$2"
+ local start_delim="$3"
+ local end_delim="$4"
+ for key in "${!vars[@]}"; do
+ line="${line//${start_delim}${key}${end_delim}/${vars[$key]}}"
+ done
+ [[ -n "$item" ]] && line="${line//${start_delim}item${end_delim}/$item}"
+ echo "$line"
+}
+
+check_dependencies_template() {
+ local lang="${shflow_vars[language]:-es}"
+ local trfile="$(dirname "${BASH_SOURCE[0]}")/template.tr.${lang}"
+ declare -A tr
+ if [[ -f "$trfile" ]]; then
+ while IFS='=' read -r k v; do tr["$k"]="$v"; done < "$trfile"
+ fi
+
+ local missing=()
+ for cmd in sed tee grep cat; do
+ command -v "$cmd" >/dev/null 2>&1 || missing+=("$cmd")
+ done
+
+ if [[ ${#missing[@]} -gt 0 ]]; then
+ echo "$(render_msg "${tr[missing_deps]}" "cmds=${missing[*]}")"
+ return 1
+ fi
+
+ echo "${tr[deps_ok]:-✅ [template] Todas las dependencias están disponibles}"
+ return 0
+}