Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.0.6-beta01</Version>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '17.0'">
<Version>9.0.6-beta02</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(VisualStudioVersion)' == '18.0'">
<Version>10.0.0-rc.2.1.2</Version>
</PropertyGroup>

<PropertyGroup>
<PackageTags>Bootstrap Blazor WebAssembly wasm UI Components Pdf</PackageTags>
<Description>Bootstrap UI components extensions of Html2Pdf use PuppeteerSharp lib</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="9.11.5-beta07" />
<ItemGroup Condition="'$(VisualStudioVersion)' == '17.0'">
<PackageReference Include="BootstrapBlazor" Version="9.11.5-beta11" />
<PackageReference Include="PuppeteerSharp" Version="20.2.4" />
</ItemGroup>

<ItemGroup Condition="'$(VisualStudioVersion)' == '18.0'">
<PackageReference Include="BootstrapBlazor" Version="10.0.0-rc.2.1.10" />
<PackageReference Include="PuppeteerSharp" Version="20.2.4" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,75 @@ private static PuppeteerSharp.PdfOptions GetOptions(PdfOptions? options)
{
return options == null ? new PuppeteerSharp.PdfOptions() : new PuppeteerSharp.PdfOptions
{
Landscape = options.Landscape
Landscape = options.Landscape,
PrintBackground = options.PrintBackground,
Format = GetFormat(options.Format),
MarginOptions = GetMarginOptions(options.MarginOptions),
DisplayHeaderFooter = options.DisplayHeaderFooter,
Scale = options.Scale
};
}

private static PuppeteerSharp.Media.MarginOptions? GetMarginOptions(MarginOptions options) => new PuppeteerSharp.Media.MarginOptions
{
Top = options.Top,
Bottom = options.Bottom,
Left = options.Left,
Right = options.Right
};
Comment on lines +109 to +115
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The method does not handle null input. If options.MarginOptions is null when called from GetOptions (line 103), this will throw a NullReferenceException when accessing options.Top, options.Bottom, etc. Consider adding a null check or making the parameter nullable and returning null if the input is null.

Suggested change
private static PuppeteerSharp.Media.MarginOptions? GetMarginOptions(MarginOptions options) => new PuppeteerSharp.Media.MarginOptions
{
Top = options.Top,
Bottom = options.Bottom,
Left = options.Left,
Right = options.Right
};
private static PuppeteerSharp.Media.MarginOptions? GetMarginOptions(MarginOptions? options)
{
if (options == null) return null;
return new PuppeteerSharp.Media.MarginOptions
{
Top = options.Top,
Bottom = options.Bottom,
Left = options.Left,
Right = options.Right
};
}

Copilot uses AI. Check for mistakes.

private static PuppeteerSharp.Media.PaperFormat GetFormat(PaperFormat format)
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 replacing the long if/else chain in GetFormat with a switch-expression or static lookup for improved clarity and maintainability.

Consider using a switch-expression (or a static lookup) to collapse the long if/else chain:

private static PuppeteerSharp.Media.PaperFormat GetFormat(PaperFormat format)
    => format switch
    {
        PaperFormat.A0     => PuppeteerSharp.Media.PaperFormat.A0,
        PaperFormat.A1     => PuppeteerSharp.Media.PaperFormat.A1,
        PaperFormat.A2     => PuppeteerSharp.Media.PaperFormat.A2,
        PaperFormat.A3     => PuppeteerSharp.Media.PaperFormat.A3,
        PaperFormat.A4     => PuppeteerSharp.Media.PaperFormat.A4,
        PaperFormat.A5     => PuppeteerSharp.Media.PaperFormat.A5,
        PaperFormat.A6     => PuppeteerSharp.Media.PaperFormat.A6,
        PaperFormat.Letter => PuppeteerSharp.Media.PaperFormat.Letter,
        PaperFormat.Legal  => PuppeteerSharp.Media.PaperFormat.Legal,
        PaperFormat.Tabloid=> PuppeteerSharp.Media.PaperFormat.Tabloid,
        PaperFormat.Ledger => PuppeteerSharp.Media.PaperFormat.Ledger,
        _                  => new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height)
    };

Or prebuild a readonly dictionary:

private static readonly IReadOnlyDictionary<PaperFormat, PuppeteerSharp.Media.PaperFormat>
    _formatMap = new Dictionary<PaperFormat, PuppeteerSharp.Media.PaperFormat>
{
    [PaperFormat.A0]     = PuppeteerSharp.Media.PaperFormat.A0,
    [PaperFormat.A1]     = PuppeteerSharp.Media.PaperFormat.A1,
    // ...
};

private static PuppeteerSharp.Media.PaperFormat GetFormat(PaperFormat format)
    => _formatMap.TryGetValue(format, out var pf)
       ? pf
       : new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height);

Either approach keeps the same behavior but is far more concise and easier to maintain.

{
if (format == PaperFormat.A0)
{
return PuppeteerSharp.Media.PaperFormat.A0;
}
else if (format == PaperFormat.A1)
{
return PuppeteerSharp.Media.PaperFormat.A1;
}
else if (format == PaperFormat.A2)
{
return PuppeteerSharp.Media.PaperFormat.A2;
}
else if (format == PaperFormat.A3)
{
return PuppeteerSharp.Media.PaperFormat.A3;
}
else if (format == PaperFormat.A4)
{
return PuppeteerSharp.Media.PaperFormat.A4;
}
else if (format == PaperFormat.A5)
{
return PuppeteerSharp.Media.PaperFormat.A5;
}
else if (format == PaperFormat.A6)
{
return PuppeteerSharp.Media.PaperFormat.A6;
}
else if (format == PaperFormat.Letter)
{
return PuppeteerSharp.Media.PaperFormat.Letter;
}
else if (format == PaperFormat.Legal)
{
return PuppeteerSharp.Media.PaperFormat.Legal;
}
else if (format == PaperFormat.Tabloid)
{
return PuppeteerSharp.Media.PaperFormat.Tabloid;
}
else if (format == PaperFormat.Ledger)
{
return PuppeteerSharp.Media.PaperFormat.Ledger;
}
else
{
return new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height);
}
Comment on lines +163 to +166
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Validate custom PaperFormat dimensions to prevent invalid PDF output.

Ensure Width and Height are positive and within acceptable limits to prevent runtime errors or malformed PDFs.

Suggested change
else
{
return new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height);
}
else
{
// Validate custom PaperFormat dimensions
const double MinDimension = 1.0; // Minimum allowed dimension in inches
const double MaxDimension = 100.0; // Maximum allowed dimension in inches
if (format.Width < MinDimension || format.Height < MinDimension ||
format.Width > MaxDimension || format.Height > MaxDimension)
{
throw new ArgumentOutOfRangeException(
$"Custom PaperFormat dimensions are invalid. Width and Height must be between {MinDimension} and {MaxDimension} inches. " +
$"Received Width: {format.Width}, Height: {format.Height}");
}
return new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height);
}

Comment on lines +119 to +166
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The long if-else chain can be refactored using a switch expression for better readability and maintainability. This would make the code more concise and easier to extend in the future.

Suggested change
if (format == PaperFormat.A0)
{
return PuppeteerSharp.Media.PaperFormat.A0;
}
else if (format == PaperFormat.A1)
{
return PuppeteerSharp.Media.PaperFormat.A1;
}
else if (format == PaperFormat.A2)
{
return PuppeteerSharp.Media.PaperFormat.A2;
}
else if (format == PaperFormat.A3)
{
return PuppeteerSharp.Media.PaperFormat.A3;
}
else if (format == PaperFormat.A4)
{
return PuppeteerSharp.Media.PaperFormat.A4;
}
else if (format == PaperFormat.A5)
{
return PuppeteerSharp.Media.PaperFormat.A5;
}
else if (format == PaperFormat.A6)
{
return PuppeteerSharp.Media.PaperFormat.A6;
}
else if (format == PaperFormat.Letter)
{
return PuppeteerSharp.Media.PaperFormat.Letter;
}
else if (format == PaperFormat.Legal)
{
return PuppeteerSharp.Media.PaperFormat.Legal;
}
else if (format == PaperFormat.Tabloid)
{
return PuppeteerSharp.Media.PaperFormat.Tabloid;
}
else if (format == PaperFormat.Ledger)
{
return PuppeteerSharp.Media.PaperFormat.Ledger;
}
else
{
return new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height);
}
return format switch
{
PaperFormat.A0 => PuppeteerSharp.Media.PaperFormat.A0,
PaperFormat.A1 => PuppeteerSharp.Media.PaperFormat.A1,
PaperFormat.A2 => PuppeteerSharp.Media.PaperFormat.A2,
PaperFormat.A3 => PuppeteerSharp.Media.PaperFormat.A3,
PaperFormat.A4 => PuppeteerSharp.Media.PaperFormat.A4,
PaperFormat.A5 => PuppeteerSharp.Media.PaperFormat.A5,
PaperFormat.A6 => PuppeteerSharp.Media.PaperFormat.A6,
PaperFormat.Letter => PuppeteerSharp.Media.PaperFormat.Letter,
PaperFormat.Legal => PuppeteerSharp.Media.PaperFormat.Legal,
PaperFormat.Tabloid => PuppeteerSharp.Media.PaperFormat.Tabloid,
PaperFormat.Ledger => PuppeteerSharp.Media.PaperFormat.Ledger,
_ => new PuppeteerSharp.Media.PaperFormat(format.Width, format.Height)
};

Copilot uses AI. Check for mistakes.
}

private static async Task AddStyleTagAsync(IPage page, IEnumerable<string>? links = null)
{
var styles = new List<string>();
Expand Down
Loading