pdf-tool-cli 1.1.0__tar.gz → 1.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/PKG-INFO +36 -21
  2. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/README.md +35 -20
  3. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/__init__.py +1 -1
  4. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/logic.py +38 -18
  5. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pyproject.toml +2 -2
  6. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/LICENSE +0 -0
  7. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/__init__.py +0 -0
  8. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/__main__.py +0 -0
  9. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/args.py +0 -0
  10. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/report.py +0 -0
  11. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/__init__.py +0 -0
  12. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/atomic.py +0 -0
  13. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/batch.py +0 -0
  14. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/config.py +0 -0
  15. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/errors.py +0 -0
  16. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/jobs.py +0 -0
  17. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/logger.py +0 -0
  18. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/naming.py +0 -0
  19. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/plugin.py +0 -0
  20. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/registry.py +0 -0
  21. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/thumbnails.py +0 -0
  22. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/updater.py +0 -0
  23. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/main.py +0 -0
  24. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/__init__.py +0 -0
  25. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/__init__.py +0 -0
  26. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/panel.py +0 -0
  27. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/params.py +0 -0
  28. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/spec.py +0 -0
  29. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/__init__.py +0 -0
  30. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/logic.py +0 -0
  31. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/panel.py +0 -0
  32. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/params.py +0 -0
  33. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/spec.py +0 -0
  34. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/__init__.py +0 -0
  35. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/logic.py +0 -0
  36. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/panel.py +0 -0
  37. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/params.py +0 -0
  38. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/spec.py +0 -0
  39. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/__init__.py +0 -0
  40. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/logic.py +0 -0
  41. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/panel.py +0 -0
  42. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/params.py +0 -0
  43. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/spec.py +0 -0
  44. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/__init__.py +0 -0
  45. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/logic.py +0 -0
  46. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/panel.py +0 -0
  47. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/params.py +0 -0
  48. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/spec.py +0 -0
  49. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/__init__.py +0 -0
  50. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/logic.py +0 -0
  51. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/panel.py +0 -0
  52. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/params.py +0 -0
  53. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/spec.py +0 -0
  54. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/__init__.py +0 -0
  55. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/accessibility.py +0 -0
  56. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/app.py +0 -0
  57. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/errors.py +0 -0
  58. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/file_list.py +0 -0
  59. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/logs.py +0 -0
  60. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/output_dir.py +0 -0
  61. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/panel_base.py +0 -0
  62. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/platform.py +0 -0
  63. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/registry.py +0 -0
  64. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/theme.py +0 -0
  65. {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/thumbnails.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdf-tool-cli
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: Herramientas PDF (unir, dividir, comprimir, proteger…) como CLI para agentes y app de escritorio.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -31,9 +31,10 @@ Description-Content-Type: text/markdown
31
31
 
32
32
  # 📄 PDF Tool
33
33
 
34
- **Una app de escritorio sencilla para trabajar con tus PDFs — sin subir nada a internet.**
34
+ **Herramientas para tus PDFs — sin subir nada a internet. Como app de escritorio
35
+ o como comando para agentes de IA y scripts.**
35
36
 
36
- <img width="980" height="680" alt="Screenshot 2026-06-15 at 6 54 49 PM" src="https://github.com/user-attachments/assets/adf416d8-bb05-478d-8a6d-31a35410af28" />
37
+ <img width="980" alt="pdf-tool: pantalla de inicio con las seis herramientas" src="https://raw.githubusercontent.com/juanMaAV92/pdf-tool/main/docs/screenshot.png" />
37
38
 
38
39
  Comprime, une, divide, protege y marca tus documentos —y conviértelos desde imágenes—
39
40
  desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
@@ -42,15 +43,12 @@ desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
42
43
 
43
44
  [![CI](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml/badge.svg)](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml)
44
45
  [![Release](https://img.shields.io/github/v/release/juanMaAV92/pdf-tool?label=versión)](https://github.com/juanMaAV92/pdf-tool/releases/latest)
45
- [![License: MIT](https://img.shields.io/badge/Licencia-MIT-blue.svg)](LICENSE)
46
+ [![PyPI](https://img.shields.io/pypi/v/pdf-tool-cli?label=PyPI)](https://pypi.org/project/pdf-tool-cli/)
47
+ [![License: MIT](https://img.shields.io/badge/Licencia-MIT-blue.svg)](https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE)
46
48
  ![Platform](https://img.shields.io/badge/macOS_·_Windows-lightgrey)
47
49
 
48
50
  </div>
49
51
 
50
- <!-- 📸 Añade aquí un screenshot o GIF de la app:
51
- ![PDF Tool](docs/screenshot.png)
52
- Es lo que más convence a quien entra al repo. -->
53
-
54
52
  ---
55
53
 
56
54
  ## ✨ Qué puedes hacer
@@ -66,9 +64,10 @@ desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
66
64
 
67
65
  > 🔐 **Todo ocurre en tu equipo.** Tus archivos nunca salen de tu ordenador.
68
66
 
69
- En **Comprimir PDF**, el modo predeterminado busca la reducción máxima. También
70
- puedes elegir **Conservar texto y enlaces** desde el selector de modo; el icono
71
- de ayuda explica la diferencia.
67
+ En **Comprimir PDF**, el modo predeterminado busca la reducción máxima: primero
68
+ reduce las imágenes y, solo si no basta, convierte páginas en imagen (lo avisa,
69
+ porque se pierde el texto seleccionable). Con **Conservar texto y enlaces** nunca
70
+ lo hace; el icono de ayuda explica la diferencia.
72
71
 
73
72
  ---
74
73
 
@@ -112,14 +111,26 @@ Cada herramienta tiene su ayuda (`pdf-tool compress --help`). Códigos de salida
112
111
  `0` ok · `1` error al procesar · `2` uso inválido · `3` algún archivo del lote falló.
113
112
  `pipx install 'pdf-tool-cli[gui]'` instala además la app (comando `pdftool`).
114
113
 
114
+ ### Plugin para Claude Code
115
+
116
+ Una [skill](https://github.com/juanMaAV92/pdf-tool/blob/main/skills/pdf-tool/SKILL.md)
117
+ le enseña a Claude Code a usar `pdf-tool` para crear o modificar PDFs en lugar de
118
+ escribir scripts: pide permiso antes de instalar la CLI, ejecuta las herramientas
119
+ con `--json` y te explica el resultado. Para instalarla, dentro de Claude Code:
120
+
121
+ ```text
122
+ /plugin marketplace add juanMaAV92/pdf-tool
123
+ /plugin install pdf-tool@pdf-tool
124
+ ```
125
+
115
126
  ---
116
127
 
117
128
  ## 🤝 Contribuir
118
129
 
119
130
  ¡Las contribuciones son bienvenidas! Puedes abrir un *issue* con ideas o errores,
120
131
  o mandar un *pull request*. La arquitectura es modular: añadir una herramienta nueva
121
- es crear una carpeta y la app la descubre sola. En el [roadmap](docs/roadmap.md)
122
- está lo que viene: una CLI para agentes de IA, a la par con la app.
132
+ es crear una carpeta y la app y la CLI la descubren solas. En el [roadmap](https://github.com/juanMaAV92/pdf-tool/blob/main/docs/roadmap.md)
133
+ está lo que viene: una skill para que los agentes de IA usen la CLI.
123
134
 
124
135
  <details>
125
136
  <summary><b>🛠️ Para desarrolladores (montar el proyecto en local)</b></summary>
@@ -141,39 +152,43 @@ poetry run pytest # corre los tests
141
152
  las dos automáticamente.
142
153
 
143
154
  La **lógica** (`logic.py`) no importa Flet y se prueba sin UI; la **UI** (`panel.py`)
144
- solo arma controles. Detalles en [AGENTS.md](AGENTS.md).
155
+ solo arma controles. Detalles en [AGENTS.md](https://github.com/juanMaAV92/pdf-tool/blob/main/AGENTS.md).
145
156
 
146
157
  ### Publicar una versión (automatizado con GitHub Actions)
147
158
  ```bash
148
- git tag v0.2.0
149
- git push origin v0.2.0
159
+ git tag vX.Y.Z
160
+ git push origin vX.Y.Z
150
161
  ```
151
162
  Eso dispara `release.yml`, que corre los tests, construye macOS (`.dmg`) y Windows
152
163
  (instalador Inno Setup) en paralelo, hornea la versión del tag en el build y crea
153
164
  un **GitHub Release en borrador** con ambos instaladores. Revísalo y pulsa
154
165
  **Publish release** para que las apps instaladas detecten la actualización.
155
166
  Si los instaladores se construyen bien, publica también el paquete en **PyPI**
156
- (Trusted Publishing, entorno `pypi` de GitHub; sin tokens).
167
+ (`pdf-tool-cli`, por Trusted Publishing y sin tokens). Ese paso espera a que lo
168
+ apruebes en Actions (entorno `pypi`), porque una versión en PyPI no se puede
169
+ reemplazar.
157
170
 
158
171
  Los PRs que cambian la app, el empaquetado o sus dependencias ejecutan además
159
172
  **Package smoke**: construye e inspecciona el DMG de macOS y compila e instala de
160
173
  forma silenciosa el instalador de Windows. Antes de una release importante,
161
- seguir la [checklist manual](docs/release-smoke.md) para validar la ventana y los
174
+ seguir la [checklist manual](https://github.com/juanMaAV92/pdf-tool/blob/main/docs/release-smoke.md) para validar la ventana y los
162
175
  diálogos nativos.
163
176
 
164
177
  El número de versión es **el tag** — única fuente de verdad.
165
178
 
166
179
  ### Build local (para depurar el empaquetado)
167
180
  ```bash
168
- poetry run flet build macos # -> build/macos/pdf-tool.app
169
- poetry run flet build windows # -> build/windows/
181
+ poetry run flet build macos --project pdf-tool --product pdf-tool # -> build/macos/pdf-tool.app
182
+ poetry run flet build windows --project pdf-tool --product pdf-tool # -> build/windows/
170
183
  ```
184
+ `--project pdf-tool` es obligatorio: sin él, `flet build` toma el nombre del
185
+ paquete (`pdf-tool-cli`) y la app cambia de identidad.
171
186
 
172
187
  </details>
173
188
 
174
189
  ---
175
190
 
176
191
  <div align="center">
177
- <sub>Hecho con 🐍 Python + <a href="https://flet.dev">Flet</a> · Licencia <a href="LICENSE">MIT</a></sub>
192
+ <sub>Hecho con 🐍 Python + <a href="https://flet.dev">Flet</a> · Licencia <a href="https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE">MIT</a></sub>
178
193
  </div>
179
194
 
@@ -2,9 +2,10 @@
2
2
 
3
3
  # 📄 PDF Tool
4
4
 
5
- **Una app de escritorio sencilla para trabajar con tus PDFs — sin subir nada a internet.**
5
+ **Herramientas para tus PDFs — sin subir nada a internet. Como app de escritorio
6
+ o como comando para agentes de IA y scripts.**
6
7
 
7
- <img width="980" height="680" alt="Screenshot 2026-06-15 at 6 54 49 PM" src="https://github.com/user-attachments/assets/adf416d8-bb05-478d-8a6d-31a35410af28" />
8
+ <img width="980" alt="pdf-tool: pantalla de inicio con las seis herramientas" src="https://raw.githubusercontent.com/juanMaAV92/pdf-tool/main/docs/screenshot.png" />
8
9
 
9
10
  Comprime, une, divide, protege y marca tus documentos —y conviértelos desde imágenes—
10
11
  desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
@@ -13,15 +14,12 @@ desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
13
14
 
14
15
  [![CI](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml/badge.svg)](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml)
15
16
  [![Release](https://img.shields.io/github/v/release/juanMaAV92/pdf-tool?label=versión)](https://github.com/juanMaAV92/pdf-tool/releases/latest)
16
- [![License: MIT](https://img.shields.io/badge/Licencia-MIT-blue.svg)](LICENSE)
17
+ [![PyPI](https://img.shields.io/pypi/v/pdf-tool-cli?label=PyPI)](https://pypi.org/project/pdf-tool-cli/)
18
+ [![License: MIT](https://img.shields.io/badge/Licencia-MIT-blue.svg)](https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE)
17
19
  ![Platform](https://img.shields.io/badge/macOS_·_Windows-lightgrey)
18
20
 
19
21
  </div>
20
22
 
21
- <!-- 📸 Añade aquí un screenshot o GIF de la app:
22
- ![PDF Tool](docs/screenshot.png)
23
- Es lo que más convence a quien entra al repo. -->
24
-
25
23
  ---
26
24
 
27
25
  ## ✨ Qué puedes hacer
@@ -37,9 +35,10 @@ desde tu propio ordenador. Gratis, de código abierto y sin anuncios.
37
35
 
38
36
  > 🔐 **Todo ocurre en tu equipo.** Tus archivos nunca salen de tu ordenador.
39
37
 
40
- En **Comprimir PDF**, el modo predeterminado busca la reducción máxima. También
41
- puedes elegir **Conservar texto y enlaces** desde el selector de modo; el icono
42
- de ayuda explica la diferencia.
38
+ En **Comprimir PDF**, el modo predeterminado busca la reducción máxima: primero
39
+ reduce las imágenes y, solo si no basta, convierte páginas en imagen (lo avisa,
40
+ porque se pierde el texto seleccionable). Con **Conservar texto y enlaces** nunca
41
+ lo hace; el icono de ayuda explica la diferencia.
43
42
 
44
43
  ---
45
44
 
@@ -83,14 +82,26 @@ Cada herramienta tiene su ayuda (`pdf-tool compress --help`). Códigos de salida
83
82
  `0` ok · `1` error al procesar · `2` uso inválido · `3` algún archivo del lote falló.
84
83
  `pipx install 'pdf-tool-cli[gui]'` instala además la app (comando `pdftool`).
85
84
 
85
+ ### Plugin para Claude Code
86
+
87
+ Una [skill](https://github.com/juanMaAV92/pdf-tool/blob/main/skills/pdf-tool/SKILL.md)
88
+ le enseña a Claude Code a usar `pdf-tool` para crear o modificar PDFs en lugar de
89
+ escribir scripts: pide permiso antes de instalar la CLI, ejecuta las herramientas
90
+ con `--json` y te explica el resultado. Para instalarla, dentro de Claude Code:
91
+
92
+ ```text
93
+ /plugin marketplace add juanMaAV92/pdf-tool
94
+ /plugin install pdf-tool@pdf-tool
95
+ ```
96
+
86
97
  ---
87
98
 
88
99
  ## 🤝 Contribuir
89
100
 
90
101
  ¡Las contribuciones son bienvenidas! Puedes abrir un *issue* con ideas o errores,
91
102
  o mandar un *pull request*. La arquitectura es modular: añadir una herramienta nueva
92
- es crear una carpeta y la app la descubre sola. En el [roadmap](docs/roadmap.md)
93
- está lo que viene: una CLI para agentes de IA, a la par con la app.
103
+ es crear una carpeta y la app y la CLI la descubren solas. En el [roadmap](https://github.com/juanMaAV92/pdf-tool/blob/main/docs/roadmap.md)
104
+ está lo que viene: una skill para que los agentes de IA usen la CLI.
94
105
 
95
106
  <details>
96
107
  <summary><b>🛠️ Para desarrolladores (montar el proyecto en local)</b></summary>
@@ -112,38 +123,42 @@ poetry run pytest # corre los tests
112
123
  las dos automáticamente.
113
124
 
114
125
  La **lógica** (`logic.py`) no importa Flet y se prueba sin UI; la **UI** (`panel.py`)
115
- solo arma controles. Detalles en [AGENTS.md](AGENTS.md).
126
+ solo arma controles. Detalles en [AGENTS.md](https://github.com/juanMaAV92/pdf-tool/blob/main/AGENTS.md).
116
127
 
117
128
  ### Publicar una versión (automatizado con GitHub Actions)
118
129
  ```bash
119
- git tag v0.2.0
120
- git push origin v0.2.0
130
+ git tag vX.Y.Z
131
+ git push origin vX.Y.Z
121
132
  ```
122
133
  Eso dispara `release.yml`, que corre los tests, construye macOS (`.dmg`) y Windows
123
134
  (instalador Inno Setup) en paralelo, hornea la versión del tag en el build y crea
124
135
  un **GitHub Release en borrador** con ambos instaladores. Revísalo y pulsa
125
136
  **Publish release** para que las apps instaladas detecten la actualización.
126
137
  Si los instaladores se construyen bien, publica también el paquete en **PyPI**
127
- (Trusted Publishing, entorno `pypi` de GitHub; sin tokens).
138
+ (`pdf-tool-cli`, por Trusted Publishing y sin tokens). Ese paso espera a que lo
139
+ apruebes en Actions (entorno `pypi`), porque una versión en PyPI no se puede
140
+ reemplazar.
128
141
 
129
142
  Los PRs que cambian la app, el empaquetado o sus dependencias ejecutan además
130
143
  **Package smoke**: construye e inspecciona el DMG de macOS y compila e instala de
131
144
  forma silenciosa el instalador de Windows. Antes de una release importante,
132
- seguir la [checklist manual](docs/release-smoke.md) para validar la ventana y los
145
+ seguir la [checklist manual](https://github.com/juanMaAV92/pdf-tool/blob/main/docs/release-smoke.md) para validar la ventana y los
133
146
  diálogos nativos.
134
147
 
135
148
  El número de versión es **el tag** — única fuente de verdad.
136
149
 
137
150
  ### Build local (para depurar el empaquetado)
138
151
  ```bash
139
- poetry run flet build macos # -> build/macos/pdf-tool.app
140
- poetry run flet build windows # -> build/windows/
152
+ poetry run flet build macos --project pdf-tool --product pdf-tool # -> build/macos/pdf-tool.app
153
+ poetry run flet build windows --project pdf-tool --product pdf-tool # -> build/windows/
141
154
  ```
155
+ `--project pdf-tool` es obligatorio: sin él, `flet build` toma el nombre del
156
+ paquete (`pdf-tool-cli`) y la app cambia de identidad.
142
157
 
143
158
  </details>
144
159
 
145
160
  ---
146
161
 
147
162
  <div align="center">
148
- <sub>Hecho con 🐍 Python + <a href="https://flet.dev">Flet</a> · Licencia <a href="LICENSE">MIT</a></sub>
163
+ <sub>Hecho con 🐍 Python + <a href="https://flet.dev">Flet</a> · Licencia <a href="https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE">MIT</a></sub>
149
164
  </div>
@@ -1,3 +1,3 @@
1
1
  # La versión real la hornea CI desde el tag git al construir el release
2
2
  # (ver .github/workflows/release.yml). En desarrollo local queda como dev.
3
- __version__ = "1.1.0"
3
+ __version__ = "1.1.1"
@@ -232,6 +232,31 @@ def _saved_label(original: float, final: float) -> str:
232
232
  return f" · {saved:.0f} % menos" if saved >= 0.5 else ""
233
233
 
234
234
 
235
+ def _reduce_images(
236
+ candidates: _Candidates,
237
+ src: Path,
238
+ target_mb: float,
239
+ progress: Progress,
240
+ span: float,
241
+ ) -> bool:
242
+ """Prueba a recomprimir solo las imágenes. True si alcanzó el objetivo."""
243
+ n = len(_PRESERVE_ATTEMPTS)
244
+ for i, attempt in enumerate(_PRESERVE_ATTEMPTS):
245
+ progress(0.1 + span * i / n, f"Reduciendo imágenes (paso {i + 1} de {n})…")
246
+ size = candidates.attempt(
247
+ partial(
248
+ _preserve_compress,
249
+ src,
250
+ dpi_threshold=attempt["dpi_threshold"],
251
+ dpi_target=attempt["dpi_target"],
252
+ quality=attempt["quality"],
253
+ )
254
+ )
255
+ if size <= target_mb:
256
+ return True
257
+ return False
258
+
259
+
235
260
  def _compress_one(
236
261
  input_path: Path,
237
262
  out: Path,
@@ -243,6 +268,9 @@ def _compress_one(
243
268
  progress(0.0, f"Tamaño original: {original:.2f} MB")
244
269
 
245
270
  if original <= target_mb:
271
+ # Abrirlo antes de copiar: un archivo dañado o que no es PDF debe
272
+ # fallar aquí, no reportarse como «sin cambios».
273
+ pymupdf.open(str(input_path)).close()
246
274
  atomic_copy(input_path, out)
247
275
  progress(1.0, "Ya está bajo el objetivo")
248
276
  return _Compressed(
@@ -275,38 +303,30 @@ def _compress_one(
275
303
  ):
276
304
  return publish()
277
305
 
306
+ # Primero se recomprimen solo las imágenes: conserva texto y enlaces y,
307
+ # con fotos de mucha resolución, suele dar el archivo más pequeño.
308
+ span = 0.9 if mode == "preserve" else 0.2
309
+ if _reduce_images(candidates, input_path, target_mb, progress, span):
310
+ return publish(" (contenido preservado)")
278
311
  if mode == "preserve":
279
- n = len(_PRESERVE_ATTEMPTS)
280
- for i, attempt in enumerate(_PRESERVE_ATTEMPTS):
281
- progress(
282
- 0.1 + 0.9 * i / n, f"Reduciendo imágenes (paso {i + 1} de {n})…"
283
- )
284
- size = candidates.attempt(
285
- partial(
286
- _preserve_compress,
287
- input_path,
288
- dpi_threshold=attempt["dpi_threshold"],
289
- dpi_target=attempt["dpi_target"],
290
- quality=attempt["quality"],
291
- )
292
- )
293
- if size <= target_mb:
294
- return publish(" (contenido preservado)")
295
312
  return publish(
296
313
  " (no se alcanzó el objetivo; se guardó la versión más pequeña "
297
314
  "con el contenido preservado)"
298
315
  )
299
316
 
317
+ # `max`: si no bastó, convertir páginas en imagen. Gana el intento más
318
+ # pequeño de todos, también si fue uno de los anteriores.
319
+ start = 0.1 + span
300
320
  n = len(_ATTEMPTS)
301
321
  for i, attempt in enumerate(_ATTEMPTS):
302
- base = 0.1 + 0.9 * i / n
322
+ base = start + (1 - start) * i / n
303
323
  step = f"Reduciendo calidad (paso {i + 1} de {n})"
304
324
  progress(base, f"{step}…")
305
325
 
306
326
  def step_progress(
307
327
  pct: float, msg: str, _base: float = base, _step: str = step
308
328
  ) -> None:
309
- progress(_base + 0.9 / n * pct, f"{_step}: {msg}")
329
+ progress(_base + (1 - start) / n * pct, f"{_step}: {msg}")
310
330
 
311
331
  size = candidates.attempt(
312
332
  partial(
@@ -2,7 +2,7 @@
2
2
  # Nombre en PyPI: «pdf-tool» choca con «pdftool» (ya existe). El comando sigue
3
3
  # siendo `pdf-tool` y la app conserva su identidad con `flet build --project`.
4
4
  name = "pdf-tool-cli"
5
- version = "1.1.0"
5
+ version = "1.1.1"
6
6
  description = "Herramientas PDF (unir, dividir, comprimir, proteger…) como CLI para agentes y app de escritorio."
7
7
  authors = ["Juan Manuel Armero <juanmanuel.armero@gmail.com>"]
8
8
  license = "MIT"
@@ -35,7 +35,7 @@ gui = ["flet"]
35
35
 
36
36
  [tool.poetry.group.dev.dependencies]
37
37
  pytest = "^9.0.3"
38
- ruff = "^0.16.8"
38
+ ruff = ">=0.16.8,<0.18.0"
39
39
  mypy = "^2.3.1"
40
40
  pytest-cov = "^7.1.0"
41
41
  # flet lo instala solo al primer `flet build`; declararlo deja el entorno
File without changes