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.
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/PKG-INFO +36 -21
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/README.md +35 -20
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/__init__.py +1 -1
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/logic.py +38 -18
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pyproject.toml +2 -2
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/LICENSE +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/__main__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/args.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/cli/report.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/atomic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/batch.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/config.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/errors.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/jobs.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/logger.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/naming.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/plugin.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/registry.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/thumbnails.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/core/updater.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/main.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/compress/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/logic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/images2pdf/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/logic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/merge/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/logic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/protect/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/logic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/split/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/logic.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/panel.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/params.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/tools/watermark/spec.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/__init__.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/accessibility.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/app.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/errors.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/file_list.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/logs.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/output_dir.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/panel_base.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/platform.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/registry.py +0 -0
- {pdf_tool_cli-1.1.0 → pdf_tool_cli-1.1.1}/pdftool/ui/theme.py +0 -0
- {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.
|
|
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
|
-
**
|
|
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"
|
|
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
|
[](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml)
|
|
44
45
|
[](https://github.com/juanMaAV92/pdf-tool/releases/latest)
|
|
45
|
-
[](https://pypi.org/project/pdf-tool-cli/)
|
|
47
|
+
[](https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE)
|
|
46
48
|

|
|
47
49
|
|
|
48
50
|
</div>
|
|
49
51
|
|
|
50
|
-
<!-- 📸 Añade aquí un screenshot o GIF de la app:
|
|
51
|
-

|
|
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
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
122
|
-
está lo que viene: una
|
|
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
|
|
149
|
-
git push origin
|
|
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
|
|
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
|
|
169
|
-
poetry run flet 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
|
-
**
|
|
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"
|
|
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
|
[](https://github.com/juanMaAV92/pdf-tool/actions/workflows/ci.yml)
|
|
15
16
|
[](https://github.com/juanMaAV92/pdf-tool/releases/latest)
|
|
16
|
-
[](https://pypi.org/project/pdf-tool-cli/)
|
|
18
|
+
[](https://github.com/juanMaAV92/pdf-tool/blob/main/LICENSE)
|
|
17
19
|

|
|
18
20
|
|
|
19
21
|
</div>
|
|
20
22
|
|
|
21
|
-
<!-- 📸 Añade aquí un screenshot o GIF de la app:
|
|
22
|
-

|
|
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
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
93
|
-
está lo que viene: una
|
|
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
|
|
120
|
-
git push origin
|
|
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
|
|
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
|
|
140
|
-
poetry run flet 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>
|
|
@@ -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 =
|
|
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 +
|
|
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.
|
|
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 = "
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|