Skip to content

feat(Html2Pdf): add PdfOptions parameter#632

Merged
ArgoZhang merged 3 commits intomasterfrom
feat-html2pdf
Oct 27, 2025
Merged

feat(Html2Pdf): add PdfOptions parameter#632
ArgoZhang merged 3 commits intomasterfrom
feat-html2pdf

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Oct 27, 2025

Link issues

fixes #631

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Enable PDF customization by accepting a PdfOptions parameter in Html2Pdf service methods, add a helper to map options for PuppeteerSharp, refine logging checks, and update license headers.

New Features:

  • Add optional PdfOptions parameter to HTML-to-PDF service methods

Enhancements:

  • Introduce GetOptions helper to convert PdfOptions to PuppeteerSharp.PdfOptions
  • Refactor logging to respect Information log level before logging

Chores:

  • Update license headers to include BootstrapBlazor attribution

Copilot AI review requested due to automatic review settings October 27, 2025 04:55
@bb-auto bb-auto Bot added the enhancement New feature or request label Oct 27, 2025
@bb-auto bb-auto Bot added this to the v9.2.0 milestone Oct 27, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Oct 27, 2025

Reviewer's Guide

The PR enhances HTML-to-PDF generation by adding an optional PdfOptions parameter to all relevant methods, implementing a helper to translate these options into PuppeteerSharp.PdfOptions, and refining logging and header comments.

Sequence diagram for PDF generation with PdfOptions

sequenceDiagram
    participant Client
    participant DefaultPdfService
    participant PuppeteerSharp
    Client->>DefaultPdfService: PdfDataAsync(url, options)
    DefaultPdfService->>PuppeteerSharp: NewPageAsync()
    DefaultPdfService->>PuppeteerSharp: GoToAsync(url)
    DefaultPdfService->>DefaultPdfService: GetOptions(options)
    DefaultPdfService->>PuppeteerSharp: PdfDataAsync(PuppeteerSharp.PdfOptions)
    DefaultPdfService-->>Client: PDF byte[]
Loading

Sequence diagram for PDF generation from HTML with PdfOptions

sequenceDiagram
    participant Client
    participant DefaultPdfService
    participant PuppeteerSharp
    Client->>DefaultPdfService: PdfDataFromHtmlAsync(html, links, scripts, options)
    DefaultPdfService->>PuppeteerSharp: NewPageAsync()
    DefaultPdfService->>DefaultPdfService: AddStyleTagAsync(page, links)
    DefaultPdfService->>DefaultPdfService: AddScriptTagAsync(page, scripts)
    DefaultPdfService->>DefaultPdfService: GetOptions(options)
    DefaultPdfService->>PuppeteerSharp: PdfDataAsync(PuppeteerSharp.PdfOptions)
    DefaultPdfService-->>Client: PDF byte[]
Loading

Class diagram for updated DefaultPdfService with PdfOptions support

classDiagram
    class DefaultPdfService {
        IWebProxy? WebProxy
        +Task<byte[]> PdfDataAsync(string url, PdfOptions? options = null)
        +Task<Stream> PdfStreamAsync(string url, PdfOptions? options = null)
        +Task<byte[]> PdfDataFromHtmlAsync(string html, IEnumerable<string>? links = null, IEnumerable<string>? scripts = null, PdfOptions? options = null)
        +Task<Stream> PdfStreamFromHtmlAsync(string html, IEnumerable<string>? links = null, IEnumerable<string>? scripts = null, PdfOptions? options = null)
        -static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
        -static Task AddStyleTagAsync(IPage page, IEnumerable<string>? links = null)
        -static Task AddScriptTagAsync(IPage page, IEnumerable<string>? scripts = null)
        -Task<IBrowser> LaunchBrowserAsync()
        -void Log(Exception? exception, string? message, params object?[] args)
    }
    class PdfOptions {
        +bool Landscape
    }
    DefaultPdfService --> PdfOptions : uses
    DefaultPdfService --> PuppeteerSharp.PdfOptions : converts
    PdfOptions --|> PuppeteerSharp.PdfOptions : mapped by GetOptions
Loading

File-Level Changes

Change Details Files
Introduce PdfOptions parameter to PDF generation methods
  • Extended PdfDataAsync, PdfStreamAsync, PdfDataFromHtmlAsync, and PdfStreamFromHtmlAsync signatures to accept an optional PdfOptions argument
  • Updated calls to page.PdfDataAsync and page.PdfStreamAsync to pass through the new options via GetOptions
src/components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs
Add helper to map custom options to PuppeteerSharp
  • Implemented a private static GetOptions method that converts PdfOptions to PuppeteerSharp.PdfOptions, defaulting when null
src/components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs
Refactor logging guard and formatting
  • Wrapped Log method calls in logger.IsEnabled(LogLevel.Information) check
  • Reorganized conditional logic to handle argument arrays before logging
src/components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs
Update copyright headers
  • Revised file header comments to credit BootstrapBlazor & Argo Zhang and updated contact email
src/components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs
src/components/BootstrapBlazor.Html2Pdf/Extensions/ServiceCollectionExtensions.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#631 Add a PdfOptions parameter to relevant Html2Pdf service methods to allow customization of PDF generation.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ArgoZhang ArgoZhang merged commit af1fb78 into master Oct 27, 2025
1 of 2 checks passed
@ArgoZhang ArgoZhang deleted the feat-html2pdf branch October 27, 2025 04:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for customizable PDF generation options by introducing a PdfOptions parameter to the HTML-to-PDF conversion methods in the Html2Pdf component. This enhancement allows consumers to specify PDF generation settings like landscape orientation.

  • Adds optional PdfOptions parameter to all PDF generation methods
  • Implements GetOptions helper method to convert custom PdfOptions to PuppeteerSharp.PdfOptions
  • Updates copyright headers and package version

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
DefaultPdfService.cs Added PdfOptions parameter to all PDF generation methods and implemented conversion logic to PuppeteerSharp.PdfOptions
ServiceCollectionExtensions.cs Updated copyright header
BootstrapBlazor.Html2Pdf.csproj Updated version to 9.0.6-beta01 and BootstrapBlazor dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 95 to +100

private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
{
return options == null ? new PuppeteerSharp.PdfOptions() : new PuppeteerSharp.PdfOptions
{
Landscape = options.Landscape
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The GetOptions method only maps the Landscape property from PdfOptions to PuppeteerSharp.PdfOptions. If PdfOptions is intended to support additional properties in the future, this implementation will require updates. Consider documenting this mapping or using a more extensible pattern if additional options are planned.

Suggested change
private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
{
return options == null ? new PuppeteerSharp.PdfOptions() : new PuppeteerSharp.PdfOptions
{
Landscape = options.Landscape
/// <summary>
/// Maps <see cref="PdfOptions"/> to <see cref="PuppeteerSharp.PdfOptions"/>.
///
/// NOTE: If new properties are added to <see cref="PdfOptions"/>, they must be mapped here as well.
/// </summary>
private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
{
return options == null ? new PuppeteerSharp.PdfOptions() : new PuppeteerSharp.PdfOptions
{
Landscape = options.Landscape
// TODO: Map additional properties from PdfOptions here as needed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • GetOptions currently only maps the Landscape flag; please extend it to include all PdfOptions properties (e.g. margins, format, printBackground) to fully support customization.
  • Refactor the Log method to early-return when LogLevel.Information is disabled, which will flatten the nested ifs and improve readability.
  • Consider renaming GetOptions to something like ToPuppeteerPdfOptions or ConvertToPuppeteerSharpOptions for clearer intent of the helper method.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- GetOptions currently only maps the Landscape flag; please extend it to include all PdfOptions properties (e.g. margins, format, printBackground) to fully support customization.
- Refactor the Log method to early-return when LogLevel.Information is disabled, which will flatten the nested ifs and improve readability.
- Consider renaming GetOptions to something like ToPuppeteerPdfOptions or ConvertToPuppeteerSharpOptions for clearer intent of the helper method.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs:152` </location>
<code_context>

     private void Log(Exception? exception, string? message, params object?[] args)
     {
-        if (args.Length != 0)
</code_context>

<issue_to_address>
**issue (complexity):** Consider removing the redundant log level check and simplifying the GetOptions method to reduce code nesting and verbosity.

```csharp
// ↓ Replace the verbose Log method...
private void Log(Exception? exception, string? message, params object?[] args)
{
-    if (logger.IsEnabled(LogLevel.Information))
-    {
-        if (args.Length != 0)
-        {
-            logger.LogInformation(exception, "{Message} | Args: {Args}", message, args);
-        }
-        else
-        {
-            logger.LogInformation(exception, "{Message}", message);
-        }
-    }
+    // no need for IsEnabled guard – LogInformation already checks the level
+    if (args.Length > 0)
+    {
+        logger.LogInformation(exception, "{Message} | Args: {Args}", message, args);
+    }
+    else
+    {
+        logger.LogInformation(exception, "{Message}", message);
+    }
}

// …and make GetOptions an expression‐bodied helper
private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
    => new()
    {
        Landscape = options?.Landscape ?? default
    };
```

These changes
- remove the redundant `IsEnabled` check and flatten the nesting,
- shorten `GetOptions` to a single expression while preserving the mapping.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -161,13 +151,16 @@ private async Task<IBrowser> LaunchBrowserAsync()

private void Log(Exception? exception, string? message, params object?[] args)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider removing the redundant log level check and simplifying the GetOptions method to reduce code nesting and verbosity.

// ↓ Replace the verbose Log method...
private void Log(Exception? exception, string? message, params object?[] args)
{
-    if (logger.IsEnabled(LogLevel.Information))
-    {
-        if (args.Length != 0)
-        {
-            logger.LogInformation(exception, "{Message} | Args: {Args}", message, args);
-        }
-        else
-        {
-            logger.LogInformation(exception, "{Message}", message);
-        }
-    }
+    // no need for IsEnabled guard – LogInformation already checks the level
+    if (args.Length > 0)
+    {
+        logger.LogInformation(exception, "{Message} | Args: {Args}", message, args);
+    }
+    else
+    {
+        logger.LogInformation(exception, "{Message}", message);
+    }
}

// …and make GetOptions an expression‐bodied helper
private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
    => new()
    {
        Landscape = options?.Landscape ?? default
    };

These changes

  • remove the redundant IsEnabled check and flatten the nesting,
  • shorten GetOptions to a single expression while preserving the mapping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(Html2Pdf): add PdfOptions parameter

2 participants