File size: 4,166 Bytes
f514b00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Archivo: inline_js.py
Fecha de modificación: 04/06/2026
Autor: Equipo AgroVisión

Descripción:
Post-procesa el HTML del build de Astro para que funcione bajo **sub-paths dinámicos**
(como los slugs `/_w_xxxx/` de ShinyApps.io). Inyecta inline los scripts que Astro
hubiera emitido en `/_astro/*.js` y normaliza las rutas de assets (favicon, JS) de
**absolutas a relativas**, ya que el host sirve la app desde una ruta distinta de la raíz.
Es la implementación de la "Regla de Oro" de `docs/doc_guia/plan_replication.md`.

Nota: nuestra UI ya usa scripts `is:inline` y `inlineStylesheets: 'always'`, por lo que
normalmente no hay `/_astro/*.js` externos; este script es idempotente y a prueba de
futuro (si se añade una isla/componente que genere JS externo, queda inlineado).

Acciones Principales:
    - Inyecta el contenido de los scripts `/_astro/*.js` directamente en el HTML.
    - Convierte las rutas absolutas de favicon a relativas.
    - Normaliza cualquier referencia absoluta restante a `/_astro/`.

Estructura Interna:
    - `inline_scripts`: inyecta el código JS externo inline.
    - `fix_favicon_paths`: relativiza las rutas de iconos.
    - `fix_absolute_asset_refs`: relativiza las rutas absolutas restantes.
    - `main`: orquesta el post-proceso sobre `frontend/dist/index.html`.

Entradas / Dependencias:
    - Biblioteca estándar (`re`, `pathlib`).

Salidas / Efectos:
    - Reescribe `frontend/dist/index.html` in place.

Ejecución:
    uv run python scripts/inline_js.py
"""

from __future__ import annotations

import re
import sys
from pathlib import Path

DIST = Path("frontend/dist")
HTML_FILE = DIST / "index.html"


def inline_scripts(html: str) -> str:
    """
    Reemplaza cada `<script ... src="/_astro/...">` por su contenido inline.

    Args:
        html (str): HTML de entrada.

    Returns:
        str: HTML con los scripts de Astro embebidos inline.
    """

    def _replace(match: re.Match) -> str:  # type: ignore[type-arg]
        src = match.group(1)
        rel = src.lstrip("/")  # la URL parte de "/"; el archivo es relativo a DIST
        js_path = DIST / rel
        if js_path.exists():
            content = js_path.read_text(encoding="utf-8")
            return f'<script type="module">{content}</script>'
        print(f"  [WARN] JS no encontrado: {js_path}", file=sys.stderr)
        return match.group(0)

    pattern = (
        r'<script\s[^>]*type=["\']module["\'][^>]*'
        r'src=["\'](\/_astro\/[^"\']+)["\'][^>]*>\s*</script>'
    )
    return re.sub(pattern, _replace, html)


def fix_favicon_paths(html: str) -> str:
    """Convierte rutas absolutas `/favicon.*` a relativas `./favicon.*`."""
    html = re.sub(r'href="\/favicon\.', 'href="./favicon.', html)
    html = re.sub(r"href='\/favicon\.", "href='./favicon.", html)
    return html


def fix_absolute_asset_refs(html: str) -> str:
    """Convierte cualquier referencia absoluta restante a `/_astro/` en relativa."""
    html = html.replace('href="/_astro/', 'href="./_astro/')
    html = html.replace("href='/_astro/", "href='./_astro/")
    html = html.replace('src="/_astro/', 'src="./_astro/')
    html = html.replace("src='/_astro/", "src='./_astro/")
    return html


def main() -> None:
    """
    Aplica el post-proceso sobre `frontend/dist/index.html` in place.

    Raises:
        SystemExit: si no existe el HTML del build (código 1).
    """
    if not HTML_FILE.exists():
        print(f"[ERROR] No se encontró {HTML_FILE}. Ejecuta 'pnpm build' (en frontend/) primero.")
        sys.exit(1)

    html = HTML_FILE.read_text(encoding="utf-8")
    original_len = len(html)

    html = inline_scripts(html)
    html = fix_favicon_paths(html)
    html = fix_absolute_asset_refs(html)

    HTML_FILE.write_text(html, encoding="utf-8")

    remaining = re.findall(r'["\']/_astro/', html)
    if remaining:
        print(f"[WARN] Aún quedan {len(remaining)} referencias a /_astro/ sin convertir.")
    else:
        print(f"[OK] inline_js.py completado ({original_len} -> {len(html)} bytes).")
        print("     No quedan referencias absolutas a /_astro/ en index.html.")


if __name__ == "__main__":
    main()