summaryrefslogtreecommitdiff
path: root/core/modules/template.sh
blob: 887a47bfb8f3813e6108815dd16d40a4272094d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
}