Cómo migrar de MuPDF a IronPDF en C#
Por qué migrar de MuPDFa IronPDF
Los retos de MuPDF
MuPDF es un excelente renderizador de PDF, pero su licencia AGPL y su enfoque exclusivo de renderización crean limitaciones significativas para los desarrolladores .NET que crean aplicaciones comerciales:
-
La trampa de la licencia AGPL: la licencia viral de MuPDFrequiere que la aplicación completa se publique en código abierto bajo AGPL o que se compren licencias comerciales costosas con precios opacos y de venta por contacto.
-
Enfoque solo en la representación: MuPDFes un visualizador/representador; no está diseñado para la creación de PDF a partir de HTML, flujos de trabajo de generación de documentos, llenado de formularios o adición de marcas de agua y encabezados/pies de página.
-
No admite HTML: MuPDFno admite la conversión directa de HTML a PDF. En primer lugar, tendrás que utilizar otra biblioteca para convertir HTML a un formato compatible. Esta es una limitación fundamental: MuPDFes principalmente un renderizador/visualizador de PDF.
-
Dependencias nativas: los binarios específicos de la plataforma requieren administración manual para Windows, Linux y macOS. Los despliegues de Docker se vuelven complejos con los requisitos de las bibliotecas nativas, y el empaquetado del despliegue introduce desafíos.
-
Manipulación limitada: no hay soporte integrado para fusionar o dividir archivos PDF, rotación o reordenamiento de páginas, marcas de agua o anotaciones, o firmas digitales.
- Complejidad de interoperabilidad de C: los enlaces nativos introducen problemas de gestión de memoria, errores específicos de la plataforma y sobrecarga de serialización.
Comparación entre MuPDFe IronPDF
| Característica | MuPDF | IronPDF |
|---|---|---|
| Licencia | AGPL (viral) o comercial caro | Comercial con precios transparentes |
| Enfoque principal | Renderización/visualización | Solución PDF completa |
| HTML a PDF | No soportado | Motor Chromium completo |
| Creación de PDF | No soportado | HTML, URL, imágenes |
| Manipulación de PDF | Limitado | Completar (combinar, dividir, editar) |
| Dependencias | Binarios nativos | Totalmente gestionado |
| Soporte de plataformas | Manual por plataforma | Automático |
| Soporte de Async | Limitado | Async/await completo |
| Integración .NET | Interoperabilidad de C | .NET nativo |
Para los equipos que planifican la adopción de .NET 10 y C# 14 hasta 2025 y 2026,IronPDFproporciona una base a prueba de futuro como biblioteca .NET totalmente gestionada sin complejidad de interoperabilidad nativa.
Evaluación de la complejidad de la migración
Esfuerzo estimado por función
| Característica | Complejidad de la migración |
|---|---|
| Carga del documento | Muy bajo |
| Extracción de Texto | Muy bajo |
| Fusión de PDF | Bajo |
| Reproducción de imágenes | Bajo |
| HTML a PDF | N/A (Nueva capacidad) |
| Seguridad/marcas de agua | N/A (Nueva capacidad) |
Cambio de paradigma
El cambio fundamental en esta migración de MuPDFes pasar de un visualizador solo de renderizado a una solución PDF completa:
MuPDF: MuPDFContext → MuPDFDocument → Iteración de páginas → Sólo renderizar/extraer
IronPDF: PdfDocument.FromFile() → Manipulación completa → Crear/Editar/Fusionar/Seguro
Antes de empezar
Prerrequisitos
- Entorno .NET : .NET Framework 4.6.2+ o .NET Core 3.1+ / .NET 5/6/7/8/9+
- Acceso a NuGet : Capacidad para instalar paquetes NuGet
- Licencia deIronPDF: Obtenga su clave de licencia en IronPDF
Cambios en el paquete NuGet
# Remove MuPDFpackages
dotnet remove package MuPDF.NET
dotnet remove package MuPDFCore
dotnet remove package MuPDFCore.MuPDFWrapper
# Install IronPDF
dotnet add package IronPdf
# Remove MuPDFpackages
dotnet remove package MuPDF.NET
dotnet remove package MuPDFCore
dotnet remove package MuPDFCore.MuPDFWrapper
# Install IronPDF
dotnet add package IronPdf
También elimine los binarios nativos de MuPDF de su implementación:
- Eliminar
mupdf.dll,libmupdf.so,libmupdf.dylib - Eliminar carpetas específicas de la plataforma (
runtimes/*/native/) - Actualizar los archivos Docker para eliminar la instalación de MuPDF
Configuración de licencias
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Identificar el uso de MuPDF
# Find all MuPDFreferences
grep -r "MuPDF\|MuPDFCore\|MuPDFDocument" --include="*.cs" .
# Find all MuPDFreferences
grep -r "MuPDF\|MuPDFCore\|MuPDFDocument" --include="*.cs" .
Referencia completa de la API
Carga del documento
| MuPDF | IronPDF |
|---|---|
new MuPDFDocument(path) |
PdfDocument.FromFile(path) |
new MuPDFDocument(stream) |
PdfDocument.FromStream(stream) |
document.Dispose() |
pdf.Dispose() |
Acceso a la página
| MuPDF | IronPDF |
|---|---|
document.Pages.Count |
pdf.PageCount |
document.Pages[index] |
pdf.Pages[index] |
page.GetText() |
page.Text |
Extracción de texto
| MuPDF | IronPDF |
|---|---|
Recorrer document.Pages[i].GetText() |
pdf.ExtractAllText() |
Creación de PDF (no disponible en MuPDF)
| MuPDF | IronPDF |
|---|---|
| (no compatible) | ChromePdfRenderer.RenderHtmlAsPdf(html) |
| (no compatible) | ChromePdfRenderer.RenderUrlAsPdf(url) |
Manipulación de PDF (limitada en MuPDF)
| MuPDF | IronPDF |
|---|---|
| Bucles de copia de página manual | PdfDocument.Merge(pdf1, pdf2) |
| (no compatible) | pdf.ApplyWatermark(html) |
| (no compatible) | pdf.SecuritySettings |
Ejemplos de migración de código
Ejemplo 1: Conversión de HTML a PDF (MuPDF no puede hacer esto)
Antes (MuPDF):
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System.IO;
class Program
{
static void Main()
{
// MuPDFdoesn't support HTML a PDFconversion directly
// You would need to use another library to convert HTML to a supported format first
// This is a limitation - MuPDFis primarily a PDF renderer/viewer
// Alternative: Use a browser engine or intermediate conversion
string html = "<html><body><h1>Hello World</h1></body></html>";
// Not natively supported in MuPDF
throw new NotSupportedException("MuPDF does not support direct HTML a PDFconversion");
}
}
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System.IO;
class Program
{
static void Main()
{
// MuPDFdoesn't support HTML a PDFconversion directly
// You would need to use another library to convert HTML to a supported format first
// This is a limitation - MuPDFis primarily a PDF renderer/viewer
// Alternative: Use a browser engine or intermediate conversion
string html = "<html><body><h1>Hello World</h1></body></html>";
// Not natively supported in MuPDF
throw new NotSupportedException("MuPDF does not support direct HTML a PDFconversion");
}
}
Imports MuPDFCore
Imports System.IO
Class Program
Shared Sub Main()
' MuPDF doesn't support HTML to PDF conversion directly
' You would need to use another library to convert HTML to a supported format first
' This is a limitation - MuPDF is primarily a PDF renderer/viewer
' Alternative: Use a browser engine or intermediate conversion
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
' Not natively supported in MuPDF
Throw New NotSupportedException("MuPDF does not support direct HTML to PDF conversion")
End Sub
End Class
Después (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
Este ejemplo pone de manifiesto la limitación más importante de MuPDF: no puede convertir HTML a PDF en absoluto. El código MuPDFlanza explícitamente NotSupportedException porque la conversión de HTML a PDF simplemente no es una capacidad que MuPDFproporciona. Si necesitaba esta funcionalidad con MuPDF, tenía que utilizar una biblioteca independiente como wkhtmltopdf o un motor de navegador y, a continuación, cargar el PDF resultante con MuPDFpara su visualización.
ChromePdfRenderer deIronPDFutiliza un motor Chromium completo para renderizar HTML con soporte completo para CSS3, JavaScript y estándares web modernos. El método RenderHtmlAsPdf() acepta cadenas HTML directamente. Consulte la documentación HTML a PDF para conocer otras opciones de conversión, como la conversión de URL y de archivos HTML.
Ejemplo 2: Extracción de texto
Antes (MuPDF):
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System;
using System.Text;
class Program
{
static void Main()
{
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
{
StringBuilder allText = new StringBuilder();
for (int i = 0; i < document.Pages.Count; i++)
{
string pageText = document.Pages[i].GetText();
allText.AppendLine(pageText);
}
Console.WriteLine(allText.ToString());
}
}
}
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System;
using System.Text;
class Program
{
static void Main()
{
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
{
StringBuilder allText = new StringBuilder();
for (int i = 0; i < document.Pages.Count; i++)
{
string pageText = document.Pages[i].GetText();
allText.AppendLine(pageText);
}
Console.WriteLine(allText.ToString());
}
}
}
Imports MuPDFCore
Imports System
Imports System.Text
Class Program
Shared Sub Main()
Using document As New MuPDFDocument("input.pdf")
Dim allText As New StringBuilder()
For i As Integer = 0 To document.Pages.Count - 1
Dim pageText As String = document.Pages(i).GetText()
allText.AppendLine(pageText)
Next
Console.WriteLine(allText.ToString())
End Using
End Sub
End Class
Después (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("input.pdf");
string text = pdf.ExtractAllText();
Console.WriteLine(text);
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("input.pdf");
string text = pdf.ExtractAllText();
Console.WriteLine(text);
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim pdf = PdfDocument.FromFile("input.pdf")
Dim text As String = pdf.ExtractAllText()
Console.WriteLine(text)
End Sub
End Class
El enfoque de MuPDFrequiere crear un bloque using con un MuPDFDocument, iterar manualmente a través de document.Pages.Count con un bucle for, llamar a document.Pages[i].GetText() para cada página y construir el texto con un StringBuilder. Se trata de 12 líneas de código para una simple extracción de texto.
IronPDF reduce esto a 3 líneas: carga el documento con PdfDocument.FromFile(), llama a ExtractAllText() e imprime el resultado. Sin iteración manual, sin StringBuilder, sin gestión explícita de recursos con bloques using para esta sencilla operación. Obtenga más información sobre la extracción de texto de archivos PDF .
Ejemplo 3: Fusión de varios PDF
Antes (MuPDF):
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System.IO;
class Program
{
static void Main()
{
using (MuPDFDocument doc1 = new MuPDFDocument("file1.pdf"))
using (MuPDFDocument doc2 = new MuPDFDocument("file2.pdf"))
{
// Create a new document
using (MuPDFDocument mergedDoc = MuPDFDocument.Create())
{
// Copy pages from first document
for (int i = 0; i < doc1.Pages.Count; i++)
{
mergedDoc.CopyPage(doc1, i);
}
// Copy pages from second document
for (int i = 0; i < doc2.Pages.Count; i++)
{
mergedDoc.CopyPage(doc2, i);
}
mergedDoc.Save("merged.pdf");
}
}
}
}
// NuGet: Install-Package MuPDF.NET
using MuPDFCore;
using System.IO;
class Program
{
static void Main()
{
using (MuPDFDocument doc1 = new MuPDFDocument("file1.pdf"))
using (MuPDFDocument doc2 = new MuPDFDocument("file2.pdf"))
{
// Create a new document
using (MuPDFDocument mergedDoc = MuPDFDocument.Create())
{
// Copy pages from first document
for (int i = 0; i < doc1.Pages.Count; i++)
{
mergedDoc.CopyPage(doc1, i);
}
// Copy pages from second document
for (int i = 0; i < doc2.Pages.Count; i++)
{
mergedDoc.CopyPage(doc2, i);
}
mergedDoc.Save("merged.pdf");
}
}
}
}
Imports MuPDFCore
Imports System.IO
Class Program
Shared Sub Main()
Using doc1 As New MuPDFDocument("file1.pdf"),
doc2 As New MuPDFDocument("file2.pdf")
' Create a new document
Using mergedDoc As MuPDFDocument = MuPDFDocument.Create()
' Copy pages from first document
For i As Integer = 0 To doc1.Pages.Count - 1
mergedDoc.CopyPage(doc1, i)
Next
' Copy pages from second document
For i As Integer = 0 To doc2.Pages.Count - 1
mergedDoc.CopyPage(doc2, i)
Next
mergedDoc.Save("merged.pdf")
End Using
End Using
End Sub
End Class
Después (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var pdf1 = PdfDocument.FromFile("file1.pdf");
var pdf2 = PdfDocument.FromFile("file2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var pdf1 = PdfDocument.FromFile("file1.pdf");
var pdf2 = PdfDocument.FromFile("file2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim pdf1 = PdfDocument.FromFile("file1.pdf")
Dim pdf2 = PdfDocument.FromFile("file2.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
End Sub
End Class
La operación de fusión de MuPDFes especialmente prolija. Debe abrir ambos documentos fuente en bloques anidados using, crear un nuevo documento vacío con MuPDFDocument.Create(), iterar a través de cada página del primer documento llamando a CopyPage(), iterar a través de cada página del segundo documento llamando a CopyPage() y, finalmente, guardar. Son más de 20 líneas de código con anidamiento complejo.
El método estático PdfDocument.Merge() deIronPDFacepta múltiples documentos PDF y devuelve un único documento fusionado. La operación completa consta de 4 líneas de código legible. Para fusionar muchos documentos, puedes pasar una lista: PdfDocument.Merge(pdfList). Consulte la documentación sobre fusión y división de PDF para obtener más opciones.
Notas de migración críticas
Quitar binarios nativos
MuPDF requiere bibliotecas nativas específicas de la plataforma. Tras migrar a IronPDF, elimine todos los binarios nativos de MuPDF:
# Delete native libraries
rm -f mupdf*.dll libmupdf*.so libmupdf*.dylib
# Remove runtime folders
rm -rf runtimes/*/native/
# Update Docker files to remove MuPDFinstallation
# Delete native libraries
rm -f mupdf*.dll libmupdf*.so libmupdf*.dylib
# Remove runtime folders
rm -rf runtimes/*/native/
# Update Docker files to remove MuPDFinstallation
IronPDF es un código .NET totalmente gestionado, sin binarios nativos que gestionar entre plataformas.
Patrón Dispose simplificado
MuPDF requiere un contexto y una gestión de documentos explícitos:
// MuPDF: Nested using blocks required
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
{
// Work with document
}
// IronPDF: Simpler pattern
var pdf = PdfDocument.FromFile("input.pdf");
// Work with pdf
// MuPDF: Nested using blocks required
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
{
// Work with document
}
// IronPDF: Simpler pattern
var pdf = PdfDocument.FromFile("input.pdf");
// Work with pdf
Imports MuPDF
Using document As New MuPDFDocument("input.pdf")
' Work with document
End Using
Dim pdf = PdfDocument.FromFile("input.pdf")
' Work with pdf
Cambio de patrón de iteración de página
MuPDF utiliza iteración basada en índices con recuento explícito de páginas:
// MuPDF
for (int i = 0; i < document.Pages.Count; i++)
{
var pageText = document.Pages[i].GetText();
}
//IronPDF(foreach supported)
foreach (var page in pdf.Pages)
{
var pageText = page.Text;
}
// MuPDF
for (int i = 0; i < document.Pages.Count; i++)
{
var pageText = document.Pages[i].GetText();
}
//IronPDF(foreach supported)
foreach (var page in pdf.Pages)
{
var pageText = page.Text;
}
' MuPDF
For i As Integer = 0 To document.Pages.Count - 1
Dim pageText = document.Pages(i).GetText()
Next
' IronPDF (foreach supported)
For Each page In pdf.Pages
Dim pageText = page.Text
Next
Nuevas funciones disponibles
Tras migrar a IronPDF, obtendrá funciones que MuPDFno puede ofrecerle:
// Creación de PDFfrom HTML (not possible in MuPDF)
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello</h1>");
// Watermarks (not possible in MuPDF)
pdf.ApplyWatermark("<div style='color:red;opacity:0.3;'>DRAFT</div>");
// Password Protection (not possible in MuPDF)
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "user";
// Headers and Footers (not possible in MuPDF)
pdf.AddTextHeader("Document Title");
pdf.AddTextFooter("Page {page} of {total-pages}");
// Creación de PDFfrom HTML (not possible in MuPDF)
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello</h1>");
// Watermarks (not possible in MuPDF)
pdf.ApplyWatermark("<div style='color:red;opacity:0.3;'>DRAFT</div>");
// Password Protection (not possible in MuPDF)
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "user";
// Headers and Footers (not possible in MuPDF)
pdf.AddTextHeader("Document Title");
pdf.AddTextFooter("Page {page} of {total-pages}");
' Creación de PDFfrom HTML (not possible in MuPDF)
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello</h1>")
' Watermarks (not possible in MuPDF)
pdf.ApplyWatermark("<div style='color:red;opacity:0.3;'>DRAFT</div>")
' Password Protection (not possible in MuPDF)
pdf.SecuritySettings.OwnerPassword = "admin"
pdf.SecuritySettings.UserPassword = "user"
' Headers and Footers (not possible in MuPDF)
pdf.AddTextHeader("Document Title")
pdf.AddTextFooter("Page {page} of {total-pages}")
Solución de problemas
Edición 1: MuPDFDocument Not Found
Problema: la clase MuPDFDocument no existe en IronPDF.
Solución: Utilice PdfDocument.FromFile():
// MuPDF
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
// IronPDF
var pdf = PdfDocument.FromFile("input.pdf");
// MuPDF
using (MuPDFDocument document = new MuPDFDocument("input.pdf"))
// IronPDF
var pdf = PdfDocument.FromFile("input.pdf");
Imports MuPDF
Imports IronPDF
Using document As New MuPDFDocument("input.pdf")
End Using
Dim pdf = PdfDocument.FromFile("input.pdf")
Asunto 2: Páginas.no encontradas
Problema: el patrón document.Pages.Count no funciona.
Solución: Utilice pdf.PageCount:
// MuPDF
for (int i = 0; i < document.Pages.Count; i++)
// IronPDF
for (int i = 0; i < pdf.PageCount; i++)
// Or use: foreach (var page in pdf.Pages)
// MuPDF
for (int i = 0; i < document.Pages.Count; i++)
// IronPDF
for (int i = 0; i < pdf.PageCount; i++)
// Or use: foreach (var page in pdf.Pages)
' MuPDF
For i As Integer = 0 To document.Pages.Count - 1
' IronPDF
For i As Integer = 0 To pdf.PageCount - 1
' Or use: For Each page In pdf.Pages
Edición 3: GetText() no se encuentra
Problema: el método page.GetText() no existe.
Solución: utilice la propiedad page.Text o pdf.ExtractAllText():
// MuPDF
string pageText = document.Pages[i].GetText();
// IronPDF
string pageText = pdf.Pages[i].Text;
// Or for all text:
string allText = pdf.ExtractAllText();
// MuPDF
string pageText = document.Pages[i].GetText();
// IronPDF
string pageText = pdf.Pages[i].Text;
// Or for all text:
string allText = pdf.ExtractAllText();
' MuPDF
Dim pageText As String = document.Pages(i).GetText()
' IronPDF
Dim pageText As String = pdf.Pages(i).Text
' Or for all text:
Dim allText As String = pdf.ExtractAllText()
Edición 4: Página de copia no encontrada
Problema: Patrón de copia de página manual para fusionar.
Solución: utilice PdfDocument.Merge() estático:
// MuPDF
mergedDoc.CopyPage(doc1, i);
// IronPDF
var merged = PdfDocument.Merge(pdf1, pdf2);
// MuPDF
mergedDoc.CopyPage(doc1, i);
// IronPDF
var merged = PdfDocument.Merge(pdf1, pdf2);
' MuPDF
mergedDoc.CopyPage(doc1, i)
' IronPDF
Dim merged = PdfDocument.Merge(pdf1, pdf2)
Lista de comprobación de la migración
Pre-Migración
- Inventario de todos los usos de MuPDFen el código base
- Documentar todas las operaciones de renderizado (DPI, factores de escala)
- Identificar cualquier necesidad de creación de PDF (actualmente utilizando herramientas externas)
- Enumerar los requisitos de extracción de texto
- Revisar los scripts de implementación para el manejo binario nativo
- Obtener la clave de licencia de IronPDF
Cambios en el paquete
- Eliminar el paquete
MuPDF.NET - Eliminar el paquete
MuPDFCore - Eliminar el paquete
MuPDFCore.MuPDFWrapper - Instalar
IronPdfel paquete NuGet :dotnet add package IronPdf - Actualizar las importaciones de espacios de nombres
Cambios de código
- Agregar configuración de clave de licencia al inicio
- Reemplace
MuPDFDocumentconPdfDocument.FromFile() - Reemplace
document.Pages.Countconpdf.PageCount - Reemplace
page.GetText()conpage.Textopdf.ExtractAllText() - Reemplazar los bucles manuales
CopyPageconPdfDocument.Merge() - Eliminar bloques
usinganidados para la gestión del contexto - Agregue código de creación de PDF si es necesario (HTML a PDF)
Posmigración
- Eliminar los binarios nativos de MuPDFdel proyecto
- Actualizar los archivos Docker para eliminar la instalación de MuPDF
- Eliminar carpetas de tiempo de ejecución específicas de la plataforma
- Ejecutar pruebas de regresión comparando la salida renderizada
- Prueba en todas las plataformas de destino (Windows, Linux, macOS)
- Considere agregar nuevas capacidades (marcas de agua, seguridad, encabezados/pies de página)

