# Contribuir

> Cómo configurar htmlpress en local, proponer cambios y publicar una versión.

Htmlpress es un proyecto de código abierto y nos encantaría contar con tu ayuda, ya sea corrigiendo un bug, puliendo la documentación o proponiendo una nueva función. Esta guía recorre todo lo que necesitas para llevar un cambio desde tu editor hasta una versión publicada.

## Inicio rápido

Necesitarás [Node.js](https://nodejs.org/) 24+, [pnpm](https://pnpm.io/) 11+ y [rustup](https://rustup.rs/); para compilar el wheel de Python, [uv](https://docs.astral.sh/uv/). Después:

```
git clone https://github.com/datisthq/htmlpress.git
cd htmlpress
pnpm install
pnpm start
```

`pnpm install` también descarga los crates de Rust cuando `cargo` está en tu `PATH`. `pnpm start` ejecuta htmlpress desde el código fuente sobre las páginas de este sitio en `rust/docs/`, con recarga en vivo, para que puedas iterar sobre htmlpress mientras ves el resultado en tu navegador.

## Estructura del repositorio

```
htmlpress/
├── rust/                # the binary and the crates.io package `htmlpress`
│   ├── src/
│   │   ├── actions/     #   asset/escape + list, config/load, page/read + render, site/…
│   │   ├── commands/    #   the `build`, `start`, `preview`, `clear` and `escape` commands
│   │   ├── models/      #   Asset, Config, Page, Site, BuildOptions, Error
│   │   ├── components/  #   built-in components, compiled in, like styles/ and scripts/
│   │   ├── program.rs   #   the CLI
│   │   └── lib.rs       #   the library façade
│   ├── tests/           #   CLI integration tests
│   └── docs/            #   this site, HTML built by htmlpress itself
├── typescript/          # the npm package `gethtmlpress`: a shim that runs the binary
├── python/              # the PyPI package `htmlpress`: maturin binary wheels
├── .skills/             # shipped agent skills for people who use htmlpress
├── .agents/skills/      # repo skills for coding agents (see AGENTS.md)
├── .scripts/            # repo-wide guards and the `pnpm squash` script
└── htmlpress.yaml       # this site's htmlpress config
```

Todo el comportamiento vive en `rust/`. Los paquetes de npm y PyPI solo distribuyen el mismo binario, así que una función nunca se añade en un wrapper.

## Comandos locales

Ejecútalos en la raíz del repositorio; cada uno se encadena a las secciones con `pnpm -C <section>`.

| Comando            | Qué hace                                                                      |
| ------------------ | ----------------------------------------------------------------------------- |
| `pnpm start`       | Sirve el sitio de documentación desde el código fuente con recarga en vivo    |
| `pnpm build:docs`  | Compilación de producción del sitio de documentación                          |
| `pnpm build`       | Compila el binario de release, el shim de npm y el wheel de Python            |
| `pnpm check:types` | Comprobación de tipos con `tsgo --noEmit` y `cargo check`                     |
| `pnpm check:lint`  | Comprobación de formato + lint (`vp fmt`, `vp lint`, `cargo fmt`, `clippy`)   |
| `pnpm check`       | Lint + tipos                                                                  |
| `pnpm format`      | Corrige el formato automáticamente (`vp fmt`, `cargo fmt`)                    |
| `pnpm test:unit`   | Ejecuta las comprobaciones del repositorio, los tests del shim y `cargo test` |
| `pnpm test`        | Lint + tipos + unitarios                                                      |
| `pnpm scan`        | Análisis de secretos y vulnerabilidades (gitleaks, semgrep)                   |

Un cambio está listo para hacer push cuando `pnpm test` está en verde y `pnpm build:docs` funciona.

## Convenciones de código

- **Rust**: edición 2024 con la toolchain estable fijada, sin avisos de clippy y sin `unwrap`/`expect` fuera de los tests; tests unitarios junto al módulo como `<module>_unit.rs`; ejecuta uno con `cargo test <name>` desde `rust/`.
- **TypeScript**: el modo estricto está activado. No uses `any`, casts con `as` ni el `!` de no nulo sin permiso. Imports ESM completos con la extensión `.ts`; tests junto al módulo como `<module>.unit.ts`.
- **Comentarios**: documentación solo en elementos públicos. Un comentario debe nombrar el error que previene, no pasar de unas tres líneas, y los comentarios nunca superan al código; la justificación y la historia van en git.
- **Páginas de documentación**: HTML semántico y los componentes `htmlpress-*` documentados, sin estilos en línea.
- **Formato**: `pnpm format`. Sangría de 2 espacios, sin punto y coma, comillas dobles (LF, UTF-8); rustfmt a 90 columnas.

## Proponer un cambio

1. **Abre primero una issue** para cualquier cosa mayor que una errata o un bug pequeño. Es más fácil acordar la dirección antes del código.

2. **Crea una rama desde `main`** con un nombre corto y descriptivo (p. ej., `fix-fragment-title`, `feat-search`).

3. **Escribe un historial de commits enfocado**. Htmlpress usa [Conventional Commits](https://www.conventionalcommits.org/); el prefijo controla release-please:

   - `fix:` corrección de un bug en lo que recibe quien instala → versión de parche
   - `feat:` nueva función en lo que recibe quien instala → versión menor
   - `chore:`, `docs:`, `refactor:`, `test:`, `perf:` → sin versión; úsalos para CI, herramientas, dependencias, el sitio de documentación, las skills distribuidas y cualquier otra cosa que quien instala nunca ve
   - nunca marques un commit como breaking (`!` o un pie `BREAKING CHANGE:`)

4. **Ejecuta `pnpm test`** antes de hacer push.

5. **Abre un PR** contra `main`. Describe el *porqué* (enlaza la issue), incluye una captura de pantalla o la salida de la CLI para cualquier cambio visible, y señala todo aquello a lo que los revisores deban prestar especial atención.

## Versiones

Las versiones las gestiona [release-please](https://github.com/googleapis/release-please): un `feat` o `fix` que llega a `main` abre un Release PR, y al fusionarlo se genera la versión, se etiqueta, se compila el binario para cada plataforma y se publica en crates.io, npm y PyPI con una única versión compartida. Los mantenedores nunca suben versiones a mano; release-please mantiene `.release/manifest.json`.

## Dónde encontrar ayuda

- **Bugs y solicitudes de funciones**: [GitHub Issues](https://github.com/datisthq/htmlpress/issues)
- **Debate / ideas**: [GitHub Discussions](https://github.com/datisthq/htmlpress/discussions)
- **Código fuente**: [github.com/datisthq/htmlpress](https://github.com/datisthq/htmlpress)

Gracias por ayudar a mejorar htmlpress.
